alchemylab 1.0.6 → 1.0.8
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/939.js +3 -3
- package/dist/cli.js +137 -110
- package/dist/http-server.js +680 -717
- package/dist/index.js +582 -619
- package/dist/mcp-direct.js +813 -850
- package/package.json +3 -2
package/dist/index.js
CHANGED
|
@@ -20,13 +20,13 @@ const f={requestId:a.requestId,projectId:l,title:a.title,description:a.descripti
|
|
|
20
20
|
u.info("Task input prepared",{taskInput:JSON.stringify(f)}),u.info("Creating task via task client",{projectId:l,requestId:a.requestId,title:a.title})
|
|
21
21
|
const m=await p.createTask(f)
|
|
22
22
|
u.debug("Task creation response structure",{type:typeof m,isArray:Array.isArray(m),hasData:null!=m,properties:m?Object.keys(m):[],dataPreview:m?JSON.stringify(m).substring(0,200)+"...":"null"})
|
|
23
|
-
const y=(0,o.extractDataFromResponse)(m,{logger:u,operationName:"createTask",defaultValue:{id:"tas"+Date.now().toString().substring(5,11),title:f.title,description:f.description,status:"pending",requestId:f.requestId,projectId:l,createdAt:(new Date).toISOString(),updatedAt:(new Date).toISOString()}}),w="data"in y?y.data:y,b=w.localId||w.id||"tas"+Date.now().toString().substring(5,11),
|
|
23
|
+
const y=(0,o.extractDataFromResponse)(m,{logger:u,operationName:"createTask",defaultValue:{id:"tas"+Date.now().toString().substring(5,11),title:f.title,description:f.description,status:"pending",requestId:f.requestId,projectId:l,createdAt:(new Date).toISOString(),updatedAt:(new Date).toISOString()}}),w="data"in y?y.data:y,b=w.localId||w.id||"tas"+Date.now().toString().substring(5,11),k=w.title||f.title,I=w.description||f.description,v=w.status||"pending",C=w.requestId||f.requestId
|
|
24
24
|
let _,E="unknown"
|
|
25
|
-
w&&"object"==typeof w&&"_workingEndpoint"in w&&(E=w._workingEndpoint),u.info("Successfully extracted task data from response",{taskId:b,requestId:C,title:
|
|
25
|
+
w&&"object"==typeof w&&"_workingEndpoint"in w&&(E=w._workingEndpoint),u.info("Successfully extracted task data from response",{taskId:b,requestId:C,title:k})
|
|
26
26
|
try{const e=i.getToolRecordClient()
|
|
27
|
-
if(e){const t=await e.createToolRecord({taskId:b,requestId:C,projectId:l,type:"create-task",metadata:{status:"completed",timestamp:(new Date).toISOString(),taskTitle:
|
|
28
|
-
_=t?.id}}catch(e){u.error("Failed to create tool record for task creation, but continuing",{error:e instanceof Error?e.stack:e+"",taskId:b,requestId:C})}h({success:!0,requestId:a.requestId,projectId:l}),u.info("Task created successfully",{taskId:b,requestId:C,title:
|
|
29
|
-
let q=`Created Task ${b}: ${
|
|
27
|
+
if(e){const t=await e.createToolRecord({taskId:b,requestId:C,projectId:l,type:"create-task",metadata:{status:"completed",timestamp:(new Date).toISOString(),taskTitle:k,taskDescription:I,taskStatus:v},note:"Created task "+k})
|
|
28
|
+
_=t?.id}}catch(e){u.error("Failed to create tool record for task creation, but continuing",{error:e instanceof Error?e.stack:e+"",taskId:b,requestId:C})}h({success:!0,requestId:a.requestId,projectId:l}),u.info("Task created successfully",{taskId:b,requestId:C,title:k,projectId:l})
|
|
29
|
+
let q=`Created Task ${b}: ${k}`
|
|
30
30
|
return _&&(q+=`\n[RECORD:${_}]`),{content:[{type:"text",text:q}]}}catch(r){if(u.error("Failed to create task",{error:r instanceof Error?r.stack:r+"",args:e}),t.projectId)try{if(r instanceof Error&&(r.message.includes("Project is disabled")||r.message.includes("Project cannot accept new tasks")||r.message.includes("disabled due to tier limits")||r.message.includes("Project is inactive due to tier limits")))u.info("Skipping tool record creation for disabled project error",{projectId:t.projectId,error:r.message})
|
|
31
31
|
else{const n=i.getToolRecordClient()
|
|
32
32
|
n&&await n.createToolRecord({requestId:e.requestId,projectId:t.projectId,type:"create-task",metadata:{status:"failed",timestamp:(new Date).toISOString(),taskTitle:e.title,taskDescription:e.description?.substring(0,100)+(e.description?.length>100?"...":""),error:(0,s.getErrorMessage)(r),errorDetails:r instanceof Error?r.stack:r+""},note:"Failed to create task: "+e.title})}}catch(e){u.error("Failed to create failure record for task creation",{error:e instanceof Error?e.message:e+""})}h({success:!1,error:r instanceof Error?r.name:"unknown"})
|
|
@@ -44,9 +44,9 @@ var t={}
|
|
|
44
44
|
if(null!=e)for(var r=n(e),i=0;i<r.length;i++)"default"!==r[i]&&o(t,e,r[i])
|
|
45
45
|
return s(t,e),t}),a=this&&this.__importDefault||function(e){return e&&e.__esModule?e:{default:e}}
|
|
46
46
|
Object.defineProperty(exports,"__esModule",{value:!0}),exports.McpServer=void 0,exports.resetStdoutWrite=function(){process.stdout.write=x},exports.getMcpServer=r,exports.createServer=function(e,t,n,o,s={}){return r(e,t,n,o,s)}
|
|
47
|
-
const c=t(3807),l=t(8909),d=a(t(6928)),u=a(t(9896)),h=a(t(1943)),g=t(9567),p=t(3444),f=t(7660),m=t(1253),y=t(5172),w=t(7976),b=i(t(7478)),
|
|
47
|
+
const c=t(3807),l=t(8909),d=a(t(6928)),u=a(t(9896)),h=a(t(1943)),g=t(9567),p=t(3444),f=t(7660),m=t(1253),y=t(5172),w=t(7976),b=i(t(7478)),k=t(4139),I=new Set,v=t(9860),C=t(1472),_=t(3328),E=t(8955),q=t(3217),S=t(8411),T=t(5278),P=t(446),R=t(9060),M=t(8824),j=(0,p.createLogger)({serviceName:"stdout-capture",console:!1,logToFile:!1}),x=process.stdout.write,O=process.argv.includes("--stdio")||"true"===process.env.MCP_DIRECT_MODE
|
|
48
48
|
!(0,p.isDebugToolsEnabled)()||O&&"true"!==process.env.DEBUG_STDOUT_CAPTURE||(process.stdout.write=function(e){try{return(0,p.isDebugToolsEnabled)()&&"true"===process.env.DEBUG_LOGGING?.toLowerCase()&&"string"==typeof e&&!e.trim().startsWith('{"jsonrpc":"2.0"')&&e.trim().length>0&&j.debug("Stdout output",{content:e.substring(0,100),length:e.length}),x.call(process.stdout,e)}catch(e){return j.error("Error in safeStdoutWrite",{error:e+""}),!0}})
|
|
49
|
-
class D{constructor(e,t,r,n,o={}){this.git=null,this.currentSSEConnection=null,this.stdioTransport=null,this.clientInfo=null,this.isInitializing=!1,this.isInitialized=!1,this.logger=t.child({component:"mcp-server"}),this.multiAgentMode=o.multiAgentMode||!1,this.logger.info("Creating McpServer instance",{basePath:e,remoteServerUrl:n,multiAgentMode:o.multiAgentMode||!1,hasExistingProjectId:!!o.existingProjectId}),this.basePath=e,this.alchemyPath=d.default.join(e,
|
|
49
|
+
class D{constructor(e,t,r,n,o={}){this.git=null,this.currentSSEConnection=null,this.stdioTransport=null,this.clientInfo=null,this.isInitializing=!1,this.isInitialized=!1,this.logger=t.child({component:"mcp-server"}),this.multiAgentMode=o.multiAgentMode||!1,this.logger.info("Creating McpServer instance",{basePath:e,remoteServerUrl:n,multiAgentMode:o.multiAgentMode||!1,hasExistingProjectId:!!o.existingProjectId}),this.basePath=e,this.alchemyPath=d.default.join(e,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 P.LockOverrideManager(t),this.configManager=new R.ConfigManager(t),this.logger.debug("Server paths initialized",{basePath:this.basePath,alchemyPath:this.alchemyPath}),this.server=new g.Server({name:"alchemy",version:"1.0.0"},{capabilities:{tools:{search:{},create_request:{},complete_task:{},get_task_information:{},complete_request:{},revert_request:{},get_request_information:{},list_tasks:{},list_requests:{},switch_to_branch:{},read_files:{},create_directory:{},move_files:{},write_file:{},replace_strings:{},insert_lines:{},replace_lines:{},delete_files:{},document_operations:{},file_history:{},task_file_history:{},request_file_history:{},quick_write:{},quick_replace:{},quick_manage:{}}}}),this.metrics.incrementCounter("mcp_server_init_started",1),this.interceptConnectMethod(),this.logger.info("Starting initialization for server instance"),this.initializationPromise=this.initialize()}get branchState(){if(!this.workspaceManager)return{currentBranch:null,activeRequestId:null,isOnMainBranch:!0}
|
|
50
50
|
const e=this.workspaceManager.getCurrentContext()
|
|
51
51
|
return{currentBranch:e.branchName,activeRequestId:e.requestId,isOnMainBranch:e.isMainBranch}}async updateBranchState(e,t){this.logger.debug("updateBranchState called - managed by WorkspaceManager",{branch:e,requestId:t})}async getCurrentBranchContext(){if(!this.workspaceManager)return{branch:null,requestId:null,isMain:!0}
|
|
52
52
|
const e=this.workspaceManager.getCurrentContext()
|
|
@@ -56,7 +56,7 @@ const n=await r.getNextId(e)
|
|
|
56
56
|
return t({success:!0,type:e}),this.metrics.incrementCounter("remote_id_success",1,{type:e}),n}catch(t){throw this.metrics.incrementCounter("remote_id_failure",1,{type:e,error:t instanceof Error?t.name:"unknown"}),this.logger.warn("Failed to get ID from remote server, unable to perform operation",{type:e,error:(0,M.getErrorMessage)(t)}),Error("Failed to get ID from remote server.")}}async initialize(){const e=this.remoteServerUrl||"https://api.alchemylabcode.com"
|
|
57
57
|
this.logger.debug("Using remote server URL",{remoteServerUrl:e})
|
|
58
58
|
const t=d.default.resolve(this.basePath)
|
|
59
|
-
if(
|
|
59
|
+
if(I.has(t))return this.logger.info("Path already initialized in global registry, skipping initialization",{path:t}),void(this.isInitialized=!0)
|
|
60
60
|
if(this.isInitialized)this.logger.info("Server already initialized, skipping initialization")
|
|
61
61
|
else{if(this.isInitializing)return this.logger.info("Initialization already in progress, waiting..."),void await this.initializationPromise
|
|
62
62
|
this.isInitializing=!0,this.logger.info("SERVER INITIALIZATION STARTING",{path:t,pid:process.pid,time:(new Date).toISOString()}),this.metrics.setGauge("mcp_initialization",0,{status:"starting"})
|
|
@@ -67,12 +67,12 @@ try{this.logger.info("Validating git repository for branch management...")
|
|
|
67
67
|
const e=await b.validateGitRepository(this.git,this.logger,this.metrics)
|
|
68
68
|
if(e.isGitRepository){this.logger.info("Git repository validation completed",{currentBranch:e.currentBranch,isClean:e.isClean,defaultBranch:e.defaultBranch,branchCount:e.branches.length,hasMainBranch:e.hasMainBranch,hasMasterBranch:e.hasMasterBranch})
|
|
69
69
|
const t=[],r=[]
|
|
70
|
-
e.currentBranch||(t.push("Repository is in detached HEAD state"),r.push("Switch to a proper branch: git checkout main")),e.isClean||(t.push(`Repository has ${e.uncommittedChanges.length} uncommitted changes`),r.push("Commit or stash changes before creating requests")),e.defaultBranch||(t.push("No default branch (main/master) found"),r.push("Create a default branch: git checkout -b main")),t.length>0?this.logger.warn("Git repository has potential issues for branch management",{issues:t,recommendations:r}):this.logger.info("Git repository is ready for automatic branch management"),this.metrics.setGauge("git_repository_ready",0===t.length?1:0),this.metrics.setGauge("git_repository_branch_count",e.branches.length),this.metrics.incrementCounter("git_repository_validation_success",1)}else this.logger.error("Git repository validation failed - not a valid git repository"),this.metrics.incrementCounter("git_repository_validation_failed",1)}catch(e){this.logger.warn("Git repository validation encountered an error",{error:e instanceof Error?e.message:e+""}),this.metrics.incrementCounter("git_repository_validation_error",1)}}async ensureGitignoreWithAlchemyLab(){const e=d.default.join(this.basePath,".gitignore"),t=
|
|
70
|
+
e.currentBranch||(t.push("Repository is in detached HEAD state"),r.push("Switch to a proper branch: git checkout main")),e.isClean||(t.push(`Repository has ${e.uncommittedChanges.length} uncommitted changes`),r.push("Commit or stash changes before creating requests")),e.defaultBranch||(t.push("No default branch (main/master) found"),r.push("Create a default branch: git checkout -b main")),t.length>0?this.logger.warn("Git repository has potential issues for branch management",{issues:t,recommendations:r}):this.logger.info("Git repository is ready for automatic branch management"),this.metrics.setGauge("git_repository_ready",0===t.length?1:0),this.metrics.setGauge("git_repository_branch_count",e.branches.length),this.metrics.incrementCounter("git_repository_validation_success",1)}else this.logger.error("Git repository validation failed - not a valid git repository"),this.metrics.incrementCounter("git_repository_validation_failed",1)}catch(e){this.logger.warn("Git repository validation encountered an error",{error:e instanceof Error?e.message:e+""}),this.metrics.incrementCounter("git_repository_validation_error",1)}}async ensureGitignoreWithAlchemyLab(){const e=d.default.join(this.basePath,".gitignore"),t=k.ALCHEMY_DIR_NAME+"/"
|
|
71
71
|
try{if(u.default.existsSync(e)){const r=await h.default.readFile(e,"utf8")
|
|
72
|
-
if(r.split("\n").some((e=>e.trim()===t||e.trim()===t.slice(0,-1))))this.logger.info(
|
|
72
|
+
if(r.split("\n").some((e=>e.trim()===t||e.trim()===t.slice(0,-1))))this.logger.info(k.ALCHEMY_DIR_NAME+"/ already present in .gitignore")
|
|
73
73
|
else{const n=r.trimEnd()+"\n\n# AlchemyMCP working directory\n"+t+"\n"
|
|
74
|
-
await h.default.writeFile(e,n),this.logger.info(`Added ${
|
|
75
|
-
await h.default.writeFile(e,r),this.logger.info(`Created new .gitignore with ${
|
|
74
|
+
await h.default.writeFile(e,n),this.logger.info(`Added ${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")
|
|
75
|
+
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,M.getErrorMessage)(e)})}}async initializeGitRepo(){try{this.logger.info("Initializing git repository"),await this.git.init(),await this.ensureGitignoreWithAlchemyLab()
|
|
76
76
|
const e=d.default.join(this.basePath,"README.md")
|
|
77
77
|
if(!u.default.existsSync(e)){const t=`# Project at ${this.basePath}\n\nCreated with AlchemyMCP Server.\n`
|
|
78
78
|
await h.default.writeFile(e,t)}this.logger.info("Git repository initialized successfully"),await this.git.add(".")
|
|
@@ -195,13 +195,13 @@ const w=[],b=a.toLowerCase()
|
|
|
195
195
|
for(const e of y){const t=[]
|
|
196
196
|
if("all"!==l&&"title"!==l||!e.title||e.title.toLowerCase().includes(b)&&t.push({request:e,matchType:"title",matchSnippet:r(e.title,a)}),"all"!==l&&"description"!==l||!e.description||e.description.toLowerCase().includes(b)&&t.push({request:e,matchType:"description",matchSnippet:n(e.description,b,150)}),("all"===l||"criteria"===l)&&e.acceptanceCriteria)for(const r of e.acceptanceCriteria){const o="string"==typeof r?r:r.description
|
|
197
197
|
if(o&&o.toLowerCase().includes(b)){t.push({request:e,matchType:"criteria",matchSnippet:n(o,b,150)})
|
|
198
|
-
break}}t.length>0&&w.push(t[0])}const
|
|
199
|
-
if(0===
|
|
200
|
-
let v=`Found ${
|
|
201
|
-
for(const e of
|
|
198
|
+
break}}t.length>0&&w.push(t[0])}const k=g.limit||20,I=w.slice(0,k)
|
|
199
|
+
if(0===I.length)return h({success:!0,resultCount:0}),{content:[{type:"text",text:`No requests found matching "${a}".\n\nSearched in: ${l}\nTotal requests checked: ${y.length}`}]}
|
|
200
|
+
let v=`Found ${I.length} request${1===I.length?"":"s"} matching "${a}":\n\n`
|
|
201
|
+
for(const e of I){const t=e.request,r=o(t.status)
|
|
202
202
|
v+=`${s(t.type)} **${t.title}** (${t.id}) ${r}\n`,v+=" \u{1f4cd} Match in "+e.matchType,e.matchSnippet&&(v+=": "+e.matchSnippet),v+="\n\n"}v+=`---\nSearched ${y.length} requests (filtered by: `
|
|
203
203
|
const C=[]
|
|
204
|
-
return g.status&&C.push("status="+g.status),g.type&&C.push("type="+g.type),g.dateFrom&&C.push("from="+g.dateFrom),g.dateTo&&C.push("to="+g.dateTo),v+=C.length>0?C.join(", "):"none",v+=")",h({success:!0,resultCount:
|
|
204
|
+
return g.status&&C.push("status="+g.status),g.type&&C.push("type="+g.type),g.dateFrom&&C.push("from="+g.dateFrom),g.dateTo&&C.push("to="+g.dateTo),v+=C.length>0?C.join(", "):"none",v+=")",h({success:!0,resultCount:I.length}),d.incrementCounter("search_requests_success",1),{content:[{type:"text",text:v}]}}catch(e){return u.error("Search requests failed",{error:e instanceof Error?e.stack:e+""}),h({success:!1,error:(0,a.getErrorMessage)(e)}),d.incrementCounter("search_requests_errors",1),{content:[{type:"text",text:"\u274c **Search Failed:** "+(0,a.getErrorMessage)(e)}],isError:!0}}}
|
|
205
205
|
const i=t(9860),a=t(8824)},260(e,exports,t){Object.defineProperty(exports,"__esModule",{value:!0}),exports.def=void 0
|
|
206
206
|
const r=t(6183),n=t(4221)
|
|
207
207
|
exports.def={name:"view_asset",description:"View an image from the project's .alchemy_lab/assets/ folder. Returns the image so you can see it. Use this when you encounter asset:filename.png references in plans or documents and need to understand the image content.",schema:r.ViewAssetSchema,annotations:{title:"View Asset Image",readOnlyHint:!0},readOnly:!0,handler(e,t){return(0,n.handleViewAsset)(e,t.context,t.logger,t.metrics)}}},270(e,exports){Object.defineProperty(exports,"__esModule",{value:!0})},293(e,exports,t){function r(e){let t
|
|
@@ -258,14 +258,14 @@ throw p.error("Failed to check request lock status",{taskId:o,requestId:w.reques
|
|
|
258
258
|
let b=d.git
|
|
259
259
|
if(d.workspaceManager){const e=d.workspaceManager.getCurrentContext()
|
|
260
260
|
if("multi-agent"===e.mode&&e.requestId){const{simpleGit}=t(3807)
|
|
261
|
-
b=simpleGit({baseDir:e.basePath,binary:d.gitBinary}),p.debug("Using workspace-aware git instance for task completion",{taskId:o,mode:e.mode,requestId:e.requestId,basePath:e.basePath})}}let
|
|
262
|
-
if(b)try{(await b.status()).isClean()||(
|
|
261
|
+
b=simpleGit({baseDir:e.basePath,binary:d.gitBinary}),p.debug("Using workspace-aware git instance for task completion",{taskId:o,mode:e.mode,requestId:e.requestId,basePath:e.basePath})}}let k=null
|
|
262
|
+
if(b)try{(await b.status()).isClean()||(k=(await b.commit(`Complete task ${o}: ${h}`)).commit,p.info("Created commit for task completion",{taskId:o,commitId:k}))}catch(e){p.warn("Failed to commit changes",{error:(0,l.getErrorMessage)(e)})}let I=null
|
|
263
263
|
try{const e=u.getToolRecordClient()
|
|
264
|
-
e&&(
|
|
265
|
-
p.info("Raw task update response data",{responseData:JSON.stringify(n)}),p.debug("Task update response structure",{type:typeof n,isArray:Array.isArray(n),hasData:null!=n,properties:n?Object.keys(n):[],dataPreview:n?JSON.stringify(n).substring(0,200)+"...":"null"}),(0,s.extractDataFromResponse)(n,{logger:p,operationName:"updateTask",defaultValue:{id:o,status:"completed"}}),p.info("Successfully completed task",{taskId:o,recordId:
|
|
264
|
+
e&&(I={id:(await e.createToolRecord({taskId:o,requestId:w.requestId,projectId:m,type:"complete-task",metadata:{status:"completed",timestamp:(new Date).toISOString(),taskTitle:w.title,completionSummary:h,lastCommit:k,completedAt:(new Date).toISOString()},note:`Completed task: ${h.substring(0,100)}${h.length>100?"...":""}`})).id})}catch(e){p.error("Failed to create tool record for task completion, but continuing",{error:e instanceof Error?e.stack:e+"",taskId:o,requestId:w.requestId})}try{const e=w.metadata||{},t=(new Date).toISOString(),r={status:"completed",metadata:{...e,lastCommit:k,completionSummary:h,completionRecordId:I?.id,completedAt:t}},n=await y.updateTask(o,r)
|
|
265
|
+
p.info("Raw task update response data",{responseData:JSON.stringify(n)}),p.debug("Task update response structure",{type:typeof n,isArray:Array.isArray(n),hasData:null!=n,properties:n?Object.keys(n):[],dataPreview:n?JSON.stringify(n).substring(0,200)+"...":"null"}),(0,s.extractDataFromResponse)(n,{logger:p,operationName:"updateTask",defaultValue:{id:o,status:"completed"}}),p.info("Successfully completed task",{taskId:o,recordId:I?.id})
|
|
266
266
|
const i=w.requestId
|
|
267
267
|
let a=`Task ${o} (${w.title}) has been marked as completed.`
|
|
268
|
-
if(
|
|
268
|
+
if(I?.id&&(a+=`\n[RECORD:${I.id}]`),k&&(a+="\nCommit: "+k.substring(0,8)),i)try{const e=await y.listTasks({requestId:i})
|
|
269
269
|
p.info("Raw tasks list response data",{responseData:JSON.stringify(e)}),p.debug("Tasks list response structure",{type:typeof e,isArray:Array.isArray(e),hasData:null!=e,properties:e?Object.keys(e):[],dataPreview:e?JSON.stringify(e).substring(0,200)+"...":"null"})
|
|
270
270
|
const t=(0,s.extractArrayFromResponse)(e,{logger:p,operationName:"listTasksForProgress",defaultValue:[]}),r=t.length,n=t.filter((e=>"completed"===e.status)).length
|
|
271
271
|
p.info("Task progress check",{requestId:i,totalTasks:r,completedTasks:n}),a+=`\n\nTask Progress: ${n}/${r} tasks completed`,n===r&&(a+=`\n\nAll tasks for request ${i} are now completed! You may consider marking the request as completed using the complete-request tool.`)}catch(e){p.warn("Failed to check task progress",{error:(0,l.getErrorMessage)(e),requestId:i})}return f({success:!0}),{content:[{type:"text",text:a}]}}catch(e){throw p.error("Failed to complete task",{error:e instanceof Error?e.stack:e+"",taskId:o}),Error("Failed to complete task: "+(0,l.getErrorMessage)(e))}}catch(t){if(p.error("Failed to complete task",{error:t instanceof Error?t.stack:t+"",args:e}),d.projectId)try{const r=u.getToolRecordClient()
|
|
@@ -328,9 +328,8 @@ t>0&&this.logger.debug("Cleaned up expired passwords",{count:t})}getActivePasswo
|
|
|
328
328
|
const r=t(1569),n=t(5997),o=t(8349),s=t(9852),i=t(9422),a=r.z.object({}),c=r.z.object({requestId:r.z.string().optional().describe("Request ID to search for")})
|
|
329
329
|
exports.debugDefs=[{name:"debug_multi_agent_status",description:"Debug tool to check multi-agent mode status, worktree state, and configuration",schema:a,annotations:{title:"Debug Multi-Agent Status",readOnlyHint:!0},debugOnly:!0,readOnly:!0,async handler(e,t){return{content:[{type:"text",text:await(0,n.handleDebugMultiAgentStatus)(e,t.context,t.logger,t.metrics)}]}}},{name:"debug_git_log",description:"Debug tool to examine git log and search for merge commits",schema:a,annotations:{title:"Debug Git Log",readOnlyHint:!0},debugOnly:!0,readOnly:!0,handler(e,t){return(0,o.handleDebugGitLog)(e,t.context,t.logger,t.metrics)}},{name:"debug_git_log_request",description:"Debug tool to examine git log for a specific request",schema:c,annotations:{title:"Debug Git Log Request",readOnlyHint:!0},debugOnly:!0,readOnly:!0,handler(e,t){return(0,s.handleDebugGitLogRequest)(e,t.context,t.logger,t.metrics)}},{name:"debug_request_file_history",description:"Debug tool to test git merge commit search patterns for request file history",schema:c,annotations:{title:"Debug Request File History",readOnlyHint:!0},debugOnly:!0,readOnly:!0,handler(e,t){return(0,i.handleDebugRequestFileHistory)(e,t.context,t.apiClient,t.logger,t.metrics)}}]},700(e,exports,t){Object.defineProperty(exports,"__esModule",{value:!0}),exports.def=void 0
|
|
330
330
|
const r=t(6183),n=t(8037),o=t(5218)
|
|
331
|
-
exports.def={name:"list_requests",description:`List requests with filtering options (status, type, dates) and pagination. Shows detailed request information${(0,o.isMultiAgentModeEnabled)()?" including lock status to indicate which requests are currently in use by other agents":""}.`,schema:r.ListRequestsSchema,annotations:{title:"List Requests",readOnlyHint:!0},hidden:!0,readOnly:!0,handler(e,t){return(0,n.handleListRequests)(e,t.context,t.apiClient,t.logger,t.metrics)}}},
|
|
332
|
-
const r=t(
|
|
333
|
-
const r=t(7645),n=t(1038),o=t(2161),s=t(5172),i=t(715)
|
|
331
|
+
exports.def={name:"list_requests",description:`List requests with filtering options (status, type, dates) and pagination. Shows detailed request information${(0,o.isMultiAgentModeEnabled)()?" including lock status to indicate which requests are currently in use by other agents":""}.`,schema:r.ListRequestsSchema,annotations:{title:"List Requests",readOnlyHint:!0},hidden:!0,readOnly:!0,handler(e,t){return(0,n.handleListRequests)(e,t.context,t.apiClient,t.logger,t.metrics)}}},857(module){module.exports=require("os")},922(e,exports,t){Object.defineProperty(exports,"__esModule",{value:!0}),exports.ToolRecordClient=void 0
|
|
332
|
+
const r=t(7645),n=t(1038),o=t(2161),s=t(5172),i=t(6688)
|
|
334
333
|
class a extends r.ConnectionAwareClient{constructor(e,t,r,n,o,s,i){const a=t.child({component:"tool-record-client"}),c=s||{isInOfflineMode(){return!1},isOffline(){return!1},setOfflineMode(){},async checkConnectivity(){return!0},getHealthCheckStats(){return{isOffline:!1,consecutiveFailures:0,currentBackoffMs:0,lastCheckTime:0}},cleanup(){}}
|
|
335
334
|
super(e,a,r,o,i),this.setConnectionStatusManager(c),this.projectClient=n,this.logger.info("ToolRecordClient initialized",{baseUrl:e,hasAuthToken:!!o,options:JSON.stringify(i)})}async createToolRecord(e){if(this.logger.debug("Creating tool record",{record:e}),!e.projectId)throw this.logger.error("No project ID provided for creating tool record"),Error("Project ID is required for tool record creation")
|
|
336
335
|
if(!e.type)throw this.logger.error("No record type provided for creating tool record"),Error("Record type is required for tool record creation")
|
|
@@ -339,7 +338,7 @@ try{const r=e.projectId||this.projectClient.getProjectId()
|
|
|
339
338
|
if(!r)throw this.logger.error("No project ID available for creating tool record"),Error("Project ID is required for tool record operations")
|
|
340
339
|
try{const a=`/api/projects/${r}/tool-records`
|
|
341
340
|
this.logger.debug("Using tool record endpoint",{endpoint:a,projectId:r}),this.getAuthToken(),this.logger.info("Sending tool record to server",{endpoint:a,recordType:e.type,taskId:e.taskId,requestId:e.requestId})
|
|
342
|
-
const c=(0,s.getGlobalClientInfo)(),l=
|
|
341
|
+
const c=(0,s.getGlobalClientInfo)(),l=i.sessionIdentity.getCurrentCallOrigin(),d={...e,...l&&{cliOrigin:l},metadata:{...e.metadata,clientName:c.clientName,clientVersion:c.clientVersion,sessionTag:c.sessionTag}},u=await this.requestWithRetry("POST",a,d)
|
|
343
342
|
this.logger.debug("Raw tool record creation response",{responseStatus:(0,o.isSuccessResponse)(u)?200:(0,o.isErrorResponse)(u)?u.error.statusCode:"unknown",responseData:(0,o.isSuccessResponse)(u)?JSON.stringify(u.data).substring(0,500):(0,o.isErrorResponse)(u)?JSON.stringify(u.error).substring(0,500):"unknown response format"})
|
|
344
343
|
const h=(0,o.safeGetResponseData)(u,{})
|
|
345
344
|
return t({success:!0}),this.metrics.incrementCounter("tool_record_creation_success",1),this.logger.info("Successfully created tool record",{recordId:h.id,type:h.type,taskId:h.task_id,requestId:h.request_id}),(0,n.adaptApiToolRecordToDomain)(h)}catch(s){if(404===this.extractErrorStatus(s)){this.logger.error("Tool record creation failed: Endpoint not found (404)",{endpoint:`/api/projects/${r}/tool-records`,error:this.getErrorMessage(s)})
|
|
@@ -462,7 +461,7 @@ Object.defineProperty(exports,"__esModule",{value:!0}),exports.registerApiRoutes
|
|
|
462
461
|
n.debug("Token retrieved from authentication manager")
|
|
463
462
|
const j=new b.ConnectionStatusManager(T,n.child({component:"connection-status-manager"}),o,{checkIntervalMs:3e4,timeoutMs:5e3}),x=new w.ProjectClient(T,n.child({component:"project-client"}),o,j,M)
|
|
464
463
|
R.registerClient(x)
|
|
465
|
-
const O=new
|
|
464
|
+
const O=new I.TaskClient(T,n.child({component:"task-client"}),o,x,j,M)
|
|
466
465
|
R.registerClient(O)
|
|
467
466
|
const D=new v.FileOperationsClient(T,n.child({component:"file-client"}),o,x,M,j)
|
|
468
467
|
R.registerClient(D)
|
|
@@ -488,9 +487,9 @@ if((0,d.isDebugToolsEnabled)()&&s.debug("Task validation response received",{tas
|
|
|
488
487
|
let o=!1
|
|
489
488
|
if("object"==typeof e&&null!==e){404===e.statusCode&&(o=!0),404===e.response?.statusCode&&(o=!0)
|
|
490
489
|
const t=(e.message||e.error||e)+"";(t.includes("404")||t.toLowerCase().includes("not found"))&&(o=!0)}if(o)return s.info("Task ID not found - blocking operation",{taskId:n,statusCode:404,action:"blocking"}),t.status(400).json({success:!1,error:{code:"TASK_NOT_FOUND",message:"Task ID does not exist: "+n,retryable:!1,statusCode:400}})
|
|
491
|
-
s.warn("Error validating task ID",{taskId:n,error:(0,
|
|
490
|
+
s.warn("Error validating task ID",{taskId:n,error:(0,k.getErrorMessage)(e)}),s.warn("Error validating task ID, but continuing as fallback",{taskId:n,action:"continuing"}),r()}}
|
|
492
491
|
e.get("/health",((e,t)=>{o.incrementCounter("api_requests_total",1,{endpoint:"health",method:"GET"}),t.json({success:!0,data:{status:"ok",version:"0.1.0",serverType:"mcp-local-server",timestamp:(new Date).toISOString()}})})),e.get("/mcp/sse",(async(e,t)=>{s.info("New SSE connection requested",{ip:e.ip,userAgent:e.headers["user-agent"]}),o.incrementCounter("mcp_connections_total",1,{type:"sse"})
|
|
493
|
-
try{await r.createSseConnection(t,e.headers["user-agent"]),t.on("close",(()=>{s.info("SSE connection closed"),o.setGauge("mcp_active_connections",0,{type:"sse"}),r.cleanupSSEConnection()}))}catch(e){s.error("Failed to establish MCP SSE connection",{error:e instanceof Error?e.stack:e+""}),o.incrementCounter("mcp_connection_errors",1,{type:"sse",error:e instanceof Error?e.name:"unknown"}),t.headersSent?t.end():t.status(500).json({success:!1,error:"Failed to establish SSE connection",message:(0,
|
|
492
|
+
try{await r.createSseConnection(t,e.headers["user-agent"]),t.on("close",(()=>{s.info("SSE connection closed"),o.setGauge("mcp_active_connections",0,{type:"sse"}),r.cleanupSSEConnection()}))}catch(e){s.error("Failed to establish MCP SSE connection",{error:e instanceof Error?e.stack:e+""}),o.incrementCounter("mcp_connection_errors",1,{type:"sse",error:e instanceof Error?e.name:"unknown"}),t.headersSent?t.end():t.status(500).json({success:!1,error:"Failed to establish SSE connection",message:(0,k.getErrorMessage)(e)})}})),e.get("/api/files/exists",U,(async(e,t,r)=>{try{o.incrementCounter("api_requests_total",1,{endpoint:"files/exists",method:"GET"})
|
|
494
493
|
const r=H("api_request_duration")
|
|
495
494
|
try{const n=await l.default.stat(e.fullPath)
|
|
496
495
|
r({endpoint:"files/exists",method:"GET",success:!0}),t.json({success:!0,data:{exists:!0,isDirectory:n.isDirectory(),isFile:n.isFile(),size:n.size,modified:n.mtime}})}catch(e){if("ENOENT"!==e.code)throw e
|
|
@@ -540,7 +539,7 @@ r.getContext(),s.info("Manual project synchronization requested"),s.info("Starti
|
|
|
540
539
|
try{await x.syncProjects(),e({endpoint:"sync/projects",method:"POST",success:!0}),t.json({success:!0,data:{message:"Project synchronization completed successfully",timestamp:(new Date).toISOString()}})}catch(r){s.error("Project synchronization failed",{error:r instanceof Error?r.stack:r+""}),e({endpoint:"sync/projects",method:"POST",success:!1}),t.status(500).json({success:!1,error:"Project synchronization failed",message:r instanceof Error?r.message:r+"",timestamp:(new Date).toISOString()})}}catch(e){n(e)}})),e.get("/api/remote/status",(async(e,t,r)=>{try{o.incrementCounter("api_requests_total",1,{endpoint:"remote/status",method:"GET"})
|
|
541
540
|
const e=H("api_request_duration")
|
|
542
541
|
try{const r=await x.pingDetailed(),n="online"===r.status,o=r.latency
|
|
543
|
-
e({endpoint:"remote/status",method:"GET",success:!0,connected:n}),s.info("Remote server status check",{status:n?"ONLINE":"OFFLINE",latencyMs:o}),t.json({success:!0,data:{connected:n,url:T,latency:o,queueStats:{total:0,pending:0,inProgress:0,completed:0,failed:0},isOffline:x.isOffline(),serverTime:(new Date).toISOString()}})}catch(r){e({endpoint:"remote/status",method:"GET",success:!0,connected:!1}),t.json({success:!0,data:{connected:!1,url:T,error:(0,
|
|
542
|
+
e({endpoint:"remote/status",method:"GET",success:!0,connected:n}),s.info("Remote server status check",{status:n?"ONLINE":"OFFLINE",latencyMs:o}),t.json({success:!0,data:{connected:n,url:T,latency:o,queueStats:{total:0,pending:0,inProgress:0,completed:0,failed:0},isOffline:x.isOffline(),serverTime:(new Date).toISOString()}})}catch(r){e({endpoint:"remote/status",method:"GET",success:!0,connected:!1}),t.json({success:!0,data:{connected:!1,url:T,error:(0,k.getErrorMessage)(r),serverTime:(new Date).toISOString()}})}}catch(e){r(e)}})),e.get("/api/proxy/*",(async(e,t,r)=>{try{const r=e.path.substring(11)
|
|
544
543
|
try{const n=await L.proxyGet(r,e.query)
|
|
545
544
|
t.json(n)}catch(e){if(e instanceof Error&&e.message.includes("ECONNREFUSED"))return t.status(503).json({success:!1,error:"Remote server is unreachable",remotePath:r})
|
|
546
545
|
throw e}}catch(e){r(e)}})),e.post("/api/proxy/*",W,(async(e,t,r)=>{try{const r=e.path.substring(11)
|
|
@@ -550,7 +549,7 @@ throw e}}catch(e){r(e)}})),e.patch("/api/proxy/*",W,(async(e,t,r)=>{try{const r=
|
|
|
550
549
|
try{const n=await L.proxyPatch(r,e.body)
|
|
551
550
|
t.json(n)}catch(e){if(e instanceof Error&&e.message.includes("ECONNREFUSED"))return t.status(503).json({success:!1,error:"Remote server is unreachable",remotePath:r})
|
|
552
551
|
throw e}}catch(e){r(e)}}))}
|
|
553
|
-
const a=i(t(7252)),c=i(t(6928)),l=i(t(1943)),d=t(3444),u=t(9860),h=t(6776),g=t(6476),p=t(3306),f=t(4079),m=t(3895),y=s(t(5967)),w=t(4710),b=t(5681),
|
|
552
|
+
const a=i(t(7252)),c=i(t(6928)),l=i(t(1943)),d=t(3444),u=t(9860),h=t(6776),g=t(6476),p=t(3306),f=t(4079),m=t(3895),y=s(t(5967)),w=t(4710),b=t(5681),k=t(8824),I=t(2968),v=t(6153),C=t(1887),_=t(1666),E=t(9884),q=t(922),S=t(3328)},1253(e,exports,t){var r=this&&this.__importDefault||function(e){return e&&e.__esModule?e:{default:e}}
|
|
554
553
|
Object.defineProperty(exports,"__esModule",{value:!0}),exports.TokenManager=void 0
|
|
555
554
|
const n=r(t(6928)),o=r(t(1943)),s=r(t(6982)),i=r(t(857)),a=t(9067),c=t(8824),l="alchemy-lab"
|
|
556
555
|
exports.TokenManager=class{constructor(e,t,r={}){this.projectId=null,this.encryptionKey=null,this.pendingAuthCheck=!1,this.tempAuthCode=null,this.CACHE_TTL_MS=6e4,this.TOKEN_CACHE={manualToken:null,encryptedToken:null,hasValidToken:null},this.initPromise=null,this.initialized=!1,this.logger=e.child({component:"token-manager"}),this.remoteServerUrl=r.remoteServerUrl||"https://api.alchemylabcode.com",this.allowInteractiveAuth=!1!==r.allowInteractiveAuth,void 0!==r.cacheTtlMs&&r.cacheTtlMs>0&&(this.CACHE_TTL_MS=r.cacheTtlMs),this.serverInstallDir=this.getModuleDir(),this.tokenDirPath=this.serverInstallDir,this.authFlow=new a.ExternalAuthFlow(e,this.remoteServerUrl),this.logger.info("TokenManager initialized",{workingDir:t,serverInstallDir:this.serverInstallDir,tokenDirPath:this.tokenDirPath,allowInteractiveAuth:this.allowInteractiveAuth,cacheTtlMs:this.CACHE_TTL_MS}),this.generateEncryptionKey()}getModuleDir(){const e=__dirname||process.cwd(),t=i.default.homedir()
|
|
@@ -614,18 +613,18 @@ const r=await fetch(t,{method:"GET",headers:{Authorization:"Bearer "+e.token,"Co
|
|
|
614
613
|
if(r.ok){const e=await r.json()
|
|
615
614
|
return this.logger.info("Token validation successful",{status:e.status||"unknown",username:e.username||"unknown"}),!0}return this.logger.info("Token validation failed - token may be invalid or expired",{status:r.status,statusText:r.statusText}),this.invalidateCache(),!1}catch(e){return e instanceof Error&&"AbortError"===e.name?(this.logger.info("Token validation request timed out - assuming offline or server unavailable"),!0):(this.logger.info("Token validation request failed",{error:(0,c.getErrorMessage)(e)}),!0)}}async hasValidAndWorkingToken(){return!!await this.hasValidToken()&&await this.validateTokenWithRemoteServer()}async isGoogleOAuthAvailable(){return await this.authFlow.isGoogleOAuthAvailable()}async startGoogleOAuthFlow(){return await this.authFlow.startGoogleOAuthFlow()}async startGoogleOAuthPolling(e,t,r,n,o){return await this.authFlow.startGoogleOAuthPolling(e,t,r,n,o)}}},1266(e,exports){Object.defineProperty(exports,"__esModule",{value:!0})},1281(e,exports,t){async function r(e,t,o,s,i,a,c,l,d,u=0){let p=0,f=0,m=0
|
|
616
615
|
const y=[]
|
|
617
|
-
if(o.length>=
|
|
616
|
+
if(o.length>=I||c>10)return a.debug("Stopping search in directory - hard cap or depth limit reached",{dir:e,matchesCount:o.length,hardCap:I,depth:c}),{filesCount:p,fileMatchesCount:f,subdirCount:m,subdirStats:y}
|
|
618
617
|
try{const w=await g.default.readdir(e,{withFileTypes:!0}),v=[],C=[]
|
|
619
618
|
for(const t of w){const r=h.default.join(e,t.name)
|
|
620
|
-
if(t.isDirectory()){if(
|
|
619
|
+
if(t.isDirectory()){if(k.includes(t.name)||t.name.startsWith(".")){a.debug("Skipping excluded directory: "+t.name)
|
|
621
620
|
continue}C.push({entry:t,fullPath:r})}else if(t.isFile()){if("*"!==i&&!t.name.endsWith(i)){a.debug("Skipping file due to extension mismatch",{filename:t.name,requiredExtension:i})
|
|
622
621
|
continue}v.push({entry:t,fullPath:r})}}if(v.length>0){const e=[]
|
|
623
622
|
for(let t=0;t<v.length;t+=16)e.push(v.slice(t,t+16))
|
|
624
|
-
for(const r of e){if(o.length>=
|
|
623
|
+
for(const r of e){if(o.length>=I)break
|
|
625
624
|
const e=await Promise.all(r.map((({entry:e,fullPath:r})=>n(r,t,0,o,l,d,e.name,u))))
|
|
626
625
|
for(const t of e){p++,t.hasMatches&&f++
|
|
627
|
-
for(const e of t.matches){if(o.length>=
|
|
628
|
-
o.push(e)}}}}for(const{entry:e,fullPath:n}of C){if(o.length>=
|
|
626
|
+
for(const e of t.matches){if(o.length>=I)return{filesCount:p,fileMatchesCount:f,subdirCount:m,subdirStats:y}
|
|
627
|
+
o.push(e)}}}}for(const{entry:e,fullPath:n}of C){if(o.length>=I)break
|
|
629
628
|
m++
|
|
630
629
|
const e={path:n,filesProcessed:0,filesMatched:0,subdirectories:0,errors:[]}
|
|
631
630
|
try{const l=await r(n,t,o,s,i,a,c+1,e,d,u)
|
|
@@ -636,7 +635,7 @@ let l,d=!1
|
|
|
636
635
|
const u=async()=>{if(void 0===l)try{const t=await g.default.stat(e)
|
|
637
636
|
l=t.mtime.getTime()}catch(e){l=void 0}return l}
|
|
638
637
|
if("filename"!==s&&"both"!==s||t.test(i)&&(d=!0,await u(),c.push({file:e,line:0,text:i,modifiedTime:l,matchType:"filename"})),"content"===s||"both"===s)try{const r=(await g.default.readFile(e,"utf8")).split("\n")
|
|
639
|
-
for(let o=0;o<r.length&&n.length<
|
|
638
|
+
for(let o=0;o<r.length&&n.length<I;o++)if(t.test(r[o])){d=!0,await u()
|
|
640
639
|
const t={file:e,line:o+1,text:(0,y.truncate)(r[o].trim(),120),modifiedTime:l,matchType:"content"}
|
|
641
640
|
if(a>0){const e=Math.max(0,o-a)
|
|
642
641
|
t.contextBefore=r.slice(e,o).map((e=>(0,y.truncate)(e.trim(),120)))
|
|
@@ -663,29 +662,29 @@ var t={}
|
|
|
663
662
|
if(null!=e)for(var r=a(e),n=0;n<r.length;n++)"default"!==r[n]&&c(t,e,r[n])
|
|
664
663
|
return l(t,e),t}),u=this&&this.__importDefault||function(e){return e&&e.__esModule?e:{default:e}}
|
|
665
664
|
Object.defineProperty(exports,"__esModule",{value:!0}),exports.handleSearch=async function(e,t,n,a,c){const l=a.child({tool:"search"}),d=c.startTimer("tool_execution_time"),u=Date.now()
|
|
666
|
-
let
|
|
667
|
-
const
|
|
665
|
+
let k=0
|
|
666
|
+
const I={searchDirectory:"",resolvedPath:"",patternInfo:{needle:"",regex:"",caseSensitive:!1,fileExtension:"",normalizedExtension:""},environmentInfo:{platform:process.platform,nodeVersion:process.version,hostname:p.default.hostname(),username:p.default.userInfo().username,workingDirectory:process.cwd(),contextBasePath:t?.basePath||"unknown"},startTime:u,endTime:0,phases:{initializationTime:0,searchTime:0,directoryListingTime:0},totalFiles:0,totalMatches:0,directoryStats:[],errors:[]}
|
|
668
667
|
try{const{needle:n,directory:p,options:v={}}=e
|
|
669
668
|
if(!n||""===n.trim())return l.info("Empty needle detected, switching to list-all mode"),await(0,w.handleListDirectory)({path:p||".",levels:v.levels||1,sortBy:v.sortBy||"name"},t,a,c)
|
|
670
|
-
if("string"!=typeof n)throw
|
|
669
|
+
if("string"!=typeof n)throw I.errors.push("Search term (needle) must be a string"),(0,f.createValidationError)("Search term (needle) must be a string")
|
|
671
670
|
let C
|
|
672
|
-
if(
|
|
671
|
+
if(I.searchDirectory=p||".",p){const{normalizedPath:e,fullPath:r}=m.validateAndNormalizePath(p,t)
|
|
673
672
|
C=r}else C=t.basePath
|
|
674
|
-
|
|
673
|
+
I.resolvedPath=C
|
|
675
674
|
let _=!1
|
|
676
675
|
try{_=(await g.default.stat(C)).isFile()}catch(e){const t=`Cannot access path ${C}: ${(0,b.getErrorMessage)(e)}`
|
|
677
|
-
throw
|
|
676
|
+
throw I.errors.push(t),Error(t)}const E=v.maxResults||50,q=v.caseSensitive||!1,S=v.useRegex||!1,T=v.fileExtension,P=v.searchIn||"content"
|
|
678
677
|
let R=void 0!==v.contextLines?v.contextLines:0
|
|
679
|
-
if(0>R?R=0:R>10&&(l.warn(`contextLines ${R} exceeds maximum of 10, clamping to 10`),R=10),!_&&!T)throw
|
|
678
|
+
if(0>R?R=0:R>10&&(l.warn(`contextLines ${R} exceeds maximum of 10, clamping to 10`),R=10),!_&&!T)throw I.errors.push('File extension is required for directory search (use "*" for any extension, or formats like "ts", ".ts", "*.ts")'),(0,f.createValidationError)('File extension is required for directory search (use "*" for any extension, or formats like "ts", ".ts", "*.ts")')
|
|
680
679
|
let M,j=""
|
|
681
680
|
if(_)j="*"
|
|
682
681
|
else if("*"===T)j="*"
|
|
683
682
|
else if(T){let e=T;(e.startsWith("*.")||e.startsWith("*"))&&(e=e.substring(1)),j=e.startsWith(".")?e:"."+e}try{M=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,b.getErrorMessage)(e)}`
|
|
684
|
-
throw
|
|
683
|
+
throw I.errors.push(t),(0,f.createValidationError)(t)}if(I.patternInfo={needle:n,regex:M.toString(),caseSensitive:q,fileExtension:T,normalizedExtension:j},!_)try{const e=Date.now(),t=await g.default.readdir(C,{withFileTypes:!0}),r=[],n=[]
|
|
685
684
|
for(const e of t)e.isDirectory()?r.push(e.name):e.isFile()&&n.push(e.name)
|
|
686
|
-
|
|
687
|
-
|
|
688
|
-
l.info(`Searching for "${n}" in ${x} ${C} (mode: ${P})`,{needle:n,searchTarget:x,path:C,options:{maxResults:E,caseSensitive:q,fileExtension:j,searchIn:P}}),
|
|
685
|
+
I.initialScan={totalEntries:t.length,directories:r,files:n,firstFewFiles:n.slice(0,10),scanTime:Date.now()-e},I.phases.directoryListingTime=I.initialScan.scanTime}catch(e){const t="Failed to scan directory contents: "+(0,b.getErrorMessage)(e)
|
|
686
|
+
I.errors.push(t),l.error(t)}const x=_?"file":"directory"
|
|
687
|
+
l.info(`Searching for "${n}" in ${x} ${C} (mode: ${P})`,{needle:n,searchTarget:x,path:C,options:{maxResults:E,caseSensitive:q,fileExtension:j,searchIn:P}}),k=Date.now(),I.phases.initializationTime=k-u
|
|
689
688
|
const O=Date.now()
|
|
690
689
|
let D=[],A=0,$=0
|
|
691
690
|
try{const e=await async function(e,t,n,o,s,i){const{maxResults:a,fileExtension:c,searchIn:l,isFile:d,contextLines:u}=n,p=[]
|
|
@@ -703,15 +702,15 @@ o.errors.push(r),n.error(r)}return{matches:i,totalFiles:1}}(e,t,l,s,i,u)
|
|
|
703
702
|
const f={path:e,filesProcessed:0,filesMatched:0,subdirectories:0,errors:[]}
|
|
704
703
|
try{const{filesCount:n,fileMatchesCount:c,subdirCount:d,subdirStats:h}=await r(e,t,p,a,o,s,0,f,l,u)
|
|
705
704
|
return f.filesProcessed=n,f.filesMatched=c,f.subdirectories=d,i.directoryStats.push(f),h&&h.length>0&&i.directoryStats.push(...h),s.info("performLocalSearch completed",{totalFiles:n,matchesFound:p.length,directories:d+1}),{matches:p,totalFiles:n}}catch(t){const r="Error in performLocalSearch: "+(0,b.getErrorMessage)(t)
|
|
706
|
-
return f.errors.push(r),i.directoryStats.push(f),i.errors.push(r),s.error(r,{error:t instanceof Error?t.stack:t+"",searchPath:e}),{matches:p,totalFiles:f.filesProcessed}}}(C,M,{maxResults:E,fileExtension:j,searchIn:P,isFile:_,contextLines:R},j,l,
|
|
705
|
+
return f.errors.push(r),i.directoryStats.push(f),i.errors.push(r),s.error(r,{error:t instanceof Error?t.stack:t+"",searchPath:e}),{matches:p,totalFiles:f.filesProcessed}}}(C,M,{maxResults:E,fileExtension:j,searchIn:P,isFile:_,contextLines:R},j,l,I)
|
|
707
706
|
D=e.matches,A=e.totalFiles
|
|
708
707
|
const t=1e3
|
|
709
708
|
D.length>0&&D.length<=t?(D.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 ${D.length} matches by modification time (newest first)`)):D.length>t&&l.info(`Skipped sorting ${D.length} matches (exceeds hard cap of ${t} for performance)`),$=D.length,D.length>E&&(D=D.slice(0,E),l.info(`Limited results to ${E} (from ${$} total matches)`)),D.forEach((e=>{e.relativePath=function(e,t){const r=h.default.relative(e,t)
|
|
710
|
-
return r?r===h.default.basename(t)?r:r.startsWith("./")?r.substring(2):r:h.default.basename(t)}(C,e.file)})),l.info(`Local search completed: found ${$||D.length} total matches in ${A} files, returning ${D.length} results`),
|
|
711
|
-
|
|
709
|
+
return r?r===h.default.basename(t)?r:r.startsWith("./")?r.substring(2):r:h.default.basename(t)}(C,e.file)})),l.info(`Local search completed: found ${$||D.length} total matches in ${A} files, returning ${D.length} results`),I.phases.searchTime=Date.now()-O}catch(e){const t="Error during search: "+(0,b.getErrorMessage)(e)
|
|
710
|
+
I.errors.push(t),l.error(t),I.phases.searchTime=Date.now()-O}I.totalFiles=A,I.totalMatches=D.length,I.endTime=Date.now()
|
|
712
711
|
let F,N=""
|
|
713
712
|
try{if(t.getCurrentBranchContext){const e=await t.getCurrentBranchContext()
|
|
714
|
-
e.branch&&(N=e.isMain?` (searched on main branch: ${e.branch})`:` (searched on request branch: ${e.branch}${e.requestId?" for "+e.requestId:""})`)}}catch(e){l.debug("Could not get branch context",{error:e}),N=" (branch context unavailable)"}l.debug("Search diagnostic information",{diagnostic:
|
|
713
|
+
e.branch&&(N=e.isMain?` (searched on main branch: ${e.branch})`:` (searched on request branch: ${e.branch}${e.requestId?" for "+e.requestId:""})`)}}catch(e){l.debug("Could not get branch context",{error:e}),N=" (branch context unavailable)"}l.debug("Search diagnostic information",{diagnostic:I})
|
|
715
714
|
const L="content"===P?"content":"filename"===P?"filenames":"content and filenames"
|
|
716
715
|
if($>D.length?(F=`Found ${$} results for "${n}" (searching ${L})`,p&&(F+=" in "+p),T&&(F+=" with extension "+T),F+=`${N}. Showing first ${D.length}:\n\n`):(F=`Found ${D.length} results for "${n}" (searching ${L})`,p&&(F+=" in "+p),T&&(F+=" with extension "+T),F+=N+":\n\n"),D.length>0)if(R>0){const{filenameMatches:e,mergedGroups:t}=function(e,t){const r=e.filter((e=>"filename"===e.matchType)),n=e.filter((e=>"content"===e.matchType))
|
|
717
716
|
if(0===n.length)return{filenameMatches:r,mergedGroups:[]}
|
|
@@ -734,10 +733,10 @@ void 0!==s&&(a+=` (${s} lines)`),a+=` - ${o} ${1===o?"match":"matches"}:`
|
|
|
734
733
|
const c=t.map((e=>` :${e.line} - ${e.text}`))
|
|
735
734
|
n.push(a+"\n"+c.join("\n"))}return n.join("\n\n")}(D)
|
|
736
735
|
else F+="No matches found."
|
|
737
|
-
return d({success:!0}),{content:[{type:"text",text:F}]}}catch(t){l.error("Search failed",{args:e,error:t instanceof Error?t.stack:t+""}),
|
|
736
|
+
return d({success:!0}),{content:[{type:"text",text:F}]}}catch(t){l.error("Search failed",{args:e,error:t instanceof Error?t.stack:t+""}),I.errors.push((0,b.getErrorMessage)(t)),I.endTime=Date.now(),l.debug("Search diagnostic information on error",{diagnostic:I})
|
|
738
737
|
let r="Search failed: "+(0,b.getErrorMessage)(t)
|
|
739
738
|
return d({success:!1,error:t instanceof Error?t.name:"unknown"}),{content:[{type:"text",text:r}],isError:!0}}}
|
|
740
|
-
const h=u(t(6928)),g=u(t(1943)),p=u(t(857)),f=t(9860),m=d(t(5967)),y=t(5967),w=t(2537),b=t(8824),
|
|
739
|
+
const h=u(t(6928)),g=u(t(1943)),p=u(t(857)),f=t(9860),m=d(t(5967)),y=t(5967),w=t(2537),b=t(8824),k=["node_modules"],I=1e4,v=new Set([".ts",".tsx",".js",".jsx",".mjs",".cjs",".py",".rb",".go",".rs",".java",".kt",".scala",".c",".cpp",".h",".hpp",".cs",".html",".css",".scss",".sass",".less",".json",".yaml",".yml",".toml",".xml",".md",".txt",".csv",".sql",".sh",".bash",".zsh",".fish",".vim",".lua",".php",".swift",".m",".vue",".svelte",".astro",".env",".gitignore",".dockerignore"]),C=1048576},1318(e,exports,t){async function r(e,t,r){try{const r=(await e.revparse(["--show-toplevel"])).trim(),n=c.default.isAbsolute(t)?t:c.default.resolve(t)
|
|
741
740
|
return c.default.relative(r,n)}catch(e){return r.warn("Failed to get repo-relative path, using original",{filePath:t,error:(0,l.getErrorMessage)(e)}),t}}function n(e){return/\(trec\d{6}\)/.test(e)}async function o(e,t,n,o,s){try{const i=await r(e,t,s),a=await e.raw(["log","-1","--pretty=format:%H|%s",`-L${n},${o}:${i}`])
|
|
742
741
|
if(!a||""===a.trim())return null
|
|
743
742
|
const c=a.trim().split("\n")[0],[l,...d]=c.split("|"),u=d.join("|")
|
|
@@ -813,37 +812,34 @@ try{return await i.hasValidToken()}catch(e){return m.error("Error checking authe
|
|
|
813
812
|
m.info(`Generating tools list with testsRequired=${e}, authenticated=${t}`)
|
|
814
813
|
const r={testsRequired:e,authenticated:t}
|
|
815
814
|
return(0,f.generateVisibleToolsList)(r)}
|
|
816
|
-
let
|
|
817
|
-
|
|
815
|
+
let k=b(),I=[]
|
|
816
|
+
k.then((e=>{I=e})).catch((e=>{m.error("Error generating initial tools list",{error:(0,l.getErrorMessage)(e)}),I=[]})),e.setRequestHandler(a.ListToolsRequestSchema,(async()=>{try{return I=await b(),{tools:I}}catch(e){return m.error("Error generating tools list",{error:(0,l.getErrorMessage)(e)}),{tools:[]}}}))
|
|
818
817
|
let v=!1
|
|
819
818
|
e.setRequestHandler(a.CallToolRequestSchema,(async e=>{try{const{name:i,arguments:a={},_meta:c}=e.params;(0,p.logSessionIdentity)(i,"_meta-debug",{has_meta:!!c,sessionId:c?.sessionId||null,messageId:c?.messageId||null,paramKeys:Object.keys(e.params)}),m.info("Tool call received: "+i,{tool:i}),s.incrementCounter("tool_calls_total",1,{tool:i})
|
|
820
819
|
const b=s.startTimer("tool_execution_time")
|
|
821
820
|
Date.now()
|
|
822
|
-
let
|
|
823
|
-
const
|
|
824
|
-
if(Date.now(),
|
|
821
|
+
let k=Date.now()
|
|
822
|
+
const I=r(a)
|
|
823
|
+
if(Date.now(),k=Date.now(),y){const e=await w()
|
|
825
824
|
if(Date.now(),!e)return m.warn("Unauthenticated tool call attempt",{tool:i}),{content:[{type:"text",text:"Authentication required. Please run 'alchemylab setup' to authenticate and configure your project."}],isError:!0}}const C=(0,f.getToolByName)(i)
|
|
826
|
-
|
|
827
|
-
|
|
828
|
-
if(
|
|
829
|
-
if(n)n.sessionId!==e&&((0,p.logSessionIdentity)(i,"_meta-session-switch",{prevSessionId:n.sessionId,prevAgentType:n.agentType,newSessionId:e}),u.sessionIdentity.setIdentity({providerId:"opencode",sessionId:e,serverUrl:n.serverUrl}))
|
|
825
|
+
let _
|
|
826
|
+
if(k=Date.now(),n?(n.setOptions({createRecords:C?.createsRecords??!1}),m.info(`Setting record creation for tool ${i}: ${C?.createsRecords??!1}`)):m.debug(`No API client available for tool ${i} (minimal mode)`),Date.now(),Date.now(),k=Date.now(),c?.sessionId){const e=c.sessionId,r=c.messageId,n=u.sessionIdentity.getIdentity()
|
|
827
|
+
if(n)n.sessionId!==e&&((0,p.logSessionIdentity)(i,"_meta-session-switch",{prevSessionId:n.sessionId,prevAgentType:n.agentType,newSessionId:e}),u.sessionIdentity.setIdentity({providerId:"opencode",sessionId:e,serverUrl:n.serverUrl}),t?.workspaceManager?.resetCurrentContext?.(e))
|
|
830
828
|
else{const r=await(0,d.getServerUrl)(t,m)
|
|
831
|
-
u.sessionIdentity.setIdentity({providerId:"opencode",sessionId:e,serverUrl:r||""})
|
|
832
|
-
|
|
833
|
-
|
|
834
|
-
|
|
835
|
-
|
|
836
|
-
|
|
837
|
-
t?(u.sessionIdentity.setIdentity({providerId:"opencode",sessionId:t.sessionId,serverUrl:e.serverUrl}),(0,p.logSessionIdentity)(i,"re-discovery",{sessionId:t.sessionId,messageId:t.messageId}),_=u.sessionIdentity.buildCliOrigin(t.messageId)):(u.sessionIdentity.setIdentity(e),_=u.sessionIdentity.buildCliOrigin(),m.info("Re-discovery found no other session, keeping current identity",{sessionId:e.sessionId})),u.sessionIdentity.markDiscoveryAttempted()}catch(t){u.sessionIdentity.setIdentity(e),_=u.sessionIdentity.buildCliOrigin(),u.sessionIdentity.markDiscoveryAttempted(),m.warn("Re-discovery failed, keeping current identity (may be stale)",{error:(0,l.getErrorMessage)(t),tool:i,sessionId:e.sessionId})}}}else if(!u.sessionIdentity.hasDiscoveryBeenAttempted())try{const e=await(0,d.getServerUrl)(t,m)
|
|
838
|
-
if(e){const t=await(0,d.getAndStoreSessionId)(e,m,i)
|
|
839
|
-
t&&(u.sessionIdentity.setIdentity({providerId:"opencode",sessionId:t.sessionId,serverUrl:e}),(0,p.logSessionIdentity)(i,"http-discovery",{sessionId:t.sessionId,messageId:t.messageId}),_=u.sessionIdentity.buildCliOrigin(t.messageId))}u.sessionIdentity.markDiscoveryAttempted()}catch(e){u.sessionIdentity.markDiscoveryAttempted(),(0,p.logSessionIdentity)(i,"discovery-failed",{error:(0,l.getErrorMessage)(e)}),m.debug("cliOrigin discovery failed",{error:(0,l.getErrorMessage)(e),tool:i})}}if(u.sessionIdentity.setCurrentCallOrigin(_),!v&&n){const e=u.sessionIdentity.getIdentity(),t=process.env.ALCHEMY_INITIAL_BRANCH
|
|
829
|
+
u.sessionIdentity.setIdentity({providerId:"opencode",sessionId:e,serverUrl:r||""})}_={providerId:"opencode",sessionId:e,messageId:r,createdAt:(new Date).toISOString()},(0,p.logSessionIdentity)(i,"_meta",{sessionId:e,messageId:r})}else m.warn("No _meta.sessionId on tool call \u2014 session identity unavailable",{tool:i})
|
|
830
|
+
u.sessionIdentity.setCurrentCallOrigin(_)
|
|
831
|
+
const E=_?.sessionId||c?.sessionId
|
|
832
|
+
if(t?.workspaceManager){k=Date.now()
|
|
833
|
+
try{const e=await(0,d.getServerUrl)(t,m)
|
|
834
|
+
e&&n&&await t.workspaceManager.ensureReadonlyBranchIfNeeded(e,i,n,E)}catch(e){m.debug("Error during workspace check",{error:(0,l.getErrorMessage)(e)})}Date.now()}if(!v&&n){const e=u.sessionIdentity.getIdentity(),t=process.env.ALCHEMY_INITIAL_BRANCH
|
|
840
835
|
if(e?.sessionId&&t){const r=t.match(/^requests\/(.+)$/),o="1"===process.env.ALCHEMY_ALLOW_PARALLEL
|
|
841
836
|
if(r&&!o){const t=r[1]
|
|
842
837
|
v=!0
|
|
843
838
|
try{const{sessionTag:r}=(0,h.getGlobalClientInfo)(),o=n.getSessionTagMappingClient(),s=n.getRequestClient(),i=o?o.getMappingByOpencodeSessionId(e.sessionId).then((t=>{t?((0,h.setSessionTag)(t.sessionTag),m.info("Recovered session tag from mapping",{opencodeSessionId:e.sessionId,sessionTag:t.sessionTag})):(o.createOrUpdateMapping(r,e.sessionId).catch((()=>{})),m.info("Registered session tag mapping",{opencodeSessionId:e.sessionId,sessionTag:r}))}),(e=>m.debug("Mapping lookup failed",{error:(0,l.getErrorMessage)(e)}))):Promise.resolve(),a=s.lockRequest?s.lockRequest(t,r).then((e=>{e.locked?m.info("Acquired request lock",{requestId:t,sessionTag:r}):m.warn("Failed to acquire request lock",{requestId:t,sessionTag:r})}),(e=>m.warn("Lock acquisition failed",{error:(0,l.getErrorMessage)(e)}))):Promise.resolve()
|
|
844
|
-
await Promise.all([i,a])}catch(e){m.warn("Error in session tag mapping / lock acquisition",{error:(0,l.getErrorMessage)(e)})}}}}
|
|
845
|
-
|
|
846
|
-
|
|
839
|
+
await Promise.all([i,a])}catch(e){m.warn("Error in session tag mapping / lock acquisition",{error:(0,l.getErrorMessage)(e)})}}}}let q
|
|
840
|
+
if(C){const e={context:t,apiClient:n,logger:o,metrics:s,mcpServer:g,cliOrigin:_}
|
|
841
|
+
q=await C.handler(I,e)}else m.info(`Tool ${i} not found, returning negative response`),q={content:[{type:"text",text:`The tool '${i}' does not exist.`}]}
|
|
842
|
+
return Date.now(),Date.now(),b({tool:i,success:!0}),q}catch(t){m.error("Error executing tool:",{error:t instanceof Error?t.stack:t+"",tool:e.params.name}),s.incrementCounter("tool_errors_total",1,{tool:e.params.name,error:t instanceof Error?t.name:"unknown"})
|
|
847
843
|
let r="Unknown error"
|
|
848
844
|
if(t instanceof Error)r=t.message
|
|
849
845
|
else if("string"==typeof t)r=t
|
|
@@ -1180,94 +1176,92 @@ const e=this.online,t=await this.performHealthCheck()
|
|
|
1180
1176
|
return e!==t&&(t?(this.logger.info("Health check status changed to ONLINE"),this.options.onOnlineCallback()):(this.logger.info("Health check status changed to OFFLINE"),this.options.onOfflineCallback())),t}isOffline(){return this.forcedOfflineMode||!1}scheduleNextCheck(e=this.options.checkIntervalMs){this.checkInterval&&(clearInterval(this.checkInterval),this.checkInterval=null),0!==e?setTimeout((()=>{this.performHealthCheck().catch((()=>{}))}),e||this.options.checkIntervalMs||3e4):this.performHealthCheck().catch((()=>{}))}setOfflineMode(e){const t=this.forcedOfflineMode
|
|
1181
1177
|
this.forcedOfflineMode=e,t!==e&&(this.logger.info("Offline mode "+(e?"ENABLED":"DISABLED")),this.metrics.setGauge("health_check_forced_offline",e?1:0),e||this.scheduleNextCheck(0))}getStats(){return{consecutiveFailures:this.consecutiveFailures,currentBackoffMs:this.currentBackoffMs,lastCheckTime:this.lastCheckTime}}}},1722(e,exports,t){Object.defineProperty(exports,"__esModule",{value:!0}),exports.def=void 0
|
|
1182
1178
|
const r=t(6183),n=t(355)
|
|
1183
|
-
exports.def={name:"complete_task",description:"Mark a task as completed with a summary of work done.",schema:r.CompleteTaskSchema,annotations:{title:"Complete Task",readOnlyHint:!1,destructiveHint:!1,idempotentHint:!0},handler(e,t){return(0,n.handleCompleteTask)(e,t.context,t.apiClient,t.logger,t.metrics,t.mcpServer)}}},1725(e,exports,t){function r(e,t,r){try{const n=`[${(new Date).toISOString()}] ${t}${r?" "+JSON.stringify(r):""}\n`,o=(0,
|
|
1179
|
+
exports.def={name:"complete_task",description:"Mark a task as completed with a summary of work done.",schema:r.CompleteTaskSchema,annotations:{title:"Complete Task",readOnlyHint:!1,destructiveHint:!1,idempotentHint:!0},handler(e,t){return(0,n.handleCompleteTask)(e,t.context,t.apiClient,t.logger,t.metrics,t.mcpServer)}}},1725(e,exports,t){function r(e,t,r){try{const n=`[${(new Date).toISOString()}] ${t}${r?" "+JSON.stringify(r):""}\n`,o=(0,T.join)(e.basePath||process.cwd(),".alchemy_lab","spawn-debug.log");(0,S.appendFileSync)(o,n)}catch{}}async function n(e){try{const t=`http://localhost:${M}/api/agents/by-name/${encodeURIComponent(e)}`,r=await fetch(t)
|
|
1184
1180
|
if(!r.ok)return null
|
|
1185
1181
|
const n=await r.json()
|
|
1186
1182
|
return n.success?n.data??null:null}catch{return null}}async function o(e,t,o,s,i){const{agent:a="work",prompt:c,requestId:l,allowParallel:d=!1,useExistingSession:u}=e
|
|
1187
|
-
if(r(t,"handleSpawn called",{agent:a,promptLength:c.length,requestId:l,useExistingSession:u,cliOriginSessionId:i?.sessionId||null}),!(0,
|
|
1188
|
-
return{content:[{type:"text",text:`\u274c Unknown agent '${a}'.\n\n**Available agents:** ${e.join(", ")}\n\nChoose one of the available agents listed above to see detailed descriptions of each agent.`}],isError:!0}}try{const e=
|
|
1189
|
-
let
|
|
1190
|
-
if(r(t,"Spawn agent type check",{
|
|
1191
|
-
r(t,"Looking up agent type from action server",{sessionId:
|
|
1192
|
-
const s=await fetch(
|
|
1193
|
-
if(s.ok){const
|
|
1194
|
-
r(t,"Agent type response from action server",{sessionId:
|
|
1195
|
-
if(e&&!e.includes(a))return{content:[{type:"text",text:`\u274c Agent type '${
|
|
1183
|
+
if(r(t,"handleSpawn called",{agent:a,promptLength:c.length,requestId:l,useExistingSession:u,cliOriginSessionId:i?.sessionId||null}),!(0,P.isValidAgent)(a)){const e=(0,P.getAgentNames)()
|
|
1184
|
+
return{content:[{type:"text",text:`\u274c Unknown agent '${a}'.\n\n**Available agents:** ${e.join(", ")}\n\nChoose one of the available agents listed above to see detailed descriptions of each agent.`}],isError:!0}}try{const e=i?.sessionId
|
|
1185
|
+
let n=v.sessionIdentity.getIdentity()?.agentType
|
|
1186
|
+
if(r(t,"Spawn agent type check",{callerSessionId:e||null,cachedAgentType:n||null,pid:process.pid}),!n&&e)try{const o=`http://localhost:${M}/api/sessions/${encodeURIComponent(e)}/agent-type`
|
|
1187
|
+
r(t,"Looking up agent type from action server",{sessionId:e,url:o})
|
|
1188
|
+
const s=await fetch(o)
|
|
1189
|
+
if(s.ok){const o=await s.json()
|
|
1190
|
+
r(t,"Agent type response from action server",{sessionId:e,agentType:o.agentType||null,source:o.source||null,success:o.success}),o.success&&o.agentType&&(n=o.agentType,v.sessionIdentity.updateIdentity({agentType:n}))}else r(t,"Agent type lookup failed",{sessionId:e,status:s.status})}catch(n){r(t,"Agent type lookup error",{sessionId:e,error:(0,q.getErrorMessage)(n)})}if(n){const e=(0,P.getAllowedSubagents)(n)
|
|
1191
|
+
if(e&&!e.includes(a))return{content:[{type:"text",text:`\u274c Agent type '${n}' cannot spawn '${a}'.\n\n**Allowed subagents for ${n}:** ${e.join(", ")}\n\nUse one of the allowed agent types instead.`}],isError:!0}}}catch(e){r(t,"allowedSubagents check failed",{error:(0,q.getErrorMessage)(e)})}let h
|
|
1196
1192
|
try{const e=await n(a)
|
|
1197
|
-
if(h=e?.requestContextMode,!h){const e=(0,
|
|
1193
|
+
if(h=e?.requestContextMode,!h){const e=(0,P.getBuiltInAgentConfig)(a)
|
|
1198
1194
|
h=e?.requestContextMode}}catch{}if(h&&"none"!==h&&!l)return{content:[{type:"text",text:`\u274c Agent '${a}' requires a requestId to be provided.\n\nThis agent has requestContextMode: '${h}' which means it needs to work in the context of a specific request.\n\nPlease provide a requestId when spawning this agent.`}],isError:!0}
|
|
1199
1195
|
const g=await(0,I.getServerUrl)(t,o)
|
|
1200
1196
|
r(t,"serverUrl resolved",{serverUrl:g})
|
|
1201
1197
|
const p=t.basePath
|
|
1202
1198
|
if(!p)throw new w.ValidationError("Working directory not available in context")
|
|
1203
|
-
const f=
|
|
1204
|
-
let m
|
|
1205
|
-
if(g)try{m=i?.sessionId||f?.sessionId||await(0,I.discoverParentSessionId)(g,o)}catch{}let y=""
|
|
1199
|
+
const f=i?.sessionId
|
|
1200
|
+
let m=""
|
|
1206
1201
|
if(s&&l)try{const e=s.getSessionRequestAssociationClient()
|
|
1207
|
-
if(e){const t=await e.getSessionsForRequest(l,!0),r=
|
|
1202
|
+
if(e){const t=await e.getSessionsForRequest(l,!0),r=f?t.filter((e=>e.opencodeSessionId!==f)):t
|
|
1208
1203
|
if(r.length>0){const e=r.map((e=>e.opencodeSessionId)).join(", ")
|
|
1209
1204
|
if(!d)return o.warn("Blocked spawn: request already has active workers",{requestId:l,existingWorkerCount:r.length,existingSessionIds:r.map((e=>e.opencodeSessionId))}),{content:[{type:"text",text:`\u274c Cannot spawn: Request ${l} already has ${r.length} active worker(s): ${e}\n\nOptions:\n\u2022 Use \`useExistingSession: "${r[0].opencodeSessionId}"\` to send work to the existing session\n\u2022 Use \`allowParallel: true\` if you really need multiple workers on the same request`}],isError:!0}
|
|
1210
|
-
|
|
1211
|
-
l&&(
|
|
1205
|
+
m=`\u26a0\ufe0f Warning: Request ${l} already has ${r.length} active worker(s): ${e}. Proceeding anyway (allowParallel=true).\n\n`,o.warn("Spawning parallel subagent for request with existing active workers",{requestId:l,existingWorkerCount:r.length,existingSessionIds:r.map((e=>e.opencodeSessionId)),allowParallel:!0})}}}catch(e){o.debug("Failed to check for existing workers",{error:(0,q.getErrorMessage)(e)})}let y,_,E=c
|
|
1206
|
+
l&&(y="requests/"+l,r(t,"Setting initialBranch for agent",{agent:a,requestId:l,initialBranch:y,agentRequestContextMode:h||"undefined"}),E="readonly"===h?`Working on request ${l} (READONLY mode - you cannot modify files, only explore and report).\n\n${c}`:`Working on request ${l}.\n\n${c}`)
|
|
1212
1207
|
let S=!1
|
|
1213
1208
|
if(u){if(_=u,o.info("Using existing session for spawn",{sessionId:_,requestId:l}),!g)throw new w.ValidationError("Could not determine OpenCode server URL")
|
|
1214
1209
|
try{let e
|
|
1215
|
-
try{const t=await fetch(`http://localhost:${
|
|
1210
|
+
try{const t=await fetch(`http://localhost:${M}/api/project-settings`)
|
|
1216
1211
|
if(t.ok){const r=await t.json()
|
|
1217
1212
|
if(r.data?.defaultModel){const[t,...n]=r.data.defaultModel.split("/")
|
|
1218
|
-
e={providerID:t,modelID:n.join("/")}}}}catch{}const t=`${g.replace(/\/$/,"")}/session/${_}/prompt_async`,r=await fetch(t,{method:"POST",headers:{"Content-Type":"application/json"},body:JSON.stringify({parts:[{type:"text",text:
|
|
1213
|
+
e={providerID:t,modelID:n.join("/")}}}}catch{}const t=`${g.replace(/\/$/,"")}/session/${_}/prompt_async`,r=await fetch(t,{method:"POST",headers:{"Content-Type":"application/json"},body:JSON.stringify({parts:[{type:"text",text:E}],...a?{agent:a}:{},...e?{model:e}:{}}),signal:AbortSignal.timeout(1e4)})
|
|
1219
1214
|
if(!r.ok){const e=await r.text().catch((()=>"Unknown error"))
|
|
1220
|
-
throw Error(`Failed to send to existing session: ${r.status} ${e}`)}o.info("Prompt sent to existing session",{sessionId:_,agent:a})}catch(e){throw Error("Failed to use existing session: "+(0,
|
|
1221
|
-
const i=
|
|
1222
|
-
const u=g.replace(/\/$/,"")+"/session",h=e.title?e.title:l?`[${l}] ${c.slice(0,40)}${c.length>40?"...":""}`:`${c.slice(0,50)}${c.length>50?"...":""}`,
|
|
1223
|
-
if(!
|
|
1224
|
-
const w=await
|
|
1215
|
+
throw Error(`Failed to send to existing session: ${r.status} ${e}`)}o.info("Prompt sent to existing session",{sessionId:_,agent:a})}catch(e){throw Error("Failed to use existing session: "+(0,q.getErrorMessage)(e))}}else{if(S=!0,r(t,"Creating session via HTTP and spawning CLI"),!g)throw Error("Cannot spawn subagent: no server URL available")
|
|
1216
|
+
const i=f;(0,C.logSessionIdentity)("subagent_operations.spawn","_meta",{parentSessionId:i}),r(t,"Parent session discovered",{parentSessionId:i})
|
|
1217
|
+
const u=g.replace(/\/$/,"")+"/session",h=e.title?e.title:l?`[${l}] ${c.slice(0,40)}${c.length>40?"...":""}`:`${c.slice(0,50)}${c.length>50?"...":""}`,m=await fetch(u,{method:"POST",headers:{"Content-Type":"application/json"},body:JSON.stringify({parentID:i,title:h})})
|
|
1218
|
+
if(!m.ok)throw Error("Failed to create session: "+m.status)
|
|
1219
|
+
const w=await m.json()
|
|
1225
1220
|
if(!w.id)throw Error("Session created but no ID returned")
|
|
1226
|
-
const
|
|
1227
|
-
r(t,"Pre-created session with parentID",{preCreatedSessionId:
|
|
1228
|
-
const
|
|
1221
|
+
const I=w.id
|
|
1222
|
+
r(t,"Pre-created session with parentID",{preCreatedSessionId:I,parentSessionId:i}),o.info("Pre-created session with parentID",{preCreatedSessionId:I,parentSessionId:i})
|
|
1223
|
+
const T=(async()=>{if(s)try{const n=s.getCLISessionClient()
|
|
1229
1224
|
if(!n)return
|
|
1230
1225
|
let o,c
|
|
1231
|
-
if(i){const e=await n.createOrUpdateSession({externalSessionId:i,providerId:"opencode",status:"active",agentType:
|
|
1232
|
-
o=e.id,c=e.workflowId,r(t,"Registered parent session in DB",{parentSessionId:i,parentDbId:o,parentWorkflowId:c})}const l=await n.createOrUpdateSession({externalSessionId:
|
|
1233
|
-
r(t,"Registered child session in DB",{childSessionId:
|
|
1234
|
-
let
|
|
1226
|
+
if(i){const e=await n.createOrUpdateSession({externalSessionId:i,providerId:"opencode",status:"active",agentType:v.sessionIdentity.getIdentity()?.agentType||void 0})
|
|
1227
|
+
o=e.id,c=e.workflowId,r(t,"Registered parent session in DB",{parentSessionId:i,parentDbId:o,parentWorkflowId:c})}const l=await n.createOrUpdateSession({externalSessionId:I,providerId:"opencode",parentSessionId:o||null,title:h,status:"active",agentType:a,specialization:e.specialization,workflowId:c||void 0})
|
|
1228
|
+
r(t,"Registered child session in DB",{childSessionId:I,childDbId:l.id,parentDbId:o})}catch(e){r(t,"Failed to register sessions in DB",{error:(0,q.getErrorMessage)(e)}),o.warn("Failed to register sessions in alchemy DB",{error:(0,q.getErrorMessage)(e)})}})()
|
|
1229
|
+
let j
|
|
1235
1230
|
r(t,"Starting model resolution",{agent:a,cwd:p})
|
|
1236
|
-
try{r(t,"Fetching agent config from action server",{agent:a,url:`http://localhost:${
|
|
1231
|
+
try{r(t,"Fetching agent config from action server",{agent:a,url:`http://localhost:${M}/api/agents/by-name/${a}`})
|
|
1237
1232
|
const e=await n(a)
|
|
1238
1233
|
if(r(t,"Agent config result",{agent:a,agentConfig:e||"null",hasConfig:!!e}),e){const n=e.preferredProvider||"inherit",o=e.preferredModelTier||"same"
|
|
1239
1234
|
r(t,"Agent preferences",{agent:a,preferredProvider:n,preferredTier:o,rawProvider:e.preferredProvider,rawTier:e.preferredModelTier})
|
|
1240
|
-
const s=(0,
|
|
1241
|
-
r(t,"Model resolution result",{agent:a,result:s}),s.resolved?(
|
|
1235
|
+
const s=(0,R.resolveAgentModel)(p,n,o)
|
|
1236
|
+
r(t,"Model resolution result",{agent:a,result:s}),s.resolved?(j=s.fullModel,r(t,"Resolved agent model",{agent:a,model:j,preferredProvider:n,preferredTier:o})):r(t,"Model resolution fallback",{agent:a,reason:s.reason})}else{const e=(0,P.getBuiltInAgentConfig)(a)
|
|
1242
1237
|
if(r(t,"No API agent config, checking built-in defaults",{agent:a,builtInConfig:e||"null"}),e){const n=e.preferredProvider||"inherit",o=e.preferredModelTier||"same"
|
|
1243
1238
|
r(t,"Using built-in agent preferences",{agent:a,preferredProvider:n,preferredTier:o})
|
|
1244
|
-
const s=(0,
|
|
1245
|
-
r(t,"Built-in model resolution result",{agent:a,result:s}),s.resolved&&(
|
|
1239
|
+
const s=(0,R.resolveAgentModel)(p,n,o)
|
|
1240
|
+
r(t,"Built-in model resolution result",{agent:a,result:s}),s.resolved&&(j=s.fullModel,r(t,"Resolved built-in agent model",{agent:a,model:j,preferredProvider:n,preferredTier:o}))}else r(t,"No built-in config found - using default model",{agent:a})}}catch(e){r(t,"Error resolving agent model",{agent:a,error:(0,q.getErrorMessage)(e)})}try{const e=await async function(){try{const e=`http://localhost:${M}/api/project-settings`,t=await fetch(e)
|
|
1246
1241
|
if(t.ok){const e=await t.json()
|
|
1247
1242
|
return e?.data?.defaultModel||null}}catch{}return null}()
|
|
1248
|
-
if(e)if(
|
|
1249
|
-
"same"===(o?.preferredModelTier||"same")&&(
|
|
1250
|
-
|
|
1251
|
-
|
|
1252
|
-
_
|
|
1253
|
-
|
|
1254
|
-
|
|
1255
|
-
return u?M+=`Prompt sent to existing session ${_}.`:(M+=`Background ${a} subagent spawned successfully.`,_&&"unknown"!==_&&"spawning"!==_&&(M+=`\n[SESSION:${_}]`)),l&&(M+="\nWorking on: "+l),M+="\n\nThe subagent is now working independently. You can continue with other tasks.",{content:[{type:"text",text:M}]}}async function s(e,t,r,n,o,s,i){const a=await(0,I.getServerUrl)(r,n)
|
|
1243
|
+
if(e)if(j){const o=await n(a)
|
|
1244
|
+
"same"===(o?.preferredModelTier||"same")&&(j=e,r(t,"Applied user default model (same tier)",{agent:a,userDefaultModel:e}))}else j=e,r(t,"Using user default model (no agent resolution)",{agent:a,userDefaultModel:e})}catch(e){r(t,"Failed to fetch user default model",{error:(0,q.getErrorMessage)(e)})}if(r(t,"Final resolved model before spawn",{agent:a,resolvedModel:j||"undefined (will use default)"}),await T,l&&y)try{await(0,k.ensureRequestWorktree)(p,l,o)}catch(e){r(t,"Pre-spawn worktree creation failed (non-fatal)",{requestId:l,error:(0,q.getErrorMessage)(e)})}const x=(0,b.spawnDetachedSubagent)({agent:a,prompt:E,cwd:p,sessionId:I,model:j,initialBranch:y,allowParallel:d,serverUrl:g})
|
|
1245
|
+
if(!x.success)throw Error("Failed to spawn subagent: "+x.error)
|
|
1246
|
+
_=I,r(t,"CLI spawn successful with pre-created session",{sessionId:I,pid:x.pid,parentSessionId:i}),o.info("Background subagent spawned via CLI with pre-created session",{agent:a,requestId:l,sessionId:I,pid:x.pid,parentSessionId:i})}if(s&&l&&_&&"unknown"!==_&&"spawning"!==_)try{const e=s.getSessionRequestAssociationClient()
|
|
1247
|
+
if(e&&(e.createAssociation(_,l).then((()=>o.info("Created session-request association",{sessionId:_,requestId:l}))).catch((e=>o.warn("Failed to create session-request association",{error:(0,q.getErrorMessage)(e),sessionId:_,requestId:l}))),"coder"===a)){const e=s.getRequestClient()
|
|
1248
|
+
e&&e.updateRequest(l,{cliOrigin:{providerId:"opencode",sessionId:_,createdAt:(new Date).toISOString()}}).catch((e=>o.debug("Failed to update request cliOrigin",{error:(0,q.getErrorMessage)(e)})))}}catch(e){o.warn("Failed to create session-request association",{error:(0,q.getErrorMessage)(e),sessionId:_,requestId:l})}let T=m
|
|
1249
|
+
return u?T+=`Prompt sent to existing session ${_}.`:(T+=`Background ${a} subagent spawned successfully.`,_&&"unknown"!==_&&"spawning"!==_&&(T+=`\n[SESSION:${_}]`)),l&&(T+="\nWorking on: "+l),T+="\n\nThe subagent is now working independently. You can continue with other tasks.",{content:[{type:"text",text:T}]}}async function s(e,t,r,n,o,s,i){const a=await(0,I.getServerUrl)(r,n)
|
|
1256
1250
|
if(!a)throw new w.ValidationError("Could not determine OpenCode server URL")
|
|
1257
|
-
if(n.info("Sending message to subagent session",{sessionId:e,promptLength:t.length}),o)try{const t=i?.sessionId
|
|
1251
|
+
if(n.info("Sending message to subagent session",{sessionId:e,promptLength:t.length}),o)try{const t=i?.sessionId
|
|
1258
1252
|
if(t){const r=o.getCLISessionClient()
|
|
1259
1253
|
if(r){let o=await r.getByExternalId(t)
|
|
1260
|
-
o||(o=await r.createOrUpdateSession({externalSessionId:t,providerId:"opencode",status:"active"}),n.info("Created caller session in DB for re-parenting",{callerSessionId:t,dbId:o?.id})),o&&(await r.createOrUpdateSession({externalSessionId:e,providerId:"opencode",parentSessionId:o.id,status:"active"}),n.info("Updated parent session for reused agent",{sessionId:e,newParentSessionId:t}))}}}catch(e){n.warn("Failed to update parent session - reports may go to wrong parent",{error:(0,
|
|
1261
|
-
if(!c)try{const t=`http://localhost:${
|
|
1254
|
+
o||(o=await r.createOrUpdateSession({externalSessionId:t,providerId:"opencode",status:"active"}),n.info("Created caller session in DB for re-parenting",{callerSessionId:t,dbId:o?.id})),o&&(await r.createOrUpdateSession({externalSessionId:e,providerId:"opencode",parentSessionId:o.id,status:"active"}),n.info("Updated parent session for reused agent",{sessionId:e,newParentSessionId:t}))}}}catch(e){n.warn("Failed to update parent session - reports may go to wrong parent",{error:(0,q.getErrorMessage)(e)})}let c=s
|
|
1255
|
+
if(!c)try{const t=`http://localhost:${M}/api/sessions/${encodeURIComponent(e)}/agent-type`,r=await fetch(t)
|
|
1262
1256
|
if(r.ok){const e=await r.json()
|
|
1263
1257
|
e.success&&e.agentType&&(c=e.agentType)}}catch{n.warn("Agent type lookup failed for session",{sessionId:e})}if(!c)throw new w.ValidationError(`Cannot continue session ${e}: unable to determine agent type. The session's agent type could not be looked up from the action server.`)
|
|
1264
1258
|
try{let r
|
|
1265
|
-
try{const e=await fetch(`http://localhost:${
|
|
1259
|
+
try{const e=await fetch(`http://localhost:${M}/api/project-settings`)
|
|
1266
1260
|
if(e.ok){const t=await e.json()
|
|
1267
1261
|
if(t.data?.defaultModel){const[e,...n]=t.data.defaultModel.split("/")
|
|
1268
1262
|
r={providerID:e,modelID:n.join("/")}}}}catch{}const o=`${a.replace(/\/$/,"")}/session/${e}/prompt_async`,s=await fetch(o,{method:"POST",headers:{"Content-Type":"application/json"},body:JSON.stringify({parts:[{type:"text",text:t}],...c?{agent:c}:{},...r?{model:r}:{}}),signal:AbortSignal.timeout(1e4)})
|
|
1269
1263
|
if(!s.ok){const e=await s.text().catch((()=>"Unknown error"))
|
|
1270
|
-
throw Error(`Failed to send message: ${s.status} ${e}`)}return n.info("Message sent to subagent session",{sessionId:e,agent:c}),{content:[{type:"text",text:`Message sent to session ${e}.\nThe subagent will process it in the background.`}]}}catch(e){throw Error("Failed to continue session: "+(0,
|
|
1264
|
+
throw Error(`Failed to send message: ${s.status} ${e}`)}return n.info("Message sent to subagent session",{sessionId:e,agent:c}),{content:[{type:"text",text:`Message sent to session ${e}.\nThe subagent will process it in the background.`}]}}catch(e){throw Error("Failed to continue session: "+(0,q.getErrorMessage)(e))}}function i(e){const t=Math.floor(e/1e3)
|
|
1271
1265
|
if(60>t)return t+"s"
|
|
1272
1266
|
const r=Math.floor(t/60)
|
|
1273
1267
|
return 60>r?`${r}m ${t%60}s`:`${Math.floor(r/60)}h ${r%60}m`}function a(e){const t=[]
|
|
@@ -1277,7 +1271,7 @@ const s=n.path||n.file||n.directory,i=n.needle||n.query||n.pattern
|
|
|
1277
1271
|
"string"==typeof s?o+=" "+(s.split("/").pop()||s):"string"==typeof i&&(o+=` "${i.length>30?i.slice(0,27)+"...":i}"`),t.push({name:o,state:e.state.status,time:r.info.time.created})}t.sort(((e,t)=>t.time-e.time))
|
|
1278
1272
|
const r=t.find((e=>"pending"===e.state||"running"===e.state)),n=t.filter((e=>"completed"===e.state||"error"===e.state)).slice(0,3),o=t.length>0?t[0].time:null
|
|
1279
1273
|
return{current:r?.name??null,recent:n.map((e=>e.name)),lastActivityTime:o}}function c(e){return 1e3>e?"<1s ago":6e4>e?Math.floor(e/1e3)+"s ago":36e5>e?Math.floor(e/6e4)+"m ago":Math.floor(e/36e5)+"h ago"}function l(e,t){const r=e||t,n=Date.now()-r
|
|
1280
|
-
return e&&
|
|
1274
|
+
return e&&j>n?{status:"working",detail:"last action "+c(n),isReady:!1}:n>x&&e?{status:"stalled",detail:"no activity for "+c(n),isReady:!0}:e?{status:"idle",detail:"no activity for "+c(n),isReady:!0}:{status:"idle",detail:"no tool activity",isReady:!0}}function d(e){let t=0,r=0,n=0
|
|
1281
1275
|
for(const o of e.trim().split("\n")){if(!o)continue
|
|
1282
1276
|
const[e,s]=o.split("\t")
|
|
1283
1277
|
"-"!==e&&(t+=parseInt(e,10)||0),"-"!==s&&(r+=parseInt(s,10)||0),n++}return{additions:t,deletions:r,files:n}}async function u(e,r,n,o){const s=await(0,I.getServerUrl)(r,n)
|
|
@@ -1290,7 +1284,7 @@ let f={input:0,output:0,reasoning:0},m="",y=l(null,h.time.updated)
|
|
|
1290
1284
|
if(p.ok){const e=await p.json()
|
|
1291
1285
|
for(const t of e)"assistant"===t.info.role&&t.info.tokens&&(f.input+=t.info.tokens.input||0,f.output+=t.info.tokens.output||0,f.reasoning+=t.info.tokens.reasoning||0)
|
|
1292
1286
|
const t=a(e)
|
|
1293
|
-
y=l(t.lastActivityTime,h.time.updated),t.current&&(m+="\nCurrent: "+t.current),t.recent.length>0&&(m+="\nRecent: "+t.recent.join(", "))}const w=Date.now()-h.time.created,b=y.status,
|
|
1287
|
+
y=l(t.lastActivityTime,h.time.updated),t.current&&(m+="\nCurrent: "+t.current),t.recent.length>0&&(m+="\nRecent: "+t.recent.join(", "))}const w=Date.now()-h.time.created,b=y.status,k=y.isReady,I=f.input+f.output+f.reasoning
|
|
1294
1288
|
let v="",C="",_=null
|
|
1295
1289
|
if(o)try{const t=o.getSessionRequestAssociationClient()
|
|
1296
1290
|
if(t){const r=await t.getActiveRequestsForSession(e,!1)
|
|
@@ -1305,12 +1299,12 @@ if(e.trim())return d(e)}try{const t=n(`git log main --merges --oneline -n 50 --g
|
|
|
1305
1299
|
if(t){const e=t.split("\n")[0].split(" ")[0],o=n(`git diff ${e}^1...${e} --numstat`,{cwd:r,encoding:"utf8"})
|
|
1306
1300
|
if(o.trim())return{...d(o),merged:!0}}}catch{}return null}catch{return null}}(_,r.basePath)
|
|
1307
1301
|
if(e){const t=e.additions+e.deletions,r=e.merged?" (merged)":""
|
|
1308
|
-
v=`\nDiff vs main (${_}): +${e.additions}/-${e.deletions} lines (${t} total) in ${e.files} file${1!==e.files?"s":""}${r}`}}return{content:[{type:"text",text:`Session ${e}\nTitle: ${h.title||"Untitled"}\nStatus: ${b} (${y.detail})\nReady for input: ${
|
|
1302
|
+
v=`\nDiff vs main (${_}): +${e.additions}/-${e.deletions} lines (${t} total) in ${e.files} file${1!==e.files?"s":""}${r}`}}return{content:[{type:"text",text:`Session ${e}\nTitle: ${h.title||"Untitled"}\nStatus: ${b} (${y.detail})\nReady for input: ${k?"Yes":"No"}\nAge: ${i(w)}\nTokens: ${I.toLocaleString()} (in: ${f.input.toLocaleString()}, out: ${f.output.toLocaleString()}${f.reasoning>0?", reasoning: "+f.reasoning.toLocaleString():""})${m}${C}${v}`}]}}catch(e){throw Error("Failed to check session status: "+(0,q.getErrorMessage)(e))}}async function h(e,t,r){const n=await(0,I.getServerUrl)(t,r)
|
|
1309
1303
|
if(!n)throw new w.ValidationError("Could not determine OpenCode server URL")
|
|
1310
1304
|
r.info("Aborting subagent session",{sessionId:e})
|
|
1311
1305
|
try{const t=`${n.replace(/\/$/,"")}/session/${e}/abort`,o=await fetch(t,{method:"POST"})
|
|
1312
1306
|
if(!o.ok){const e=await o.text().catch((()=>"Unknown error"))
|
|
1313
|
-
throw Error(`Failed to abort session: ${o.status} ${e}`)}return r.info("Session aborted",{sessionId:e}),{content:[{type:"text",text:`Session ${e} has been aborted.`}]}}catch(e){throw Error("Failed to abort session: "+(0,
|
|
1307
|
+
throw Error(`Failed to abort session: ${o.status} ${e}`)}return r.info("Session aborted",{sessionId:e}),{content:[{type:"text",text:`Session ${e} has been aborted.`}]}}catch(e){throw Error("Failed to abort session: "+(0,q.getErrorMessage)(e))}}async function g(e,t,r,n={}){const{activeOnly:o=!1,requestId:s,limit:c,minTokens:d,maxTokens:u,maxAgeHours:h}=n,g=await(0,I.getServerUrl)(e,t)
|
|
1314
1308
|
if(!g)throw new w.ValidationError("Could not determine OpenCode server URL")
|
|
1315
1309
|
t.info("Listing sessions",{filters:n})
|
|
1316
1310
|
try{const e=g.replace(/\/$/,"")+"/session",t=await fetch(e)
|
|
@@ -1324,10 +1318,10 @@ if(o&&(w=w.filter((e=>"idle"!==(y[e.id]?.type||"idle")))),void 0!==h){const e=36
|
|
|
1324
1318
|
w=w.filter((e=>e.time.created>=t))}if(0===w.length)return{content:[{type:"text",text:"No sessions match the specified filters."}]}
|
|
1325
1319
|
let b={}
|
|
1326
1320
|
if(r)try{const e=r.getCLISessionClient()
|
|
1327
|
-
e&&(b=await e.batchEnrich(w.map((e=>e.id))))}catch{}const
|
|
1321
|
+
e&&(b=await e.batchEnrich(w.map((e=>e.id))))}catch{}const k=g.replace(/\/$/,""),I=await Promise.allSettled(w.map((e=>fetch(`${k}/session/${e.id}/message`).then((e=>e.ok?e.json():[])).catch((()=>[]))))),v=[]
|
|
1328
1322
|
for(let e=0;e<w.length;e++){const t=w[e],r=Date.now()-t.time.created
|
|
1329
1323
|
let o=0,i=null,c=[],h=l(null,t.time.updated)
|
|
1330
|
-
const g=
|
|
1324
|
+
const g=I[e],p="fulfilled"===g.status?g.value:[]
|
|
1331
1325
|
for(const e of p)"assistant"===e.info.role&&e.info.tokens&&(o+=(e.info.tokens.input||0)+(e.info.tokens.output||0)+(e.info.tokens.reasoning||0))
|
|
1332
1326
|
if(p.length>0){const e=a(p)
|
|
1333
1327
|
h=l(e.lastActivityTime,t.time.updated),i=e.current||null,c=e.recent}const f=h.status
|
|
@@ -1337,16 +1331,16 @@ const m=b[t.id]
|
|
|
1337
1331
|
if(n.agentType&&(!m||m.agentType!==n.agentType))continue
|
|
1338
1332
|
if("archived"===m?.status)continue
|
|
1339
1333
|
let y=""
|
|
1340
|
-
const
|
|
1334
|
+
const k=[]
|
|
1341
1335
|
if(m?.associations&&m.associations.length>0){const e=m.associations.filter((e=>!e.endedAt)).map((e=>e.requestLocalId)),t=m.associations.filter((e=>e.endedAt)).map((e=>e.requestLocalId))
|
|
1342
|
-
|
|
1336
|
+
k.push(...e,...t)
|
|
1343
1337
|
const r=[]
|
|
1344
|
-
e.length>0&&r.push("active: "+e.join(", ")),t.length>0&&r.push("prev: "+t.join(", ")),r.length>0&&(y=` [${r.join(" | ")}]`)}if(s&&!
|
|
1338
|
+
e.length>0&&r.push("active: "+e.join(", ")),t.length>0&&r.push("prev: "+t.join(", ")),r.length>0&&(y=` [${r.join(" | ")}]`)}if(s&&!k.includes(s))continue
|
|
1345
1339
|
const C=t.title||"Untitled",_=C.length>50?C.slice(0,47)+"...":C
|
|
1346
|
-
v.push({id:t.id,title:_,status:f,age:r,totalTokens:o,requestsInfo:y,allRequestIds:
|
|
1340
|
+
v.push({id:t.id,title:_,status:f,age:r,totalTokens:o,requestsInfo:y,allRequestIds:k,statusDetail:h.detail,specialization:m?.specialization??null,currentAction:i,recentActions:c})}if(0===v.length)return{content:[{type:"text",text:"No sessions match the specified filters."}]}
|
|
1347
1341
|
const C=c?v.slice(0,c):v,_=C.map((e=>{const t=e.specialization?"\n Specialization: "+e.specialization:"",r=e.currentAction?"\n Current: "+e.currentAction:"",n=e.recentActions.length>0?"\n Recent: "+e.recentActions.join(", "):""
|
|
1348
1342
|
return`\u2022 ${e.id}\n ${e.title}${t}\n Status: ${e.status} (${e.statusDetail}) | Age: ${i(e.age)} | ${e.totalTokens.toLocaleString()} tokens${e.requestsInfo}${r}${n}`})),E=c&&v.length>c?` (showing ${c} of ${v.length})`:""
|
|
1349
|
-
return{content:[{type:"text",text:`Found ${C.length} session${1!==C.length?"s":""}${E}:\n\n${_.join("\n\n")}`}]}}catch(e){throw Error("Failed to list sessions: "+(0,
|
|
1343
|
+
return{content:[{type:"text",text:`Found ${C.length} session${1!==C.length?"s":""}${E}:\n\n${_.join("\n\n")}`}]}}catch(e){throw Error("Failed to list sessions: "+(0,q.getErrorMessage)(e))}}var p,f=this&&this.__createBinding||(Object.create?function(e,t,r,n){void 0===n&&(n=r)
|
|
1350
1344
|
var o=Object.getOwnPropertyDescriptor(t,r)
|
|
1351
1345
|
o&&!("get"in o?!t.__esModule:o.writable||o.configurable)||(o={enumerable:!0,get(){return t[r]}}),Object.defineProperty(e,n,o)}:function(e,t,r,n){void 0===n&&(n=r),e[n]=t[r]}),m=this&&this.__setModuleDefault||(Object.create?function(e,t){Object.defineProperty(e,"default",{enumerable:!0,value:t})}:function(e,t){e.default=t}),y=this&&this.__importStar||(p=function(e){return p=Object.getOwnPropertyNames||function(e){var t=[]
|
|
1352
1346
|
for(var r in e)({}).hasOwnProperty.call(e,r)&&(t[t.length]=r)
|
|
@@ -1356,7 +1350,7 @@ if(null!=e)for(var r=p(e),n=0;n<r.length;n++)"default"!==r[n]&&f(t,e,r[n])
|
|
|
1356
1350
|
return m(t,e),t})
|
|
1357
1351
|
Object.defineProperty(exports,"__esModule",{value:!0}),exports.handleSpawn=o,exports.handleContinue=s,exports.handleCheckStatus=u,exports.handleAbort=h,exports.handleListSessions=g,exports.handleSubagentOperations=async function(e,t,r,n,i,a){const c=r.child({tool:"subagent_operations"}),l=n.startTimer("tool_execution_time")
|
|
1358
1352
|
try{if(e&&!e.operation&&(e.spawn?e.operation="spawn":e.continue?e.operation="continue":e.readMessages?e.operation="read-messages":e.listSessions?e.operation="list-sessions":e.prompt&&(e.agent||e.description)?e={operation:"spawn",spawn:{agent:e.agent||"coder",prompt:e.prompt,description:e.description||e.prompt.slice(0,60),requestId:e.requestId,allowParallel:e.allowParallel,useExistingSession:e.useExistingSession}}:e.sessionId&&e.prompt&&!e.spawn?e={operation:"continue",sessionId:e.sessionId,continue:{prompt:e.prompt}}:e.sessionId&&(e={operation:"check-status",sessionId:e.sessionId})),e?.spawn&&"string"==typeof e.spawn)try{e.spawn=JSON.parse(e.spawn)}catch{}if(e?.continue&&"string"==typeof e.continue)try{e.continue=JSON.parse(e.continue)}catch{}"spawn"===e?.operation&&e?.prompt&&!e?.spawn&&(e.spawn={agent:e.agent||"coder",prompt:e.prompt,description:e.description||e.prompt.slice(0,60),requestId:e.requestId},delete e.prompt,delete e.agent,delete e.description,delete e.requestId),"continue"===e?.operation&&e?.prompt&&!e?.continue&&(e.continue={prompt:e.prompt},delete e.prompt)
|
|
1359
|
-
const r=
|
|
1353
|
+
const r=E.validateArgs(e,_.SubagentOperationsSchema),{sessionId:d,operation:p}=r
|
|
1360
1354
|
let f
|
|
1361
1355
|
switch(c.info("Processing subagent_operations",{operation:p,sessionId:d}),p){case"spawn":f=await o(r.spawn,t,c,i,a)
|
|
1362
1356
|
break
|
|
@@ -1376,13 +1370,13 @@ throw Error("Failed to fetch messages: "+n.status)}const s=await n.json()
|
|
|
1376
1370
|
if(0===s.length)return{content:[{type:"text",text:`Session ${e} has no messages yet.`}]}
|
|
1377
1371
|
const i=s.map(((e,t)=>{const r="user"===e.info.role?"USER":"ASSISTANT",n=e.parts.filter((e=>"text"===e.type&&e.text)).map((e=>e.text)).join("\n"),o=n.length>5e3?n.slice(0,5e3)+"...[truncated]":n
|
|
1378
1372
|
return`[${t+1}] ${r} (${new Date(e.info.time.created).toLocaleTimeString()}):\n${o}`})).join("\n\n---\n\n")
|
|
1379
|
-
return{content:[{type:"text",text:`Session ${e} - Last ${s.length} messages:\n\n${i}`}]}}catch(e){throw Error("Failed to read messages: "+(0,
|
|
1373
|
+
return{content:[{type:"text",text:`Session ${e} - Last ${s.length} messages:\n\n${i}`}]}}catch(e){throw Error("Failed to read messages: "+(0,q.getErrorMessage)(e))}}(d,e,t,c)
|
|
1380
1374
|
break
|
|
1381
|
-
case"list-sessions":const n={activeOnly:r.listSessions?.activeOnly,requestId:r.listSessions?.requestId,limit:r.listSessions?.limit,minTokens:r.listSessions?.minTokens,maxTokens:r.listSessions?.maxTokens,maxAgeHours:r.listSessions?.maxAgeHours,parentSessionId:a?.sessionId
|
|
1375
|
+
case"list-sessions":const n={activeOnly:r.listSessions?.activeOnly,requestId:r.listSessions?.requestId,limit:r.listSessions?.limit,minTokens:r.listSessions?.minTokens,maxTokens:r.listSessions?.maxTokens,maxAgeHours:r.listSessions?.maxAgeHours,parentSessionId:a?.sessionId}
|
|
1382
1376
|
f=await g(t,c,i,n)
|
|
1383
1377
|
break
|
|
1384
|
-
default:throw new w.ValidationError("Unknown operation: "+p)}return l({success:!0}),n.incrementCounter(`subagent_operations_${p}_success`,1),f}catch(e){return c.error("Subagent operations failed",{error:e instanceof Error?e.stack:e+""}),l({success:!1}),n.incrementCounter("subagent_operations_errors",1),{content:[{type:"text",text:"Subagent operation failed: "+(0,
|
|
1385
|
-
const w=t(9860),b=t(8035),I=t(7617),
|
|
1378
|
+
default:throw new w.ValidationError("Unknown operation: "+p)}return l({success:!0}),n.incrementCounter(`subagent_operations_${p}_success`,1),f}catch(e){return c.error("Subagent operations failed",{error:e instanceof Error?e.stack:e+""}),l({success:!1}),n.incrementCounter("subagent_operations_errors",1),{content:[{type:"text",text:"Subagent operation failed: "+(0,q.getErrorMessage)(e)}],isError:!0}}}
|
|
1379
|
+
const w=t(9860),b=t(8035),k=t(2424),I=t(7617),v=t(6688),C=t(7280),_=t(6183),E=y(t(5967)),q=t(8824),S=t(9896),T=t(6928),P=t(8955),R=t(5671),M=3456,j=6e4,x=3e5},1791(e,exports,t){function r(e,t){return t.info("Creating project context middleware",{projectId:e}),(t,r,n)=>{"GET"===t.method&&(t.query.projectId=e),["POST","PATCH","PUT"].includes(t.method)&&t.body&&(t.body.projectId=e),n()}}var n=this&&this.__importDefault||function(e){return e&&e.__esModule?e:{default:e}}
|
|
1386
1380
|
Object.defineProperty(exports,"__esModule",{value:!0}),exports.ProjectContext=void 0,exports.projectContextMiddleware=r
|
|
1387
1381
|
const o=n(t(9896)),s=n(t(6928)),i=t(4139),a=t(4055),c=t(8824)
|
|
1388
1382
|
exports.ProjectContext=class{constructor(e,t){this.projectId=null,this.initialized=!1,this.initializationInProgress=!1,this.initializationPromise=null,this.basePath=e,this.alchemyPath=s.default.join(e,i.ALCHEMY_DIR_NAME),this.projectFilePath=s.default.join(this.alchemyPath,"project.json"),this.logger=t.child({component:"project-context"}),this.logger.debug("Project context constructed",{basePath:this.basePath,alchemyPath:this.alchemyPath,projectFilePath:this.projectFilePath})}initialize(){return this.initialized&&this.projectId?(this.logger.info("Project context already initialized",{projectId:this.projectId}),Promise.resolve(this.projectId)):this.initializationInProgress&&this.initializationPromise?(this.logger.info("Project context initialization already in progress, reusing promise"),this.initializationPromise):(this.initializationInProgress=!0,this.logger.debug("Starting initialization",{basePath:this.basePath}),this.initializationPromise=this.doInitialize(),this.initializationPromise)}async doInitialize(){try{if(o.default.existsSync(this.alchemyPath))this.logger.debug("alchemy_lab directory already exists")
|
|
@@ -1673,26 +1667,26 @@ var t={}
|
|
|
1673
1667
|
if(null!=e)for(var s=r(e),i=0;i<s.length;i++)"default"!==s[i]&&n(t,e,s[i])
|
|
1674
1668
|
return o(t,e),t}),i=this&&this.__importDefault||function(e){return e&&e.__esModule?e:{default:e}}
|
|
1675
1669
|
Object.defineProperty(exports,"__esModule",{value:!0}),exports.handleMoveFiles=async function(e,t,r,n,o,s,i,f){const m=s.child({tool:"move_files"}),y=Date.now()
|
|
1676
|
-
let w,b,
|
|
1677
|
-
const
|
|
1670
|
+
let w,b,k=d.FileOperationPhase.VALIDATION
|
|
1671
|
+
const I={toolName:"move-files",operationName:"write",fileOperationPhase:d.FileOperationPhase.FILE_WRITE,recordType:"move-files",metricsPrefix:"move_files",successMessage:"Successfully moved files",failureMessage:"Failed to move files"}
|
|
1678
1672
|
try{const s=d.validateArgs(e,l.MoveFilesSchema),{taskId:u,operations:h,comment:v}=s
|
|
1679
1673
|
if(m.info("Moving multiple files and directories",{taskId:u,operationCount:h.length,comment:v}),!h||0===h.length)throw Error("At least one move operation must be specified")
|
|
1680
|
-
d.validateTaskIdFormat(u,m,i,
|
|
1674
|
+
d.validateTaskIdFormat(u,m,i,I.metricsPrefix)
|
|
1681
1675
|
const C=t.getCurrentBranchContext?await t.getCurrentBranchContext():{branch:null,requestId:null,isMain:!0}
|
|
1682
1676
|
m.info("Initial branch context",{initialBranch:C.branch,initialRequestId:C.requestId,isMain:C.isMain})
|
|
1683
1677
|
const _=[]
|
|
1684
1678
|
for(const e of h){const{normalizedPath:r,fullPath:n}=d.validateAndNormalizePath(e.source,t),{normalizedPath:o,fullPath:s}=d.validateAndNormalizePath(e.destination,t)
|
|
1685
|
-
_.push({source:r,destination:o,fullSource:n,fullDestination:s})}
|
|
1686
|
-
const E=await d.validateTaskId(u,_[0].source,r,m,i,
|
|
1679
|
+
_.push({source:r,destination:o,fullSource:n,fullDestination:s})}k=d.FileOperationPhase.TASK_VALIDATION,i.incrementCounter("move_files_phase",1,{phase:k})
|
|
1680
|
+
const E=await d.validateTaskId(u,_[0].source,r,m,i,I.metricsPrefix),q=E?.requestId,S=await d.validateWorkItemStates(u,_[0].source,r,o,t,m,i,I.metricsPrefix),T=await d.autoPromoteTaskStatus(u,E.status,q,S.request?.status,_[0].source,r,o,m,i,I.metricsPrefix)
|
|
1687
1681
|
T.taskPromoted&&m.info(`Auto-promoted task ${u} (${E.title||"Untitled"}) to in_progress for file operations`,{taskId:u,taskTitle:E.title,previousStatus:E.status,newStatus:T.newTaskStatus,operationCount:h.length}),T.requestPromoted&&m.info(`Auto-promoted request ${q} to in_progress for file operations`,{requestId:q,previousStatus:S.request?.status,newStatus:T.newRequestStatus,triggeringTaskId:u})
|
|
1688
|
-
const P=await d.ensureCorrectWorkspaceContext({taskPromoted:T.taskPromoted,requestId:q,context:t,operation:"move-files",logger:m,metrics:i,metricsPrefix:
|
|
1682
|
+
const P=await d.ensureCorrectWorkspaceContext({taskPromoted:T.taskPromoted,requestId:q,context:t,operation:"move-files",logger:m,metrics:i,metricsPrefix:I.metricsPrefix})
|
|
1689
1683
|
if(!P.success){if(P.isLockConflict)return{content:[{type:"text",text:"\u274c "+P.error}],isError:!0}
|
|
1690
1684
|
throw Error(P.error)}let R={hadUserMods:!1,userModsCommitHash:void 0}
|
|
1691
1685
|
if(t.git)try{m.debug("[MOVE-FILES] Checking for user changes before move operations")
|
|
1692
1686
|
const e=await(0,g.commitUserChangesBeforeToolOperation)(t.git,"move-files",{requestId:q,taskId:u,workspaceManager:t.workspaceManager},m,i)
|
|
1693
|
-
e.userChangesCommitted&&(m.debug("[MOVE-FILES] User changes committed before move operations",{commitHash:e.commitHash?.substring(0,8),filesCommitted:e.filesCommitted}),m.info("User changes committed before move-files operation",{taskId:u,moveOperationsCount:_.length,userCommitHash:e.commitHash?.substring(0,8),userFilesCommitted:e.filesCommitted}),R={hadUserMods:!0,userModsCommitHash:e.commitHash})}catch(e){m.debug("[MOVE-FILES] Pre-tool commit failed, continuing with move operations",{error:e instanceof Error?e.message:e+""}),m.warn("Pre-tool user changes commit failed, continuing with move operation",{taskId:u,moveOperationsCount:_.length,error:e instanceof Error?e.message:e+""})}m.debug("[MOVE-FILES] Proceeding with move operations",{operationCount:_.length}),
|
|
1694
|
-
const{toolRecordId:M,localToolRecordId:j}=await d.createFileOperationRecords(u,q,t.projectId,
|
|
1695
|
-
w=M,b=M,I
|
|
1687
|
+
e.userChangesCommitted&&(m.debug("[MOVE-FILES] User changes committed before move operations",{commitHash:e.commitHash?.substring(0,8),filesCommitted:e.filesCommitted}),m.info("User changes committed before move-files operation",{taskId:u,moveOperationsCount:_.length,userCommitHash:e.commitHash?.substring(0,8),userFilesCommitted:e.filesCommitted}),R={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}),k=d.FileOperationPhase.RECORD_CREATION,i.incrementCounter("move_files_phase",1,{phase:k})
|
|
1688
|
+
const{toolRecordId:M,localToolRecordId:j}=await d.createFileOperationRecords(u,q,t.projectId,I.recordType,_[0].source,{operationCount:h.length,operations:_.map((e=>({source:e.source,destination:e.destination}))),userComment:v,hadUserMods:R.hadUserMods,userModsCommitHash:R.userModsCommitHash},r,n,m,i,I.metricsPrefix,f)
|
|
1689
|
+
w=M,b=M,k=I.fileOperationPhase,i.incrementCounter("move_files_phase",1,{phase:k})
|
|
1696
1690
|
const x=[]
|
|
1697
1691
|
let O=0
|
|
1698
1692
|
for(const e of _){const t={operation:{source:e.source,destination:e.destination},success:!1}
|
|
@@ -1702,24 +1696,32 @@ const n=c.default.dirname(e.fullDestination)
|
|
|
1702
1696
|
try{await a.default.mkdir(n,{recursive:!0})}catch(e){throw Error("Failed to create destination directory: "+n)}try{throw await a.default.access(e.fullDestination),Error("Destination already exists: "+e.destination)}catch(e){if(!(e instanceof Error&&e.message.includes("ENOENT")))throw e}await a.default.rename(e.fullSource,e.fullDestination),t.success=!0,O++,m.info("Successfully moved "+(r?"directory":"file"),{source:e.source,destination:e.destination,isDirectory:r})}catch(r){t.error=(0,p.getErrorMessage)(r),m.warn(`Failed to move ${e.source} to ${e.destination}`,{error:t.error})}x.push(t)}const D=Date.now()-y
|
|
1703
1697
|
i.recordValue("move_files_time",D),i.incrementCounter("move_files_operations_total",h.length),i.incrementCounter("move_files_operations_success",O),i.incrementCounter("move_files_operations_failed",h.length-O),O===h.length?i.incrementCounter("move_files_success",1):O>0?i.incrementCounter("move_files_partial_success",1):i.incrementCounter("move_files_total_failure",1)
|
|
1704
1698
|
let A=null
|
|
1705
|
-
if(O>0){
|
|
1699
|
+
if(O>0){k=d.FileOperationPhase.GIT_COMMIT,i.incrementCounter("move_files_phase",1,{phase:k})
|
|
1706
1700
|
const e=x.filter((e=>e.success)),r=1===e.length?`Move ${e[0].isDirectory?"directory":"file"} from ${e[0].operation.source} to ${e[0].operation.destination} - ${v}`:`Move ${e.length} ${1===e.length?"item":"items"} - ${v}`
|
|
1707
|
-
A=await d.commitToGit(u,_[0].destination,M,j,r,t,m,i,
|
|
1701
|
+
A=await d.commitToGit(u,_[0].destination,M,j,r,t,m,i,I.metricsPrefix)}k=d.FileOperationPhase.RECORD_UPDATE_SUCCESS,i.incrementCounter("move_files_phase",1,{phase:k})
|
|
1708
1702
|
const $=x.filter((e=>e.success)),F=x.filter((e=>!e.success))
|
|
1709
|
-
await d.updateFileOperationRecords(u,w,b,_[0].source,
|
|
1703
|
+
await d.updateFileOperationRecords(u,w,b,_[0].source,I.recordType,O===h.length?`Successfully moved all ${h.length} items`:`Moved ${O}/${h.length} items successfully`,{status:O===h.length?"completed":"partial_success",commitHash:A?.commitHash,previousCommitHash:A?.previousCommitHash,operationCount:h.length,successCount:O,failureCount:h.length-O,successfulOperations:$.map((e=>({source:e.operation.source,destination:e.operation.destination,isDirectory:e.isDirectory}))),failedOperations:F.map((e=>({source:e.operation.source,destination:e.operation.destination,error:e.error}))),userComment:v,hadUserMods:R.hadUserMods,userModsCommitHash:R.userModsCommitHash},O===h.length?`Successfully moved all ${h.length} items`:`Moved ${O}/${h.length} items successfully`,r,n,m,i,I.metricsPrefix)
|
|
1710
1704
|
const N=t.getCurrentBranchContext?await t.getCurrentBranchContext():{branch:null,requestId:null,isMain:!0}
|
|
1711
1705
|
let L=""
|
|
1712
1706
|
if(O===h.length)L=`Successfully moved all ${h.length} ${1===h.length?"item":"items"}`
|
|
1713
1707
|
else if(O>0){const e=x.filter((e=>!e.success))
|
|
1714
1708
|
L=`Successfully moved ${O}/${h.length} items.\n\nFailed operations:\n`+e.map((e=>`\u2022 ${e.operation.source} \u2192 ${e.operation.destination}: ${e.error}`)).join("\n")}else L="All move operations failed:\n"+x.map((e=>`\u2022 ${e.operation.source} \u2192 ${e.operation.destination}: ${e.error}`)).join("\n")
|
|
1715
1709
|
return A?.commitHash&&(L+="\nCommit: "+A.commitHash.substring(0,8)),N.requestId&&(L+="\nBranch: "+N.requestId),P.lockAcquired&&P.lockedRequestId&&(L+="\n\u{1f512} **Locked request:** "+P.lockedRequestId),{content:[{type:"text",text:L}],isError:0===O}}catch(o){if(e.taskId&&n)try{const r=o instanceof u.NotFoundError||o instanceof u.ValidationError||o instanceof h.ZodError
|
|
1716
|
-
await n.createToolRecord({...r?{}:{taskId:e.taskId},projectId:t.projectId,type:"move-files",metadata:{status:"failed",timestamp:(new Date).toISOString(),operationCount:e.operations?.length||0,operations:e.operations||[],userComment:e.comment,error:(0,p.getErrorMessage)(o),errorDetails:o instanceof Error?o.stack:o+"",phase:
|
|
1717
|
-
if(i.recordValue("move_files_time",s),i.incrementCounter("move_files_errors",1),m.error("Error in move-files operation:",{error:(0,p.getErrorMessage)(o),time:s}),(w||b)&&e.taskId){
|
|
1718
|
-
try{await d.updateFileOperationRecords(e.taskId,w,b,e.operations?.[0]?.source||"unknown",
|
|
1719
|
-
const a=i(t(1943)),c=i(t(6928)),l=t(6183),d=s(t(5967)),u=t(9860),h=t(1569),g=t(7478),p=t(8824)},2422(module){module.exports=require("@modelcontextprotocol/sdk/server/sse.js")},
|
|
1710
|
+
await n.createToolRecord({...r?{}:{taskId:e.taskId},projectId:t.projectId,type:"move-files",metadata:{status:"failed",timestamp:(new Date).toISOString(),operationCount:e.operations?.length||0,operations:e.operations||[],userComment:e.comment,error:(0,p.getErrorMessage)(o),errorDetails:o instanceof Error?o.stack:o+"",phase:k,attemptedTaskId:e.taskId,taskIdValidationFailed:r},note:"Failed to move files - "+(0,p.getErrorMessage)(o)})}catch(t){m.error("Failed to create failure record for move-files operation",{error:t instanceof Error?t.message:t+"",taskId:e.taskId,operationCount:e.operations?.length||0})}const s=Date.now()-y
|
|
1711
|
+
if(i.recordValue("move_files_time",s),i.incrementCounter("move_files_errors",1),m.error("Error in move-files operation:",{error:(0,p.getErrorMessage)(o),time:s}),(w||b)&&e.taskId){k=d.FileOperationPhase.RECORD_UPDATE_FAILURE
|
|
1712
|
+
try{await d.updateFileOperationRecords(e.taskId,w,b,e.operations?.[0]?.source||"unknown",I.recordType,"Failed to move files",{status:"failed",error:(0,p.getErrorMessage)(o),operationCount:e.operations?.length||0,operations:e.operations||[],userComment:e.comment},"Failed to move files",r,n,m,i,I.metricsPrefix)}catch(t){m.error("Failed to update record with failure status",{taskId:e.taskId,recordId:w,error:t instanceof Error?t.message:t+""})}}return d.handleFileOperationError(o,k,m,i,e,I)}}
|
|
1713
|
+
const a=i(t(1943)),c=i(t(6928)),l=t(6183),d=s(t(5967)),u=t(9860),h=t(1569),g=t(7478),p=t(8824)},2422(module){module.exports=require("@modelcontextprotocol/sdk/server/sse.js")},2424(e,exports,t){Object.defineProperty(exports,"__esModule",{value:!0}),exports.ensureRequestWorktree=async function(e,t,i){const a="requests/"+t,c=(0,n.join)(e,s.ALCHEMY_DIR_NAME,"worktrees"),l=(0,n.join)(c,t)
|
|
1714
|
+
if((0,r.existsSync)(l))return void i.info("Worktree already exists on disk, skipping pre-spawn creation",{requestId:t,worktreePath:l})
|
|
1715
|
+
const d=(0,o.simpleGit)(e);(0,r.mkdirSync)(c,{recursive:!0})
|
|
1716
|
+
try{await d.raw(["worktree","prune"])}catch{}const u=await d.branch(),h=u.all.includes(a)
|
|
1717
|
+
try{if(h)await d.raw(["worktree","add",l,a]),i.info("Pre-spawn: created worktree for existing branch",{requestId:t,branchName:a,worktreePath:l})
|
|
1718
|
+
else{const e=u.all.includes("main")?"main":"master"
|
|
1719
|
+
await d.raw(["worktree","add","-b",a,l,e]),i.info("Pre-spawn: created worktree with new branch from latest main",{requestId:t,branchName:a,mainBranch:e,worktreePath:l})}}catch(e){const r=e instanceof Error?e.message:e+""
|
|
1720
|
+
i.warn("Pre-spawn: failed to create worktree (MCP process will retry)",{requestId:t,error:r})}}
|
|
1721
|
+
const r=t(9896),n=t(6928),o=t(3807),s=t(4139)},2425(e,exports,t){Object.defineProperty(exports,"__esModule",{value:!0}),exports.def=void 0
|
|
1720
1722
|
const r=t(6183),n=t(3707)
|
|
1721
1723
|
exports.def={name:"quick_manage",description:"Move, delete, or create directories. Wraps the change in a request/task workflow that auto-completes.\n\nProvide an array of operations, each with operationType and corresponding data:\n\u2022 create-directory: { createDirectory: { path } }\n\u2022 move-files: { moveFiles: { moves: [{ source, destination }] } }\n\u2022 delete-files: { deleteFiles: { targets: [{ path }] } }\n\nFor read-only operations like get-file-info, use manage_files instead.\n\nRequires: title, description, operations.",schema:r.QuickManageSchema,annotations:{title:"Quick Manage",readOnlyHint:!1,destructiveHint:!0,idempotentHint:!1},handler(e,t){return(0,n.handleQuickChange)(e,"manage",t.context,t.apiClient,t.logger,t.metrics,t.mcpServer)}}},2462(e,exports,t){Object.defineProperty(exports,"__esModule",{value:!0})
|
|
1722
|
-
const r=t(2245),n=t(9080),o=t(5692),s=t(9030),i=t(2903),a=t(4607),c=t(9499),l=t(6770),d=t(8045),u=t(9697),h=t(9196),g=t(5459),p=t(4805),f=t(260),m=t(2283),y=t(4165),w=t(7834),b=t(9373),
|
|
1724
|
+
const r=t(2245),n=t(9080),o=t(5692),s=t(9030),i=t(2903),a=t(4607),c=t(9499),l=t(6770),d=t(8045),u=t(9697),h=t(9196),g=t(5459),p=t(4805),f=t(260),m=t(2283),y=t(4165),w=t(7834),b=t(9373),k=t(6111),I=t(700),v=t(2783),C=t(2601),_=t(1722),E=t(7257),q=t(9230),S=t(5216),T=t(6473),P=t(4921),R=t(8850),M=t(3556),j=t(1391),x=t(6315),O=t(7713),D=t(6252),A=t(213),$=t(7250),F=t(2425),N=t(1540),L=t(5767),z=t(4973),B=t(7613),H=t(3322),U=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)(b.def),(0,r.registerTool)(k.def),(0,r.registerTool)(I.def),(0,r.registerTool)(v.def),(0,r.registerTool)(C.def),(0,r.registerTool)(_.def),(0,r.registerTool)(E.def),(0,r.registerTool)(q.def),(0,r.registerTool)(S.def),(0,r.registerTool)(T.def),(0,r.registerTool)(P.def),(0,r.registerTool)(R.def),(0,r.registerTool)(M.def),(0,r.registerTool)(j.def),(0,r.registerTool)(x.def),(0,r.registerTool)(O.def),(0,r.registerTool)(D.def),(0,r.registerTool)(A.def),(0,r.registerTool)($.def),(0,r.registerTool)(F.def),(0,r.registerTool)(N.def),(0,r.registerTool)(L.def),(0,r.registerTool)(z.def),(0,r.registerTool)(B.def),(0,r.registerTools)(H.metaDefs),(0,r.registerTools)(U.testingDefs),(0,r.registerTools)(W.debugDefs),(0,t(2245).freezeRegistry)()},2478(e,exports){Object.defineProperty(exports,"__esModule",{value:!0}),exports.requestConfig=void 0,exports.areTestsRequiredForCompletion=function(){return exports.requestConfig.requireTestsForCompletion},exports.setTestsRequiredForCompletion=function(e){exports.requestConfig.requireTestsForCompletion=e},exports.getCompletionMode=function(e){return e&&["auto-merge","auto-test-then-merge","manual-review"].includes(e)?e:"auto-merge"},exports.getApprovalMode=function(e){return e&&["none","require-approval"].includes(e)?e:"none"},exports.requestConfig={requireTestsForCompletion:!1}},2537(e,exports,t){async function r(e,t,r){if(C.has(r)&&_>=t){if(0===t)return 0
|
|
1723
1725
|
try{return(await y.default.readFile(e,"utf-8")).split("\n").length}catch{return}}}function n(e,t,r){const n="depth"in e,o=n?e:r,s=n?e.isDirectory:e.isDirectory(),a=e.name,c=s?"[\u{1f4c1} DIR]":"[\u{1f4c4} FILE]"
|
|
1724
1726
|
let l=""
|
|
1725
1727
|
if(s||void 0===o?.lineCount||(l=` (${i(o.lineCount)} lines)`),s&&o?.subtreeTotals){const{files:e,lines:t}=o.subtreeTotals
|
|
@@ -1735,14 +1737,14 @@ if(30>s)return`${s} day${1===s?"":"s"} ago`
|
|
|
1735
1737
|
const i=Math.floor(s/30)
|
|
1736
1738
|
if(12>i)return`${i} month${1===i?"":"s"} ago`
|
|
1737
1739
|
const a=Math.floor(i/12)
|
|
1738
|
-
return`${a} year${1===a?"":"s"} ago`}(o.modified)} | ${(0,
|
|
1740
|
+
return`${a} year${1===a?"":"s"} ago`}(o.modified)} | ${(0,I.formatTimestamp)(o.modified)})`)
|
|
1739
1741
|
break
|
|
1740
1742
|
case"size":s||"number"!=typeof o.size||(l+=` (${function(e){if(0===e)return"0 bytes"
|
|
1741
1743
|
let t=e,r=0
|
|
1742
1744
|
for(;t>=1024&&4>r;)t/=1024,r++
|
|
1743
1745
|
return`${0===r?t.toString():t.toFixed(10>t?1:0)}${["bytes","KB","MB","GB","TB"][r]}`}(o.size)})`)}return`${c} ${a}${l}`}async function o(e,t,n=0,s,i,l){if(n>=s)return[]
|
|
1744
|
-
try{const{fullPath:d}=
|
|
1745
|
-
for(const d of h)try{const u=w.default.join(e,d.name).replace(/\\/g,"/"),{fullPath:h}=
|
|
1746
|
+
try{const{fullPath:d}=k.validateAndNormalizePath(e,t),h=await y.default.readdir(d,{withFileTypes:!0}),g=[]
|
|
1747
|
+
for(const d of h)try{const u=w.default.join(e,d.name).replace(/\\/g,"/"),{fullPath:h}=k.validateAndNormalizePath(u,t),p=await y.default.stat(h),f=d.isFile()?w.default.extname(d.name).toLowerCase():""
|
|
1746
1748
|
let m
|
|
1747
1749
|
d.isFile()&&(m=await r(h,p.size,f))
|
|
1748
1750
|
const b={name:d.name,isDirectory:d.isDirectory(),depth:n,size:p.size,modified:p.mtime,extension:f,lineCount:m}
|
|
@@ -1751,8 +1753,8 @@ const o=[]
|
|
|
1751
1753
|
return e.forEach(((i,a)=>{const c=a===e.length-1,l=c?"\u2514\u2500\u2500 ":"\u251c\u2500\u2500 ",d=n(i,t),u=i.isDirectory?"/":""
|
|
1752
1754
|
if(o.push(`${r}${l}${d}${u}`),i.children&&i.children.length>0){const e=r+(c?" ":"\u2502 "),n=s(i.children,t,e)
|
|
1753
1755
|
n&&o.push(n)}})),o.join("\n")}function i(e){return e.toLocaleString()}async function a(e,t,n){const o={files:0,directories:0,lines:0}
|
|
1754
|
-
try{const{fullPath:n}=
|
|
1755
|
-
for(const n of s)try{const s=w.default.join(e,n.name).replace(/\\/g,"/"),{fullPath:i}=
|
|
1756
|
+
try{const{fullPath:n}=k.validateAndNormalizePath(e,t),s=await y.default.readdir(n,{withFileTypes:!0})
|
|
1757
|
+
for(const n of s)try{const s=w.default.join(e,n.name).replace(/\\/g,"/"),{fullPath:i}=k.validateAndNormalizePath(s,t)
|
|
1756
1758
|
if(n.isDirectory())o.directories+=1
|
|
1757
1759
|
else{o.files+=1
|
|
1758
1760
|
const e=await y.default.stat(i),t=w.default.extname(n.name).toLowerCase(),s=await r(i,e.size,t)
|
|
@@ -1778,27 +1780,27 @@ var t={}
|
|
|
1778
1780
|
if(null!=e)for(var r=h(e),n=0;n<r.length;n++)"default"!==r[n]&&g(t,e,r[n])
|
|
1779
1781
|
return p(t,e),t}),m=this&&this.__importDefault||function(e){return e&&e.__esModule?e:{default:e}}
|
|
1780
1782
|
Object.defineProperty(exports,"__esModule",{value:!0}),exports.handleListDirectory=async function(e,t,i,a){const h=Date.now()
|
|
1781
|
-
let g=
|
|
1782
|
-
|
|
1783
|
-
try{const p=
|
|
1783
|
+
let g=k.FileOperationPhase.VALIDATION
|
|
1784
|
+
k.FileOperationPhase.FILE_WRITE
|
|
1785
|
+
try{const p=k.validateArgs(e,b.ListDirectorySchema),{path:f,levels:m=1,sortBy:I="name"}=p
|
|
1784
1786
|
i.info("Listing directory: "+f)
|
|
1785
|
-
const{normalizedPath:C,fullPath:_}=
|
|
1786
|
-
g=
|
|
1787
|
+
const{normalizedPath:C,fullPath:_}=k.validateAndNormalizePath(f,t)
|
|
1788
|
+
g=k.FileOperationPhase.FILE_WRITE
|
|
1787
1789
|
try{if(!(await y.default.stat(_)).isDirectory())return{content:[{type:"text",text:"Path is not a directory: "+f}],isError:!0}
|
|
1788
1790
|
await y.default.access(_,y.default.constants.R_OK)}catch(e){return e instanceof Error&&"ENOENT"===e.code?{content:[{type:"text",text:"Directory does not exist: "+f}],isError:!0}:e instanceof Error&&"EACCES"===e.code?{content:[{type:"text",text:"Directory not accessible: "+f}],isError:!0}:{content:[{type:"text",text:"Cannot access directory: "+f}],isError:!0}}let E,q
|
|
1789
|
-
if(m>1){i.info(`Building tree structure for: ${C} (levels: ${m}, sortBy: ${
|
|
1790
|
-
const e=await o(C,t,0,m,
|
|
1791
|
-
if(e.length>0){const t=s(e,
|
|
1791
|
+
if(m>1){i.info(`Building tree structure for: ${C} (levels: ${m}, sortBy: ${I})`)
|
|
1792
|
+
const e=await o(C,t,0,m,I,i)
|
|
1793
|
+
if(e.length>0){const t=s(e,I)
|
|
1792
1794
|
E=`Directory tree for ${C} (${m} levels):\n${l(c(e))}\n\n${t}`,q=d(e)}else E=`Directory ${C} is empty or inaccessible.`,q=0}else{const e=await y.default.readdir(_,{withFileTypes:!0}),o=[]
|
|
1793
|
-
for(const n of e)try{const e=w.default.join(C,n.name).replace(/\\/g,"/"),{fullPath:s}=
|
|
1795
|
+
for(const n of e)try{const e=w.default.join(C,n.name).replace(/\\/g,"/"),{fullPath:s}=k.validateAndNormalizePath(e,t),i=await y.default.stat(s),a=n.isFile()?w.default.extname(n.name).toLowerCase():""
|
|
1794
1796
|
let c
|
|
1795
|
-
n.isFile()&&(c=await r(s,i.size,a)),o.push({name:n.name,isDirectory:n.isDirectory(),depth:0,size:i.size,modified:i.mtime,extension:a,lineCount:c})}catch(e){i.debug("Excluding directory entry from listing: "+n.name,{reason:(0,v.getErrorMessage)(e)})}const s=u(o,
|
|
1797
|
+
n.isFile()&&(c=await r(s,i.size,a)),o.push({name:n.name,isDirectory:n.isDirectory(),depth:0,size:i.size,modified:i.mtime,extension:a,lineCount:c})}catch(e){i.debug("Excluding directory entry from listing: "+n.name,{reason:(0,v.getErrorMessage)(e)})}const s=u(o,I),a=s.map((e=>n({name:e.name,isDirectory(){return e.isDirectory},isFile(){return!e.isDirectory}},I,e)))
|
|
1796
1798
|
E=a.length>0?`Directory listing for ${C}:\n${l(c(s))}\n\n${a.join("\n")}`:`Directory ${C} is empty.`,q=s.length}const S=t.workspaceManager?.getCurrentContext()
|
|
1797
1799
|
E+="\n\nBranch: "+(S?.branchName||"unknown")
|
|
1798
1800
|
const T=Date.now()-h
|
|
1799
1801
|
return a.recordValue("list_directory_time",T),a.recordValue("list_directory_entries",q),a.incrementCounter("list_directory_success",1),i.info("Successfully listed directory: "+C,{entryCount:q,levels:m,time:T}),{content:[{type:"text",text:E}]}}catch(e){const t=Date.now()-h
|
|
1800
1802
|
return a.recordValue("list_directory_time",t),a.incrementCounter("list_directory_errors",1),i.error("Error listing directory:",{error:(0,v.getErrorMessage)(e),time:t}),{content:[{type:"text",text:(0,v.getErrorMessage)(e)}],isError:!0}}}
|
|
1801
|
-
const y=m(t(1943)),w=m(t(6928)),b=t(6183),
|
|
1803
|
+
const y=m(t(1943)),w=m(t(6928)),b=t(6183),k=f(t(5967)),I=t(3253),v=t(8824),C=new Set([".ts",".tsx",".js",".jsx",".mjs",".cjs",".py",".rb",".go",".rs",".java",".kt",".scala",".c",".cpp",".h",".hpp",".cs",".html",".css",".scss",".sass",".less",".json",".yaml",".yml",".toml",".xml",".md",".txt",".csv",".sql",".sh",".bash",".zsh",".fish",".vim",".lua",".php",".swift",".m",".vue",".svelte",".astro",".env",".gitignore",".dockerignore",".config",".conf",".ini",".cfg"]),_=1048576},2568(e,exports,t){var r=this&&this.__importDefault||function(e){return e&&e.__esModule?e:{default:e}}
|
|
1802
1804
|
Object.defineProperty(exports,"__esModule",{value:!0}),exports.ProjectSynchronizer=void 0
|
|
1803
1805
|
const n=r(t(6928)),o=t(8029),s=t(8824),i=t(2096)
|
|
1804
1806
|
exports.ProjectSynchronizer=class{constructor(e,t,r,n,o={}){this.logger=e.child({component:"project-synchronizer"}),this.registry=t,this.remoteApi=r,this.fileSystem=n,this.options={createRemoteProjects:o.createRemoteProjects??!0,maxRetryAttempts:o.maxRetryAttempts??3,retryDelayMs:o.retryDelayMs??1e3},this.logger.info("ProjectSynchronizer initialized",{options:this.options})}async ensureProjectExists(e){const t=Math.random().toString(36).substring(2,8)
|
|
@@ -1977,11 +1979,11 @@ const f=await Promise.all(p)
|
|
|
1977
1979
|
let m=""
|
|
1978
1980
|
if(t.getCurrentBranchContext)try{const e=await t.getCurrentBranchContext()
|
|
1979
1981
|
e.branch&&(m=`**Current Branch:** ${e.branch}\n`)}catch(e){i.debug("Could not get branch context",{error:e})}const y=f.filter((e=>e.success)).length,w=f.filter((e=>!e.success)).length,b=f.length
|
|
1980
|
-
let
|
|
1981
|
-
m&&(
|
|
1982
|
+
let k="## Read Files/Documents\n\n"
|
|
1983
|
+
m&&(k+=m),k+=`**Total Requests:** ${b} - **Successful:** ${y} - **Failed:** ${w}\n\n`
|
|
1982
1984
|
for(let e=0;e<f.length;e++){const t=f[e]
|
|
1983
|
-
"file"===t.type?
|
|
1984
|
-
return i.info("Multiple file/document read completed",{duration:Date.now()-a,totalRequests:b,successfulReads:y,failedReads:w,success:
|
|
1985
|
+
"file"===t.type?k+=`File ${e+1}: ${t.path}\n`:(k+=`Document ${e+1}: ${t.documentId}`,t.filename&&(k+=` (${t.filename})`),k+="\n"),t.success?(k+="**Status:** Success\n",t.lineCount&&t.totalLines&&(k+=`Lines Read / Total Lines ${t.lineCount} / ${t.totalLines}\n`),t.originalRequest?.lines&&t.totalLines&&(k+=`**Lines:** ${t.originalRequest.lines}\n`),k+=`\n**Content:**\n\`\`\`\n${t.content}\n\`\`\`\n`):(k+="**Status:** Failed\n",k+=`**Error:** ${t.error}\n`),k+="\n"}const I=0===w
|
|
1986
|
+
return i.info("Multiple file/document read completed",{duration:Date.now()-a,totalRequests:b,successfulReads:y,failedReads:w,success:I}),s.incrementCounter("read_files_total",1,{success:I}),{content:[{type:"text",text:k}],isError:!I}}catch(e){const t=Date.now()-a
|
|
1985
1987
|
return i.error("Read multiple files operation failed",{error:e instanceof Error?e.stack:e+"",duration:t}),s.incrementCounter("read_files_errors",1),{content:[{type:"text",text:"\u274c **Read Operation Failed:** "+(0,p.getErrorMessage)(e)}],isError:!0}}}
|
|
1986
1988
|
const l=c(t(1943)),d=t(6183),u=t(1569),h=a(t(5967)),g=t(9470),p=t(8824)},2968(e,exports,t){Object.defineProperty(exports,"__esModule",{value:!0}),exports.TaskClient=void 0
|
|
1987
1989
|
const r=t(8824),n=t(7645),o=t(2161),s=t(5172)
|
|
@@ -2094,12 +2096,12 @@ d.info("Generating journal for request",{requestId:c})
|
|
|
2094
2096
|
const h=t.projectId
|
|
2095
2097
|
if(!h)throw(0,n.createValidationError)("Project ID is required. Make sure you are in a project context.")
|
|
2096
2098
|
o.setProjectId(h),d.info("Fetching request data, tasks, and file history in parallel")
|
|
2097
|
-
const g=o.getRequestClient(),p=o.getTaskClient(),f=o.getToolRecordClient(),[m,y,w]=await Promise.all([g.getRequest(c),p.listTasks({requestId:c}),f.getToolRecordsByRequestId(c).catch((e=>(d.warn("Failed to fetch tool records",{error:e+""}),[])))]),b=(0,s.extractDataFromResponse)(m,{logger:d,operationName:"getRequest",throwOnNoData:!0}),
|
|
2099
|
+
const g=o.getRequestClient(),p=o.getTaskClient(),f=o.getToolRecordClient(),[m,y,w]=await Promise.all([g.getRequest(c),p.listTasks({requestId:c}),f.getToolRecordsByRequestId(c).catch((e=>(d.warn("Failed to fetch tool records",{error:e+""}),[])))]),b=(0,s.extractDataFromResponse)(m,{logger:d,operationName:"getRequest",throwOnNoData:!0}),k="data"in b?b.data:b,I={id:k.id||c,title:k.title||"Unknown Request",description:k.description||"No description available",status:k.status||"unknown",type:k.type||"unknown",acceptanceCriteria:k.acceptanceCriteria||[],createdAt:k.createdAt||(new Date).toISOString(),updatedAt:k.updatedAt||(new Date).toISOString(),completedAt:k.completedAt},v=(0,s.extractDataFromResponse)(y,{logger:d,operationName:"listTasks",throwOnNoData:!1}),C=(Array.isArray(v)?v:"data"in v?v.data:[]).map((e=>({id:e.id,title:e.title||"Untitled Task",description:e.description||"No description",status:e.status||"unknown",createdAt:e.createdAt||(new Date).toISOString(),completedAt:e.metadata?.completedAt})))
|
|
2098
2100
|
d.info(`Fetched request, ${C.length} tasks, ${w.length} tool records`)
|
|
2099
2101
|
const _=await async function(e){const t=new Map,n=[],o=e.filter((e=>["write-file","replace-in-files","move-files","delete-files","manage-files"].includes(e.type))).sort(((e,t)=>new Date(e.createdAt).getTime()-new Date(t.createdAt).getTime()))
|
|
2100
2102
|
for(const e of o){const o=r(e),s=e.metadata?.comment||e.metadata?.userComment||"No comment"
|
|
2101
2103
|
n.push({type:e.type,timestamp:e.createdAt,comment:s,files:o,recordId:e.localId||e.id})
|
|
2102
|
-
for(const e of o)t.set(e,(t.get(e)||0)+1)}return{files:Array.from(t.entries()).map((([e,t])=>({path:e,operations:t}))).sort(((e,t)=>t.operations-e.operations)),operations:n}}(w),E={request:
|
|
2104
|
+
for(const e of o)t.set(e,(t.get(e)||0)+1)}return{files:Array.from(t.entries()).map((([e,t])=>({path:e,operations:t}))).sort(((e,t)=>t.operations-e.operations)),operations:n}}(w),E={request:I,tasks:C,fileChanges:{summary:{totalFiles:_.files.length,totalOperations:_.operations.length,files:_.files},operations:_.operations},suggestedFilename:`JOURNAL-${c}.md`,metadata:{projectId:h,requestId:c,generatedAt:(new Date).toISOString()}},q=`\u2705 **Request Data Fetched Successfully!**\n\n**Request:** ${I.title} (${c})\n**Status:** ${I.status}\n**Type:** ${I.type}\n**Tasks:** ${C.length}\n**Files Changed:** ${_.files.length}\n**File Operations:** ${_.operations.length}\n\n**Data Summary:**\n\`\`\`json\n${JSON.stringify(E,null,2)}\n\`\`\`\n\n**Next Steps:**\nWrite a **compact technical narrative** and save as \`JOURNAL-${c}.md\` using document_operations (create).\n\n**Style Guide:**\n- Be concise and direct - no fluff, repetition, or unnecessary elaboration\n- Write in narrative flow connecting the changes chronologically\n- Reference files with paths: "Modified \\\`src/tools/example.ts\\\` to add X..."\n- Include operation comments inline: ("comment: 'Fix bug in parser'")\n- **Link to tool records**: Use \\\`[RECORD:trec######]\\\` format to reference operations (e.g., "Modified parser.ts [RECORD:trec004123]")\n- Show key code changes with brief snippets where they add clarity\n- Explain what changed and why, skip obvious details\n- Focus on technical substance over structure\n\n**Example:** "Modified \\\`parser.ts\\\` [RECORD:trec004123] to handle edge cases (comment: 'Fix null handling'). Added \\\`if (!input) return null;\\\` check at line 45. Then updated \\\`validator.ts\\\` [RECORD:trec004124] to use the new parser behavior..."`
|
|
2103
2105
|
return u({tool:"generate_request_journal",success:!0}),l.incrementCounter("generate_request_journal_total",1,{success:!0}),{content:[{type:"text",text:q}]}}catch(e){return d.error("Error generating request journal",{error:e instanceof Error?e.stack:e+""}),u({tool:"generate_request_journal",success:!1}),l.incrementCounter("generate_request_journal_errors",1),{content:[{type:"text",text:"\u274c **Failed to generate journal:** "+(0,i.getErrorMessage)(e)}],isError:!0}}}
|
|
2104
2106
|
const n=t(9860),o=t(1569),s=t(2960),i=t(8824),a=o.z.object({requestId:o.z.string().regex(/^req[_\d].+$/,"Invalid request ID format")})},3064(e,exports,t){async function r(e,t,r,n){if(!r.lockOverrideManager||!r.configManager)return e
|
|
2105
2107
|
try{const n=await r.configManager.getEffectiveConfig(r.mainBasePath)
|
|
@@ -2219,7 +2221,7 @@ var t={}
|
|
|
2219
2221
|
if(null!=e)for(var r=o(e),n=0;n<r.length;n++)"default"!==r[n]&&s(t,e,r[n])
|
|
2220
2222
|
return i(t,e),t}),c=this&&this.__importDefault||function(e){return e&&e.__esModule?e:{default:e}}
|
|
2221
2223
|
Object.defineProperty(exports,"__esModule",{value:!0}),exports.handleReplaceStrings=async function(e,t,r,o,s,i,a,c){const y=i.child({tool:"replace_strings"}),w=Date.now()
|
|
2222
|
-
let b,I
|
|
2224
|
+
let b,k,I=u.FileOperationPhase.VALIDATION
|
|
2223
2225
|
const v={toolName:"replace-strings",operationName:"replace-string",fileOperationPhase:u.FileOperationPhase.STRING_REPLACEMENT,recordType:"replace-strings",metricsPrefix:"replace_strings",successMessage:"Successfully replaced strings across files and documents",failureMessage:"Failed to replace strings across files and documents"}
|
|
2224
2226
|
try{const i=u.validateArgs(e,d.ReplaceStringsSchema),{taskId:C,operations:_,comment:E}=i
|
|
2225
2227
|
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")
|
|
@@ -2232,7 +2234,7 @@ if(S.length>0&&!t.documentFileManager)throw Error("Document file manager not ava
|
|
|
2232
2234
|
for(const e of S)P.push({type:"document",documentId:e.documentId,replacements:e.replacements,mode:e.mode||"unique"})
|
|
2233
2235
|
if(P.length>0&&t.apiClient){const e=P.map((e=>e.documentId))
|
|
2234
2236
|
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}
|
|
2235
|
-
throw e}}
|
|
2237
|
+
throw e}}I=u.FileOperationPhase.TASK_VALIDATION,a.incrementCounter("replace_strings_phase",1,{phase:I})
|
|
2236
2238
|
const R=T.length>0?T[0].path:"document-operation",M=await u.validateTaskId(C,R,r,y,a,v.metricsPrefix),j=M?.requestId
|
|
2237
2239
|
let x=null
|
|
2238
2240
|
T.length>0&&j&&(x=await u.validateWorkItemStates(C,T[0].path,r,s,t,y,a,v.metricsPrefix))
|
|
@@ -2243,9 +2245,9 @@ if(!D.success){if(D.isLockConflict)return{content:[{type:"text",text:"\u274c "+D
|
|
|
2243
2245
|
throw Error(D.error)}if(T.length>0){y.debug("Re-validating file paths with correct workspace context",{operationCount:T.length,workspaceBasePath:t.workspaceManager?.getCurrentContext().basePath})
|
|
2244
2246
|
for(let e=0;e<T.length;e++){const r=T[e],n=q[e],{normalizedPath:o,fullPath:s}=u.validateAndNormalizePath(n.path,t)
|
|
2245
2247
|
T[e]={...r,path:o,fullPath:s}}}if(P.length>0&&j)try{await(0,g.validateRequestStatusForDocumentOperation)(j,s,y,a,"replace-strings-document")}catch(e){if(e instanceof h.ValidationError)return{content:[{type:"text",text:e.message}],isError:!0}
|
|
2246
|
-
throw e}
|
|
2248
|
+
throw e}I=u.FileOperationPhase.RECORD_CREATION,a.incrementCounter("replace_strings_phase",1,{phase:I})
|
|
2247
2249
|
const A=[...T.map((e=>({type:"file",path:e.path,replacements:e.replacements,mode:e.mode}))),...P.map((e=>({type:"document",documentId:e.documentId,replacements:e.replacements,mode:e.mode})))],{toolRecordId:$}=await u.createFileOperationRecords(C,j,t.projectId,v.recordType,R,{operationCount:_.length,fileOperations:T.length,documentOperations:P.length,operations:A,userComment:E},r,o,y,a,v.metricsPrefix,c)
|
|
2248
|
-
if(b=$,I
|
|
2250
|
+
if(b=$,k=$,I=v.fileOperationPhase,a.incrementCounter("replace_strings_phase",1,{phase:I}),T.length>0&&t.git)try{y.debug("[REPLACE-STRINGS] Checking for user changes before replace operations")
|
|
2249
2251
|
const e=await(0,p.commitUserChangesBeforeToolOperation)(t.git,"replace-strings",{requestId:j,taskId:C,workspaceManager:t.workspaceManager},y,a)
|
|
2250
2252
|
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})
|
|
2251
2253
|
const F=[]
|
|
@@ -2258,8 +2260,8 @@ try{const o=await t.documentFileManager.getDocumentAsFile(e.documentId),s=t.docu
|
|
|
2258
2260
|
r.filename=s?.filename
|
|
2259
2261
|
const i=await l.default.readFile(o,"utf8"),{newContent:a,results:c}=await n(i,e.replacements,e.mode)
|
|
2260
2262
|
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))
|
|
2261
|
-
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:
|
|
2262
|
-
try{await o.updateToolRecord(
|
|
2263
|
+
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:k,successField:"successfulReplacements",logger:y,metrics:a,metricsPrefix:"replace_strings"},t),B=u.processMultiFileOperationResults(F,"successfulReplacements"),{successfulOperations:H,failedOperations:U,totalSuccessfulChanges:W,overallSuccess:G,successfulFiles:V,failedFiles:J}=B
|
|
2264
|
+
try{await o.updateToolRecord(k,{metadata:{path:T.length>0?T[0].path:"document:"+P[0]?.documentId,status:G?"completed":"failed",error:G?void 0:U+" operations failed",totalOperations:F.length,successfulFiles:V,failedFiles:J,operations:A,totalSuccessfulReplacements:W,totalFailedReplacements:N,operationsWithChanges:L,processingTime:Date.now()-w,userComment:E,...T.length>0&&z.success&&z.commitHash&&{commitHash:z.commitHash,previousCommitHash:z.previousCommitHash||void 0}},note:G?`String replacement completed: ${H}/${F.length} operations successful${T.length>0?" (committed to git)":""}`:`String replacement partially failed: ${U}/${F.length} operations failed`})}catch(e){y.warn("Failed to update tool record",{recordError:e})}u.formatMultiFileToolResponse("String Replacement",{successfulOperations:H,failedOperations:U,totalSuccessfulChanges:W,overallSuccess:G,successfulFiles:V,failedFiles:J},z,D)
|
|
2263
2265
|
let K="## String Replacement Results\n\n"
|
|
2264
2266
|
if(t.workspaceManager&&(K+=`**Branch:** \`${t.workspaceManager.getCurrentContext().branchName}\`\n\n`),K+="**Summary:**\n",K+=`- **Files processed:** ${H+U}\n`,K+=`- **Successful operations:** ${H}\n`,K+=`- **Failed operations:** ${U}\n`,K+=`- **Total replacements:** ${W} 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"),D.lockAcquired&&D.lockedRequestId&&(K+=`\u{1f512} **Locked request:** ${D.lockedRequestId}\n\n`),1===F.length){const e=F[0]
|
|
2265
2267
|
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"
|
|
@@ -2268,7 +2270,7 @@ for(const e of F){if("file"===e.type?K+=`### File: ${e.path}\n`:(K+="### Documen
|
|
|
2268
2270
|
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")
|
|
2269
2271
|
const Y=Date.now()-w
|
|
2270
2272
|
return y.info("Replace strings operation completed",{duration:Y,success:G,totalOperations:F.length,successfulOperations:H,failedOperations:U}),a.incrementCounter("replace_strings_total",1,{success:G}),{content:[{type:"text",text:K}],isError:!G}}catch(t){const r=Date.now()-w
|
|
2271
|
-
if(y.error("Replace strings operation failed",{error:t instanceof Error?t.stack:t+"",duration:r,phase:
|
|
2273
|
+
if(y.error("Replace strings operation failed",{error:t instanceof Error?t.stack:t+"",duration:r,phase:I}),k)try{await o.updateToolRecord(k,{metadata:{path:e?.operations?.[0]?.path||e?.operations?.[0]?.documentId,status:"failed",error:(0,m.getErrorMessage)(t),phase:I,duration:r,userComment:e?.comment},note:"String replacement failed: "+(0,m.getErrorMessage)(t)})}catch(e){}return a.incrementCounter("replace_strings_errors",1,{phase:I}),{content:[{type:"text",text:"\u274c **Replace Strings Failed:** "+(0,m.getErrorMessage)(t)}],isError:!0}}}
|
|
2272
2274
|
const l=c(t(1943)),d=t(6183),u=a(t(5967)),h=t(9860),g=t(5003),p=t(7478),f=t(9949),m=t(8824)},3322(e,exports,t){var r,n=this&&this.__createBinding||(Object.create?function(e,t,r,n){void 0===n&&(n=r)
|
|
2273
2275
|
var o=Object.getOwnPropertyDescriptor(t,r)
|
|
2274
2276
|
o&&!("get"in o?!t.__esModule:o.writable||o.configurable)||(o={enumerable:!0,get(){return t[r]}}),Object.defineProperty(e,n,o)}:function(e,t,r,n){void 0===n&&(n=r),e[n]=t[r]}),o=this&&this.__setModuleDefault||(Object.create?function(e,t){Object.defineProperty(e,"default",{enumerable:!0,value:t})}:function(e,t){e.default=t}),s=this&&this.__importStar||(r=function(e){return r=Object.getOwnPropertyNames||function(e){var t=[]
|
|
@@ -2354,14 +2356,14 @@ Object.defineProperty(exports,"LogLevel",{enumerable:!0,get(){return s.LogLevel}
|
|
|
2354
2356
|
const r=t(6183),n=t(8317)
|
|
2355
2357
|
exports.def={name:"request_file_history",description:"Get file change history for an entire request. Supports summary mode (net diffs) or detailed mode (chronological operations). Can be filtered to specific task. Use query_history tool instead.",schema:r.QueryHistorySchema,annotations:{title:"Request File History",readOnlyHint:!0},hidden:!0,readOnly:!0,handler(e,t){return(0,n.handleRequestFileHistory)(e,t.context,t.apiClient,t.logger,t.metrics)}}},3611(e,exports,t){var r=this&&this.__importDefault||function(e){return e&&e.__esModule?e:{default:e}}
|
|
2356
2358
|
Object.defineProperty(exports,"__esModule",{value:!0})
|
|
2357
|
-
const n=r(t(6928)),o=r(t(7252)),s=r(t(8577)),i=t(184),a=t(1213),c=t(3444),l=t(9955),d=t(5218),u=t(2568),h=t(3102),g=t(1152),p=t(3884),f=t(7888),m=t(4139),y=t(6800),w=t(6539),b=t(8824),
|
|
2359
|
+
const n=r(t(6928)),o=r(t(7252)),s=r(t(8577)),i=t(184),a=t(1213),c=t(3444),l=t(9955),d=t(5218),u=t(2568),h=t(3102),g=t(1152),p=t(3884),f=t(7888),m=t(4139),y=t(6800),w=t(6539),b=t(8824),k=t(6975),I=t(1253),v=process.argv.slice(2),C=v[0]||process.cwd(),_=n.default.resolve(C),E=parseInt(process.env.LOCAL_SERVER_PORT||v[1]||"3002",10),q=(0,c.createEnvLogger)({serviceName:"mcp-http-server"});(0,c.isDebugToolsEnabled)()?q.info("HTTP server initializing",{baseDir:_,preferredPort:E,debugLogging:process.env.DEBUG_LOGGING,debugLevel:process.env.DEBUG_LEVEL}):q.info("HTTP server starting",{port:E})
|
|
2358
2360
|
const S=(0,g.createMetricsCollector)(!0),T=(process.env.REMOTE_SERVER_PORT,process.env.REMOTE_SERVER_HOST,process.env.REMOTE_SERVER_URL||"https://api.alchemylabcode.com")
|
|
2359
2361
|
q.info("Using remote server URL",{remoteServerUrl:T}),async function(){try{q.info("Finding available port...",{preferredPort:E,baseDir:_,remoteServerUrl:T})
|
|
2360
2362
|
const e=await(0,y.findAvailablePort)(E)
|
|
2361
2363
|
e!==E&&q.info(`Preferred port ${E} is in use, using port ${e} instead`),q.info("Starting HTTP API server...",{port:e,baseDir:_,remoteServerUrl:T})
|
|
2362
2364
|
const t=new l.ProjectRegistry(q),r=new h.DefaultProjectFileSystem(q),c=n.default.join(_,m.ALCHEMY_DIR_NAME)
|
|
2363
2365
|
q.info(`Checking ${m.ALCHEMY_DIR_NAME} directory`,{alchemyPath:c}),await r.ensureDirectoryExists(c)
|
|
2364
|
-
const g=new
|
|
2366
|
+
const g=new I.TokenManager(q,n.default.join(c,"auth-token.json")),v=(await w.ClientFactory.createClient(T,q,S,{tokenManager:g,workingDir:_,alchemyPath:c})).projectClient,C=new k.ProjectClientAdapter(v,q),P=new u.ProjectSynchronizer(q,t,C,r),R=await P.getOrCreateProject(_,{name:n.default.basename(_)||"Local Project",description:"Project for "+n.default.basename(_),status:"active",metadata:{basePath:_,alchemyPath:c,bootstrapped:!0}})
|
|
2365
2367
|
q.info("Using project",{projectId:R.id,projectName:R.name})
|
|
2366
2368
|
const M=(0,o.default)()
|
|
2367
2369
|
M.use((0,s.default)()),M.use(o.default.json({limit:"50mb"})),M.use(o.default.urlencoded({extended:!0})),M.use((0,p.requestLogger)(q))
|
|
@@ -2464,18 +2466,18 @@ try{const a=u.validateArgs(e,d.GetFileInfoSchema),{path:h}=a
|
|
|
2464
2466
|
n.info("Getting file info: "+h)
|
|
2465
2467
|
const{normalizedPath:f,fullPath:m}=u.validateAndNormalizePath(h,t)
|
|
2466
2468
|
i=u.FileOperationPhase.FILE_WRITE
|
|
2467
|
-
try{await c.default.access(m)}catch(e){throw Error("Path not accessible: "+h)}const y=await c.default.stat(m),w=y.isFile()?l.default.extname(m).slice(1):"",b={path:f,type:y.isDirectory()?"directory":"file",size:y.size,sizeFormatted:(p=y.size,u.formatFileSize(p)),created:r(y.birthtime),modified:r(y.mtime),accessed:r(y.atime),permissions:(g=y.mode,(511&g).toString(8)),isDirectory:y.isDirectory(),isFile:y.isFile(),isSymbolicLink:y.isSymbolicLink(),extension:w},
|
|
2468
|
-
b.isFile&&w&&
|
|
2469
|
-
const
|
|
2470
|
-
return o.recordValue("get_file_info_time",
|
|
2469
|
+
try{await c.default.access(m)}catch(e){throw Error("Path not accessible: "+h)}const y=await c.default.stat(m),w=y.isFile()?l.default.extname(m).slice(1):"",b={path:f,type:y.isDirectory()?"directory":"file",size:y.size,sizeFormatted:(p=y.size,u.formatFileSize(p)),created:r(y.birthtime),modified:r(y.mtime),accessed:r(y.atime),permissions:(g=y.mode,(511&g).toString(8)),isDirectory:y.isDirectory(),isFile:y.isFile(),isSymbolicLink:y.isSymbolicLink(),extension:w},k=["File Information for: "+f,"Type: "+b.type,`Size: ${b.sizeFormatted} (${b.size} bytes)`,"Created: "+b.created,"Modified: "+b.modified,"Accessed: "+b.accessed,"Permissions: "+b.permissions,"Is Directory: "+b.isDirectory,"Is File: "+b.isFile,"Is Symbolic Link: "+b.isSymbolicLink]
|
|
2470
|
+
b.isFile&&w&&k.push("Extension: "+w)
|
|
2471
|
+
const I=Date.now()-s
|
|
2472
|
+
return o.recordValue("get_file_info_time",I),o.incrementCounter("get_file_info_success",1),n.info("Successfully retrieved file info: "+f,{type:b.type,size:b.size,time:I}),{content:[{type:"text",text:k.join("\n")}]}}catch(t){const r=Date.now()-s
|
|
2471
2473
|
return o.recordValue("get_file_info_time",r),o.incrementCounter("get_file_info_errors",1),n.error("Error getting file info:",{error:(0,h.getErrorMessage)(t),time:r}),u.handleFileOperationError(t,i,n,o,e,a)}var g,p}
|
|
2472
2474
|
const c=a(t(1943)),l=a(t(6928)),d=t(6183),u=i(t(5967)),h=t(8824)},3707(e,exports,t){Object.defineProperty(exports,"__esModule",{value:!0}),exports.handleQuickChange=async function(e,t,d,u,h,g,p){const f=h.child({tool:"quick_edit"}),m=Date.now()
|
|
2473
|
-
try{const y=u.getRequestClient(),w=u.getTaskClient(),b=u.getFileClient(),
|
|
2474
|
-
f.info("Starting quick_edit workflow",{title:
|
|
2475
|
+
try{const y=u.getRequestClient(),w=u.getTaskClient(),b=u.getFileClient(),k=u.getToolRecordClient(),{title:I,description:v,...C}=e,_=e.comment||I
|
|
2476
|
+
f.info("Starting quick_edit workflow",{title:I,operationType:t})
|
|
2475
2477
|
let E=!1
|
|
2476
2478
|
try{const e=await y.listRequests({limit:2,sortBy:"created_at",sortDirection:"desc"})
|
|
2477
2479
|
e&&2===e.length&&e.every((e=>"quick-edit"===e.type))&&(E=!0,f.info("Detected two consecutive quick-edits, will recommend normal request"))}catch(e){f.warn("Could not check recent requests for recommendation",{error:e})}f.debug("Creating quick_edit request")
|
|
2478
|
-
const q=await y.createRequest({title:
|
|
2480
|
+
const q=await y.createRequest({title:I,description:v,type:"quick-edit",acceptanceCriteria:["Quick change completed successfully"]})
|
|
2479
2481
|
if(!q||!q.id)throw Error("Failed to create request")
|
|
2480
2482
|
const S=q.id
|
|
2481
2483
|
let T
|
|
@@ -2483,24 +2485,24 @@ f.info("Created request",{requestId:S})
|
|
|
2483
2485
|
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)
|
|
2484
2486
|
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")
|
|
2485
2487
|
f.debug("Creating task")
|
|
2486
|
-
const e=await w.createTask({requestId:S,projectId:d.projectId,title:`Execute ${t} operation`,description:"Quick change: "+
|
|
2488
|
+
const e=await w.createTask({requestId:S,projectId:d.projectId,title:`Execute ${t} operation`,description:"Quick change: "+I})
|
|
2487
2489
|
if(!e||!e.id)throw Error("Failed to create task")
|
|
2488
2490
|
let v
|
|
2489
|
-
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,b,w,
|
|
2490
|
-
else if("replace"===t)v=await(0,o.handleReplaceInFiles)({taskId:T,...C,comment:_},d,w,
|
|
2491
|
+
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,b,w,k,y,h,g,p)
|
|
2492
|
+
else if("replace"===t)v=await(0,o.handleReplaceInFiles)({taskId:T,...C,comment:_},d,w,k,y,h,g,p)
|
|
2491
2493
|
else{if("manage"!==t)throw new r.ValidationError("Unsupported operation type: "+t)
|
|
2492
|
-
v=await(0,s.handleManageFiles)({taskId:T,...C,comment:_||
|
|
2494
|
+
v=await(0,s.handleManageFiles)({taskId:T,...C,comment:_||I},d,w,k,y,u,h,g,p)}if(v.isError){f.error("File operation failed, cleaning up request and task",{requestId:S,taskId:T})
|
|
2493
2495
|
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")
|
|
2494
2496
|
P?f.warn("File operation completed with partial failures",{requestId:S}):f.info("File operation completed successfully"),f.debug("Completing task")
|
|
2495
|
-
try{await(0,i.handleCompleteTask)({taskId:T,summary:`Executed ${t} operation for quick fix: ${
|
|
2497
|
+
try{await(0,i.handleCompleteTask)({taskId:T,summary:`Executed ${t} operation for quick fix: ${I}${P?" (partial success)":""}`},d,u,h,g),f.info("Task completed successfully",{taskId:T})}catch(e){f.error("Task completion via handleCompleteTask failed, attempting direct status update",{taskId:T,error:e instanceof Error?e.message:e+"",errorStack:e instanceof Error?e.stack:void 0})
|
|
2496
2498
|
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")
|
|
2497
|
-
const R=P?`Quick change completed with partial success: ${
|
|
2499
|
+
const R=P?`Quick change completed with partial success: ${I}. Some replacements failed - see details below.`:"Quick change completed: "+I,M=P?t+" operation partially completed - some operations succeeded, some failed":t+" operation executed successfully"
|
|
2498
2500
|
let j=!1
|
|
2499
2501
|
try{const e=await(0,a.handleCompleteRequest)({requestId:S,summary:R,acceptanceEvidence:[{evidence:M}],testVerification:void 0},d,u,h,g,p)
|
|
2500
2502
|
if(e.isError)f.error("Request completion failed, attempting direct completion",{requestId:S,error:e.content[0].text})
|
|
2501
2503
|
else{try{await y.updateRequest(S,{status:"completed",completionSummary:R}),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)})}j=!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(!j)try{f.info("Attempting direct request completion via API",{requestId:S}),await y.updateRequest(S,{status:"completed",completionSummary:R}),j=!0,f.info("Request completed successfully via direct API call",{requestId:S})}catch(e){return f.error("Direct request completion also failed",{requestId:S,error:e instanceof Error?e.message:e+""}),{content:[{type:"text",text:`\u26a0\ufe0f Quick change operation succeeded but request completion failed.\n\n**Request:** ${S}\n**Status:** Still in 'in_progress' - please complete manually\n\nThe file operation was successful, but we couldn't automatically complete the request. Please use the complete-request tool manually.`}],isError:!0}}const x=Date.now()-m
|
|
2502
2504
|
let O
|
|
2503
|
-
return f.info("Quick fix completed",{requestId:S,duration:x,hasPartialFailure:P}),O=P?`\u26a0\ufe0f Quick change completed with partial success\n\n**Request:** ${S}\n**Title:** ${
|
|
2505
|
+
return f.info("Quick fix completed",{requestId:S,duration:x,hasPartialFailure:P}),O=P?`\u26a0\ufe0f Quick change completed with partial success\n\n**Request:** ${S}\n**Title:** ${I}\n**Operation:** ${t}\n**Duration:** ${x}ms\n**Status:** Some operations succeeded, some failed\n\nThe successful changes have been applied and automatically merged to main.\n**Active branch:** main\n\n**\u26a0\ufe0f Note:** This quick-fix had partial failures. See operation details below:\n\n`+q:`\u2705 Quick change completed successfully!\n\n**Request:** ${S}\n**Title:** ${I}\n**Operation:** ${t}\n**Duration:** ${x}ms\n\nThe change has been applied and automatically merged to main.\n**Active branch:** main`+(q.match(/\[RECORD:trec\d{6}\]/)?.[0]?"\n"+q.match(/\[RECORD:trec\d{6}\]/)?.[0]:""),E&&(O+="\n\n\u{1f4a1} **Recommendation:** You've created several quick-edits in a row. For better traceability and organization, consider creating a proper feature or bugfix request with multiple tasks for your next change."),{content:[{type:"text",text:O}]}}catch(e){if(f.error("Quick change workflow failed after request creation, cleaning up",{requestId:S,error:(0,l.getErrorMessage)(e)}),T)try{await w.updateTaskStatus(T,"canceled"),f.info("Canceled task after workflow failure",{taskId:T})}catch(e){f.warn("Failed to cancel task during cleanup",{taskId:T,error:e instanceof Error?e.message:e+""})}try{await y.updateRequest(S,{status:"canceled"}),f.info("Canceled request after workflow failure",{requestId:S}),d.workspaceManager&&(await d.workspaceManager.cancelRequest(S),f.info("Cleaned up branch/worktree after workflow failure",{requestId:S}))}catch(e){f.warn("Failed to cancel request during cleanup",{requestId:S,error:e instanceof Error?e.message:e+""})}throw e}}catch(e){const t=Date.now()-m
|
|
2504
2506
|
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}}}
|
|
2505
2507
|
const r=t(9860),n=t(4079),o=t(9442),s=t(7684),i=t(355),a=t(5715),c=t(7478),l=t(8824)},3807(module){module.exports=require("simple-git")},3884(e,exports,t){Object.defineProperty(exports,"__esModule",{value:!0}),exports.middleware=exports.validateRequest=exports.authenticate=exports.corsOptions=exports.errorHandler=exports.requestLogger=void 0
|
|
2506
2508
|
const r=t(9860),n=t(5674)
|
|
@@ -2573,8 +2575,8 @@ return t},r(e)},function(e){if(e&&e.__esModule)return e
|
|
|
2573
2575
|
var t={}
|
|
2574
2576
|
if(null!=e)for(var s=r(e),i=0;i<s.length;i++)"default"!==s[i]&&n(t,e,s[i])
|
|
2575
2577
|
return o(t,e),t}),i=this&&this.__importDefault||function(e){return e&&e.__esModule?e:{default:e}}
|
|
2576
|
-
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"}),b=m.startTimer("tool_execution_time"),
|
|
2577
|
-
let
|
|
2578
|
+
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"}),b=m.startTimer("tool_execution_time"),k=Date.now()
|
|
2579
|
+
let I,v,C=d.FileOperationPhase.VALIDATION
|
|
2578
2580
|
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"}
|
|
2579
2581
|
try{const r=d.validateArgs(e,l.WriteFileSchema),{taskId:i,path:f,documentId:E,content:q,format:S,append:T,comment:P}=r,R=!!E,M=!!f
|
|
2580
2582
|
w.info("Writing content to "+(R?"document":"file"),{taskId:i,filePath:M?f:void 0,documentId:R?E:void 0,contentLength:"string"==typeof q?q.length:JSON.stringify(q).length,format:S,append:T,comment:P})
|
|
@@ -2598,7 +2600,7 @@ try{await c.default.access(x),$=!0}catch{$=!1,A=!0}w.debug("Path validated with
|
|
|
2598
2600
|
throw e}C=d.FileOperationPhase.RECORD_CREATION,m.incrementCounter("write_file_phase",1,{phase:C})
|
|
2599
2601
|
const{toolRecordId:W}=await d.createFileOperationRecords(i,z,t.projectId,_.recordType,N,{operationType:R?"document":"file",documentId:R?E:void 0,documentFilename:O,filePath:M?j:void 0,contentLength:"string"==typeof q?q.length:JSON.stringify(q).length,format:S||"text",append:T||!1,wasFileCreated:!$,userComment:P},n,o,w,m,_.metricsPrefix,y)
|
|
2600
2602
|
let G
|
|
2601
|
-
if(
|
|
2603
|
+
if(I=W,v=W,C=_.fileOperationPhase,m.incrementCounter("write_file_phase",1,{phase:C}),"json"===S)if("string"==typeof q)try{JSON.parse(q),G=q}catch(e){throw new u.ValidationError("Content is not valid JSON")}else G=JSON.stringify(q,null,2)
|
|
2602
2604
|
else G="string"==typeof q?q:JSON.stringify(q,null,2)
|
|
2603
2605
|
let V=G
|
|
2604
2606
|
if(M&&t.git)try{w.debug("[WRITE-FILE] Checking for user changes before write operation")
|
|
@@ -2609,10 +2611,10 @@ if(await c.default.mkdir(J,{recursive:!0}),await c.default.writeFile(D,V,"utf8")
|
|
|
2609
2611
|
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
|
|
2610
2612
|
if(M){if(C=d.FileOperationPhase.GIT_COMMIT,m.incrementCounter("write_file_phase",1,{phase:C}),t.workspaceManager){const e=t.workspaceManager.getCurrentContext()
|
|
2611
2613
|
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=`${A?"Create":T?"Append to":"Update"} ${j} (${v})`,r=await d.commitToGit(i,j,v,v,e,t,w,m,_.metricsPrefix)
|
|
2612
|
-
K=r.commitHash,Q=r.previousCommitHash,w.info("Changes committed to git via shared utility",{path:j,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:M?j:"document:"+E,status:"completed",finalContentLength:V.length,wasFileCreated:A,wasAppended:T&&$,operationType:R?"document":"file",processingTime:Date.now()-
|
|
2614
|
+
K=r.commitHash,Q=r.previousCommitHash,w.info("Changes committed to git via shared utility",{path:j,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:M?j:"document:"+E,status:"completed",finalContentLength:V.length,wasFileCreated:A,wasAppended:T&&$,operationType:R?"document":"file",processingTime:Date.now()-k,userComment:P,...M&&K&&{commitHash:K,previousCommitHash:Q||void 0}},note:"Write operation completed successfully"+(R?" (document synced)":" (committed to git)")})}catch(e){w.warn("Failed to update tool record",{recordError:e})}let Z=`**${A?"Created":T?"Appended to":"Updated"} ${R?`document ${E}${O?` (${O})`:""}`:"file "+j}**\n`
|
|
2613
2615
|
Z+=`**Content Length:** ${V.length} characters\n`,M&&Y&&(Z+=`**Branch:** ${Y}\n`),U.lockAcquired&&U.lockedRequestId&&(Z+=`**Locked request:** ${U.lockedRequestId}\n`),M&&K&&(Z+=`**Commit Hash:** ${K.substring(0,8)}\n`,Q&&(Z+=`**Previous Commit:** ${Q.substring(0,8)}\n`)),v&&(Z+=`[RECORD:${v}]\n`),R&&(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}\`.`)
|
|
2614
2616
|
const X=Date.now()
|
|
2615
|
-
return w.info("Write operation completed successfully",{duration:X-
|
|
2617
|
+
return w.info("Write operation completed successfully",{duration:X-k,path:M?j:"document:"+E,contentLength:V.length,wasCreated:A}),b({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()-k
|
|
2616
2618
|
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 b({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}}}
|
|
2617
2619
|
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)},4118(e,exports){Object.defineProperty(exports,"__esModule",{value:!0})},4139(e,exports){Object.defineProperty(exports,"__esModule",{value:!0}),exports.ALCHEMY_DIR_NAME=exports.TOKEN_DIR_NAME=void 0,exports.TOKEN_DIR_NAME="alchemy-key",exports.ALCHEMY_DIR_NAME=".alchemy_lab"},4165(e,exports,t){Object.defineProperty(exports,"__esModule",{value:!0}),exports.def=void 0
|
|
2618
2620
|
const r=t(6183),n=t(4648)
|
|
@@ -2783,10 +2785,10 @@ try{let o
|
|
|
2783
2785
|
try{o=i.FileRecoverSchema.parse(e)}catch(t){if(t instanceof a.ZodError){const r="Invalid arguments: "+t.errors.map((e=>e.message)).join(", ")
|
|
2784
2786
|
return p.warn("Validation error",{error:r,args:e}),{content:[{type:"text",text:"\u274c "+r}],isError:!0}}throw t}const{taskId:f,path:y,commitHash:w,createBackup:b}=o
|
|
2785
2787
|
return p.info("Recovering file to previous version",{taskId:f,filePath:y,commitHash:w,createBackup:b}),await async function(e,t,r,n,o,s,i,a,g,p,f){let m
|
|
2786
|
-
try{const{normalizedPath:y,fullPath:w}=d.validateAndNormalizePath(t,o),b=await d.validateTaskId(e,y,s.getTaskClient(),a,g,"file-recover"),{toolRecordId:
|
|
2787
|
-
m=
|
|
2788
|
-
let
|
|
2789
|
-
try{await l.access(w),v=!0,n&&(
|
|
2788
|
+
try{const{normalizedPath:y,fullPath:w}=d.validateAndNormalizePath(t,o),b=await d.validateTaskId(e,y,s.getTaskClient(),a,g,"file-recover"),{toolRecordId:k}=await d.createFileOperationRecords(e,b?.requestId,o.projectId,"file-recover",y,{operationType:"file",filePath:y,commitHash:r,createBackup:n},s.getTaskClient(),i,a,g,"file-recover",f)
|
|
2789
|
+
m=k
|
|
2790
|
+
let I,v=!1
|
|
2791
|
+
try{await l.access(w),v=!0,n&&(I=`${w}.backup-${(new Date).toISOString().replace(/[:.]/g,"-")}`,await l.copyFile(w,I),a.info("Created backup",{originalPath:w,backupPath:I}))}catch{v=!1}const C=o.git
|
|
2790
2792
|
if(!C)throw Error("Git is not available")
|
|
2791
2793
|
if(!(await(0,u.validateCommitHash)(C,r,a,"file-recover")).valid)throw Error(`Commit hash '${r}' is invalid or not found`)
|
|
2792
2794
|
let _
|
|
@@ -2795,9 +2797,9 @@ if(t.includes("does not exist")||t.includes("not found")||t.includes("Path"))thr
|
|
|
2795
2797
|
throw Error(`Failed to retrieve file '${y}' from commit '${r}': ${t}`)}await l.writeFile(w,_,"utf8")
|
|
2796
2798
|
let E={}
|
|
2797
2799
|
try{const t=`Recover ${y} from ${r.substring(0,8)}`
|
|
2798
|
-
E=await d.commitToGit(e,y,m,m,t,o,a,g,"file-recover"),a.info("Recovery committed via shared utility",{path:y,sourceCommitHash:r,newCommitHash:E.commitHash?.substring(0,8),commitMessage:t})}catch(e){a.warn("Failed to commit recovery via shared utility",{error:e})}if(m)try{await i.updateToolRecord(m,{metadata:{path:y,status:"completed",recoveredLength:_.length,hadBackup:n&&v,backupPath:
|
|
2800
|
+
E=await d.commitToGit(e,y,m,m,t,o,a,g,"file-recover"),a.info("Recovery committed via shared utility",{path:y,sourceCommitHash:r,newCommitHash:E.commitHash?.substring(0,8),commitMessage:t})}catch(e){a.warn("Failed to commit recovery via shared utility",{error:e})}if(m)try{await i.updateToolRecord(m,{metadata:{path:y,status:"completed",recoveredLength:_.length,hadBackup:n&&v,backupPath:I,wasFileCreated:!v,processingTime:Date.now()-p,...E.commitHash&&{commitHash:E.commitHash,previousCommitHash:E.previousCommitHash||void 0}},note:"File recovered successfully from "+r.substring(0,8)})}catch(e){a.warn("Failed to update tool record",{recordError:e})}const q=v?"recovered":"created from recovery"
|
|
2799
2801
|
let S=`\u2705 **File ${q.charAt(0).toUpperCase()+q.slice(1)} Successfully**\n\n`
|
|
2800
|
-
return S+=`**File:** ${y}\n`,S+=`**Recovered from:** ${r.substring(0,8)}\n`,S+=`**Content length:** ${_.length} characters\n`,n&&v&&
|
|
2802
|
+
return S+=`**File:** ${y}\n`,S+=`**Recovered from:** ${r.substring(0,8)}\n`,S+=`**Content length:** ${_.length} characters\n`,n&&v&&I&&(S+=`**Backup created:** ${c.basename(I)}\n`),S+="**Git status:** Recovery committed\n",S+="\u{1f4a1} **Tip:** The file has been restored to its state at the specified commit.",a.info("File recovery completed successfully",{path:y,commitHash:r,duration:Date.now()-p}),g.incrementCounter("file_recover_total",1,{success:!0,type:"file"}),{content:[{type:"text",text:S}]}}catch(e){throw e}}(f,y,w,b,t,r,n,p,s,m,g)}catch(e){const t=Date.now()-m
|
|
2801
2803
|
return p.error("Recovery operation failed",{error:e instanceof Error?e.stack:e+"",duration:t}),f({tool:"file_recover",success:!1}),s.incrementCounter("file_recover_errors",1),{content:[{type:"text",text:"\u274c **Recovery Failed:** "+(0,h.getErrorMessage)(e)}],isError:!0}}}
|
|
2802
2804
|
const i=t(6183),a=t(1569),c=s(t(6928)),l=s(t(1943)),d=s(t(5967)),u=t(3922),h=t(8824)},4648(e,exports,t){Object.defineProperty(exports,"__esModule",{value:!0}),exports.handleRequestOperations=async function(e,t,u,h,g,p){const f=h.child({tool:"request_operations"})
|
|
2803
2805
|
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)
|
|
@@ -2945,15 +2947,15 @@ if(/^\d+$/.test(e)){const t=parseInt(e,10)
|
|
|
2945
2947
|
return{start:t,end:t}}const t=e.match(/^(\d+)-(\d+)$/)
|
|
2946
2948
|
if(t)return{start:parseInt(t[1],10),end:parseInt(t[2],10)}
|
|
2947
2949
|
if(e.match(/^(\d+(?:,\d+)+)$/)){const t=e.split(",").map((e=>parseInt(e,10)))
|
|
2948
|
-
return{start:Math.min(...t),end:Math.max(...t)}}return null}(p),
|
|
2949
|
-
let
|
|
2950
|
-
b&&
|
|
2950
|
+
return{start:Math.min(...t),end:Math.max(...t)}}return null}(p),k=["blame","--porcelain"]
|
|
2951
|
+
let I
|
|
2952
|
+
b&&k.push(`-L${b.start},${b.end}`),f&&k.push(f),k.push("--",w),c.debug("Executing git blame",{args:k})
|
|
2951
2953
|
try{if(!t.git)throw Error("Git context not available")
|
|
2952
|
-
|
|
2954
|
+
I=await t.git.raw(k)}catch(e){const t=(0,h.getErrorMessage)(e)
|
|
2953
2955
|
return c.error("Git blame failed",{error:t}),{content:[{type:"text",text:"\u274c Git blame failed: "+t}],isError:!0}}const v=function(e){const t=[],r=e.split("\n")
|
|
2954
2956
|
let n="",o="",s="",i=0,a=0,c=new Map
|
|
2955
2957
|
for(let e=0;e<r.length;e++){const l=r[e],d=l.match(/^([0-9a-f]{40})\s+\d+\s+(\d+)/)
|
|
2956
|
-
d?(n=d[1],a=parseInt(d[2],10)):l.startsWith("author ")?o=l.substring(7):l.startsWith("author-mail ")?s=l.substring(12).replace(/[<>]/g,""):l.startsWith("author-time ")?i=parseInt(l.substring(12),10):l.startsWith("summary ")?c.set(n,l.substring(8)):l.startsWith("\t")&&t.push({lineNumber:a,commitHash:n,author:o,authorEmail:s,timestamp:i,content:l.substring(1),commitMessage:c.get(n)})}return t}(
|
|
2958
|
+
d?(n=d[1],a=parseInt(d[2],10)):l.startsWith("author ")?o=l.substring(7):l.startsWith("author-mail ")?s=l.substring(12).replace(/[<>]/g,""):l.startsWith("author-time ")?i=parseInt(l.substring(12),10):l.startsWith("summary ")?c.set(n,l.substring(8)):l.startsWith("\t")&&t.push({lineNumber:a,commitHash:n,author:o,authorEmail:s,timestamp:i,content:l.substring(1),commitMessage:c.get(n)})}return t}(I)
|
|
2957
2959
|
if(0===v.length)return{content:[{type:"text",text:"\u274c No blame information found for "+w}],isError:!0}
|
|
2958
2960
|
const C=function(e){if(0===e.length)return[]
|
|
2959
2961
|
const t=[]
|
|
@@ -3189,10 +3191,10 @@ const m=g.acceptanceCriteria||[],y={unverified:0,partial:0,verified:0,partially_
|
|
|
3189
3191
|
m.forEach((e=>{const t=e.status||"unverified"
|
|
3190
3192
|
t in y&&y[t]++}))
|
|
3191
3193
|
let w=g.testVerification||null
|
|
3192
|
-
const b=g.title,
|
|
3193
|
-
let
|
|
3194
|
-
return
|
|
3195
|
-
|
|
3194
|
+
const b=g.title,k=g.type
|
|
3195
|
+
let I=`# ${"feature"===k?"Feature":"quick-edit"===k?"Quick Edit":"Bug Fix"} Request: ${b} (${t})\nStatus: ${g.status}\nCreated: ${new Date(g.createdAt).toLocaleString()}\nUpdated: ${new Date(g.updatedAt).toLocaleString()}\n\n## Description\n${g.description||"_No description provided._"}\n\n## Progress Summary\n- Tasks: ${f.completed}/${f.total} completed (${Math.round(f.completed/f.total*100)||0}%)\n- Acceptance Criteria: ${y.verified}/${y.total} verified (${Math.round(y.verified/y.total*100)||0}%)\n`
|
|
3196
|
+
return I+=`\n## Task Status\n- Pending: ${f.pending}\n- In Progress: ${f.in_progress}\n- Blocked: ${f.blocked}\n- Ready for Review: ${f.ready_for_review}\n- Completed: ${f.completed}\n- Reverted: ${f.reverted}\n`,I+="\n## Tasks\n",0===p.length?I+="No tasks found for this request.\n":p.forEach((e=>{I+=`**[${e.id}]** ${e.title} (Status: ${e.status})\n`})),d.info(`Added task listing with ${p.length} tasks`),I+="\n## Acceptance Criteria\n",I+=(0,i.formatCriteriaWithHashes)(m)+"\n","ready_for_review"===g.status&&m.some((e=>"verified"!==e.status))&&(I+="\n> **Status: ready_for_review** \u2014 Use the merge operation to verify criteria and merge to main.\n"),w&&(I+=`\n## Test Coverage\n- Test Cases: ${w.totalTestCases||0}\n- Criteria Tested: ${w.criteriaTestedCount||0}/${y.total}\n`,w.criterionCoverage&&Array.isArray(w.criterionCoverage)&&(I+="\n### Detailed Test Coverage:\n",w.criterionCoverage.forEach((e=>{I+=`- Criterion ${e.criterionId}: ${e.coverage} coverage\n`})))),g.recentActivity&&Array.isArray(g.recentActivity)&&(I+="\n## Recent Activity\n",g.recentActivity.slice(0,5).forEach((e=>{const t=new Date(e.timestamp).toLocaleString()
|
|
3197
|
+
I+=`- ${t}: ${e.description}\n`}))),u({success:!0}),{content:[{type:"text",text:I}]}}catch(t){return d.error("Error getting request information",{args:e,error:t instanceof Error?t.stack:t+""}),u({success:!1,error:t instanceof Error?t.name:"unknown"}),t instanceof n.ConnectionError?{content:[{type:"text",text:"Unable to get request information: Connection to the server failed. Please check your network connection and try again."}],isError:!0}:{content:[{type:"text",text:"Error getting request information: "+(0,s.getErrorMessage)(t)}],isError:!0}}}
|
|
3196
3198
|
const r=t(9860),n=t(5674),o=t(2960),s=t(8824),i=t(5454)},5454(e,exports){function t(e,t){let r=0
|
|
3197
3199
|
for(let t=0;t<e.length;t++)r=(r<<5)-r+e.charCodeAt(t)|0
|
|
3198
3200
|
return`${t+1}${String.fromCharCode(97+Math.abs(r)%26)}`}function r(e){const r=new Map
|
|
@@ -3290,25 +3292,25 @@ if(t){const e=Date.now()-t
|
|
|
3290
3292
|
try{this.metrics.observeHistogram("offline_duration_ms",e,{reconnection_type:"manual"}),this.logger.info(`System was offline for ${Math.round(e/1e3)} seconds before manual reconnection`)}catch(e){this.logger.warn("Error observing histogram for offline duration on manual reconnection",{error:e instanceof Error?e.message:e+""})}}}}catch(e){this.logger.warn("Error calculating offline duration during manual mode change",{error:(0,s.getErrorMessage)(e)})}this.notifyOnlineStatus()}else!t&&e&&(this.logger.info("Manually setting connection mode to OFFLINE"),this.safeSetGauge("connection_status",0),this.safeSetGauge("last_connection_failure_timestamp",Date.now()),this.safeIncrementCounter("manual_disconnections",1),process.nextTick((()=>{exports.eventBus.emit(exports.EVENTS.OFFLINE,{timestamp:(new Date).toISOString()})})))}isOffline(){return this.isInOfflineMode()}async checkConnectivity(){return this.logger.debug("Explicit connectivity check requested"),this.healthCheckManager.requestHealthCheck()}getHealthCheckStats(){const e=this.healthCheckManager.getStats()
|
|
3291
3293
|
return{isOffline:this.isInOfflineMode(),consecutiveFailures:e.consecutiveFailures,currentBackoffMs:e.currentBackoffMs,lastCheckTime:e.lastCheckTime}}cleanup(){this.logger.debug("Cleaning up connection status manager resources"),this.healthCheckManager.stopHealthChecks(),exports.eventBus.removeAllListeners(exports.EVENTS.ONLINE),exports.eventBus.removeAllListeners(exports.EVENTS.OFFLINE)}}},5692(e,exports,t){Object.defineProperty(exports,"__esModule",{value:!0}),exports.def=void 0
|
|
3292
3294
|
const r=t(6183),n=t(2965)
|
|
3293
|
-
exports.def={name:"read_files",description:'Read the contents of multiple files and documents with flexible line selection.\n\nLINE SELECTION (string format):\n- Single line: "lines": "5"\n- Multiple lines: "lines": "1,3,7,10"\n- Range: "lines": "5-15"\n- Entire file: omit "lines" parameter\n\nEXAMPLES:\n- Read first 10 lines: {"path": "file.txt", "lines": "1-10"}\n- Read specific lines: {"path": "file.txt", "lines": "1,5,25"}\n- Read line 42 only: {"path": "file.txt", "lines": "42"}\n- Read entire file: {"path": "file.txt"}\n\nSupports both filesystem files (using \'path\') and tracked documents (using \'documentId\'). More efficient than reading files one by one. Failed reads won\'t stop the entire operation.',schema:r.ReadFilesSchema,annotations:{title:"Read Files/Documents",readOnlyHint:!0},readOnly:!0,handler(e,t){return(0,n.handleReadFiles)(e,t.context,t.logger,t.metrics)}}},5715(e,exports,t){Object.defineProperty(exports,"__esModule",{value:!0}),exports.handleCompleteRequest=async function(e,t,c,l,d,u
|
|
3294
|
-
try{const{requestId:
|
|
3295
|
-
if(!
|
|
3296
|
-
if(!
|
|
3297
|
-
|
|
3298
|
-
const
|
|
3299
|
-
let
|
|
3300
|
-
try{const e=await
|
|
3301
|
-
|
|
3302
|
-
return
|
|
3303
|
-
return
|
|
3304
|
-
try{await
|
|
3305
|
-
return
|
|
3306
|
-
try{
|
|
3307
|
-
return
|
|
3308
|
-
return
|
|
3309
|
-
r instanceof
|
|
3310
|
-
try{await(0,
|
|
3311
|
-
const r=t(9860),n=t(
|
|
3295
|
+
exports.def={name:"read_files",description:'Read the contents of multiple files and documents with flexible line selection.\n\nLINE SELECTION (string format):\n- Single line: "lines": "5"\n- Multiple lines: "lines": "1,3,7,10"\n- Range: "lines": "5-15"\n- Entire file: omit "lines" parameter\n\nEXAMPLES:\n- Read first 10 lines: {"path": "file.txt", "lines": "1-10"}\n- Read specific lines: {"path": "file.txt", "lines": "1,5,25"}\n- Read line 42 only: {"path": "file.txt", "lines": "42"}\n- Read entire file: {"path": "file.txt"}\n\nSupports both filesystem files (using \'path\') and tracked documents (using \'documentId\'). More efficient than reading files one by one. Failed reads won\'t stop the entire operation.',schema:r.ReadFilesSchema,annotations:{title:"Read Files/Documents",readOnlyHint:!0},readOnly:!0,handler(e,t){return(0,n.handleReadFiles)(e,t.context,t.logger,t.metrics)}}},5715(e,exports,t){Object.defineProperty(exports,"__esModule",{value:!0}),exports.handleCompleteRequest=async function(e,t,a,c,l,d,u){const h=c.child({tool:"complete_request"}),g=l.startTimer("tool_execution_time")
|
|
3296
|
+
try{const{requestId:n,summary:o}=e
|
|
3297
|
+
if(!n)throw(0,r.createValidationError)("Request ID is required")
|
|
3298
|
+
if(!o)throw(0,r.createValidationError)("Summary is required")
|
|
3299
|
+
h.info("Starting request completion",{requestId:n})
|
|
3300
|
+
const c=u?.sessionId
|
|
3301
|
+
let l
|
|
3302
|
+
try{const e=await a.proxyPost(`/api/projects/${t.projectId}/requests/${n}/validate-completion`,{sessionId:c})
|
|
3303
|
+
l=e?.data||e}catch(e){const t=(0,s.getErrorMessage)(e)
|
|
3304
|
+
return h.error("Server validation failed",{requestId:n,error:t}),g({success:!1,error:"validation_request_failed"}),{content:[{type:"text",text:"Failed to validate completion: "+t}],isError:!0}}if(!l.canComplete){let e=`Cannot complete request ${n}: ${l.reason}\n`
|
|
3305
|
+
return l.blockedByTasks&&l.blockedByTasks.length>0&&(e+="\n**Tasks that must be completed or canceled first:**\n",l.blockedByTasks.forEach(((t,r)=>{e+=`${r+1}. **${t.taskId}** - ${t.title} (Status: ${t.status})\n`}))),l.lifoViolation&&(e+="\n**Requests that must be re-completed first (LIFO order):**\n",l.lifoViolation.blockingRequests.forEach(((t,r)=>{e+=`${r+1}. **${t.requestId}** - ${t.title} (Status: ${t.status})\n`}))),g({success:!1,reason:"server_blocked"}),{content:[{type:"text",text:e}],isError:!0}}const d=a.getRequestClient(),p="auto-test-then-merge"===l.completionMode,f=p?"ready_for_review":"ready_for_merge"
|
|
3306
|
+
try{await d.updateRequest(n,{status:f,completionSummary:o})}catch(e){const t=(0,s.getErrorMessage)(e)
|
|
3307
|
+
return g({success:!1,error:"status_transition_failed"}),{content:[{type:"text",text:"Failed to transition request: "+t}],isError:!0}}let m
|
|
3308
|
+
try{m=await d.getRequest(n)}catch(e){const t=(0,s.getErrorMessage)(e)
|
|
3309
|
+
return g({success:!1,error:"fetch_request_failed"}),{content:[{type:"text",text:"Failed to fetch request criteria: "+t}],isError:!0}}const y=m?.acceptanceCriteria||[]
|
|
3310
|
+
return g({success:!0}),p?{content:[{type:"text",text:`Request ${n} moved to ready_for_review. Testing is active \u2014 a notification has been created for the user to choose testing mode. Do NOT call merge or any other tool. Your work is done. Stop here and wait.`}]}:0===y.length?{content:[{type:"text",text:`Request ${n} is ready. No acceptance criteria defined \u2014 call merge directly.`}]}:{content:[{type:"text",text:`Request ${n} completion started (${f}).\n\n## Next Step: Verify & Merge\n\n${(0,i.formatVerifyInstructions)(y)}\n\nUse the merge operation with your verification evidence to merge to main.`}]}}catch(r){let s="An unexpected error occurred",i=""
|
|
3311
|
+
r instanceof n.ZodError?(s="Validation error",i=r.errors.map((e=>`${e.path.join(".")}: ${e.message}`)).join(", ")):r instanceof Error?(s=r.message,i=r.stack||""):i=r+"",h.error("Complete request failed",{error:s,details:i})
|
|
3312
|
+
try{await(0,o.createFailureToolRecord)("complete-request",r,{error:s,details:i,requestId:e?.requestId},a.getToolRecordClient(),h,l,{requestId:e?.requestId,projectId:t.projectId,note:"Failed to complete request"})}catch{}return l.startTimer("tool_execution_time")({success:!1,error:r instanceof Error?r.name:"unknown"}),{content:[{type:"text",text:"Error: "+s}],isError:!0}}}
|
|
3313
|
+
const r=t(9860),n=t(1569),o=t(8616),s=t(8824),i=t(5454)},5767(e,exports,t){Object.defineProperty(exports,"__esModule",{value:!0}),exports.def=void 0
|
|
3312
3314
|
const r=t(6183),n=t(6285)
|
|
3313
3315
|
exports.def={name:"specialist_ops",description:"Manage your pool of up to 10 specialists. Each has a specialization describing their domain. Reuse specialists via follow-up before spawning new ones.\n\nOperations:\n\u2022 delegate - Spawn a new specialist (include specialization). Abort an idle specialist first if pool is full.\n\u2022 follow-up - Send follow-up instructions to an existing specialist (can update specialization)\n\u2022 check-status - Check if a specialist is busy or idle\n\u2022 list - List specialist sessions with specializations\n\u2022 abort - Cancel a stuck specialist",schema:r.SpecialistOpsSchema,annotations:{title:"Specialist Operations",readOnlyHint:!1,destructiveHint:!1,idempotentHint:!1},handler(e,t){return(0,n.handleSpecialistOps)(e,t.context,t.logger,t.metrics,t.apiClient??void 0,t.cliOrigin)}}},5802(module){module.exports=require("@modelcontextprotocol/sdk/server/stdio.js")},5806(e,exports,t){function r(){const e=n.z.object({requestId:n.z.string(),summary:n.z.string(),acceptanceEvidence:n.z.array(n.z.object({evidence:n.z.string()}))}),t=n.z.object({testRecords:n.z.array(n.z.string()),coverage:n.z.object({criteriaTestedCount:n.z.number(),totalTestCases:n.z.number()}),criterionCoverage:n.z.array(n.z.object({coverage:n.z.enum(["none","partial","full"]),testRecords:n.z.array(n.z.string())}))})
|
|
3314
3316
|
return(0,o.areTestsRequiredForCompletion)()?e.extend({testVerification:t}):e}Object.defineProperty(exports,"__esModule",{value:!0}),exports.DynamicCompleteRequestSchema=void 0,exports.getDynamicCompleteRequestSchema=r
|
|
@@ -3327,8 +3329,8 @@ if(null!=e)for(var s=r(e),i=0;i<s.length;i++)"default"!==s[i]&&n(t,e,s[i])
|
|
|
3327
3329
|
return o(t,e),t}),i=this&&this.__importDefault||function(e){return e&&e.__esModule?e:{default:e}}
|
|
3328
3330
|
Object.defineProperty(exports,"__esModule",{value:!0}),exports.handleDeleteFiles=async function(e,t,r,n,o,s){const i=n.child({tool:"delete_files"}),m=Date.now()
|
|
3329
3331
|
let y,w,b=l.FileOperationPhase.VALIDATION
|
|
3330
|
-
const
|
|
3331
|
-
try{const n=r.getTaskClient(),u=r.getToolRecordClient(),
|
|
3332
|
+
const k={toolName:"delete-files",operationName:"delete",fileOperationPhase:l.FileOperationPhase.FILE_WRITE,recordType:"delete-files",metricsPrefix:"delete_files",successMessage:"Successfully deleted files",failureMessage:"Failed to delete files"}
|
|
3333
|
+
try{const n=r.getTaskClient(),u=r.getToolRecordClient(),I=r.getRequestClient(),v=l.validateArgs(e,c.DeleteFilesSchema),{taskId:C,paths:_,operations:E,comment:q}=v
|
|
3332
3334
|
let S=[]
|
|
3333
3335
|
if(_)S=_.map((e=>({type:"file",target:e})))
|
|
3334
3336
|
else{if(!E)throw Error("Either paths or operations must be specified")
|
|
@@ -3336,22 +3338,22 @@ S=E.map((e=>{if(e.path)return{type:"file",target:e.path}
|
|
|
3336
3338
|
if(e.documentId)return{type:"document",target:e.documentId}
|
|
3337
3339
|
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")
|
|
3338
3340
|
const T=S.filter((e=>"file"===e.type)),P=S.filter((e=>"document"===e.type)),R=S.length
|
|
3339
|
-
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,
|
|
3341
|
+
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,k.metricsPrefix)
|
|
3340
3342
|
const M=t.getCurrentBranchContext?await t.getCurrentBranchContext():{branch:null,requestId:null,isMain:!0}
|
|
3341
3343
|
i.info("Initial branch context",{initialBranch:M.branch,initialRequestId:M.requestId,isMain:M.isMain})
|
|
3342
3344
|
const j=[]
|
|
3343
3345
|
for(const e of T){const{normalizedPath:r,fullPath:n}=l.validateAndNormalizePath(e.target,t)
|
|
3344
3346
|
j.push({normalized:r,full:n})}b=l.FileOperationPhase.TASK_VALIDATION,o.incrementCounter("delete_files_phase",1,{phase:b})
|
|
3345
|
-
const x=j.length>0?j[0].normalized:"document_operations",O=await l.validateTaskId(C,x,n,i,o,
|
|
3347
|
+
const x=j.length>0?j[0].normalized:"document_operations",O=await l.validateTaskId(C,x,n,i,o,k.metricsPrefix),D=O?.requestId,A=await l.validateWorkItemStates(C,x,n,I,t,i,o,k.metricsPrefix),$=await l.autoPromoteTaskStatus(C,O.status,D,A.request?.status,x,n,I,i,o,k.metricsPrefix)
|
|
3346
3348
|
$.taskPromoted&&i.info(`Auto-promoted task ${C} (${O.title||"Untitled"}) to in_progress for mixed operations`,{taskId:C,taskTitle:O.title,previousStatus:O.status,newStatus:$.newTaskStatus,totalOperations:S.length,fileOperations:T.length,documentOperations:P.length}),$.requestPromoted&&i.info(`Auto-promoted request ${D} to in_progress for file operations`,{requestId:D,previousStatus:A.request?.status,newStatus:$.newRequestStatus,triggeringTaskId:C})
|
|
3347
|
-
const F=await l.ensureCorrectWorkspaceContext({taskPromoted:$.taskPromoted,requestId:D,context:t,operation:"delete-files",logger:i,metrics:o,metricsPrefix:
|
|
3349
|
+
const F=await l.ensureCorrectWorkspaceContext({taskPromoted:$.taskPromoted,requestId:D,context:t,operation:"delete-files",logger:i,metrics:o,metricsPrefix:k.metricsPrefix})
|
|
3348
3350
|
if(!F.success){if(F.isLockConflict)return{content:[{type:"text",text:"\u274c "+F.error}],isError:!0}
|
|
3349
3351
|
throw Error(F.error)}let N={hadUserMods:!1,userModsCommitHash:void 0}
|
|
3350
3352
|
if(t.git)try{i.debug("[DELETE-FILES] Checking for user changes before mixed delete operations")
|
|
3351
3353
|
const e=await(0,h.commitUserChangesBeforeToolOperation)(t.git,"delete-files",{requestId:D,taskId:C,workspaceManager:t.workspaceManager},i,o)
|
|
3352
3354
|
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}),b=l.FileOperationPhase.RECORD_CREATION,o.incrementCounter("delete_files_phase",1,{phase:b})
|
|
3353
|
-
const{toolRecordId:L,localToolRecordId:z}=await l.createFileOperationRecords(C,D,t.projectId,
|
|
3354
|
-
y=L,w=L,b=
|
|
3355
|
+
const{toolRecordId:L,localToolRecordId:z}=await l.createFileOperationRecords(C,D,t.projectId,k.recordType,x,{totalOperations:S.length,fileOperations:T.length,documentOperations:P.length,filePaths:j.map((e=>e.normalized)),documentIds:P.map((e=>e.target)),userComment:q,hadUserMods:N.hadUserMods,userModsCommitHash:N.userModsCommitHash},n,u,i,o,k.metricsPrefix,s)
|
|
3356
|
+
y=L,w=L,b=k.fileOperationPhase,o.incrementCounter("delete_files_phase",1,{phase:b})
|
|
3355
3357
|
const B=[]
|
|
3356
3358
|
let H=0
|
|
3357
3359
|
P.length>0&&r.setProjectId(t.projectId)
|
|
@@ -3360,7 +3362,7 @@ try{try{await a.default.access(t.full)}catch(e){throw Error("File not found: "+t
|
|
|
3360
3362
|
await a.default.unlink(t.full),r.success=!0,H++,i.info("Successfully deleted file",{path:t.normalized})}catch(e){r.error=(0,f.getErrorMessage)(e),i.warn("Failed to delete file "+t.normalized,{error:r.error})}B.push(r)}const U=P.length>0?r.getDocumentClient():null
|
|
3361
3363
|
for(const e of P){const t=e.target,n={type:"document",documentId:t,success:!1,replacements:[],successfulReplacements:0,failedReplacements:0}
|
|
3362
3364
|
try{let e
|
|
3363
|
-
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,
|
|
3365
|
+
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,I,i,o,"delete-document")}catch(e){if(e instanceof d.ValidationError)throw Error(e.message)
|
|
3364
3366
|
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)
|
|
3365
3367
|
throw e}}catch(e){throw Error(`Document not found or validation failed: ${t}. ${(0,f.getErrorMessage)(e)}`)}const s=await U.archiveDocument(t)
|
|
3366
3368
|
n.success=!0,n.filename=s.filename,H++,i.info("Document archived successfully",{documentId:s.id,filename:s.filename,archivedAt:s.archived_at})}catch(e){n.error=(0,f.getErrorMessage)(e),i.warn("Failed to delete document "+t,{error:n.error})}B.push(n)}const W=Date.now()-m
|
|
@@ -3369,9 +3371,9 @@ let G=null
|
|
|
3369
3371
|
if(H>0){b=l.FileOperationPhase.GIT_COMMIT,o.incrementCounter("delete_files_phase",1,{phase:b})
|
|
3370
3372
|
const e=B.filter((e=>e.success)),r=e.filter((e=>"file"===e.type)).length,n=e.filter((e=>"document"===e.type)).length
|
|
3371
3373
|
let s
|
|
3372
|
-
s=r>0&&n>0?`Delete ${r} files and ${n} documents - ${q}`:r>0?1===r?"Delete file - "+q:`Delete ${r} files - ${q}`:1===n?"Delete document - "+q:`Delete ${n} documents - ${q}`,G=await l.commitToGit(C,x,L,z,s,t,i,o,
|
|
3374
|
+
s=r>0&&n>0?`Delete ${r} files and ${n} documents - ${q}`:r>0?1===r?"Delete file - "+q:`Delete ${r} files - ${q}`:1===n?"Delete document - "+q:`Delete ${n} documents - ${q}`,G=await l.commitToGit(C,x,L,z,s,t,i,o,k.metricsPrefix)}b=l.FileOperationPhase.RECORD_UPDATE_SUCCESS,o.incrementCounter("delete_files_phase",1,{phase:b})
|
|
3373
3375
|
const V=B.filter((e=>e.success)),J=B.filter((e=>!e.success))
|
|
3374
|
-
await l.updateFileOperationRecords(C,y,w,x,
|
|
3376
|
+
await l.updateFileOperationRecords(C,y,w,x,k.recordType,H===R?`Successfully deleted all ${R} operations`:`Deleted ${H}/${R} operations successfully`,{status:H===R?"completed":"partial_success",commitHash:G?.commitHash,previousCommitHash:G?.previousCommitHash,totalOperations:R,fileOperations:T.length,documentOperations:P.length,successCount:H,failureCount:R-H,successfulOperations:V.map((e=>({type:e.type,path:e.path,documentId:e.documentId,filename:e.filename}))),failedOperations:J.map((e=>({type:e.type,path:e.path,documentId:e.documentId,filename:e.filename,error:e.error}))),userComment:q,hadUserMods:N.hadUserMods,userModsCommitHash:N.userModsCommitHash},H===R?`Successfully deleted all ${R} operations`:`Deleted ${H}/${R} operations successfully`,n,u,i,o,k.metricsPrefix)
|
|
3375
3377
|
const K=t.getCurrentBranchContext?await t.getCurrentBranchContext():{branch:null,requestId:null,isMain:!0}
|
|
3376
3378
|
let Y=""
|
|
3377
3379
|
if(H===R){const e=V.filter((e=>"file"===e.type)).length,t=V.filter((e=>"document"===e.type)).length
|
|
@@ -3382,7 +3384,7 @@ return G?.commitHash&&(Y+="\nCommit: "+G.commitHash.substring(0,8)),K.requestId&
|
|
|
3382
3384
|
await o.createToolRecord({...s?{}:{taskId:e.taskId},projectId:t.projectId,type:"delete-files",metadata:{status:"failed",timestamp:(new Date).toISOString(),totalOperations:e.operations?.length||e.paths?.length||0,fileOperations:e.paths?.length||e.operations?.filter((e=>e.path))?.length||0,documentOperations:e.operations?.filter((e=>e.documentId))?.length||0,paths:e.paths||e.operations?.filter((e=>e.path))?.map((e=>e.path))||[],documentIds:e.operations?.filter((e=>e.documentId))?.map((e=>e.documentId))||[],userComment:e.comment,error:(0,f.getErrorMessage)(n),errorDetails:n instanceof Error?n.stack:n+"",phase:b,attemptedTaskId:e.taskId,taskIdValidationFailed:s},note:"Failed to delete files - "+(0,f.getErrorMessage)(n)})}catch(t){i.error("Failed to create failure record for delete-files operation",{error:t instanceof Error?t.message:t+"",taskId:e.taskId,totalOperations:e.operations?.length||e.paths?.length||0,fileOperations:e.paths?.length||e.operations?.filter((e=>e.path))?.length||0,documentOperations:e.operations?.filter((e=>e.documentId))?.length||0})}const s=Date.now()-m
|
|
3383
3385
|
if(o.recordValue("delete_files_time",s),o.incrementCounter("delete_files_errors",1),i.error("Error in delete-files operation:",{error:(0,f.getErrorMessage)(n),time:s}),(y||w)&&e.taskId){b=l.FileOperationPhase.RECORD_UPDATE_FAILURE
|
|
3384
3386
|
try{const t=r.getTaskClient(),s=r.getToolRecordClient()
|
|
3385
|
-
await l.updateFileOperationRecords(e.taskId,y,w,e.paths?.[0]||e.operations?.[0]?.path||e.operations?.[0]?.documentId||"unknown",
|
|
3387
|
+
await l.updateFileOperationRecords(e.taskId,y,w,e.paths?.[0]||e.operations?.[0]?.path||e.operations?.[0]?.documentId||"unknown",k.recordType,"Failed to delete operations",{status:"failed",error:(0,f.getErrorMessage)(n),totalOperations:e.operations?.length||e.paths?.length||0,fileOperations:e.paths?.length||e.operations?.filter((e=>e.path))?.length||0,documentOperations:e.operations?.filter((e=>e.documentId))?.length||0,paths:e.paths||e.operations?.filter((e=>e.path))?.map((e=>e.path))||[],documentIds:e.operations?.filter((e=>e.documentId))?.map((e=>e.documentId))||[],userComment:e.comment},"Failed to delete operations",t,s,i,o,k.metricsPrefix)}catch(t){i.error("Failed to update record with failure status",{taskId:e.taskId,recordId:y,error:t instanceof Error?t.message:t+""})}}return l.handleFileOperationError(n,b,i,o,e,k)}}
|
|
3386
3388
|
const a=i(t(1943)),c=t(6183),l=s(t(5967)),d=t(9860),u=t(1569),h=t(7478),g=t(5003),p=t(9949),f=t(8824)},5997(e,exports,t){var r,n=this&&this.__createBinding||(Object.create?function(e,t,r,n){void 0===n&&(n=r)
|
|
3387
3389
|
var o=Object.getOwnPropertyDescriptor(t,r)
|
|
3388
3390
|
o&&!("get"in o?!t.__esModule:o.writable||o.configurable)||(o={enumerable:!0,get(){return t[r]}}),Object.defineProperty(e,n,o)}:function(e,t,r,n){void 0===n&&(n=r),e[n]=t[r]}),o=this&&this.__setModuleDefault||(Object.create?function(e,t){Object.defineProperty(e,"default",{enumerable:!0,value:t})}:function(e,t){e.default=t}),s=this&&this.__importStar||(r=function(e){return r=Object.getOwnPropertyNames||function(e){var t=[]
|
|
@@ -3466,15 +3468,13 @@ return t},r(e)},function(e){if(e&&e.__esModule)return e
|
|
|
3466
3468
|
var t={}
|
|
3467
3469
|
if(null!=e)for(var s=r(e),i=0;i<s.length;i++)"default"!==s[i]&&n(t,e,s[i])
|
|
3468
3470
|
return o(t,e),t})
|
|
3469
|
-
Object.defineProperty(exports,"__esModule",{value:!0}),exports.handleSpecialistOps=async function(e,r,n,o,s,
|
|
3471
|
+
Object.defineProperty(exports,"__esModule",{value:!0}),exports.handleSpecialistOps=async function(e,r,n,o,s,p){const f=n.child({tool:"specialist_ops"}),m=o.startTimer("tool_execution_time")
|
|
3470
3472
|
try{if(!e?.operation&&e&&(e.prompt&&!e.sessionId?e.operation="delegate":e.prompt&&e.sessionId?e.operation="follow-up":e.sessionId&&(e.operation="check-status")),e?.followUp&&"string"==typeof e.followUp)try{e.followUp=JSON.parse(e.followUp)}catch{}if(e?.delegate&&"string"==typeof e.delegate)try{e.delegate=JSON.parse(e.delegate)}catch{}if("string"==typeof e?.delegate){const t=e.delegate
|
|
3471
3473
|
e.delegate={prompt:e.prompt||t,description:e.description||t.slice(0,60),specialization:e.specialization||"general",requestId:e.requestId},e.operation=e.operation||"delegate",delete e.prompt,delete e.description,delete e.specialization,delete e.requestId}"follow-up"===e?.operation&&e?.prompt&&!e?.followUp&&(e.followUp={prompt:e.prompt,specialization:e.specialization},delete e.prompt,e.specialization&&delete e.specialization),"delegate"===e?.operation&&e?.prompt&&!e?.delegate&&(e.delegate={prompt:e.prompt,description:e.description||e.prompt.slice(0,60),specialization:e.specialization||"general",requestId:e.requestId},delete e.prompt,delete e.description,delete e.specialization,delete e.requestId)
|
|
3472
|
-
const n=c.validateArgs(e,a.SpecialistOpsSchema),{operation:
|
|
3473
|
-
let
|
|
3474
|
-
switch(
|
|
3475
|
-
|
|
3476
|
-
if(!i){const e=await(0,h.getServerUrl)(r,m)
|
|
3477
|
-
if(e)try{i=(0,g.getCachedSession)()?.sessionId||await(0,h.discoverParentSessionId)(e,m)}catch{}}if(i&&s){const e=await async function(e,t,r,n,o){n.info("enforcePoolLimit called",{parentSessionId:e,maxPoolSize:t})
|
|
3474
|
+
const n=c.validateArgs(e,a.SpecialistOpsSchema),{operation:y,sessionId:w}=n
|
|
3475
|
+
let b
|
|
3476
|
+
switch(f.info("Processing specialist_ops",{operation:y,sessionId:w}),y){case"delegate":{const e=n.delegate,o=10,i=p?.sessionId||g.sessionIdentity.getIdentity()?.sessionId
|
|
3477
|
+
if(i&&s){const e=await async function(e,t,r,n,o){n.info("enforcePoolLimit called",{parentSessionId:e,maxPoolSize:t})
|
|
3478
3478
|
const s=await(0,h.getServerUrl)(r,n)
|
|
3479
3479
|
if(s)try{const r=await fetch(s.replace(/\/$/,"")+"/session")
|
|
3480
3480
|
if(!r.ok)return
|
|
@@ -3487,34 +3487,33 @@ return"specialist"===t?.agentType&&"archived"!==t?.status}))
|
|
|
3487
3487
|
if(n.info("Pool check: specialist count",{specialistCount:h.length,maxPoolSize:t}),h.length<t)return
|
|
3488
3488
|
const g=h.map((e=>{const t=l[e.id],r=u[e.id]?.type||"idle",n=t?.specialization||"(none)"
|
|
3489
3489
|
return` \u2022 ${e.id} \u2014 ${n} [${r}]`})).join("\n")
|
|
3490
|
-
return{content:[{type:"text",text:`\u274c Specialist pool is full (${h.length}/${t}).\nAbort an idle specialist first with \`specialist_ops abort\`, then delegate again.\n\nCurrent pool:\n`+g}],isError:!0}}catch(e){return void n.warn("Pool limit check failed, allowing spawn",{error:(0,l.getErrorMessage)(e)})}}(i,o,r,
|
|
3491
|
-
if(e){
|
|
3490
|
+
return{content:[{type:"text",text:`\u274c Specialist pool is full (${h.length}/${t}).\nAbort an idle specialist first with \`specialist_ops abort\`, then delegate again.\n\nCurrent pool:\n`+g}],isError:!0}}catch(e){return void n.warn("Pool limit check failed, allowing spawn",{error:(0,l.getErrorMessage)(e)})}}(i,o,r,f,s)
|
|
3491
|
+
if(e){b=e
|
|
3492
3492
|
break}}let a=e.description
|
|
3493
|
-
const c=await Promise.resolve().then(t.t.bind(t,9896,23)),
|
|
3494
|
-
if(i)try{const e=await(0,h.getServerUrl)(r,
|
|
3495
|
-
if(
|
|
3496
|
-
if(
|
|
3497
|
-
|
|
3493
|
+
const c=await Promise.resolve().then(t.t.bind(t,9896,23)),m=e=>c.appendFileSync("/tmp/specialist-name-debug.log",`${(new Date).toISOString()} ${e}\n`)
|
|
3494
|
+
if(i)try{const e=await(0,h.getServerUrl)(r,f)
|
|
3495
|
+
if(m(`serverUrl=${e}, parentId=${i}`),e){const t=await fetch(e.replace(/\/$/,"")+"/session")
|
|
3496
|
+
if(m("session fetch status="+t.status),t.ok){const e=(await t.json()).filter((e=>(e.parentId||e.parentID)===i)).map((e=>e.title||""))
|
|
3497
|
+
m(`siblings=${e.length}: ${e.join(", ")}`)
|
|
3498
3498
|
const r=(0,d.pickSpecialistName)(e)
|
|
3499
|
-
a=r,
|
|
3500
|
-
const
|
|
3501
|
-
|
|
3502
|
-
break}case"follow-up":{const e=await(0,h.getServerUrl)(r,
|
|
3499
|
+
a=r,m("picked name: "+r)}}else m("no serverUrl")}catch(e){m("error: "+(e instanceof Error?e.message:e+""))}else m("no parentId")
|
|
3500
|
+
const y=e.requestId,w=y?`Working on request ${y}.\n\n${e.prompt}`:e.prompt
|
|
3501
|
+
b=await(0,u.handleSpawn)({agent:"specialist",prompt:w,title:a,specialization:e.specialization},r,f,s,p)
|
|
3502
|
+
break}case"follow-up":{const e=await(0,h.getServerUrl)(r,f)
|
|
3503
3503
|
if(e)try{const t=await fetch(e.replace(/\/$/,"")+"/session/status")
|
|
3504
|
-
if(t.ok){const e=await t.json(),r=e[
|
|
3505
|
-
if(r&&"idle"!==r&&"prompting"!==r){
|
|
3506
|
-
break}}}catch{}
|
|
3504
|
+
if(t.ok){const e=await t.json(),r=e[w]?.type
|
|
3505
|
+
if(r&&"idle"!==r&&"prompting"!==r){b={content:[{type:"text",text:`\u274c Specialist ${w} is currently busy (status: ${r}).\nUse \`delegate\` to spawn a new specialist instead.`}],isError:!0}
|
|
3506
|
+
break}}}catch{}b=await(0,u.handleContinue)(w,n.followUp.prompt,r,f,s,"specialist",p)
|
|
3507
3507
|
const t=n.followUp.specialization
|
|
3508
3508
|
if(t&&s)try{const e=s.getCLISessionClient()
|
|
3509
|
-
e&&(await e.createOrUpdateSession({externalSessionId:
|
|
3509
|
+
e&&(await e.createOrUpdateSession({externalSessionId:w,specialization:t}),b.content[0].text+="\nSpecialization updated to: "+t)}catch{}break}case"check-status":b=await(0,u.handleCheckStatus)(w,r,f,s)
|
|
3510
3510
|
break
|
|
3511
|
-
case"abort":if(
|
|
3512
|
-
e&&await e.createOrUpdateSession({externalSessionId:
|
|
3513
|
-
case"list":{
|
|
3514
|
-
|
|
3515
|
-
|
|
3516
|
-
|
|
3517
|
-
const i=t(9860),a=t(6183),c=s(t(5967)),l=t(8824),d=t(9089),u=t(1725),h=t(7617),g=t(715),p=t(6688)},6315(e,exports,t){Object.defineProperty(exports,"__esModule",{value:!0}),exports.def=void 0
|
|
3511
|
+
case"abort":if(b=await(0,u.handleAbort)(w,r,f),!b.isError&&s)try{const e=s.getCLISessionClient()
|
|
3512
|
+
e&&await e.createOrUpdateSession({externalSessionId:w,status:"archived"})}catch{}break
|
|
3513
|
+
case"list":{const e=p?.sessionId||g.sessionIdentity.getIdentity()?.sessionId
|
|
3514
|
+
b=await(0,u.handleListSessions)(r,f,s,{activeOnly:n.list?.activeOnly,requestId:n.list?.requestId,limit:n.list?.limit,agentType:"specialist",parentSessionId:e})
|
|
3515
|
+
break}default:throw new i.ValidationError("Unknown operation: "+y)}return m({success:!0}),o.incrementCounter(`specialist_ops_${y}_success`,1),b}catch(e){return f.error("Specialist ops failed",{error:e instanceof Error?e.stack:e+""}),m({success:!1}),o.incrementCounter("specialist_ops_errors",1),{content:[{type:"text",text:"Specialist operation failed: "+(0,l.getErrorMessage)(e)}],isError:!0}}}
|
|
3516
|
+
const i=t(9860),a=t(6183),c=s(t(5967)),l=t(8824),d=t(9089),u=t(1725),h=t(7617),g=t(6688)},6315(e,exports,t){Object.defineProperty(exports,"__esModule",{value:!0}),exports.def=void 0
|
|
3518
3517
|
const r=t(6183),n=t(2982)
|
|
3519
3518
|
exports.def={name:"generate_request_journal",description:"Fetch comprehensive data about a request for writing a journal entry.\n\nReturns structured data including:\n\u2022 Request details (title, description, type, status, acceptance criteria)\n\u2022 All tasks with descriptions and status\n\u2022 File changes summary (files modified, operations performed)\n\u2022 Chronological operation history\n\nUse this data to write a narrative journal entry and save it as:\nJOURNAL-{requestId}.md using document-operations (create).",schema:r.GenerateRequestJournalSchema,annotations:{title:"Generate Request Journal",readOnlyHint:!0,destructiveHint:!1,idempotentHint:!0},readOnly:!0,hidden(){return"journal"!==process.env.ALCHEMY_MODE},handler(e,t){return(0,n.handleGenerateRequestJournal)(e,t.context,t.apiClient,t.logger,t.metrics,t.mcpServer)}}},6416(e,exports,t){var r,n=this&&this.__createBinding||(Object.create?function(e,t,r,n){void 0===n&&(n=r)
|
|
3520
3519
|
var o=Object.getOwnPropertyDescriptor(t,r)
|
|
@@ -3591,7 +3590,7 @@ var t={}
|
|
|
3591
3590
|
if(null!=e)for(var r=n(e),i=0;i<r.length;i++)"default"!==r[i]&&o(t,e,r[i])
|
|
3592
3591
|
return s(t,e),t}),a=this&&this.__importDefault||function(e){return e&&e.__esModule?e:{default:e}}
|
|
3593
3592
|
Object.defineProperty(exports,"__esModule",{value:!0}),exports.handleInsertLines=async function(e,t,n,o,s,i,a,m){const y=i.child({tool:"insert_lines"}),w=Date.now()
|
|
3594
|
-
let b,I
|
|
3593
|
+
let b,k,I=d.FileOperationPhase.VALIDATION
|
|
3595
3594
|
const v={toolName:"insert-lines",operationName:"insert-lines",fileOperationPhase:d.FileOperationPhase.FILE_WRITE,recordType:"insert-lines",metricsPrefix:"insert_lines",successMessage:"Successfully inserted lines into files and documents",failureMessage:"Failed to insert lines into files and documents"}
|
|
3596
3595
|
try{const i=d.validateArgs(e,l.InsertLinesSchema),{taskId:C,operations:_,comment:E}=i
|
|
3597
3596
|
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")
|
|
@@ -3604,7 +3603,7 @@ if(S.length>0&&!t.documentFileManager)throw Error("Document file manager not ava
|
|
|
3604
3603
|
for(const e of S)P.push({type:"document",documentId:e.documentId,insertions:e.insertions})
|
|
3605
3604
|
if(P.length>0&&t.apiClient){const e=P.map((e=>e.documentId))
|
|
3606
3605
|
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}
|
|
3607
|
-
throw e}}
|
|
3606
|
+
throw e}}I=d.FileOperationPhase.TASK_VALIDATION,a.incrementCounter("insert_lines_phase",1,{phase:I})
|
|
3608
3607
|
const R=T.length>0?T[0].path:"document-operation",M=await d.validateTaskId(C,R,n,y,a,v.metricsPrefix),j=M?.requestId
|
|
3609
3608
|
let x=null
|
|
3610
3609
|
T.length>0&&j&&(x=await d.validateWorkItemStates(C,T[0].path,n,s,t,y,a,v.metricsPrefix))
|
|
@@ -3615,9 +3614,9 @@ if(!D.success){if(D.isLockConflict)return{content:[{type:"text",text:"\u274c "+D
|
|
|
3615
3614
|
throw Error(D.error)}if(T.length>0){y.debug("Re-validating file paths with correct workspace context",{operationCount:T.length,workspaceBasePath:t.workspaceManager?.getCurrentContext().basePath})
|
|
3616
3615
|
for(let e=0;e<T.length;e++){const r=T[e],n=q[e],{normalizedPath:o,fullPath:s}=d.validateAndNormalizePath(n.path,t)
|
|
3617
3616
|
T[e]={...r,path:o,fullPath:s}}}if(P.length>0&&j)try{await(0,h.validateRequestStatusForDocumentOperation)(j,s,y,a,"insert-lines-document")}catch(e){if(e instanceof u.ValidationError)return{content:[{type:"text",text:e.message}],isError:!0}
|
|
3618
|
-
throw e}
|
|
3617
|
+
throw e}I=d.FileOperationPhase.RECORD_CREATION,a.incrementCounter("insert_lines_phase",1,{phase:I})
|
|
3619
3618
|
const A=[...T.map((e=>({type:"file",path:e.path,insertions:e.insertions}))),...P.map((e=>({type:"document",documentId:e.documentId,insertions:e.insertions})))],{toolRecordId:$}=await d.createFileOperationRecords(C,j,t.projectId,v.recordType,R,{operationCount:_.length,fileOperations:T.length,documentOperations:P.length,operations:A,userComment:E},n,o,y,a,v.metricsPrefix,m)
|
|
3620
|
-
if(b=$,I
|
|
3619
|
+
if(b=$,k=$,I=v.fileOperationPhase,a.incrementCounter("insert_lines_phase",1,{phase:I}),T.length>0&&t.git)try{y.debug("[INSERT-LINES] Checking for user changes before insert operations")
|
|
3621
3620
|
const e=await(0,g.commitUserChangesBeforeToolOperation)(t.git,"insert-lines",{requestId:j,taskId:C,workspaceManager:t.workspaceManager},y,a)
|
|
3622
3621
|
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})
|
|
3623
3622
|
const F=[]
|
|
@@ -3630,8 +3629,8 @@ try{const o=await t.documentFileManager.getDocumentAsFile(e.documentId),s=t.docu
|
|
|
3630
3629
|
n.filename=s?.filename
|
|
3631
3630
|
const i=await c.default.readFile(o,"utf8"),{newContent:a,results:l}=await r(i,e.insertions)
|
|
3632
3631
|
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))
|
|
3633
|
-
r?.success&&await t.documentFileManager.syncDocument(e.documentId)}}catch(e){y.warn("Some documents may not have synced properly",{error:e})}const B=await d.handleMultiFileGitCommit(C,T,F,z,{operationType:"Insert lines",toolRecordId:
|
|
3634
|
-
try{await o.updateToolRecord(
|
|
3632
|
+
r?.success&&await t.documentFileManager.syncDocument(e.documentId)}}catch(e){y.warn("Some documents may not have synced properly",{error:e})}const B=await d.handleMultiFileGitCommit(C,T,F,z,{operationType:"Insert lines",toolRecordId:k,successField:"successfulInsertions",logger:y,metrics:a,metricsPrefix:"insert_lines"},t),H=d.processMultiFileOperationResults(F,"successfulInsertions"),{successfulOperations:U,failedOperations:W,totalSuccessfulChanges:G,overallSuccess:V,successfulFiles:J,failedFiles:K}=H
|
|
3633
|
+
try{await o.updateToolRecord(k,{metadata:{path:T.length>0?T[0].path:"document:"+P[0]?.documentId,status:V?"completed":"failed",error:V?void 0:W+" operations failed",totalOperations:F.length,successfulFiles:J,failedFiles:K,operations:A,totalSuccessfulInsertions:G,totalFailedInsertions:N,totalLinesAdded:L,operationsWithChanges:z,processingTime:Date.now()-w,userComment:E,...T.length>0&&B.success&&B.commitHash&&{commitHash:B.commitHash,previousCommitHash:B.previousCommitHash||void 0}},note:V?`Line insertion completed: ${U}/${F.length} operations successful${T.length>0?" (committed to git)":""}`:`Line insertion partially failed: ${W}/${F.length} operations failed`})}catch(e){y.warn("Failed to update tool record",{recordError:e})}let Y="## Line Insertion Results\n\n"
|
|
3635
3634
|
if(t.workspaceManager&&(Y+=`**Branch:** \`${t.workspaceManager.getCurrentContext().branchName}\`\n\n`),Y+="**Summary:**\n",Y+=`- **Files processed:** ${U+W}\n`,Y+=`- **Successful operations:** ${U}\n`,Y+=`- **Failed operations:** ${W}\n`,Y+=`- **Total insertions:** ${G} successful, ${N} failed\n`,Y+=`- **Total Lines Added:** ${L}\n`,Y+="\n",B.success&&B.commitHash&&(Y+="**Git Commit:**\n",Y+=`- **Commit Hash:** ${B.commitHash.substring(0,8)}\n`,Y+=`- **Files Committed:** ${B.filesCommitted.length}\n`,B.previousCommitHash&&(Y+=`- **Previous Commit:** ${B.previousCommitHash.substring(0,8)}\n`),Y+="\n"),D.lockAcquired&&D.lockedRequestId&&(Y+=`\u{1f512} **Locked request:** ${D.lockedRequestId}\n\n`),1===F.length){const e=F[0]
|
|
3636
3635
|
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"
|
|
3637
3636
|
for(const t of e.insertions.filter((e=>!e.success))){const e="between"===t.type?`between lines ${t.afterLine} and ${t.beforeLine}`:`${t.type} line ${t.line}`
|
|
@@ -3641,68 +3640,68 @@ for(const t of e.insertions.filter((e=>!e.success))){const e="between"===t.type?
|
|
|
3641
3640
|
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")
|
|
3642
3641
|
const Q=Date.now()-w
|
|
3643
3642
|
return y.info("Insert lines operation completed",{duration:Q,success:V,totalOperations:F.length,successfulOperations:U,failedOperations:W}),a.incrementCounter("insert_lines_total",1,{success:V}),{content:[{type:"text",text:Y}],isError:!V}}catch(t){const r=Date.now()-w
|
|
3644
|
-
if(y.error("Insert lines operation failed",{error:t instanceof Error?t.stack:t+"",duration:r,phase:
|
|
3643
|
+
if(y.error("Insert lines operation failed",{error:t instanceof Error?t.stack:t+"",duration:r,phase:I}),k)try{await o.updateToolRecord(k,{metadata:{path:e?.operations?.[0]?.path||e?.operations?.[0]?.documentId,status:"failed",error:(0,f.getErrorMessage)(t),phase:I,duration:r,userComment:e?.comment},note:"Line insertion failed: "+(0,f.getErrorMessage)(t)})}catch(e){}return a.incrementCounter("insert_lines_errors",1,{phase:I}),{content:[{type:"text",text:"\u274c **Insert Lines Failed:** "+(0,f.getErrorMessage)(t)}],isError:!0}}}
|
|
3645
3644
|
const c=a(t(1943)),l=t(6183),d=i(t(5967)),u=t(9860),h=t(5003),g=t(7478),p=t(9949),f=t(8824),m=t(3255)},6539(e,exports,t){Object.defineProperty(exports,"__esModule",{value:!0}),exports.ClientFactory=void 0
|
|
3646
3645
|
const r=t(1253),n=t(5681),o=t(6595),s=t(3895),i=t(6848),a=t(6153),c=t(4710),l=t(6975),d=t(1887),u=t(1666),h=t(8824),g=t(9884),p=t(2968),f=t(922)
|
|
3647
3646
|
exports.ClientFactory=class{static async createClient(e,m,y,w={}){(m=m.child({component:"client-factory"})).info("Creating API client with components")
|
|
3648
3647
|
const b=w.tokenManager||new r.TokenManager(m,w.workingDir||process.cwd())
|
|
3649
3648
|
await b.initialize()
|
|
3650
|
-
const
|
|
3651
|
-
|
|
3649
|
+
const k=w.tokenSynchronizer||new i.ClientTokenSynchronizer(m),I=new s.AuthenticationManager(b,m,k),v=await I.getTokenString(),C=w.connectionStatusManager||new n.ConnectionStatusManager(e,m,y,{alchemyPath:w.alchemyPath,checkIntervalMs:w.offlineCheckIntervalMs,timeoutMs:w.timeout,retryCount:w.retryAttempts}),_=new c.ProjectClient(e,m,y,C,v||void 0,{timeout:w.timeout,retryAttempts:w.retryAttempts,retryDelay:w.retryDelay,circuitBreakerThreshold:w.circuitBreakerThreshold,circuitBreakerResetTime:w.circuitBreakerResetTime})
|
|
3650
|
+
k.registerClient(_),w.alchemyPath&&_.setAlchemyPath(w.alchemyPath)
|
|
3652
3651
|
const E=new p.TaskClient(e,m,y,_,C,v||void 0,{timeout:w.timeout,retryAttempts:w.retryAttempts,retryDelay:w.retryDelay,circuitBreakerThreshold:w.circuitBreakerThreshold,circuitBreakerResetTime:w.circuitBreakerResetTime})
|
|
3653
|
-
|
|
3652
|
+
k.registerClient(E)
|
|
3654
3653
|
const q=new a.FileOperationsClient(e,m,y,_,v||void 0,C,{timeout:w.timeout,retryAttempts:w.retryAttempts,retryDelay:w.retryDelay,circuitBreakerThreshold:w.circuitBreakerThreshold,circuitBreakerResetTime:w.circuitBreakerResetTime})
|
|
3655
|
-
|
|
3654
|
+
k.registerClient(q),m.info("RequestClient constructor received token: "+(v?"present":"missing"))
|
|
3656
3655
|
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})
|
|
3657
|
-
|
|
3656
|
+
k.registerClient(S),m.info("RequestClient post-constructor token: "+(S.getAuthToken()?"present":"missing"))
|
|
3658
3657
|
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})
|
|
3659
|
-
|
|
3658
|
+
k.registerClient(T)
|
|
3660
3659
|
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})
|
|
3661
|
-
|
|
3660
|
+
k.registerClient(P)
|
|
3662
3661
|
const R=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})
|
|
3663
|
-
if(
|
|
3662
|
+
if(k.registerClient(R),!w.alchemyPath)throw Error("alchemyPath is required for ProjectSynchronizer creation. Cannot create API client without project synchronization capabilities.")
|
|
3664
3663
|
try{m.info("Creating ProjectSynchronizer components")
|
|
3665
3664
|
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})
|
|
3666
3665
|
_.setProjectSynchronizer(n),m.info("ProjectSynchronizer created and connected to ProjectClient")}catch(e){const t="Failed to create required ProjectSynchronizer components: "+(0,h.getErrorMessage)(e)
|
|
3667
|
-
throw m.error(t,{error:e instanceof Error?e.stack:e+""}),Error(t)}const M=new o.ApiClient(
|
|
3666
|
+
throw m.error(t,{error:e instanceof Error?e.stack:e+""}),Error(t)}const M=new o.ApiClient(I,_,E,q,S,T,P,R,m)
|
|
3668
3667
|
m.info("API client initialized with specialized clients"),v?(M.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"})
|
|
3669
|
-
const j=
|
|
3668
|
+
const j=k.verifyAllClients()
|
|
3670
3669
|
j.success?m.info("Token consistency verified across all clients"):m.error(`Token inconsistency detected in ${j.failedClients.length} clients: ${j.failedClients.join(", ")}`)
|
|
3671
3670
|
const x=M.getAuthToken()
|
|
3672
3671
|
return v&&!x?(m.error("CRITICAL: ApiClient token was not set properly!"),M.setAuthToken(v)):x&&m.info("ApiClient token verified",{tokenLength:x.length,matches:x===v}),m.info("API client creation completed successfully"),M}}},6540(e,exports){var t
|
|
3673
|
-
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={}))},6552(e,exports,t){async function r(){const e=new o.StdioServerTransport,t=(0,l.setupParentProcessDetection)((()=>{
|
|
3674
|
-
if(E)try{await E.connectStdio(),(0,a.isDebugToolsEnabled)()&&
|
|
3675
|
-
throw
|
|
3672
|
+
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={}))},6552(e,exports,t){async function r(){const e=new o.StdioServerTransport,t=(0,l.setupParentProcessDetection)((()=>{k.info("Parent process gone or orphan detected. Shutting down."),process.exit(0)}))
|
|
3673
|
+
if(E)try{await E.connectStdio(),(0,a.isDebugToolsEnabled)()&&k.info("Connected stdio transport to server")}catch(e){const t=e instanceof Error?{message:e.message,name:e.name,stack:e.stack}:e+""
|
|
3674
|
+
throw k.error("Failed to connect stdio transport",{errorDetails:t}),e}else k.error("No global server instance available to connect transport")
|
|
3676
3675
|
return{transport:e,shutdownHandler:t}}var n=this&&this.__importDefault||function(e){return e&&e.__esModule?e:{default:e}}
|
|
3677
3676
|
Object.defineProperty(exports,"__esModule",{value:!0})
|
|
3678
3677
|
const o=t(5802),s=n(t(6928)),i=t(184),a=t(3444),c=t(1152),l=t(8851),d=t(8411),u=n(t(9896)),h=t(4139),g=t(5218),p=t(8824),f=t(9939),m=t(7960),y=process.argv.slice(2),w=y[0]||process.cwd(),b=s.default.resolve(w)
|
|
3679
3678
|
console.error("\n=== MCP STARTUP DIAGNOSTICS ==="),console.error("Script path (process.argv[1]):",process.argv[1]),console.error("Base directory:",b),console.error("ENABLE_DEBUG_TOOLS env:",process.env.ENABLE_DEBUG_TOOLS),console.error("DEBUG_LOGGING env:",process.env.DEBUG_LOGGING),console.error("isDevBuild():",(0,m.isDevBuild)()),console.error("isDebugToolsEnabled():",(0,a.isDebugToolsEnabled)()),console.error("===============================\n")
|
|
3680
|
-
const
|
|
3681
|
-
const
|
|
3682
|
-
process.stdout.write=function(e,t,r){try{if("string"==typeof e)try{JSON.parse(e)}catch(t){return e.includes('"__message_type"')||(process.stderr.write("[STDOUT REDIRECTED]: "+e),r&&r()),!0}return"string"==typeof t&&"function"==typeof r?
|
|
3683
|
-
try{if(u.default.existsSync(b)||(
|
|
3684
|
-
u.default.writeFileSync(e,(new Date).toISOString()),
|
|
3679
|
+
const k=(0,a.createEnvLogger)({serviceName:"direct-mcp-server",console:!0,baseDir:b});(0,a.isDebugToolsEnabled)()?k.info("MCP Direct server initializing",{baseDir:b,debugLogging:process.env.DEBUG_LOGGING,debugLevel:process.env.DEBUG_LEVEL,pid:process.pid}):k.info("MCP Direct server starting"),console.log=function(...e){console.error("[LOG]",...e)},console.info=function(...e){console.error("[INFO]",...e)},console.warn=function(...e){console.error("[WARN]",...e)},process.on("uncaughtException",(e=>{if(k.error("UNCAUGHT EXCEPTION: "+e,{stack:e.stack||"No stack available"}),E)try{E.cleanupSSEConnection()}catch(e){k.error("Error during cleanup after uncaught exception: "+e)}setTimeout((()=>process.exit(1)),500)})),process.on("unhandledRejection",(e=>{k.error("UNHANDLED REJECTION: "+e,{stack:e instanceof Error?e.stack:"No stack available"})})),process.on("exit",(e=>{k.info("Process exiting with code: "+e)}))
|
|
3680
|
+
const I=process.stdout.write
|
|
3681
|
+
process.stdout.write=function(e,t,r){try{if("string"==typeof e)try{JSON.parse(e)}catch(t){return e.includes('"__message_type"')||(process.stderr.write("[STDOUT REDIRECTED]: "+e),r&&r()),!0}return"string"==typeof t&&"function"==typeof r?I.call(process.stdout,e,t,r):"function"==typeof t?I.call(process.stdout,e,void 0,t):I.call(process.stdout,e)}catch(e){return process.stderr.write("[STDOUT ERROR]: "+e),!0}},(0,a.isDebugToolsEnabled)()&&(k.info("Initialized stdout filtering to ensure only valid JSON is sent"),k.info("!!!MARKER!!! COMMAND-LINE ARGS:",{args:JSON.stringify(y)}),k.info("!!!MARKER!!! BASE DIRECTORY:",{baseDir:w}),k.info("!!!MARKER!!! ABSOLUTE BASE DIR:",{absBaseDir:b}),k.info("Working with base directory:",{absBaseDir:b}))
|
|
3682
|
+
try{if(u.default.existsSync(b)||(k.warn(`Base directory ${b} does not exist. Creating it...`),u.default.mkdirSync(b,{recursive:!0})),(0,a.isDebugToolsEnabled)()){const e=s.default.join(b,".mcp-test-file")
|
|
3683
|
+
u.default.writeFileSync(e,(new Date).toISOString()),k.info("Successfully wrote test file to "+e),u.default.unlinkSync(e),k.info("Successfully deleted test file"),k.info(`Confirmed base directory ${b} exists and is accessible`)}}catch(e){k.error(`Error accessing base directory ${b}:`,{error:e}),k.warn("This may cause issues with file operations - please check permissions")}const v=(0,c.createMetricsCollector)(!1)
|
|
3685
3684
|
let C=process.env.REMOTE_SERVER_URL||"https://api.alchemylabcode.com"
|
|
3686
3685
|
const _=global.__serverInitialized
|
|
3687
|
-
void 0===_?(global.__serverInitialized=!1,(0,a.isDebugToolsEnabled)()&&
|
|
3686
|
+
void 0===_?(global.__serverInitialized=!1,(0,a.isDebugToolsEnabled)()&&k.info("FIRST RUN: Setting global.__serverInitialized to false")):(0,a.isDebugToolsEnabled)()&&k.info("REUSE: global.__serverInitialized is already "+global.__serverInitialized)
|
|
3688
3687
|
let E=null
|
|
3689
3688
|
const q=(0,g.isMultiAgentModeEnabled)(b)
|
|
3690
|
-
try{(0,d.acquireProcessLock)(b,q)||(
|
|
3691
|
-
|
|
3689
|
+
try{(0,d.acquireProcessLock)(b,q)||(k.error(`Process lock acquisition failed for ${b}. Another instance may be running.`),k.error("This instance will exit to prevent duplicate initialization"),process.exit(1)),(0,a.isDebugToolsEnabled)()&&(q?k.info("Multi-agent mode enabled - allowing concurrent access to "+b):k.info("Successfully acquired process lock for "+b))}catch(e){k.error("Lock acquisition threw exception",{error:(0,p.getErrorMessage)(e),stack:e instanceof Error?e.stack:void 0}),k.error("Cannot continue without lock in single-agent mode"),process.exit(1)}(0,a.isDebugToolsEnabled)()&&(k.info("============================================================"),k.info(`PROCESS START: PID=${process.pid}, TIME=${(new Date).toISOString()}`),k.info("BASE DIR: "+b),k.info("ALCHEMY PATH: "+s.default.join(b,h.ALCHEMY_DIR_NAME)),k.info("PROJECT PATH: "+s.default.join(b,h.ALCHEMY_DIR_NAME+"/project.json")),k.info("MULTI-AGENT MODE: "+q),k.info("MCP client information will be captured during protocol initialization")),k.info("Starting MCP server"),(0,a.isDebugToolsEnabled)()&&(k.info("============================================================"),k.info("Base directory: "+b),k.info("Remote server URL: "+C),k.info("Node version: "+process.version),k.info("Current working directory: "+process.cwd()),k.info("ALLOWED_DIRECTORIES env var: not used (single working directory mode)"),k.info("Server already initialized: "+(_?"YES":"NO"))),_&&((0,a.isDebugToolsEnabled)()&&(k.info("Server already initialized globally, reusing existing server instance"),k.info("Reconnecting stdio to existing server...")),r().catch((e=>{const t=e instanceof Error?{message:e.message,name:e.name,stack:e.stack}:e+""
|
|
3690
|
+
k.error("Failed to connect stdio transport to existing server",{errorDetails:t}),process.exit(1)})))
|
|
3692
3691
|
try{const e=u.default.existsSync(b)
|
|
3693
|
-
if((0,a.isDebugToolsEnabled)()&&
|
|
3694
|
-
|
|
3695
|
-
if(!u.default.existsSync(S))try{u.default.mkdirSync(S,{recursive:!0}),(0,a.isDebugToolsEnabled)()&&
|
|
3696
|
-
try{const{createConfigManager:e}=await Promise.resolve().then(t.t.bind(t,9060,23)),r=e(
|
|
3697
|
-
if(n.remoteServerUrl)return(0,a.isDebugToolsEnabled)()&&
|
|
3698
|
-
try{const e=await(0,f.syncPlugins)(b,(0,m.isDevBuild)(),
|
|
3699
|
-
e.synced.length>0&&
|
|
3700
|
-
const e=await(0,i.createServer)(b,
|
|
3701
|
-
E=e,global.__serverInitialized=!0,(0,a.isDebugToolsEnabled)()&&
|
|
3692
|
+
if((0,a.isDebugToolsEnabled)()&&k.info("Base directory exists: "+e),e&&(0,a.isDebugToolsEnabled)()){const e=u.default.statSync(b)
|
|
3693
|
+
k.info(`Directory stats: isDirectory=${e.isDirectory()}, mode=${e.mode.toString(8)}`)}else(0,a.isDebugToolsEnabled)()&&k.info("Directory does not exist, trying to create it"),u.default.mkdirSync(b,{recursive:!0})}catch(e){k.error("Error checking directory: "+e)}if(!u.default.existsSync(b))try{u.default.mkdirSync(b,{recursive:!0}),(0,a.isDebugToolsEnabled)()&&k.info("Created base directory: "+b)}catch(e){k.error("Failed to create base directory: "+e)}const S=s.default.join(b,h.ALCHEMY_DIR_NAME)
|
|
3694
|
+
if(!u.default.existsSync(S))try{u.default.mkdirSync(S,{recursive:!0}),(0,a.isDebugToolsEnabled)()&&k.info("Created alchemy lab directory: "+S)}catch(e){k.error("Failed to create alchemy lab directory: "+e)}try{(async function(){try{C=await async function(){if(process.env.REMOTE_SERVER_URL)return process.env.REMOTE_SERVER_URL
|
|
3695
|
+
try{const{createConfigManager:e}=await Promise.resolve().then(t.t.bind(t,9060,23)),r=e(k),n=await r.getInstallationConfig()
|
|
3696
|
+
if(n.remoteServerUrl)return(0,a.isDebugToolsEnabled)()&&k.info("Loaded REMOTE_SERVER_URL from installation config",{remoteServerUrl:n.remoteServerUrl}),n.remoteServerUrl}catch(e){(0,a.isDebugToolsEnabled)()&&k.debug("Could not read REMOTE_SERVER_URL from installation config",{error:e instanceof Error?e.message:"Unknown error"})}return"https://api.alchemylabcode.com"}()
|
|
3697
|
+
try{const e=await(0,f.syncPlugins)(b,(0,m.isDevBuild)(),k)
|
|
3698
|
+
e.synced.length>0&&k.info("Synced plugins on startup",{synced:e.synced}),e.errors.length>0&&k.warn("Some plugins failed to sync",{errors:e.errors})}catch(e){k.warn("Plugin sync failed",{error:e instanceof Error?e.message:"Unknown error"})}(0,a.isDebugToolsEnabled)()&&(k.info("Creating MCP server with base dir: "+b),k.info("Using remote server URL: "+C))
|
|
3699
|
+
const e=await(0,i.createServer)(b,k,v,C,{multiAgentMode:(0,g.isMultiAgentModeEnabled)(b)})
|
|
3700
|
+
E=e,global.__serverInitialized=!0,(0,a.isDebugToolsEnabled)()&&k.info("MCP server created successfully")
|
|
3702
3701
|
const n=r()
|
|
3703
|
-
return(0,a.isDebugToolsEnabled)()&&
|
|
3704
|
-
|
|
3705
|
-
|
|
3702
|
+
return(0,a.isDebugToolsEnabled)()&&k.info("Stdio transport registered with server"),{server:E,transportInfo:n}}catch(e){throw k.error("Failed to initialize MCP server",{error:e}),e}})().then((()=>{(0,a.isDebugToolsEnabled)()&&k.info("MCP server initialization complete")})).catch((e=>{const t=e instanceof Error?{message:e.message,name:e.name,stack:e.stack}:e+""
|
|
3703
|
+
k.error("Server initialization failed",{errorDetails:t}),process.exit(1)}))}catch(e){const t=e instanceof Error?{message:e.message,name:e.name,stack:e.stack}:e+""
|
|
3704
|
+
k.error("Exception during server initialization",{errorDetails:t}),process.exit(1)}process.on("SIGTERM",(()=>{k.info("SIGTERM received, shutting down"),setTimeout((()=>process.exit(0)),500)})),process.on("SIGINT",(()=>{k.info("SIGINT received, shutting down"),setTimeout((()=>process.exit(0)),500)}))},6595(e,exports,t){Object.defineProperty(exports,"__esModule",{value:!0}),exports.ApiClient=void 0
|
|
3706
3705
|
const r=t(1599),n=t(2690),o=t(4465),s=t(5187),i=t(5674),a=t(8824)
|
|
3707
3706
|
exports.ApiClient=class{constructor(e,t,r,n,o,s,i,a,c){this.options={createRecords:!0},this.alchemyPath="",this.sessionRequestAssociationClient=null,this.sessionMessageClient=null,this.sessionTagMappingClient=null,this.cliSessionClient=null,this.logger=c,this.authManager=e,this.projectClient=t,this.taskClient=r,this.fileClient=n,this.requestClient=o,this.documentClient=s,this.toolRecordClient=i,this.proxyClient=a,this.tokenSynchronizer=e.getTokenSynchronizer(),this.baseUrl=a.baseUrl||"",this.documentClient&&"function"==typeof this.documentClient.setParentApiClient&&this.documentClient.setParentApiClient(this),this.logger.info("API client initialized with specialized clients")}async setToken(e){return this.authManager.setToken(e)}async getToken(){return this.authManager.getToken()}async hasValidToken(){return this.authManager.hasValidToken()}async removeToken(){return this.authManager.removeToken()}setOptions(e){this.options={...this.options,...e},this.logger.info("API client options updated",{options:this.options})}getOptions(){return{...this.options}}isOffline(){const e=this.projectClient.isOffline?.()||!1,t=this.fileClient.isOffline?.()||!1,r=this.proxyClient.isOffline?.()||!1,n=e||t||r
|
|
3708
3707
|
return this.logger.debug("ApiClient.isOffline called - reporting actual connection status",{isOffline:n,client:"ApiClient"}),n}checkConnectivity(e,t){if(this.isOffline()){let r
|
|
@@ -3739,7 +3738,7 @@ var t={}
|
|
|
3739
3738
|
if(null!=e)for(var r=n(e),i=0;i<r.length;i++)"default"!==r[i]&&o(t,e,r[i])
|
|
3740
3739
|
return s(t,e),t}),a=this&&this.__importDefault||function(e){return e&&e.__esModule?e:{default:e}}
|
|
3741
3740
|
Object.defineProperty(exports,"__esModule",{value:!0}),exports.handleReplaceLines=async function(e,t,n,o,s,i,a,m){const w=i.child({tool:"replace_lines"}),b=Date.now()
|
|
3742
|
-
let I,
|
|
3741
|
+
let k,I,v=d.FileOperationPhase.VALIDATION
|
|
3743
3742
|
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"}
|
|
3744
3743
|
try{const i=d.validateArgs(e,l.ReplaceLinesSchema),{taskId:_,operations:E,comment:q}=i
|
|
3745
3744
|
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")
|
|
@@ -3765,7 +3764,7 @@ for(let e=0;e<P.length;e++){const r=P[e],n=S[e],{normalizedPath:o,fullPath:s}=d.
|
|
|
3765
3764
|
P[e]={...r,path:o,fullPath:s}}}if(R.length>0&&x)try{await(0,h.validateRequestStatusForDocumentOperation)(x,s,w,a,"replace-lines-document")}catch(e){if(e instanceof u.ValidationError)return{content:[{type:"text",text:e.message}],isError:!0}
|
|
3766
3765
|
throw e}v=d.FileOperationPhase.RECORD_CREATION,a.incrementCounter("replace_lines_phase",1,{phase:v})
|
|
3767
3766
|
const $=[...P.map((e=>({type:"file",path:e.path,replacements:e.replacements}))),...R.map((e=>({type:"document",documentId:e.documentId,replacements:e.replacements})))],{toolRecordId:F}=await d.createFileOperationRecords(_,x,t.projectId,C.recordType,M,{operationCount:E.length,fileOperations:P.length,documentOperations:R.length,operations:$,userComment:q},n,o,w,a,C.metricsPrefix,m)
|
|
3768
|
-
if(
|
|
3767
|
+
if(k=F,I=F,v=C.fileOperationPhase,a.incrementCounter("replace_lines_phase",1,{phase:v}),P.length>0&&t.git)try{w.debug("[REPLACE-LINES] Checking for user changes before replace operations")
|
|
3769
3768
|
const e=await(0,g.commitUserChangesBeforeToolOperation)(t.git,"replace-lines",{requestId:x,taskId:_,workspaceManager:t.workspaceManager},w,a)
|
|
3770
3769
|
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})
|
|
3771
3770
|
const N=[]
|
|
@@ -3778,8 +3777,8 @@ try{const o=await t.documentFileManager.getDocumentAsFile(e.documentId),s=t.docu
|
|
|
3778
3777
|
n.filename=s?.filename
|
|
3779
3778
|
const i=await c.default.readFile(o,"utf8"),{newContent:a,results:l}=await r(i,e.replacements)
|
|
3780
3779
|
n.replacements=l,n.successfulReplacements=l.filter((e=>e.success)).length,n.failedReplacements=l.filter((e=>!e.success)).length,n.totalLinesReplaced=l.filter((e=>e.success)).reduce(((e,t)=>e+(t.linesReplaced||0)),0),n.totalLinesAdded=l.filter((e=>e.success)).reduce(((e,t)=>e+(t.linesAdded||0)),0),a!==i&&n.successfulReplacements>0?(await c.default.writeFile(o,a,"utf8"),t.documentFileManager.markForSync(e.documentId),n.success=!0,H++,w.info("Document updated successfully",{documentId:e.documentId,filename:n.filename,successfulReplacements:n.successfulReplacements,failedReplacements:n.failedReplacements,linesReplaced:n.totalLinesReplaced,linesAdded:n.totalLinesAdded})):0===n.failedReplacements&&(n.success=!0),L+=n.failedReplacements,z+=n.totalLinesReplaced,B+=n.totalLinesAdded}catch(t){n.error=(0,f.getErrorMessage)(t),n.failedReplacements=e.replacements.length,L+=n.failedReplacements,w.error("Document operation failed",{documentId:e.documentId,error:n.error})}N.push(n)}if(R.length>0)try{for(const e of R){const r=N.find((t=>t.documentId===e.documentId))
|
|
3781
|
-
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,H,{operationType:"Replace lines",toolRecordId:
|
|
3782
|
-
try{await o.updateToolRecord(
|
|
3780
|
+
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,H,{operationType:"Replace lines",toolRecordId:I,successField:"successfulReplacements",logger:w,metrics:a,metricsPrefix:"replace_lines"},t),W=d.processMultiFileOperationResults(N,"successfulReplacements"),{successfulOperations:G,failedOperations:V,totalSuccessfulChanges:J,overallSuccess:K,successfulFiles:Y,failedFiles:Q}=W
|
|
3781
|
+
try{await o.updateToolRecord(I,{metadata:{path:P.length>0?P[0].path:"document:"+R[0]?.documentId,status:K?"completed":"failed",error:K?void 0:V+" operations failed",totalOperations:N.length,successfulFiles:Y,failedFiles:Q,operations:$,totalSuccessfulReplacements:J,totalFailedReplacements:L,totalLinesReplaced:z,totalLinesAdded:B,operationsWithChanges:H,processingTime:Date.now()-b,userComment:q,...P.length>0&&U.success&&U.commitHash&&{commitHash:U.commitHash,previousCommitHash:U.previousCommitHash||void 0}},note:K?`Line replacement completed: ${G}/${N.length} operations successful${P.length>0?" (committed to git)":""}`:`Line replacement partially failed: ${V}/${N.length} operations failed`})}catch(e){w.warn("Failed to update tool record",{recordError:e})}let Z="## Line Replacement Results\n\n"
|
|
3783
3782
|
if(t.workspaceManager&&(Z+=`**Branch:** \`${t.workspaceManager.getCurrentContext().branchName}\`\n\n`),Z+="**Summary:**\n",Z+=`- **Files processed:** ${G+V}\n`,Z+=`- **Successful operations:** ${G}\n`,Z+=`- **Failed operations:** ${V}\n`,Z+=`- **Total replacements:** ${J} successful, ${L} failed\n`,Z+=`- **Total Lines Replaced:** ${z}\n`,B>0&&(Z+=`- **Total Lines Added:** ${B}\n`),Z+="\n",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"),A.lockAcquired&&A.lockedRequestId&&(Z+=`\u{1f512} **Locked request:** ${A.lockedRequestId}\n\n`),1===N.length){const e=N[0]
|
|
3784
3783
|
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"
|
|
3785
3784
|
for(const t of e.replacements.filter((e=>!e.success)))Z+=`- Replace ${"number"==typeof t.lines?"line "+t.lines:Array.isArray(t.lines)?`lines [${t.lines.join(", ")}]`:`lines ${t.lines.start}-${t.lines.end}`}: ${t.error}\n`}}else{Z+="**Summary:**\n",Z+=`- **Total Operations:** ${N.length}\n`,Z+=`- **Successful:** ${G}\n`,Z+=`- **Failed:** ${V}\n`,Z+=`- **Total Replacements:** ${J} successful, ${L} failed\n`,Z+=`- **Total Lines Replaced:** ${z}\n`,B>0&&(Z+=`- **Total Lines Added:** ${B}\n`),Z+="\n",Z+="**Detailed Results:**\n\n"
|
|
@@ -3787,24 +3786,24 @@ for(const e of N){if("file"===e.type?Z+=`### File: ${e.path}\n`:(Z+="### Documen
|
|
|
3787
3786
|
for(const t of e.replacements.filter((e=>!e.success)))Z+=` - Replace ${"number"==typeof t.lines?"line "+t.lines:Array.isArray(t.lines)?`lines [${t.lines.join(", ")}]`:`lines ${t.lines.start}-${t.lines.end}`}: ${t.error}\n`}Z+="\n"}}R.length>0&&(Z+="\u{1f4c4} **Document Changes:** Modified documents have been automatically synced back to the tracking system.\n\n")
|
|
3788
3787
|
const X=Date.now()-b
|
|
3789
3788
|
return w.info("Replace lines operation completed",{duration:X,success:K,totalOperations:N.length,successfulOperations:G,failedOperations:V}),a.incrementCounter("replace_lines_total",1,{success:K}),{content:[{type:"text",text:Z}],isError:!K}}catch(t){const r=Date.now()-b
|
|
3790
|
-
if(w.error("Replace lines operation failed",{error:t instanceof Error?t.stack:t+"",duration:r,phase:v}),
|
|
3789
|
+
if(w.error("Replace lines operation failed",{error:t instanceof Error?t.stack:t+"",duration:r,phase:v}),I)try{await o.updateToolRecord(I,{metadata:{path:e?.operations?.[0]?.path||e?.operations?.[0]?.documentId,status:"failed",error:(0,f.getErrorMessage)(t),phase:v,duration:r,userComment:e?.comment},note:"Line replacement failed: "+(0,f.getErrorMessage)(t)})}catch(e){}return a.incrementCounter("replace_lines_errors",1,{phase:v}),{content:[{type:"text",text:"\u274c **Replace Lines Failed:** "+(0,f.getErrorMessage)(t)}],isError:!0}}}
|
|
3791
3790
|
const c=a(t(1943)),l=t(6183),d=i(t(5967)),u=t(9860),h=t(5003),g=t(7478),p=t(9949),f=t(8824),m=t(3255),y=t(9470)},6688(e,exports,t){Object.defineProperty(exports,"__esModule",{value:!0}),exports.sessionIdentity=void 0
|
|
3792
3791
|
const r=t(9896),n=t(6928)
|
|
3793
|
-
exports.sessionIdentity=new class{constructor(){this.
|
|
3792
|
+
exports.sessionIdentity=new class{constructor(){this.parentCache=new Map}setIdentity(e){const t=this.identity
|
|
3794
3793
|
this.identity=e,this.log("setIdentity",{sessionId:e.sessionId,serverUrl:e.serverUrl,agentType:e.agentType||null,prevSessionId:t?.sessionId||null,changed:t?.sessionId!==e.sessionId})}getIdentity(){return this.identity}updateIdentity(e){if(this.identity){const t={...this.identity}
|
|
3795
|
-
this.identity={...this.identity,...e},this.log("updateIdentity",{sessionId:this.identity.sessionId,updates:Object.keys(e),agentTypeBefore:t.agentType||null,agentTypeAfter:this.identity.agentType||null})}}
|
|
3796
|
-
this.identity=void 0,this.discoveryAttempted=!1,this.log("reset",{prevSessionId:e?.sessionId||null,prevAgentType:e?.agentType||null})}hasDiscoveryBeenAttempted(){return this.discoveryAttempted}markDiscoveryAttempted(){this.discoveryAttempted=!0}async getParentSessionId(e,t,r){if(this.parentCache.has(e)){const t=this.parentCache.get(e)
|
|
3794
|
+
this.identity={...this.identity,...e},this.log("updateIdentity",{sessionId:this.identity.sessionId,updates:Object.keys(e),agentTypeBefore:t.agentType||null,agentTypeAfter:this.identity.agentType||null})}}async getParentSessionId(e,t,r){if(this.parentCache.has(e)){const t=this.parentCache.get(e)
|
|
3797
3795
|
return this.log("getParentSessionId.cache-hit",{childExternalId:e,parentExternalId:t}),t}try{const n=t.getCLISessionClient()
|
|
3798
3796
|
if(!n)return r.warn("CLI session client not available"),null
|
|
3799
3797
|
const o=await n.getParent(e),s=o?.externalSessionId||null
|
|
3800
3798
|
return this.parentCache.set(e,s),this.log("getParentSessionId.resolved",{childExternalId:e,parentExternalId:s}),s||r.warn("Parent session not found",{sessionId:e}),s}catch(t){const n=t instanceof Error?t.message:t+""
|
|
3801
|
-
return r.warn("Error getting parent session",{sessionId:e,error:n}),null}}setParentSessionId(e,t){this.parentCache.set(e,t)}async getSessionRequestId(e,t){
|
|
3799
|
+
return r.warn("Error getting parent session",{sessionId:e,error:n}),null}}setParentSessionId(e,t){this.parentCache.set(e,t)}async getSessionRequestId(e,t,r){const n=r||this.identity?.sessionId
|
|
3800
|
+
if(!n)return t.warn("Cannot get session request: no session identity"),null
|
|
3802
3801
|
try{const r=e.getSessionRequestAssociationClient?.()
|
|
3803
3802
|
if(!r)return t.warn("Session request association client not available"),null
|
|
3804
|
-
const
|
|
3805
|
-
if(
|
|
3806
|
-
return this.log("getSessionRequestId.resolved",{sessionId:
|
|
3807
|
-
return t.warn("Error getting session request",{sessionId:
|
|
3803
|
+
const o=await r.getActiveRequestsForSession(n)
|
|
3804
|
+
if(o?.length>0){const e=o[0].requestLocalId||o[0].request_local_id
|
|
3805
|
+
return this.log("getSessionRequestId.resolved",{sessionId:n,requestId:e}),e||null}return this.log("getSessionRequestId.none",{sessionId:n}),null}catch(e){const r=e instanceof Error?e.message:e+""
|
|
3806
|
+
return t.warn("Error getting session request",{sessionId:n,error:r}),null}}buildCliOrigin(e){if(this.identity)return{providerId:this.identity.providerId,sessionId:this.identity.sessionId,messageId:e,createdAt:(new Date).toISOString()}}setCurrentCallOrigin(e){this.currentCallOrigin=e}getCurrentCallOrigin(){return this.currentCallOrigin||this.buildCliOrigin()}log(e,t){try{const o=process.env.ALCHEMY_PROJECT_PATH||process.cwd(),s=(0,n.join)(o,".alchemy_lab");(0,r.existsSync)(s)||(0,r.mkdirSync)(s,{recursive:!0})
|
|
3808
3807
|
const i=(0,n.join)(s,"mcp-identity-debug.log"),a=(new Date).toISOString(),c=process.pid,l=t?" "+JSON.stringify(t):"";(0,r.appendFileSync)(i,`[${a}] [PID:${c}] identity.${e}${l}\n`)}catch{}}},exports.sessionIdentity.log("module-load",{ALCHEMY_SESSION_TAG:process.env.ALCHEMY_SESSION_TAG||null,ALCHEMY_INITIAL_BRANCH:process.env.ALCHEMY_INITIAL_BRANCH||null,ALCHEMY_ALLOW_PARALLEL:process.env.ALCHEMY_ALLOW_PARALLEL||null})},6756(e,exports){var t,r
|
|
3809
3808
|
Object.defineProperty(exports,"__esModule",{value:!0}),exports.TaskStatus=exports.RequestStatus=void 0,function(e){e.OPEN="open",e.IN_PROGRESS="in_progress",e.COMPLETED="completed",e.CONFLICTED="conflicted",e.READY_FOR_REVIEW="ready_for_review",e.PENDING_APPROVAL="pending_approval"}(t||(exports.RequestStatus=t={})),function(e){e.PENDING="pending",e.IN_PROGRESS="in_progress",e.READY_FOR_REVIEW="ready_for_review",e.COMPLETED="completed"}(r||(exports.TaskStatus=r={}))},6770(e,exports,t){Object.defineProperty(exports,"__esModule",{value:!0}),exports.def=void 0
|
|
3810
3809
|
const r=t(6183),n=t(6651)
|
|
@@ -3867,13 +3866,13 @@ s.info("Raw task response data",{responseDataType:typeof P,isArray:Array.isArray
|
|
|
3867
3866
|
try{const M=await m.getToolRecordsByTaskId(g)
|
|
3868
3867
|
if(s.info("Raw records response data",{responseDataType:typeof M,isArray:Array.isArray(M),hasData:null!=M,properties:M&&"object"==typeof M?Object.keys(M):[]}),b=(0,l.extractArrayFromResponse)(M,{logger:s,operationName:"searchRecords",defaultValue:[]}),b.length>0&&s.info("First record summary:",{id:b[0].id,type:b[0].type,hasMetadata:!!b[0].metadata,hasCommitHash:!!b[0].metadata?.commitHash}),s.info(`Extracted ${b.length} records for task ${g}`),b.length>0){const j={}
|
|
3869
3868
|
b.forEach((e=>{j[e.type]=(j[e.type]||0)+1})),s.info("Record type distribution:",j)}}catch(x){s.warn("Error fetching records for task "+g,{error:(0,u.getErrorMessage)(x)}),b=[]}if(0===b.length)return h({success:!0,recordCount:0}),{content:[{type:"text",text:`No records found for task ${g}.`}]}
|
|
3870
|
-
function
|
|
3869
|
+
function k(e){const t=new Map,r=new Map,n=[]
|
|
3871
3870
|
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
3871
|
if(e&&s){const i={source:e,destination:s,recordId:o.id,timestamp:o.createdAt,type:"move-file"}
|
|
3873
3872
|
t.set(e,i),r.set(s,i),n.push(i)}}else if("move-files"===o.type&&o.metadata){const e=[...o.metadata.successfulOperations||[],...o.metadata.failedOperations||[]]
|
|
3874
3873
|
for(const s of e)if(s.source&&s.destination){const e={source:s.source,destination:s.destination,recordId:o.id,timestamp:o.createdAt,type:"move-files"}
|
|
3875
|
-
t.set(s.source,e),r.set(s.destination,e),n.push(e)}}return{sourceToMove:t,destToMove:r,allMoves:n}}const k
|
|
3876
|
-
s.info(`Detected ${
|
|
3874
|
+
t.set(s.source,e),r.set(s.destination,e),n.push(e)}}return{sourceToMove:t,destToMove:r,allMoves:n}}const I=k(b)
|
|
3875
|
+
s.info(`Detected ${I.allMoves.length} move operations`)
|
|
3877
3876
|
const v=b.filter((e=>{if(!e||"object"!=typeof e)return s.warn("Skipping invalid record (not an object)"),!1
|
|
3878
3877
|
if(!["write-file","replace-in-files","move-file","move-files","delete-file","delete-files","manage-files"].includes(e.type))return s.debug("Skipping record with non-file operation type: "+e.type),!1
|
|
3879
3878
|
if(!e.metadata)return s.warn("Skipping record without metadata: "+e.id),!1
|
|
@@ -3949,7 +3948,7 @@ continue}let pe
|
|
|
3949
3948
|
if("pre-task"===W.status?(pe=[`${W.commitHash}..${B.commitHash}`,"--",$],s.info(`Comparing pre-task commit with final commit: ${W.commitHash?W.commitHash.substring(0,8):"unknown"}..${B.commitHash?B.commitHash.substring(0,8):"unknown"} for ${$}`)):(pe=["4b825dc642cb6eb9a060e54bf8d69288fbee4904.."+B.commitHash,"--",$],s.info(`File created during task, showing full file diff using empty tree object: ${B.commitHash?B.commitHash.substring(0,8):"unknown"} for ${$}`)),G=await t.git.diff(pe),V=!!G&&G.trim().length>0,!V&&W.commitHash!==B.commitHash){s.info("No diff found between commits but commits are different, trying direct file content comparison")
|
|
3950
3949
|
try{const me=await t.git.show([`${W.commitHash}:${$}`]),ye=await t.git.show([`${B.commitHash}:${$}`])
|
|
3951
3950
|
if(me!==ye&&(V=!0,G="Changes detected through direct content comparison (not visible in standard diff)",p)){const we=me.split("\n"),be=ye.split("\n")
|
|
3952
|
-
Math.abs(we.length-be.length)>0&&(G+=`\n\nLine count changed: ${we.length} \u2192 ${be.length}`),me.includes("\0")||ye.includes("\0")?G+="\n\nBinary content detected - changes not displayed":me.replace(/\s+/g,"")===ye.replace(/\s+/g,"")&&(G+="\n\nWhitespace-only changes detected")}}catch(
|
|
3951
|
+
Math.abs(we.length-be.length)>0&&(G+=`\n\nLine count changed: ${we.length} \u2192 ${be.length}`),me.includes("\0")||ye.includes("\0")?G+="\n\nBinary content detected - changes not displayed":me.replace(/\s+/g,"")===ye.replace(/\s+/g,"")&&(G+="\n\nWhitespace-only changes detected")}}catch(ke){s.warn("Error in direct file comparison: "+(ke instanceof Error?ke.message:ke+""))}}s.info(`Diff generation result for ${$}: hasDiff=${V}, length=${G.length}`)}}catch(Ie){if(s.warn("Error getting diff for "+$,{error:(0,u.getErrorMessage)(Ie),firstCommit:z.commitHash||"unknown",lastCommit:B.commitHash||"unknown"}),G="Error getting diff: "+(0,u.getErrorMessage)(Ie),"pre-task"!==z.status&&t.git)try{const ve=[`${B.commitHash}:${$}`]
|
|
3953
3952
|
s.info(`Trying fallback to show file content using git show: ${B.commitHash?B.commitHash.substring(0,8):"unknown"}:${$}`)
|
|
3954
3953
|
const Ce=await t.git.show(ve)
|
|
3955
3954
|
if(Ce&&Ce.trim().length>0){if(p){let _e=""
|
|
@@ -3961,14 +3960,14 @@ w&&"object"==typeof w&&(E+="## Task Information\n",E+=`- **Title**: ${w.title||"
|
|
|
3961
3960
|
const q=3e3
|
|
3962
3961
|
let S=0,T=!1
|
|
3963
3962
|
if(p){for(const Te of _.values())Te.hasDiff&&Te.diffText&&(S+=Te.diffText.split("\n").length)
|
|
3964
|
-
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`,
|
|
3965
|
-
for(const Pe of
|
|
3963
|
+
T=S>q,s.info(`Total diff size: ${S} lines (limit: ${q} lines)`),s.info(`Diffs ${T?"will be limited":"will be shown"} based on size`)}if(E+="## Summary\n",E+=`- **Files Modified**: ${C.size}\n`,E+=`- **Total File Operations**: ${v.length}\n`,E+="- **What's Shown**: For existing files, comparing state before task started with final state.\n",E+=" For files created during task, showing the entire file as created.\n",T?(E+=`- **Diff Display**: Limited (total diff size of ${S} lines exceeds limit of ${q} lines)\n`,E+=" Use file-history tool with individual files to see detailed changes\n\n"):E+=`- **Diff Display**: ${p?"Enabled":"Disabled"} (use showDiff=${!p} to ${p?"hide":"show"} diffs)\n\n`,I.allMoves.length>0){E+="## Move Operations\n\n",E+=`Detected ${I.allMoves.length} file move operation(s):\n\n`
|
|
3964
|
+
for(const Pe of I.allMoves)E+=`- **${Pe.source}** \u2192 **${Pe.destination}**\n`,E+=` - Operation: ${Pe.type}\n`,E+=` - Timestamp: ${new Date(Pe.timestamp).toLocaleString()}\n`,E+=` - Record ID: ${Pe.recordId}\n\n`}E+="## Modified Files\n\n"
|
|
3966
3965
|
for(const[Re,Me]of _.entries()){const{normalizedPath:je,fullPath:xe}=d.validateAndNormalizePath(Re,t)
|
|
3967
3966
|
let Oe=!1
|
|
3968
3967
|
try{await a.access(xe),Oe=!0}catch{}E+=`### ${Re} ${Oe?"":"(Deleted)"}\n\n`
|
|
3969
3968
|
const De=new Date(Me.firstChange.timestamp).toLocaleString(),Ae=new Date(Me.lastChange.timestamp).toLocaleString()
|
|
3970
3969
|
E+=`**First Change**: ${De}\n`,E+=`**Last Change**: ${Ae}\n`,"pre-task"===Me.firstChange.status&&Me.firstChange.commitHash?E+=`**Pre-Task Commit**: ${Me.firstChange.commitHash.substring(0,8)}\n`:Me.firstChange.commitHash&&(E+=`**File Created During Task**: ${Me.firstChange.commitHash.substring(0,8)}\n`),Me.lastChange.commitHash&&(E+=`**Final Commit**: ${Me.lastChange.commitHash.substring(0,8)}\n`)
|
|
3971
|
-
const $e=
|
|
3970
|
+
const $e=I.sourceToMove.get(Re),Fe=I.destToMove.get(Re)
|
|
3972
3971
|
$e?E+=`**\u2139\ufe0f Move Operation**: This file was moved TO **${$e.destination}**\n`:Fe&&(E+=`**\u2139\ufe0f Move Operation**: This file was moved FROM **${Fe.source}**\n`),p&&!T?Me.hasDiff?(E+="\n**Changes**:\n",E+="```diff\n",E+=Me.diffText,E+="\n```\n\n"):E+=`\n**Note**: ${Me.diffText}\n\n`:T&&Me.hasDiff?(E+=`\n**Note**: File has changes (${Me.diffText?Me.diffText.split("\n").length:0} lines). `,E+=`Compare ${Me.firstChange.commitHash?Me.firstChange.commitHash.substring(0,8):"unknown"}..${Me.lastChange.commitHash?Me.lastChange.commitHash.substring(0,8):"unknown"} to see changes.\n\n`):Me.hasDiff?E+="\n**Note**: File has changes. Use showDiff=true to see the diff.\n\n":E+=`\n**Note**: ${Me.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
3972
|
const i=t(9860),a=s(t(1943)),c=t(9671),l=t(2960),d=s(t(5967)),u=t(8824)},6928(module){module.exports=require("path")},6975(e,exports,t){Object.defineProperty(exports,"__esModule",{value:!0}),exports.ProjectClientAdapter=void 0
|
|
3974
3973
|
const r=t(1058)
|
|
@@ -4091,42 +4090,42 @@ Object.defineProperty(exports,"__esModule",{value:!0}),exports.logSessionIdentit
|
|
|
4091
4090
|
i.existsSync(n)||i.mkdirSync(n,{recursive:!0})
|
|
4092
4091
|
const s=(new Date).toISOString(),c=Object.keys(r).length?" "+JSON.stringify(r):""
|
|
4093
4092
|
i.appendFileSync(o,`[${s}] ${e} | ${t}${c}\n`)}catch(e){}}
|
|
4094
|
-
const i=s(t(9896)),a=s(t(6928))},7334(e,exports,t){Object.defineProperty(exports,"__esModule",{value:!0}),exports.handleCreateRequest=async function(e,t,l,d,u,h
|
|
4095
|
-
|
|
4096
|
-
const
|
|
4097
|
-
try{if(e&&"string"==typeof e.acceptanceCriteria)try{e.acceptanceCriteria=JSON.parse(e.acceptanceCriteria)}catch{}const
|
|
4093
|
+
const i=s(t(9896)),a=s(t(6928))},7334(e,exports,t){Object.defineProperty(exports,"__esModule",{value:!0}),exports.handleCreateRequest=async function(e,t,c,l,d,u,h){const g=l.child({tool:"create_request"})
|
|
4094
|
+
g.info("Creating new request",{args:e})
|
|
4095
|
+
const p=d.startTimer("tool_handler_duration")
|
|
4096
|
+
try{if(e&&"string"==typeof e.acceptanceCriteria)try{e.acceptanceCriteria=JSON.parse(e.acceptanceCriteria)}catch{}const l=function(e){try{return r.CreateRequestSchema.parse(e)}catch(e){if(e instanceof s.ZodError&&e.errors.length>0)throw new n.ValidationError(e.errors[0].message)
|
|
4098
4097
|
throw new n.ValidationError("Invalid input: "+(0,i.getErrorMessage)(e))}}(e)
|
|
4099
|
-
|
|
4100
|
-
const
|
|
4101
|
-
if(!
|
|
4102
|
-
|
|
4103
|
-
const
|
|
4104
|
-
let
|
|
4105
|
-
try{const e=
|
|
4106
|
-
if(e){const t=
|
|
4098
|
+
d.incrementCounter("create_request_attempts",1,{type:l.type,criteriaCounts:l.acceptanceCriteria.length})
|
|
4099
|
+
const f=t.projectId
|
|
4100
|
+
if(!f)throw new n.ValidationError("Project ID is required for creating requests.")
|
|
4101
|
+
c.setProjectId(f)
|
|
4102
|
+
const m=c.getRequestClient()
|
|
4103
|
+
let y=(0,a.getApprovalMode)()
|
|
4104
|
+
try{const e=h?.sessionId
|
|
4105
|
+
if(e){const t=c.getCLISessionClient()
|
|
4107
4106
|
if(t){const r=await t.getByExternalId(e)
|
|
4108
|
-
if(r?.workflowId){const e=await
|
|
4109
|
-
t?.approvalMode&&(
|
|
4110
|
-
r&&(
|
|
4111
|
-
|
|
4112
|
-
const k=await
|
|
4113
|
-
|
|
4114
|
-
const
|
|
4115
|
-
let _
|
|
4116
|
-
if(
|
|
4117
|
-
|
|
4118
|
-
try{const e=
|
|
4119
|
-
if(e){const t=await e.createToolRecord({requestId:
|
|
4120
|
-
|
|
4121
|
-
const
|
|
4122
|
-
let
|
|
4123
|
-
return
|
|
4124
|
-
else{const n=
|
|
4125
|
-
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){
|
|
4107
|
+
if(r?.workflowId){const e=await c.proxyGet("/api/workflows/"+r.workflowId),t=e?.data||e
|
|
4108
|
+
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
|
|
4109
|
+
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",b={title:l.title,description:l.description,type:l.type,acceptanceCriteria:l.acceptanceCriteria,status:w,...l.planDocumentId&&{planDocumentId:l.planDocumentId},...h&&{cliOrigin:h}}
|
|
4110
|
+
g.info("Creating request via request client",{projectId:f,title:l.title,type:l.type,criteriaCount:l.acceptanceCriteria.length})
|
|
4111
|
+
const k=await m.createRequest(b)
|
|
4112
|
+
g.debug("Create request response structure",{type:typeof k,isArray:Array.isArray(k),hasData:null!=k,properties:k?Object.keys(k):[],dataPreview:k?JSON.stringify(k).substring(0,200)+"...":"null"})
|
|
4113
|
+
const I=(0,o.extractDataFromResponse)(k,{logger:g,operationName:"createRequest",throwOnNoData:!0}),v="data"in I?I.data:I
|
|
4114
|
+
let C,_={created:!1}
|
|
4115
|
+
if(u?.workspaceManager)try{await u.workspaceManager.initializeRequest(v.id,v.title),_={created:!0,branchName:"requests/"+v.id,message:"Branch created successfully"},g.info("Request branch initialized successfully",{requestId:v.id,branchName:_.branchName,title:v.title})}catch(e){g.warn("Failed to initialize request branch, will retry on first operation",{requestId:v.id,error:(0,i.getErrorMessage)(e)})}else"quick-edit"===l.type?g.info("Quick-edit request - skipping branch creation, will work directly on main",{requestId:v.id}):g.debug("No workspace manager available, branch creation deferred",{requestId:v.id})
|
|
4116
|
+
g.info("Request created successfully",{requestId:v.id,title:v.title,branchCreated:_.created,branchName:_.branchName})
|
|
4117
|
+
try{const e=c.getToolRecordClient()
|
|
4118
|
+
if(e){const t=await e.createToolRecord({requestId:v.id,projectId:f,type:"create-request",metadata:{status:"completed",timestamp:(new Date).toISOString(),requestType:v.type,requestTitle:v.title,requestDescription:v.description,criteriaCount:v.acceptanceCriteria.length,branchCreated:_.created,branchName:_.created?_.branchName:null},note:`Created request "${v.title}" of type ${v.type}${_.created?" with branch "+_.branchName:" - branch will be created on first file operation"}`})
|
|
4119
|
+
C=t?.id}}catch(e){g.warn("Failed to create tool record for request creation",{error:(0,i.getErrorMessage)(e),requestId:v.id})}p({success:!0,type:l.type,hasProjectId:!0}),g.info("Request created successfully",{requestId:v.id,title:v.title,type:v.type,projectId:f})
|
|
4120
|
+
const E=v.localId||v.id
|
|
4121
|
+
let q="pending_approval"===w?`Created Request ${E} (pending approval)`:"Created Request "+E
|
|
4122
|
+
return C&&(q+=`\n[RECORD:${C}]`),{content:[{type:"text",text:q}]}}catch(r){if(g.error("Failed to create request",{error:r instanceof Error?r.stack:r+"",args:e}),t.projectId)try{if(r instanceof Error&&(r.message.includes("Project is disabled")||r.message.includes("Project cannot accept new requests")||r.message.includes("disabled due to tier limits")))g.info("Skipping tool record creation for disabled project error",{projectId:t.projectId,error:r.message})
|
|
4123
|
+
else{const n=c.getToolRecordClient()
|
|
4124
|
+
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]
|
|
4126
4125
|
let t=e.message
|
|
4127
4126
|
return e.path.includes("acceptanceCriteria")&&(t=`Acceptance criteria: ${t}. Please provide a list of criteria descriptions.`),{content:[{type:"text",text:"Error: "+t}],isError:!0}}let n=(0,i.getErrorMessage)(r),o="Unable to create request. Please check your input and try again."
|
|
4128
4127
|
return(n.includes("Project cannot accept new requests")||n.includes("Project is inactive due to tier limits"))&&(o="This project is currently inactive due to tier limits. Only your oldest projects can accept new requests. Please use an active project or upgrade your tier for more simultaneous projects."),{content:[{type:"text",text:`Error: ${n}\n\n${o}`}],isError:!0}}}
|
|
4129
|
-
const r=t(6183),n=t(9860),o=t(2960),s=t(1569),i=t(8824),a=t(2478)
|
|
4128
|
+
const r=t(6183),n=t(9860),o=t(2960),s=t(1569),i=t(8824),a=t(2478)},7388(e,exports,t){var r=this&&this.__createBinding||(Object.create?function(e,t,r,n){void 0===n&&(n=r)
|
|
4130
4129
|
var o=Object.getOwnPropertyDescriptor(t,r)
|
|
4131
4130
|
o&&!("get"in o?!t.__esModule:o.writable||o.configurable)||(o={enumerable:!0,get(){return t[r]}}),Object.defineProperty(e,n,o)}:function(e,t,r,n){void 0===n&&(n=r),e[n]=t[r]}),n=this&&this.__exportStar||function(e,exports){for(var t in e)"default"===t||{}.hasOwnProperty.call(exports,t)||r(exports,e,t)}
|
|
4132
4131
|
Object.defineProperty(exports,"__esModule",{value:!0}),n(t(441),exports),n(t(270),exports)},7456(e,exports,t){var r,n=this&&this.__createBinding||(Object.create?function(e,t,r,n){void 0===n&&(n=r)
|
|
@@ -4140,7 +4139,7 @@ return o(t,e),t})
|
|
|
4140
4139
|
Object.defineProperty(exports,"__esModule",{value:!0}),exports.handleModifyFile=async function(e,t,r,n,o,s,h,g){const p=s.child({tool:"modify_file"})
|
|
4141
4140
|
try{const s=a.validateArgs(e,i.ModifyFileSchema),{taskId:u,operations:f,comment:m}=s
|
|
4142
4141
|
p.info("Processing modify-file operations",{taskId:u,operationCount:f.length,comment:m})
|
|
4143
|
-
const y=[],w=[],b=[],
|
|
4142
|
+
const y=[],w=[],b=[],k=[],I=[]
|
|
4144
4143
|
for(const e of f){const t={path:e.path,documentId:e.documentId}
|
|
4145
4144
|
switch(e.operationType){case"replace-string":y.push({...t,replacements:e.replaceString.replacements,mode:e.replaceString.mode})
|
|
4146
4145
|
break
|
|
@@ -4148,19 +4147,19 @@ case"insert-lines":w.push({...t,insertions:e.insertLines.insertions})
|
|
|
4148
4147
|
break
|
|
4149
4148
|
case"replace-lines":b.push({...t,replacements:e.replaceLines.replacements})
|
|
4150
4149
|
break
|
|
4151
|
-
case"delete-string":
|
|
4150
|
+
case"delete-string":k.push({...t,replacements:e.deleteString.patterns.map((e=>({old_str:e,new_str:""}))),mode:e.deleteString.mode||"all"})
|
|
4152
4151
|
break
|
|
4153
|
-
case"delete-lines":
|
|
4152
|
+
case"delete-lines":I.push({...t,lines:e.deleteLines.lines})}}const v=[]
|
|
4154
4153
|
if(y.length>0){p.info("Routing to replace-strings handler",{operationCount:y.length})
|
|
4155
4154
|
const e=await(0,c.handleReplaceStrings)({taskId:u,operations:y,comment:m+" [via modify-file: replace-string]"},t,r,n,o,p,h,g)
|
|
4156
4155
|
v.push({type:"replace-string",result:e})}if(w.length>0){p.info("Routing to insert-lines handler",{operationCount:w.length})
|
|
4157
4156
|
const e=await(0,l.handleInsertLines)({taskId:u,operations:w,comment:m+" [via modify-file: insert-lines]"},t,r,n,o,p,h,g)
|
|
4158
4157
|
v.push({type:"insert-lines",result:e})}if(b.length>0){p.info("Routing to replace-lines handler",{operationCount:b.length})
|
|
4159
4158
|
const e=await(0,d.handleReplaceLines)({taskId:u,operations:b,comment:m+" [via modify-file: replace-lines]"},t,r,n,o,p,h,g)
|
|
4160
|
-
v.push({type:"replace-lines",result:e})}if(
|
|
4161
|
-
const e=await(0,c.handleReplaceStrings)({taskId:u,operations:
|
|
4162
|
-
v.push({type:"delete-string",result:e})}if(
|
|
4163
|
-
const e=
|
|
4159
|
+
v.push({type:"replace-lines",result:e})}if(k.length>0){p.info("Routing delete-string to replace-strings handler",{operationCount:k.length})
|
|
4160
|
+
const e=await(0,c.handleReplaceStrings)({taskId:u,operations:k,comment:m+" [via modify-file: delete-string]"},t,r,n,o,p,h,g)
|
|
4161
|
+
v.push({type:"delete-string",result:e})}if(I.length>0){p.info("Processing delete-lines operations",{operationCount:I.length})
|
|
4162
|
+
const e=I.map((e=>({path:e.path,documentId:e.documentId,replacements:[{lines:e.lines,content:[]}]}))),s=await(0,d.handleReplaceLines)({taskId:u,operations:e,comment:m+" [via modify-file: delete-lines]"},t,r,n,o,p,h,g)
|
|
4164
4163
|
v.push({type:"delete-lines",result:s})}const C=v.some((e=>e.result.isError)),_=v.filter((e=>!e.result.isError)).length,E=v.filter((e=>e.result.isError)).length
|
|
4165
4164
|
let q="## Modify File Results\n\n"
|
|
4166
4165
|
q+="**Summary:**\n",q+=`- **Total operation types:** ${v.length}\n`,q+=`- **Successful:** ${_}\n`,q+=`- **Failed:** ${E}\n\n`
|
|
@@ -4312,55 +4311,9 @@ const i=await t.updateDocument(e.planId,o),a=i.localId||i.id
|
|
|
4312
4311
|
return s.info("Plan updated",{planId:a}),{content:[{type:"text",text:`\u2705 **Plan Updated**\n\n**Plan ID:** ${a}\n**Filename:** ${i.filename}\n**Updated:** `+new Date(i.updatedAt).toLocaleString()}]}}catch(e){return s.error("Failed to update plan",{error:(0,r.getErrorMessage)(e)}),{content:[{type:"text",text:"\u274c **Failed to update plan:** "+(0,r.getErrorMessage)(e)}],isError:!0}}}
|
|
4313
4312
|
const r=t(8824)},7613(e,exports,t){Object.defineProperty(exports,"__esModule",{value:!0}),exports.def=void 0
|
|
4314
4313
|
const r=t(6183),n=t(9072)
|
|
4315
|
-
exports.def={name:"session_message_operations",description:'Inter-session messaging (questions and reports).\n\nOperations:\n\u2022 send - Send a message (type: "question" or "report")\n\u2022 reply - Reply to a message (answer a question or acknowledge a report). Type inferred from code prefix (Q-/R-).\n\u2022 list - List messages (filter by messageType, direction, status)\n\u2022 get - Get a message by its code\n\u2022 offer-handoff - Present the user with a choice to start building or keep planning\n\nMessage codes: Q-{id}-{seq} for questions, R-{id}-{seq} for reports.',schema:r.SessionMessageOperationsSchema,annotations:{title:"Session Message Operations",readOnlyHint:!1,destructiveHint:!1,idempotentHint:!1},handler(e,t){return(0,n.handleSessionMessageOperations)(e,t.context,t.logger,t.metrics,t.apiClient??void 0)}}},7617(e,exports,t){function
|
|
4316
|
-
if(e.operation!==t.operation)return!1
|
|
4317
|
-
if("ask"===e.operation){let r=e.ask||e,n=t.ask||t
|
|
4318
|
-
if("string"==typeof n)try{n=JSON.parse(n)}catch{}if("string"==typeof r)try{r=JSON.parse(r)}catch{}const o=r?.questionContent?.question||r?.question,s=n?.questionContent?.question||n?.question
|
|
4319
|
-
return!(!o||!s)&&o===s}return!0}async function n(e,t,n,s){const i=n.child({component:"session-discovery"})
|
|
4320
|
-
try{const n=e.replace(/\/$/,"")+"/session",o=await fetch(n)
|
|
4321
|
-
if(!o.ok)return void i.warn("Failed to get session list",{status:o.status})
|
|
4322
|
-
const a=await o.json(),c=a.sort(((e,t)=>t.time.updated-e.time.updated)),l=e.replace(/\/$/,"")+"/session/status",d=await fetch(l)
|
|
4323
|
-
if(!d.ok)return void i.warn("Failed to get session status",{status:d.status})
|
|
4324
|
-
const u=await d.json(),h=c.filter((e=>"busy"===u[e.id]?.type)),g=5,p=c.slice(0,g),f=new Set(h.map((e=>e.id))),m=[...h,...p.filter((e=>!f.has(e.id)))]
|
|
4325
|
-
let y=null
|
|
4326
|
-
const w=[]
|
|
4327
|
-
for(const n of m)try{const o=`${e.replace(/\/$/,"")}/session/${n.id}/message?limit=50`,a=await fetch(o)
|
|
4328
|
-
if(!a.ok){i.debug("Failed to get messages for session",{sessionId:n.id,status:a.status})
|
|
4329
|
-
continue}const c=await a.json()
|
|
4330
|
-
let l=0
|
|
4331
|
-
for(const e of c){const o=(e.info||e).role||e.role,i=e.parts
|
|
4332
|
-
if("assistant"===o&&i)for(const o of i)if("tool"===o.type){const i=o.tool,a=o.state?.status,c=o.sessionID
|
|
4333
|
-
if(l++,i&&i.includes(t)){if("running"!==a&&"pending"!==a){w.push({sessionId:n.id,tool:i,reason:"wrong state: "+a})
|
|
4334
|
-
continue}const t=o.state?.input,l=o.state?.time?.start||0,d=c||n.id,u=Date.now(),h=l>0?u-l:0
|
|
4335
|
-
if(l>0&&h>6e4){w.push({sessionId:n.id,tool:i,reason:`stale: running for ${Math.round(h/1e3)}s`})
|
|
4336
|
-
continue}if(s&&t&&!r(s,t)){w.push({sessionId:n.id,tool:i,reason:"params mismatch"})
|
|
4337
|
-
continue}const g=e.info?.id
|
|
4338
|
-
y&&l<=y.startTime||(y={sessionId:d,messageId:g,startTime:l,toolName:i})}else i&&(i.includes("session-qa")||i.includes("subagent"))&&w.push({sessionId:n.id,tool:i,reason:"name mismatch: looking for "+t})}}}catch(e){i.debug("Error checking session",{sessionId:n.id,error:e+""})
|
|
4339
|
-
continue}return y?{sessionId:y.sessionId,messageId:y.messageId}:void i.warn("Session discovery failed - no matching tool call found",{toolName:t,totalSessions:a.length,busySessions:h.length,rejectionCount:w.length,rejections:w.slice(0,10)})}catch(e){return void i.warn("Failed to discover calling session",{error:(0,o.getErrorMessage)(e)})}}Object.defineProperty(exports,"__esModule",{value:!0}),exports.getServerUrl=async function(e,r){let n=process.env.OPENCODE_TUI_URL
|
|
4314
|
+
exports.def={name:"session_message_operations",description:'Inter-session messaging (questions and reports).\n\nOperations:\n\u2022 send - Send a message (type: "question" or "report")\n\u2022 reply - Reply to a message (answer a question or acknowledge a report). Type inferred from code prefix (Q-/R-).\n\u2022 list - List messages (filter by messageType, direction, status)\n\u2022 get - Get a message by its code\n\u2022 offer-handoff - Present the user with a choice to start building or keep planning\n\nMessage codes: Q-{id}-{seq} for questions, R-{id}-{seq} for reports.',schema:r.SessionMessageOperationsSchema,annotations:{title:"Session Message Operations",readOnlyHint:!1,destructiveHint:!1,idempotentHint:!1},handler(e,t){return(0,n.handleSessionMessageOperations)(e,t.context,t.logger,t.metrics,t.apiClient??void 0)}}},7617(e,exports,t){Object.defineProperty(exports,"__esModule",{value:!0}),exports.getServerUrl=async function(e,r){let n=process.env.OPENCODE_TUI_URL
|
|
4340
4315
|
if(!n)try{const{readFileSync:o}=await Promise.resolve().then(t.t.bind(t,9896,23)),{join:s}=await Promise.resolve().then(t.t.bind(t,6928,23)),i=o(s(e.basePath,".alchemy_lab","opencode.json"),"utf8"),a=JSON.parse(i)
|
|
4341
|
-
a.port&&(n="http://127.0.0.1:"+a.port,r.debug("Discovered OpenCode server URL from .alchemy_lab/opencode.json",{serverUrl:n}))}catch(e){r.debug("Could not read .alchemy_lab/opencode.json",{error:e instanceof Error?e.message:e+""})}return n},exports
|
|
4342
|
-
if(s)return t.info("Found calling session by tool",{sessionId:s.sessionId,messageId:s.messageId,toolName:r}),s}},exports.findMessageIdForTool=async function(e,t,r){try{const n=`${e.replace(/\/$/,"")}/session/${t}/message?limit=50`,o=await fetch(n)
|
|
4343
|
-
if(!o.ok)return
|
|
4344
|
-
const s=await o.json()
|
|
4345
|
-
let i,a=0
|
|
4346
|
-
for(const e of s){const t=(e.info||e).role||e.role,n=e.parts
|
|
4347
|
-
if("assistant"===t&&n)for(const t of n){if("tool"!==t.type)continue
|
|
4348
|
-
const n=t.tool,o=t.state?.status
|
|
4349
|
-
if(!n?.includes(r))continue
|
|
4350
|
-
if("running"!==o&&"pending"!==o)continue
|
|
4351
|
-
const s=t.state?.time?.start||0
|
|
4352
|
-
s>a&&(a=s,i=e.info?.id)}}return i}catch{return}},exports.discoverCallingSession=n,exports.discoverParentSessionId=async function(e,t){try{const r=e.replace(/\/$/,"")+"/session",n=await fetch(r)
|
|
4353
|
-
if(!n.ok)return void t.warn("Failed to get session list",{status:n.status})
|
|
4354
|
-
const o=[...await n.json()].sort(((e,t)=>t.time.updated-e.time.updated))
|
|
4355
|
-
if(0===o.length)return void t.warn("No sessions found")
|
|
4356
|
-
const s=e.replace(/\/$/,"")+"/session/status",i=await fetch(s)
|
|
4357
|
-
if(!i.ok)return void t.warn("Failed to get session status",{status:i.status})
|
|
4358
|
-
const a=await i.json(),c=o.filter((e=>"busy"===a[e.id]?.type))
|
|
4359
|
-
for(const r of c)try{const n=`${e.replace(/\/$/,"")}/session/${r.id}/message?limit=20`,o=await fetch(n)
|
|
4360
|
-
if(!o.ok)continue
|
|
4361
|
-
const s=await o.json()
|
|
4362
|
-
for(const e of s)if("assistant"===e.role&&e.parts)for(const n of e.parts)if("tool-invocation"===n.type&&"subagent_operations"===n.toolInvocation?.toolName&&"spawn"===n.toolInvocation?.args?.operation&&"pending"===n.toolInvocation?.state)return t.info("Found parent session via spawn tool call",{parentSessionId:r.id}),r.id}catch{continue}return c.length>0?(t.info("Fallback: using first busy session",{parentSessionId:c[0].id}),c[0].id):(t.info("Last resort: using most recent session",{parentSessionId:o[0].id}),o[0].id)}catch(e){t.warn("Failed to query OpenCode API for parent session",{error:e instanceof Error?e.message:e+""})}}
|
|
4363
|
-
const o=t(8824)},7621(e,exports,t){async function r(e,t,r){const n=r.startTimer("get_current_git_branch_duration")
|
|
4316
|
+
a.port&&(n="http://127.0.0.1:"+a.port,r.debug("Discovered OpenCode server URL from .alchemy_lab/opencode.json",{serverUrl:n}))}catch(e){r.debug("Could not read .alchemy_lab/opencode.json",{error:e instanceof Error?e.message:e+""})}return n}},7621(e,exports,t){async function r(e,t,r){const n=r.startTimer("get_current_git_branch_duration")
|
|
4364
4317
|
try{if(!e.git)return t.debug("No git repository available"),r.incrementCounter("get_current_git_branch_no_git",1),n({success:!1,reason:"no_git"}),null
|
|
4365
4318
|
const o=await u.getCurrentBranch(e.git,t,r)
|
|
4366
4319
|
return t.debug("Retrieved current git branch",{currentBranch:o}),r.incrementCounter("get_current_git_branch_success",1),n({success:!0}),o}catch(e){const o=(0,g.getErrorMessage)(e)
|
|
@@ -4454,7 +4407,9 @@ var n=t(2037)
|
|
|
4454
4407
|
Object.defineProperty(exports,"RequestLockManager",{enumerable:!0,get(){return n.RequestLockManager}})},7636(e,exports,t){var r=this&&this.__importDefault||function(e){return e&&e.__esModule?e:{default:e}}
|
|
4455
4408
|
Object.defineProperty(exports,"__esModule",{value:!0}),exports.MultiAgentWorkspaceManager=void 0
|
|
4456
4409
|
const n=r(t(6928)),o=t(3807),s=t(7634),i=t(8824),a=t(7075),c=t(1387),l=t(4968)
|
|
4457
|
-
|
|
4410
|
+
class d{getSession(e){const t=e||d.DEFAULT_SESSION
|
|
4411
|
+
let r=this.sessions.get(t)
|
|
4412
|
+
return r||(r={requestId:null,worktreePath:null,git:this.mainGit,readonlyBranchCheckDone:!1,workspaceKnownClean:!1,largeFileWarning:""},this.sessions.set(t,r)),r}constructor(e,t,r,n,o){this.basePath=e,this.logger=t,this.mainGit=r,this.metrics=n,this.workspaceStates=new Map,this.sessions=new Map,this.apiClient=o
|
|
4458
4413
|
const i=a.ConflictResolutionUtils.initializeDetectors(r,t)
|
|
4459
4414
|
this.conflictDetector=i.conflictDetector,this.safetyAnalyzer=i.safetyAnalyzer,this.conflictResolver=i.conflictResolver,this.worktreeManager=new s.WorktreeManager(e,t,n),this.gitAdapter=new l.WorktreeGitAdapter(r,this.worktreeManager,this.conflictDetector,t,n),this.requestProcessor=new c.WorkspaceRequestProcessor(this.gitAdapter,this.conflictDetector,this.safetyAnalyzer,this.conflictResolver,t),this.initializeWorktreeManager(),this.initializeFromEnv()}async initializeFromEnv(){const e=process.env.ALCHEMY_INITIAL_BRANCH
|
|
4460
4415
|
if(!e)return
|
|
@@ -4462,73 +4417,81 @@ const t=e.match(/^requests\/(.+)$/)
|
|
|
4462
4417
|
if(!t)return void this.logger.warn("ALCHEMY_INITIAL_BRANCH set but not a request branch",{initialBranch:e})
|
|
4463
4418
|
const r=t[1]
|
|
4464
4419
|
this.logger.info("ALCHEMY_INITIAL_BRANCH set, switching to worktree",{initialBranch:e,requestId:r})
|
|
4465
|
-
try{await this.ensureWorkspaceReady(r)
|
|
4420
|
+
try{await this.ensureWorkspaceReady(r)
|
|
4421
|
+
const e=this.getSession()
|
|
4422
|
+
e.readonlyBranchCheckDone=!0,this.logger.info("Successfully switched to worktree from ALCHEMY_INITIAL_BRANCH",{requestId:r,worktreePath:e.worktreePath})}catch(t){this.logger.warn("Failed to switch to worktree from ALCHEMY_INITIAL_BRANCH",{initialBranch:e,requestId:r,error:(0,i.getErrorMessage)(t)})}}hasExactConflictMarkers(e){return!(!e||!e.trim())&&[/^\s*<{7}(?:\s|$)/m,/^\s*={7}(?:\s|$)/m,/^\s*>{7}(?:\s|$)/m].some((t=>t.test(e)))}async initializeWorktreeManager(){try{await this.worktreeManager.initialize(),this.logger.debug("Initialized multi-agent workspace manager with worktrees")}catch(e){throw this.logger.error("Failed to initialize worktree manager",{error:e}),e}}setTaskCreator(e){this.taskCreator=e}async initializeRequest(e,t){const r=Date.now(),n=a.WorkspaceValidation.validateRequestId(e)
|
|
4466
4423
|
if(!n.isValid)throw Error("Invalid request ID: "+n.errors.join(", "))
|
|
4467
4424
|
const o=n.sanitized
|
|
4468
|
-
try{
|
|
4469
|
-
const n="requests/"+o,s=await this.mainGit.branch().then((e=>e.all.includes(n)||e.all.includes("remotes/origin/"+n)))
|
|
4470
|
-
if(!s){const e=await this.mainGit.revparse(["--abbrev-ref","HEAD"]),t=(await this.mainGit.branch()).all.includes("main")?"main":"master"
|
|
4471
|
-
await this.mainGit.checkout(["-b",n,t]),this.logger.info("Created branch for request",{requestId:o,branchName:n,fromBranch:t}),await this.mainGit.checkout(e),this.logger.info("Returned to original branch after creation",{returnedTo:e,createdBranch:n})}this.workspaceStates.set(o,"initialized")
|
|
4472
|
-
const i=Date.now()-r
|
|
4473
|
-
this.metrics.recordValue("workspace.initialize",i),a.WorkspaceLogging.logOperation(this.logger,"info","Successfully initialized request with branch (no worktree)",e,"multi-agent","initializeRequest",{branchName:n,branchExisted:s,duration:i,architecture:"hybrid-creation"})}catch(t){const n=Date.now()-r
|
|
4474
|
-
throw this.metrics.recordValue("workspace.initialize",n),a.WorkspaceLogging.logOperation(this.logger,"error","Failed to initialize request",e,"multi-agent","initializeRequest",{error:(0,i.getErrorMessage)(t),duration:n}),t}}async ensureWorkspaceReady(e){const t=Date.now(),r=a.WorkspaceValidation.validateRequestId(e)
|
|
4475
|
-
if(!r.isValid)throw Error("Invalid request ID: "+r.errors.join(", "))
|
|
4476
|
-
const n=r.sanitized
|
|
4477
|
-
let s=!1
|
|
4478
|
-
if(this.apiClient)try{const e=this.apiClient.getRequestClient(),t=await e.getRequest(n)
|
|
4479
|
-
if(t&&"quick-edit"===t.type){s=!0,this.logger.info("Quick-edit request detected - checking out branch in main repo (no worktree)",{requestId:n,requestType:t.type})
|
|
4480
|
-
const e="requests/"+n
|
|
4481
|
-
return(await this.mainGit.branch()).all.includes(e)?(await this.mainGit.checkout(e),this.logger.info("Checked out existing quick-edit branch in main repo",{requestId:n,branchName:e})):(await this.mainGit.checkoutLocalBranch(e),this.logger.info("Created and checked out quick-edit branch in main repo",{requestId:n,branchName:e})),this.currentRequestId=n,this.currentWorktreePath=null,this.currentGit=this.mainGit,void this.workspaceStates.set(n,"ready")}}catch(e){this.logger.warn("Failed to check request type, proceeding with normal workflow",{requestId:n,error:(0,i.getErrorMessage)(e)})}if("ready"!==this.workspaceStates.get(n)||this.currentRequestId!==n){if("ready"===this.workspaceStates.get(n)&&this.currentRequestId!==n){this.logger.info("Workspace ready but not in correct context, switching to it",{requestId:n,currentRequestId:this.currentRequestId,reason:"context_mismatch"})
|
|
4482
|
-
const e=this.worktreeManager.getWorktreeInfo(n)
|
|
4483
|
-
if(e&&e.worktreePath)return this.currentRequestId=n,this.currentWorktreePath=e.worktreePath,this.currentGit=(0,o.simpleGit)(e.worktreePath),void this.logger.info("Switched to existing ready workspace",{requestId:n,worktreePath:e.worktreePath})}try{a.WorkspaceLogging.logOperation(this.logger,"info","Ensuring workspace ready by creating/switching to worktree",e,"multi-agent","ensureWorkspaceReady",{currentState:this.workspaceStates.get(n)||"not-initialized",currentRequestId:this.currentRequestId,architecture:"hybrid-creation"})
|
|
4484
|
-
const r=await this.worktreeManager.ensureWorktreeExists(n,void 0,void 0)
|
|
4485
|
-
if(!r.success)throw Error("Failed to create worktree: "+r.message)
|
|
4486
|
-
if(this.currentRequestId=n,this.currentWorktreePath=r.worktreePath,this.currentGit=(0,o.simpleGit)(r.worktreePath),this.workspaceStates.set(n,"ready"),r.created){this.workspaceKnownClean=!0
|
|
4487
|
-
try{const e=(0,o.simpleGit)(r.worktreePath),t=(await this.mainGit.branch()).all.includes("main")?"main":"master",s=await this.mainGit.revparse([t]),i=await e.revparse(["HEAD"])
|
|
4488
|
-
s!==i&&0===(await e.log({from:t,to:"HEAD"})).total&&(await e.rebase([t]),this.logger.info("Rebased fresh request branch onto latest main",{requestId:n,mainHead:s.substring(0,8),previousHead:i.substring(0,8)}))}catch(e){this.logger.warn("Failed to rebase onto main, proceeding with existing branch",{requestId:n,error:(0,i.getErrorMessage)(e)})}}const s=Date.now()-t
|
|
4489
|
-
this.metrics.recordValue("workspace.ensure_ready",s),a.WorkspaceLogging.logOperation(this.logger,"info","Workspace is ready with worktree",e,"multi-agent","ensureWorkspaceReady",{worktreePath:r.worktreePath,branchName:r.branchName,duration:s,architecture:"hybrid-creation"})}catch(r){const n=Date.now()-t
|
|
4490
|
-
throw this.metrics.recordValue("workspace.ensure_ready",n),a.WorkspaceLogging.logOperation(this.logger,"error","Failed to ensure workspace ready",e,"multi-agent","ensureWorkspaceReady",{error:(0,i.getErrorMessage)(r),duration:n}),r}}else this.logger.debug("Workspace already ready and in correct context",{requestId:n,worktreePath:this.currentWorktreePath})}async switchToRequest(e,t){this.logger.debug("switchToRequest called",{requestId:e,options:t})
|
|
4491
|
-
const r=Date.now(),n=this.getCurrentContext()
|
|
4492
|
-
if(this.logger.debug("previousContext",{previousContext:n}),t?.isCompleted&&this.currentRequestId!==e)return this.logger.debug("Completed request detected - using simple checkout instead of worktree"),await this.switchToCompletedRequest(e,r,n)
|
|
4493
|
-
const o=a.WorkspaceValidation.validateRequestId(e)
|
|
4494
|
-
if(!o.isValid){const t="Invalid request ID: "+o.errors.join(", ")
|
|
4495
|
-
return a.WorkspaceLogging.logOperation(this.logger,"error",t,e,"multi-agent","switchToRequest"),{success:!1,message:t,previousContext:n,newContext:n}}try{this.logger.debug("About to call ensureWorkspaceReady",{requestId:o.sanitized}),await this.ensureWorkspaceReady(o.sanitized),this.logger.debug("ensureWorkspaceReady completed",{currentRequestId:this.currentRequestId,currentWorktreePath:this.currentWorktreePath})
|
|
4425
|
+
try{this.workspaceStates.set(o,"initialized")
|
|
4496
4426
|
const t=Date.now()-r
|
|
4497
|
-
|
|
4498
|
-
|
|
4499
|
-
|
|
4500
|
-
const
|
|
4501
|
-
|
|
4502
|
-
|
|
4503
|
-
|
|
4504
|
-
|
|
4505
|
-
|
|
4506
|
-
const
|
|
4507
|
-
return
|
|
4508
|
-
|
|
4427
|
+
this.metrics.recordValue("workspace.initialize",t),a.WorkspaceLogging.logOperation(this.logger,"info","Successfully initialized request (branch deferred)",e,"multi-agent","initializeRequest",{duration:t,architecture:"hybrid-creation"})}catch(t){const n=Date.now()-r
|
|
4428
|
+
throw this.metrics.recordValue("workspace.initialize",n),a.WorkspaceLogging.logOperation(this.logger,"error","Failed to initialize request",e,"multi-agent","initializeRequest",{error:(0,i.getErrorMessage)(t),duration:n}),t}}async ensureWorkspaceReady(e,t){const r=this.getSession(t),n=Date.now(),s=a.WorkspaceValidation.validateRequestId(e)
|
|
4429
|
+
if(!s.isValid)throw Error("Invalid request ID: "+s.errors.join(", "))
|
|
4430
|
+
const c=s.sanitized
|
|
4431
|
+
let l=!1
|
|
4432
|
+
if(this.apiClient)try{const e=this.apiClient.getRequestClient(),t=await e.getRequest(c)
|
|
4433
|
+
if(t&&"quick-edit"===t.type){l=!0,this.logger.info("Quick-edit request detected - checking out branch in main repo (no worktree)",{requestId:c,requestType:t.type})
|
|
4434
|
+
const e="requests/"+c
|
|
4435
|
+
return(await this.mainGit.branch()).all.includes(e)?(await this.mainGit.checkout(e),this.logger.info("Checked out existing quick-edit branch in main repo",{requestId:c,branchName:e})):(await this.mainGit.checkoutLocalBranch(e),this.logger.info("Created and checked out quick-edit branch in main repo",{requestId:c,branchName:e})),r.requestId=c,r.worktreePath=null,r.git=this.mainGit,void this.workspaceStates.set(c,"ready")}}catch(e){this.logger.warn("Failed to check request type, proceeding with normal workflow",{requestId:c,error:(0,i.getErrorMessage)(e)})}if("ready"!==this.workspaceStates.get(c)||r.requestId!==c){if("ready"===this.workspaceStates.get(c)&&r.requestId!==c){this.logger.info("Workspace ready but not in correct context, switching to it",{requestId:c,currentRequestId:r.requestId,reason:"context_mismatch"})
|
|
4436
|
+
const e=this.worktreeManager.getWorktreeInfo(c)
|
|
4437
|
+
if(e&&e.worktreePath)return r.requestId=c,r.worktreePath=e.worktreePath,r.git=(0,o.simpleGit)(e.worktreePath),void this.logger.info("Switched to existing ready workspace",{requestId:c,worktreePath:e.worktreePath})}try{a.WorkspaceLogging.logOperation(this.logger,"info","Ensuring workspace ready by creating/switching to worktree",e,"multi-agent","ensureWorkspaceReady",{currentState:this.workspaceStates.get(c)||"not-initialized",currentRequestId:r.requestId,architecture:"hybrid-creation"})
|
|
4438
|
+
const t=await this.worktreeManager.ensureWorktreeExists(c,void 0,void 0)
|
|
4439
|
+
if(!t.success)throw Error("Failed to create worktree: "+t.message)
|
|
4440
|
+
if(r.requestId=c,r.worktreePath=t.worktreePath,r.git=(0,o.simpleGit)(t.worktreePath),this.workspaceStates.set(c,"ready"),t.created){r.workspaceKnownClean=!0
|
|
4441
|
+
try{const e=(0,o.simpleGit)(t.worktreePath),r=(await this.mainGit.branch()).all.includes("main")?"main":"master",n=await this.mainGit.revparse([r]),s=await e.revparse(["HEAD"])
|
|
4442
|
+
n!==s&&0===(await e.log({from:r,to:"HEAD"})).total&&(await e.rebase([r]),this.logger.info("Rebased fresh request branch onto latest main",{requestId:c,mainHead:n.substring(0,8),previousHead:s.substring(0,8)}))}catch(e){this.logger.warn("Failed to rebase onto main, proceeding with existing branch",{requestId:c,error:(0,i.getErrorMessage)(e)})}}const s=Date.now()-n
|
|
4443
|
+
this.metrics.recordValue("workspace.ensure_ready",s),a.WorkspaceLogging.logOperation(this.logger,"info","Workspace is ready with worktree",e,"multi-agent","ensureWorkspaceReady",{worktreePath:t.worktreePath,branchName:t.branchName,duration:s,architecture:"hybrid-creation"})}catch(t){const r=Date.now()-n
|
|
4444
|
+
throw this.metrics.recordValue("workspace.ensure_ready",r),a.WorkspaceLogging.logOperation(this.logger,"error","Failed to ensure workspace ready",e,"multi-agent","ensureWorkspaceReady",{error:(0,i.getErrorMessage)(t),duration:r}),t}}else this.logger.debug("Workspace already ready and in correct context",{requestId:c,worktreePath:r.worktreePath})}async switchToRequest(e,t){const r=t?.sessionId,n=this.getSession(r)
|
|
4445
|
+
this.logger.debug("switchToRequest called",{requestId:e,options:t,sessionId:r})
|
|
4446
|
+
const o=Date.now(),s=this.getCurrentContext(r)
|
|
4447
|
+
if(this.logger.debug("previousContext",{previousContext:s}),t?.isCompleted&&n.requestId!==e)return this.logger.debug("Completed request detected - using simple checkout instead of worktree"),await this.switchToCompletedRequest(e,o,s)
|
|
4448
|
+
const c=a.WorkspaceValidation.validateRequestId(e)
|
|
4449
|
+
if(!c.isValid){const t="Invalid request ID: "+c.errors.join(", ")
|
|
4450
|
+
return a.WorkspaceLogging.logOperation(this.logger,"error",t,e,"multi-agent","switchToRequest"),{success:!1,message:t,previousContext:s,newContext:s}}try{this.logger.debug("About to call ensureWorkspaceReady",{requestId:c.sanitized}),await this.ensureWorkspaceReady(c.sanitized,r),this.logger.debug("ensureWorkspaceReady completed",{currentRequestId:n.requestId,currentWorktreePath:n.worktreePath})
|
|
4451
|
+
const t=Date.now()-o
|
|
4452
|
+
return this.metrics?.recordValue("workspace_switch_duration",t),a.WorkspaceLogging.logOperation(this.logger,"info","Switched to worktree for request",e,"multi-agent","switchToRequest",{worktreePath:n.worktreePath,duration:t}),{success:!0,message:"Switched to worktree for request: "+e,previousContext:s,newContext:this.getCurrentContext(r),worktreePath:n.worktreePath}}catch(t){const r=Date.now()-o
|
|
4453
|
+
return this.metrics?.recordValue("workspace_switch_duration",r),a.WorkspaceLogging.logOperation(this.logger,"error","Failed to switch to request",e,"multi-agent","switchToRequest",{error:(0,i.getErrorMessage)(t),duration:r}),{success:!1,message:"Failed to switch to request: "+(0,i.getErrorMessage)(t),previousContext:s,newContext:s}}}async switchToCompletedRequest(e,t,r){try{const n="requests/"+e
|
|
4454
|
+
a.WorkspaceLogging.logOperation(this.logger,"info","Switching to completed request (no worktree)",e,"multi-agent","switchToCompletedRequest",{branchName:n}),await this.mainGit.checkout(n)
|
|
4455
|
+
const o=this.getSession()
|
|
4456
|
+
o.requestId=e,o.worktreePath=null,o.git=this.mainGit
|
|
4457
|
+
const s=Date.now()-t
|
|
4458
|
+
return this.metrics?.recordValue("workspace_switch_duration",s),a.WorkspaceLogging.logOperation(this.logger,"info","Successfully switched to completed request branch",e,"multi-agent","switchToCompletedRequest",{branchName:n,duration:s,worktree:!1}),{success:!0,message:`Switched to completed request branch: ${n} (no worktree)`,previousContext:r,newContext:this.getCurrentContext()}}catch(n){const o=Date.now()-t
|
|
4459
|
+
return this.metrics?.recordValue("workspace_switch_duration",o),a.WorkspaceLogging.logOperation(this.logger,"error","Failed to switch to completed request",e,"multi-agent","switchToCompletedRequest",{error:(0,i.getErrorMessage)(n),duration:o}),{success:!1,message:"Failed to switch to completed request: "+(0,i.getErrorMessage)(n),previousContext:r,newContext:r}}}async switchToMain(e){const t=this.getSession(e),r=this.getCurrentContext(e)
|
|
4460
|
+
return t.requestId=null,t.worktreePath=null,t.git=this.mainGit,this.logger.info("Switched to main repository context"),{success:!0,message:"Switched to main repository",previousContext:r,newContext:this.getCurrentContext(e)}}async commitChanges(e,t,r){const n=this.getSession(r),o=Date.now()
|
|
4461
|
+
if(!n.requestId||!n.worktreePath)throw new a.ConflictDetectionError("No active request context for commit","multi-agent-commit",[])
|
|
4462
|
+
try{t&&t.length>0?await n.git.add(t):await n.git.add("."),await n.git.commit(e)
|
|
4463
|
+
const r=await n.git.revparse(["HEAD"]),s=Date.now()-o
|
|
4464
|
+
return this.metrics?.recordValue("workspace_commit_duration",s),this.logger.info("Successfully committed changes in worktree",{requestId:n.requestId,worktreePath:n.worktreePath,message:e,commitHash:r.substring(0,8),filesCount:t?.length||"all",duration:s}),{hash:r,message:e,files:t||[]}}catch(t){const r=Date.now()-o
|
|
4465
|
+
throw this.metrics?.recordValue("workspace_commit_duration",r),this.logger.error("Failed to commit changes in worktree",{requestId:n.requestId,worktreePath:n.worktreePath,message:e,error:(0,i.getErrorMessage)(t),duration:r}),new a.ConflictDetectionError("Failed to commit changes: "+(0,i.getErrorMessage)(t),"multi-agent-commit",[])}}async completeRequest(e,t,r){const n=Date.now()
|
|
4509
4466
|
try{a.WorkspaceLogging.logOperation(this.logger,"info","Starting request completion (refactored)",e,"multi-agent","completeRequest",{requestTitle:t,skipConflictDetection:r?.skipConflictDetection||!1,architecture:"shared-processor"})
|
|
4510
4467
|
const o=await this.requestProcessor.completeRequest(e,t,{skipConflictDetection:r?.skipConflictDetection||!1}),s=Date.now()-n
|
|
4511
|
-
|
|
4512
|
-
|
|
4513
|
-
|
|
4514
|
-
throw this.
|
|
4468
|
+
this.metrics?.recordValue("workspace_complete_duration",s),this.metrics?.incrementCounter("workspace_complete_success",1)
|
|
4469
|
+
for(const[t,r]of this.sessions)r.requestId===e&&(r.requestId=null,r.worktreePath=null,r.git=this.mainGit)
|
|
4470
|
+
return a.WorkspaceLogging.logOperation(this.logger,"info","Request completion successful (refactored)",e,"multi-agent","completeRequest",{mergeCommitHash:o.mergeCommitHash.substring(0,8),mergedFiles:o.mergedFiles?.length||0,cleanedUp:o.cleanedUp,wasAutoMerged:o.autoMergeInfo?.wasAutoMerged,strategy:o.autoMergeInfo?.strategy,duration:s,architecture:"shared-processor"}),o}catch(t){const r=Date.now()-n
|
|
4471
|
+
throw this.metrics?.recordValue("workspace_complete_duration",r),this.metrics?.incrementCounter("workspace_complete_error",1),a.WorkspaceLogging.logOperation(this.logger,"error","Request completion failed (refactored)",e,"multi-agent","completeRequest",{error:(0,i.getErrorMessage)(t),duration:r,architecture:"shared-processor"}),t}}resolveFilePath(e,t){const r=this.getSession(t)
|
|
4472
|
+
if(r.worktreePath)return this.logger.debug("Resolving file path in worktree context",{relativePath:e,worktreePath:r.worktreePath,requestId:r.requestId}),n.default.resolve(r.worktreePath,e)
|
|
4473
|
+
const o=`Cannot resolve file path in multi-agent mode without request context. Current state: requestId=${r.requestId}, worktreePath=${r.worktreePath}. Ensure you switch to a request workspace before performing file operations.`
|
|
4474
|
+
throw this.logger.error("Unsafe file path resolution attempt in multi-agent mode",{relativePath:e,currentRequestId:r.requestId,currentWorktreePath:r.worktreePath,basePath:this.basePath,action:"preventing_fallback_to_main"}),Error(o)}resolveMainBranchFilePath(e){return this.logger.debug("Resolving file path in main branch context",{relativePath:e,basePath:this.basePath,context:"explicit_main_branch_operation"}),n.default.resolve(this.basePath,e)}async createCommit(e,t,r){return await this.commitChanges(e,t,r)}async cancelRequest(e){const t=a.WorkspaceValidation.validateRequestId(e)
|
|
4515
4475
|
if(!t.isValid)throw Error("Invalid request ID: "+t.errors.join(", "))
|
|
4516
4476
|
const r=t.sanitized
|
|
4517
|
-
try{this.
|
|
4477
|
+
try{for(const[e,t]of this.sessions)t.requestId===r&&(t.requestId=null,t.worktreePath=null,t.git=this.mainGit)
|
|
4518
4478
|
const e=await this.worktreeManager.removeWorktree(r,!1)
|
|
4519
4479
|
if(!e.success)throw Error(e.message||"Failed to remove worktree")
|
|
4520
|
-
this.logger.info("Successfully cancelled request",{requestId:r})}catch(e){throw this.logger.error("Failed to cancel request",{requestId:r,error:(0,i.getErrorMessage)(e)}),e}}getCurrentContext(){const e={requestId:
|
|
4521
|
-
return this.logger.debug("getCurrentContext returning",{context:e}),
|
|
4480
|
+
this.logger.info("Successfully cancelled request",{requestId:r})}catch(e){throw this.logger.error("Failed to cancel request",{requestId:r,error:(0,i.getErrorMessage)(e)}),e}}getCurrentContext(e){const t=this.getSession(e),r={requestId:t.requestId,basePath:t.worktreePath||this.basePath,branchName:t.requestId?"requests/"+t.requestId:"main",isMainBranch:!t.requestId,mode:"multi-agent"}
|
|
4481
|
+
return this.logger.debug("getCurrentContext returning",{context:r,sessionId:e}),r}resetCurrentContext(e){const t=this.getSession(e)
|
|
4482
|
+
t.requestId&&this.logger.info("Resetting workspace context (session switch)",{prevRequestId:t.requestId,prevWorktreePath:t.worktreePath,sessionId:e}),t.requestId=null,t.worktreePath=null,t.git=this.mainGit,t.readonlyBranchCheckDone=!1}async getWorkspaceInfo(e){try{const t=a.WorkspaceValidation.validateRequestId(e)
|
|
4522
4483
|
if(!t.isValid)return null
|
|
4523
4484
|
const r=t.sanitized,n=await this.getWorktreeInfo(r)
|
|
4524
|
-
return n?{requestId:r,path:n.worktreePath,branchName:n.branchName,isActive:this.
|
|
4525
|
-
return t?t[1]:null}convertWorktreeInfoToWorkspaceInfo(e){return{requestId:e.requestId,path:e.worktreePath,branchName:e.branchName,isActive:this.
|
|
4526
|
-
return this.worktreeManager.getWorktreeInfo(t)}catch(t){return void this.logger.warn("Failed to get worktree info",{requestId:e,error:(0,i.getErrorMessage)(t)})}}getMainGit(){return this.gitAdapter.getMainGit()}getCurrentGit(){return this.
|
|
4527
|
-
|
|
4528
|
-
const
|
|
4529
|
-
if(o){
|
|
4485
|
+
return n?{requestId:r,path:n.worktreePath,branchName:n.branchName,isActive:this.isActiveForAnySession(r),created:new Date,lastAccessed:new Date}:null}catch(t){return this.logger.error("Failed to get workspace info",{requestId:e,error:(0,i.getErrorMessage)(t)}),null}}async listActiveWorkspaces(){try{return(await this.worktreeManager.listActiveWorktrees()).map((e=>this.convertWorktreeInfoToWorkspaceInfo(e)))}catch(e){return this.logger.error("Failed to list active workspaces",{error:(0,i.getErrorMessage)(e)}),[]}}extractRequestIdFromBranch(e){const t=e.match(/^requests\/(.+)$/)
|
|
4486
|
+
return t?t[1]:null}convertWorktreeInfoToWorkspaceInfo(e){return{requestId:e.requestId,path:e.worktreePath,branchName:e.branchName,isActive:this.isActiveForAnySession(e.requestId),created:e.created,lastAccessed:e.lastAccessed}}async getWorktreeInfo(e){try{const t=e.replace(/[^a-zA-Z0-9_-]/g,"_")
|
|
4487
|
+
return this.worktreeManager.getWorktreeInfo(t)}catch(t){return void this.logger.warn("Failed to get worktree info",{requestId:e,error:(0,i.getErrorMessage)(t)})}}getMainGit(){return this.gitAdapter.getMainGit()}getCurrentGit(e){return this.getSession(e).git}get readonlyBranchCheckDone(){return this.getSession().readonlyBranchCheckDone}set readonlyBranchCheckDone(e){this.getSession().readonlyBranchCheckDone=e}get workspaceKnownClean(){return this.getSession().workspaceKnownClean}set workspaceKnownClean(e){this.getSession().workspaceKnownClean=e}get largeFileWarning(){return this.getSession().largeFileWarning}set largeFileWarning(e){this.getSession().largeFileWarning=e}async ensureReadonlyBranchIfNeeded(e,r,n,o){const s=this.getSession(o)
|
|
4488
|
+
if(s.readonlyBranchCheckDone)return
|
|
4489
|
+
if(s.readonlyBranchCheckDone=!0,o&&n)try{const{sessionIdentity:e}=await Promise.resolve().then(t.bind(t,6688)),r=await e.getSessionRequestId(n,this.logger,o)
|
|
4490
|
+
if(r)return await this.ensureWorkspaceReady(r,o),void this.logger.info("ensureReadonlyBranchIfNeeded: workspace ready from session DB lookup",{requestId:r,sessionId:o})}catch(e){this.logger.warn("ensureReadonlyBranchIfNeeded: session DB lookup failed, falling back to env var",{error:(0,i.getErrorMessage)(e)})}const a=process.env.ALCHEMY_INITIAL_BRANCH
|
|
4491
|
+
if(a){const e=a.match(/^requests\/(.+)$/)
|
|
4530
4492
|
if(e){const t=e[1]
|
|
4531
|
-
try{await this.ensureWorkspaceReady(t),this.logger.info("ensureReadonlyBranchIfNeeded: workspace ready",{requestId:t})}catch(e){this.logger.warn("ensureReadonlyBranchIfNeeded: failed to ensure workspace",{requestId:t,error:(0,i.getErrorMessage)(e)})}}}}
|
|
4493
|
+
try{await this.ensureWorkspaceReady(t,o),this.logger.info("ensureReadonlyBranchIfNeeded: workspace ready from env var",{requestId:t})}catch(e){this.logger.warn("ensureReadonlyBranchIfNeeded: failed to ensure workspace",{requestId:t,error:(0,i.getErrorMessage)(e)})}}}}isActiveForAnySession(e){for(const[,t]of this.sessions)if(t.requestId===e)return!0
|
|
4494
|
+
return!1}async cleanup(){this.logger.info("Cleaning up multi-agent workspace manager"),this.sessions.clear()}}exports.MultiAgentWorkspaceManager=d,d.DEFAULT_SESSION="__default__"},7645(e,exports,t){Object.defineProperty(exports,"__esModule",{value:!0}),exports.ConnectionAwareClient=void 0
|
|
4532
4495
|
const r=t(4192),n=t(7163)
|
|
4533
4496
|
class o extends r.BaseApiClient{constructor(e,t,r,o,s,i){t.debug("ConnectionAwareClient constructor parameters:",{hasAuthToken:!!o,hasOptions:!!s,optionsType:s?typeof s:"undefined",options:s?JSON.stringify(s):"undefined",hasConnectionManager:!!i}),super(e,t,r,o,s),this.isGettingAuthToken=!1,this.connectionStatusManager=i||{isInOfflineMode(){return!1},isOffline(){return!1},setOfflineMode(){},async checkConnectivity(){return!0},getHealthCheckStats(){return{isOffline:!1,consecutiveFailures:0,currentBackoffMs:0,lastCheckTime:0}},cleanup(){}},o&&this.logger.debug("Client initialized with auth token",{clientType:this.constructor.name,tokenPrefix:o.substring(0,10)+"..."})
|
|
4534
4497
|
try{(0,n.debugTokenAccess)(this,"ConnectionAwareClient constructor")}catch(e){this.logger.debug("Error accessing token details during init",{error:e instanceof Error?e.message:e+""})}}setConnectionStatusManager(e){this.logger.debug("Setting connection status manager in ConnectionAwareClient"),this.connectionStatusManager=e}}exports.ConnectionAwareClient=o},7660(e,exports,t){Object.defineProperty(exports,"__esModule",{value:!0}),exports.projectContextMiddleware=exports.ProjectContext=exports.ProjectIDFactory=exports.ProjectID=void 0
|
|
@@ -4546,20 +4509,20 @@ return o(t,e),t})
|
|
|
4546
4509
|
Object.defineProperty(exports,"__esModule",{value:!0}),exports.handleManageFiles=async function(e,t,r,n,o,s,g,p,f){const m=g.child({tool:"manage_files"})
|
|
4547
4510
|
try{const h=a.validateArgs(e,i.ManageFilesSchema),{taskId:g,operations:y,comment:w}=h
|
|
4548
4511
|
m.info("Processing manage-files operations",{taskId:g,operationCount:y.length,comment:w})
|
|
4549
|
-
const b=[],
|
|
4512
|
+
const b=[],k=[],I=[],v=[]
|
|
4550
4513
|
for(const e of y)switch(e.operationType){case"create-directory":b.push({path:e.createDirectory.path})
|
|
4551
4514
|
break
|
|
4552
|
-
case"move-files":for(const t of e.moveFiles.moves)
|
|
4515
|
+
case"move-files":for(const t of e.moveFiles.moves)k.push(t)
|
|
4553
4516
|
break
|
|
4554
|
-
case"delete-files":
|
|
4517
|
+
case"delete-files":I.push(...e.deleteFiles.targets)
|
|
4555
4518
|
break
|
|
4556
4519
|
case"get-file-info":v.push({path:e.getFileInfo.path})}const C=[]
|
|
4557
4520
|
for(const e of b){m.info("Routing to create-directory handler",{path:e.path})
|
|
4558
4521
|
const s=await(0,c.handleCreateDirectory)({taskId:g,path:e.path,comment:w+" [via manage-files: create-directory]"},t,r,n,o,m,p,f)
|
|
4559
|
-
C.push({type:"create-directory",result:s})}if(
|
|
4560
|
-
const e=await(0,l.handleMoveFiles)({taskId:g,operations:
|
|
4561
|
-
C.push({type:"move-files",result:e})}if(
|
|
4562
|
-
const e=await(0,u.handleDeleteFiles)({taskId:g,operations:
|
|
4522
|
+
C.push({type:"create-directory",result:s})}if(k.length>0){m.info("Routing to move-files handler",{operationCount:k.length})
|
|
4523
|
+
const e=await(0,l.handleMoveFiles)({taskId:g,operations:k,comment:w+" [via manage-files: move-files]"},t,r,n,o,m,p,f)
|
|
4524
|
+
C.push({type:"move-files",result:e})}if(I.length>0){m.info("Routing to delete-files handler",{operationCount:I.length})
|
|
4525
|
+
const e=await(0,u.handleDeleteFiles)({taskId:g,operations:I,comment:w+" [via manage-files: delete-files]"},t,s,m,p,f)
|
|
4563
4526
|
C.push({type:"delete-files",result:e})}for(const e of v){m.info("Routing to get-file-info handler",{path:e.path})
|
|
4564
4527
|
const r=await(0,d.handleGetFileInfo)({path:e.path},t,m,p)
|
|
4565
4528
|
C.push({type:"get-file-info",result:r})}const _=C.some((e=>e.result.isError)),E=C.filter((e=>!e.result.isError)).length,q=C.filter((e=>e.result.isError)).length
|
|
@@ -4649,19 +4612,19 @@ const n=r(t(6982))
|
|
|
4649
4612
|
class o{static create(){return exports.ProjectIDFactory.create()}static fromString(e){return exports.ProjectIDFactory.fromString(e)}static isValid(e){return exports.ProjectIDFactory.isValid(e)}constructor(e){this.id=e}toString(){return this.id}equals(e){return this.id===e.toString()}isStandardFormat(){return this.id.includes("_")&&this.id.startsWith("prj_")}}exports.ProjectID=o,exports.ProjectIDFactory={create(){const e=Date.now().toString().substring(5),t=n.default.randomBytes(4).toString("hex")
|
|
4650
4613
|
return o.fromString(`prj_${e}_${t}`)},fromString(e){return this.isValid(e)?new o(e):null},isValid(e){if(!e||"string"!=typeof e||5>e.length||!e.startsWith("prj"))return!1
|
|
4651
4614
|
if(e.includes("_")){const t=e.split("_")
|
|
4652
|
-
return t.length>=3&&"prj"===t[0]}return!1}},exports.ProjectIDBackwardCompat={create:exports.ProjectIDFactory.create,fromString:exports.ProjectIDFactory.fromString,isValid:exports.ProjectIDFactory.isValid},Object.assign(o,exports.ProjectIDBackwardCompat)},8035(e,exports,t){function r(e,t,r){try{const n=`[${(new Date).toISOString()}] [detached-subagent] ${t}${r?" "+JSON.stringify(r):""}\n`,o=(0,a.join)(e||process.cwd(),".alchemy_lab","spawn-debug.log");(0,i.appendFileSync)(o,n)}catch{}}function n(e){const{agent:t,prompt:n,cwd:
|
|
4615
|
+
return t.length>=3&&"prj"===t[0]}return!1}},exports.ProjectIDBackwardCompat={create:exports.ProjectIDFactory.create,fromString:exports.ProjectIDFactory.fromString,isValid:exports.ProjectIDFactory.isValid},Object.assign(o,exports.ProjectIDBackwardCompat)},8035(e,exports,t){function r(e,t,r){try{const n=`[${(new Date).toISOString()}] [detached-subagent] ${t}${r?" "+JSON.stringify(r):""}\n`,o=(0,a.join)(e||process.cwd(),".alchemy_lab","spawn-debug.log");(0,i.appendFileSync)(o,n)}catch{}}function n(e){const{agent:t,prompt:n,cwd:l,parentServerUrl:d,parentSessionId:u,sessionId:h,model:g,initialBranch:p,serverUrl:f,onSpawn:m,onError:y}=e
|
|
4653
4616
|
try{const s={...process.env}
|
|
4654
|
-
|
|
4655
|
-
const
|
|
4656
|
-
let
|
|
4657
|
-
if(s.ALCHEMY_SESSION_TAG=`mcp-${
|
|
4658
|
-
e>0?
|
|
4659
|
-
const
|
|
4660
|
-
let
|
|
4661
|
-
try{
|
|
4662
|
-
return
|
|
4663
|
-
return
|
|
4664
|
-
const o=t(5317),s=t(8824),i=t(9896),a=t(6928)},8037(e,exports,t){Object.defineProperty(exports,"__esModule",{value:!0}),exports.handleListRequests=async function(e,t,i,a,c){const l=a.child({tool:"list_requests"}),d=c.startTimer("tool_execution_time")
|
|
4617
|
+
d&&(s.OPENCODE_PARENT_SERVER=d),p&&(s.ALCHEMY_INITIAL_BRANCH=p),e.allowParallel&&(s.ALCHEMY_ALLOW_PARALLEL="1")
|
|
4618
|
+
const u=new Date,y=`${(u.getHours()+"").padStart(2,"0")}${(u.getMinutes()+"").padStart(2,"0")}${(u.getSeconds()+"").padStart(2,"0")}`,w=Math.random().toString(36).substring(2,7)
|
|
4619
|
+
let b
|
|
4620
|
+
if(s.ALCHEMY_SESSION_TAG=`mcp-${y}-${w}`,r(l,"Spawn env setup",{agent:t,initialBranch:p||"none",hasParentServer:!!d,sessionId:h||"new",attachMode:!!f}),b=f&&h&&n?["run","--attach",f,"--session",h,"--agent",t,n]:h&&n?["run","--session",h,"--agent",t,n]:n?["run","--agent",t,n]:["run","--agent",t],g){const e=b.findIndex((e=>e===n))
|
|
4621
|
+
e>0?b.splice(e,0,"--model",g):b.push("--model",g)}r(l,"Spawning opencode",{args:b.map((e=>e===n?`[prompt:${e.length}chars]`:e)),model:g||"not specified",promptLength:n?.length,promptPreview:n?.slice(0,100),cwd:l,hasSessionId:!!h,hasParentServerUrl:!!d})
|
|
4622
|
+
const k=(0,a.join)(l||process.cwd(),".alchemy_lab"),I=(0,a.join)(k,"spawn-stderr.log")
|
|
4623
|
+
let v
|
|
4624
|
+
try{v=(0,i.openSync)(I,"a")}catch{}const C=(0,c.resolveRunCommand)(),_=(0,o.spawn)(C.command,[...C.prependArgs,...b],{detached:!0,stdio:["ignore","ignore",v??"ignore"],cwd:l||process.cwd(),env:s})
|
|
4625
|
+
return _.unref(),m&&m(_.pid),{success:!0,pid:_.pid}}catch(e){const t=(0,s.getErrorMessage)(e)
|
|
4626
|
+
return y&&e instanceof Error&&y(e),{success:!1,error:t}}}Object.defineProperty(exports,"__esModule",{value:!0}),exports.spawnDetachedSubagent=n,exports.spawnJournalSubagent=function(e,t,r,o){return n({agent:"journal",prompt:`Generate a journal entry for request ${e}.\n\nSteps:\n1. Use ${t}__generate_request_journal tool with requestId: ${e}\n2. Write a concise narrative journal entry based on the returned data covering:\n - What was implemented and why\n - Key decisions and trade-offs made\n - Challenges encountered and solutions\n - Files modified and their purposes\n - How acceptance criteria were met\n3. Save as JOURNAL-${e}.md using ${t}__document_operations (operation: create, type: Report)\n\nKeep it story-focused and informative.`,cwd:r,parentServerUrl:o})},exports.spawnWorkSubagent=function(e,t,r){return n({agent:"work",prompt:e,cwd:t,parentServerUrl:r})}
|
|
4627
|
+
const o=t(5317),s=t(8824),i=t(9896),a=t(6928),c=t(9068)},8037(e,exports,t){Object.defineProperty(exports,"__esModule",{value:!0}),exports.handleListRequests=async function(e,t,i,a,c){const l=a.child({tool:"list_requests"}),d=c.startTimer("tool_execution_time")
|
|
4665
4628
|
try{const{filters:s={}}=e,a=["open","in_progress","ready_for_review","completed","canceled","reverted"]
|
|
4666
4629
|
if(s.status&&!a.includes(s.status))throw new r.ValidationError(`Invalid status: ${s.status}. Must be one of: ${a.join(", ")}`)
|
|
4667
4630
|
if(void 0!==s.limit&&1>s.limit)throw new r.ValidationError("Limit must be at least 1")
|
|
@@ -4737,31 +4700,31 @@ if(null!=e)for(var s=r(e),i=0;i<s.length;i++)"default"!==s[i]&&n(t,e,s[i])
|
|
|
4737
4700
|
return o(t,e),t}),i=this&&this.__importDefault||function(e){return e&&e.__esModule?e:{default:e}}
|
|
4738
4701
|
Object.defineProperty(exports,"__esModule",{value:!0}),exports.handleCreateDirectory=async function(e,t,r,n,o,s,i,p){const f=s.child({tool:"create_directory"}),m=Date.now()
|
|
4739
4702
|
let y,w,b=d.FileOperationPhase.VALIDATION
|
|
4740
|
-
const
|
|
4703
|
+
const k={toolName:"create-directory",operationName:"create",fileOperationPhase:d.FileOperationPhase.FILE_WRITE,recordType:"create-directory",metricsPrefix:"create_directory",successMessage:"Successfully created directory {path}",failureMessage:"Failed to create directory {path}"}
|
|
4741
4704
|
try{const s=d.validateArgs(e,l.CreateDirectorySchema),{taskId:u,path:h,comment:g}=s
|
|
4742
|
-
f.info("Creating directory: "+h,{taskId:u,path:h,comment:g}),d.validateTaskIdFormat(u,f,i,
|
|
4743
|
-
const{normalizedPath:
|
|
4705
|
+
f.info("Creating directory: "+h,{taskId:u,path:h,comment:g}),d.validateTaskIdFormat(u,f,i,k.metricsPrefix),t.getCurrentBranchContext&&await t.getCurrentBranchContext()
|
|
4706
|
+
const{normalizedPath:I,fullPath:v}=d.validateAndNormalizePath(h,t)
|
|
4744
4707
|
b=d.FileOperationPhase.TASK_VALIDATION,i.incrementCounter("create_directory_phase",1,{phase:b})
|
|
4745
|
-
const C=await d.validateTaskId(u,
|
|
4746
|
-
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:
|
|
4747
|
-
const S=await d.ensureCorrectWorkspaceContext({taskPromoted:q.taskPromoted,requestId:_,context:t,operation:"create-directory",logger:f,metrics:i,metricsPrefix:
|
|
4708
|
+
const C=await d.validateTaskId(u,I,r,f,i,k.metricsPrefix),_=C?.requestId,E=await d.validateWorkItemStates(u,I,r,o,t,f,i,k.metricsPrefix),q=await d.autoPromoteTaskStatus(u,C.status,_,E.request?.status,I,r,o,f,i,k.metricsPrefix)
|
|
4709
|
+
q.taskPromoted&&f.info(`Auto-promoted task ${u} (${C.title||"Untitled"}) to in_progress for file operation`,{taskId:u,taskTitle:C.title,previousStatus:C.status,newStatus:q.newTaskStatus,path:I}),q.requestPromoted&&f.info(`Auto-promoted request ${_} to in_progress for file operation`,{requestId:_,previousStatus:E.request?.status,newStatus:q.newRequestStatus,triggeringTaskId:u})
|
|
4710
|
+
const S=await d.ensureCorrectWorkspaceContext({taskPromoted:q.taskPromoted,requestId:_,context:t,operation:"create-directory",logger:f,metrics:i,metricsPrefix:k.metricsPrefix})
|
|
4748
4711
|
if(!S.success){if(S.isLockConflict)return{content:[{type:"text",text:"\u274c "+S.error}],isError:!0}
|
|
4749
4712
|
throw Error(S.error)}let T=!1
|
|
4750
4713
|
try{T=(await a.default.stat(v)).isDirectory()}catch{T=!1}b=d.FileOperationPhase.RECORD_CREATION,i.incrementCounter("create_directory_phase",1,{phase:b})
|
|
4751
|
-
const{toolRecordId:P,localToolRecordId:R}=await d.createFileOperationRecords(u,_,t.projectId,
|
|
4752
|
-
y=P,w=P,b=
|
|
4714
|
+
const{toolRecordId:P,localToolRecordId:R}=await d.createFileOperationRecords(u,_,t.projectId,k.recordType,I,{directoryExists:T,userComment:g},r,n,f,i,k.metricsPrefix,p)
|
|
4715
|
+
y=P,w=P,b=k.fileOperationPhase,i.incrementCounter("create_directory_phase",1,{phase:b})
|
|
4753
4716
|
let M=T
|
|
4754
|
-
if(!T){await a.default.mkdir(v,{recursive:!0}),f.info("Successfully created directory "+
|
|
4717
|
+
if(!T){await a.default.mkdir(v,{recursive:!0}),f.info("Successfully created directory "+I)
|
|
4755
4718
|
try{const e=c.default.join(v,".gitkeep")
|
|
4756
4719
|
await a.default.writeFile(e,"# This file makes the directory trackable by Git\n"),M=!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+""}),M=!1}}const j=Date.now()-m
|
|
4757
4720
|
i.recordValue("create_directory_time",j),i.incrementCounter("create_directory_success",1),b=d.FileOperationPhase.GIT_COMMIT,i.incrementCounter("create_directory_phase",1,{phase:b})
|
|
4758
|
-
const x=`Create directory: ${
|
|
4759
|
-
b=d.FileOperationPhase.RECORD_UPDATE_SUCCESS,i.incrementCounter("create_directory_phase",1,{phase:b}),await d.updateFileOperationRecords(u,y,w,k
|
|
4721
|
+
const x=`Create directory: ${I} - ${g||"Create directory"}`,O=!T&&M?I+"/.gitkeep":I,D=await d.commitToGit(u,O,P,R,x,t,f,i,k.metricsPrefix)
|
|
4722
|
+
b=d.FileOperationPhase.RECORD_UPDATE_SUCCESS,i.incrementCounter("create_directory_phase",1,{phase:b}),await d.updateFileOperationRecords(u,y,w,I,k.recordType,`Successfully ${T?"verified":"created"} directory: ${I}`,{status:"completed",commitHash:D.commitHash,previousCommitHash:D.previousCommitHash,directoryExists:T,isDirectory:!0,userComment:g},`Successfully ${T?"verified":"created"} directory: ${I}`,r,n,f,i,k.metricsPrefix)
|
|
4760
4723
|
const A=t.getCurrentBranchContext?await t.getCurrentBranchContext():{branch:null,requestId:null,isMain:!0}
|
|
4761
4724
|
return{content:[{type:"text",text:T?"Directory already exists":`Successfully created directory${D.commitHash?"\nCommit: "+D.commitHash.substring(0,8):""}${A.requestId?"\nBranch: "+A.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
|
|
4762
4725
|
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:b,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
|
|
4763
4726
|
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){b=d.FileOperationPhase.RECORD_UPDATE_FAILURE
|
|
4764
|
-
try{await d.updateFileOperationRecords(e.taskId,y,w,e.path,
|
|
4727
|
+
try{await d.updateFileOperationRecords(e.taskId,y,w,e.path,k.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,k.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,b,f,i,e,k)}}
|
|
4765
4728
|
const a=i(t(1943)),c=i(t(6928)),l=t(6183),d=s(t(5967)),u=t(9860),h=t(1569),g=t(8824)},8317(e,exports,t){function r(e){const t=[]
|
|
4766
4729
|
return"write-file"===e.type&&e.metadata?.path?t.push(e.metadata.path):"replace-in-files"===e.type&&e.metadata?.operations?e.metadata.operations.forEach((e=>{e.path&&t.push(e.path)})):"move-files"===e.type&&e.metadata?.successfulOperations?e.metadata.successfulOperations.forEach((e=>{e.destination&&t.push(e.destination)})):"delete-files"===e.type&&e.metadata?.paths?t.push(...e.metadata.paths):"manage-files"===e.type&&e.metadata?.operations&&e.metadata.operations.forEach((e=>{e.createDirectory?.path&&t.push(e.createDirectory.path),e.moveFiles?.moves&&e.moveFiles.moves.forEach((e=>{e.destination&&t.push(e.destination)})),e.deleteFiles?.targets&&e.deleteFiles.targets.forEach((e=>{e.path&&t.push(e.path)}))})),[...new Set(t)]}function n(e){switch(e){case"write-file":return"\u{1f4dd} Write File"
|
|
4767
4730
|
case"replace-in-files":return"\u{1f504} Replace in Files"
|
|
@@ -4970,34 +4933,34 @@ return i(t,e),t})
|
|
|
4970
4933
|
Object.defineProperty(exports,"__esModule",{value:!0}),exports.handleFileHistory=async function(e,t,n,o,s){const i=o.child({tool:"file_history"}),a=s.startTimer("tool_execution_time"),m=Date.now()
|
|
4971
4934
|
try{let o
|
|
4972
4935
|
try{o=d.FileHistorySchema.parse(e)}catch(t){if(t instanceof u.ZodError){const r="Invalid arguments: "+t.errors.map((e=>e.message)).join(", ")
|
|
4973
|
-
return i.warn("Validation error",{error:r,args:e}),{content:[{type:"text",text:"\u274c "+r}],isError:!0}}throw t}const{path:a,limit:y,showDiff:w,showTraceability:b,branch:
|
|
4974
|
-
return
|
|
4936
|
+
return i.warn("Validation error",{error:r,args:e}),{content:[{type:"text",text:"\u274c "+r}],isError:!0}}throw t}const{path:a,limit:y,showDiff:w,showTraceability:b,branch:k,commit:I,since:v}=o
|
|
4937
|
+
return I?(i.info("Getting diff for specific commit",{filePath:a,commit:I}),await async function(e,t,r,n){const o=r.git,s=c.normalize(e).replace(/\\/g,"/")
|
|
4975
4938
|
if(n.info("Getting full diff for commit",{filePath:e,commit:t}),!o)return{content:[{type:"text",text:"\u274c Git not initialized"}],isError:!0}
|
|
4976
4939
|
try{const r=await o.log({from:t,to:t,file:s,maxCount:1})
|
|
4977
4940
|
if(!r.all||0===r.all.length)return{content:[{type:"text",text:`No commit found with hash ${t} for file ${e}`}]}
|
|
4978
4941
|
const n=r.all[0],i=await o.diff([t+"^",t,"--",s])
|
|
4979
4942
|
let a="# File History - Commit Diff\n\n"
|
|
4980
|
-
return a+=`**File:** ${e}\n`,a+=`**Commit:** ${t.substring(0,8)}\n`,a+=`**Author:** ${n.author_name}\n`,a+=`**Date:** ${n.date}\n`,a+=`**Message:** ${n.message}\n\n`,i&&i.trim()?a+=`## Full Diff\n\n\`\`\`diff\n${i}\n\`\`\`\n`:a+="*No diff available for this commit*\n",{content:[{type:"text",text:a}]}}catch(r){return n.error("Failed to get commit diff",{error:r,commit:t,filePath:e}),{content:[{type:"text",text:`\u274c Failed to get diff for commit ${t}: ${(0,p.getErrorMessage)(r)}`}],isError:!0}}}(a,
|
|
4943
|
+
return a+=`**File:** ${e}\n`,a+=`**Commit:** ${t.substring(0,8)}\n`,a+=`**Author:** ${n.author_name}\n`,a+=`**Date:** ${n.date}\n`,a+=`**Message:** ${n.message}\n\n`,i&&i.trim()?a+=`## Full Diff\n\n\`\`\`diff\n${i}\n\`\`\`\n`:a+="*No diff available for this commit*\n",{content:[{type:"text",text:a}]}}catch(r){return n.error("Failed to get commit diff",{error:r,commit:t,filePath:e}),{content:[{type:"text",text:`\u274c Failed to get diff for commit ${t}: ${(0,p.getErrorMessage)(r)}`}],isError:!0}}}(a,I,t,i)):(i.info("Getting file history with branch support",{filePath:a,limit:y,showDiff:w,showTraceability:b,branch:k}),await async function(e,t,n,o,s,i,a,c,d,u,p){try{const{normalizedPath:m,fullPath:y}=f.validateAndNormalizePath(e,a)
|
|
4981
4944
|
try{await l.access(y)}catch(e){throw Error("File not found: "+m)}const w=a.git
|
|
4982
4945
|
if(!w)throw Error("Git is not available in this context")
|
|
4983
4946
|
let b={branch:null,requestId:null,isMain:!0}
|
|
4984
|
-
if(a.getCurrentBranchContext)try{b=await a.getCurrentBranchContext(),d.info("Current branch context detected",{branch:b.branch,requestId:b.requestId,isMain:b.isMain})}catch(e){d.warn("Could not get current branch context",{error:e})}let
|
|
4985
|
-
if(s)
|
|
4947
|
+
if(a.getCurrentBranchContext)try{b=await a.getCurrentBranchContext(),d.info("Current branch context detected",{branch:b.branch,requestId:b.requestId,isMain:b.isMain})}catch(e){d.warn("Could not get current branch context",{error:e})}let k=[],I=""
|
|
4948
|
+
if(s)k=await r(w,m,t,n,o,s,i,c,d,u),I=`## File History: ${m} (Branch: ${s})\n\n`
|
|
4986
4949
|
else{if(b.isMain&&!o)return d.info("Showing request-level timeline on main branch"),{content:[{type:"text",text:await(0,g.getRequestTimelineForFile)(w,m,c,d,u)}]}
|
|
4987
4950
|
if(b.requestId)return d.info("Showing operation-level detail on request branch",{requestId:b.requestId}),{content:[{type:"text",text:await(0,g.getOperationDetailForFile)(m,b.requestId,c,d,u)}]}
|
|
4988
4951
|
{const e=await async function(e,t,n,o,s,i,a,c,l,d){const u=[],h=[]
|
|
4989
4952
|
if(!i.isMain&&i.branch){const g=await r(e,t,n,o,s,i.branch,a,c,l,d)
|
|
4990
4953
|
u.push(...g),g.length>0&&h.push(i.branch+" (current)")}const g=await r(e,t,n,o,s,"main",a,c,l,d),p=new Set(u.map((e=>e.hash))),f=g.filter((e=>!p.has(e.hash)))
|
|
4991
4954
|
return u.push(...f),g.length>0&&h.push("main"),u.sort(((e,t)=>new Date(t.date).getTime()-new Date(e.date).getTime())),{versions:u.slice(0,n),sources:h}}(w,m,t,n,o,b,i,c,d,u)
|
|
4992
|
-
|
|
4993
|
-
const v=
|
|
4994
|
-
v>t?
|
|
4995
|
-
try{
|
|
4996
|
-
for(let e=0;e<
|
|
4997
|
-
if(
|
|
4955
|
+
k=e.versions,I=`## File History: ${m} (Combined View)\n\n`,I+=`**Current Context:** ${b.isMain?"main":`${b.branch} (${b.requestId})`}\n`,I+=`**History Sources:** ${e.sources.join(", ")}\n\n`}}if(0===k.length)return I+="\u274c **No history found**\n\nThis file has no git history. It may be:\n- A new file that hasn't been committed\n- Located outside the git repository\n- The path may be incorrect\n- No history exists in the specified branch context",{content:[{type:"text",text:I}]}
|
|
4956
|
+
const v=k.length,C=Math.min(k.length,t)
|
|
4957
|
+
v>t?I+=`\u{1f4ca} **Summary:** ${v} versions found, showing ${C} most recent\n\n`:v>0&&(I+=`\u{1f4ca} **Summary:** ${v} version${v>1?"s":""} found\n\n`),I+=`**Total Versions:** ${k.length}\n`,I+="**Current File Size:** "
|
|
4958
|
+
try{I+=(await l.stat(y)).size+" bytes\n"}catch{I+="Unknown\n"}I+="\n"
|
|
4959
|
+
for(let e=0;e<k.length;e++){const t=k[e]
|
|
4960
|
+
if(I+=`### Version ${e+1} (${t.hash.substring(0,8)})\n`,t.branch&&(I+=`- **Branch:** ${t.branch}\n`),I+=`- **Author:** ${t.author}\n`,I+=`- **Date:** ${t.date}\n`,I+=`- **Message:** ${t.message}\n`,o&&t.traceability&&(I+=`\n${(0,h.formatTraceabilityInfo)(t.traceability)}\n`),n&&t.diff){const e=t.diff.split("\n")
|
|
4998
4961
|
let r=0,n=0
|
|
4999
4962
|
for(const t of e)t.startsWith("+")&&!t.startsWith("+++")&&r++,t.startsWith("-")&&!t.startsWith("---")&&n++
|
|
5000
|
-
|
|
4963
|
+
I+=`\n**Changes:**${r>0||n>0?` (Added ${r} lines, removed ${n} lines)`:""}\n\`\`\`diff\n${t.diff}\n\`\`\`\n`}I+="\n"}return I+="\u{1f4a1} **Tips:**\n",I+="- Use `file-recover` with a commit hash to restore the file to a previous version\n",I+='- Use `{"branch": "main"}` to see only main branch history\n',I+='- Use `{"branch": "req123456"}` to see only request branch history\n\n',d.info("Branch-aware file history retrieved successfully",{path:m,versions:k.length,targetBranch:s,currentBranch:b.branch,duration:Date.now()-p}),u.incrementCounter("file_history_total",1,{success:!0,type:"file",mode:s?"single-branch":"combined"}),{content:[{type:"text",text:I}]}}catch(e){throw e}}(a,y,w,b,k,v,t,n,i,s,m))}catch(e){const t=Date.now()-m
|
|
5001
4964
|
return i.error("File/Document history operation failed",{error:e instanceof Error?e.stack:e+"",duration:t}),a({tool:"file_history",success:!1}),s.incrementCounter("file_history_errors",1),{content:[{type:"text",text:"\u274c **History Operation Failed:** "+(0,p.getErrorMessage)(e)}],isError:!0}}}
|
|
5002
4965
|
const c=a(t(6928)),l=a(t(1943)),d=t(6183),u=t(1569),h=t(1181),g=t(2085),p=t(8824),f=a(t(5967)),m=a(t(7478)),{getCurrentBranch:y}=m},8850(e,exports,t){Object.defineProperty(exports,"__esModule",{value:!0}),exports.def=void 0
|
|
5003
4966
|
const r=t(6183),n=t(6891)
|
|
@@ -5133,7 +5096,14 @@ if(!o.ok)return void this.logger.debug("Polling response not ok",{status:o.statu
|
|
|
5133
5096
|
const i=await o.json()
|
|
5134
5097
|
if(this.logger.debug("Google OAuth polling response",{data:i}),i.success&&i.data&&i.data.authenticated&&i.data.token){this.logger.info("Google OAuth authentication completed")
|
|
5135
5098
|
const e=this.parseTokenResponse(i.data)
|
|
5136
|
-
e&&(this.pollingStatus=s.AUTHENTICATED,this.tokenResult=e,this.stopPolling(),r&&r(e))}else this.logger.debug("Not authenticated yet, continuing to poll",{hasSuccess:!!i.success,hasData:!!i.data,authenticated:i.data?.authenticated})}catch(e){this.logger.error("Error during Google OAuth polling",{error:(0,o.getErrorMessage)(e)}),this.pollingStatus=s.ERROR,this.pollingError=(0,o.getErrorMessage)(e),this.stopPolling(),i&&i(this.pollingError)}}),this.pollingIntervalMs),{authUrl:e,state:t}}}},
|
|
5099
|
+
e&&(this.pollingStatus=s.AUTHENTICATED,this.tokenResult=e,this.stopPolling(),r&&r(e))}else this.logger.debug("Not authenticated yet, continuing to poll",{hasSuccess:!!i.success,hasData:!!i.data,authenticated:i.data?.authenticated})}catch(e){this.logger.error("Error during Google OAuth polling",{error:(0,o.getErrorMessage)(e)}),this.pollingStatus=s.ERROR,this.pollingError=(0,o.getErrorMessage)(e),this.stopPolling(),i&&i(this.pollingError)}}),this.pollingIntervalMs),{authUrl:e,state:t}}}},9068(e,exports,t){function r(){const e=process.env.ALCHEMY_OPENCODE_DIR
|
|
5100
|
+
if(e)return e
|
|
5101
|
+
try{const e=Object(function(){var e=Error("Cannot find module 'alchemylab-opencode/package.json'")
|
|
5102
|
+
throw e.code="MODULE_NOT_FOUND",e}())
|
|
5103
|
+
return(0,o.dirname)(e)}catch{}}function n(e,t){return{command:"node",prependArgs:["--experimental-strip-types","--experimental-transform-types","--no-warnings","--import",(0,o.join)(e,"node-preload.mjs"),(0,o.join)(e,t)]}}Object.defineProperty(exports,"__esModule",{value:!0}),exports.resolveServeCommand=function(){const e=r()
|
|
5104
|
+
return e?n((0,o.join)(e,"packages","opencode","src"),"serve.ts"):{command:"opencode",prependArgs:["serve"]}},exports.resolveRunCommand=function(){const e=r()
|
|
5105
|
+
return e?n((0,o.join)(e,"packages","opencode","src"),"run.ts"):{command:"opencode",prependArgs:[]}}
|
|
5106
|
+
const o=t(6928)},9072(e,exports,t){async function r(e,t,r,n){try{const o=await(0,d.getServerUrl)(r,n)
|
|
5137
5107
|
if(!o)return n.warn("Could not get server URL for notification",{sessionId:e}),!1
|
|
5138
5108
|
let s,i
|
|
5139
5109
|
try{const t=`http://localhost:${g}/api/sessions/${encodeURIComponent(e)}/agent-type`,r=await fetch(t)
|
|
@@ -5142,27 +5112,23 @@ e.success&&e.agentType&&(s=e.agentType)}}catch(t){n.warn("Agent type lookup fail
|
|
|
5142
5112
|
if(e.ok){const t=await e.json()
|
|
5143
5113
|
if(t.data?.defaultModel){const[e,...r]=t.data.defaultModel.split("/")
|
|
5144
5114
|
i={providerID:e,modelID:r.join("/")}}}}catch{}const a=`${o.replace(/\/$/,"")}/session/${e}/prompt_async`,c=await fetch(a,{method:"POST",headers:{"Content-Type":"application/json"},body:JSON.stringify({parts:[{type:"text",text:"\x3c!-- inserted-prompt --\x3e"+t}],...s?{agent:s}:{},...i?{model:i}:{}})})
|
|
5145
|
-
return c.ok?(n.info("Notified session",{sessionId:e}),!0):(n.warn("Failed to notify session",{sessionId:e,status:c.status}),!1)}catch(t){return n.warn("Error notifying session",{sessionId:e,error:(0,l.getErrorMessage)(t)}),!1}}function n(e,t,r){return u.sessionIdentity.getParentSessionId(e,t,r)}
|
|
5146
|
-
if(
|
|
5147
|
-
|
|
5148
|
-
if(!s)throw new c.ValidationError("Could not determine OpenCode server URL")
|
|
5149
|
-
const i=await(0,d.getAndStoreSessionId)(s,t,r,n),a=i?.sessionId
|
|
5150
|
-
if(!a)throw new c.ValidationError("Could not discover current session ID. Make sure you are running within an OpenCode session.")
|
|
5151
|
-
return(0,h.logSessionIdentity)(""+r,"per-call-discovery",{sessionId:a}),a}function s(e){const t=[],r=e.content||{}
|
|
5115
|
+
return c.ok?(n.info("Notified session",{sessionId:e}),!0):(n.warn("Failed to notify session",{sessionId:e,status:c.status}),!1)}catch(t){return n.warn("Error notifying session",{sessionId:e,error:(0,l.getErrorMessage)(t)}),!1}}function n(e,t,r){return u.sessionIdentity.getParentSessionId(e,t,r)}function o(e,t,r){const n=u.sessionIdentity.getIdentity()
|
|
5116
|
+
if(!n?.sessionId)throw new c.ValidationError("No session identity available. Make sure you are running within an OpenCode session.")
|
|
5117
|
+
return(0,h.logSessionIdentity)(""+r,"identity",{sessionId:n.sessionId}),n.sessionId}function s(e){const t=[],r=e.content||{}
|
|
5152
5118
|
if(t.push("**Message Code:** "+e.messageCode),t.push(`**Type:** question (${r.questionType})`),t.push("**Status:** "+e.status),t.push("**Priority:** "+e.priority),t.push("**From:** "+e.fromSessionId),t.push(e.toSessionId?"**To:** "+e.toSessionId:"**To:** (broadcast)"),t.push("**Created:** "+e.createdAt),t.push("**Expires:** "+e.expiresAt),t.push(""),t.push("**Question:** "+r.question),r.context&&t.push("**Context:** "+r.context),"alternatives"===r.questionType&&r.options){t.push(""),t.push("**Options:**")
|
|
5153
5119
|
for(const e of r.options)t.push(` - [${e.id}] ${e.label}${e.description?" - "+e.description:""}`)}return"responded"===e.status&&e.response&&(t.push(""),t.push("---"),t.push("**Answered by:** "+e.respondedBySessionId),t.push("**Answered at:** "+e.respondedAt),e.response.text&&t.push("**Answer:** "+e.response.text),e.response.selectedOptions&&t.push("**Selected:** "+e.response.selectedOptions.join(", ")),e.response.notes&&t.push("**Notes:** "+e.response.notes)),t.join("\n")}function i(e){const t=[],r=e.content||{}
|
|
5154
|
-
return t.push("**Status:** "+(r.reportStatus||"unknown")),t.push("**Summary:** "+(r.summary||"")),r.details&&(t.push(""),t.push("**Details:**"),t.push(r.details)),t.join("\n")}function a(e){return"question"===e.messageType?s(e):i(e)}Object.defineProperty(exports,"__esModule",{value:!0}),exports.handleSessionMessageOperations=async function(e,t,p,f
|
|
5155
|
-
if(!
|
|
5156
|
-
const{operation:
|
|
5157
|
-
|
|
5158
|
-
try{switch(
|
|
5120
|
+
return t.push("**Status:** "+(r.reportStatus||"unknown")),t.push("**Summary:** "+(r.summary||"")),r.details&&(t.push(""),t.push("**Details:**"),t.push(r.details)),t.join("\n")}function a(e){return"question"===e.messageType?s(e):i(e)}Object.defineProperty(exports,"__esModule",{value:!0}),exports.handleSessionMessageOperations=async function(e,t,d,p,f){const m=d.child({component:"session_message_operations"})
|
|
5121
|
+
if(!f)throw new c.ValidationError("API client not available")
|
|
5122
|
+
const{operation:y}=e
|
|
5123
|
+
m.info("Session message operation",{operation:y}),p.incrementCounter("session_message_operations",1,{operation:y})
|
|
5124
|
+
try{switch(y){case"send":if(!e.type)throw new c.ValidationError('send operation requires type ("question" or "report")')
|
|
5159
5125
|
return await async function(e,t,a,l){const{type:d}=e
|
|
5160
5126
|
if(!d)throw new c.ValidationError('send operation requires type ("question" or "report")')
|
|
5161
5127
|
const u=l.getSessionMessageClient()
|
|
5162
5128
|
if(!u)throw new c.ValidationError("Session message client not available")
|
|
5163
5129
|
if("question"===d)return await async function(e,t,i,a,l){const{toSessionId:d,questionType:u,questionContent:h,priority:g,expiresInHours:p}=e
|
|
5164
5130
|
if(!u||!h?.question)throw new c.ValidationError("Question requires questionType and questionContent.question")
|
|
5165
|
-
const f=await o(
|
|
5131
|
+
const f=await o(0,0,"session_message_operations"),m=await async function(e,t,r,o){if("parent"===e){const e=await n(t,r,o)
|
|
5166
5132
|
if(!e)throw new c.ValidationError("Could not find parent session. Make sure this session was spawned as a subagent.")
|
|
5167
5133
|
return o.info('Resolved toSessionId "parent" to actual ID',{parentId:e}),e}return e}(d,f,a,i)
|
|
5168
5134
|
if(!("alternatives"!==u||h.options&&Array.isArray(h.options)))throw new c.ValidationError("Alternatives questions require options array")
|
|
@@ -5174,7 +5140,7 @@ if(t.context&&r.push("**Context:** "+t.context),"alternatives"===t.questionType&
|
|
|
5174
5140
|
for(const e of t.options)r.push(` - [${e.id}] ${e.label}${e.description?" - "+e.description:""}`)}return r.push(""),r.push(`Use \`session_message_operations\` with \`reply\` operation and message code \`${e.messageCode}\` to respond.`),r.join("\n")}(y),t,i)?"\n\n\u{1f4ec} The target session has been notified.":"\n\n\u26a0\ufe0f Could not notify the target session (may be offline)."),{content:[{type:"text",text:`\u2705 Question created!${w}\n\n**Message Code: ${y.messageCode}**\n\nUse this code to check for answers or share with other sessions.\n\n${s(y)}`}]}}(e,t,a,l,u)
|
|
5175
5141
|
if("report"===d)return await async function(e,t,s,a,l){const{status:d,summary:u,details:h,finish:p}=e
|
|
5176
5142
|
if(!d||!u)throw new c.ValidationError("Report requires status and summary")
|
|
5177
|
-
const f=await o(
|
|
5143
|
+
const f=await o(0,0,"session_message_operations"),m=await(async()=>{if(e.toSessionId&&"parent"!==e.toSessionId)return s.info("Using explicit toSessionId for report",{parentSessionId:e.toSessionId}),e.toSessionId
|
|
5178
5144
|
const t=await n(f,a,s)
|
|
5179
5145
|
if(!t)throw new c.ValidationError("Could not find parent session. This tool should only be used by subagent sessions.")
|
|
5180
5146
|
return s.info("Auto-resolved parent session",{parentSessionId:t}),t})()
|
|
@@ -5186,7 +5152,7 @@ if(e.ok){const t=await e.json()
|
|
|
5186
5152
|
t.success&&t.agentType&&(w=t.agentType)}}catch{}const b=await r(m,function(e,t="agent"){const r=e.content||{},n=[`${{success:"\u2705",partial:"\u26a0\ufe0f",failure:"\u274c",blocked:"\u{1f6ab}"}[r.reportStatus]||"\u{1f4cb}"} **Report \u2014 ${r.reportStatus}**`,`from: ${t} (${e.fromSessionId})`,"",r.summary]
|
|
5187
5153
|
return r.details&&(n.push(""),n.push(r.details)),n.join("\n")}(y,w),t,s)
|
|
5188
5154
|
return{content:[{type:"text",text:`\u2705 Report submitted.${b?"\n\n\u{1f4ec} The parent session has been notified.":"\n\n\u26a0\ufe0f Could not notify the parent session (may be offline)."}\n\n${i(y)}`}]}}(e,t,a,l,u)
|
|
5189
|
-
throw new c.ValidationError(`Unknown message type: ${d}. Use "question" or "report".`)}(e,t,
|
|
5155
|
+
throw new c.ValidationError(`Unknown message type: ${d}. Use "question" or "report".`)}(e,t,m,f)
|
|
5190
5156
|
case"reply":if(!e.messageCode)throw new c.ValidationError("reply operation requires messageCode")
|
|
5191
5157
|
return await async function(e,t,n,o){const{messageCode:a}=e
|
|
5192
5158
|
if(!a)throw new c.ValidationError("reply operation requires messageCode")
|
|
@@ -5197,26 +5163,24 @@ n.info("Answering question",{messageCode:a,respondedBySessionId:o})
|
|
|
5197
5163
|
const u=await l.answerQuestion(a,{respondedBySessionId:o,text:i,selectedOptions:c,notes:d})
|
|
5198
5164
|
return{content:[{type:"text",text:`\u2705 Question answered!${await r(u.fromSessionId,function(e){const t=e.content||{},r=e.response||{},n=["\u{1f4ec} **Your question has been answered!**","","**Question Code:** "+e.messageCode,"**Question:** "+t.question,"","---","**Answered by:** "+e.respondedBySessionId]
|
|
5199
5165
|
return r.text&&n.push("**Answer:** "+r.text),r.selectedOptions&&n.push("**Selected:** "+r.selectedOptions.join(", ")),r.notes&&n.push("**Notes:** "+r.notes),n.join("\n")}(u),t,n)?"\n\n\u{1f4ec} The asking session has been notified.":"\n\n\u26a0\ufe0f Could not notify the asking session (may be offline)."}\n\n${s(u)}`}]}}if(a.startsWith("R-"))return n.info("Acknowledging report",{messageCode:a}),{content:[{type:"text",text:"\u2705 Report acknowledged!\n\n"+i(await l.acknowledgeReport(a))}]}
|
|
5200
|
-
throw new c.ValidationError(`Cannot determine message type from code "${a}". Expected Q-xxx (question) or R-xxx (report).`)}(e,t,
|
|
5201
|
-
case"offer-handoff":{const
|
|
5202
|
-
let
|
|
5203
|
-
try{
|
|
5204
|
-
if(e
|
|
5205
|
-
|
|
5206
|
-
await e.createQuestion({fromSessionId:s,toSessionId:i||void 0,questionType:"alternatives",question:"Plan ready: "+(r.summary||"Plan complete"),options:[{id:"build",label:"Start Building",description:`Begin building ${t} request${1!==t?"s":""}`},{id:"plan",label:"Keep Planning",description:"Continue refining the plan"}],context:t>0?"Created requests: "+r.requestIds.join(", "):void 0,category:"action-required",priority:"high"}),y.info("offer-handoff: notification question created",{fromSessionId:s})}else y.warn("offer-handoff: skipping notification question",{hasClient:!!e,fromSessionId:s})}catch(e){y.warn("offer-handoff: failed to create notification question",{error:(0,l.getErrorMessage)(e)})}return{content:[{type:"text",text:'Handoff offered to user. STOP here and wait \u2014 the user will choose "Start Building" or "Keep Planning". You will receive their choice as a new message. Do NOT generate any further output until then.\nPLAN_HANDOFF_PENDING|'+JSON.stringify({summary:r.summary,requestIds:r.requestIds,parentSessionId:i})}],isError:!1}}case"list":return await async function(e,t,r,n){let{sessionId:o,messageType:s,direction:i,status:l,readStatus:u,reportStatus:g,limit:p,offset:f}=e
|
|
5166
|
+
throw new c.ValidationError(`Cannot determine message type from code "${a}". Expected Q-xxx (question) or R-xxx (report).`)}(e,t,m,f)
|
|
5167
|
+
case"offer-handoff":{const t=e.offerHandoff||{summary:e.summary||"",requestIds:e.requestIds||[]}
|
|
5168
|
+
let r=null,s=null
|
|
5169
|
+
try{r=o(0,0,"session_message_operations"),s=await n(r,f,m)}catch(e){m.warn("offer-handoff: could not resolve session/parent",{error:(0,l.getErrorMessage)(e)})}try{const e=f.getSessionMessageClient()
|
|
5170
|
+
if(e&&r){const n=t.requestIds?.length||0
|
|
5171
|
+
await e.createQuestion({fromSessionId:r,toSessionId:s||void 0,questionType:"alternatives",question:"Plan ready: "+(t.summary||"Plan complete"),options:[{id:"build",label:"Start Building",description:`Begin building ${n} request${1!==n?"s":""}`},{id:"plan",label:"Keep Planning",description:"Continue refining the plan"}],context:n>0?"Created requests: "+t.requestIds.join(", "):void 0,category:"action-required",priority:"high"}),m.info("offer-handoff: notification question created",{fromSessionId:r})}else m.warn("offer-handoff: skipping notification question",{hasClient:!!e,fromSessionId:r})}catch(e){m.warn("offer-handoff: failed to create notification question",{error:(0,l.getErrorMessage)(e)})}return{content:[{type:"text",text:'Handoff offered to user. STOP here and wait \u2014 the user will choose "Start Building" or "Keep Planning". You will receive their choice as a new message. Do NOT generate any further output until then.\nPLAN_HANDOFF_PENDING|'+JSON.stringify({summary:t.summary,requestIds:t.requestIds,parentSessionId:s})}],isError:!1}}case"list":return await async function(e,t,r,n){let{sessionId:o,messageType:s,direction:i,status:l,readStatus:d,reportStatus:g,limit:p,offset:f}=e
|
|
5207
5172
|
const m=n.getSessionMessageClient()
|
|
5208
5173
|
if(!m)throw new c.ValidationError("Session message client not available")
|
|
5209
|
-
if(!o){const e=
|
|
5210
|
-
if(!e)return{content:[{type:"text",text:"\u26a0\ufe0f Could not
|
|
5211
|
-
|
|
5212
|
-
if(o=n?.sessionId,(0,h.logSessionIdentity)("session_message_operations.list",o?"per-call-discovery":"discovery-failed",{sessionId:o}),!o)return r.warn("Session discovery FAILED for list - returning empty to prevent data leak"),{content:[{type:"text",text:"\u26a0\ufe0f Could not determine current session ID. Unable to list messages without a session context."}]}}}r.debug("Listing messages",{sessionId:o,messageType:s,direction:i,status:l,readStatus:u})
|
|
5174
|
+
if(!o){const e=u.sessionIdentity.getIdentity()
|
|
5175
|
+
if(!e?.sessionId)return r.warn("No session identity for list operation"),{content:[{type:"text",text:"\u26a0\ufe0f Could not determine current session ID. Unable to list messages without a session context."}]}
|
|
5176
|
+
o=e.sessionId,(0,h.logSessionIdentity)("session_message_operations.list","identity",{sessionId:o})}r.debug("Listing messages",{sessionId:o,messageType:s,direction:i,status:l,readStatus:d})
|
|
5213
5177
|
const y={sessionId:o,direction:i,limit:p,offset:f}
|
|
5214
|
-
s&&"all"!==s&&(y.messageType=s),l&&"all"!==l&&("report"===s?y.reportStatus=l:y.status=l),
|
|
5178
|
+
s&&"all"!==s&&(y.messageType=s),l&&"all"!==l&&("report"===s?y.reportStatus=l:y.status=l),d&&"all"!==d&&(y.readStatus=d),g&&"all"!==g&&(y.reportStatus=g)
|
|
5215
5179
|
const w=await m.listMessages(y)
|
|
5216
5180
|
if(0===w.length)return{content:[{type:"text",text:"No messages found matching the criteria."}]}
|
|
5217
5181
|
const b=[`Found ${w.length} message(s):\n`]
|
|
5218
5182
|
for(const e of w)b.push("---\n"),b.push(a(e)),b.push("")
|
|
5219
|
-
return{content:[{type:"text",text:b.join("\n")}]}}(e.list||{},
|
|
5183
|
+
return{content:[{type:"text",text:b.join("\n")}]}}(e.list||{},0,m,f)
|
|
5220
5184
|
case"get":if(!e.messageCode)throw new c.ValidationError("get operation requires messageCode")
|
|
5221
5185
|
return await async function(e,t,r){const{messageCode:n}=e
|
|
5222
5186
|
if(!n)throw new c.ValidationError("get operation requires messageCode")
|
|
@@ -5224,8 +5188,8 @@ const o=r.getSessionMessageClient()
|
|
|
5224
5188
|
if(!o)throw new c.ValidationError("Session message client not available")
|
|
5225
5189
|
t.debug("Getting message",{messageCode:n})
|
|
5226
5190
|
const s=await o.getMessage(n)
|
|
5227
|
-
return s?{content:[{type:"text",text:a(s)}]}:{content:[{type:"text",text:`\u274c Message with code ${n} not found.`}],isError:!0}}(e,
|
|
5228
|
-
default:throw new c.ValidationError(`Unknown operation: ${
|
|
5191
|
+
return s?{content:[{type:"text",text:a(s)}]}:{content:[{type:"text",text:`\u274c Message with code ${n} not found.`}],isError:!0}}(e,m,f)
|
|
5192
|
+
default:throw new c.ValidationError(`Unknown operation: ${y}. Valid operations: send, reply, list, get`)}}catch(e){return m.error("Session message operation failed",{operation:y,error:(0,l.getErrorMessage)(e)}),{content:[{type:"text",text:"\u274c Error: "+(0,l.getErrorMessage)(e)}],isError:!0}}}
|
|
5229
5193
|
const c=t(9860),l=t(8824),d=t(7617),u=t(6688),h=t(7280),g=3456},9080(e,exports,t){Object.defineProperty(exports,"__esModule",{value:!0}),exports.def=void 0
|
|
5230
5194
|
const r=t(6183),n=t(1281)
|
|
5231
5195
|
exports.def={name:"search",description:"Search for text patterns in files on the currently active branch. Supports regex patterns and sorts results by file modification time (newest first).\n\nFile extensions: 'ts', '.ts', '*.ts' (all valid). Use '*' for any file type.\n\nCONTEXT LINES: Use contextLines option (0-10) to show surrounding lines before and after matches, reducing need for follow-up reads.\n\nLIST-ALL MODE: Omit 'needle' to list all files in a directory with tree structure (like ls/tree). Options: levels (1-4 depth), sortBy (name/modified/size/type).",schema:r.SearchSchema,annotations:{title:"Search Files",readOnlyHint:!0},readOnly:!0,handler(e,t){return(0,n.handleSearch)(e,t.context,t.apiClient,t.logger,t.metrics)}}},9089(e,exports){function t(e){if(e.toLowerCase().startsWith("specialist:")){const t=e.slice(11).trim()
|
|
@@ -5329,10 +5293,10 @@ continue}const t=(0,h.findMatches)(s,n,m,100,e.path)
|
|
|
5329
5293
|
if(a.matchesFound=t.length,0===t.length){a.error="No matches found"+(m?" (tried fuzzy matching)":""),a.success=!1
|
|
5330
5294
|
const e=(0,h.findSimilarMatches)(s,n,5,.3)
|
|
5331
5295
|
e.length>0&&(a.similarMatches=e),y.failedReplacements++}else"unique"===i&&t.length>1?(a.error=`Multiple matches found (${t.length}) - expected unique match`,a.success=!1,a.details=t.map(r),y.failedReplacements++):p.push({matches:t,newText:o,matchMode:i,repResult:a})}catch(e){a.error=(0,b.getErrorMessage)(e),a.success=!1,y.failedReplacements++}y.replacements.push(a)}let w=s
|
|
5332
|
-
const
|
|
5333
|
-
for(const e of p)for(const t of e.matches)
|
|
5334
|
-
|
|
5335
|
-
for(const{match:e,newText:t,repResult:n}of
|
|
5296
|
+
const k=[]
|
|
5297
|
+
for(const e of p)for(const t of e.matches)k.push({match:t,newText:e.newText,repResult:e.repResult})
|
|
5298
|
+
k.sort(((e,t)=>t.match.startPos-e.match.startPos))
|
|
5299
|
+
for(const{match:e,newText:t,repResult:n}of k)w=(0,h.replaceMatch)(w,e,t),n.success?(n.lines.push(e.line),n.details.push(r(e))):(n.success=!0,n.matchType=e.matchType,n.lines=[e.line],n.details=[r(e)],y.successfulReplacements++)
|
|
5336
5300
|
y.successfulReplacements>0&&(await l.default.writeFile(t,w,"utf8"),f&&(n.documentFileManager.markForSync(d),await n.documentFileManager.syncDocument(d))),i&&(y.externalEditWarning=i),a&&(y.externalEditDebugInfo={detectionRan:!0,...a}),y.success=0===y.failedReplacements}catch(e){y.error=(0,b.getErrorMessage)(e),y.success=!1,y.failedReplacements=g.length,y.replacements=g.map((e=>({old:e.old,new:e.new,success:!1,error:y.error})))}return y}var o,s=this&&this.__createBinding||(Object.create?function(e,t,r,n){void 0===n&&(n=r)
|
|
5337
5301
|
var o=Object.getOwnPropertyDescriptor(t,r)
|
|
5338
5302
|
o&&!("get"in o?!t.__esModule:o.writable||o.configurable)||(o={enumerable:!0,get(){return t[r]}}),Object.defineProperty(e,n,o)}:function(e,t,r,n){void 0===n&&(n=r),e[n]=t[r]}),i=this&&this.__setModuleDefault||(Object.create?function(e,t){Object.defineProperty(e,"default",{enumerable:!0,value:t})}:function(e,t){e.default=t}),a=this&&this.__importStar||(o=function(e){return o=Object.getOwnPropertyNames||function(e){var t=[]
|
|
@@ -5341,47 +5305,47 @@ return t},o(e)},function(e){if(e&&e.__esModule)return e
|
|
|
5341
5305
|
var t={}
|
|
5342
5306
|
if(null!=e)for(var r=o(e),n=0;n<r.length;n++)"default"!==r[n]&&s(t,e,r[n])
|
|
5343
5307
|
return i(t,e),t}),c=this&&this.__importDefault||function(e){return e&&e.__esModule?e:{default:e}}
|
|
5344
|
-
Object.defineProperty(exports,"__esModule",{value:!0}),exports.handleReplaceInFiles=async function(e,t,r,o,s,i,a,c){const
|
|
5308
|
+
Object.defineProperty(exports,"__esModule",{value:!0}),exports.handleReplaceInFiles=async function(e,t,r,o,s,i,a,c){const k=i.child({tool:"replace_in_files"}),I=Date.now()
|
|
5345
5309
|
let v,C=u.FileOperationPhase.VALIDATION
|
|
5346
5310
|
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)
|
|
5347
5311
|
const i=u.validateArgs(e,d.ReplaceInFilesSchema),{taskId:_,operations:E,fuzzy_match:q=!0,comment:S}=i
|
|
5348
|
-
|
|
5312
|
+
k.info("Replace in files batch operation",{taskId:_,operationCount:E.length,totalReplacements:E.reduce(((e,t)=>e+t.replacements.length),0),globalFuzzyMatch:q,comment:S})
|
|
5349
5313
|
const T=E.filter((e=>e.documentId)).map((e=>e.documentId))
|
|
5350
|
-
if(T.length>0&&t.apiClient)try{await(0,m.ensureDocumentsNotLocked)(T,t.apiClient,
|
|
5314
|
+
if(T.length>0&&t.apiClient)try{await(0,m.ensureDocumentsNotLocked)(T,t.apiClient,k,a,"replace_in_files-documents")}catch(e){if(e instanceof g.ValidationError)return{content:[{type:"text",text:e.message}],isError:!0}
|
|
5351
5315
|
throw e}C=u.FileOperationPhase.TASK_VALIDATION,a.incrementCounter("replace_in_files_phase",1,{phase:C})
|
|
5352
5316
|
const P=E[0],R=P.documentId?"document:"+P.documentId:P.path
|
|
5353
5317
|
let M=Date.now()
|
|
5354
|
-
const j=await u.validateTaskId(_,R,r,
|
|
5318
|
+
const j=await u.validateTaskId(_,R,r,k,a,"replace_in_files")
|
|
5355
5319
|
Date.now()
|
|
5356
5320
|
const x=j?.requestId,O=E.some((e=>e.path))
|
|
5357
5321
|
let D=!1
|
|
5358
5322
|
if(O&&x){M=Date.now()
|
|
5359
|
-
const e=await u.validateWorkItemStates(_,R,r,s,t,
|
|
5323
|
+
const e=await u.validateWorkItemStates(_,R,r,s,t,k,a,"replace_in_files")
|
|
5360
5324
|
Date.now(),M=Date.now()
|
|
5361
|
-
const n=await u.autoPromoteTaskStatus(_,j.status,x,e.request?.status,R,r,s,
|
|
5362
|
-
n.taskPromoted&&
|
|
5363
|
-
const o=await u.ensureCorrectWorkspaceContext({taskPromoted:n.taskPromoted,requestId:x,context:t,operation:"replace_in_files",logger:
|
|
5325
|
+
const n=await u.autoPromoteTaskStatus(_,j.status,x,e.request?.status,R,r,s,k,a,"replace_in_files")
|
|
5326
|
+
n.taskPromoted&&k.info("Auto-promoted task to in_progress",{taskId:_,requestId:x,previousStatus:j.status,newStatus:n.newTaskStatus}),Date.now(),M=Date.now()
|
|
5327
|
+
const o=await u.ensureCorrectWorkspaceContext({taskPromoted:n.taskPromoted,requestId:x,context:t,operation:"replace_in_files",logger:k,metrics:a,metricsPrefix:"replace_in_files"})
|
|
5364
5328
|
if(!o.success){if(o.isLockConflict)return{content:[{type:"text",text:"\u274c "+o.error}],isError:!0}
|
|
5365
|
-
throw Error(o.error)}Date.now(),D=!0}if(T.length>0&&x)try{await(0,p.validateRequestStatusForDocumentOperation)(x,s,
|
|
5329
|
+
throw Error(o.error)}Date.now(),D=!0}if(T.length>0&&x)try{await(0,p.validateRequestStatusForDocumentOperation)(x,s,k,a,"replace_in_files-documents")}catch(e){if(e instanceof g.ValidationError)return{content:[{type:"text",text:e.message}],isError:!0}
|
|
5366
5330
|
throw e}M=Date.now()
|
|
5367
5331
|
const A=new Map
|
|
5368
|
-
if(
|
|
5332
|
+
if(k.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=[]
|
|
5369
5333
|
for(const t of e.replacements){const r=(0,h.findMatches)(n,t.old,o,100,e.path)
|
|
5370
5334
|
s.push(...r)}if(s.length>0){const o=(0,y.calculateReplacementRegion)(n,s,r.fullPath)
|
|
5371
|
-
|
|
5372
|
-
const i=await(0,w.detectExternalEdits)(t.git,o,
|
|
5373
|
-
|
|
5374
|
-
const e=await(0,f.commitUserChangesBeforeToolOperation)(t.git,"replace_in_files",{requestId:x,taskId:_,workspaceManager:t.workspaceManager},
|
|
5375
|
-
e.userChangesCommitted&&(
|
|
5376
|
-
const{toolRecordId:$}=await u.createFileOperationRecords(_,x,t.projectId,"replace-in-files",R,{operationCount:E.length,totalReplacements:E.reduce(((e,t)=>e+t.replacements.length),0),globalFuzzyMatch:q,userComment:S},r,o,
|
|
5335
|
+
k.info("\u{1f50d} Checking for external edits",{path:r.normalizedPath,affectedLines:o.lineRanges.map((e=>`${e.start}-${e.end}`)).join(", "),matchCount:s.length})
|
|
5336
|
+
const i=await(0,w.detectExternalEdits)(t.git,o,k)
|
|
5337
|
+
k.info("\u{1f50d} External edit detection result",{path:r.normalizedPath,hasExternalEdits:i.hasExternalEdits,conflictingLines:i.conflictingLines,hasMessage:!!i.message}),i.hasExternalEdits&&i.message?(A.set(e.path,{message:i.message,debugInfo:i.debugInfo}),k.warn("\u26a0\ufe0f External edits detected before auto-commit",{path:r.normalizedPath,conflictingLines:i.conflictingLines})):(i.debugInfo&&A.set(e.path,{message:"",debugInfo:i.debugInfo}),k.info("\u2705 No external edit conflicts detected",{path:r.normalizedPath}))}else k.info("\u2139\ufe0f No matches found for external edit detection",{path:r.normalizedPath}),A.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){k.warn("Failed to check for external edits before auto-commit",{path:e.path,error:(0,b.getErrorMessage)(t)})}if(Date.now(),M=Date.now(),O&&t.git)try{k.debug("[REPLACE-IN-FILES] Checking for user changes before batch operation")
|
|
5338
|
+
const e=await(0,f.commitUserChangesBeforeToolOperation)(t.git,"replace_in_files",{requestId:x,taskId:_,workspaceManager:t.workspaceManager},k,a)
|
|
5339
|
+
e.userChangesCommitted&&(k.debug("[REPLACE-IN-FILES] User changes committed",{commitHash:e.commitHash?.substring(0,8),filesCommitted:e.filesCommitted}),k.info("User changes committed before batch operation",{taskId:_,userCommitHash:e.commitHash?.substring(0,8),userFilesCommitted:e.filesCommitted}))}catch(e){k.warn("Pre-tool user changes commit failed",{taskId:_,error:e instanceof Error?e.message:e+""})}Date.now(),M=Date.now(),C=u.FileOperationPhase.RECORD_CREATION,a.incrementCounter("replace_in_files_phase",1,{phase:C})
|
|
5340
|
+
const{toolRecordId:$}=await u.createFileOperationRecords(_,x,t.projectId,"replace-in-files",R,{operationCount:E.length,totalReplacements:E.reduce(((e,t)=>e+t.replacements.length),0),globalFuzzyMatch:q,userComment:S},r,o,k,a,"replace_in_files",c)
|
|
5377
5341
|
v=$,Date.now(),M=Date.now(),C=u.FileOperationPhase.STRING_REPLACEMENT,a.incrementCounter("replace_in_files_phase",1,{phase:C})
|
|
5378
5342
|
const F=[],N=[]
|
|
5379
5343
|
for(const e of E){const r=e.path?A.get(e.path):void 0,o=await n(e,q,t,0,0,r?.message,r?.debugInfo)
|
|
5380
5344
|
F.push(o),o.successfulReplacements>0&&"file"===o.type&&o.path&&N.push(o.path)}Date.now(),M=Date.now()
|
|
5381
|
-
const L=E.filter((e=>e.path&&!e.documentId)).map((e=>({path:e.path}))),z=await u.handleMultiFileGitCommit(_,L,F,N.length,{operationType:"Replace in files",toolRecordId:$||v||"unknown",successField:"successfulReplacements",logger:
|
|
5345
|
+
const L=E.filter((e=>e.path&&!e.documentId)).map((e=>({path:e.path}))),z=await u.handleMultiFileGitCommit(_,L,F,N.length,{operationType:"Replace in files",toolRecordId:$||v||"unknown",successField:"successfulReplacements",logger:k,metrics:a,metricsPrefix:"replace_in_files"},t),B=z.commitHash
|
|
5382
5346
|
Date.now(),Date.now()
|
|
5383
5347
|
const H=F.filter((e=>e.success)).length,U=F.length-H,W=F.reduce(((e,t)=>e+t.successfulReplacements),0),G=F.reduce(((e,t)=>e+t.failedReplacements),0),V=F.map((e=>({type:e.type,path:e.path,documentId:e.documentId,filename:e.filename,replacements:e.replacements.map((e=>({old_str:e.old,new_str:e.new,success:e.success,error:e.error,matchesFound:e.matchesFound,matchType:e.matchType,lines:e.lines})))}))),J=F.filter((e=>e.success)).map((e=>({path:e.path,documentId:e.documentId,filename:e.filename,successfulReplacements:e.successfulReplacements,failedReplacements:e.failedReplacements}))),K=F.filter((e=>!e.success)).map((e=>({path:e.path,documentId:e.documentId,filename:e.filename,error:e.error,successfulReplacements:e.successfulReplacements,failedReplacements:e.failedReplacements})))
|
|
5384
|
-
await o.updateToolRecord(v,{metadata:{path:R,status:0===U?"completed":"partial",operationCount:E.length,operations:V,successfulFiles:J,failedFiles:K,successfulReplacements:W,failedReplacements:G,processingTime:Date.now()-
|
|
5348
|
+
await o.updateToolRecord(v,{metadata:{path:R,status:0===U?"completed":"partial",operationCount:E.length,operations:V,successfulFiles:J,failedFiles:K,successfulReplacements:W,failedReplacements:G,processingTime:Date.now()-I,userComment:S,...z.success&&z.commitHash&&{commitHash:z.commitHash,previousCommitHash:z.previousCommitHash||void 0}}})
|
|
5385
5349
|
const Y=await async function(e,t,r,n,o,s){const i=e.filter((e=>e.success)).length,a=e.length-i,c=e.filter((e=>!e.success&&!e.error&&e.successfulReplacements>0)).length
|
|
5386
5350
|
let l="## Replace In Files - Batch Results\n\n"
|
|
5387
5351
|
if(o.getCurrentBranchContext)try{const e=await o.getCurrentBranchContext()
|
|
@@ -5394,8 +5358,8 @@ for(const e of o)l+=`- \u2705 \`${e.old.substring(0,40)}${e.old.length>40?"...":
|
|
|
5394
5358
|
if(s.length>0){l+="\n**Failed Replacement Details:**\n"
|
|
5395
5359
|
for(const e of s)l+=`- \u274c \`${e.old.substring(0,40)}${e.old.length>40?"...":""}\` \u2192 \`${e.new.substring(0,40)}${e.new.length>40?"...":""}\`: ${e.error}\n`,e.details&&e.details.length>0&&(l+=" **Candidates found:**\n",l+=e.details.slice(0,5).map((e=>` - Line ${e.line}: \`${e.actually_matched.substring(0,40)}${e.actually_matched.length>40?"...":""}\` (${e.match_type})`)).join("\n")+"\n",e.details.length>5&&(l+=` ... and ${e.details.length-5} more matches\n`)),e.similarMatches&&e.similarMatches.length>0&&(l+=" **Did you mean? (Similar matches found):**\n",l+=e.similarMatches.map((e=>` - Line ${e.line}: \`${e.text.substring(0,60)}${e.text.length>60?"...":""}\` (${e.reason}, similarity: ${(100*e.similarity).toFixed(0)}%)`)).join("\n")+"\n")}l+="\n"}const d=e.filter((e=>"document"===e.type&&(e.success||e.successfulReplacements>0)))
|
|
5396
5360
|
return d.length>0&&(l+=`\n**Document Changes:** ${d.length} modified document(s) synced back to tracking system.\n`),o.workspaceManager?.largeFileWarning&&(l+=o.workspaceManager.largeFileWarning,o.workspaceManager.largeFileWarning=""),l}(F,B,W,G,t,v)
|
|
5397
|
-
return{content:[{type:"text",text:Y}],isError:0===W}}catch(e){const t=Date.now()-
|
|
5398
|
-
if(
|
|
5361
|
+
return{content:[{type:"text",text:Y}],isError:0===W}}catch(e){const t=Date.now()-I
|
|
5362
|
+
if(k.error("Replace in files batch operation failed",{error:e instanceof Error?e.stack:e+"",duration:t,phase:C}),v)try{await o.updateToolRecord(v,{metadata:{status:"failed",error:(0,b.getErrorMessage)(e),phase:C,duration:t}})}catch(e){}return a.incrementCounter("replace_in_files_errors",1,{phase:C}),{content:[{type:"text",text:"\u274c **Replace In Files Failed:** "+(0,b.getErrorMessage)(e)}],isError:!0}}}
|
|
5399
5363
|
const l=c(t(1943)),d=(a(t(9896)),a(t(6928)),c(t(6982)),t(6183)),u=a(t(5967)),h=t(3626),g=t(9860),p=t(5003),f=t(7478),m=t(9949),y=t(9947),w=t(1318),b=t(8824)},9470(e,exports){Object.defineProperty(exports,"__esModule",{value:!0}),exports.parseLineSpec=function(e){if(!e||""===e.trim())throw Error("Line specification cannot be empty")
|
|
5400
5364
|
const t=e.trim()
|
|
5401
5365
|
if(t.includes("-")){const r=t.split("-").map((e=>e.trim()))
|
|
@@ -5451,14 +5415,14 @@ if(n)s.WorkspaceLogging.logOperation(this.logger,"info","Branch already exists,
|
|
|
5451
5415
|
else{const t=await this.git.revparse(["--abbrev-ref","HEAD"]),r=await this.gitAdapter.branchManager.getBaseBranch()
|
|
5452
5416
|
await this.git.checkout(["-b",i,r]),await this.git.checkout(t),s.WorkspaceLogging.logOperation(this.logger,"info","Created branch and returned to original",e,"single-agent","initializeRequest",{branchName:i,baseBranch:r,returnedTo:t})}const o=Date.now()-r
|
|
5453
5417
|
this.metrics.recordValue("workspace.initialize",o),s.WorkspaceLogging.logOperation(this.logger,"info","Successfully initialized request with branch",e,"single-agent","initializeRequest",{branchName:i,existed:n,duration:o,architecture:"hybrid-creation"})}catch(t){const n=Date.now()-r
|
|
5454
|
-
throw this.metrics.recordValue("workspace.initialize",n),s.WorkspaceLogging.logOperation(this.logger,"error","Failed to initialize request",e,"single-agent","initializeRequest",{error:(0,o.getErrorMessage)(t),duration:n}),t}}async ensureWorkspaceReady(e){const
|
|
5455
|
-
if(!
|
|
5456
|
-
const n
|
|
5457
|
-
if(a
|
|
5458
|
-
try{if(s.WorkspaceLogging.logOperation(this.logger,"info","Ensuring workspace ready by switching to branch",e,"single-agent","ensureWorkspaceReady",{currentBranch:
|
|
5459
|
-
try{await this.switchToRequest(
|
|
5460
|
-
this.metrics.recordValue("workspace.ensure_ready",
|
|
5461
|
-
throw this.metrics.recordValue("workspace.ensure_ready",n),s.WorkspaceLogging.logOperation(this.logger,"error","Failed to ensure workspace ready",e,"single-agent","ensureWorkspaceReady",{error:(0,o.getErrorMessage)(
|
|
5418
|
+
throw this.metrics.recordValue("workspace.initialize",n),s.WorkspaceLogging.logOperation(this.logger,"error","Failed to initialize request",e,"single-agent","initializeRequest",{error:(0,o.getErrorMessage)(t),duration:n}),t}}async ensureWorkspaceReady(e,t){const r=Date.now(),n=s.WorkspaceValidation.validateRequestId(e)
|
|
5419
|
+
if(!n.isValid)throw Error("Invalid request ID: "+n.errors.join(", "))
|
|
5420
|
+
const i=n.sanitized,a="requests/"+i,c=await this.git.revparse(["--abbrev-ref","HEAD"])
|
|
5421
|
+
if(c===a)return this.currentRequestId=i,this.currentBranch=a,void this.logger.debug("Workspace already ready",{requestId:i,currentBranch:this.currentBranch})
|
|
5422
|
+
try{if(s.WorkspaceLogging.logOperation(this.logger,"info","Ensuring workspace ready by switching to branch",e,"single-agent","ensureWorkspaceReady",{currentBranch:c,targetBranch:a,architecture:"hybrid-creation"}),!(await this.git.branch()).all.includes(a))throw Error(`Branch ${a} does not exist. Was initializeRequest() called?`)
|
|
5423
|
+
try{await this.switchToRequest(i)}catch(t){s.WorkspaceLogging.logOperation(this.logger,"warn","switchToRequest failed, trying direct checkout",e,"single-agent","ensureWorkspaceReady",{error:t instanceof Error?t.message:t+"",attempting:"direct-checkout",branchName:a}),await this.git.checkout(a),this.currentRequestId=i,this.currentBranch=a,s.WorkspaceLogging.logOperation(this.logger,"info","Direct checkout succeeded",e,"single-agent","ensureWorkspaceReady",{branchName:a})}const t=Date.now()-r
|
|
5424
|
+
this.metrics.recordValue("workspace.ensure_ready",t),s.WorkspaceLogging.logOperation(this.logger,"info","Workspace is ready",e,"single-agent","ensureWorkspaceReady",{branchName:this.currentBranch,duration:t,architecture:"hybrid-creation"})}catch(t){const n=Date.now()-r
|
|
5425
|
+
throw this.metrics.recordValue("workspace.ensure_ready",n),s.WorkspaceLogging.logOperation(this.logger,"error","Failed to ensure workspace ready",e,"single-agent","ensureWorkspaceReady",{error:(0,o.getErrorMessage)(t),duration:n}),t}}async switchToRequest(e,t){const r=Date.now(),n=this.getCurrentContext(),i=s.WorkspaceValidation.validateRequestId(e)
|
|
5462
5426
|
if(!i.isValid){const t="Invalid request ID: "+i.errors.join(", ")
|
|
5463
5427
|
throw s.WorkspaceLogging.logOperation(this.logger,"error",t,e,"single-agent","switchToRequest"),Error(t)}const a=i.sanitized
|
|
5464
5428
|
try{s.WorkspaceLogging.logOperation(this.logger,"info","Switching to request (assuming branch exists)",e,"single-agent","switchToRequest",{previousBranch:n.branchName,architecture:"aligned-with-multi-agent"})
|
|
@@ -5468,13 +5432,13 @@ const o=Date.now()-r
|
|
|
5468
5432
|
return this.metrics.recordValue("workspace.switch",o),s.WorkspaceLogging.logOperation(this.logger,"info","Successfully switched to request",e,"single-agent","switchToRequest",{branchName:t.branchName,previousBranch:n.branchName,duration:o,architecture:"aligned-with-multi-agent"}),{success:!0,message:"Switched to request "+a,previousContext:n,newContext:this.getCurrentContext()}}catch(t){const n=Date.now()-r
|
|
5469
5433
|
this.metrics.recordValue("workspace.switch",n)
|
|
5470
5434
|
const i=(0,o.getErrorMessage)(t),a=i.includes("does not exist"),c=a?`Branch for request ${e} does not exist. Use initializeRequest() first to create the branch.`:`Failed to switch to request ${e}: ${i}`
|
|
5471
|
-
throw s.WorkspaceLogging.logOperation(this.logger,"error","Failed to switch to request",e,"single-agent","switchToRequest",{error:i,isMissingBranch:a,duration:n,suggestion:a?"Call initializeRequest() first":"Check branch status"}),new s.ConflictDetectionError(c,"single-agent-switch-"+e,[])}}async switchToMain(){const
|
|
5472
|
-
try{const
|
|
5435
|
+
throw s.WorkspaceLogging.logOperation(this.logger,"error","Failed to switch to request",e,"single-agent","switchToRequest",{error:i,isMissingBranch:a,duration:n,suggestion:a?"Call initializeRequest() first":"Check branch status"}),new s.ConflictDetectionError(c,"single-agent-switch-"+e,[])}}async switchToMain(e){const t=Date.now(),r=this.getCurrentContext()
|
|
5436
|
+
try{const e=await this.gitAdapter.branchManager.getBaseBranch(),n=await this.gitAdapter.branchManager.switchToBranch(e)
|
|
5473
5437
|
if(!n.success)throw Error("Failed to switch to main branch: "+n.error)
|
|
5474
|
-
this.currentBranch=
|
|
5475
|
-
const o=Date.now()-
|
|
5476
|
-
return this.metrics.recordValue("workspace.switch_main",o),s.WorkspaceLogging.logOperation(this.logger,"info","Successfully switched to main branch",null,"single-agent","switchToMain",{mainBranch:
|
|
5477
|
-
throw this.metrics.recordValue("workspace.switch_main",r),s.WorkspaceLogging.logOperation(this.logger,"error","Failed to switch to main branch",null,"single-agent","switchToMain",{error:(0,o.getErrorMessage)(
|
|
5438
|
+
this.currentBranch=e,this.currentRequestId=null
|
|
5439
|
+
const o=Date.now()-t
|
|
5440
|
+
return this.metrics.recordValue("workspace.switch_main",o),s.WorkspaceLogging.logOperation(this.logger,"info","Successfully switched to main branch",null,"single-agent","switchToMain",{mainBranch:e,previousBranch:r.branchName,duration:o,architecture:"aligned-with-multi-agent"}),{success:!0,message:"Switched to "+e,previousContext:r,newContext:this.getCurrentContext()}}catch(e){const r=Date.now()-t
|
|
5441
|
+
throw this.metrics.recordValue("workspace.switch_main",r),s.WorkspaceLogging.logOperation(this.logger,"error","Failed to switch to main branch",null,"single-agent","switchToMain",{error:(0,o.getErrorMessage)(e),duration:r}),new s.ConflictDetectionError("Failed to switch to main: "+(0,o.getErrorMessage)(e),"single-agent",[])}}async commitChanges(e,t){const r=Date.now()
|
|
5478
5442
|
try{t&&t.length>0?await this.git.add(t):await this.git.add("."),await this.git.commit(e)
|
|
5479
5443
|
const n=await this.git.revparse(["HEAD"]),o=Date.now()-r
|
|
5480
5444
|
return this.metrics.recordValue("workspace.commit",o),this.logger.info("Successfully committed changes",{message:e,commitHash:n.substring(0,8),filesCount:t?.length||"all",duration:o}),{hash:n,message:e,files:t||[]}}catch(t){const n=Date.now()-r
|
|
@@ -5482,33 +5446,32 @@ throw this.metrics.recordValue("workspace.commit",n),this.logger.error("Failed t
|
|
|
5482
5446
|
try{s.WorkspaceLogging.logOperation(this.logger,"info","Starting request completion (refactored)",e,"single-agent","completeRequest",{requestTitle:t,skipConflictDetection:r?.skipConflictDetection||!1,architecture:"shared-processor"})
|
|
5483
5447
|
const o=await this.requestProcessor.completeRequest(e,t,{skipConflictDetection:r?.skipConflictDetection||!1}),i=Date.now()-n
|
|
5484
5448
|
return this.metrics.recordValue("workspace.complete",i),s.WorkspaceLogging.logOperation(this.logger,"info","Request completion successful (refactored)",e,"single-agent","completeRequest",{mergeCommitHash:o.mergeCommitHash.substring(0,8),mergedFiles:o.mergedFiles?.length||0,cleanedUp:o.cleanedUp,wasAutoMerged:o.autoMergeInfo?.wasAutoMerged,strategy:o.autoMergeInfo?.strategy,duration:i,architecture:"shared-processor"}),o}catch(t){const r=Date.now()-n
|
|
5485
|
-
throw this.metrics.recordValue("workspace.complete",r),s.WorkspaceLogging.logOperation(this.logger,"error","Request completion failed (refactored)",e,"single-agent","completeRequest",{error:(0,o.getErrorMessage)(t),duration:r,architecture:"shared-processor"}),t}}resolveFilePath(e){return n.default.resolve(this.basePath,e)}async createCommit(e,t){return await this.commitChanges(e,t)}async cancelRequest(e){const t=s.WorkspaceValidation.validateRequestId(e)
|
|
5449
|
+
throw this.metrics.recordValue("workspace.complete",r),s.WorkspaceLogging.logOperation(this.logger,"error","Request completion failed (refactored)",e,"single-agent","completeRequest",{error:(0,o.getErrorMessage)(t),duration:r,architecture:"shared-processor"}),t}}resolveFilePath(e,t){return n.default.resolve(this.basePath,e)}async createCommit(e,t,r){return await this.commitChanges(e,t)}async cancelRequest(e){const t=s.WorkspaceValidation.validateRequestId(e)
|
|
5486
5450
|
if(!t.isValid)throw Error("Invalid request ID: "+t.errors.join(", "))
|
|
5487
5451
|
const r="requests/"+t.sanitized
|
|
5488
|
-
try{s.WorkspaceLogging.logOperation(this.logger,"info","Cancelling request (deleting branch)",e,"single-agent","cancelRequest",{branchName:r,architecture:"aligned-with-multi-agent"}),this.currentBranch===r&&await this.switchToMain(),await this.git.deleteLocalBranch(r),s.WorkspaceLogging.logOperation(this.logger,"info","Successfully cancelled request",e,"single-agent","cancelRequest",{branchName:r,switchedToMain:this.currentBranch!==r})}catch(t){throw s.WorkspaceLogging.logOperation(this.logger,"error","Failed to cancel request",e,"single-agent","cancelRequest",{branchName:r,error:(0,o.getErrorMessage)(t)}),t}}async listActiveWorkspaces(){try{return(await this.git.branch()).all.filter((e=>e.startsWith("requests/"))).map((e=>({requestId:e.replace("requests/",""),path:this.basePath,branchName:e,isActive:this.currentBranch===e,created:new Date,lastAccessed:new Date})))}catch(e){return this.logger.error("Failed to list active workspaces",{error:(0,o.getErrorMessage)(e)}),[]}}getCurrentContext(){return{requestId:this.currentRequestId,basePath:this.basePath,branchName:this.currentBranch,isMainBranch:"main"===this.currentBranch||"master"===this.currentBranch,mode:"single-agent"}}async getWorkspaceInfo(e){try{const t=s.WorkspaceValidation.validateRequestId(e)
|
|
5452
|
+
try{s.WorkspaceLogging.logOperation(this.logger,"info","Cancelling request (deleting branch)",e,"single-agent","cancelRequest",{branchName:r,architecture:"aligned-with-multi-agent"}),this.currentBranch===r&&await this.switchToMain(),await this.git.deleteLocalBranch(r),s.WorkspaceLogging.logOperation(this.logger,"info","Successfully cancelled request",e,"single-agent","cancelRequest",{branchName:r,switchedToMain:this.currentBranch!==r})}catch(t){throw s.WorkspaceLogging.logOperation(this.logger,"error","Failed to cancel request",e,"single-agent","cancelRequest",{branchName:r,error:(0,o.getErrorMessage)(t)}),t}}async listActiveWorkspaces(){try{return(await this.git.branch()).all.filter((e=>e.startsWith("requests/"))).map((e=>({requestId:e.replace("requests/",""),path:this.basePath,branchName:e,isActive:this.currentBranch===e,created:new Date,lastAccessed:new Date})))}catch(e){return this.logger.error("Failed to list active workspaces",{error:(0,o.getErrorMessage)(e)}),[]}}getCurrentContext(e){return{requestId:this.currentRequestId,basePath:this.basePath,branchName:this.currentBranch,isMainBranch:"main"===this.currentBranch||"master"===this.currentBranch,mode:"single-agent"}}async getWorkspaceInfo(e){try{const t=s.WorkspaceValidation.validateRequestId(e)
|
|
5489
5453
|
if(!t.isValid)return null
|
|
5490
5454
|
const r=t.sanitized,n="requests/"+r,o=await this.git.branch()
|
|
5491
|
-
return o.all.includes(n)||o.all.includes("remotes/origin/"+n)?{requestId:r,path:this.basePath,branchName:n,isActive:this.currentBranch===n,created:new Date,lastAccessed:new Date}:null}catch(t){return this.logger.error("Failed to get workspace info",{requestId:e,error:(0,o.getErrorMessage)(t)}),null}}getMainGit(){return this.gitAdapter.getMainGit()}async getWorktreeInfo(e){}getCurrentGit(){return this.git}async ensureReadonlyBranchIfNeeded(e,r,n
|
|
5492
|
-
try{
|
|
5493
|
-
if(!
|
|
5494
|
-
|
|
5495
|
-
|
|
5496
|
-
|
|
5497
|
-
|
|
5498
|
-
|
|
5499
|
-
|
|
5500
|
-
this.
|
|
5501
|
-
|
|
5502
|
-
|
|
5503
|
-
|
|
5504
|
-
|
|
5505
|
-
|
|
5506
|
-
|
|
5507
|
-
|
|
5508
|
-
|
|
5509
|
-
this.
|
|
5510
|
-
|
|
5511
|
-
g.all.includes(h)||g.all.includes("remotes/origin/"+h)?(await this.git.checkout(h),this.currentBranch=h,this.currentRequestId=u,this.logger.info("Successfully switched to readonly branch",{currentBranch:this.currentBranch,currentRequestId:this.currentRequestId})):this.logger.warn("Readonly branch does not exist",{readonlyBranch:h})}catch(e){this.logger.debug("Error during readonly branch check",{error:(0,o.getErrorMessage)(e)})}}}async fetchAgentConfig(e){try{const t="http://localhost:3456/api/agents/by-name/"+encodeURIComponent(e),r=await fetch(t)
|
|
5455
|
+
return o.all.includes(n)||o.all.includes("remotes/origin/"+n)?{requestId:r,path:this.basePath,branchName:n,isActive:this.currentBranch===n,created:new Date,lastAccessed:new Date}:null}catch(t){return this.logger.error("Failed to get workspace info",{requestId:e,error:(0,o.getErrorMessage)(t)}),null}}getMainGit(){return this.gitAdapter.getMainGit()}async getWorktreeInfo(e){}getCurrentGit(e){return this.git}async ensureReadonlyBranchIfNeeded(e,t,r,n){if(!this.readonlyBranchCheckDone){this.readonlyBranchCheckDone=!0
|
|
5456
|
+
try{const e=n
|
|
5457
|
+
if(!e)return void this.logger.debug("No sessionId available for readonly check")
|
|
5458
|
+
this.logger.debug("Checking readonly branch for session",{sessionId:e,toolName:t})
|
|
5459
|
+
const o=r?.getCLISessionClient?.()
|
|
5460
|
+
if(!o)return void this.logger.debug("No CLI session client available for readonly check")
|
|
5461
|
+
const s=await o.getByExternalId(e)
|
|
5462
|
+
if(!s?.agentType)return void this.logger.debug("No agent type found for session",{sessionId:e})
|
|
5463
|
+
this.logger.debug("Found session agent type",{sessionId:e,agentType:s.agentType})
|
|
5464
|
+
const i=await this.fetchAgentConfig(s.agentType)
|
|
5465
|
+
if(!i||"readonly"!==i.requestContextMode)return void this.logger.debug("Agent does not have readonly requestContextMode",{agentType:s.agentType})
|
|
5466
|
+
this.logger.debug("Agent has readonly requestContextMode",{agentType:s.agentType})
|
|
5467
|
+
const a=r?.getSessionRequestAssociationClient?.()
|
|
5468
|
+
if(!a)return void this.logger.debug("No session association client available")
|
|
5469
|
+
const c=await a.getActiveRequestsForSession(e,!0)
|
|
5470
|
+
if(0===c.length)return void this.logger.debug("No active request association found for session",{sessionId:e})
|
|
5471
|
+
const l=c[0].requestLocalId,d="requests/"+l
|
|
5472
|
+
this.logger.info("Readonly agent with request association, switching to branch without locking",{sessionId:e,agentType:s.agentType,requestId:l,readonlyBranch:d})
|
|
5473
|
+
const u=await this.git.branch()
|
|
5474
|
+
u.all.includes(d)||u.all.includes("remotes/origin/"+d)?(await this.git.checkout(d),this.currentBranch=d,this.currentRequestId=l,this.logger.info("Successfully switched to readonly branch",{currentBranch:this.currentBranch,currentRequestId:this.currentRequestId})):this.logger.warn("Readonly branch does not exist",{readonlyBranch:d})}catch(e){this.logger.debug("Error during readonly branch check",{error:(0,o.getErrorMessage)(e)})}}}async fetchAgentConfig(e){try{const t="http://localhost:3456/api/agents/by-name/"+encodeURIComponent(e),r=await fetch(t)
|
|
5512
5475
|
if(!r.ok)return null
|
|
5513
5476
|
const n=await r.json()
|
|
5514
5477
|
return n.success?n.data??null:null}catch{return null}}async cleanup(){this.logger.info("Cleaning up single-agent workspace manager")}}},9671(e,exports){Object.defineProperty(exports,"__esModule",{value:!0}),exports.findPreviousCommit=async function(e,t,r){try{if(!r){const r=await e.raw(["rev-list","--max-count=1","HEAD","--",t])
|
|
@@ -5651,7 +5614,7 @@ try{await o.default.promises.mkdir(u,{recursive:!0})}catch(e){return n.error("Fa
|
|
|
5651
5614
|
try{if(!o.default.existsSync(t)){n.warn("Plugin source not found: "+e.sourceName,{sourcePath:t}),l.errors.push(e.destName)
|
|
5652
5615
|
continue}const c=await o.default.promises.readFile(t,"utf8").catch((()=>null))
|
|
5653
5616
|
if(null===c){n.warn("Could not read plugin source: "+e.sourceName),l.errors.push(e.destName)
|
|
5654
|
-
continue}const d=e.destName.startsWith("lib/")?c:["
|
|
5617
|
+
continue}const d=e.destName.startsWith("lib/")?c:['import { createRequire as __createRequire } from "node:module";\nconst require = __createRequire(import.meta.url);\nconst __plugin = (function() {\n const module = { exports: {} };\n const exports = module.exports;\n (function() {',c," })();\n return module.exports.default || module.exports;\n})();\nexport default __plugin;"].join("\n"),h=i.default.createHash("md5").update(d).digest("hex"),g=r(a)
|
|
5655
5618
|
if(null===g||h!==g){const t=s.default.dirname(a)
|
|
5656
5619
|
t!==u&&await o.default.promises.mkdir(t,{recursive:!0}),await o.default.promises.writeFile(a,d,"utf8"),n.info("Synced plugin: "+e.destName,{reason:null===g?"not installed":"updated"}),l.synced.push(e.destName)}else l.skipped.push(e.destName)}catch(t){n.error("Failed to sync plugin: "+e.destName,{error:t instanceof Error?t.message:"Unknown error"}),l.errors.push(e.destName)}}return l}
|
|
5657
5620
|
const o=n(t(9896)),s=n(t(6928)),i=n(t(6982)),a=[{sourceName:"plugins/hooks/plugin.js",destName:"event-hooks.js"},{sourceName:"plugins/hooks/lib/condition-evaluator.js",destName:"lib/condition-evaluator.js"},{sourceName:"plugins/hooks/lib/hook-utils.js",destName:"lib/hook-utils.js"},{sourceName:"plugins/hooks/lib/dedup-utils.js",destName:"lib/dedup-utils.js"},{sourceName:"plugins/inject-session.js",destName:"inject-session.js"},{sourceName:"plugins/system-logger.js",destName:"system-logger.js"}]},9947(e,exports){function t(e,t){return e.substring(0,t).split("\n").length}function r(e){if(0===e.length)return[]
|