@@ -73,10 +73,7 @@ export class AiMemoryMcpServer {
7373 private pendingMemoryTracker : PendingMemoryTracker ;
7474
7575 // Tools that should NOT trigger memory reminder (to avoid infinite loops)
76- private readonly NO_REMINDER_TOOLS = new Set ( [
77- "record_context" ,
78- "verify_work_recorded" ,
79- ] ) ;
76+ private readonly NO_REMINDER_TOOLS = new Set ( [ "record_context" ] ) ;
8077
8178 // 真实日期记录函数
8279 private getCurrentRealDate ( ) : string {
@@ -207,20 +204,26 @@ export class AiMemoryMcpServer {
207204 */
208205 private generateMemoryReminder ( ) : {
209206 pending_count : number ;
210- pending_files : string [ ] ;
207+ pending_details : Array < { file : string ; type : string } > ;
211208 action : string ;
212209 } | null {
213- const unrecordedFiles = this . pendingMemoryTracker . getUnrecorded ( ) ;
210+ const pendingDetails = this . pendingMemoryTracker . getPendingDetails ( ) ;
214211
215- if ( unrecordedFiles . length === 0 ) {
212+ if ( pendingDetails . length === 0 ) {
216213 return null ;
217214 }
218215
216+ // Format file details with change type
217+ const fileDetails = pendingDetails . slice ( 0 , 10 ) . map ( ( detail ) => ( {
218+ file : detail . filePath ,
219+ type : detail . changeType ,
220+ } ) ) ;
221+
219222 return {
220- pending_count : unrecordedFiles . length ,
221- pending_files : unrecordedFiles . slice ( 0 , 5 ) , // Show max 5 files
223+ pending_count : pendingDetails . length ,
224+ pending_details : fileDetails ,
222225 action :
223- "Call record_context NOW to save your work before responding to user." ,
226+ "Call record_context NOW with appropriate type (bug_fix, feature_add, code_modify, etc.) before responding to user." ,
224227 } ;
225228 }
226229
@@ -241,12 +244,21 @@ export class AiMemoryMcpServer {
241244 return result ;
242245 }
243246
247+ // Format file list with change types
248+ const fileList = reminder . pending_details
249+ . map ( ( detail ) => `${ detail . file } (${ detail . type } )` )
250+ . join ( ", " ) ;
251+
252+ const moreFilesText =
253+ reminder . pending_count > 10
254+ ? ` (+${ reminder . pending_count - 10 } more)`
255+ : "" ;
256+
244257 // Add reminder to the result
245- const reminderText = `\n\n---\n[MEMORY REMINDER] ${
246- reminder . pending_count
247- } file(s) edited but not recorded: ${ reminder . pending_files . join ( ", " ) } ${
248- reminder . pending_count > 5 ? ` (+${ reminder . pending_count - 5 } more)` : ""
249- } . ${ reminder . action } `;
258+ const reminderText = `\n\n---\n⚠️ [MEMORY REMINDER] ${ reminder . pending_count } file(s) edited but not recorded:
259+ ${ fileList } ${ moreFilesText }
260+
261+ ${ reminder . action } `;
250262
251263 // Append reminder to the last text content
252264 const newContent = [ ...result . content ] ;
@@ -546,22 +558,6 @@ export class AiMemoryMcpServer {
546558 required : [ "content" ] , // type is optional for AI auto-classification
547559 } ,
548560 } ,
549- {
550- name : "verify_work_recorded" ,
551- description :
552- "Call before responding to user. Checks if edited files have been recorded. Returns warning if record_context was not called." ,
553- inputSchema : {
554- type : "object" ,
555- properties : {
556- work_summary : {
557- type : "string" ,
558- description : "Brief summary of work done" ,
559- } ,
560- project_path : { type : "string" , description : "Project path" } ,
561- } ,
562- required : [ "work_summary" ] ,
563- } ,
564- } ,
565561 {
566562 name : "end_session" ,
567563 description : "End a development session" ,
@@ -885,10 +881,6 @@ export class AiMemoryMcpServer {
885881 return this . handleRecordContext (
886882 safeArgs as unknown as RecordContextParams
887883 ) ;
888- case "verify_work_recorded" :
889- return this . handleVerifyWorkRecorded (
890- safeArgs as { work_summary : string ; project_path ?: string }
891- ) ;
892884 case "end_session" :
893885 return executeAndWrap ( ( ) =>
894886 this . handleEndSession ( safeArgs as { session_id : string } )
@@ -1760,114 +1752,6 @@ export class AiMemoryMcpServer {
17601752 }
17611753 }
17621754
1763- /**
1764- * Handle verify_work_recorded tool call
1765- * Checks if there are unrecorded file changes and provides guidance
1766- */
1767- private async handleVerifyWorkRecorded ( args : {
1768- work_summary : string ;
1769- project_path ?: string ;
1770- } ) {
1771- try {
1772- // Get current session
1773- let sessionId : string | null = null ;
1774- let projectPath = args . project_path ;
1775-
1776- // If no project_path provided, try to infer from current working directory
1777- if ( ! projectPath ) {
1778- const potentialDirs = [
1779- process . env . INIT_CWD ,
1780- process . env . PWD ,
1781- process . env . CD ,
1782- process . cwd ( ) ,
1783- ] . filter ( Boolean ) as string [ ] ;
1784-
1785- for ( const dir of potentialDirs ) {
1786- if ( existsSync ( dir ) ) {
1787- projectPath = dir ;
1788- break ;
1789- }
1790- }
1791- }
1792-
1793- if ( projectPath ) {
1794- sessionId = await this . sessionManager . getCurrentSession ( projectPath ) ;
1795- }
1796-
1797- // Check for unrecorded files
1798- const unrecordedFiles = this . pendingMemoryTracker . getUnrecorded (
1799- sessionId || undefined
1800- ) ;
1801-
1802- if ( unrecordedFiles . length > 0 ) {
1803- // There are unrecorded files - return warning
1804- const fileList = unrecordedFiles
1805- . slice ( 0 , 10 )
1806- . map ( ( f , i ) => ` ${ i + 1 } . ${ f } ` )
1807- . join ( "\n" ) ;
1808- const moreFiles =
1809- unrecordedFiles . length > 10
1810- ? `\n ... and ${ unrecordedFiles . length - 10 } more files`
1811- : "" ;
1812-
1813- // Suggest context type based on work summary
1814- const suggestedType = this . suggestContextType ( args . work_summary ) ;
1815-
1816- const warningText = `WARNING: Work not fully recorded
1817-
1818- Unrecorded files (${ unrecordedFiles . length } ):
1819- ${ fileList } ${ moreFiles }
1820-
1821- ACTION REQUIRED:
1822- Call record_context with:
1823- - type: ${ suggestedType }
1824- - content: "${ args . work_summary } "
1825- - files_changed: [${ unrecordedFiles
1826- . slice ( 0 , 5 )
1827- . map ( ( f ) => `"${ f } "` )
1828- . join ( ", " ) } ${ unrecordedFiles . length > 5 ? ", ..." : "" } ]
1829-
1830- Then call verify_work_recorded again to confirm.` ;
1831-
1832- return {
1833- content : [ { type : "text" , text : warningText } ] ,
1834- isError : true ,
1835- _meta : {
1836- verification_status : "failed" ,
1837- unrecorded_count : unrecordedFiles . length ,
1838- suggested_type : suggestedType ,
1839- } ,
1840- } ;
1841- }
1842-
1843- // All work is recorded
1844- const successText = `VERIFICATION PASSED: All work has been recorded.
1845-
1846- You may now respond to the user.` ;
1847-
1848- return {
1849- content : [ { type : "text" , text : successText } ] ,
1850- isError : false ,
1851- _meta : {
1852- verification_status : "passed" ,
1853- unrecorded_count : 0 ,
1854- } ,
1855- } ;
1856- } catch ( error ) {
1857- return {
1858- content : [
1859- {
1860- type : "text" ,
1861- text : `Failed to verify work: ${
1862- error instanceof Error ? error . message : "Unknown error"
1863- } `,
1864- } ,
1865- ] ,
1866- isError : true ,
1867- } ;
1868- }
1869- }
1870-
18711755 /**
18721756 * Suggest context type based on work summary
18731757 */
0 commit comments