1- import {
2- existsSync ,
3- mkdirSync ,
4- readFileSync ,
5- unlinkSync ,
6- writeFileSync ,
7- } from 'fs'
8- import os from 'os'
91import { spawn } from 'child_process'
102import {
3+ ClientAction ,
114 FileChanges ,
125 FileChangeSchema ,
136 InitResponseSchema ,
@@ -17,8 +10,15 @@ import {
1710 ServerAction ,
1811 UsageReponseSchema ,
1912 UsageResponse ,
20- ClientAction ,
2113} from 'common/actions'
14+ import {
15+ existsSync ,
16+ mkdirSync ,
17+ readFileSync ,
18+ unlinkSync ,
19+ writeFileSync ,
20+ } from 'fs'
21+ import os from 'os'
2222
2323import { ApiKeyType , READABLE_NAME } from 'common/api-keys/constants'
2424import {
@@ -43,6 +43,7 @@ import { User } from 'common/util/credentials'
4343import { ProjectFileContext } from 'common/util/file'
4444import { pluralize } from 'common/util/string'
4545import { APIRealtimeClient } from 'common/websockets/websocket-client'
46+ import path from 'path'
4647import {
4748 blue ,
4849 blueBright ,
@@ -54,8 +55,6 @@ import {
5455} from 'picocolors'
5556import { match , P } from 'ts-pattern'
5657import { z } from 'zod'
57- import gitUrlParse from 'git-url-parse'
58- import path from 'path'
5958
6059import packageJson from '../package.json'
6160import { getBackgroundProcessUpdates } from './background-process-manager'
@@ -82,10 +81,10 @@ import { identifyUser, trackEvent } from './utils/analytics'
8281import { getRepoMetrics , gitCommandIsAvailable } from './utils/git'
8382import { logger , loggerContext } from './utils/logger'
8483import { Spinner } from './utils/spinner'
84+ import { readNewTerminalOutput } from './utils/terminal'
8585import { toolRenderers } from './utils/tool-renderers'
8686import { createXMLStreamParser } from './utils/xml-stream-parser'
8787import { getScrapedContentBlocks , parseUrlsFromContent } from './web-scraper'
88- import { readNewTerminalOutput } from './utils/terminal'
8988
9089const LOW_BALANCE_THRESHOLD = 100
9190
@@ -164,6 +163,7 @@ export class Client {
164163 public pendingTopUpMessageAmount : number = 0
165164 public fileContext : ProjectFileContext | undefined
166165 public lastChanges : FileChanges = [ ]
166+ public filesChangedForHook : string [ ] = [ ]
167167 public agentState : AgentState | undefined
168168 public originalFileVersions : Record < string , string | null > = { }
169169 public creditsByPromptId : Record < string , number [ ] > = { }
@@ -842,7 +842,17 @@ export class Client {
842842 throw new Error ( 'Agent state not initialized' )
843843 }
844844
845+ setMessages ( [
846+ ...this . agentState . messageHistory ,
847+ {
848+ role : 'user' ,
849+ content : prompt ,
850+ } ,
851+ ] )
852+
845853 this . agentState . agentStepsRemaining = loadCodebuffConfig ( ) ?. maxAgentSteps
854+ this . lastChanges = [ ]
855+ this . filesChangedForHook = [ ]
846856
847857 const userInputId =
848858 `mc-input-` + Math . random ( ) . toString ( 36 ) . substring ( 2 , 15 )
@@ -1062,7 +1072,6 @@ export class Client {
10621072
10631073 this . agentState = a . agentState
10641074 const toolResults : ToolResult [ ] = [ ...a . toolResults ]
1065- const changedFiles : string [ ] = [ ]
10661075
10671076 for ( const toolCall of a . toolCalls ) {
10681077 try {
@@ -1071,12 +1080,16 @@ export class Client {
10711080 isComplete = true
10721081 continue
10731082 }
1074- if ( toolCall . name === 'write_file' ) {
1083+ if (
1084+ toolCall . name === 'write_file' ||
1085+ toolCall . name === 'str_replace' ||
1086+ toolCall . name === 'create_plan'
1087+ ) {
10751088 // Save lastChanges for `diff` command
10761089 this . lastChanges . push ( FileChangeSchema . parse ( toolCall . parameters ) )
10771090 this . hadFileChanges = true
10781091 // Track the changed file path
1079- changedFiles . push ( toolCall . parameters . path )
1092+ this . filesChangedForHook . push ( toolCall . parameters . path )
10801093 }
10811094 if (
10821095 toolCall . name === 'run_terminal_command' &&
@@ -1126,14 +1139,15 @@ export class Client {
11261139 this . fileContext = await getProjectFileContext ( getProjectRoot ( ) , { } )
11271140 }
11281141
1129- if ( changedFiles . length > 0 ) {
1142+ if ( this . filesChangedForHook . length > 0 && isComplete ) {
11301143 // Run file change hooks with the actual changed files
11311144 const { toolResults : hookToolResults , someHooksFailed } =
1132- await runFileChangeHooks ( changedFiles )
1145+ await runFileChangeHooks ( this . filesChangedForHook )
11331146 toolResults . push ( ...hookToolResults )
11341147 if ( someHooksFailed ) {
11351148 isComplete = false
11361149 }
1150+ this . filesChangedForHook = [ ]
11371151 }
11381152
11391153 if ( ! isComplete ) {
0 commit comments