perf: pre-compile regex patterns and optimize hot-path string operations

- error-classifier: pre-compile default retry pattern regex
- think-mode/detector: combine multilingual patterns into single regex
- parser: skip redundant toLowerCase on pre-lowered keywords
- edit-operations: use fast arraysEqual instead of JSON comparison
- hash-computation: optimize streaming line extraction with index tracking
This commit is contained in:
YeonGyu-Kim
2026-03-18 14:19:23 +09:00
parent 90aa3a306c
commit c5c7ba4eed
5 changed files with 27 additions and 12 deletions

View File

@@ -70,7 +70,7 @@ function isTokenLimitError(text: string): boolean {
return false
}
const lower = text.toLowerCase()
return TOKEN_LIMIT_KEYWORDS.some((kw) => lower.includes(kw.toLowerCase()))
return TOKEN_LIMIT_KEYWORDS.some((kw) => lower.includes(kw))
}
export function parseAnthropicTokenLimitError(err: unknown): ParsedTokenLimitError | null {

View File

@@ -28,6 +28,8 @@ export function getErrorMessage(error: unknown): string {
}
}
const DEFAULT_RETRY_PATTERN = new RegExp(`\\b(${DEFAULT_CONFIG.retry_on_errors.join("|")})\\b`)
export function extractStatusCode(error: unknown, retryOnErrors?: number[]): number | undefined {
if (!error) return undefined
@@ -45,8 +47,9 @@ export function extractStatusCode(error: unknown, retryOnErrors?: number[]): num
return statusCode
}
const codes = retryOnErrors ?? DEFAULT_CONFIG.retry_on_errors
const pattern = new RegExp(`\\b(${codes.join("|")})\\b`)
const pattern = retryOnErrors
? new RegExp(`\\b(${retryOnErrors.join("|")})\\b`)
: DEFAULT_RETRY_PATTERN
const message = getErrorMessage(error)
const statusMatch = message.match(pattern)
if (statusMatch) {

View File

@@ -32,8 +32,10 @@ const MULTILINGUAL_KEYWORDS = [
"fikir", "berfikir",
]
const MULTILINGUAL_PATTERNS = MULTILINGUAL_KEYWORDS.map((kw) => new RegExp(kw, "i"))
const THINK_PATTERNS = [...ENGLISH_PATTERNS, ...MULTILINGUAL_PATTERNS]
const COMBINED_THINK_PATTERN = new RegExp(
`\\b(?:ultrathink|think)\\b|${MULTILINGUAL_KEYWORDS.join("|")}`,
"i"
)
const CODE_BLOCK_PATTERN = /```[\s\S]*?```/g
const INLINE_CODE_PATTERN = /`[^`]+`/g
@@ -44,7 +46,7 @@ function removeCodeBlocks(text: string): string {
export function detectThinkKeyword(text: string): boolean {
const textWithoutCode = removeCodeBlocks(text)
return THINK_PATTERNS.some((pattern) => pattern.test(textWithoutCode))
return COMBINED_THINK_PATTERN.test(textWithoutCode)
}
export function extractPromptText(

View File

@@ -11,6 +11,14 @@ import {
} from "./edit-operation-primitives"
import { validateLineRefs } from "./validation"
function arraysEqual(a: string[], b: string[]): boolean {
if (a.length !== b.length) return false
for (let i = 0; i < a.length; i++) {
if (a[i] !== b[i]) return false
}
return true
}
export interface HashlineApplyReport {
content: string
noopEdits: number
@@ -51,7 +59,7 @@ export function applyHashlineEditsWithReport(content: string, edits: HashlineEdi
const next = edit.end
? applyReplaceLines(lines, edit.pos, edit.end, edit.lines, { skipValidation: true })
: applySetLine(lines, edit.pos, edit.lines, { skipValidation: true })
if (next.join("\n") === lines.join("\n")) {
if (arraysEqual(next, lines)) {
noopEdits += 1
break
}
@@ -62,7 +70,7 @@ export function applyHashlineEditsWithReport(content: string, edits: HashlineEdi
const next = edit.pos
? applyInsertAfter(lines, edit.pos, edit.lines, { skipValidation: true })
: applyAppend(lines, edit.lines)
if (next.join("\n") === lines.join("\n")) {
if (arraysEqual(next, lines)) {
noopEdits += 1
break
}
@@ -73,7 +81,7 @@ export function applyHashlineEditsWithReport(content: string, edits: HashlineEdi
const next = edit.pos
? applyInsertBefore(lines, edit.pos, edit.lines, { skipValidation: true })
: applyPrepend(lines, edit.lines)
if (next.join("\n") === lines.join("\n")) {
if (arraysEqual(next, lines)) {
noopEdits += 1
break
}

View File

@@ -86,15 +86,17 @@ export async function* streamHashLinesFromUtf8(
pending += text
const chunksToYield: string[] = []
let lastIdx = 0
while (true) {
const idx = pending.indexOf("\n")
const idx = pending.indexOf("\n", lastIdx)
if (idx === -1) break
const line = pending.slice(0, idx)
pending = pending.slice(idx + 1)
const line = pending.slice(lastIdx, idx)
lastIdx = idx + 1
endedWithNewline = true
chunksToYield.push(...pushLine(line))
}
pending = pending.slice(lastIdx)
if (pending.length > 0) endedWithNewline = false
return chunksToYield
}