11// src/agent/state.ts
22import { create } from "zustand" ;
33import type { Message } from "./types.js" ;
4+ import logger from "@/logger.js" ;
45import { streamAssistantResponse } from "./llm.js" ;
56import { runTool } from "./tools/index.js" ;
67import { type Config , HISTORY_PATH , loadConfig , saveConfig } from "@/config.js" ;
@@ -67,49 +68,62 @@ export const useStore = create<AppState & AppActions>((set, get) => ({
6768 branchName : "unknown" ,
6869 actions : {
6970 loadInitialConfig : async ( ) => {
71+ logger . info ( "Loading initial configuration." ) ;
7072 try {
7173 const config = await loadConfig ( ) ;
7274 set ( { config, status : "idle" } ) ;
75+ logger . info ( "Configuration loaded successfully." ) ;
7376 await get ( ) . actions . updateBranchName ( ) ;
7477 } catch ( error ) {
7578 const errorMessage =
7679 error instanceof Error ? error . message : "An unknown error occurred." ;
80+ logger . error ( `Failed to load configuration: ${ errorMessage } ` ) ;
7781 set ( { error : `Failed to load configuration: ${ errorMessage } ` , status : "error" } ) ;
7882 }
7983 } ,
8084 updateBranchName : async ( ) => {
85+ logger . info ( "Updating branch name." ) ;
8186 try {
8287 const git = simpleGit ( ) ;
8388 const branch = await git . revparse ( [ "--abbrev-ref" , "HEAD" ] ) ;
8489 set ( { branchName : branch } ) ;
90+ logger . info ( `Branch name updated to: ${ branch } ` ) ;
8591 } catch ( error ) {
92+ logger . warn ( "Failed to update branch name. Are you in a git repository?" ) ;
8693 set ( { branchName : "unknown" } ) ;
8794 }
8895 } ,
8996 openHelpMenu : ( ) => {
97+ logger . info ( "Opening help menu." ) ;
9098 set ( { helpMenuOpen : true } ) ;
9199 } ,
92100 closeHelpMenu : ( ) => {
101+ logger . info ( "Closing help menu." ) ;
93102 set ( { helpMenuOpen : false } ) ;
94103 } ,
95104 clearOutput : ( ) => {
105+ logger . info ( "Clearing output." ) ;
96106 set ( { history : [ ] } ) ;
97107 } ,
98108 clearCommandHistory : ( ) => {
109+ logger . info ( "Clearing command history." ) ;
99110 set ( { commandHistory : [ ] , commandHistoryIndex : 0 } ) ;
100111 try {
101112 fsSync . writeFileSync ( HISTORY_PATH , "" ) ;
102113 } catch ( err ) {
114+ logger . error ( "Failed to clear history file:" , err ) ;
103115 console . error ( "Failed to clear history file:" , err ) ;
104116 }
105117 } ,
106118 clearError : ( ) => {
107119 const { status } = get ( ) ;
108120 if ( status === "error" ) {
121+ logger . info ( "Clearing error." ) ;
109122 set ( { error : null , status : "idle" } ) ;
110123 }
111124 } ,
112125 addCommandToHistory : ( command ) => {
126+ logger . info ( `Adding command to history: ${ command } ` ) ;
113127 const { commandHistory } = get ( ) ;
114128 const newCommandHistory = [ ...commandHistory , command ] ;
115129 set ( {
@@ -119,6 +133,7 @@ export const useStore = create<AppState & AppActions>((set, get) => ({
119133 try {
120134 fsSync . appendFileSync ( HISTORY_PATH , command + "\n" ) ;
121135 } catch ( err ) {
136+ logger . error ( "Failed to write to history file:" , err ) ;
122137 console . error ( "Failed to write to history file:" , err ) ;
123138 }
124139 } ,
@@ -145,6 +160,7 @@ export const useStore = create<AppState & AppActions>((set, get) => ({
145160 return null ;
146161 } ,
147162 setSystemPrompt : ( prompt ) => {
163+ logger . info ( `Setting system prompt to: ${ prompt } ` ) ;
148164 const { config } = get ( ) ;
149165 if ( config ) {
150166 const newConfig = { ...config , systemPrompt : prompt } ;
@@ -153,37 +169,51 @@ export const useStore = create<AppState & AppActions>((set, get) => ({
153169 }
154170 } ,
155171 setModel : ( modelName ) => {
172+ logger . info ( `Setting model to: ${ modelName } ` ) ;
156173 const { config } = get ( ) ;
157174 if ( config ) {
158175 const modelExists = config . models . some ( ( m ) => m . name === modelName ) ;
159176 if ( modelExists ) {
160177 const newConfig = { ...config , defaultModel : modelName } ;
161178 set ( { config : newConfig } ) ;
162179 saveConfig ( newConfig ) ;
180+ logger . info ( `Successfully set model to: ${ modelName } ` ) ;
163181 } else {
182+ logger . error ( `Model "${ modelName } " not found in config.` ) ;
164183 console . error ( `Model "${ modelName } " not found in config.` ) ;
165184 }
166185 }
167186 } ,
168187 startAgent : async ( input : string ) => {
169- if ( get ( ) . status === "error" ) return ;
188+ logger . info ( `Starting agent with input: ${ input } ` ) ;
189+ if ( get ( ) . status === "error" ) {
190+ logger . warn ( "Agent start prevented due to existing error." ) ;
191+ return ;
192+ }
170193 const fileRegex = / @ ( [ ^ \s ] + ) / g;
171194 let processedInput = input ;
172195 const matches = Array . from ( input . matchAll ( fileRegex ) ) ;
173196 const newHistory : Message [ ] = [ ...get ( ) . history ] ;
174197 let shouldContinue = true ;
175198
199+ if ( matches . length > 0 ) {
200+ logger . info ( `Found ${ matches . length } file references in input.` ) ;
201+ }
202+
176203 for ( const match of matches ) {
177204 const filePath = match [ 1 ] ;
178205 if ( filePath ) {
206+ logger . info ( `Reading file content for: ${ filePath } ` ) ;
179207 try {
180208 const fileContent = await fs . readFile ( filePath , "utf-8" ) ;
181209 processedInput = processedInput . replace (
182210 `@${ filePath } ` ,
183211 `\n\n\`\`\`${ filePath } \n${ fileContent } \n\`\`\`` ,
184212 ) ;
213+ logger . info ( `Successfully read and embedded file: ${ filePath } ` ) ;
185214 } catch ( error ) {
186215 const errorMessage = `File not found: ${ filePath } ` ;
216+ logger . error ( `Error reading file: ${ errorMessage } ` ) ;
187217 newHistory . push ( {
188218 id : crypto . randomUUID ( ) ,
189219 role : "assistant" ,
@@ -195,21 +225,30 @@ export const useStore = create<AppState & AppActions>((set, get) => ({
195225 }
196226 }
197227
198- if ( ! shouldContinue ) return ;
228+ if ( ! shouldContinue ) {
229+ logger . warn ( "Agent execution halted due to file reading error." ) ;
230+ return ;
231+ }
199232
200233 newHistory . push ( { role : "user" , content : processedInput , id : crypto . randomUUID ( ) } ) ;
201234 set ( { history : newHistory , status : "thinking" } ) ;
235+ logger . info ( "Agent is now thinking." ) ;
202236 await get ( ) . actions . _runAgentLogic ( ) ;
203237 } ,
204238 _runAgentLogic : async ( retryCount = 0 ) => {
239+ logger . info ( `Running agent logic, retry count: ${ retryCount } ` ) ;
205240 try {
206241 const { history, config } = get ( ) ;
207- if ( ! config ) return ;
242+ if ( ! config ) {
243+ logger . warn ( "No config found, aborting agent logic." ) ;
244+ return ;
245+ }
208246
209247 const { textStream, toolCalls : toolCallPartsPromise } =
210248 await streamAssistantResponse ( history , config ) ;
211249
212250 let assistantMessage : Message | null = null ;
251+ logger . info ( "Streaming assistant response." ) ;
213252
214253 for await ( const part of textStream ) {
215254 if ( ! assistantMessage ) {
@@ -225,8 +264,10 @@ export const useStore = create<AppState & AppActions>((set, get) => ({
225264 assistantMessage . content += part ;
226265 set ( ( state ) => ( { history : [ ...state . history ] } ) ) ;
227266 }
267+ logger . info ( "Finished streaming assistant response." ) ;
228268
229269 const toolCalls = await toolCallPartsPromise ;
270+ logger . info ( "Tool calls received from LLM." , { toolCalls } ) ;
230271
231272 if ( toolCalls . length > 0 ) {
232273 const toolCallContents : ToolCallPart [ ] = toolCalls . map ( ( toolCall ) => ( {
@@ -257,6 +298,7 @@ export const useStore = create<AppState & AppActions>((set, get) => ({
257298 set ( ( state ) => ( { history : [ ...state . history ] } ) ) ;
258299
259300 set ( { status : "executing-tool" } ) ;
301+ logger . info ( "Executing tools." , { toolCalls } ) ;
260302 const toolResults : Message [ ] = [ ] ;
261303 for ( const toolCall of toolCalls ) {
262304 try {
@@ -268,6 +310,7 @@ export const useStore = create<AppState & AppActions>((set, get) => ({
268310 result === "" || result === null || result === undefined
269311 ? "Tool executed successfully and produced no output."
270312 : result ;
313+ logger . info ( "Tool executed successfully." , { toolCall, output } ) ;
271314 toolResults . push ( {
272315 id : crypto . randomUUID ( ) ,
273316 role : "tool" ,
@@ -283,6 +326,7 @@ export const useStore = create<AppState & AppActions>((set, get) => ({
283326 } ) ;
284327 } catch ( error ) {
285328 if ( error instanceof ToolError ) {
329+ logger . error ( "Tool execution failed." , { toolCall, error } ) ;
286330 toolResults . push ( {
287331 id : crypto . randomUUID ( ) ,
288332 role : "tool" ,
@@ -297,6 +341,10 @@ export const useStore = create<AppState & AppActions>((set, get) => ({
297341 ] ,
298342 } ) ;
299343 } else {
344+ logger . error (
345+ "An unexpected error occurred during tool execution." ,
346+ { toolCall, error } ,
347+ ) ;
300348 throw error ;
301349 }
302350 }
@@ -305,12 +353,15 @@ export const useStore = create<AppState & AppActions>((set, get) => ({
305353 history : [ ...state . history , ...toolResults ] ,
306354 status : "thinking" ,
307355 } ) ) ;
356+ logger . info ( "Tool execution finished, rerunning agent logic." ) ;
308357 await get ( ) . actions . _runAgentLogic ( ) ;
309358 } else {
310359 set ( { status : "idle" } ) ;
360+ logger . info ( "No tool calls, agent is now idle." ) ;
311361 }
312362 } catch ( error ) {
313363 if ( error instanceof TransientError && retryCount < MAX_RETRIES ) {
364+ logger . warn ( `Transient error caught, retrying... (${ retryCount + 1 } )` ) ;
314365 set ( { status : "idle" } ) ;
315366 const backoff = INITIAL_BACKOFF_MS * 2 ** retryCount ;
316367 setTimeout ( ( ) => {
@@ -324,8 +375,10 @@ export const useStore = create<AppState & AppActions>((set, get) => ({
324375 error instanceof Error ? error . message : "An unknown error occurred." ;
325376
326377 if ( error instanceof FatalError ) {
378+ logger . error ( `Fatal error: ${ errorMessage } ` ) ;
327379 set ( { error : errorMessage , status : "error" } ) ;
328380 } else {
381+ logger . error ( `Unhandled error in agent logic: ${ errorMessage } ` ) ;
329382 set ( { error : errorMessage , status : "error" } ) ;
330383 }
331384 }
0 commit comments