Conversation
📝 WalkthroughWalkthrough实现了一个思考签名修复特性,允许系统在上游返回 4xx/5xx 错误且请求包含思考/签名块时,移除这些块并重试,同时提供可配置的全局开关和审计日志追踪。 Changes
Estimated code review effort🎯 4 (Complex) | ⏱️ ~45 minutes Possibly related PRs
Pre-merge checks and finishing touches❌ Failed checks (1 warning)
✅ Passed checks (2 passed)
✨ Finishing touches
🧪 Generate unit tests (beta)
Comment |
Summary of ChangesHello @ding113, I'm Gemini Code Assist1! I'm currently reviewing this pull request and will post my feedback shortly. In the meantime, here's a summary to help you and other reviewers quickly get up to speed! This pull request addresses a common issue of 'thinking signature' incompatibility errors that can arise when interacting with various AI providers, particularly during provider switching. It introduces a robust, configurable recovery mechanism that automatically attempts to fix these errors by sanitizing request bodies and retrying failed requests. This enhancement aims to improve session stability and prevent unrecoverable error loops, while also providing clear audit trails for transparency and debugging. Highlights
Using Gemini Code AssistThe full guide for Gemini Code Assist can be found on our documentation page, here are some quick tips. Invoking Gemini You can request assistance from Gemini at any point by creating a comment using either
Customization To customize Gemini Code Assist for GitHub experience, repository maintainers can create a configuration file and/or provide a custom code review style guide (such as PEP-8 for Python) by creating and adding files to a Limitations & Feedback Gemini Code Assist may make mistakes. Please leave feedback on any instances where its feedback is incorrect or counter productive. You can react with 👍 and 👎 on @gemini-code-assist comments. If you're interested in giving your feedback about your experience with Gemini Code Assist for Github and other Google products, sign up here. You can also get AI-powered code generation, chat, as well as code reviews directly in the IDE at no cost with the Gemini Code Assist IDE Extension. Footnotes
|
🧪 测试结果
总体结果: ✅ 所有测试通过 |
There was a problem hiding this comment.
Code Review
本次 PR 新增了 thinking signature 恢复功能,这是一个非常实用的容错增强。当上游服务因为 thinking 块签名不兼容而返回错误时,系统会自动移除相关内容并重试一次,从而避免会话中断。
整体实现非常完整,涵盖了数据库结构变更、核心代理逻辑、UI 展示和相关配置,并且为这个关键功能增加了专门的单元测试和覆盖率检查,这是一个很好的实践。核心的恢复逻辑设计得很周全,特别是排除了认证、配额等状态码,避免了掩盖其他重要问题。
我提出了一些建议以进一步提升代码质量:
- 将
forwarder.ts中复杂的重试逻辑提取为独立方法,以提高代码的可读性。 - 在重试逻辑中为 JSON 解析失败的情况添加日志,以便于未来问题诊断。
总的来说,这是一个高质量的 PR,很好地解决了实际问题。
| }); | ||
|
|
||
| // 可选:对 thinking/signature 相关 400 做一次最小降级重试,避免会话进入不可恢复错误循环 | ||
| try { |
| try { | ||
| parsedBody = JSON.parse(init.body); | ||
| } catch { | ||
| parsedBody = null; | ||
| } |
There was a problem hiding this comment.
在 thinking signature 恢复逻辑中,如果 JSON.parse(init.body) 失败,parsedBody 会被设为 null,然后静默地跳过整个恢复流程。虽然这种处理是安全的,但如果 init.body 是一个字符串但不是有效的 JSON,这通常是一个预期之外的状态。建议在 catch 块中增加一个 debug 或 warn 级别的日志,记录 JSON 解析失败的情况,以便于未来诊断类似问题。
try {
parsedBody = JSON.parse(init.body);
} catch (e) {
logger.debug("[ThinkingSignatureFix] Failed to parse request body as JSON", {
providerId: provider.id,
providerName: provider.name,
error: e instanceof Error ? e.message : String(e),
});
parsedBody = null;
}There was a problem hiding this comment.
Actionable comments posted: 0
🧹 Nitpick comments (7)
messages/ru/dashboard.json (1)
131-131: “Fix” 是否需要在俄语环境下本地化?
logs.table.thinkingSignatureFix当前值为英文"Fix",在俄语界面中略显突兀。如果产品设计希望跨语言统一使用英文短 Badge,这样保持即可;否则可以考虑改成简短俄语(例如 “Фикс” 或更贴切的动词),与其他列标题风格更一致。messages/ja/dashboard.json (1)
131-131: 日语 locale 下 “Fix” 的文案风格确认这里
logs.table.thinkingSignatureFix使用英文"Fix",在日文界面中会有一点风格不统一。若设计上刻意统一使用英文 Badge 文案(方便跨语言识别),保持现状即可;若追求完全本地化,可考虑换成简短日文(例如「修正」等)以与表格其他列标题风格一致。messages/zh-CN/dashboard.json (1)
131-131: 可读性:考虑将标签从「修复」改为更具体表述当前
"thinkingSignatureFix": "修复"在表格中是可读的,但略显笼统;如果希望后续与其他可能的“修复”含义区分,可以考虑改为「签名修复」之类更具体的文案,以便一眼看出含义。可选文案调整示例
- "thinkingSignatureFix": "修复", + "thinkingSignatureFix": "签名修复",tests/unit/dashboard-logs-thinking-signature-fix-ui.test.tsx (1)
5-103: UsageLogsTable “Fix” 标记单测逻辑清晰完备这段测试正确构造了包含
thinkingSignatureFixApplied的UsageLogRow,通过NextIntlClientProvider注入真实文案,最后断言渲染文本包含"Fix",很好地保护了仪表盘日志中修复标记的 UI 行为。若后续还有类似日志用例,可以考虑提取一个构造UsageLogRow的测试工厂方法,减少重复样板数据。tests/unit/validation/system-settings-thinking-signature-fix-schema.test.ts (1)
1-15: Schema 测试有效防止漏声明enableThinkingSignatureFix字段这里不仅校验了
safeParse成功,还额外断言返回数据里确实包含enableThinkingSignatureFix: true,可以防止 Zod 将未知字段静默剥离导致“误通过”,很好地锁定了系统设置 schema 对该开关字段的约束。后续如果想更严格,可以再补一条传入非布尔值应失败的用例,但当前测试已满足主要需求。tests/unit/proxy/thinking-signature-recovery.test.ts (1)
52-106: 消息清理测试实现正确。测试用例覆盖了主要场景:
- 正确移除
thinking和redacted_thinking块,保留其他类型- 验证
changed标志和removedBlocks计数- 安全处理非 Claude 消息结构
- 正确处理字符串类型的
content可以考虑添加以下边缘场景的测试(可选):
- 空
messages数组- 移除所有块后
content为空数组的消息🔎 可选测试用例示例
it("应正确处理空 messages 数组", () => { const input = { model: "claude-sonnet", messages: [] }; const result = sanitizeClaudeMessagesRequestThinkingBlocks(input); expect(result.changed).toBe(false); expect(result.sanitized).toBe(input); }); it("应正确处理移除后 content 为空的情况", () => { const input = { model: "claude-sonnet", messages: [ { role: "assistant", content: [{ type: "thinking", thinking: "test" }] }, ], }; const result = sanitizeClaudeMessagesRequestThinkingBlocks(input); expect(result.changed).toBe(true); expect(result.removedBlocks).toBe(1); const messages = result.sanitized.messages as any[]; expect(messages[0].content).toEqual([]); });src/app/v1/_lib/proxy/session.ts (1)
262-281: 可选:简化冗余的防御性包装。
Boolean()包装和?? null在这里是冗余的,因为字段已经有正确的类型和初始值。不过这不影响功能,仅是代码风格建议。🔎 建议的简化
getThinkingSignatureFixApplied(): boolean { - return Boolean(this.thinkingSignatureFixApplied); + return this.thinkingSignatureFixApplied; } getThinkingSignatureFixReason(): string | null { - return this.thinkingSignatureFixReason ?? null; + return this.thinkingSignatureFixReason; }
📜 Review details
Configuration used: Organization UI
Review profile: CHILL
Plan: Pro
Cache: Disabled due to Reviews > Disable Cache setting
📒 Files selected for processing (42)
.gitignoredrizzle/0047_mute_joystick.sqldrizzle/meta/0047_snapshot.jsondrizzle/meta/_journal.jsonmessages/en/dashboard.jsonmessages/en/settings.jsonmessages/ja/dashboard.jsonmessages/ja/settings.jsonmessages/ru/dashboard.jsonmessages/ru/settings.jsonmessages/zh-CN/dashboard.jsonmessages/zh-CN/settings.jsonmessages/zh-TW/dashboard.jsonmessages/zh-TW/settings.jsonpackage.jsonsrc/actions/system-config.tssrc/app/[locale]/dashboard/logs/_components/usage-logs-table.tsxsrc/app/[locale]/settings/config/_components/system-settings-form.tsxsrc/app/[locale]/settings/config/page.tsxsrc/app/api/admin/system-config/route.tssrc/app/v1/_lib/proxy/error-handler.tssrc/app/v1/_lib/proxy/forwarder.tssrc/app/v1/_lib/proxy/response-handler.tssrc/app/v1/_lib/proxy/session.tssrc/app/v1/_lib/proxy/thinking-signature-recovery.tssrc/drizzle/schema.tssrc/lib/config/index.tssrc/lib/config/system-settings-cache.tssrc/lib/validation/schemas.tssrc/repository/_shared/transformers.tssrc/repository/message-write-buffer.tssrc/repository/message.tssrc/repository/system-config.tssrc/repository/usage-logs.tssrc/types/system-config.tstests/unit/dashboard-logs-thinking-signature-fix-ui.test.tsxtests/unit/proxy/proxy-forwarder-thinking-signature-recovery.test.tstests/unit/proxy/thinking-signature-recovery.test.tstests/unit/repository/message-write-buffer.test.tstests/unit/repository/usage-logs-thinking-signature-fix-columns.test.tstests/unit/validation/system-settings-thinking-signature-fix-schema.test.tsvitest.thinking-signature-fix.config.ts
🧰 Additional context used
📓 Path-based instructions (21)
**/*.{ts,tsx,js,jsx,json}
📄 CodeRabbit inference engine (CLAUDE.md)
Use 2-space indentation in all code files
Files:
package.jsonsrc/types/system-config.tsdrizzle/meta/_journal.jsonmessages/en/dashboard.jsonmessages/zh-CN/settings.jsonsrc/lib/config/index.tssrc/repository/message-write-buffer.tssrc/app/[locale]/settings/config/page.tsxtests/unit/repository/usage-logs-thinking-signature-fix-columns.test.tsmessages/ja/settings.jsonmessages/ru/settings.jsonmessages/zh-TW/dashboard.jsonsrc/repository/message.tssrc/app/[locale]/dashboard/logs/_components/usage-logs-table.tsxmessages/zh-CN/dashboard.jsontests/unit/proxy/thinking-signature-recovery.test.tsmessages/zh-TW/settings.jsonsrc/repository/system-config.tssrc/app/v1/_lib/proxy/thinking-signature-recovery.tsmessages/ja/dashboard.jsonsrc/repository/usage-logs.tssrc/actions/system-config.tssrc/lib/validation/schemas.tssrc/app/api/admin/system-config/route.tsvitest.thinking-signature-fix.config.tssrc/app/v1/_lib/proxy/session.tstests/unit/proxy/proxy-forwarder-thinking-signature-recovery.test.tssrc/app/v1/_lib/proxy/error-handler.tssrc/app/v1/_lib/proxy/response-handler.tstests/unit/validation/system-settings-thinking-signature-fix-schema.test.tssrc/lib/config/system-settings-cache.tstests/unit/repository/message-write-buffer.test.tsmessages/en/settings.jsonsrc/app/[locale]/settings/config/_components/system-settings-form.tsxdrizzle/meta/0047_snapshot.jsonsrc/repository/_shared/transformers.tssrc/app/v1/_lib/proxy/forwarder.tssrc/drizzle/schema.tsmessages/ru/dashboard.jsontests/unit/dashboard-logs-thinking-signature-fix-ui.test.tsx
**/*.{tsx,json}
📄 CodeRabbit inference engine (AGENTS.md)
Use next-intl for internationalization with 5 locales: en, ja, ru, zh-CN, zh-TW
Files:
package.jsondrizzle/meta/_journal.jsonmessages/en/dashboard.jsonmessages/zh-CN/settings.jsonsrc/app/[locale]/settings/config/page.tsxmessages/ja/settings.jsonmessages/ru/settings.jsonmessages/zh-TW/dashboard.jsonsrc/app/[locale]/dashboard/logs/_components/usage-logs-table.tsxmessages/zh-CN/dashboard.jsonmessages/zh-TW/settings.jsonmessages/ja/dashboard.jsonmessages/en/settings.jsonsrc/app/[locale]/settings/config/_components/system-settings-form.tsxdrizzle/meta/0047_snapshot.jsonmessages/ru/dashboard.jsontests/unit/dashboard-logs-thinking-signature-fix-ui.test.tsx
**/*.{ts,tsx,js,jsx}
📄 CodeRabbit inference engine (CLAUDE.md)
**/*.{ts,tsx,js,jsx}: Use double quotes for strings instead of single quotes
Use trailing commas in multi-line structures
Enforce maximum line length of 100 characters
Use path alias@/*to reference files from./src/*directory
**/*.{ts,tsx,js,jsx}: Use Biome for linting and formatting with 2-space indent, double quotes, trailing commas, and 100 character max line length
Use path alias@/*to reference files in./src/*directory
Files:
src/types/system-config.tssrc/lib/config/index.tssrc/repository/message-write-buffer.tssrc/app/[locale]/settings/config/page.tsxtests/unit/repository/usage-logs-thinking-signature-fix-columns.test.tssrc/repository/message.tssrc/app/[locale]/dashboard/logs/_components/usage-logs-table.tsxtests/unit/proxy/thinking-signature-recovery.test.tssrc/repository/system-config.tssrc/app/v1/_lib/proxy/thinking-signature-recovery.tssrc/repository/usage-logs.tssrc/actions/system-config.tssrc/lib/validation/schemas.tssrc/app/api/admin/system-config/route.tsvitest.thinking-signature-fix.config.tssrc/app/v1/_lib/proxy/session.tstests/unit/proxy/proxy-forwarder-thinking-signature-recovery.test.tssrc/app/v1/_lib/proxy/error-handler.tssrc/app/v1/_lib/proxy/response-handler.tstests/unit/validation/system-settings-thinking-signature-fix-schema.test.tssrc/lib/config/system-settings-cache.tstests/unit/repository/message-write-buffer.test.tssrc/app/[locale]/settings/config/_components/system-settings-form.tsxsrc/repository/_shared/transformers.tssrc/app/v1/_lib/proxy/forwarder.tssrc/drizzle/schema.tstests/unit/dashboard-logs-thinking-signature-fix-ui.test.tsx
**/*.{ts,tsx}
📄 CodeRabbit inference engine (AGENTS.md)
**/*.{ts,tsx}: Use TypeScript strict mode for type safety
Use readonly or const assertions for immutable data structures
Files:
src/types/system-config.tssrc/lib/config/index.tssrc/repository/message-write-buffer.tssrc/app/[locale]/settings/config/page.tsxtests/unit/repository/usage-logs-thinking-signature-fix-columns.test.tssrc/repository/message.tssrc/app/[locale]/dashboard/logs/_components/usage-logs-table.tsxtests/unit/proxy/thinking-signature-recovery.test.tssrc/repository/system-config.tssrc/app/v1/_lib/proxy/thinking-signature-recovery.tssrc/repository/usage-logs.tssrc/actions/system-config.tssrc/lib/validation/schemas.tssrc/app/api/admin/system-config/route.tsvitest.thinking-signature-fix.config.tssrc/app/v1/_lib/proxy/session.tstests/unit/proxy/proxy-forwarder-thinking-signature-recovery.test.tssrc/app/v1/_lib/proxy/error-handler.tssrc/app/v1/_lib/proxy/response-handler.tstests/unit/validation/system-settings-thinking-signature-fix-schema.test.tssrc/lib/config/system-settings-cache.tstests/unit/repository/message-write-buffer.test.tssrc/app/[locale]/settings/config/_components/system-settings-form.tsxsrc/repository/_shared/transformers.tssrc/app/v1/_lib/proxy/forwarder.tssrc/drizzle/schema.tstests/unit/dashboard-logs-thinking-signature-fix-ui.test.tsx
src/**/*.ts
📄 CodeRabbit inference engine (AGENTS.md)
src/**/*.ts: Hash API keys using SHA-256 before storing in database, never store plaintext keys
Mask API keys and sensitive data in application logs
Validate required environment variables at startup with clear error messages
Files:
src/types/system-config.tssrc/lib/config/index.tssrc/repository/message-write-buffer.tssrc/repository/message.tssrc/repository/system-config.tssrc/app/v1/_lib/proxy/thinking-signature-recovery.tssrc/repository/usage-logs.tssrc/actions/system-config.tssrc/lib/validation/schemas.tssrc/app/api/admin/system-config/route.tssrc/app/v1/_lib/proxy/session.tssrc/app/v1/_lib/proxy/error-handler.tssrc/app/v1/_lib/proxy/response-handler.tssrc/lib/config/system-settings-cache.tssrc/repository/_shared/transformers.tssrc/app/v1/_lib/proxy/forwarder.tssrc/drizzle/schema.ts
messages/**/*.json
📄 CodeRabbit inference engine (CLAUDE.md)
Support 5 locales via next-intl: en, ja, ru, zh-CN, zh-TW with messages in
messages/{locale}/*.jsonStore message translations in
messages/{locale}/*.jsonfiles
Files:
messages/en/dashboard.jsonmessages/zh-CN/settings.jsonmessages/ja/settings.jsonmessages/ru/settings.jsonmessages/zh-TW/dashboard.jsonmessages/zh-CN/dashboard.jsonmessages/zh-TW/settings.jsonmessages/ja/dashboard.jsonmessages/en/settings.jsonmessages/ru/dashboard.json
src/lib/**/*.ts
📄 CodeRabbit inference engine (AGENTS.md)
Use connection pooling for database and Redis connections
Files:
src/lib/config/index.tssrc/lib/validation/schemas.tssrc/lib/config/system-settings-cache.ts
src/repository/**/*.ts
📄 CodeRabbit inference engine (CLAUDE.md)
Use Repository pattern in
src/repository/to wrap Drizzle queries
Files:
src/repository/message-write-buffer.tssrc/repository/message.tssrc/repository/system-config.tssrc/repository/usage-logs.tssrc/repository/_shared/transformers.ts
src/**/*{message,response,log}*.ts
📄 CodeRabbit inference engine (AGENTS.md)
Log request duration, token usage, and cost to message_request table for analytics
Files:
src/repository/message-write-buffer.tssrc/repository/message.tssrc/repository/usage-logs.tssrc/app/v1/_lib/proxy/response-handler.ts
src/{repository,actions}/**/*.ts
📄 CodeRabbit inference engine (AGENTS.md)
Avoid N+1 queries by using eager loading and batch queries for statistics
Files:
src/repository/message-write-buffer.tssrc/repository/message.tssrc/repository/system-config.tssrc/repository/usage-logs.tssrc/actions/system-config.tssrc/repository/_shared/transformers.ts
src/**/*.{tsx,jsx}
📄 CodeRabbit inference engine (AGENTS.md)
src/**/*.{tsx,jsx}: Uselucide-reactfor icons, no custom SVGs
Use React's automatic escaping to prevent XSS vulnerabilities
Files:
src/app/[locale]/settings/config/page.tsxsrc/app/[locale]/dashboard/logs/_components/usage-logs-table.tsxsrc/app/[locale]/settings/config/_components/system-settings-form.tsx
**/*.test.{ts,tsx}
📄 CodeRabbit inference engine (AGENTS.md)
Use Vitest for unit testing with Node environment, coverage thresholds: 50% lines/functions, 40% branches
Files:
tests/unit/repository/usage-logs-thinking-signature-fix-columns.test.tstests/unit/proxy/thinking-signature-recovery.test.tstests/unit/proxy/proxy-forwarder-thinking-signature-recovery.test.tstests/unit/validation/system-settings-thinking-signature-fix-schema.test.tstests/unit/repository/message-write-buffer.test.tstests/unit/dashboard-logs-thinking-signature-fix-ui.test.tsx
**/*.test.ts
📄 CodeRabbit inference engine (AGENTS.md)
Ensure test database names contain 'test' keyword for safety validation
Files:
tests/unit/repository/usage-logs-thinking-signature-fix-columns.test.tstests/unit/proxy/thinking-signature-recovery.test.tstests/unit/proxy/proxy-forwarder-thinking-signature-recovery.test.tstests/unit/validation/system-settings-thinking-signature-fix-schema.test.tstests/unit/repository/message-write-buffer.test.ts
src/app/v1/_lib/**/*.ts
📄 CodeRabbit inference engine (CLAUDE.md)
Guard pipeline must execute in order: ProxyAuthenticator, SensitiveWordGuard, VersionGuard, ProxySessionGuard, ProxyRateLimitGuard, ProxyProviderResolver
Files:
src/app/v1/_lib/proxy/thinking-signature-recovery.tssrc/app/v1/_lib/proxy/session.tssrc/app/v1/_lib/proxy/error-handler.tssrc/app/v1/_lib/proxy/response-handler.tssrc/app/v1/_lib/proxy/forwarder.ts
src/app/v1/_lib/proxy/**/*.ts
📄 CodeRabbit inference engine (AGENTS.md)
src/app/v1/_lib/proxy/**/*.ts: Implement guard pipeline pattern for cross-cutting concerns in request processing (auth, rate limiting, session)
Use undici library for HTTP requests instead of node-fetch for better performance
Files:
src/app/v1/_lib/proxy/thinking-signature-recovery.tssrc/app/v1/_lib/proxy/session.tssrc/app/v1/_lib/proxy/error-handler.tssrc/app/v1/_lib/proxy/response-handler.tssrc/app/v1/_lib/proxy/forwarder.ts
src/app/**/*.ts
📄 CodeRabbit inference engine (AGENTS.md)
Implement Content-Security-Policy headers for XSS prevention
Files:
src/app/v1/_lib/proxy/thinking-signature-recovery.tssrc/app/api/admin/system-config/route.tssrc/app/v1/_lib/proxy/session.tssrc/app/v1/_lib/proxy/error-handler.tssrc/app/v1/_lib/proxy/response-handler.tssrc/app/v1/_lib/proxy/forwarder.ts
src/app/v1/**/*.ts
📄 CodeRabbit inference engine (AGENTS.md)
Use Hono router for ultrafast, lightweight routing in proxy endpoints
Files:
src/app/v1/_lib/proxy/thinking-signature-recovery.tssrc/app/v1/_lib/proxy/session.tssrc/app/v1/_lib/proxy/error-handler.tssrc/app/v1/_lib/proxy/response-handler.tssrc/app/v1/_lib/proxy/forwarder.ts
src/actions/**/*.ts
📄 CodeRabbit inference engine (AGENTS.md)
src/actions/**/*.ts: Validate all user inputs with Zod schemas before processing
Use Server Actions innext-safe-actionwith OpenAPI generation for admin API endpoints
Use Next.js API Routes and Server Actions for admin operations and REST endpoints
Files:
src/actions/system-config.ts
src/app/api/**/*.ts
📄 CodeRabbit inference engine (AGENTS.md)
Implement health check endpoint returning database and Redis status
Files:
src/app/api/admin/system-config/route.ts
src/app/v1/_lib/proxy/*handler*.ts
📄 CodeRabbit inference engine (AGENTS.md)
Stream responses with proper backpressure handling and chunked transfer encoding
Files:
src/app/v1/_lib/proxy/error-handler.tssrc/app/v1/_lib/proxy/response-handler.ts
src/drizzle/**/*.ts
📄 CodeRabbit inference engine (CLAUDE.md)
Use Drizzle ORM with PostgreSQL for database operations
src/drizzle/**/*.ts: Use Drizzle ORM with parameterized queries to prevent SQL injection
Use soft delete pattern withdeletedAtcolumn instead of hard deletes
Use JSON columns in PostgreSQL for flexible data structures (modelRedirects, providerChain, etc.)
Implement proper indexing strategy for common queries and foreign keys
Files:
src/drizzle/schema.ts
🧠 Learnings (19)
📚 Learning: 2026-01-03T09:08:49.019Z
Learnt from: CR
Repo: ding113/claude-code-hub PR: 0
File: AGENTS.md:0-0
Timestamp: 2026-01-03T09:08:49.019Z
Learning: Applies to **/*.test.{ts,tsx} : Use Vitest for unit testing with Node environment, coverage thresholds: 50% lines/functions, 40% branches
Applied to files:
package.jsontests/unit/repository/usage-logs-thinking-signature-fix-columns.test.tsvitest.thinking-signature-fix.config.ts.gitignoretests/unit/dashboard-logs-thinking-signature-fix-ui.test.tsx
📚 Learning: 2026-01-03T09:08:49.019Z
Learnt from: CR
Repo: ding113/claude-code-hub PR: 0
File: AGENTS.md:0-0
Timestamp: 2026-01-03T09:08:49.019Z
Learning: Applies to **/*.test.ts : Ensure test database names contain 'test' keyword for safety validation
Applied to files:
package.jsontests/unit/repository/usage-logs-thinking-signature-fix-columns.test.tsvitest.thinking-signature-fix.config.tstests/unit/validation/system-settings-thinking-signature-fix-schema.test.tstests/unit/repository/message-write-buffer.test.tstests/unit/dashboard-logs-thinking-signature-fix-ui.test.tsx
📚 Learning: 2026-01-03T09:08:20.573Z
Learnt from: CR
Repo: ding113/claude-code-hub PR: 0
File: CLAUDE.md:0-0
Timestamp: 2026-01-03T09:08:20.573Z
Learning: Applies to tests/integration/**/*.test.{ts,tsx} : Integration tests requiring database must be placed in `tests/integration/` and use test database with 'test' in the name
Applied to files:
tests/unit/repository/usage-logs-thinking-signature-fix-columns.test.tstests/unit/validation/system-settings-thinking-signature-fix-schema.test.tstests/unit/dashboard-logs-thinking-signature-fix-ui.test.tsx
📚 Learning: 2026-01-03T09:08:49.019Z
Learnt from: CR
Repo: ding113/claude-code-hub PR: 0
File: AGENTS.md:0-0
Timestamp: 2026-01-03T09:08:49.019Z
Learning: Applies to tests/integration/**/*.test.ts : Place integration tests requiring database in `tests/integration/` (excluded by default)
Applied to files:
tests/unit/repository/usage-logs-thinking-signature-fix-columns.test.tsvitest.thinking-signature-fix.config.ts
📚 Learning: 2026-01-03T09:08:20.573Z
Learnt from: CR
Repo: ding113/claude-code-hub PR: 0
File: CLAUDE.md:0-0
Timestamp: 2026-01-03T09:08:20.573Z
Learning: Applies to src/repository/**/*.ts : Use Repository pattern in `src/repository/` to wrap Drizzle queries
Applied to files:
tests/unit/repository/usage-logs-thinking-signature-fix-columns.test.ts
📚 Learning: 2026-01-03T09:08:49.019Z
Learnt from: CR
Repo: ding113/claude-code-hub PR: 0
File: AGENTS.md:0-0
Timestamp: 2026-01-03T09:08:49.019Z
Learning: Applies to src/drizzle/**/*.ts : Implement proper indexing strategy for common queries and foreign keys
Applied to files:
tests/unit/repository/usage-logs-thinking-signature-fix-columns.test.tsdrizzle/meta/0047_snapshot.json
📚 Learning: 2026-01-03T09:08:20.573Z
Learnt from: CR
Repo: ding113/claude-code-hub PR: 0
File: CLAUDE.md:0-0
Timestamp: 2026-01-03T09:08:20.573Z
Learning: Applies to src/drizzle/**/*.ts : Use Drizzle ORM with PostgreSQL for database operations
Applied to files:
tests/unit/repository/usage-logs-thinking-signature-fix-columns.test.tsdrizzle/meta/0047_snapshot.json
📚 Learning: 2026-01-03T09:08:49.019Z
Learnt from: CR
Repo: ding113/claude-code-hub PR: 0
File: AGENTS.md:0-0
Timestamp: 2026-01-03T09:08:49.019Z
Learning: Applies to src/**/*{message,response,log}*.ts : Log request duration, token usage, and cost to message_request table for analytics
Applied to files:
src/app/[locale]/dashboard/logs/_components/usage-logs-table.tsxsrc/repository/usage-logs.tssrc/drizzle/schema.ts
📚 Learning: 2026-01-03T09:08:20.573Z
Learnt from: CR
Repo: ding113/claude-code-hub PR: 0
File: CLAUDE.md:0-0
Timestamp: 2026-01-03T09:08:20.573Z
Learning: Applies to messages/**/*.json : Support 5 locales via next-intl: en, ja, ru, zh-CN, zh-TW with messages in `messages/{locale}/*.json`
Applied to files:
messages/zh-TW/settings.json
📚 Learning: 2026-01-03T09:08:49.019Z
Learnt from: CR
Repo: ding113/claude-code-hub PR: 0
File: AGENTS.md:0-0
Timestamp: 2026-01-03T09:08:49.019Z
Learning: Applies to src/app/v1/_lib/proxy/**/*.ts : Implement guard pipeline pattern for cross-cutting concerns in request processing (auth, rate limiting, session)
Applied to files:
src/app/v1/_lib/proxy/thinking-signature-recovery.tssrc/app/v1/_lib/proxy/session.tstests/unit/proxy/proxy-forwarder-thinking-signature-recovery.test.tssrc/app/v1/_lib/proxy/error-handler.tssrc/app/v1/_lib/proxy/response-handler.tssrc/app/v1/_lib/proxy/forwarder.ts
📚 Learning: 2026-01-03T09:08:20.573Z
Learnt from: CR
Repo: ding113/claude-code-hub PR: 0
File: CLAUDE.md:0-0
Timestamp: 2026-01-03T09:08:20.573Z
Learning: Applies to src/app/v1/_lib/proxy-handler.ts : Structure request flow in proxy handler through: ProxySession.fromContext() -> detectFormat() -> GuardPipelineBuilder.run() -> ProxyForwarder.send() -> ProxyResponseHandler.dispatch()
Applied to files:
src/app/v1/_lib/proxy/session.tstests/unit/proxy/proxy-forwarder-thinking-signature-recovery.test.tssrc/app/v1/_lib/proxy/response-handler.tssrc/app/v1/_lib/proxy/forwarder.ts
📚 Learning: 2026-01-03T09:08:20.573Z
Learnt from: CR
Repo: ding113/claude-code-hub PR: 0
File: CLAUDE.md:0-0
Timestamp: 2026-01-03T09:08:20.573Z
Learning: Applies to src/app/v1/_lib/**/*.ts : Guard pipeline must execute in order: ProxyAuthenticator, SensitiveWordGuard, VersionGuard, ProxySessionGuard, ProxyRateLimitGuard, ProxyProviderResolver
Applied to files:
src/app/v1/_lib/proxy/session.tssrc/app/v1/_lib/proxy/forwarder.ts
📚 Learning: 2026-01-03T09:08:20.573Z
Learnt from: CR
Repo: ding113/claude-code-hub PR: 0
File: CLAUDE.md:0-0
Timestamp: 2026-01-03T09:08:20.573Z
Learning: Applies to src/lib/session-manager.ts : Session Manager must use 5-minute Redis context cache with sliding window and record decision chains for audit trail
Applied to files:
src/app/v1/_lib/proxy/session.ts
📚 Learning: 2026-01-03T09:08:49.019Z
Learnt from: CR
Repo: ding113/claude-code-hub PR: 0
File: AGENTS.md:0-0
Timestamp: 2026-01-03T09:08:49.019Z
Learning: Applies to src/drizzle/**/*.ts : Use JSON columns in PostgreSQL for flexible data structures (modelRedirects, providerChain, etc.)
Applied to files:
drizzle/meta/0047_snapshot.json
📚 Learning: 2026-01-03T09:08:49.019Z
Learnt from: CR
Repo: ding113/claude-code-hub PR: 0
File: AGENTS.md:0-0
Timestamp: 2026-01-03T09:08:49.019Z
Learning: Applies to src/app/v1/_lib/proxy/*handler*.ts : Stream responses with proper backpressure handling and chunked transfer encoding
Applied to files:
src/app/v1/_lib/proxy/forwarder.ts
📚 Learning: 2026-01-03T09:08:49.019Z
Learnt from: CR
Repo: ding113/claude-code-hub PR: 0
File: AGENTS.md:0-0
Timestamp: 2026-01-03T09:08:49.019Z
Learning: Applies to src/app/v1/_lib/proxy/**/*.ts : Use undici library for HTTP requests instead of node-fetch for better performance
Applied to files:
src/app/v1/_lib/proxy/forwarder.ts
📚 Learning: 2026-01-03T09:08:49.019Z
Learnt from: CR
Repo: ding113/claude-code-hub PR: 0
File: AGENTS.md:0-0
Timestamp: 2026-01-03T09:08:49.019Z
Learning: Applies to src/app/v1/_lib/proxy/**/*guard*.ts : Implement fail-open strategy: allow requests when Redis is unavailable
Applied to files:
src/app/v1/_lib/proxy/forwarder.ts
📚 Learning: 2026-01-03T09:08:49.019Z
Learnt from: CR
Repo: ding113/claude-code-hub PR: 0
File: AGENTS.md:0-0
Timestamp: 2026-01-03T09:08:49.019Z
Learning: Applies to src/**/*provider*.ts : Set provider circuit breaker failure threshold, open duration, and half-open success threshold in configuration
Applied to files:
src/app/v1/_lib/proxy/forwarder.ts
📚 Learning: 2026-01-03T09:08:20.573Z
Learnt from: CR
Repo: ding113/claude-code-hub PR: 0
File: CLAUDE.md:0-0
Timestamp: 2026-01-03T09:08:20.573Z
Learning: Applies to src/lib/circuit-breaker.ts : Circuit Breaker must implement state machine: CLOSED -> OPEN -> HALF_OPEN -> CLOSED with per-provider isolation and Redis persistence
Applied to files:
src/app/v1/_lib/proxy/forwarder.ts
🧬 Code graph analysis (13)
tests/unit/repository/usage-logs-thinking-signature-fix-columns.test.ts (1)
src/repository/usage-logs.ts (2)
findUsageLogsBatch(112-261)findUsageLogsWithDetails(306-482)
src/app/[locale]/dashboard/logs/_components/usage-logs-table.tsx (2)
src/components/ui/badge.tsx (1)
Badge(39-39)scripts/sync-settings-keys.js (1)
t(72-72)
tests/unit/proxy/thinking-signature-recovery.test.ts (2)
src/app/v1/_lib/proxy/errors.ts (1)
ProxyError(14-450)src/app/v1/_lib/proxy/thinking-signature-recovery.ts (2)
isThinkingSignatureRelatedError(18-42)sanitizeClaudeMessagesRequestThinkingBlocks(52-101)
src/repository/system-config.ts (1)
src/drizzle/schema.ts (1)
systemSettings(453-490)
src/app/v1/_lib/proxy/thinking-signature-recovery.ts (1)
src/app/v1/_lib/proxy/errors.ts (1)
ProxyError(14-450)
src/repository/usage-logs.ts (1)
src/drizzle/schema.ts (1)
messageRequest(274-359)
tests/unit/proxy/proxy-forwarder-thinking-signature-recovery.test.ts (2)
src/app/v1/_lib/proxy/session.ts (1)
ProxySession(48-758)src/app/v1/_lib/proxy/forwarder.ts (2)
ProxyForwarder(188-2246)doForward(786-1797)
src/app/v1/_lib/proxy/response-handler.ts (1)
src/app/v1/_lib/proxy/session.ts (1)
ProxySession(48-758)
tests/unit/validation/system-settings-thinking-signature-fix-schema.test.ts (1)
src/lib/validation/schemas.ts (1)
UpdateSystemSettingsSchema(705-746)
tests/unit/repository/message-write-buffer.test.ts (1)
src/repository/message-write-buffer.ts (2)
enqueueMessageRequestUpdate(324-334)stopMessageRequestWriteBuffer(343-357)
src/app/[locale]/settings/config/_components/system-settings-form.tsx (2)
src/components/ui/label.tsx (1)
Label(21-21)src/components/ui/switch.tsx (1)
Switch(28-28)
src/app/v1/_lib/proxy/forwarder.ts (5)
src/app/v1/_lib/proxy/errors.ts (1)
ProxyError(14-450)src/lib/config/index.ts (1)
isThinkingSignatureFixEnabled(11-11)src/lib/config/system-settings-cache.ts (1)
isThinkingSignatureFixEnabled(115-118)src/app/v1/_lib/proxy/thinking-signature-recovery.ts (2)
sanitizeClaudeMessagesRequestThinkingBlocks(52-101)isThinkingSignatureRelatedError(18-42)src/app/v1/_lib/proxy/session.ts (1)
ProxySession(48-758)
src/drizzle/schema.ts (1)
src/lib/polyfills/file.ts (1)
text(40-42)
⏰ Context from checks skipped due to timeout of 90000ms. You can increase the timeout in your CodeRabbit configuration to a maximum of 15 minutes (900000ms). (7)
- GitHub Check: Greptile Review
- GitHub Check: 🌐 API Tests
- GitHub Check: pr-description
- GitHub Check: Docker Build Test
- GitHub Check: pr-review
- GitHub Check: check-codex-status
- GitHub Check: dev-build-deploy
🔇 Additional comments (59)
messages/en/settings.json (1)
107-108: 思考签名修复开关文案清晰且与功能一致
enableThinkingSignatureFix及描述准确概括了触发条件(4xx/5xx + 含 thinking/redacted_thinking)、一次性重试以及日志标记行为,命名也与现有config.form.*保持一致,无需调整。messages/en/dashboard.json (1)
131-131: Dashboard 日志表新增 “Fix” 标记键命名与用法一致
logs.table.thinkingSignatureFix命名与现有表格键风格一致,英文短文案 “Fix” 也契合 Badge 样式,便于快速识别触发了思考签名修复的请求。messages/ja/settings.json (1)
105-106: 日文配置文案自然且与功能一致这两条日文文案准确说明了开关行为(4xx/5xx + thinking/redacted_thinking 时去除并单次重试且记录到日志),语气和细节与其他语言版本保持一致,无需调整。
messages/ru/settings.json (1)
105-106: 俄文翻译与设计语义对齐俄文标题和说明完整涵盖了开关含义(触发条件、仅重试一次、专门针对供应商切换时的签名不兼容、并写入审计日志),与功能设计和其他语言版本保持一致,可以直接使用。
messages/zh-CN/settings.json (1)
88-89: 中文配置项文案清晰、信息完整这两个配置项标题和说明准确传达了开关的触发条件、处理方式和审计行为,术语风格与本文件其他条目及多语言版本保持一致,无需修改。
messages/zh-TW/settings.json (1)
105-106: 翻譯文案準確清晰新增的 Thinking 簽名修復功能翻譯準確,描述詳細說明了功能的觸發條件(上游返回 4xx/5xx 且請求包含 thinking/redacted_thinking 區塊)、行為(移除區塊並重試)以及審計追蹤,符合功能設計意圖。
.gitignore (1)
16-16: 正確忽略測試覆蓋率目錄新增的覆蓋率目錄忽略規則與新增的
test:coverage:thinking-signature-fix測試腳本相對應,符合現有的覆蓋率目錄管理模式。messages/zh-TW/dashboard.json (1)
131-131: 表格標籤翻譯簡潔適當新增的
thinkingSignatureFix標籤翻譯為「修復」,簡潔明了,適合在使用記錄表格中作為標記顯示,與功能設計一致。src/lib/validation/schemas.ts (1)
744-745: Schema 擴展正確無誤為
UpdateSystemSettingsSchema新增的enableThinkingSignatureFix可選布爾欄位驗證邏輯清晰,與其他功能開關保持一致,支持系統設定的部分更新,實現合理。src/repository/_shared/transformers.ts (1)
164-164: 轉換邏輯實現正確新增的
enableThinkingSignatureFix欄位轉換邏輯與其他系統設定保持一致,預設值為false(功能預設關閉),符合漸進式功能發布的最佳實踐。package.json (1)
23-23: 新增测试覆盖率脚本符合预期。该脚本遵循了现有覆盖率测试脚本的命名和结构模式,用于针对性测试 thinking-signature-fix 特性。
src/lib/config/index.ts (1)
11-11: 配置导出符合规范。新增的
isThinkingSignatureFixEnabled导出遵循了现有的配置导出模式,为特性开关提供了清晰的公共 API。src/app/v1/_lib/proxy/error-handler.ts (1)
335-340: 审计字段条件注入实现正确。使用条件展开运算符仅在应用了 thinking signature 修复时才添加审计字段,这是一个清晰且高效的模式。实现假设当
getThinkingSignatureFixApplied()返回 true 时,getThinkingSignatureFixReason()必定返回有效值,这应该在 session 层面得到保证。src/app/[locale]/settings/config/page.tsx (1)
44-44: 设置字段传递符合既定模式。新增的
enableThinkingSignatureFix字段遵循了其他系统设置的传递模式,与现有代码结构保持一致。tests/unit/repository/message-write-buffer.test.ts (1)
146-167: 测试覆盖全面且实现正确。该测试用例有效验证了新增审计字段的批量写入功能:
- 测试场景清晰:验证
thinkingSignatureFixApplied和thinkingSignatureFixReason字段能够正确入队并生成相应的 SQL 更新语句- 第 155 行将
thinkingSignatureFixReason设置为 JSON 字符串是正确的,与实际存储格式一致- SQL 断言验证了列名的存在,适用于批量写入场景
drizzle/0047_mute_joystick.sql (1)
1-3: 数据库迁移结构合理。迁移文件正确添加了三个新列:
thinking_signature_fix_applied: 布尔标志,用于审计thinking_signature_fix_reason: 可选文本字段,记录修复原因enable_thinking_signature_fix: 系统级开关字段命名、类型和约束均符合预期,默认值设置为关闭状态符合渐进式发布的最佳实践。
src/repository/system-config.ts (4)
151-151: 后备配置正确设置。在
createFallbackSettings()中正确添加了enableThinkingSignatureFix: false的默认值,与数据库迁移中的默认值保持一致。
176-176: 查询选择字段完整。在
fullSelection中正确添加了enableThinkingSignatureFix字段,确保从数据库读取时包含该配置。
307-310: 更新逻辑遵循现有模式。条件更新逻辑与文件中其他配置字段保持一致,仅在
payload.enableThinkingSignatureFix !== undefined时更新该字段,支持部分更新的设计。
330-330: 返回字段列表完整。在
.returning()子句中正确包含了enableThinkingSignatureFix字段,确保更新后返回最新的配置值。src/app/[locale]/dashboard/logs/_components/usage-logs-table.tsx (1)
221-228: UI 标记正确实现。条件渲染的 Badge 组件实现合理:
- 仅在
log.thinkingSignatureFixApplied为真时显示- 样式与其他 Badge(如成本倍率)保持一致
- 使用紫色主题与其他特殊功能标记(如 1M Context)保持视觉一致性
- 正确使用
shrink-0防止在容器中被压缩代码结构清晰,遵循了现有的 UI 模式。
src/types/system-config.ts (2)
35-36: 类型定义准确。在
SystemSettings接口中添加了必需的enableThinkingSignatureFix: boolean字段,与数据库 schema 中的NOT NULL约束一致。注释清晰说明了该字段的用途。
71-72: 更新接口设计合理。在
UpdateSystemSettingsInput中将enableThinkingSignatureFix定义为可选字段,支持部分更新模式,与文件中其他配置字段保持一致。drizzle/meta/_journal.json (1)
334-340: 迁移日志条目正确。新增的迁移条目遵循现有模式:
- 索引递增正确(46 → 47)
- 版本号与其他条目一致
- 标签与迁移文件名匹配
- 时间戳合理
- 断点标志与其他条目保持一致
元数据结构完整且格式正确。
src/app/v1/_lib/proxy/forwarder.ts (1)
13-14: thinking/signature 修复重试路径整体设计合理,满足“最小降级 + 可审计”目标
- 仅在
!response.ok且开启enableThinkingSignatureFix,并且解析出的请求体经sanitizeClaudeMessagesRequestThinkingBlocks确认实际移除了thinking/redacted_thinking块时才进入重试,符合“有问题才动手”的设计。- 对 401/402/403/404/429 使用排除列表直接短路,避免掩盖鉴权、配额、路由类真实问题,这里的注释也把语义解释得很清楚。
- 重试时重新挂上响应超时定时器,并在
retryResponse.ok分支下为session填充clearResponseTimeout/responseController,让response-handler能透明接管后续生命周期,保持与普通成功路径一致。- 通过
session.setThinkingSignatureFixApplied记录触发状态、移除块数量、原始错误和策略(命中过滤规则 vs 仅靠状态码保守兜底),为后续 DB 审计字段和前端 “Fix” 标记提供了充分上下文,链路清晰。整体看,这段逻辑与外层重试/熔断状态机衔接良好,没有明显的重试风暴或隐藏错误风险,属于可以放心合入的变更。
Also applies to: 43-46, 1648-1773
src/repository/message.ts (1)
135-137: 消息请求扩展字段对接思考签名修复审计信息是正确的在
updateMessageRequestDetails中新增thinkingSignatureFixApplied/thinkingSignatureFixReason两个可选字段,并在构造updateData时仅在字段非undefined时写入,既与message_request表中新列保持一致,也避免在未触发修复时反复更新列值。这与上层通过 session 条件打补丁的用法是对齐的。Also applies to: 196-201
src/app/v1/_lib/proxy/response-handler.ts (1)
58-70: 统一的getThinkingSignatureFixAuditPatch有效消除了重复并保证审计信息在各路径上一致落盘
- 帮助函数通过
session.getThinkingSignatureFixApplied/Reason决定是否附加thinkingSignatureFixApplied/thinkingSignatureFixReason,未触发修复时返回空对象,避免无意义更新。- 在非流正常完成、非流提前终止、流式完成、抽象的
finalizeRequestStats以及persistRequestFailure多个路径中统一...getThinkingSignatureFixAuditPatch(session),可以确保无论请求成功、失败还是在后台统计阶段出错,只要前面走过修复重试逻辑,对应的审计信息都会写入message_request。- 与
message.ts中的新字段和usage-logs.ts的查询结构配合后,上游 ProxySession → DB → 仪表盘 Logs 的审计链路是闭合的。这部分实现没有逻辑漏洞,看起来可以直接合入。
Also applies to: 247-258, 393-409, 1765-1772, 1839-1854, 1978-1989
src/lib/config/system-settings-cache.ts (1)
27-34: 系统设置缓存对enableThinkingSignatureFix的扩展符合现有模式
- 在
DEFAULT_SETTINGS与getCachedSystemSettings的 fallback 返回值中新增enableThinkingSignatureFix: false,保持了“读失败时 fail-open 到安全默认值”的既有约定。- 新增的
isThinkingSignatureFixEnabled()复用缓存读路径,与isHttp2Enabled()对称,使代理层可以在热路径上按布尔值快速判断是否启用修复逻辑,而无需关心完整SystemSettings结构。整体实现简单直接,没有发现行为风险。
Also applies to: 80-96, 110-118
src/repository/usage-logs.ts (1)
30-63: UsageLogRow 增加思考签名修复审计字段且已在查询层完整贯通
UsageLogRow接口中新增thinkingSignatureFixApplied/thinkingSignatureFixReason,并在两种查询入口(游标分页的findUsageLogsBatch与详情版findUsageLogsWithDetails)里从messageRequest显式选出对应列,最终通过...row映射到返回结果,保证仪表盘/前端可以直接消费这两个审计字段。- 新字段不参与任何聚合统计或
totalTokens计算,只作为额外的可视化/排障信息输出,避免了对现有统计口径的影响。实现与上游仓储和前端用法对齐,没有发现问题。
Also applies to: 188-222, 405-437
tests/unit/repository/usage-logs-thinking-signature-fix-columns.test.ts (3)
3-16: 辅助函数实现合理
createThenableQuery辅助函数很好地模拟了 Drizzle 查询构建器的链式调用模式,使测试能够验证字段选择而无需真实数据库连接。
19-43: findUsageLogsBatch 测试实现正确测试正确验证了
findUsageLogsBatch的 select 调用包含thinkingSignatureFixApplied和thinkingSignatureFixReason字段。使用vi.resetModules()和动态导入确保了模拟的正确隔离。
45-92: findUsageLogsWithDetails 测试实现合理测试通过队列模拟两次 select 调用(summary 和 logs),并验证第二次调用包含审计字段。虽然这依赖于实现细节(select 调用顺序),但注释已清楚说明约定,且这是验证字段选择的合理方式。
src/repository/message-write-buffer.ts (2)
29-31: 审计字段定义清晰准确新增的
thinkingSignatureFixApplied和thinkingSignatureFixReason字段定义合理:
- 字段设为可选,仅在触发修复时才会被设置,避免不必要的数据写入
- 注释清楚说明了字段用途和默认值策略
- 类型定义与数据库 schema 保持一致
64-65: 列映射配置正确列名映射遵循现有模式,camelCase 到 snake_case 的转换与其他字段保持一致。
src/drizzle/schema.ts (2)
320-322: message_request 审计字段设计合理新增的审计字段设计合理:
thinkingSignatureFixApplied使用NOT NULL+default(false)简化查询逻辑,避免处理 null 值thinkingSignatureFixReason设为可空,适合存储可选的元数据信息- 注释清晰说明字段用途
- 未添加索引符合审计字段的使用场景(主要用于展示和审计,非主查询条件)
485-486: 系统设置开关定义正确
enableThinkingSignatureFix使用NOT NULL+default(false)确保:
- 功能默认关闭,符合保守策略
- 不需要处理 null 值的边界情况
- 与现有系统设置字段模式保持一致
drizzle/meta/0047_snapshot.json (1)
504-516: Drizzle 快照正确生成该快照文件由 drizzle-kit 自动生成,正确反映了 schema 变更:
message_request.thinking_signature_fix_applied和thinking_signature_fix_reasonsystem_settings.enable_thinking_signature_fix类型定义和约束与 schema.ts 一致。
Also applies to: 1914-1920
src/actions/system-config.ts (1)
41-41: 系统设置扩展实现正确
enableThinkingSignatureFix新设置的集成遵循现有模式:
- 字段为可选,支持部分更新
- 通过 Zod schema 进行验证
- 正确传递给
updateSystemSettings进行持久化- 缓存失效机制确保代理请求获取最新配置
Also applies to: 63-63
src/app/[locale]/settings/config/_components/system-settings-form.tsx (5)
23-35: 类型定义正确。新增的
enableThinkingSignatureFix字段已正确添加到SystemSettingsFormProps的initialSettings类型中,遵循了现有设置的模式。
58-60: 状态管理实现正确。新增的
enableThinkingSignatureFix状态管理遵循了现有布尔设置的模式,从initialSettings正确初始化。
71-81: 表单提交逻辑正确。新设置已正确包含在
saveSystemSettings调用的 payload 中,与其他设置保持一致。
88-97: 服务器响应同步正确。成功保存后,本地状态正确地从服务器响应中更新,确保了 UI 与后端的一致性。
224-239: UI 实现符合规范。新增的开关控件完全遵循了现有设置项的模式,包括:
- 正确的标签关联(
htmlFor与id匹配)- 国际化翻译键的使用
- 禁用状态的正确绑定
tests/unit/proxy/thinking-signature-recovery.test.ts (1)
9-50: 错误识别测试覆盖全面。测试用例很好地覆盖了:
- 不同格式的 "Invalid signature" 错误消息(有/无
messages前缀)- 不稳定的状态码场景(4xx 和 5xx)
- "cannot be modified" 错误模式
- 负面测试用例(非 ProxyError 类型、不相关的错误消息)
这些测试与实现代码中的错误检测逻辑保持一致。
src/app/api/admin/system-config/route.ts (2)
30-49: API 文档更新正确。JSDoc 注释已更新,包含了新增的六个可选字段,包括
enableThinkingSignatureFix,与实际实现保持一致。
64-78: 系统设置更新逻辑正确。新增的六个字段(包括
enableThinkingSignatureFix)已正确地:
- 通过
UpdateSystemSettingsSchema验证- 从
validated对象中提取- 传递给
updateSystemSettings函数实现遵循了现有字段的模式。
vitest.thinking-signature-fix.config.ts (3)
11-21: 测试环境配置正确。测试配置合理地:
- 使用 Node 环境(适合代理逻辑测试)
- 通过
include精确定位两个相关测试文件- 排除了标准的构建和集成测试目录
23-37: 覆盖率配置策略合理。针对关键的故障恢复逻辑设置了更高的覆盖率阈值(80%/80%/70%/80%),这是一个良好的实践。通过只包含
thinking-signature-recovery.ts文件,避免了大文件(如forwarder.ts)导致的指标失真。
39-52: 测试配置选项符合最佳实践。测试隔离和 mock 清理选项(
isolate,mockReset,restoreMocks,clearMocks)确保了测试之间的独立性,路径别名配置与项目结构一致。tests/unit/proxy/proxy-forwarder-thinking-signature-recovery.test.ts (6)
1-101: 测试辅助函数实现合理。Mock 配置和辅助函数设计良好:
isThinkingSignatureFixEnabledMock允许在测试中控制功能开关createSession支持可选的 thinking 块包含(通过includeThinkingBlocks参数)createClaudeProvider创建完整的 Provider 对象用于测试这些辅助函数为后续测试用例提供了灵活的基础。
104-161: 重试逻辑测试全面且准确。此测试用例完整地验证了 thinking signature 修复的核心流程:
- ✅ 第一次请求包含 thinking 块,返回 400 错误
- ✅ 第二次请求移除了 thinking 块,返回成功
- ✅ 会话状态正确标记了修复操作(
getThinkingSignatureFixApplied)- ✅ 响应超时清理钩子正确附加到会话对象
测试覆盖了功能的关键行为路径。
163-210: 5xx 错误回退测试正确。此测试验证了即使错误消息不明确包含 "Invalid signature",只要请求包含 thinking 块且上游返回 5xx 错误,系统仍会尝试移除 thinking 块并重试。这覆盖了 PR 目标中提到的"错误码不稳定"场景。
212-246: 功能开关测试正确。此测试验证了当
enableThinkingSignatureFix关闭时,即使遇到相关错误也不会触发重试,确保了功能开关的有效性。
248-278: 排除状态码测试关键且正确。此测试使用参数化测试验证了 401/402/403/404/429 等关键错误码不会触发重试。这是一个重要的安全考虑,确保了认证、配额和限流错误不会被掩盖。测试实现清晰且全面。
280-308: 无 thinking 块场景测试正确。此测试验证了当请求不包含 thinking 或 redacted_thinking 块时,即使功能开启且遇到错误,也不会触发不必要的重试。这避免了对无关请求的性能影响。
src/app/v1/_lib/proxy/session.ts (1)
96-99: LGTM!审计字段设计合理,私有字段配合公共访问器的模式与类中其他属性保持一致(如
cacheTtlResolved、context1mApplied)。src/app/v1/_lib/proxy/thinking-signature-recovery.ts (3)
3-7: LGTM!类型定义简洁明了,包含了调用方所需的全部信息:处理后的对象、是否有变化、以及移除的块数量。
18-42: LGTM!错误检测逻辑设计合理:
- 类型和状态码校验提供了基本防护
- 关键词匹配覆盖了两种典型错误模式
- 多信号组合(
hasContentIndex && hasInvalid && hasSignature && hasThinking)降低了误判风险- 注释清晰说明了设计意图和不稳定的上游错误格式
52-101: LGTM!清理函数实现得很好:
- 最小侵入性:仅移除
thinking和redacted_thinking块,不影响其他内容- 引用保留优化:未发生变化时返回原对象引用,避免不必要的对象创建
- 纯函数设计:不修改输入参数,通过浅拷贝创建新对象
- 健壮的类型处理:正确处理各种边界情况(非数组、非对象等)
There was a problem hiding this comment.
Code Review Summary
No significant issues identified in this PR.
PR Size: XL
- Lines changed: 3454
- Files changed: 42
- Split suggestions: Split into (1) proxy recovery core, (2) DB schema/migration, (3) UI + i18n, (4) tests + Vitest config.
Review Coverage
- Logic and correctness - Clean
- Security (OWASP Top 10) - Clean
- Error handling - Clean
- Type safety - Clean
- Documentation accuracy - Clean
- Test coverage - Adequate
- Code clarity - Good
Automated review by Codex AI
There was a problem hiding this comment.
- Reviewed PR
#540(headpull/540/merge) across all changed files/lines. - Applied PR size label:
size/XL. - Submitted a review comment via
gh pr reviewusing the “No significant issues identified” summary format (no inline comments posted since nothing met the reporting threshold).
|
Greptile encountered an error while reviewing this PR. Please reach out to support@greptile.com for assistance. |
Summary
Adds an optional thinking signature recovery mechanism that automatically strips
thinking/redacted_thinkingblocks from requests and retries when upstream providers return 4xx/5xx errors related to signature incompatibility. This prevents sessions from entering unrecoverable error loops when switching between different provider types.Problem
Related Issues:
signatureinthinkingblock #518 - Expands on the error rule approach with automatic recoveryWhen users switch between Anthropic and non-Anthropic providers (e.g., AWS Bedrock), the
thinkingblocks may contain signatures that are incompatible with the target provider. This results in errors like:Invalid \signature` in `thinking` block`thinking blocks cannot be modifiedPreviously, these errors would cause the session to enter an unrecoverable 4xx/5xx error loop. PR #519 added an error rule to provide better error messages, but this PR goes further by implementing automatic recovery.
Solution
enableThinkingSignatureFix): Disabled by default to ensure opt-in behaviorisThinkingSignatureRelatedError()sanitizeClaudeMessagesRequestThinkingBlocks()removes onlythinking/redacted_thinkingcontent blocksthinking_signature_fix_appliedandthinking_signature_fix_reasonfor observabilityChanges
Core Changes
src/app/v1/_lib/proxy/thinking-signature-recovery.ts- New module for error detection and request sanitizationsrc/app/v1/_lib/proxy/forwarder.ts- Integrates recovery logic into the proxy pipelinesrc/app/v1/_lib/proxy/session.ts- Adds state tracking for fix applicationsrc/app/v1/_lib/proxy/response-handler.ts- Writes audit fields on response completionsrc/app/v1/_lib/proxy/error-handler.ts- Minor integration updatesDatabase Migration
drizzle/0047_mute_joystick.sql- Adds three columns:message_request.thinking_signature_fix_applied(boolean)message_request.thinking_signature_fix_reason(text)system_settings.enable_thinking_signature_fix(boolean)Configuration & UI
src/lib/config/system-settings-cache.ts- ExportsisThinkingSignatureFixEnabled()src/lib/validation/schemas.ts- Adds schema validation for new settingsrc/actions/system-config.ts- Server action updatessrc/app/[locale]/settings/config/_components/system-settings-form.tsx- Toggle in settings UIsrc/app/[locale]/dashboard/logs/_components/usage-logs-table.tsx- "Fix" badge in logs viewi18n
messages/*/settings.jsonandmessages/*/dashboard.jsonTests
tests/unit/proxy/thinking-signature-recovery.test.ts- Core detection/sanitization logictests/unit/proxy/proxy-forwarder-thinking-signature-recovery.test.ts- Integration teststests/unit/repository/message-write-buffer.test.ts- Audit field persistencetests/unit/repository/usage-logs-thinking-signature-fix-columns.test.ts- Query/display teststests/unit/dashboard-logs-thinking-signature-fix-ui.test.tsx- UI component teststests/unit/validation/system-settings-thinking-signature-fix-schema.test.ts- Schema validationBreaking Changes
None. The feature is disabled by default and must be explicitly enabled in system settings.
Testing
Automated Tests
Manual Testing
Checklist
bun run test,bun run test:coverage:thinking-signature-fix)bun run typecheck)bun run lint)bun run build)Description enhanced by Claude AI