responses_to_anthropic_read_tool_test.go 4.1 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115
  1. package apicompat
  2. import (
  3. "testing"
  4. "github.com/stretchr/testify/assert"
  5. "github.com/stretchr/testify/require"
  6. )
  7. func TestResToAnthFuncArgsDelta_ReadToolWaitsForCompleteJSON(t *testing.T) {
  8. state := NewResponsesEventToAnthropicState()
  9. state.MessageStartSent = true
  10. state.ContentBlockOpen = true
  11. state.CurrentBlockType = "tool_use"
  12. state.CurrentToolName = "Read"
  13. state.OutputIndexToBlockIdx = map[int]int{0: 0}
  14. events := ResponsesEventToAnthropicEvents(&ResponsesStreamEvent{
  15. Type: "response.function_call_arguments.delta",
  16. OutputIndex: 0,
  17. Delta: `{"file_path":"/tmp/te`,
  18. }, state)
  19. assert.Empty(t, events, "partial Read JSON must wait for sanitization")
  20. assert.False(t, state.CurrentToolHadDelta)
  21. events = ResponsesEventToAnthropicEvents(&ResponsesStreamEvent{
  22. Type: "response.function_call_arguments.delta",
  23. OutputIndex: 0,
  24. Delta: `st.go","pages":""}`,
  25. }, state)
  26. require.Len(t, events, 1)
  27. assert.Equal(t, "content_block_delta", events[0].Type)
  28. assert.Equal(t, "input_json_delta", events[0].Delta.Type)
  29. assert.JSONEq(t, `{"file_path":"/tmp/test.go"}`, events[0].Delta.PartialJSON)
  30. assert.Equal(t, `{"file_path":"/tmp/test.go","pages":""}`, state.CurrentToolArgs)
  31. assert.True(t, state.CurrentToolHadDelta)
  32. events = ResponsesEventToAnthropicEvents(&ResponsesStreamEvent{
  33. Type: "response.function_call_arguments.done",
  34. OutputIndex: 0,
  35. Arguments: `{"file_path":"/tmp/test.go","pages":""}`,
  36. }, state)
  37. require.Len(t, events, 1)
  38. assert.Equal(t, "content_block_stop", events[0].Type)
  39. events = ResponsesEventToAnthropicEvents(&ResponsesStreamEvent{
  40. Type: "response.function_call_arguments.done",
  41. OutputIndex: 0,
  42. Arguments: `{"file_path":"/tmp/test.go","pages":""}`,
  43. }, state)
  44. assert.Empty(t, events, "duplicate done must be idempotent")
  45. }
  46. func TestResponsesEventToAnthropicEvents_ReadToolWithoutArgumentsDoneClosesOnCompleted(t *testing.T) {
  47. state := NewResponsesEventToAnthropicState()
  48. events := ResponsesEventToAnthropicEvents(&ResponsesStreamEvent{
  49. Type: "response.created",
  50. Response: &ResponsesResponse{ID: "resp_read", Model: "gpt-5.5"},
  51. }, state)
  52. require.Len(t, events, 1)
  53. assert.Equal(t, "message_start", events[0].Type)
  54. events = ResponsesEventToAnthropicEvents(&ResponsesStreamEvent{
  55. Type: "response.output_item.added",
  56. OutputIndex: 0,
  57. Item: &ResponsesOutput{Type: "function_call", CallID: "call_read", Name: "Read"},
  58. }, state)
  59. require.Len(t, events, 1)
  60. assert.Equal(t, "content_block_start", events[0].Type)
  61. events = ResponsesEventToAnthropicEvents(&ResponsesStreamEvent{
  62. Type: "response.function_call_arguments.delta",
  63. OutputIndex: 0,
  64. Delta: `{"file_path":"/tmp/test.go","pages":""}`,
  65. }, state)
  66. require.Len(t, events, 1)
  67. assert.Equal(t, "content_block_delta", events[0].Type)
  68. assert.Equal(t, "input_json_delta", events[0].Delta.Type)
  69. assert.JSONEq(t, `{"file_path":"/tmp/test.go"}`, events[0].Delta.PartialJSON)
  70. events = ResponsesEventToAnthropicEvents(&ResponsesStreamEvent{
  71. Type: "response.completed",
  72. Response: &ResponsesResponse{
  73. Status: "completed",
  74. },
  75. }, state)
  76. require.Len(t, events, 3)
  77. assert.Equal(t, "content_block_stop", events[0].Type)
  78. assert.Equal(t, "message_delta", events[1].Type)
  79. assert.Equal(t, "tool_use", events[1].Delta.StopReason)
  80. assert.Equal(t, "message_stop", events[2].Type)
  81. assert.Empty(t, FinalizeResponsesAnthropicStream(state), "terminal event already finalized the stream")
  82. }
  83. func TestResToAnthFuncArgsDelta_NonReadToolStreamsPartialJSONImmediately(t *testing.T) {
  84. state := NewResponsesEventToAnthropicState()
  85. state.MessageStartSent = true
  86. state.CurrentBlockType = "tool_use"
  87. state.CurrentToolName = "Write"
  88. state.OutputIndexToBlockIdx = map[int]int{0: 0}
  89. evt := &ResponsesStreamEvent{
  90. Type: "response.function_call_arguments.delta",
  91. OutputIndex: 0,
  92. Delta: `{"file_path":"/tmp/out`,
  93. }
  94. events := ResponsesEventToAnthropicEvents(evt, state)
  95. require.Len(t, events, 1)
  96. assert.Equal(t, "content_block_delta", events[0].Type)
  97. assert.Equal(t, `{"file_path":"/tmp/out`, events[0].Delta.PartialJSON)
  98. assert.True(t, state.CurrentToolHadDelta)
  99. }