alchemylab 1.3.2 → 1.3.3
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/cli.js +8 -7
- package/dist/http-server.js +3 -3
- package/dist/index.js +79 -79
- package/dist/mcp-direct.js +3 -3
- package/package.json +1 -1
package/dist/cli.js
CHANGED
|
@@ -96,9 +96,9 @@ if(this.TOKEN_CACHE.hasValidToken&&e<this.TOKEN_CACHE.hasValidToken.expiresAt){c
|
|
|
96
96
|
return this.logger.debug("Using cached hasValidToken result",{ageSecs:Math.round((e-t.timestamp)/1e3),hasToken:t.value}),t.value}this.logger.debug("Checking if valid token exists (cache miss or expired)")
|
|
97
97
|
const t=null!==await this.getToken()
|
|
98
98
|
return this.TOKEN_CACHE.hasValidToken={value:t,timestamp:e,expiresAt:e+this.CACHE_TTL_MS,lastCheck:e,exists:t},t}getTokenDirectoryPath(){return this.tokenDirPath}getManualTokenFilePath(){return r.default.join(this.tokenDirPath,"manual-token.json")}logTokenLocationInstructions(){const e=this.getManualTokenFilePath()
|
|
99
|
-
console.log("========================================"),console.log("To use
|
|
99
|
+
console.log("========================================"),console.log("To use the alchemy CLI, you need to authenticate."),console.log("Token file location: "+e),console.log("You can either:"),console.log('\n1. Use the authenticate tool (recommended)\n2. Manually place a token file at the above location\n3. Set up automatic authentication flow\n\nFor manual token placement, create a JSON file with:\n{\n "token": "your_token_here",\n "userId": "your_user_id",\n "username": "your_username", \n "role": "user",\n "expiresAt": "2025-12-31T23:59:59.000Z"\n}\n'),console.log("For more information, see the authentication documentation."),console.log("========================================")}async startAuthenticationFlow(){this.pendingAuthCheck=!0
|
|
100
100
|
try{const{tempCode:e,authUrl:t}=await this.authFlow.startAuthFlow()
|
|
101
|
-
return this.tempAuthCode=e,this.logger.info("Started external authentication flow",{tempCode:e,authUrl:t}),this.authFlow.startPolling(e,(async t=>{this.logger.info("Authentication flow completed",{tempCode:e.substring(0,4)+"***",username:t.username}),await this.storeToken(t),this.pendingAuthCheck=!1,this.tempAuthCode=null,this.invalidateCache(),console.log("Authentication successful!"),console.log(`Welcome, ${t.username}!`),console.log("You can now use
|
|
101
|
+
return this.tempAuthCode=e,this.logger.info("Started external authentication flow",{tempCode:e,authUrl:t}),this.authFlow.startPolling(e,(async t=>{this.logger.info("Authentication flow completed",{tempCode:e.substring(0,4)+"***",username:t.username}),await this.storeToken(t),this.pendingAuthCheck=!1,this.tempAuthCode=null,this.invalidateCache(),console.log("Authentication successful!"),console.log(`Welcome, ${t.username}!`),console.log("You can now use the alchemy CLI."),console.log("========================================")}),(()=>{this.logger.info("Authentication flow timed out",{tempCode:e.substring(0,4)+"***"}),this.pendingAuthCheck=!1,this.tempAuthCode=null,console.log("Authentication flow timed out."),console.log("Please try again or manually place a token file."),console.log("Token file location:"),console.log(""+this.getManualTokenFilePath()),console.log("========================================")}),(t=>{this.logger.error("Authentication flow error",{tempCode:e.substring(0,4)+"***",error:t}),this.pendingAuthCheck=!1,this.tempAuthCode=null,console.log("Authentication flow error."),console.log("Error: "+t),console.log("Please try again or manually place a token file."),console.log(""+this.getManualTokenFilePath()),console.log("========================================")})),{tempCode:e,authUrl:t}}catch(e){throw this.logger.error("Error starting authentication flow",{error:(0,c.getErrorMessage)(e)}),this.pendingAuthCheck=!1,this.tempAuthCode=null,e}}hasPendingAuth(){return this.pendingAuthCheck||!!this.tempAuthCode}getAuthStatus(){return this.hasPendingAuth()?{hasToken:!1,isPendingAuth:!0,tempCode:this.tempAuthCode,authUrl:this.authFlow.getAuthUrl(this.tempAuthCode)}:{hasToken:!1,isPendingAuth:!1}}async checkAuthStatus(e){if(!e)return null
|
|
102
102
|
try{const t=this.authFlow.getPollingStatus()
|
|
103
103
|
if(t.status===a.PollingStatus.AUTHENTICATED&&t.tokenInfo)return this.logger.info("Authentication polling has token available",{tempCode:e.substring(0,4)+"***",username:t.tokenInfo.username}),t.tokenInfo
|
|
104
104
|
if(t.status===a.PollingStatus.ERROR||t.status===a.PollingStatus.TIMEOUT)return this.pendingAuthCheck=!1,this.tempAuthCode=null,null
|
|
@@ -177,7 +177,7 @@ const r=s(t(7252)),o=s(t(8577)),n=t(4192),i=t(1152),a=s(t(6928)),c=s(t(9896)),l=
|
|
|
177
177
|
class I{updateAuthToken(e){this.options.authToken=e,this.apiClient.authToken=e,this.configurer.authToken=e}constructor(e,t){this.directReportDedup=new Map,this.activeMcpCalls=new Map,this.pendingAgentResync=!1,this.settingsSyncCounter=0,this.versionWarnings=[],this.updateBlocked=!1,this._pendingUpdateBlock=!1,this.isPolling=!1,this.isProcessingAction=!1,this.openCodeUrlCache=null,this.openCodePort=null,this.proxyAbortControllers=new Map,this.trackedChildPids=new Set,this.sseEventBuffer=[],this.hasRemoteEventConsumers=!1,this.cachedProjectConfig=null,this.logger=e,this.options=t,this.port=t.port||3456,this.startTime=new Date
|
|
178
178
|
const s=(0,i.createMetricsCollector)(!1)
|
|
179
179
|
this.apiClient=new n.BaseApiClient(t.remoteServerUrl,e,s,t.authToken,{timeout:35e3}),this.configurer=new u.MCPClientConfigurer(e,t.remoteServerUrl,t.authToken),this.cliBridge=new h.CLIBridgeWebSocket(e),(0,h.setCLIBridge)(this.cliBridge),this.hookExecutor=new f.HookExecutor(e,"",t.projectPath,this.apiClient,{cachedDefaultModel:this.cachedDefaultModel,trackChildPid:e=>this.trackedChildPids.add(e)}),this.app=this.createApp()}createApp(){const e=(0,r.default)()
|
|
180
|
-
return e.use((0,o.default)()),e.use(r.default.json({limit:"10mb"})),e.get("/health",this.handleHealth.bind(this)),e.get("/status",this.handleStatus.bind(this)),e.get("/opencode",this.handleOpenCodeConfig.bind(this)),e.post("/sync-agents",this.handleSyncAgents.bind(this)),e.post("/api/generate-journal",this.handleGenerateJournal.bind(this)),e.get("/api/event-hooks/by-event/:eventType",this.handleEventHooksProxy.bind(this)),e.post("/api/hook-triggers",this.handleHookTriggersProxy.bind(this)),e.get("/api/hook-iterations/:sessionId/:hookId",this.handleGetHookIteration.bind(this)),e.post("/api/hook-iterations/:sessionId/:hookId/increment",this.handleIncrementHookIteration.bind(this)),e.get("/api/project-settings",((e,t)=>{t.json({success:!0,data:{defaultModel:this.cachedDefaultModel||null}})})),e.post("/api/sync-settings",(async(e,t)=>{await this.syncProjectSettings(),t.json({success:!0,data:{defaultModel:this.cachedDefaultModel||null}})})),e.get("/api/agents/by-name/:agentName",this.handleGetAgentByName.bind(this)),e.get("/api/sessions/:sessionId/agent-type",this.handleGetSessionAgentType.bind(this)),e.get("/api/sessions/:sessionId/parent",this.handleGetSessionParent.bind(this)),e.get("/api/sessions/:sessionId/ancestors",(async(e,t)=>{try{const{sessionId:s}=e.params,r=this.projectId
|
|
180
|
+
return e.use(((e,t,s)=>{t.setHeader("Access-Control-Allow-Private-Network","true"),s()})),e.use((0,o.default)()),e.use(r.default.json({limit:"10mb"})),e.get("/health",this.handleHealth.bind(this)),e.get("/status",this.handleStatus.bind(this)),e.get("/opencode",this.handleOpenCodeConfig.bind(this)),e.post("/sync-agents",this.handleSyncAgents.bind(this)),e.post("/api/generate-journal",this.handleGenerateJournal.bind(this)),e.get("/api/event-hooks/by-event/:eventType",this.handleEventHooksProxy.bind(this)),e.post("/api/hook-triggers",this.handleHookTriggersProxy.bind(this)),e.get("/api/hook-iterations/:sessionId/:hookId",this.handleGetHookIteration.bind(this)),e.post("/api/hook-iterations/:sessionId/:hookId/increment",this.handleIncrementHookIteration.bind(this)),e.get("/api/project-settings",((e,t)=>{t.json({success:!0,data:{defaultModel:this.cachedDefaultModel||null}})})),e.post("/api/sync-settings",(async(e,t)=>{await this.syncProjectSettings(),t.json({success:!0,data:{defaultModel:this.cachedDefaultModel||null}})})),e.get("/api/agents/by-name/:agentName",this.handleGetAgentByName.bind(this)),e.get("/api/sessions/:sessionId/agent-type",this.handleGetSessionAgentType.bind(this)),e.get("/api/sessions/:sessionId/parent",this.handleGetSessionParent.bind(this)),e.get("/api/sessions/:sessionId/ancestors",(async(e,t)=>{try{const{sessionId:s}=e.params,r=this.projectId
|
|
181
181
|
if(!r)return void t.status(400).json({success:!1,error:"No project"})
|
|
182
182
|
const o=await this.apiClient.get(`/api/projects/${r}/cli-sessions/external/opencode/${encodeURIComponent(s)}/ancestors`),n=(o?.data||o||[]).map((e=>({externalSessionId:e.externalSessionId,agentType:e.agentType,title:e.title})))
|
|
183
183
|
t.json({success:!0,ancestors:n})}catch(e){t.status(500).json({success:!1,error:(0,g.getErrorMessage)(e)})}})),e.get("/api/registry/projects",(async(e,s)=>{try{const{listLive:e}=await t.e(640).then(t.bind(t,2640))
|
|
@@ -1158,7 +1158,7 @@ if(this.logger.debug("Polling response",{data:r}),r.authenticated&&r.token){this
|
|
|
1158
1158
|
const s=this.parseTokenResponse(r)
|
|
1159
1159
|
if(!s)throw Error("Invalid token response from server")
|
|
1160
1160
|
this.pollingStatus=n.AUTHENTICATED,this.tokenResult=s,this.stopPolling(),t&&t(s)}else this.logger.debug("Not authenticated yet, continuing to poll",{tempCode:e.substring(0,4)+"***"})}catch(e){const t=(0,o.getErrorMessage)(e)
|
|
1161
|
-
throw Error(
|
|
1161
|
+
throw Error(`Error during polling: ${t}${/fetch failed|ECONNREFUSED|ENOTFOUND|ETIMEDOUT|network/i.test(t)?" (remote may be unreachable \u2014 check your connection and try again)":""}`)}}catch(t){const s=(0,o.getErrorMessage)(t)
|
|
1162
1162
|
this.logger.error("Error polling for authentication",{tempCode:e.substring(0,4)+"***",error:s}),this.pollingStatus=n.ERROR,this.pollingError=s,this.stopPolling(),r&&r(s)}}
|
|
1163
1163
|
return i(),this.pollingIntervalId=setInterval(i,this.pollingIntervalMs),()=>this.stopPolling()}stopPolling(){this.pollingIntervalId&&(clearInterval(this.pollingIntervalId),this.pollingIntervalId=null,this.logger.debug("Stopped polling for authentication",{status:this.pollingStatus}))}getPollingStatus(){const e={status:this.pollingStatus}
|
|
1164
1164
|
return this.pollingStatus===n.AUTHENTICATED&&this.tokenResult?e.tokenInfo=this.tokenResult:this.pollingStatus===n.ERROR&&this.pollingError&&(e.error=this.pollingError),this.pollingStartTime>0&&(e.elapsedTimeMs=Date.now()-this.pollingStartTime),e}resetPollingState(){this.stopPolling(),this.pollingStatus=n.NOT_STARTED,this.pollingStartTime=0,this.tokenResult=null,this.pollingError=null}async startGoogleOAuthFlow(){this.logger.info("Starting Google OAuth authentication flow")
|
|
@@ -1289,11 +1289,12 @@ let l=!1,u=null
|
|
|
1289
1289
|
const g=async()=>{l||(l=!0,u&&clearInterval(u),console.log(""),console.log("Shutting down..."),await $.stop(),process.exit(0))}
|
|
1290
1290
|
process.on("SIGTERM",g),process.on("SIGINT",g)
|
|
1291
1291
|
const{InteractiveShell:p}=await e.e(994).then(e.t.bind(e,5994,23)),f=new p({projectPath:i,logger:b,remoteServerUrl:E,authToken:P,projectId:_})
|
|
1292
|
-
|
|
1293
|
-
|
|
1292
|
+
let y=!1
|
|
1293
|
+
u=setInterval((async()=>{if(!y)try{if(await T.hasValidToken())return
|
|
1294
|
+
y=!0,console.log(""),console.log("\u26a0\ufe0f Auth token expired. Opening browser to re-authenticate...")
|
|
1294
1295
|
const e=await T.startAuthenticationFlow()
|
|
1295
1296
|
if(console.log("\u{1f310} "+e.authUrl),o(e.authUrl),console.log("\u23f1\ufe0f Waiting for re-authentication..."),await n(T)){const e=await T.getToken()
|
|
1296
|
-
e?.token&&(P=e.token,$.updateAuthToken(P)),console.log("\u2705 Re-authenticated successfully.")}else console.log("\u274c Re-authentication timed out. Some features may not work until you restart.")}catch(e){b.warn("Token watchdog check failed",{error:(0,I.getErrorMessage)(e)})}}),3e5),await f.start(g)}catch(e){b.error("Failed to start server",{error:(0,I.getErrorMessage)(e)}),console.error("\u274c Failed to start: "+(0,I.getErrorMessage)(e)),process.exit(1)}}({port:C})
|
|
1297
|
+
e?.token&&(P=e.token,$.updateAuthToken(P)),console.log("\u2705 Re-authenticated successfully.")}else console.log("\u274c Re-authentication timed out. Some features may not work until you restart.")}catch(e){b.warn("Token watchdog check failed",{error:(0,I.getErrorMessage)(e)})}finally{y=!1}}),3e5),await f.start(g)}catch(e){b.error("Failed to start server",{error:(0,I.getErrorMessage)(e)}),console.error("\u274c Failed to start: "+(0,I.getErrorMessage)(e)),process.exit(1)}}({port:C})
|
|
1297
1298
|
const E=b[0].toLowerCase()
|
|
1298
1299
|
switch("--help"!==E&&"-h"!==E||(s(),process.exit(0)),"--version"!==E&&"-v"!==E||(console.log("alchemy v"+t()),process.exit(0)),E){case"serve":await async function(e={}){const s=process.cwd()
|
|
1299
1300
|
r(s)||(console.log("\u{1f4c1} Current directory is not an AlchemyLab project."),console.log(""),console.log("\u{1f4a1} Run `alchemy` to initialize this project."),console.log(""),process.exit(1))
|
package/dist/http-server.js
CHANGED
|
@@ -587,9 +587,9 @@ if(this.TOKEN_CACHE.hasValidToken&&e<this.TOKEN_CACHE.hasValidToken.expiresAt){c
|
|
|
587
587
|
return this.logger.debug("Using cached hasValidToken result",{ageSecs:Math.round((e-t.timestamp)/1e3),hasToken:t.value}),t.value}this.logger.debug("Checking if valid token exists (cache miss or expired)")
|
|
588
588
|
const t=null!==await this.getToken()
|
|
589
589
|
return this.TOKEN_CACHE.hasValidToken={value:t,timestamp:e,expiresAt:e+this.CACHE_TTL_MS,lastCheck:e,exists:t},t}getTokenDirectoryPath(){return this.tokenDirPath}getManualTokenFilePath(){return n.default.join(this.tokenDirPath,"manual-token.json")}logTokenLocationInstructions(){const e=this.getManualTokenFilePath()
|
|
590
|
-
console.log("========================================"),console.log("To use
|
|
590
|
+
console.log("========================================"),console.log("To use the alchemy CLI, you need to authenticate."),console.log("Token file location: "+e),console.log("You can either:"),console.log('\n1. Use the authenticate tool (recommended)\n2. Manually place a token file at the above location\n3. Set up automatic authentication flow\n\nFor manual token placement, create a JSON file with:\n{\n "token": "your_token_here",\n "userId": "your_user_id",\n "username": "your_username", \n "role": "user",\n "expiresAt": "2025-12-31T23:59:59.000Z"\n}\n'),console.log("For more information, see the authentication documentation."),console.log("========================================")}async startAuthenticationFlow(){this.pendingAuthCheck=!0
|
|
591
591
|
try{const{tempCode:e,authUrl:t}=await this.authFlow.startAuthFlow()
|
|
592
|
-
return this.tempAuthCode=e,this.logger.info("Started external authentication flow",{tempCode:e,authUrl:t}),this.authFlow.startPolling(e,(async t=>{this.logger.info("Authentication flow completed",{tempCode:e.substring(0,4)+"***",username:t.username}),await this.storeToken(t),this.pendingAuthCheck=!1,this.tempAuthCode=null,this.invalidateCache(),console.log("Authentication successful!"),console.log(`Welcome, ${t.username}!`),console.log("You can now use
|
|
592
|
+
return this.tempAuthCode=e,this.logger.info("Started external authentication flow",{tempCode:e,authUrl:t}),this.authFlow.startPolling(e,(async t=>{this.logger.info("Authentication flow completed",{tempCode:e.substring(0,4)+"***",username:t.username}),await this.storeToken(t),this.pendingAuthCheck=!1,this.tempAuthCode=null,this.invalidateCache(),console.log("Authentication successful!"),console.log(`Welcome, ${t.username}!`),console.log("You can now use the alchemy CLI."),console.log("========================================")}),(()=>{this.logger.info("Authentication flow timed out",{tempCode:e.substring(0,4)+"***"}),this.pendingAuthCheck=!1,this.tempAuthCode=null,console.log("Authentication flow timed out."),console.log("Please try again or manually place a token file."),console.log("Token file location:"),console.log(""+this.getManualTokenFilePath()),console.log("========================================")}),(t=>{this.logger.error("Authentication flow error",{tempCode:e.substring(0,4)+"***",error:t}),this.pendingAuthCheck=!1,this.tempAuthCode=null,console.log("Authentication flow error."),console.log("Error: "+t),console.log("Please try again or manually place a token file."),console.log(""+this.getManualTokenFilePath()),console.log("========================================")})),{tempCode:e,authUrl:t}}catch(e){throw this.logger.error("Error starting authentication flow",{error:(0,c.getErrorMessage)(e)}),this.pendingAuthCheck=!1,this.tempAuthCode=null,e}}hasPendingAuth(){return this.pendingAuthCheck||!!this.tempAuthCode}getAuthStatus(){return this.hasPendingAuth()?{hasToken:!1,isPendingAuth:!0,tempCode:this.tempAuthCode,authUrl:this.authFlow.getAuthUrl(this.tempAuthCode)}:{hasToken:!1,isPendingAuth:!1}}async checkAuthStatus(e){if(!e)return null
|
|
593
593
|
try{const t=this.authFlow.getPollingStatus()
|
|
594
594
|
if(t.status===a.PollingStatus.AUTHENTICATED&&t.tokenInfo)return this.logger.info("Authentication polling has token available",{tempCode:e.substring(0,4)+"***",username:t.tokenInfo.username}),t.tokenInfo
|
|
595
595
|
if(t.status===a.PollingStatus.ERROR||t.status===a.PollingStatus.TIMEOUT)return this.pendingAuthCheck=!1,this.tempAuthCode=null,null
|
|
@@ -5192,7 +5192,7 @@ if(this.logger.debug("Polling response",{data:n}),n.authenticated&&n.token){this
|
|
|
5192
5192
|
const r=this.parseTokenResponse(n)
|
|
5193
5193
|
if(!r)throw Error("Invalid token response from server")
|
|
5194
5194
|
this.pollingStatus=s.AUTHENTICATED,this.tokenResult=r,this.stopPolling(),t&&t(r)}else this.logger.debug("Not authenticated yet, continuing to poll",{tempCode:e.substring(0,4)+"***"})}catch(e){const t=(0,o.getErrorMessage)(e)
|
|
5195
|
-
throw Error(
|
|
5195
|
+
throw Error(`Error during polling: ${t}${/fetch failed|ECONNREFUSED|ENOTFOUND|ETIMEDOUT|network/i.test(t)?" (remote may be unreachable \u2014 check your connection and try again)":""}`)}}catch(t){const r=(0,o.getErrorMessage)(t)
|
|
5196
5196
|
this.logger.error("Error polling for authentication",{tempCode:e.substring(0,4)+"***",error:r}),this.pollingStatus=s.ERROR,this.pollingError=r,this.stopPolling(),n&&n(r)}}
|
|
5197
5197
|
return i(),this.pollingIntervalId=setInterval(i,this.pollingIntervalMs),()=>this.stopPolling()}stopPolling(){this.pollingIntervalId&&(clearInterval(this.pollingIntervalId),this.pollingIntervalId=null,this.logger.debug("Stopped polling for authentication",{status:this.pollingStatus}))}getPollingStatus(){const e={status:this.pollingStatus}
|
|
5198
5198
|
return this.pollingStatus===s.AUTHENTICATED&&this.tokenResult?e.tokenInfo=this.tokenResult:this.pollingStatus===s.ERROR&&this.pollingError&&(e.error=this.pollingError),this.pollingStartTime>0&&(e.elapsedTimeMs=Date.now()-this.pollingStartTime),e}resetPollingState(){this.stopPolling(),this.pollingStatus=s.NOT_STARTED,this.pollingStartTime=0,this.tokenResult=null,this.pollingError=null}async startGoogleOAuthFlow(){this.logger.info("Starting Google OAuth authentication flow")
|
package/dist/index.js
CHANGED
|
@@ -455,17 +455,17 @@ const x=new k.ConnectionStatusManager(T,n.child({component:"connection-status-ma
|
|
|
455
455
|
j.registerClient(M)
|
|
456
456
|
const O=new I.TaskClient(T,n.child({component:"task-client"}),o,M,x,R)
|
|
457
457
|
j.registerClient(O)
|
|
458
|
-
const
|
|
459
|
-
j.registerClient($)
|
|
460
|
-
const D=new C.ProxyClient(T,n.child({component:"proxy-client"}),o,M,R,x)
|
|
458
|
+
const D=new v.FileOperationsClient(T,n.child({component:"file-client"}),o,M,R,x)
|
|
461
459
|
j.registerClient(D)
|
|
460
|
+
const $=new C.ProxyClient(T,n.child({component:"proxy-client"}),o,M,R,x)
|
|
461
|
+
j.registerClient($)
|
|
462
462
|
const A=new _.RequestClient(T,n.child({component:"request-client"}),o,M,R,x)
|
|
463
463
|
A.setAuthToken(R),(0,d.isDebugToolsEnabled)()&&n.debug("Explicitly set token on RequestClient",{tokenPresent:!!R}),j.registerClient(A)
|
|
464
464
|
const F=new E.DocumentClient(T,n.child({component:"document-client"}),o,M,R,x)
|
|
465
465
|
j.registerClient(F)
|
|
466
466
|
const N=new q.ToolRecordClient(T,n.child({component:"tool-record-client"}),o,M,R,x)
|
|
467
467
|
j.registerClient(N)
|
|
468
|
-
const L=new S.ApiClient(P,M,O
|
|
468
|
+
const L=new S.ApiClient(P,M,O,D,A,F,N,$,n.child({component:"api-client"})),z=a.default.Router();(0,h.registerAuthRoutes)(z,{projectClient:M,taskClient:O,fileClient:D,authManager:P,apiClient:L},i,n)
|
|
469
469
|
const H=r.getContext();(0,g.registerConfigRoutes)(z,n,H.basePath),e.use("/api",z)
|
|
470
470
|
const B=e=>{const t=o.startTimer(e)
|
|
471
471
|
return e=>t(e)},U=(e,t,n)=>{const o=e.query.path||e.body.path
|
|
@@ -500,7 +500,7 @@ return r({endpoint:"files/content",method:"GET",success:!0,encoding:"binary"}),t
|
|
|
500
500
|
r({endpoint:"files/content",method:"GET",success:!0,encoding:o}),t.json({success:!0,data:{path:e.relativePath,content:s,size:n.size,modified:n.mtime}})}catch(t){throw"ENOENT"===t.code?(r({endpoint:"files/content",method:"GET",success:!1,error:"not_found"}),(0,u.createNotFoundError)("File not found: "+e.relativePath)):t}}catch(e){r(e)}})),e.post("/api/files/write",U,G,(async(e,t,s)=>{try{o.incrementCounter("api_requests_total",1,{endpoint:"files/write",method:"POST"})
|
|
501
501
|
const s=B("api_request_duration"),{content:i,taskId:a,format:c="text"}=e.body
|
|
502
502
|
if(void 0===i)throw(0,u.createValidationError)("Content parameter is required")
|
|
503
|
-
const l=await(0,f.handleWriteFile)({taskId:a,path:e.relativePath,content:i,format:c},r.getContext()
|
|
503
|
+
const l=await(0,f.handleWriteFile)({taskId:a,path:e.relativePath,content:i,format:c},r.getContext(),D,O,N,A,n,o)
|
|
504
504
|
s({endpoint:"files/write",method:"POST",success:!0}),t.json({success:!0,data:l})}catch(e){s(e)}})),e.post("/api/files/replace",U,G,(async(e,t,s)=>{try{o.incrementCounter("api_requests_total",1,{endpoint:"files/replace",method:"POST"})
|
|
505
505
|
const s=B("api_request_duration"),{replacements:i,mode:a="unique",taskId:c}=e.body
|
|
506
506
|
if(!i||!Array.isArray(i))throw(0,u.createValidationError)("Replacements array is required")
|
|
@@ -588,9 +588,9 @@ if(this.TOKEN_CACHE.hasValidToken&&e<this.TOKEN_CACHE.hasValidToken.expiresAt){c
|
|
|
588
588
|
return this.logger.debug("Using cached hasValidToken result",{ageSecs:Math.round((e-t.timestamp)/1e3),hasToken:t.value}),t.value}this.logger.debug("Checking if valid token exists (cache miss or expired)")
|
|
589
589
|
const t=null!==await this.getToken()
|
|
590
590
|
return this.TOKEN_CACHE.hasValidToken={value:t,timestamp:e,expiresAt:e+this.CACHE_TTL_MS,lastCheck:e,exists:t},t}getTokenDirectoryPath(){return this.tokenDirPath}getManualTokenFilePath(){return n.default.join(this.tokenDirPath,"manual-token.json")}logTokenLocationInstructions(){const e=this.getManualTokenFilePath()
|
|
591
|
-
console.log("========================================"),console.log("To use
|
|
591
|
+
console.log("========================================"),console.log("To use the alchemy CLI, you need to authenticate."),console.log("Token file location: "+e),console.log("You can either:"),console.log('\n1. Use the authenticate tool (recommended)\n2. Manually place a token file at the above location\n3. Set up automatic authentication flow\n\nFor manual token placement, create a JSON file with:\n{\n "token": "your_token_here",\n "userId": "your_user_id",\n "username": "your_username", \n "role": "user",\n "expiresAt": "2025-12-31T23:59:59.000Z"\n}\n'),console.log("For more information, see the authentication documentation."),console.log("========================================")}async startAuthenticationFlow(){this.pendingAuthCheck=!0
|
|
592
592
|
try{const{tempCode:e,authUrl:t}=await this.authFlow.startAuthFlow()
|
|
593
|
-
return this.tempAuthCode=e,this.logger.info("Started external authentication flow",{tempCode:e,authUrl:t}),this.authFlow.startPolling(e,(async t=>{this.logger.info("Authentication flow completed",{tempCode:e.substring(0,4)+"***",username:t.username}),await this.storeToken(t),this.pendingAuthCheck=!1,this.tempAuthCode=null,this.invalidateCache(),console.log("Authentication successful!"),console.log(`Welcome, ${t.username}!`),console.log("You can now use
|
|
593
|
+
return this.tempAuthCode=e,this.logger.info("Started external authentication flow",{tempCode:e,authUrl:t}),this.authFlow.startPolling(e,(async t=>{this.logger.info("Authentication flow completed",{tempCode:e.substring(0,4)+"***",username:t.username}),await this.storeToken(t),this.pendingAuthCheck=!1,this.tempAuthCode=null,this.invalidateCache(),console.log("Authentication successful!"),console.log(`Welcome, ${t.username}!`),console.log("You can now use the alchemy CLI."),console.log("========================================")}),(()=>{this.logger.info("Authentication flow timed out",{tempCode:e.substring(0,4)+"***"}),this.pendingAuthCheck=!1,this.tempAuthCode=null,console.log("Authentication flow timed out."),console.log("Please try again or manually place a token file."),console.log("Token file location:"),console.log(""+this.getManualTokenFilePath()),console.log("========================================")}),(t=>{this.logger.error("Authentication flow error",{tempCode:e.substring(0,4)+"***",error:t}),this.pendingAuthCheck=!1,this.tempAuthCode=null,console.log("Authentication flow error."),console.log("Error: "+t),console.log("Please try again or manually place a token file."),console.log(""+this.getManualTokenFilePath()),console.log("========================================")})),{tempCode:e,authUrl:t}}catch(e){throw this.logger.error("Error starting authentication flow",{error:(0,c.getErrorMessage)(e)}),this.pendingAuthCheck=!1,this.tempAuthCode=null,e}}hasPendingAuth(){return this.pendingAuthCheck||!!this.tempAuthCode}getAuthStatus(){return this.hasPendingAuth()?{hasToken:!1,isPendingAuth:!0,tempCode:this.tempAuthCode,authUrl:this.authFlow.getAuthUrl(this.tempAuthCode)}:{hasToken:!1,isPendingAuth:!1}}async checkAuthStatus(e){if(!e)return null
|
|
594
594
|
try{const t=this.authFlow.getPollingStatus()
|
|
595
595
|
if(t.status===a.PollingStatus.AUTHENTICATED&&t.tokenInfo)return this.logger.info("Authentication polling has token available",{tempCode:e.substring(0,4)+"***",username:t.tokenInfo.username}),t.tokenInfo
|
|
596
596
|
if(t.status===a.PollingStatus.ERROR||t.status===a.PollingStatus.TIMEOUT)return this.pendingAuthCheck=!1,this.tempAuthCode=null,null
|
|
@@ -681,7 +681,7 @@ I.initialScan={totalEntries:t.length,directories:r,files:n,firstFewFiles:n.slice
|
|
|
681
681
|
I.errors.push(t),l.error(t)}const M=_?"file":"directory"
|
|
682
682
|
l.info(`Searching for "${n}" in ${M} ${C} (mode: ${P})`,{needle:n,searchTarget:M,path:C,options:{maxResults:E,caseSensitive:q,fileExtension:x,searchIn:P}}),b=Date.now(),I.phases.initializationTime=b-u
|
|
683
683
|
const O=Date.now()
|
|
684
|
-
let
|
|
684
|
+
let D=[],$=0,A=0
|
|
685
685
|
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=[]
|
|
686
686
|
if(s.info("performLocalSearch started",{searchPath:e,pattern:t.toString(),options:n}),d)return await async function(e,t,r,n,o,s=0){const i=[],a=h.default.basename(e)
|
|
687
687
|
let c
|
|
@@ -698,16 +698,16 @@ const f={path:e,filesProcessed:0,filesMatched:0,subdirectories:0,errors:[]}
|
|
|
698
698
|
try{const{filesCount:n,fileMatchesCount:c,subdirCount:d,subdirStats:h}=await r(e,t,p,a,o,s,0,f,l,u)
|
|
699
699
|
return f.filesProcessed=n,f.filesMatched=c,f.subdirectories=d,i.directoryStats.push(f),h&&h.length>0&&i.directoryStats.push(...h),s.info("performLocalSearch completed",{totalFiles:n,matchesFound:p.length,directories:d+1}),{matches:p,totalFiles:n}}catch(t){const r="Error in performLocalSearch: "+(0,k.getErrorMessage)(t)
|
|
700
700
|
return f.errors.push(r),i.directoryStats.push(f),i.errors.push(r),s.error(r,{error:t instanceof Error?t.stack:t+"",searchPath:e}),{matches:p,totalFiles:f.filesProcessed}}}(C,R,{maxResults:E,fileExtension:x,searchIn:P,isFile:_,contextLines:j},x,l,I)
|
|
701
|
-
|
|
701
|
+
D=e.matches,$=e.totalFiles
|
|
702
702
|
const t=1e3
|
|
703
|
-
|
|
704
|
-
return r?r===h.default.basename(t)?r:r.startsWith("./")?r.substring(2):r:h.default.basename(t)}(C,e.file)})),l.info(`Local search completed: found ${A
|
|
705
|
-
I.errors.push(t),l.error(t),I.phases.searchTime=Date.now()-O}I.totalFiles=D
|
|
703
|
+
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)`),A=D.length,D.length>E&&(D=D.slice(0,E),l.info(`Limited results to ${E} (from ${A} total matches)`)),D.forEach((e=>{e.relativePath=function(e,t){const r=h.default.relative(e,t)
|
|
704
|
+
return r?r===h.default.basename(t)?r:r.startsWith("./")?r.substring(2):r:h.default.basename(t)}(C,e.file)})),l.info(`Local search completed: found ${A||D.length} total matches in ${$} files, returning ${D.length} results`),I.phases.searchTime=Date.now()-O}catch(e){const t="Error during search: "+(0,k.getErrorMessage)(e)
|
|
705
|
+
I.errors.push(t),l.error(t),I.phases.searchTime=Date.now()-O}I.totalFiles=$,I.totalMatches=D.length,I.endTime=Date.now()
|
|
706
706
|
let F,N=""
|
|
707
707
|
try{if(t.workspaceManager){const e=t.workspaceManager.getCurrentContext(t.currentSessionId)
|
|
708
708
|
e.branchName&&!e.permanentBranch&&(N=e.isMainBranch?` (searched on main branch: ${e.branchName})`:` (searched on request branch: ${e.branchName}${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})
|
|
709
709
|
const L="content"===P?"content":"filename"===P?"filenames":"content and filenames"
|
|
710
|
-
if(A
|
|
710
|
+
if(A>D.length?(F=`Found ${A} 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(j>0){const{filenameMatches:e,mergedGroups:t}=function(e,t){const r=e.filter((e=>"filename"===e.matchType)),n=e.filter((e=>"content"===e.matchType))
|
|
711
711
|
if(0===n.length)return{filenameMatches:r,mergedGroups:[]}
|
|
712
712
|
const o=new Map
|
|
713
713
|
for(const e of n){const t=o.get(e.file)||[]
|
|
@@ -715,7 +715,7 @@ t.push(e),o.set(e.file,t)}const i=[]
|
|
|
715
715
|
for(const[e,r]of o.entries()){r.sort(((e,t)=>e.line-t.line))
|
|
716
716
|
let e=[r[0]]
|
|
717
717
|
for(let n=1;n<r.length;n++){const o=e[e.length-1],a=r[n],c=o.line+t
|
|
718
|
-
a.line-t>c+1?(i.push(s(e,t)),e=[a]):e.push(a)}e.length>0&&i.push(s(e,t))}return{filenameMatches:r,mergedGroups:i}}(
|
|
718
|
+
a.line-t>c+1?(i.push(s(e,t)),e=[a]):e.push(a)}e.length>0&&i.push(s(e,t))}return{filenameMatches:r,mergedGroups:i}}(D,j),r=[]
|
|
719
719
|
e.forEach((e=>{r.push(e.relativePath+" [filename match]")})),t.forEach((e=>{const t=[]
|
|
720
720
|
e.lines.forEach((e=>{e.isMatch?t.push(`> ${e.lineNumber}: ${e.content}`):t.push(` ${e.lineNumber}: ${e.content}`)})),r.push(`${e.relativePath}:\n${t.join("\n")}`)})),F+=r.join("\n\n")}else F+=await async function(e){const t=e.filter((e=>"filename"===e.matchType)),r=e.filter((e=>"content"===e.matchType)),n=[]
|
|
721
721
|
t.length>0&&t.forEach((e=>{n.push(e.relativePath+" [filename match]")}))
|
|
@@ -726,7 +726,7 @@ const r=t[0].relativePath||e,o=t.length,s=await i(e)
|
|
|
726
726
|
let a=r
|
|
727
727
|
void 0!==s&&(a+=` (${s} lines)`),a+=` - ${o} ${1===o?"match":"matches"}:`
|
|
728
728
|
const c=t.map((e=>` :${e.line} - ${e.text}`))
|
|
729
|
-
n.push(a+"\n"+c.join("\n"))}return n.join("\n\n")}(
|
|
729
|
+
n.push(a+"\n"+c.join("\n"))}return n.join("\n\n")}(D)
|
|
730
730
|
else F+="No matches found."
|
|
731
731
|
return d({success:!0}),{content:[{type:"text",text:F}]}}catch(t){l.error("Search failed",{args:e,error:t instanceof Error?t.stack:t+""}),I.errors.push((0,k.getErrorMessage)(t)),I.endTime=Date.now(),l.debug("Search diagnostic information on error",{diagnostic:I})
|
|
732
732
|
let r="Search failed: "+(0,k.getErrorMessage)(t)
|
|
@@ -1735,27 +1735,27 @@ throw Error(x.error)}let M={hadUserMods:!1,userModsCommitHash:void 0}
|
|
|
1735
1735
|
if(r.git)try{y.debug("[MOVE-FILES] Checking for user changes before move operations")
|
|
1736
1736
|
const e=await(0,g.commitUserChangesBeforeToolOperation)(r.git,"move-files",{requestId:P,taskId:E,workspaceManager:r.workspaceManager},y,f)
|
|
1737
1737
|
e.userChangesCommitted&&(y.debug("[MOVE-FILES] User changes committed before move operations",{commitHash:e.commitHash?.substring(0,8),filesCommitted:e.filesCommitted}),y.info("User changes committed before move-files operation",{taskId:E,moveOperationsCount:S.length,userCommitHash:e.commitHash?.substring(0,8),userFilesCommitted:e.filesCommitted}),M={hadUserMods:!0,userModsCommitHash:e.commitHash})}catch(e){y.debug("[MOVE-FILES] Pre-tool commit failed, continuing with move operations",{error:e instanceof Error?e.message:e+""}),y.warn("Pre-tool user changes commit failed, continuing with move operation",{taskId:E,moveOperationsCount:S.length,error:e instanceof Error?e.message:e+""})}y.debug("[MOVE-FILES] Proceeding with move operations",{operationCount:S.length}),I=d.FileOperationPhase.RECORD_CREATION,f.incrementCounter("move_files_phase",1,{phase:I})
|
|
1738
|
-
const{toolRecordId:O,localToolRecordId
|
|
1738
|
+
const{toolRecordId:O,localToolRecordId:D}=await d.createFileOperationRecords(E,P,r.projectId,v.recordType,S[0].source,{operationCount:h.length,operations:S.map((e=>({source:e.source,destination:e.destination}))),userComment:C,hadUserMods:M.hadUserMods,userModsCommitHash:M.userModsCommitHash},n,o,y,f,v.metricsPrefix,m)
|
|
1739
1739
|
k=O,b=O,I=v.fileOperationPhase,f.incrementCounter("move_files_phase",1,{phase:I})
|
|
1740
|
-
const
|
|
1740
|
+
const $=[]
|
|
1741
1741
|
let A=0
|
|
1742
1742
|
for(const e of S){const t={operation:{source:e.source,destination:e.destination},success:!1}
|
|
1743
1743
|
try{try{await a.default.access(e.fullSource)}catch(t){throw Error("Source path not accessible: "+e.source)}const r=(await a.default.stat(e.fullSource)).isDirectory()
|
|
1744
1744
|
t.isDirectory=r
|
|
1745
1745
|
const n=c.default.dirname(e.fullDestination)
|
|
1746
|
-
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,A++,y.info("Successfully moved "+(r?"directory":"file"),{source:e.source,destination:e.destination,isDirectory:r})}catch(r){t.error=(0,p.getErrorMessage)(r),y.warn(`Failed to move ${e.source} to ${e.destination}`,{error:t.error})}
|
|
1746
|
+
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,A++,y.info("Successfully moved "+(r?"directory":"file"),{source:e.source,destination:e.destination,isDirectory:r})}catch(r){t.error=(0,p.getErrorMessage)(r),y.warn(`Failed to move ${e.source} to ${e.destination}`,{error:t.error})}$.push(t)}const F=Date.now()-w
|
|
1747
1747
|
f.recordValue("move_files_time",F),f.incrementCounter("move_files_operations_total",h.length),f.incrementCounter("move_files_operations_success",A),f.incrementCounter("move_files_operations_failed",h.length-A),A===h.length?f.incrementCounter("move_files_success",1):A>0?f.incrementCounter("move_files_partial_success",1):f.incrementCounter("move_files_total_failure",1)
|
|
1748
1748
|
let N=null
|
|
1749
1749
|
if(A>0){I=d.FileOperationPhase.GIT_COMMIT,f.incrementCounter("move_files_phase",1,{phase:I})
|
|
1750
|
-
const e
|
|
1751
|
-
N=await d.commitToGit(E,S[0].destination,O
|
|
1752
|
-
const L
|
|
1750
|
+
const e=$.filter((e=>e.success)),t=1===e.length?`Move ${e[0].isDirectory?"directory":"file"} from ${e[0].operation.source} to ${e[0].operation.destination} - ${C}`:`Move ${e.length} ${1===e.length?"item":"items"} - ${C}`
|
|
1751
|
+
N=await d.commitToGit(E,S[0].destination,O,D,t,r,y,f,v.metricsPrefix)}I=d.FileOperationPhase.RECORD_UPDATE_SUCCESS,f.incrementCounter("move_files_phase",1,{phase:I})
|
|
1752
|
+
const L=$.filter((e=>e.success)),z=$.filter((e=>!e.success))
|
|
1753
1753
|
await d.updateFileOperationRecords(E,k,b,S[0].source,v.recordType,A===h.length?`Successfully moved all ${h.length} items`:`Moved ${A}/${h.length} items successfully`,{status:A===h.length?"completed":"partial_success",commitHash:N?.commitHash,previousCommitHash:N?.previousCommitHash,operationCount:h.length,successCount:A,failureCount:h.length-A,successfulOperations:L.map((e=>({source:e.operation.source,destination:e.operation.destination,isDirectory:e.isDirectory}))),failedOperations:z.map((e=>({source:e.operation.source,destination:e.operation.destination,error:e.error}))),userComment:C,hadUserMods:M.hadUserMods,userModsCommitHash:M.userModsCommitHash},A===h.length?`Successfully moved all ${h.length} items`:`Moved ${A}/${h.length} items successfully`,n,o,y,f,v.metricsPrefix)
|
|
1754
1754
|
const H=r.getCurrentBranchContext?await r.getCurrentBranchContext():{branch:null,requestId:null,isMain:!0}
|
|
1755
1755
|
let B=""
|
|
1756
1756
|
if(A===h.length)B=`Successfully moved all ${h.length} ${1===h.length?"item":"items"}`
|
|
1757
|
-
else if(A>0){const e
|
|
1758
|
-
B=`Successfully moved ${A}/${h.length} items.\n\nFailed operations:\n`+e.map((e=>`\u2022 ${e.operation.source} \u2192 ${e.operation.destination}: ${e.error}`)).join("\n")}else B="All move operations failed:\n"
|
|
1757
|
+
else if(A>0){const e=$.filter((e=>!e.success))
|
|
1758
|
+
B=`Successfully moved ${A}/${h.length} items.\n\nFailed operations:\n`+e.map((e=>`\u2022 ${e.operation.source} \u2192 ${e.operation.destination}: ${e.error}`)).join("\n")}else B="All move operations failed:\n"+$.map((e=>`\u2022 ${e.operation.source} \u2192 ${e.operation.destination}: ${e.error}`)).join("\n")
|
|
1759
1759
|
if(N?.commitHash&&(B+="\nCommit: "+N.commitHash.substring(0,8)),H.requestId&&(B+="\nBranch: "+H.requestId),x.lockAcquired&&x.lockedRequestId){const e=r.workspaceManager?.getCurrentContext(r.currentSessionId)
|
|
1760
1760
|
e?.permanentBranch||(B+="\n\u{1f512} **Locked request:** "+x.lockedRequestId)}return{content:[{type:"text",text:B}],isError:0===A}}catch(t){if(e.taskId&&o)try{const n=t instanceof u.NotFoundError||t instanceof u.ValidationError||t instanceof h.ZodError
|
|
1761
1761
|
await o.createToolRecord({...n?{}:{taskId:e.taskId},projectId:r.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)(t),errorDetails:t instanceof Error?t.stack:t+"",phase:I,attemptedTaskId:e.taskId,taskIdValidationFailed:n},note:"Failed to move files - "+(0,p.getErrorMessage)(t)})}catch(t){y.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()-w
|
|
@@ -1767,7 +1767,7 @@ Object.defineProperty(exports,"__esModule",{value:!0}),exports.def=void 0
|
|
|
1767
1767
|
const r=t(6183),n=t(3707)
|
|
1768
1768
|
exports.def={name:"quick_manage",description:"WHEN TO USE: trivial single-file edits only. For multi-file or feature work, spawn a coder via subagent_operations.\n\nMove, delete, or create directories. Wraps the change in a request/task workflow that auto-completes.\n\nProvide an array of operations, each with operationType and corresponding data:\n\u2022 create-directory: { createDirectory: { path } }\n\u2022 move-files: { moveFiles: { moves: [{ source, destination }] } }\n\u2022 delete-files: { deleteFiles: { targets: [{ path }] } }\n\nFor read-only operations like get-file-info, use manage_files instead.\n\nRequires: title, description, operations.",schema:r.QuickManageSchema,annotations:{title:"Quick Manage",readOnlyHint:!1,destructiveHint:!0,idempotentHint:!1},handler(e,t){return(0,n.handleQuickChange)(e,"manage",t.context,t.apiClient,t.logger,t.metrics,t.mcpServer)}}},2462(e,exports,t){"use strict"
|
|
1769
1769
|
Object.defineProperty(exports,"__esModule",{value:!0})
|
|
1770
|
-
const r=t(2245),n=t(9080),o=t(5692),s=t(9030),i=t(2903),a=t(4607),c=t(9499),l=t(6770),d=t(8045),u=t(9697),h=t(9196),g=t(5459),p=t(4805),f=t(260),m=t(2283),y=t(4165),w=t(7834),k=t(9373),b=t(6111),I=t(700),v=t(2783),C=t(2601),_=t(1722),E=t(7257),q=t(9230),S=t(6064),T=t(5216),P=t(6473),j=t(4921),R=t(8850),x=t(3556),M=t(1391),O=t(6315)
|
|
1770
|
+
const r=t(2245),n=t(9080),o=t(5692),s=t(9030),i=t(2903),a=t(4607),c=t(9499),l=t(6770),d=t(8045),u=t(9697),h=t(9196),g=t(5459),p=t(4805),f=t(260),m=t(2283),y=t(4165),w=t(7834),k=t(9373),b=t(6111),I=t(700),v=t(2783),C=t(2601),_=t(1722),E=t(7257),q=t(9230),S=t(6064),T=t(5216),P=t(6473),j=t(4921),R=t(8850),x=t(3556),M=t(1391),O=t(6315),D=t(7713),$=t(6252),A=t(213),F=t(7250),N=t(2425),L=t(1540),z=t(5767),H=t(4973),B=t(509),U=t(7613),G=t(8456),W=t(3322),V=t(5247),J=t(8849),K=t(542);(0,r.registerTool)(n.def),(0,r.registerTool)(o.def),(0,r.registerTool)(s.def),(0,r.registerTool)(i.def),(0,r.registerTool)(a.def),(0,r.registerTool)(c.def),(0,r.registerTool)(l.def),(0,r.registerTool)(d.def),(0,r.registerTool)(u.def),(0,r.registerTool)(h.def),(0,r.registerTool)(g.def),(0,r.registerTool)(p.def),(0,r.registerTool)(f.def),(0,r.registerTool)(m.def),(0,r.registerTool)(y.def),(0,r.registerTool)(w.def),(0,r.registerTool)(k.def),(0,r.registerTool)(b.def),(0,r.registerTool)(I.def),(0,r.registerTool)(v.def),(0,r.registerTool)(S.def),(0,r.registerTool)(C.def),(0,r.registerTool)(_.def),(0,r.registerTool)(E.def),(0,r.registerTool)(q.def),(0,r.registerTool)(T.def),(0,r.registerTool)(P.def),(0,r.registerTool)(j.def),(0,r.registerTool)(R.def),(0,r.registerTool)(x.def),(0,r.registerTool)(M.def),(0,r.registerTool)(O.def),(0,r.registerTool)(D.def),(0,r.registerTool)($.def),(0,r.registerTool)(A.def),(0,r.registerTool)(F.def),(0,r.registerTool)(N.def),(0,r.registerTool)(L.def),(0,r.registerTool)(z.def),(0,r.registerTool)(H.def),(0,r.registerTool)(B.def),(0,r.registerTool)(U.def),(0,r.registerTool)(G.def),(0,r.registerTools)(W.metaDefs),(0,r.registerTools)(V.testingDefs),(0,r.registerTools)(J.checkingDefs),(0,r.registerTools)(K.debugDefs),(0,t(2245).freezeRegistry)()},2478(e,exports){"use strict"
|
|
1771
1771
|
Object.defineProperty(exports,"__esModule",{value:!0}),exports.requestConfig=void 0,exports.areTestsRequiredForCompletion=function(){return exports.requestConfig.requireTestsForCompletion},exports.setTestsRequiredForCompletion=function(e){exports.requestConfig.requireTestsForCompletion=e},exports.getCompletionMode=function(e){return e&&["auto-merge","auto-test-then-merge","manual-review"].includes(e)?e:"auto-merge"},exports.getApprovalMode=function(e){return e&&["none","require-approval"].includes(e)?e:"none"},exports.requestConfig={requireTestsForCompletion:!1}},2537(e,exports,t){"use strict"
|
|
1772
1772
|
async function r(e,t,r){if(C.has(r)&&_>=t){if(0===t)return 0
|
|
1773
1773
|
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]"
|
|
@@ -2296,20 +2296,20 @@ for(const e of j)x.push({type:"document",documentId:e.documentId,replacements:e.
|
|
|
2296
2296
|
if(x.length>0&&r.apiClient){const e=x.map((e=>e.documentId))
|
|
2297
2297
|
try{await(0,f.ensureDocumentsNotLocked)(e,r.apiClient,w,c,"replace-strings-documents")}catch(e){if(e instanceof h.ValidationError)return{content:[{type:"text",text:e.message}],isError:!0}
|
|
2298
2298
|
throw e}}v=u.FileOperationPhase.TASK_VALIDATION,c.incrementCounter("replace_strings_phase",1,{phase:v})
|
|
2299
|
-
const M=R.length>0?R[0].path:"document-operation",O=await u.validateTaskId(T,M,o,w,c,C.metricsPrefix)
|
|
2300
|
-
let
|
|
2301
|
-
R.length>0
|
|
2299
|
+
const M=R.length>0?R[0].path:"document-operation",O=await u.validateTaskId(T,M,o,w,c,C.metricsPrefix),D=O?.requestId
|
|
2300
|
+
let $=null
|
|
2301
|
+
R.length>0&&D&&($=await u.validateWorkItemStates(T,R[0].path,o,i,r,w,c,C.metricsPrefix))
|
|
2302
2302
|
let A={taskPromoted:!1,requestPromoted:!1}
|
|
2303
|
-
R.length>0&&$&&
|
|
2304
|
-
const F=await u.ensureCorrectWorkspaceContext({taskPromoted:A.taskPromoted,requestId
|
|
2303
|
+
R.length>0&&D&&$&&(A=await u.autoPromoteTaskStatus(T,O.status,D,$.request?.status,R[0].path,o,i,w,c,C.metricsPrefix),A.taskPromoted&&w.info("Auto-promoted task to in_progress for replace-strings operation",{taskId:T,requestId:D,previousStatus:O.status,newStatus:A.newTaskStatus,triggeringOperation:"replace-strings"}))
|
|
2304
|
+
const F=await u.ensureCorrectWorkspaceContext({taskPromoted:A.taskPromoted,requestId:D,context:r,operation:"replace-strings",logger:w,metrics:c,metricsPrefix:C.metricsPrefix})
|
|
2305
2305
|
if(!F.success){if(F.isLockConflict)return{content:[{type:"text",text:"\u274c "+F.error}],isError:!0}
|
|
2306
2306
|
throw Error(F.error)}if(R.length>0){w.debug("Re-validating file paths with correct workspace context",{operationCount:R.length,workspaceBasePath:r.workspaceManager?.getCurrentContext(r.currentSessionId).basePath})
|
|
2307
2307
|
for(let e=0;e<R.length;e++){const t=R[e],n=P[e],{normalizedPath:o,fullPath:s}=u.validateAndNormalizePath(n.path,r)
|
|
2308
|
-
R[e]={...t,path:o,fullPath:s}}}if(x.length>0
|
|
2308
|
+
R[e]={...t,path:o,fullPath:s}}}if(x.length>0&&D)try{await(0,g.validateRequestStatusForDocumentOperation)(D,i,w,c,"replace-strings-document")}catch(e){if(e instanceof h.ValidationError)return{content:[{type:"text",text:e.message}],isError:!0}
|
|
2309
2309
|
throw e}v=u.FileOperationPhase.RECORD_CREATION,c.incrementCounter("replace_strings_phase",1,{phase:v})
|
|
2310
|
-
const N=[...R.map((e=>({type:"file",path:e.path,replacements:e.replacements,mode:e.mode}))),...x.map((e=>({type:"document",documentId:e.documentId,replacements:e.replacements,mode:e.mode})))],{toolRecordId:L}=await u.createFileOperationRecords(T
|
|
2310
|
+
const N=[...R.map((e=>({type:"file",path:e.path,replacements:e.replacements,mode:e.mode}))),...x.map((e=>({type:"document",documentId:e.documentId,replacements:e.replacements,mode:e.mode})))],{toolRecordId:L}=await u.createFileOperationRecords(T,D,r.projectId,C.recordType,M,{operationCount:E.length,fileOperations:R.length,documentOperations:x.length,operations:N,userComment:q},o,s,w,c,C.metricsPrefix,y)
|
|
2311
2311
|
if(b=L,I=L,v=C.fileOperationPhase,c.incrementCounter("replace_strings_phase",1,{phase:v}),R.length>0&&r.git)try{w.debug("[REPLACE-STRINGS] Checking for user changes before replace operations")
|
|
2312
|
-
const e=await(0,p.commitUserChangesBeforeToolOperation)(r.git,"replace-strings",{requestId
|
|
2312
|
+
const e=await(0,p.commitUserChangesBeforeToolOperation)(r.git,"replace-strings",{requestId:D,taskId:T,workspaceManager:r.workspaceManager},w,c)
|
|
2313
2313
|
e.userChangesCommitted&&(w.debug("[REPLACE-STRINGS] User changes committed before replace operations",{commitHash:e.commitHash?.substring(0,8),filesCommitted:e.filesCommitted}),w.info("User changes committed before replace-strings operation",{taskId:T,fileOperationsCount:R.length,userCommitHash:e.commitHash?.substring(0,8),userFilesCommitted:e.filesCommitted}))}catch(e){w.debug("[REPLACE-STRINGS] 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:T,fileOperationsCount:R.length,error:e instanceof Error?e.message:e+""})}w.debug("[REPLACE-STRINGS] Proceeding with file operations",{fileCount:R.length})
|
|
2314
2314
|
const z=[]
|
|
2315
2315
|
let H=0,B=0
|
|
@@ -2673,7 +2673,7 @@ let v,C,_=d.FileOperationPhase.VALIDATION
|
|
|
2673
2673
|
const E={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"}
|
|
2674
2674
|
try{const n=d.validateArgs(e,l.WriteFileSchema),{path:f,documentId:q,content:S,format:T,append:P,comment:j}=n,{resolveActiveTaskId:R}=await Promise.resolve().then(t.bind(t,3451)),x=e.taskId||await R(r,o,m)||"untracked",M=!!q,O=!!f
|
|
2675
2675
|
k.info("Writing content to "+(M?"document":"file"),{taskId:x,filePath:O?f:void 0,documentId:M?q:void 0,contentLength:"string"==typeof S?S.length:JSON.stringify(S).length,format:T,append:P,comment:j})
|
|
2676
|
-
let
|
|
2676
|
+
let D,$,A,F="",N=!1,L=!1
|
|
2677
2677
|
const z=O?f:void 0
|
|
2678
2678
|
if(M){if(r.apiClient)try{await(0,p.ensureDocumentNotLocked)(q,r.apiClient,k,y,"write_file-document")}catch(e){if(e instanceof u.ValidationError)return{content:[{type:"text",text:e.message}],isError:!0}
|
|
2679
2679
|
throw e}if(!r.documentFileManager)throw Error("Document file manager not available")
|
|
@@ -2688,26 +2688,26 @@ O&&U&&G&&(W=await d.autoPromoteTaskStatus(x,B.status,U,G.request?.status,H,o,i,k
|
|
|
2688
2688
|
const V=await d.ensureCorrectWorkspaceContext({taskPromoted:W.taskPromoted,requestId:U,context:r,operation:"write_file",logger:k,metrics:y,metricsPrefix:E.metricsPrefix,requireRequestContext:O})
|
|
2689
2689
|
if(!V.success){if(V.isLockConflict)return{content:[{type:"text",text:"\u274c "+V.error}],isError:!0}
|
|
2690
2690
|
throw Error(V.error)}if(V.switched&&k.info("Workspace context successfully established",{requestId:U,branchName:V.branchName,operation:"write_file"}),O&&z){const e=d.validateAndNormalizePath(z,r)
|
|
2691
|
-
|
|
2692
|
-
try{await c.default.access(
|
|
2691
|
+
D=e.normalizedPath,$=e.fullPath,F=$
|
|
2692
|
+
try{await c.default.access($),L=!0}catch{L=!1,N=!0}k.debug("Path validated with correct workspace context",{rawPath:z,normalizedPath:D,fullPath:$,workspaceBasePath:r.workspaceManager?.getCurrentContext(r.currentSessionId).basePath})}if(M&&U)try{await(0,h.validateRequestStatusForDocumentOperation)(U,i,k,y,"write_file-document")}catch(e){if(e instanceof u.ValidationError)return{content:[{type:"text",text:e.message}],isError:!0}
|
|
2693
2693
|
throw e}_=d.FileOperationPhase.RECORD_CREATION,y.incrementCounter("write_file_phase",1,{phase:_})
|
|
2694
|
-
const{toolRecordId:J}=await d.createFileOperationRecords(x,U,r.projectId,E.recordType,H,{operationType:M?"document":"file",documentId:M?q:void 0,documentFilename:A,filePath:O
|
|
2694
|
+
const{toolRecordId:J}=await d.createFileOperationRecords(x,U,r.projectId,E.recordType,H,{operationType:M?"document":"file",documentId:M?q:void 0,documentFilename:A,filePath:O?D:void 0,contentLength:"string"==typeof S?S.length:JSON.stringify(S).length,format:T||"text",append:P||!1,wasFileCreated:!L,userComment:j},o,s,k,y,E.metricsPrefix,w)
|
|
2695
2695
|
let K
|
|
2696
2696
|
if(v=J,C=J,_=E.fileOperationPhase,y.incrementCounter("write_file_phase",1,{phase:_}),"json"===T)if("string"==typeof S)try{JSON.parse(S),K=S}catch(e){throw new u.ValidationError("Content is not valid JSON")}else K=JSON.stringify(S,null,2)
|
|
2697
2697
|
else K="string"==typeof S?S:JSON.stringify(S,null,2)
|
|
2698
2698
|
let Y=K
|
|
2699
2699
|
if(O&&r.git)try{k.debug("[WRITE-FILE] Checking for user changes before write operation")
|
|
2700
2700
|
const e=await(0,g.commitUserChangesBeforeToolOperation)(r.git,"write_file",{requestId:r.workspaceManager?.getCurrentContext(r.currentSessionId)?.requestId,taskId:x},k,y)
|
|
2701
|
-
e.userChangesCommitted&&(k.debug("[WRITE-FILE] User changes committed before write operation",{commitHash:e.commitHash?.substring(0,8),filesCommitted:e.filesCommitted}),k.info("User changes committed before write-file operation",{taskId:x,path
|
|
2701
|
+
e.userChangesCommitted&&(k.debug("[WRITE-FILE] User changes committed before write operation",{commitHash:e.commitHash?.substring(0,8),filesCommitted:e.filesCommitted}),k.info("User changes committed before write-file operation",{taskId:x,path:D,userCommitHash:e.commitHash?.substring(0,8),userFilesCommitted:e.filesCommitted}))}catch(e){k.debug("[WRITE-FILE] Pre-tool commit failed, continuing with write",{error:e instanceof Error?e.message:e+""}),k.warn("Pre-tool user changes commit failed, continuing with write operation",{taskId:x,path:D,error:e instanceof Error?e.message:e+""})}if(!F)throw Error("Target path not properly initialized")
|
|
2702
2702
|
if(k.debug("[WRITE-FILE] Proceeding with file write operation",{targetPath:F}),P&&L)try{Y=await c.default.readFile(F,"utf8")+K}catch(e){k.warn("Failed to read existing content for append",{error:e})}const Q=a.default.dirname(F)
|
|
2703
|
-
if(await c.default.mkdir(Q,{recursive:!0}),await c.default.writeFile(F,Y,"utf8"),k.info("Content written successfully",{path:O
|
|
2703
|
+
if(await c.default.mkdir(Q,{recursive:!0}),await c.default.writeFile(F,Y,"utf8"),k.info("Content written successfully",{path:O?D:"document:"+q,finalLength:Y.length,append:P,wasCreated:N}),M){r.documentFileManager.markForSync(q)
|
|
2704
2704
|
try{await r.documentFileManager.syncDocument(q),k.info("Document synced successfully",{documentId:q})}catch(e){k.warn("Failed to sync document immediately",{documentId:q,error:e})}}let Z,X,ee=null,te=!1
|
|
2705
2705
|
if(O){if(_=d.FileOperationPhase.GIT_COMMIT,y.incrementCounter("write_file_phase",1,{phase:_}),r.workspaceManager){const e=r.workspaceManager.getCurrentContext(r.currentSessionId)
|
|
2706
|
-
X=e.branchName,te=e.permanentBranch,k.debug("Retrieved branch name from workspace manager",{branchName:X,requestId:e.requestId,mode:e.mode,isMainBranch:e.isMainBranch})}try{const e=`${N?"Create":P?"Append to":"Update"} ${
|
|
2707
|
-
Z=t.commitHash,ee=t.previousCommitHash,k.info("Changes committed to git via shared utility",{path
|
|
2706
|
+
X=e.branchName,te=e.permanentBranch,k.debug("Retrieved branch name from workspace manager",{branchName:X,requestId:e.requestId,mode:e.mode,isMainBranch:e.isMainBranch})}try{const e=`${N?"Create":P?"Append to":"Update"} ${D} (${C})`,t=await d.commitToGit(x,D,C,C,e,r,k,y,E.metricsPrefix)
|
|
2707
|
+
Z=t.commitHash,ee=t.previousCommitHash,k.info("Changes committed to git via shared utility",{path:D,commitMessage:e,commitHash:Z?.substring(0,8),previousCommitHash:ee?.substring(0,8),branchName:X,toolRecordId:C})}catch(e){k.warn("Git operations failed via shared utility",{error:e})}}try{await s.updateToolRecord(C,{metadata:{path:O?D:"document:"+q,status:"completed",finalContentLength:Y.length,wasFileCreated:N,wasAppended:P&&L,operationType:M?"document":"file",processingTime:Date.now()-I,userComment:j,...O&&Z&&{commitHash:Z,previousCommitHash:ee||void 0}},note:"Write operation completed successfully"+(M?" (document synced)":" (committed to git)")})}catch(e){k.warn("Failed to update tool record",{recordError:e})}let re=`**${N?"Created":P?"Appended to":"Updated"} ${M?`document ${q}${A?` (${A})`:""}`:"file "+D}**\n`
|
|
2708
2708
|
re+=`**Content Length:** ${Y.length} characters\n`,O&&X&&(te||(re+=`**Branch:** ${X}\n`)),V.lockAcquired&&V.lockedRequestId&&!te&&(re+=`**Locked request:** ${V.lockedRequestId}\n`),O&&Z&&(re+=`**Commit Hash:** ${Z.substring(0,8)}\n`,ee&&(re+=`**Previous Commit:** ${ee.substring(0,8)}\n`)),C&&(re+=`[RECORD:${C}]\n`),M&&(re+=`\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 \`${q}\`.`)
|
|
2709
2709
|
const ne=Date.now()
|
|
2710
|
-
return k.info("Write operation completed successfully",{duration:ne-I,path:O
|
|
2710
|
+
return k.info("Write operation completed successfully",{duration:ne-I,path:O?D:"document:"+q,contentLength:Y.length,wasCreated:N}),b({tool:"write_file",success:!0}),y.incrementCounter("write_file_total",1,{success:!0}),r.workspaceManager?.largeFileWarning&&(re+=r.workspaceManager.largeFileWarning,r.workspaceManager.largeFileWarning=""),{content:[{type:"text",text:re}]}}catch(t){const r=Date.now()-I
|
|
2711
2711
|
if(k.error("Write operation failed",{error:t instanceof Error?t.stack:t+"",duration:r,phase:_}),C)try{await s.updateToolRecord(C,{metadata:{path:e?.path,status:"failed",error:(0,f.getErrorMessage)(t),phase:_,duration:r,userComment:e?.comment},note:"Write operation failed: "+(0,f.getErrorMessage)(t)})}catch(e){}return b({tool:"write_file",success:!1}),y.incrementCounter("write_file_errors",1,{phase:_}),{content:[{type:"text",text:"\u274c **Write Operation Failed:** "+(0,f.getErrorMessage)(t)}],isError:!0}}}
|
|
2712
2712
|
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){"use strict"
|
|
2713
2713
|
Object.defineProperty(exports,"__esModule",{value:!0})},4139(e,exports){"use strict"
|
|
@@ -3467,10 +3467,10 @@ const R=j.filter((e=>"file"===e.type)),x=j.filter((e=>"document"===e.type)),M=j.
|
|
|
3467
3467
|
m.info("Starting mixed file and document deletion operation",{taskId:P,totalOperations:j.length,fileOperations:R.length,documentOperations:x.length,comment:S}),l.validateTaskIdFormat(P,m,s,I.metricsPrefix)
|
|
3468
3468
|
const O=r.getCurrentBranchContext?await r.getCurrentBranchContext():{branch:null,requestId:null,isMain:!0}
|
|
3469
3469
|
m.info("Initial branch context",{initialBranch:O.branch,initialRequestId:O.requestId,isMain:O.isMain})
|
|
3470
|
-
const
|
|
3470
|
+
const D=[]
|
|
3471
3471
|
for(const e of R){const{normalizedPath:t,fullPath:n}=l.validateAndNormalizePath(e.target,r)
|
|
3472
|
-
|
|
3473
|
-
const D
|
|
3472
|
+
D.push({normalized:t,full:n})}b=l.FileOperationPhase.TASK_VALIDATION,s.incrementCounter("delete_files_phase",1,{phase:b})
|
|
3473
|
+
const $=D.length>0?D[0].normalized:"document_operations",A=await l.validateTaskId(P,$,u,m,s,I.metricsPrefix),F=A?.requestId,N=await l.validateWorkItemStates(P,$,u,C,r,m,s,I.metricsPrefix),L=await l.autoPromoteTaskStatus(P,A.status,F,N.request?.status,$,u,C,m,s,I.metricsPrefix)
|
|
3474
3474
|
L.taskPromoted&&m.info(`Auto-promoted task ${P} (${A.title||"Untitled"}) to in_progress for mixed operations`,{taskId:P,taskTitle:A.title,previousStatus:A.status,newStatus:L.newTaskStatus,totalOperations:j.length,fileOperations:R.length,documentOperations:x.length}),L.requestPromoted&&m.info(`Auto-promoted request ${F} to in_progress for file operations`,{requestId:F,previousStatus:N.request?.status,newStatus:L.newRequestStatus,triggeringTaskId:P})
|
|
3475
3475
|
const z=await l.ensureCorrectWorkspaceContext({taskPromoted:L.taskPromoted,requestId:F,context:r,operation:"delete-files",logger:m,metrics:s,metricsPrefix:I.metricsPrefix})
|
|
3476
3476
|
if(!z.success){if(z.isLockConflict)return{content:[{type:"text",text:"\u274c "+z.error}],isError:!0}
|
|
@@ -3478,12 +3478,12 @@ throw Error(z.error)}let H={hadUserMods:!1,userModsCommitHash:void 0}
|
|
|
3478
3478
|
if(r.git)try{m.debug("[DELETE-FILES] Checking for user changes before mixed delete operations")
|
|
3479
3479
|
const e=await(0,h.commitUserChangesBeforeToolOperation)(r.git,"delete-files",{requestId:F,taskId:P,workspaceManager:r.workspaceManager},m,s)
|
|
3480
3480
|
e.userChangesCommitted&&(m.debug("[DELETE-FILES] User changes committed before mixed delete operations",{commitHash:e.commitHash?.substring(0,8),filesCommitted:e.filesCommitted}),m.info("User changes committed before mixed delete-files operation",{taskId:P,totalOperations:j.length,fileOperations:R.length,documentOperations:x.length,userCommitHash:e.commitHash?.substring(0,8),userFilesCommitted:e.filesCommitted}),H={hadUserMods:!0,userModsCommitHash:e.commitHash})}catch(e){m.debug("[DELETE-FILES] Pre-tool commit failed, continuing with mixed delete operations",{error:e instanceof Error?e.message:e+""}),m.warn("Pre-tool user changes commit failed, continuing with mixed delete operation",{taskId:P,totalOperations:j.length,fileOperations:R.length,documentOperations:x.length,error:e instanceof Error?e.message:e+""})}m.debug("[DELETE-FILES] Proceeding with mixed delete operations",{totalOperations:j.length,fileDeletes:R.length,documentDeletes:x.length}),b=l.FileOperationPhase.RECORD_CREATION,s.incrementCounter("delete_files_phase",1,{phase:b})
|
|
3481
|
-
const{toolRecordId:B,localToolRecordId:U}=await l.createFileOperationRecords(P,F,r.projectId,I.recordType
|
|
3481
|
+
const{toolRecordId:B,localToolRecordId:U}=await l.createFileOperationRecords(P,F,r.projectId,I.recordType,$,{totalOperations:j.length,fileOperations:R.length,documentOperations:x.length,filePaths:D.map((e=>e.normalized)),documentIds:x.map((e=>e.target)),userComment:S,hadUserMods:H.hadUserMods,userModsCommitHash:H.userModsCommitHash},u,v,m,s,I.metricsPrefix,i)
|
|
3482
3482
|
w=B,k=B,b=I.fileOperationPhase,s.incrementCounter("delete_files_phase",1,{phase:b})
|
|
3483
3483
|
const G=[]
|
|
3484
3484
|
let W=0
|
|
3485
3485
|
x.length>0&&n.setProjectId(r.projectId)
|
|
3486
|
-
for(let e=0;e
|
|
3486
|
+
for(let e=0;e<D.length;e++){const t=D[e],r={type:"file",path:t.normalized,success:!1,replacements:[],successfulReplacements:0,failedReplacements:0}
|
|
3487
3487
|
try{try{await a.default.access(t.full)}catch(e){throw Error("File not found: "+t.normalized)}if((await a.default.stat(t.full)).isDirectory())throw Error("Cannot 'delete' a directory: "+t.normalized)
|
|
3488
3488
|
await a.default.unlink(t.full),r.success=!0,W++,m.info("Successfully deleted file",{path:t.normalized})}catch(e){r.error=(0,f.getErrorMessage)(e),m.warn("Failed to delete file "+t.normalized,{error:r.error})}G.push(r)}const V=x.length>0?n.getDocumentClient():null
|
|
3489
3489
|
for(const e of x){const t=e.target,r={type:"document",documentId:t,success:!1,replacements:[],successfulReplacements:0,failedReplacements:0}
|
|
@@ -3497,9 +3497,9 @@ let K=null
|
|
|
3497
3497
|
if(W>0){b=l.FileOperationPhase.GIT_COMMIT,s.incrementCounter("delete_files_phase",1,{phase:b})
|
|
3498
3498
|
const e=G.filter((e=>e.success)),t=e.filter((e=>"file"===e.type)).length,n=e.filter((e=>"document"===e.type)).length
|
|
3499
3499
|
let o
|
|
3500
|
-
o=t>0&&n>0?`Delete ${t} files and ${n} documents - ${S}`:t>0?1===t?"Delete file - "+S:`Delete ${t} files - ${S}`:1===n?"Delete document - "+S:`Delete ${n} documents - ${S}`,K=await l.commitToGit(P
|
|
3500
|
+
o=t>0&&n>0?`Delete ${t} files and ${n} documents - ${S}`:t>0?1===t?"Delete file - "+S:`Delete ${t} files - ${S}`:1===n?"Delete document - "+S:`Delete ${n} documents - ${S}`,K=await l.commitToGit(P,$,B,U,o,r,m,s,I.metricsPrefix)}b=l.FileOperationPhase.RECORD_UPDATE_SUCCESS,s.incrementCounter("delete_files_phase",1,{phase:b})
|
|
3501
3501
|
const Y=G.filter((e=>e.success)),Q=G.filter((e=>!e.success))
|
|
3502
|
-
await l.updateFileOperationRecords(P,w,k
|
|
3502
|
+
await l.updateFileOperationRecords(P,w,k,$,I.recordType,W===M?`Successfully deleted all ${M} operations`:`Deleted ${W}/${M} operations successfully`,{status:W===M?"completed":"partial_success",commitHash:K?.commitHash,previousCommitHash:K?.previousCommitHash,totalOperations:M,fileOperations:R.length,documentOperations:x.length,successCount:W,failureCount:M-W,successfulOperations:Y.map((e=>({type:e.type,path:e.path,documentId:e.documentId,filename:e.filename}))),failedOperations:Q.map((e=>({type:e.type,path:e.path,documentId:e.documentId,filename:e.filename,error:e.error}))),userComment:S,hadUserMods:H.hadUserMods,userModsCommitHash:H.userModsCommitHash},W===M?`Successfully deleted all ${M} operations`:`Deleted ${W}/${M} operations successfully`,u,v,m,s,I.metricsPrefix)
|
|
3503
3503
|
const Z=r.getCurrentBranchContext?await r.getCurrentBranchContext():{branch:null,requestId:null,isMain:!0}
|
|
3504
3504
|
let X=""
|
|
3505
3505
|
if(W===M){const e=Y.filter((e=>"file"===e.type)).length,t=Y.filter((e=>"document"===e.type)).length
|
|
@@ -3741,20 +3741,20 @@ for(const e of j)x.push({type:"document",documentId:e.documentId,insertions:e.in
|
|
|
3741
3741
|
if(x.length>0&&n.apiClient){const e=x.map((e=>e.documentId))
|
|
3742
3742
|
try{await(0,p.ensureDocumentsNotLocked)(e,n.apiClient,w,m,"insert-lines-documents")}catch(e){if(e instanceof u.ValidationError)return{content:[{type:"text",text:e.message}],isError:!0}
|
|
3743
3743
|
throw e}}v=d.FileOperationPhase.TASK_VALIDATION,m.incrementCounter("insert_lines_phase",1,{phase:v})
|
|
3744
|
-
const M=R.length>0?R[0].path:"document-operation",O=await d.validateTaskId(T,M,o,w,m,C.metricsPrefix)
|
|
3745
|
-
let
|
|
3746
|
-
R.length>0
|
|
3744
|
+
const M=R.length>0?R[0].path:"document-operation",O=await d.validateTaskId(T,M,o,w,m,C.metricsPrefix),D=O?.requestId
|
|
3745
|
+
let $=null
|
|
3746
|
+
R.length>0&&D&&($=await d.validateWorkItemStates(T,R[0].path,o,i,n,w,m,C.metricsPrefix))
|
|
3747
3747
|
let A={taskPromoted:!1,requestPromoted:!1}
|
|
3748
|
-
R.length>0&&$&&
|
|
3749
|
-
const F=await d.ensureCorrectWorkspaceContext({taskPromoted:A.taskPromoted,requestId
|
|
3748
|
+
R.length>0&&D&&$&&(A=await d.autoPromoteTaskStatus(T,O.status,D,$.request?.status,R[0].path,o,i,w,m,C.metricsPrefix),A.taskPromoted&&w.info("Auto-promoted task to in_progress for insert-lines operation",{taskId:T,requestId:D,previousStatus:O.status,newStatus:A.newTaskStatus,triggeringOperation:"insert-lines"}))
|
|
3749
|
+
const F=await d.ensureCorrectWorkspaceContext({taskPromoted:A.taskPromoted,requestId:D,context:n,operation:"insert-lines",logger:w,metrics:m,metricsPrefix:C.metricsPrefix})
|
|
3750
3750
|
if(!F.success){if(F.isLockConflict)return{content:[{type:"text",text:"\u274c "+F.error}],isError:!0}
|
|
3751
3751
|
throw Error(F.error)}if(R.length>0){w.debug("Re-validating file paths with correct workspace context",{operationCount:R.length,workspaceBasePath:n.workspaceManager?.getCurrentContext(n.currentSessionId).basePath})
|
|
3752
3752
|
for(let e=0;e<R.length;e++){const t=R[e],r=P[e],{normalizedPath:o,fullPath:s}=d.validateAndNormalizePath(r.path,n)
|
|
3753
|
-
R[e]={...t,path:o,fullPath:s}}}if(x.length>0
|
|
3753
|
+
R[e]={...t,path:o,fullPath:s}}}if(x.length>0&&D)try{await(0,h.validateRequestStatusForDocumentOperation)(D,i,w,m,"insert-lines-document")}catch(e){if(e instanceof u.ValidationError)return{content:[{type:"text",text:e.message}],isError:!0}
|
|
3754
3754
|
throw e}v=d.FileOperationPhase.RECORD_CREATION,m.incrementCounter("insert_lines_phase",1,{phase:v})
|
|
3755
|
-
const N=[...R.map((e=>({type:"file",path:e.path,insertions:e.insertions}))),...x.map((e=>({type:"document",documentId:e.documentId,insertions:e.insertions})))],{toolRecordId:L}=await d.createFileOperationRecords(T
|
|
3755
|
+
const N=[...R.map((e=>({type:"file",path:e.path,insertions:e.insertions}))),...x.map((e=>({type:"document",documentId:e.documentId,insertions:e.insertions})))],{toolRecordId:L}=await d.createFileOperationRecords(T,D,n.projectId,C.recordType,M,{operationCount:E.length,fileOperations:R.length,documentOperations:x.length,operations:N,userComment:q},o,s,w,m,C.metricsPrefix,y)
|
|
3756
3756
|
if(b=L,I=L,v=C.fileOperationPhase,m.incrementCounter("insert_lines_phase",1,{phase:v}),R.length>0&&n.git)try{w.debug("[INSERT-LINES] Checking for user changes before insert operations")
|
|
3757
|
-
const e=await(0,g.commitUserChangesBeforeToolOperation)(n.git,"insert-lines",{requestId
|
|
3757
|
+
const e=await(0,g.commitUserChangesBeforeToolOperation)(n.git,"insert-lines",{requestId:D,taskId:T,workspaceManager:n.workspaceManager},w,m)
|
|
3758
3758
|
e.userChangesCommitted&&(w.debug("[INSERT-LINES] User changes committed before insert operations",{commitHash:e.commitHash?.substring(0,8),filesCommitted:e.filesCommitted}),w.info("User changes committed before insert-lines operation",{taskId:T,fileOperationsCount:R.length,userCommitHash:e.commitHash?.substring(0,8),userFilesCommitted:e.filesCommitted}))}catch(e){w.debug("[INSERT-LINES] Pre-tool commit failed, continuing with insertions",{error:e instanceof Error?e.message:e+""}),w.warn("Pre-tool user changes commit failed, continuing with insert operation",{taskId:T,fileOperationsCount:R.length,error:e instanceof Error?e.message:e+""})}w.debug("[INSERT-LINES] Proceeding with file operations",{fileCount:R.length})
|
|
3759
3759
|
const z=[]
|
|
3760
3760
|
let H=0,B=0,U=0
|
|
@@ -3894,20 +3894,20 @@ for(const e of R)M.push({type:"document",documentId:e.documentId,replacements:e.
|
|
|
3894
3894
|
if(M.length>0&&n.apiClient){const e=M.map((e=>e.documentId))
|
|
3895
3895
|
try{await(0,p.ensureDocumentsNotLocked)(e,n.apiClient,k,m,"replace-lines-documents")}catch(e){if(e instanceof u.ValidationError)return{content:[{type:"text",text:e.message}],isError:!0}
|
|
3896
3896
|
throw e}}C=d.FileOperationPhase.TASK_VALIDATION,m.incrementCounter("replace_lines_phase",1,{phase:C})
|
|
3897
|
-
const O=x.length>0?x[0].path:"document-operation"
|
|
3897
|
+
const O=x.length>0?x[0].path:"document-operation",D=await d.validateTaskId(P,O,o,k,m,_.metricsPrefix),$=D?.requestId
|
|
3898
3898
|
let A=null
|
|
3899
|
-
x.length>0
|
|
3899
|
+
x.length>0&&$&&(A=await d.validateWorkItemStates(P,x[0].path,o,i,n,k,m,_.metricsPrefix))
|
|
3900
3900
|
let F={taskPromoted:!1,requestPromoted:!1}
|
|
3901
|
-
x.length>0
|
|
3902
|
-
const N=await d.ensureCorrectWorkspaceContext({taskPromoted:F.taskPromoted,requestId
|
|
3901
|
+
x.length>0&&$&&A&&(F=await d.autoPromoteTaskStatus(P,D.status,$,A.request?.status,x[0].path,o,i,k,m,_.metricsPrefix),F.taskPromoted&&k.info("Auto-promoted task to in_progress for replace-lines operation",{taskId:P,requestId:$,previousStatus:D.status,newStatus:F.newTaskStatus,triggeringOperation:"replace-lines"}))
|
|
3902
|
+
const N=await d.ensureCorrectWorkspaceContext({taskPromoted:F.taskPromoted,requestId:$,context:n,operation:"replace-lines",logger:k,metrics:m,metricsPrefix:_.metricsPrefix})
|
|
3903
3903
|
if(!N.success){if(N.isLockConflict)return{content:[{type:"text",text:"\u274c "+N.error}],isError:!0}
|
|
3904
3904
|
throw Error(N.error)}if(x.length>0){k.debug("Re-validating file paths with correct workspace context",{operationCount:x.length,workspaceBasePath:n.workspaceManager?.getCurrentContext(n.currentSessionId).basePath})
|
|
3905
3905
|
for(let e=0;e<x.length;e++){const t=x[e],r=j[e],{normalizedPath:o,fullPath:s}=d.validateAndNormalizePath(r.path,n)
|
|
3906
|
-
x[e]={...t,path:o,fullPath:s}}}if(M.length>0
|
|
3906
|
+
x[e]={...t,path:o,fullPath:s}}}if(M.length>0&&$)try{await(0,h.validateRequestStatusForDocumentOperation)($,i,k,m,"replace-lines-document")}catch(e){if(e instanceof u.ValidationError)return{content:[{type:"text",text:e.message}],isError:!0}
|
|
3907
3907
|
throw e}C=d.FileOperationPhase.RECORD_CREATION,m.incrementCounter("replace_lines_phase",1,{phase:C})
|
|
3908
|
-
const L=[...x.map((e=>({type:"file",path:e.path,replacements:e.replacements}))),...M.map((e=>({type:"document",documentId:e.documentId,replacements:e.replacements})))],{toolRecordId:z}=await d.createFileOperationRecords(P
|
|
3908
|
+
const L=[...x.map((e=>({type:"file",path:e.path,replacements:e.replacements}))),...M.map((e=>({type:"document",documentId:e.documentId,replacements:e.replacements})))],{toolRecordId:z}=await d.createFileOperationRecords(P,$,n.projectId,_.recordType,O,{operationCount:q.length,fileOperations:x.length,documentOperations:M.length,operations:L,userComment:S},o,s,k,m,_.metricsPrefix,w)
|
|
3909
3909
|
if(I=z,v=z,C=_.fileOperationPhase,m.incrementCounter("replace_lines_phase",1,{phase:C}),x.length>0&&n.git)try{k.debug("[REPLACE-LINES] Checking for user changes before replace operations")
|
|
3910
|
-
const e=await(0,g.commitUserChangesBeforeToolOperation)(n.git,"replace-lines",{requestId
|
|
3910
|
+
const e=await(0,g.commitUserChangesBeforeToolOperation)(n.git,"replace-lines",{requestId:$,taskId:P,workspaceManager:n.workspaceManager},k,m)
|
|
3911
3911
|
e.userChangesCommitted&&(k.debug("[REPLACE-LINES] User changes committed before replace operations",{commitHash:e.commitHash?.substring(0,8),filesCommitted:e.filesCommitted}),k.info("User changes committed before replace-lines operation",{taskId:P,fileOperationsCount:x.length,userCommitHash:e.commitHash?.substring(0,8),userFilesCommitted:e.filesCommitted}))}catch(e){k.debug("[REPLACE-LINES] Pre-tool commit failed, continuing with replacements",{error:e instanceof Error?e.message:e+""}),k.warn("Pre-tool user changes commit failed, continuing with replace operation",{taskId:P,fileOperationsCount:x.length,error:e instanceof Error?e.message:e+""})}k.debug("[REPLACE-LINES] Proceeding with file operations",{fileCount:x.length})
|
|
3912
3912
|
const H=[]
|
|
3913
3913
|
let B=0,U=0,G=0,W=0
|
|
@@ -4066,7 +4066,7 @@ n&&n.push({filePath:r,recordId:e.id,type:"replace-in-files",timestamp:e.createdA
|
|
|
4066
4066
|
C.has(t)||C.set(t,[])
|
|
4067
4067
|
const r=C.get(t)
|
|
4068
4068
|
r&&r.push({filePath:t,recordId:e.id,type:e.type,timestamp:e.createdAt,commitHash:e.metadata.commitHash,status:e.metadata.status||"",record:e})})),s.info(`Grouped records by file path. Found ${C.size} unique files.`)
|
|
4069
|
-
for(const[
|
|
4069
|
+
for(const[D,$]of C.entries())$.sort(((e,t)=>new Date(e.timestamp).getTime()-new Date(t.timestamp).getTime())),s.info(`File ${D} has ${$.length} records.`),s.info("Records with commit hashes: "+$.filter((e=>e.commitHash)).length)
|
|
4070
4070
|
const _=new Map
|
|
4071
4071
|
for(const[A,F]of C.entries()){s.info(`Processing file: ${A} (${F.length} records)`)
|
|
4072
4072
|
const N=new Map
|
|
@@ -4118,8 +4118,8 @@ for(const Pe of I.allMoves)E+=`- **${Pe.source}** \u2192 **${Pe.destination}**\n
|
|
|
4118
4118
|
for(const[je,Re]of _.entries()){const{normalizedPath:xe,fullPath:Me}=d.validateAndNormalizePath(je,t)
|
|
4119
4119
|
let Oe=!1
|
|
4120
4120
|
try{await a.access(Me),Oe=!0}catch{}E+=`### ${je} ${Oe?"":"(Deleted)"}\n\n`
|
|
4121
|
-
const
|
|
4122
|
-
E+=`**First Change**: ${
|
|
4121
|
+
const De=new Date(Re.firstChange.timestamp).toLocaleString(),$e=new Date(Re.lastChange.timestamp).toLocaleString()
|
|
4122
|
+
E+=`**First Change**: ${De}\n`,E+=`**Last Change**: ${$e}\n`,"pre-task"===Re.firstChange.status&&Re.firstChange.commitHash?E+=`**Pre-Task Commit**: ${Re.firstChange.commitHash.substring(0,8)}\n`:Re.firstChange.commitHash&&(E+=`**File Created During Task**: ${Re.firstChange.commitHash.substring(0,8)}\n`),Re.lastChange.commitHash&&(E+=`**Final Commit**: ${Re.lastChange.commitHash.substring(0,8)}\n`)
|
|
4123
4123
|
const Ae=I.sourceToMove.get(je),Fe=I.destToMove.get(je)
|
|
4124
4124
|
Ae?E+=`**\u2139\ufe0f Move Operation**: This file was moved TO **${Ae.destination}**\n`:Fe&&(E+=`**\u2139\ufe0f Move Operation**: This file was moved FROM **${Fe.source}**\n`),p&&!T?Re.hasDiff?(E+="\n**Changes**:\n",E+="```diff\n",E+=Re.diffText,E+="\n```\n\n"):E+=`\n**Note**: ${Re.diffText}\n\n`:T&&Re.hasDiff?(E+=`\n**Note**: File has changes (${Re.diffText?Re.diffText.split("\n").length:0} lines). `,E+=`Compare ${Re.firstChange.commitHash?Re.firstChange.commitHash.substring(0,8):"unknown"}..${Re.lastChange.commitHash?Re.lastChange.commitHash.substring(0,8):"unknown"} to see changes.\n\n`):Re.hasDiff?E+="\n**Note**: File has changes. Use showDiff=true to see the diff.\n\n":E+=`\n**Note**: ${Re.diffText}\n\n`,E+="---\n\n"}return h({success:!0,fileCount:C.size}),{content:[{type:"text",text:E}]}}catch(Ne){return s.error("Error in task file history tool",{error:Ne instanceof Error?Ne.stack:Ne+""}),h({success:!1,error:Ne instanceof Error?Ne.name:"unknown"}),{content:[{type:"text",text:"Error: "+(0,u.getErrorMessage)(Ne)}],isError:!0}}}
|
|
4125
4125
|
const i=t(9860),a=s(t(1943)),c=t(9671),l=t(2960),d=s(t(5967)),u=t(8824)},6928(module){"use strict"
|
|
@@ -4937,9 +4937,9 @@ w=x,k=x,b=I.fileOperationPhase,p.incrementCounter("create_directory_phase",1,{ph
|
|
|
4937
4937
|
let O=R
|
|
4938
4938
|
if(!R){await a.default.mkdir(E,{recursive:!0}),m.info("Successfully created directory "+_)
|
|
4939
4939
|
try{const e=c.default.join(E,".gitkeep")
|
|
4940
|
-
await a.default.writeFile(e,"# This file makes the directory trackable by Git\n"),O=!0,m.info("Created .gitkeep file for Git tracking")}catch(e){m.warn("Failed to create .gitkeep file",{error:e instanceof Error?e.message:e+""}),O=!1}}const
|
|
4941
|
-
p.recordValue("create_directory_time"
|
|
4942
|
-
const
|
|
4940
|
+
await a.default.writeFile(e,"# This file makes the directory trackable by Git\n"),O=!0,m.info("Created .gitkeep file for Git tracking")}catch(e){m.warn("Failed to create .gitkeep file",{error:e instanceof Error?e.message:e+""}),O=!1}}const D=Date.now()-y
|
|
4941
|
+
p.recordValue("create_directory_time",D),p.incrementCounter("create_directory_success",1),b=d.FileOperationPhase.GIT_COMMIT,p.incrementCounter("create_directory_phase",1,{phase:b})
|
|
4942
|
+
const $=`Create directory: ${_} - ${g||"Create directory"}`,A=!R&&O?_+"/.gitkeep":_,F=await d.commitToGit(C,A,x,M,$,r,m,p,I.metricsPrefix)
|
|
4943
4943
|
b=d.FileOperationPhase.RECORD_UPDATE_SUCCESS,p.incrementCounter("create_directory_phase",1,{phase:b}),await d.updateFileOperationRecords(C,w,k,_,I.recordType,`Successfully ${R?"verified":"created"} directory: ${_}`,{status:"completed",commitHash:F.commitHash,previousCommitHash:F.previousCommitHash,directoryExists:R,isDirectory:!0,userComment:g},`Successfully ${R?"verified":"created"} directory: ${_}`,n,o,m,p,I.metricsPrefix)
|
|
4944
4944
|
const N=r.getCurrentBranchContext?await r.getCurrentBranchContext():{branch:null,requestId:null,isMain:!0}
|
|
4945
4945
|
return{content:[{type:"text",text:R?"Directory already exists":`Successfully created directory${F.commitHash?"\nCommit: "+F.commitHash.substring(0,8):""}${N.requestId&&!N.permanentBranch?"\nBranch: "+N.requestId:""}${j.lockAcquired&&j.lockedRequestId&&!N.permanentBranch?"\n\u{1f512} **Locked request:** "+j.lockedRequestId:""}`}]}}catch(t){if(e.taskId&&o)try{const n=t instanceof u.NotFoundError||t instanceof u.ValidationError||t instanceof h.ZodError
|
|
@@ -5280,7 +5280,7 @@ if(this.logger.debug("Polling response",{data:n}),n.authenticated&&n.token){this
|
|
|
5280
5280
|
const r=this.parseTokenResponse(n)
|
|
5281
5281
|
if(!r)throw Error("Invalid token response from server")
|
|
5282
5282
|
this.pollingStatus=s.AUTHENTICATED,this.tokenResult=r,this.stopPolling(),t&&t(r)}else this.logger.debug("Not authenticated yet, continuing to poll",{tempCode:e.substring(0,4)+"***"})}catch(e){const t=(0,o.getErrorMessage)(e)
|
|
5283
|
-
throw Error(
|
|
5283
|
+
throw Error(`Error during polling: ${t}${/fetch failed|ECONNREFUSED|ENOTFOUND|ETIMEDOUT|network/i.test(t)?" (remote may be unreachable \u2014 check your connection and try again)":""}`)}}catch(t){const r=(0,o.getErrorMessage)(t)
|
|
5284
5284
|
this.logger.error("Error polling for authentication",{tempCode:e.substring(0,4)+"***",error:r}),this.pollingStatus=s.ERROR,this.pollingError=r,this.stopPolling(),n&&n(r)}}
|
|
5285
5285
|
return i(),this.pollingIntervalId=setInterval(i,this.pollingIntervalMs),()=>this.stopPolling()}stopPolling(){this.pollingIntervalId&&(clearInterval(this.pollingIntervalId),this.pollingIntervalId=null,this.logger.debug("Stopped polling for authentication",{status:this.pollingStatus}))}getPollingStatus(){const e={status:this.pollingStatus}
|
|
5286
5286
|
return this.pollingStatus===s.AUTHENTICATED&&this.tokenResult?e.tokenInfo=this.tokenResult:this.pollingStatus===s.ERROR&&this.pollingError&&(e.error=this.pollingError),this.pollingStartTime>0&&(e.elapsedTimeMs=Date.now()-this.pollingStartTime),e}resetPollingState(){this.stopPolling(),this.pollingStatus=s.NOT_STARTED,this.pollingStartTime=0,this.tokenResult=null,this.pollingError=null}async startGoogleOAuthFlow(){this.logger.info("Starting Google OAuth authentication flow")
|
|
@@ -5520,18 +5520,18 @@ if(R.length>0&&r.apiClient)try{await(0,m.ensureDocumentsNotLocked)(R,r.apiClient
|
|
|
5520
5520
|
throw e}_=u.FileOperationPhase.TASK_VALIDATION,c.incrementCounter("replace_in_files_phase",1,{phase:_})
|
|
5521
5521
|
const x=T[0],M=x.documentId?"document:"+x.documentId:x.path
|
|
5522
5522
|
let O=Date.now()
|
|
5523
|
-
const
|
|
5523
|
+
const D=await u.validateTaskId(S,M,o,I,c,"replace_in_files")
|
|
5524
5524
|
Date.now()
|
|
5525
|
-
const D
|
|
5525
|
+
const $=D?.requestId,A=T.some((e=>e.path))
|
|
5526
5526
|
let F=!1
|
|
5527
|
-
if(A
|
|
5527
|
+
if(A&&$){O=Date.now()
|
|
5528
5528
|
const e=await u.validateWorkItemStates(S,M,o,i,r,I,c,"replace_in_files")
|
|
5529
5529
|
Date.now(),O=Date.now()
|
|
5530
|
-
const t=await u.autoPromoteTaskStatus(S
|
|
5531
|
-
t.taskPromoted&&I.info("Auto-promoted task to in_progress",{taskId:S,requestId:D
|
|
5532
|
-
const n=await u.ensureCorrectWorkspaceContext({taskPromoted:t.taskPromoted,requestId
|
|
5530
|
+
const t=await u.autoPromoteTaskStatus(S,D.status,$,e.request?.status,M,o,i,I,c,"replace_in_files")
|
|
5531
|
+
t.taskPromoted&&I.info("Auto-promoted task to in_progress",{taskId:S,requestId:$,previousStatus:D.status,newStatus:t.newTaskStatus}),Date.now(),O=Date.now()
|
|
5532
|
+
const n=await u.ensureCorrectWorkspaceContext({taskPromoted:t.taskPromoted,requestId:$,context:r,operation:"replace_in_files",logger:I,metrics:c,metricsPrefix:"replace_in_files"})
|
|
5533
5533
|
if(!n.success){if(n.isLockConflict)return{content:[{type:"text",text:"\u274c "+n.error}],isError:!0}
|
|
5534
|
-
throw Error(n.error)}Date.now(),F=!0}if(R.length>0
|
|
5534
|
+
throw Error(n.error)}Date.now(),F=!0}if(R.length>0&&$)try{await(0,p.validateRequestStatusForDocumentOperation)($,i,I,c,"replace_in_files-documents")}catch(e){if(e instanceof g.ValidationError)return{content:[{type:"text",text:e.message}],isError:!0}
|
|
5535
5535
|
throw e}O=Date.now()
|
|
5536
5536
|
const N=new Map
|
|
5537
5537
|
if(I.info("\u{1f50d} Starting external edit detection",{hasFileOperations:A,hasGit:!!r.git,operationCount:T.length}),A&&r.git)for(const e of T)if(e.path&&!e.documentId)try{const t=u.validateAndNormalizePath(e.path,r),n=await l.default.readFile(t.fullPath,"utf8"),o=void 0!==e.fuzzy_match?e.fuzzy_match:P,s=[]
|
|
@@ -5540,9 +5540,9 @@ s.push(...r)}if(s.length>0){const o=(0,y.calculateReplacementRegion)(n,s,t.fullP
|
|
|
5540
5540
|
I.info("\u{1f50d} Checking for external edits",{path:t.normalizedPath,affectedLines:o.lineRanges.map((e=>`${e.start}-${e.end}`)).join(", "),matchCount:s.length})
|
|
5541
5541
|
const i=await(0,w.detectExternalEdits)(r.git,o,I)
|
|
5542
5542
|
I.info("\u{1f50d} External edit detection result",{path:t.normalizedPath,hasExternalEdits:i.hasExternalEdits,conflictingLines:i.conflictingLines,hasMessage:!!i.message}),i.hasExternalEdits&&i.message?(N.set(e.path,{message:i.message,debugInfo:i.debugInfo}),I.warn("\u26a0\ufe0f External edits detected before auto-commit",{path:t.normalizedPath,conflictingLines:i.conflictingLines})):(i.debugInfo&&N.set(e.path,{message:"",debugInfo:i.debugInfo}),I.info("\u2705 No external edit conflicts detected",{path:t.normalizedPath}))}else I.info("\u2139\ufe0f No matches found for external edit detection",{path:t.normalizedPath}),N.set(e.path,{message:"",debugInfo:{detectionRan:!1,reason:"No matches found - patterns not found in file",affectedRegion:"none",uncommittedChanges:"not checked",overlapDetected:!1}})}catch(t){I.warn("Failed to check for external edits before auto-commit",{path:e.path,error:(0,k.getErrorMessage)(t)})}if(Date.now(),O=Date.now(),A&&r.git)try{I.debug("[REPLACE-IN-FILES] Checking for user changes before batch operation")
|
|
5543
|
-
const e=await(0,f.commitUserChangesBeforeToolOperation)(r.git,"replace_in_files",{requestId
|
|
5543
|
+
const e=await(0,f.commitUserChangesBeforeToolOperation)(r.git,"replace_in_files",{requestId:$,taskId:S,workspaceManager:r.workspaceManager},I,c)
|
|
5544
5544
|
e.userChangesCommitted&&(I.debug("[REPLACE-IN-FILES] User changes committed",{commitHash:e.commitHash?.substring(0,8),filesCommitted:e.filesCommitted}),I.info("User changes committed before batch operation",{taskId:S,userCommitHash:e.commitHash?.substring(0,8),userFilesCommitted:e.filesCommitted}))}catch(e){I.warn("Pre-tool user changes commit failed",{taskId:S,error:e instanceof Error?e.message:e+""})}Date.now(),O=Date.now(),_=u.FileOperationPhase.RECORD_CREATION,c.incrementCounter("replace_in_files_phase",1,{phase:_})
|
|
5545
|
-
const{toolRecordId:L}=await u.createFileOperationRecords(S
|
|
5545
|
+
const{toolRecordId:L}=await u.createFileOperationRecords(S,$,r.projectId,"replace-in-files",M,{operationCount:T.length,totalReplacements:T.reduce(((e,t)=>e+t.replacements.length),0),globalFuzzyMatch:P,userComment:j},o,s,I,c,"replace_in_files",b)
|
|
5546
5546
|
C=L,Date.now(),O=Date.now(),_=u.FileOperationPhase.STRING_REPLACEMENT,c.incrementCounter("replace_in_files_phase",1,{phase:_})
|
|
5547
5547
|
const z=[],H=[]
|
|
5548
5548
|
for(const e of T){const t=e.path?N.get(e.path):void 0,o=await n(e,P,r,0,0,t?.message,t?.debugInfo)
|
package/dist/mcp-direct.js
CHANGED
|
@@ -486,9 +486,9 @@ if(this.TOKEN_CACHE.hasValidToken&&e<this.TOKEN_CACHE.hasValidToken.expiresAt){c
|
|
|
486
486
|
return this.logger.debug("Using cached hasValidToken result",{ageSecs:Math.round((e-t.timestamp)/1e3),hasToken:t.value}),t.value}this.logger.debug("Checking if valid token exists (cache miss or expired)")
|
|
487
487
|
const t=null!==await this.getToken()
|
|
488
488
|
return this.TOKEN_CACHE.hasValidToken={value:t,timestamp:e,expiresAt:e+this.CACHE_TTL_MS,lastCheck:e,exists:t},t}getTokenDirectoryPath(){return this.tokenDirPath}getManualTokenFilePath(){return n.default.join(this.tokenDirPath,"manual-token.json")}logTokenLocationInstructions(){const e=this.getManualTokenFilePath()
|
|
489
|
-
console.log("========================================"),console.log("To use
|
|
489
|
+
console.log("========================================"),console.log("To use the alchemy CLI, you need to authenticate."),console.log("Token file location: "+e),console.log("You can either:"),console.log('\n1. Use the authenticate tool (recommended)\n2. Manually place a token file at the above location\n3. Set up automatic authentication flow\n\nFor manual token placement, create a JSON file with:\n{\n "token": "your_token_here",\n "userId": "your_user_id",\n "username": "your_username", \n "role": "user",\n "expiresAt": "2025-12-31T23:59:59.000Z"\n}\n'),console.log("For more information, see the authentication documentation."),console.log("========================================")}async startAuthenticationFlow(){this.pendingAuthCheck=!0
|
|
490
490
|
try{const{tempCode:e,authUrl:t}=await this.authFlow.startAuthFlow()
|
|
491
|
-
return this.tempAuthCode=e,this.logger.info("Started external authentication flow",{tempCode:e,authUrl:t}),this.authFlow.startPolling(e,(async t=>{this.logger.info("Authentication flow completed",{tempCode:e.substring(0,4)+"***",username:t.username}),await this.storeToken(t),this.pendingAuthCheck=!1,this.tempAuthCode=null,this.invalidateCache(),console.log("Authentication successful!"),console.log(`Welcome, ${t.username}!`),console.log("You can now use
|
|
491
|
+
return this.tempAuthCode=e,this.logger.info("Started external authentication flow",{tempCode:e,authUrl:t}),this.authFlow.startPolling(e,(async t=>{this.logger.info("Authentication flow completed",{tempCode:e.substring(0,4)+"***",username:t.username}),await this.storeToken(t),this.pendingAuthCheck=!1,this.tempAuthCode=null,this.invalidateCache(),console.log("Authentication successful!"),console.log(`Welcome, ${t.username}!`),console.log("You can now use the alchemy CLI."),console.log("========================================")}),(()=>{this.logger.info("Authentication flow timed out",{tempCode:e.substring(0,4)+"***"}),this.pendingAuthCheck=!1,this.tempAuthCode=null,console.log("Authentication flow timed out."),console.log("Please try again or manually place a token file."),console.log("Token file location:"),console.log(""+this.getManualTokenFilePath()),console.log("========================================")}),(t=>{this.logger.error("Authentication flow error",{tempCode:e.substring(0,4)+"***",error:t}),this.pendingAuthCheck=!1,this.tempAuthCode=null,console.log("Authentication flow error."),console.log("Error: "+t),console.log("Please try again or manually place a token file."),console.log(""+this.getManualTokenFilePath()),console.log("========================================")})),{tempCode:e,authUrl:t}}catch(e){throw this.logger.error("Error starting authentication flow",{error:(0,c.getErrorMessage)(e)}),this.pendingAuthCheck=!1,this.tempAuthCode=null,e}}hasPendingAuth(){return this.pendingAuthCheck||!!this.tempAuthCode}getAuthStatus(){return this.hasPendingAuth()?{hasToken:!1,isPendingAuth:!0,tempCode:this.tempAuthCode,authUrl:this.authFlow.getAuthUrl(this.tempAuthCode)}:{hasToken:!1,isPendingAuth:!1}}async checkAuthStatus(e){if(!e)return null
|
|
492
492
|
try{const t=this.authFlow.getPollingStatus()
|
|
493
493
|
if(t.status===a.PollingStatus.AUTHENTICATED&&t.tokenInfo)return this.logger.info("Authentication polling has token available",{tempCode:e.substring(0,4)+"***",username:t.tokenInfo.username}),t.tokenInfo
|
|
494
494
|
if(t.status===a.PollingStatus.ERROR||t.status===a.PollingStatus.TIMEOUT)return this.pendingAuthCheck=!1,this.tempAuthCode=null,null
|
|
@@ -4976,7 +4976,7 @@ if(this.logger.debug("Polling response",{data:n}),n.authenticated&&n.token){this
|
|
|
4976
4976
|
const r=this.parseTokenResponse(n)
|
|
4977
4977
|
if(!r)throw Error("Invalid token response from server")
|
|
4978
4978
|
this.pollingStatus=s.AUTHENTICATED,this.tokenResult=r,this.stopPolling(),t&&t(r)}else this.logger.debug("Not authenticated yet, continuing to poll",{tempCode:e.substring(0,4)+"***"})}catch(e){const t=(0,o.getErrorMessage)(e)
|
|
4979
|
-
throw Error(
|
|
4979
|
+
throw Error(`Error during polling: ${t}${/fetch failed|ECONNREFUSED|ENOTFOUND|ETIMEDOUT|network/i.test(t)?" (remote may be unreachable \u2014 check your connection and try again)":""}`)}}catch(t){const r=(0,o.getErrorMessage)(t)
|
|
4980
4980
|
this.logger.error("Error polling for authentication",{tempCode:e.substring(0,4)+"***",error:r}),this.pollingStatus=s.ERROR,this.pollingError=r,this.stopPolling(),n&&n(r)}}
|
|
4981
4981
|
return i(),this.pollingIntervalId=setInterval(i,this.pollingIntervalMs),()=>this.stopPolling()}stopPolling(){this.pollingIntervalId&&(clearInterval(this.pollingIntervalId),this.pollingIntervalId=null,this.logger.debug("Stopped polling for authentication",{status:this.pollingStatus}))}getPollingStatus(){const e={status:this.pollingStatus}
|
|
4982
4982
|
return this.pollingStatus===s.AUTHENTICATED&&this.tokenResult?e.tokenInfo=this.tokenResult:this.pollingStatus===s.ERROR&&this.pollingError&&(e.error=this.pollingError),this.pollingStartTime>0&&(e.elapsedTimeMs=Date.now()-this.pollingStartTime),e}resetPollingState(){this.stopPolling(),this.pollingStatus=s.NOT_STARTED,this.pollingStartTime=0,this.tokenResult=null,this.pollingError=null}async startGoogleOAuthFlow(){this.logger.info("Starting Google OAuth authentication flow")
|