fix(pkg):do regex precompile insteadd on the fly#911
Conversation
There was a problem hiding this comment.
Pull request overview
This PR refactors the provider error classifier to avoid recompiling HTTP-status regexes on the hot path (extractHTTPStatus), improving performance when classifying frequent LLM API errors.
Changes:
- Moved HTTP-status
regexp.MustCompilecalls from insideextractHTTPStatusto a package-level precompiled slice. - Updated
extractHTTPStatusto iterate over the shared precompiled regex list.
💡 Add Copilot custom instructions for smarter, more guided reviews. Learn how to get started.
There was a problem hiding this comment.
Pull request overview
Copilot reviewed 2 out of 2 changed files in this pull request and generated 2 comments.
💡 Add Copilot custom instructions for smarter, more guided reviews. Learn how to get started.
40ac9ef to
59c3300
Compare
There was a problem hiding this comment.
Pull request overview
Copilot reviewed 3 out of 3 changed files in this pull request and generated 1 comment.
💡 Add Copilot custom instructions for smarter, more guided reviews. Learn how to get started.
nikolasdehor
left a comment
There was a problem hiding this comment.
Review: fix(pkg/providers): do regex precompile instead of on the fly
Good performance optimization with a correctness fix included.
Changes
-
error_classifier.go-- MovedhttpStatusPatternsfrom local variables insideextractHTTPStatus()to package-levelvarblock. This avoids recompiling 2-3 regexes on every error classification call. Sinceregexp.MustCompileis safe for concurrent use after compilation, this is the correct Go pattern. -
Fixed case mismatch -- Changed
HTTP[/\s]+tohttp[/\s]+in the regex. This is a real bug fix:ClassifyErrorlowercases the input before callingextractHTTPStatus, so the uppercaseHTTPpattern was dead code that could never match. Good catch. -
Added standalone status code fallback -- New pattern
\b([3-5]\d{2})\bmatches bare status codes like "error 429". This improves error classification coverage for messages that don't follow the "status: NNN" or "http/1.1 NNN" format. -
Test updates -- Fixed test input to use lowercase (matching actual calling convention) and added "error 429" test case.
shell.go Changes
-
absolutePathPatternmoved to package-level -- Same precompile optimization. Previously compiled insideguardCommand()on every call. -
defaultDenyPatternsreformatted fromvar = []*regexp.Regexp{...}tovar (\n defaultDenyPatterns = ...\n absolutePathPattern = ...\n)block -- This is just grouping, no functional change.
Concern
-
Standalone status code regex
\b([3-5]\d{2})\bis broad -- This will match any 3-digit number from 300-599 at a word boundary. Strings like "connection on port 443" would return 443 as a status code. "error code 500" is fine, but "timeout after 300ms" would incorrectly match 300. Consider narrowing the pattern or adding it only as a last-resort fallback with lower priority (which it already is, being the last pattern tried). The current test cases pass, but edge cases could produce false positives. -
httpStatusPatternsvariable rename -- Changed frompatternstohttpStatusPatterns. Good -- avoids shadowing thepatternsparameter name inmatchesAny. Clean naming.
LGTM with the caveat on point #7 (broad fallback pattern). The precompile optimization is correct and the case-sensitivity fix addresses a real bug.
…de matcher The precompiled HTTP regex used uppercase "HTTP" which never matched because ClassifyError lowercases the input. Replace it with a case-insensitive word-boundary pattern that matches any standalone 3-digit status code (300-599), which also subsumes the HTTP/x.x case. Add test case for standalone status code extraction.
…cher Restore the http-prefixed regex (without unnecessary (?i) flag since input is already lowercased by ClassifyError) as a mid-priority pattern to reduce false positives. Add a standalone word-boundary matcher as a fallback for bare status codes like "429". Fix test to use lowercased input matching the actual calling convention.
The path regex in guardCommand was compiled on every call. Hoist it to a package-level var (absolutePathPattern) alongside defaultDenyPatterns in a single var block, so it is compiled once at init time.
a310804 to
10f142c
Compare
Changes from upstream: - fix(channel): config cleanup and regex precompile (sipeed#911, sipeed#916) - fix(github_copilot): improve error handling (sipeed#919) - fix(wecom): context leaks and data race fixes (sipeed#914, sipeed#918) - fix(tools): HTTP client caching and response body cleanup (sipeed#940) - feat(tui): Add configurable Launcher and Gateway process management (sipeed#909) - feat(migrate): Update migration system with openclaw support (sipeed#910) - fix(skills): Use registry-backed search for skills discovery (sipeed#929) - build: Add armv6 support to goreleaser (sipeed#905) - docs: Sync READMEs and channel documentation
* fix(pkg/providers):do regex precompile insteadd on the fly * fix(providers): replace HTTP-specific regex with standalone status code matcher The precompiled HTTP regex used uppercase "HTTP" which never matched because ClassifyError lowercases the input. Replace it with a case-insensitive word-boundary pattern that matches any standalone 3-digit status code (300-599), which also subsumes the HTTP/x.x case. Add test case for standalone status code extraction. * fix(providers): restore http regex and add standalone status code matcher Restore the http-prefixed regex (without unnecessary (?i) flag since input is already lowercased by ClassifyError) as a mid-priority pattern to reduce false positives. Add a standalone word-boundary matcher as a fallback for bare status codes like "429". Fix test to use lowercased input matching the actual calling convention. * perf(tools): move path regex compilation from per-call to package init The path regex in guardCommand was compiled on every call. Hoist it to a package-level var (absolutePathPattern) alongside defaultDenyPatterns in a single var block, so it is compiled once at init time. * style(tools): move inline comment to fix golines formatting error
* fix(pkg/providers):do regex precompile insteadd on the fly * fix(providers): replace HTTP-specific regex with standalone status code matcher The precompiled HTTP regex used uppercase "HTTP" which never matched because ClassifyError lowercases the input. Replace it with a case-insensitive word-boundary pattern that matches any standalone 3-digit status code (300-599), which also subsumes the HTTP/x.x case. Add test case for standalone status code extraction. * fix(providers): restore http regex and add standalone status code matcher Restore the http-prefixed regex (without unnecessary (?i) flag since input is already lowercased by ClassifyError) as a mid-priority pattern to reduce false positives. Add a standalone word-boundary matcher as a fallback for bare status codes like "429". Fix test to use lowercased input matching the actual calling convention. * perf(tools): move path regex compilation from per-call to package init The path regex in guardCommand was compiled on every call. Hoist it to a package-level var (absolutePathPattern) alongside defaultDenyPatterns in a single var block, so it is compiled once at init time. * style(tools): move inline comment to fix golines formatting error
* fix(pkg/providers):do regex precompile insteadd on the fly * fix(providers): replace HTTP-specific regex with standalone status code matcher The precompiled HTTP regex used uppercase "HTTP" which never matched because ClassifyError lowercases the input. Replace it with a case-insensitive word-boundary pattern that matches any standalone 3-digit status code (300-599), which also subsumes the HTTP/x.x case. Add test case for standalone status code extraction. * fix(providers): restore http regex and add standalone status code matcher Restore the http-prefixed regex (without unnecessary (?i) flag since input is already lowercased by ClassifyError) as a mid-priority pattern to reduce false positives. Add a standalone word-boundary matcher as a fallback for bare status codes like "429". Fix test to use lowercased input matching the actual calling convention. * perf(tools): move path regex compilation from per-call to package init The path regex in guardCommand was compiled on every call. Hoist it to a package-level var (absolutePathPattern) alongside defaultDenyPatterns in a single var block, so it is compiled once at init time. * style(tools): move inline comment to fix golines formatting error
📝 Description
Pattern priority
extractHTTPStatus now tries patterns in order of specificity:
Test changes
🗣️ Type of Change
🤖 AI Code Generation
🔗 Related Issue
📚 Technical Context (Skip for Docs)
🧪 Test Environment
📸 Evidence (Optional)
Click to view Logs/Screenshots
☑️ Checklist