You signed in with another tab or window. Reload to refresh your session.You signed out in another tab or window. Reload to refresh your session.You switched accounts on another tab or window. Reload to refresh your session.Dismiss alert
fix(copilot): stop the literal path flashing payloads and rescanning the buffer
Review round on the four-outcome rewrite. Three defects in how an opener is
judged, plus the cost of judging it.
A valid tag showed its raw payload as text while its closing marker streamed
in. The JSON value closes at the `}`, so a half-arrived `</opt` read as stray
trailing content and settled the tag as unresolvable. Every JSON-bodied tag hit
this, and most replies carry a trailing <options> block. dropArrivingClose now
ignores a trailing fragment that could still grow into this tag's own close.
Evidence that a close is genuinely wrong still lands immediately: a misspelled
`</workflow_resource>` is not a prefix of `</workspace_resource>`, and a
truncated `</workspac` stops being one the moment prose follows it.
bodyIsLiteralText scanned the raw body for tag markers while its streaming
counterpart blanked JSON string literals first. A payload that failed its shape
guard and legitimately quoted tag syntax was therefore called literal text and
rendered as raw JSON, which is what discard exists to prevent. Both paths now
judge the same blanked body.
An opener whose own close was misspelled reached forward and matched the NEXT
tag's close, swallowing a valid resource into one literal span and destroying
its chip. When markers in the body prove the matched close belongs to a
different opener, resolution resumes past the opener so the interior is
rescanned and the inner tag still renders.
Cost: resuming past a rejected opener instead of abandoning the message made
each parse O(openers x length), and the parse re-runs for every streamed chunk.
A 40KB reply repeatedly mentioning a tag name cost 7.3s of blocked main thread.
The unclosed-body inspection is now bounded, since both rules decide on their
first piece of evidence, and the opener and close lookups are memoized per
parse rather than rescanning to the end of the buffer for every opener. Same
message: 1.2s. A realistic 40KB reply with 8 mentions: 0.35ms per parse, 28ms
across the entire stream.
Also derives JSON_BODY_TAG_NAMES from SPECIAL_TAG_NAMES so a new tag cannot
silently fall back to the weaker prose heuristics; deletes a docstring the
rewrite orphaned above TAG_SHAPED_MARKER; corrects one still describing the
first-character check that depth tracking replaced; drops a test duplicating
one already in the file; and fixes a test that named the no-nesting rule but
passed with that rule deleted, because its JSON closed before the marker.
Copy file name to clipboardExpand all lines: apps/sim/app/workspace/[workspaceId]/home/components/message-content/components/special-tags/special-tags.test.ts
+60-17Lines changed: 60 additions & 17 deletions
Original file line number
Diff line number
Diff line change
@@ -218,16 +218,71 @@ describe('parseSpecialTags with <question>', () => {
218
218
it('still drops a marker-free malformed payload rather than showing raw JSON',()=>{
219
219
// The complement of the case above: no tag markers in the body, so this is
220
220
// a genuinely broken emission from the agent, not swallowed prose.
Copy file name to clipboardExpand all lines: apps/sim/app/workspace/[workspaceId]/home/components/message-content/components/special-tags/special-tags.tsx
0 commit comments