@@ -79,6 +79,106 @@ def extra_json_from_code_block(
7979
8080 last_character = ""
8181
82+ def track_code_block_delimiter (delta : str ) -> list [str ]:
83+ nonlocal code_block_cache , code_block_delimiter_count , last_character
84+
85+ if delta == "`" :
86+ last_character = delta
87+ code_block_cache += delta
88+ code_block_delimiter_count += 1
89+ return []
90+
91+ pending_output = []
92+ if not in_code_block and code_block_delimiter_count > 0 :
93+ last_character = delta
94+ pending_output .append (code_block_cache )
95+ elif in_code_block :
96+ last_character = delta
97+ code_block_cache += delta
98+
99+ code_block_cache = "" if not in_code_block else code_block_cache
100+ code_block_delimiter_count = 0
101+ return pending_output
102+
103+ def track_marker (
104+ delta : str ,
105+ marker : str ,
106+ marker_cache : str ,
107+ marker_index : int ,
108+ ) -> tuple [str , int , bool , bool , list [str ]]:
109+ nonlocal last_character
110+
111+ if delta .lower () != marker [marker_index ]:
112+ if marker_cache :
113+ last_character = delta
114+ return "" , 0 , False , False , [marker_cache ]
115+ return marker_cache , marker_index , False , False , []
116+
117+ if marker_index == 0 and last_character not in TRIM_BOUNDARY_CHARACTERS :
118+ return marker_cache , marker_index , False , True , []
119+
120+ last_character = delta
121+ marker_cache += delta
122+ marker_index += 1
123+ if marker_index == len (marker ):
124+ marker_cache = ""
125+ marker_index = 0
126+ return marker_cache , marker_index , True , False , []
127+
128+ def close_code_block () -> Generator [
129+ str | AgentScratchpadUnit .Action , None , None
130+ ]:
131+ nonlocal \
132+ code_block_cache , \
133+ code_block_delimiter_count , \
134+ in_code_block , \
135+ last_character
136+
137+ if code_block_delimiter_count != CODE_BLOCK_DELIMITER_COUNT :
138+ return
139+
140+ if in_code_block :
141+ last_character = "`"
142+ yield from extra_json_from_code_block (code_block_cache )
143+ code_block_cache = ""
144+
145+ in_code_block = not in_code_block
146+ code_block_delimiter_count = 0
147+
148+ def track_json (
149+ delta : str ,
150+ ) -> tuple [bool , list [str | AgentScratchpadUnit .Action ]]:
151+ nonlocal got_json , in_json , json_cache , json_quote_count , last_character
152+
153+ if delta == "{" :
154+ json_quote_count += 1
155+ in_json = True
156+ last_character = delta
157+ json_cache += delta
158+ elif delta == "}" :
159+ last_character = delta
160+ json_cache += delta
161+ if json_quote_count > 0 :
162+ json_quote_count -= 1
163+ if json_quote_count == 0 :
164+ in_json = False
165+ got_json = True
166+ return True , []
167+ elif in_json :
168+ last_character = delta
169+ json_cache += delta
170+
171+ if not got_json :
172+ return False , []
173+
174+ got_json = False
175+ last_character = delta
176+ parsed_json = parse_action (json_cache )
177+ json_cache = ""
178+ json_quote_count = 0
179+ in_json = False
180+ return False , [parsed_json ]
181+
82182 for response in llm_response :
83183 if response .delta .usage :
84184 usage_dict ["usage" ] = response .delta .usage
@@ -93,119 +193,45 @@ def extra_json_from_code_block(
93193 delta = response_content [index : index + steps ]
94194 yield_delta = False
95195
96- if delta == "`" :
97- last_character = delta
98- code_block_cache += delta
99- code_block_delimiter_count += 1
100- else :
101- if not in_code_block :
102- if code_block_delimiter_count > 0 :
103- last_character = delta
104- yield code_block_cache
105- code_block_cache = ""
106- else :
107- last_character = delta
108- code_block_cache += delta
109- code_block_delimiter_count = 0
196+ yield from track_code_block_delimiter (delta )
110197
111198 if not in_code_block and not in_json :
112- if delta .lower () == action_str [action_idx ] and action_idx == 0 :
113- if last_character not in TRIM_BOUNDARY_CHARACTERS :
114- yield_delta = True
115- else :
116- last_character = delta
117- action_cache += delta
118- action_idx += 1
119- if action_idx == len (action_str ):
120- action_cache = ""
121- action_idx = 0
122- index += steps
123- continue
124- elif delta .lower () == action_str [action_idx ] and action_idx > 0 :
125- last_character = delta
126- action_cache += delta
127- action_idx += 1
128- if action_idx == len (action_str ):
129- action_cache = ""
130- action_idx = 0
199+ action_cache , action_idx , consumed , yield_delta , output = (
200+ track_marker (delta , action_str , action_cache , action_idx )
201+ )
202+ yield from output
203+ if consumed :
131204 index += steps
132205 continue
133- elif action_cache :
134- last_character = delta
135- yield action_cache
136- action_cache = ""
137- action_idx = 0
138-
139- if delta .lower () == thought_str [thought_idx ] and thought_idx == 0 :
140- if last_character not in TRIM_BOUNDARY_CHARACTERS :
141- yield_delta = True
142- else :
143- last_character = delta
144- thought_cache += delta
145- thought_idx += 1
146- if thought_idx == len (thought_str ):
147- thought_cache = ""
148- thought_idx = 0
149- index += steps
150- continue
151- elif delta .lower () == thought_str [thought_idx ] and thought_idx > 0 :
152- last_character = delta
153- thought_cache += delta
154- thought_idx += 1
155- if thought_idx == len (thought_str ):
156- thought_cache = ""
157- thought_idx = 0
206+
207+ (
208+ thought_cache ,
209+ thought_idx ,
210+ consumed ,
211+ thought_yield_delta ,
212+ output ,
213+ ) = track_marker (delta , thought_str , thought_cache , thought_idx )
214+ yield_delta = yield_delta or thought_yield_delta
215+ yield from output
216+ if consumed :
158217 index += steps
159218 continue
160- elif thought_cache :
161- last_character = delta
162- yield thought_cache
163- thought_cache = ""
164- thought_idx = 0
165219
166220 if yield_delta :
167221 index += steps
168222 last_character = delta
169223 yield delta
170224 continue
171225
172- if code_block_delimiter_count == CODE_BLOCK_DELIMITER_COUNT :
173- if in_code_block :
174- last_character = delta
175- yield from extra_json_from_code_block (code_block_cache )
176- code_block_cache = ""
177-
178- in_code_block = not in_code_block
179- code_block_delimiter_count = 0
226+ yield from close_code_block ()
180227
181228 if not in_code_block :
182229 # handle single json
183- if delta == "{" :
184- json_quote_count += 1
185- in_json = True
186- last_character = delta
187- json_cache += delta
188- elif delta == "}" :
189- last_character = delta
190- json_cache += delta
191- if json_quote_count > 0 :
192- json_quote_count -= 1
193- if json_quote_count == 0 :
194- in_json = False
195- got_json = True
196- index += steps
197- continue
198- elif in_json :
199- last_character = delta
200- json_cache += delta
201-
202- if got_json :
203- got_json = False
204- last_character = delta
205- yield parse_action (json_cache )
206- json_cache = ""
207- json_quote_count = 0
208- in_json = False
230+ consumed , output = track_json (delta )
231+ yield from output
232+ if consumed :
233+ index += steps
234+ continue
209235
210236 if not in_code_block and not in_json :
211237 last_character = delta
0 commit comments