@@ -31,11 +31,16 @@ func TestTodoTool_CreateTodo(t *testing.T) {
3131 })
3232 require .NoError (t , err )
3333
34- var output Todo
34+ var output CreateTodoOutput
3535 require .NoError (t , json .Unmarshal ([]byte (result .Output ), & output ))
36- assert .Equal (t , "todo_1" , output .ID )
37- assert .Equal (t , "Test todo item" , output .Description )
38- assert .Equal (t , "pending" , output .Status )
36+ assert .Equal (t , "todo_1" , output .Created .ID )
37+ assert .Equal (t , "Test todo item" , output .Created .Description )
38+ assert .Equal (t , "pending" , output .Created .Status )
39+
40+ // Full state is included in the response
41+ require .Len (t , output .AllTodos , 1 )
42+ assert .Equal (t , "todo_1" , output .AllTodos [0 ].ID )
43+ assert .Contains (t , output .Reminder , "todo_1" )
3944
4045 require .Equal (t , 1 , storage .Len ())
4146 requireMeta (t , result , 1 )
@@ -59,10 +64,16 @@ func TestTodoTool_CreateTodos(t *testing.T) {
5964 assert .Equal (t , "todo_2" , output .Created [1 ].ID )
6065 assert .Equal (t , "todo_3" , output .Created [2 ].ID )
6166
67+ // Full state included in response
68+ require .Len (t , output .AllTodos , 3 )
69+ assert .Contains (t , output .Reminder , "todo_1" )
70+ assert .Contains (t , output .Reminder , "todo_2" )
71+ assert .Contains (t , output .Reminder , "todo_3" )
72+
6273 assert .Equal (t , 3 , storage .Len ())
6374 requireMeta (t , result , 3 )
6475
65- // A second call continues the ID sequence
76+ // A second call continues the ID sequence and includes all 4 items
6677 result , err = tool .handler .createTodos (t .Context (), CreateTodosArgs {
6778 Descriptions : []string {"Last" },
6879 })
@@ -71,6 +82,7 @@ func TestTodoTool_CreateTodos(t *testing.T) {
7182 require .NoError (t , json .Unmarshal ([]byte (result .Output ), & output ))
7283 require .Len (t , output .Created , 1 )
7384 assert .Equal (t , "todo_4" , output .Created [0 ].ID )
85+ require .Len (t , output .AllTodos , 4 )
7486 assert .Equal (t , 4 , storage .Len ())
7587 requireMeta (t , result , 4 )
7688}
@@ -95,9 +107,28 @@ func TestTodoTool_ListTodos(t *testing.T) {
95107 assert .Equal (t , "pending" , output .Todos [i ].Status )
96108 }
97109
110+ // All pending, so reminder should list all of them
111+ assert .Contains (t , output .Reminder , "todo_1" )
112+ assert .Contains (t , output .Reminder , "todo_2" )
113+ assert .Contains (t , output .Reminder , "todo_3" )
114+
98115 requireMeta (t , result , 3 )
99116}
100117
118+ func TestTodoTool_ListTodos_Empty (t * testing.T ) {
119+ tool := NewTodoTool ()
120+
121+ result , err := tool .handler .listTodos (t .Context (), tools.ToolCall {})
122+ require .NoError (t , err )
123+
124+ var output ListTodosOutput
125+ require .NoError (t , json .Unmarshal ([]byte (result .Output ), & output ))
126+ assert .Empty (t , output .Todos )
127+ assert .Empty (t , output .Reminder )
128+
129+ requireMeta (t , result , 0 )
130+ }
131+
101132func TestTodoTool_UpdateTodos (t * testing.T ) {
102133 storage := NewMemoryTodoStorage ()
103134 tool := NewTodoTool (WithStorage (storage ))
@@ -125,6 +156,17 @@ func TestTodoTool_UpdateTodos(t *testing.T) {
125156 assert .Equal (t , "in-progress" , output .Updated [1 ].Status )
126157 assert .Empty (t , output .NotFound )
127158
159+ // Full state included in response
160+ require .Len (t , output .AllTodos , 3 )
161+ assert .Equal (t , "completed" , output .AllTodos [0 ].Status )
162+ assert .Equal (t , "pending" , output .AllTodos [1 ].Status )
163+ assert .Equal (t , "in-progress" , output .AllTodos [2 ].Status )
164+
165+ // Reminder should list incomplete todos
166+ assert .Contains (t , output .Reminder , "todo_2" )
167+ assert .Contains (t , output .Reminder , "todo_3" )
168+ assert .NotContains (t , output .Reminder , "todo_1" ) // completed, should not appear
169+
128170 todos := storage .All ()
129171 require .Len (t , todos , 3 )
130172 assert .Equal (t , "completed" , todos [0 ].Status )
@@ -159,6 +201,9 @@ func TestTodoTool_UpdateTodos_PartialFailure(t *testing.T) {
159201 require .Len (t , output .NotFound , 1 )
160202 assert .Equal (t , "nonexistent" , output .NotFound [0 ])
161203
204+ // Reminder should mention the still-pending todo
205+ assert .Contains (t , output .Reminder , "todo_2" )
206+
162207 todos := storage .All ()
163208 require .Len (t , todos , 2 )
164209 assert .Equal (t , "completed" , todos [0 ].Status )
@@ -185,7 +230,7 @@ func TestTodoTool_UpdateTodos_AllNotFound(t *testing.T) {
185230 assert .Equal (t , "nonexistent2" , output .NotFound [1 ])
186231}
187232
188- func TestTodoTool_UpdateTodos_ClearsWhenAllCompleted (t * testing.T ) {
233+ func TestTodoTool_UpdateTodos_AllCompleted_NoAutoRemoval (t * testing.T ) {
189234 storage := NewMemoryTodoStorage ()
190235 tool := NewTodoTool (WithStorage (storage ))
191236
@@ -205,9 +250,16 @@ func TestTodoTool_UpdateTodos_ClearsWhenAllCompleted(t *testing.T) {
205250 var output UpdateTodosOutput
206251 require .NoError (t , json .Unmarshal ([]byte (result .Output ), & output ))
207252 require .Len (t , output .Updated , 2 )
253+ assert .Empty (t , output .Reminder ) // no reminder when all completed
208254
209- assert .Empty (t , storage .All ())
210- requireMeta (t , result , 0 )
255+ // Full state shows both items as completed
256+ require .Len (t , output .AllTodos , 2 )
257+ assert .Equal (t , "completed" , output .AllTodos [0 ].Status )
258+ assert .Equal (t , "completed" , output .AllTodos [1 ].Status )
259+
260+ // Todos remain in storage (no auto-clear on completion)
261+ assert .Equal (t , 2 , storage .Len ())
262+ requireMeta (t , result , 2 )
211263}
212264
213265func TestTodoTool_WithStorage (t * testing.T ) {
@@ -254,6 +306,55 @@ func TestTodoTool_ParametersAreObjects(t *testing.T) {
254306 }
255307}
256308
309+ func TestTodoTool_CreateTodo_FullStateOutput (t * testing.T ) {
310+ tool := NewTodoTool ()
311+
312+ // Create first todo
313+ result1 , err := tool .handler .createTodo (t .Context (), CreateTodoArgs {Description : "First" })
314+ require .NoError (t , err )
315+ var out1 CreateTodoOutput
316+ require .NoError (t , json .Unmarshal ([]byte (result1 .Output ), & out1 ))
317+ require .Len (t , out1 .AllTodos , 1 )
318+ assert .Contains (t , out1 .Reminder , "todo_1" )
319+
320+ // Create second todo — response shows both
321+ result2 , err := tool .handler .createTodo (t .Context (), CreateTodoArgs {Description : "Second" })
322+ require .NoError (t , err )
323+ var out2 CreateTodoOutput
324+ require .NoError (t , json .Unmarshal ([]byte (result2 .Output ), & out2 ))
325+ require .Len (t , out2 .AllTodos , 2 )
326+ assert .Contains (t , out2 .Reminder , "todo_1" )
327+ assert .Contains (t , out2 .Reminder , "todo_2" )
328+ }
329+
330+ func TestTodoTool_UpdateTodos_FullStateOutput (t * testing.T ) {
331+ tool := NewTodoTool ()
332+
333+ _ , err := tool .handler .createTodos (t .Context (), CreateTodosArgs {
334+ Descriptions : []string {"A" , "B" , "C" },
335+ })
336+ require .NoError (t , err )
337+
338+ result , err := tool .handler .updateTodos (t .Context (), UpdateTodosArgs {
339+ Updates : []TodoUpdate {{ID : "todo_1" , Status : "completed" }},
340+ })
341+ require .NoError (t , err )
342+
343+ var output UpdateTodosOutput
344+ require .NoError (t , json .Unmarshal ([]byte (result .Output ), & output ))
345+
346+ // AllTodos shows full state including the completed item
347+ require .Len (t , output .AllTodos , 3 )
348+ assert .Equal (t , "completed" , output .AllTodos [0 ].Status )
349+ assert .Equal (t , "pending" , output .AllTodos [1 ].Status )
350+ assert .Equal (t , "pending" , output .AllTodos [2 ].Status )
351+
352+ // Reminder only lists incomplete items
353+ assert .NotContains (t , output .Reminder , "todo_1" )
354+ assert .Contains (t , output .Reminder , "todo_2" )
355+ assert .Contains (t , output .Reminder , "todo_3" )
356+ }
357+
257358// requireMeta asserts that result.Meta is a []Todo of the expected length.
258359func requireMeta (t * testing.T , result * tools.ToolCallResult , expectedLen int ) {
259360 t .Helper ()
0 commit comments