11import { AnalyticsEvent } from '@codebuff/common/constants/analytics-events'
2- import {
3- endsAgentStepParam ,
4- endToolTag ,
5- startToolTag ,
6- toolNameParam ,
7- } from '@codebuff/common/tools/constants'
82
93import type { Model } from '@codebuff/common/old-constants'
104import type { TrackEventFn } from '@codebuff/common/types/contracts/analytics'
@@ -15,13 +9,6 @@ import type {
159 PrintModeText ,
1610} from '@codebuff/common/types/print-mode'
1711
18- const toolExtractionPattern = new RegExp (
19- `${ startToolTag } (.*?)${ endToolTag } ` ,
20- 'gs' ,
21- )
22-
23- const completionSuffix = `${ JSON . stringify ( endsAgentStepParam ) } : true\n}${ endToolTag } `
24-
2512export async function * processStreamWithTags ( params : {
2613 stream : AsyncGenerator < StreamChunk , string | null >
2714 processors : Record <
@@ -60,83 +47,6 @@ export async function* processStreamWithTags(params: {
6047 let buffer = ''
6148 let autocompleted = false
6249
63- function extractToolCalls ( ) : string [ ] {
64- const matches : string [ ] = [ ]
65- let lastIndex = 0
66- for ( const match of buffer . matchAll ( toolExtractionPattern ) ) {
67- if ( match . index > lastIndex ) {
68- onResponseChunk ( {
69- type : 'text' ,
70- text : buffer . slice ( lastIndex , match . index ) ,
71- } )
72- }
73- lastIndex = match . index + match [ 0 ] . length
74- matches . push ( match [ 1 ] )
75- }
76-
77- buffer = buffer . slice ( lastIndex )
78- return matches
79- }
80-
81- function processToolCallContents ( contents : string ) : void {
82- let input : any
83- try {
84- input = JSON . parse ( contents )
85- } catch ( error : any ) {
86- trackEvent ( {
87- event : AnalyticsEvent . MALFORMED_TOOL_CALL_JSON ,
88- userId : loggerOptions ?. userId ?? '' ,
89- properties : {
90- contents : JSON . stringify ( contents ) ,
91- model : loggerOptions ?. model ,
92- agent : loggerOptions ?. agentName ,
93- error : {
94- name : error . name ,
95- message : error . message ,
96- stack : error . stack ,
97- } ,
98- autocompleted,
99- } ,
100- logger,
101- } )
102- const shortenedContents =
103- contents . length < 200
104- ? contents
105- : contents . slice ( 0 , 100 ) + '...' + contents . slice ( - 100 )
106- const errorMessage = `Invalid JSON: ${ JSON . stringify ( shortenedContents ) } \nError: ${ error . message } `
107- onResponseChunk ( {
108- type : 'error' ,
109- message : errorMessage ,
110- } )
111- onError ( 'parse_error' , errorMessage )
112- return
113- }
114-
115- const toolName = input [ toolNameParam ] as keyof typeof processors
116- if ( typeof toolName !== 'string' ) {
117- trackEvent ( {
118- event : AnalyticsEvent . UNKNOWN_TOOL_CALL ,
119- userId : loggerOptions ?. userId ?? '' ,
120- properties : {
121- contents,
122- toolName,
123- model : loggerOptions ?. model ,
124- agent : loggerOptions ?. agentName ,
125- autocompleted,
126- } ,
127- logger,
128- } )
129- onError (
130- 'parse_error' ,
131- `Unknown tool ${ JSON . stringify ( toolName ) } for tool call: ${ contents } ` ,
132- )
133- return
134- }
135-
136- delete input [ toolNameParam ]
137- processToolCallObject ( { toolName, input, contents } )
138- }
139-
14050 function processToolCallObject ( params : {
14151 toolName : string
14252 input : any
@@ -164,18 +74,14 @@ export async function* processStreamWithTags(params: {
16474 processor . onTagEnd ( toolName , input )
16575 }
16676
167- function extractToolsFromBufferAndProcess ( forceFlush = false ) {
168- const matches = extractToolCalls ( )
169- matches . forEach ( processToolCallContents )
170- if ( forceFlush ) {
171- if ( buffer ) {
172- onResponseChunk ( {
173- type : 'text' ,
174- text : buffer ,
175- } )
176- }
177- buffer = ''
77+ function flush ( ) {
78+ if ( buffer ) {
79+ onResponseChunk ( {
80+ type : 'text' ,
81+ text : buffer ,
82+ } )
17883 }
84+ buffer = ''
17985 }
18086
18187 function * processChunk (
@@ -185,23 +91,13 @@ export async function* processStreamWithTags(params: {
18591 buffer += chunk . text
18692 }
18793 if ( chunk && chunk . type === 'tool-call' ) {
188- extractToolsFromBufferAndProcess ( true )
94+ flush ( )
18995 processToolCallObject ( chunk )
190- } else {
191- extractToolsFromBufferAndProcess ( )
19296 }
19397
19498 if ( chunk === undefined ) {
19599 streamCompleted = true
196- if ( buffer . includes ( startToolTag ) ) {
197- buffer += completionSuffix
198- chunk = {
199- type : 'text' ,
200- text : completionSuffix ,
201- }
202- autocompleted = true
203- }
204- extractToolsFromBufferAndProcess ( true )
100+ flush ( )
205101 }
206102
207103 if ( chunk ) {
0 commit comments