(token: string)
| 100 | const MAX_MARKER = Math.max(LLAMA_THINK_START.length, LLAMA_THINK_END.length); |
| 101 | |
| 102 | const callback = (token: string) => { |
| 103 | buf += token; |
| 104 | |
| 105 | while (buf.length > 0) { |
| 106 | if (state === 'scanning' || state === 'answering') { |
| 107 | const idx = buf.indexOf(LLAMA_THINK_START); |
| 108 | if (idx !== -1) { |
| 109 | // Emit everything before the marker as answer text |
| 110 | const before = buf.slice(0, idx); |
| 111 | if (before) onToken?.(before); |
| 112 | buf = buf.slice(idx + LLAMA_THINK_START.length); |
| 113 | state = 'thinking'; |
| 114 | } else { |
| 115 | // No marker yet — keep a tail in case the marker is split across tokens |
| 116 | const safe = buf.length > MAX_MARKER ? buf.slice(0, buf.length - MAX_MARKER) : ''; |
| 117 | if (safe) onToken?.(safe); |
| 118 | buf = buf.slice(safe.length); |
| 119 | break; |
| 120 | } |
| 121 | } else { |
| 122 | // state === 'thinking' |
| 123 | const idx = buf.indexOf(LLAMA_THINK_END); |
| 124 | if (idx !== -1) { |
| 125 | const reasoning = buf.slice(0, idx); |
| 126 | if (reasoning) onReasoningToken?.(reasoning); |
| 127 | buf = buf.slice(idx + LLAMA_THINK_END.length); |
| 128 | state = 'answering'; |
| 129 | } else { |
| 130 | const safe = buf.length > MAX_MARKER ? buf.slice(0, buf.length - MAX_MARKER) : ''; |
| 131 | if (safe) onReasoningToken?.(safe); |
| 132 | buf = buf.slice(safe.length); |
| 133 | break; |
| 134 | } |
| 135 | } |
| 136 | } |
| 137 | }; |
| 138 | |
| 139 | callback.flush = () => { |
| 140 | if (!buf) return; |
nothing calls this directly
no outgoing calls
no test coverage detected