Conversation
📝 WalkthroughWalkthrough新增 specialSettings 类型与构建工具,扩展消息审计查询并在会话与使用日志路径合并 Redis/审计字段生成统一 specialSettings;前端将该数据传递给错误详情对话框,日志表中部分行内的 specialSettings 徽章被移除;补充相关单元测试覆盖(合并、去重、渲染)。 Changes
Estimated code review effort🎯 3 (Moderate) | ⏱️ ~25 minutes Possibly related PRs
🚥 Pre-merge checks | ✅ 2 | ❌ 1❌ Failed checks (1 warning)
✅ Passed checks (2 passed)
✏️ Tip: You can configure your own custom pre-merge checks in the settings. ✨ Finishing touches
🧪 Generate unit tests (beta)
📜 Recent review detailsConfiguration used: Organization UI Review profile: CHILL Plan: Pro Cache: Disabled due to Reviews > Disable Cache setting 📒 Files selected for processing (4)
💤 Files with no reviewable changes (1)
🧰 Additional context used📓 Path-based instructions (4)**/*.{js,ts,tsx,jsx}📄 CodeRabbit inference engine (CLAUDE.md)
Files:
**/*.{ts,tsx,jsx,js}📄 CodeRabbit inference engine (CLAUDE.md)
Files:
**/*.test.{ts,tsx,js,jsx}📄 CodeRabbit inference engine (CLAUDE.md)
Files:
**/*.{tsx,jsx}📄 CodeRabbit inference engine (CLAUDE.md)
Files:
🧠 Learnings (3)📚 Learning: 2026-01-05T03:02:06.594ZApplied to files:
📚 Learning: 2026-01-07T17:05:36.362ZApplied to files:
📚 Learning: 2026-01-07T17:05:36.362ZApplied to files:
🧬 Code graph analysis (1)tests/unit/dashboard-logs-virtualized-special-settings-ui.test.tsx (2)
⏰ 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). (3)
🔇 Additional comments (4)
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! 此拉取请求旨在标准化应用程序中请求相关“特殊设置”的展示方式。通过整合来自不同数据源(如 Redis 和数据库)的各种审计字段,将其统一为一致的 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
本次变更通过引入 buildUnifiedSpecialSettings 工具函数,统一了来自数据库和 Redis 的 specialSettings 数据源,逻辑清晰,结构良好。新的 specialSettings 类型定义和相应的后端数据获取逻辑修改都很到位。前端在日志表格中增加了 Special 标记,并透传了数据,实现了端到端的展示。此外,为新功能增加了全面的单元测试和 UI 测试,保证了代码质量。
我发现了一些可以改进的地方,主要涉及去重逻辑中的一个潜在 bug 和一些代码可读性优化,具体请看我的评论。
| function buildSettingKey(setting: SpecialSetting): string { | ||
| switch (setting.type) { | ||
| case "provider_parameter_override": | ||
| return [ | ||
| setting.type, | ||
| setting.providerId ?? "null", | ||
| setting.providerType ?? "null", | ||
| setting.hit ? "1" : "0", | ||
| setting.changed ? "1" : "0", | ||
| ].join(":"); | ||
| case "response_fixer": | ||
| return [ | ||
| setting.type, | ||
| setting.hit ? "1" : "0", | ||
| setting.fixersApplied | ||
| .map((f) => `${f.fixer}=${f.applied ? "1" : "0"}`) | ||
| .sort() | ||
| .join(","), | ||
| ].join(":"); | ||
| case "guard_intercept": | ||
| return [ | ||
| setting.type, | ||
| setting.guard, | ||
| setting.action, | ||
| setting.statusCode ?? "null", | ||
| setting.reason ?? "null", | ||
| ].join(":"); | ||
| case "anthropic_cache_ttl_header_override": | ||
| return [setting.type, setting.ttl].join(":"); | ||
| case "anthropic_context_1m_header_override": | ||
| return [setting.type, setting.flag].join(":"); | ||
| default: { | ||
| // 兜底:保证即使未来扩展类型也不会导致运行时崩溃 | ||
| const _exhaustive: never = setting; | ||
| return JSON.stringify(_exhaustive); | ||
| } | ||
| } | ||
| } |
There was a problem hiding this comment.
当前的 buildSettingKey 实现中,使用 ?? "null" 来处理 null 值,当属性的字符串值恰好是 "null" 时,会产生哈希碰撞,导致去重逻辑错误。例如,reason: null 和 reason: 'null' 会生成相同的 key。建议直接使用 Array.prototype.join 的默认行为,它会将 null 和 undefined 转换为空字符串,从而避免此问题。
function buildSettingKey(setting: SpecialSetting): string {
switch (setting.type) {
case "provider_parameter_override":
return [
setting.type,
setting.providerId,
setting.providerType,
setting.hit ? "1" : "0",
setting.changed ? "1" : "0",
].join(":");
case "response_fixer":
return [
setting.type,
setting.hit ? "1" : "0",
setting.fixersApplied
.map((f) => `${f.fixer}=${f.applied ? "1" : "0"}`)
.sort()
.join(","),
].join(":");
case "guard_intercept":
return [
setting.type,
setting.guard,
setting.action,
setting.statusCode,
setting.reason,
].join(":");
case "anthropic_cache_ttl_header_override":
return [setting.type, setting.ttl].join(":");
case "anthropic_context_1m_header_override":
return [setting.type, setting.flag].join(":");
default: {
// 兜底:保证即使未来扩展类型也不会导致运行时崩溃
const _exhaustive: never = setting;
return JSON.stringify(_exhaustive);
}
}
}
src/actions/active-sessions.ts
Outdated
| const { findMessageRequestAuditBySessionIdAndSequence } = await import("@/repository/message"); | ||
|
|
||
| const { findAdjacentRequestSequences } = await import("@/repository/message"); |
There was a problem hiding this comment.
为了代码简洁和避免重复导入,可以将来自同一模块的动态导入合并为一条语句。
| const { findMessageRequestAuditBySessionIdAndSequence } = await import("@/repository/message"); | |
| const { findAdjacentRequestSequences } = await import("@/repository/message"); | |
| const { findMessageRequestAuditBySessionIdAndSequence, findAdjacentRequestSequences } = | |
| await import("@/repository/message"); |
src/actions/active-sessions.ts
Outdated
| const existingSpecialSettings: SpecialSetting[] | null = (() => { | ||
| const merged = [ | ||
| ...(Array.isArray(redisSpecialSettings) ? redisSpecialSettings : []), | ||
| ...(Array.isArray(requestAudit?.specialSettings) ? requestAudit.specialSettings : []), | ||
| ]; | ||
| return merged.length > 0 ? merged : null; | ||
| })(); |
There was a problem hiding this comment.
这个立即执行函数表达式(IIFE)使代码稍微有些复杂。可以将其重构为几个简单的常量声明,以提高可读性。
const mergedSpecialSettings = [
...(Array.isArray(redisSpecialSettings) ? redisSpecialSettings : []),
...(Array.isArray(requestAudit?.specialSettings) ? requestAudit.specialSettings : []),
];
const existingSpecialSettings = mergedSpecialSettings.length > 0 ? mergedSpecialSettings : null;
src/lib/utils/special-settings.ts
Outdated
| if (params.context1mApplied) { | ||
| derived.push({ | ||
| type: "anthropic_context_1m_header_override", | ||
| scope: "request_header", | ||
| hit: true, | ||
| header: "anthropic-beta", | ||
| flag: CONTEXT_1M_BETA_HEADER, | ||
| }); | ||
| } |
There was a problem hiding this comment.
The condition if (params.context1mApplied) only adds the setting when context1mApplied is true. However, based on the type signature on line 28 (context1mApplied?: boolean | null), this means:
- When
context1mAppliedisfalse, no setting is added (expected behavior) - When
context1mAppliedisnull, no setting is added (expected behavior) - When
context1mAppliedistrue, the setting IS added (expected behavior)
This is actually correct as is. The issue is that unlike the other two conditions (if (params.blockedBy) and if (params.cacheTtlApplied) which check truthiness), the context1m condition explicitly checks for boolean true - which is the correct behavior since we need to distinguish between "not applied" (false) and "no data" (null). However, for consistency with the other two conditions that derive settings, this should use explicit null checking instead of relying on truthiness:
| if (params.context1mApplied) { | |
| derived.push({ | |
| type: "anthropic_context_1m_header_override", | |
| scope: "request_header", | |
| hit: true, | |
| header: "anthropic-beta", | |
| flag: CONTEXT_1M_BETA_HEADER, | |
| }); | |
| } | |
| if (params.context1mApplied === true) { | |
| derived.push({ | |
| type: "anthropic_context_1m_header_override", | |
| scope: "request_header", | |
| hit: true, | |
| header: "anthropic-beta", | |
| flag: CONTEXT_1M_BETA_HEADER, | |
| }); | |
| } |
This makes the intention clearer - we only want to add this setting when the flag is explicitly set to true, not just truthy.
Note: If this suggestion doesn't match your team's coding style, reply to this and let me know. I'll remember it for next time!
Prompt To Fix With AI
This is a comment left during a code review.
Path: src/lib/utils/special-settings.ts
Line: 106:114
Comment:
The condition `if (params.context1mApplied)` only adds the setting when `context1mApplied` is `true`. However, based on the type signature on line 28 (`context1mApplied?: boolean | null`), this means:
- When `context1mApplied` is `false`, no setting is added (expected behavior)
- When `context1mApplied` is `null`, no setting is added (expected behavior)
- When `context1mApplied` is `true`, the setting IS added (expected behavior)
This is actually correct as is. The issue is that unlike the other two conditions (`if (params.blockedBy)` and `if (params.cacheTtlApplied)` which check truthiness), the context1m condition explicitly checks for boolean `true` - which is the correct behavior since we need to distinguish between "not applied" (`false`) and "no data" (`null`). However, for consistency with the other two conditions that derive settings, this should use explicit null checking instead of relying on truthiness:
```suggestion
if (params.context1mApplied === true) {
derived.push({
type: "anthropic_context_1m_header_override",
scope: "request_header",
hit: true,
header: "anthropic-beta",
flag: CONTEXT_1M_BETA_HEADER,
});
}
```
This makes the intention clearer - we only want to add this setting when the flag is explicitly set to `true`, not just truthy.
<sub>Note: If this suggestion doesn't match your team's coding style, reply to this and let me know. I'll remember it for next time!</sub>
How can I resolve this? If you propose a fix, please make it concise.| const seen = new Set<string>(); | ||
| const result: SpecialSetting[] = []; | ||
| for (const item of [...base, ...derived]) { | ||
| const key = buildSettingKey(item); | ||
| if (seen.has(key)) continue; | ||
| seen.add(key); | ||
| result.push(item); | ||
| } |
There was a problem hiding this comment.
The deduplication logic assumes that if two settings have the same buildSettingKey() result, they are duplicates and should be deduplicated. However, there's a subtle issue with the guard_intercept type deduplication.
Consider this scenario:
existingcontains:{ type: "guard_intercept", guard: "warmup", action: "intercept_response", statusCode: 200, reason: "original_reason" }params.blockedBy: "warmup",params.blockedReason: "different_reason",params.statusCode: 200
The buildSettingKey for guard_intercept (line 51-57) uses the reason field in the key, so:
- existing key:
"guard_intercept:warmup:intercept_response:200:original_reason" - derived key:
"guard_intercept:warmup:intercept_response:200:different_reason"
These have different keys, so both would be included! This violates the intention to deduplicate.
The issue is that the reason field (which contains JSON string like {"reason": "..."}) is being used in the deduplication key. If the same guard intercepts a request multiple times with different reasons, they would all be kept rather than deduplicated.
A better approach would be to not include the reason in the deduplication key, or to normalize the reason data before comparison:
| const seen = new Set<string>(); | |
| const result: SpecialSetting[] = []; | |
| for (const item of [...base, ...derived]) { | |
| const key = buildSettingKey(item); | |
| if (seen.has(key)) continue; | |
| seen.add(key); | |
| result.push(item); | |
| } | |
| case "guard_intercept": | |
| return [ | |
| setting.type, | |
| setting.guard, | |
| setting.action, | |
| setting.statusCode ?? "null", | |
| // Excluded: reason | |
| ].join(":"); |
Or if you want to keep the reason, at least normalize it by parsing the JSON first to make the comparison more robust.
Prompt To Fix With AI
This is a comment left during a code review.
Path: src/lib/utils/special-settings.ts
Line: 120:127
Comment:
The deduplication logic assumes that if two settings have the same `buildSettingKey()` result, they are duplicates and should be deduplicated. However, there's a subtle issue with the guard_intercept type deduplication.
Consider this scenario:
1. `existing` contains: `{ type: "guard_intercept", guard: "warmup", action: "intercept_response", statusCode: 200, reason: "original_reason" }`
2. `params.blockedBy: "warmup"`, `params.blockedReason: "different_reason"`, `params.statusCode: 200`
The buildSettingKey for guard_intercept (line 51-57) uses the `reason` field in the key, so:
- existing key: `"guard_intercept:warmup:intercept_response:200:original_reason"`
- derived key: `"guard_intercept:warmup:intercept_response:200:different_reason"`
These have different keys, so both would be included! This violates the intention to deduplicate.
The issue is that the `reason` field (which contains JSON string like `{"reason": "..."}`) is being used in the deduplication key. If the same guard intercepts a request multiple times with different reasons, they would all be kept rather than deduplicated.
A better approach would be to not include the reason in the deduplication key, or to normalize the reason data before comparison:
```suggestion
case "guard_intercept":
return [
setting.type,
setting.guard,
setting.action,
setting.statusCode ?? "null",
// Excluded: reason
].join(":");
```
Or if you want to keep the reason, at least normalize it by parsing the JSON first to make the comparison more robust.
How can I resolve this? If you propose a fix, please make it concise.
src/actions/active-sessions.ts
Outdated
| const existingSpecialSettings: SpecialSetting[] | null = (() => { | ||
| const merged = [ | ||
| ...(Array.isArray(redisSpecialSettings) ? redisSpecialSettings : []), | ||
| ...(Array.isArray(requestAudit?.specialSettings) ? requestAudit.specialSettings : []), | ||
| ]; | ||
| return merged.length > 0 ? merged : null; | ||
| })(); | ||
|
|
||
| const unifiedSpecialSettings = buildUnifiedSpecialSettings({ | ||
| existing: existingSpecialSettings, | ||
| blockedBy: requestAudit?.blockedBy ?? null, | ||
| blockedReason: requestAudit?.blockedReason ?? null, | ||
| statusCode: requestAudit?.statusCode ?? null, | ||
| cacheTtlApplied: requestAudit?.cacheTtlApplied ?? null, | ||
| context1mApplied: requestAudit?.context1mApplied ?? null, | ||
| }); |
There was a problem hiding this comment.
The code merges redisSpecialSettings and requestAudit?.specialSettings into existingSpecialSettings, then passes this to buildUnifiedSpecialSettings. However, there's a potential issue with the merge strategy.
Looking at lines 656-662:
const existingSpecialSettings: SpecialSetting[] | null = (() => {
const merged = [
...(Array.isArray(redisSpecialSettings) ? redisSpecialSettings : []),
...(Array.isArray(requestAudit?.specialSettings) ? requestAudit.specialSettings : []),
];
return merged.length > 0 ? merged : null;
})();This concatenates Redis settings and DB settings without deduplication. Then buildUnifiedSpecialSettings is called with this merged array as the existing parameter (line 665).
The issue is that if the same special setting exists in both Redis and DB (which can happen if data is cached in both places), buildUnifiedSpecialSettings will see duplicates in the existing array. The buildSettingKey and deduplication logic (lines 120-127) should handle this, but it's redundant to have the same data in both places.
More critically, if you look at the deduplication in buildUnifiedSpecialSettings (line 124), it uses a Set with buildSettingKey(). This means:
- If Redis and DB have the same setting, they will be deduplicated ✓
- BUT if they have slightly different data (e.g., different
reasonfield in guard_intercept), they might both appear ✗
This isn't necessarily a bug, but it's a subtle edge case. Consider adding a comment explaining this expected behavior, or consider normalizing the data before merging.
Note: If this suggestion doesn't match your team's coding style, reply to this and let me know. I'll remember it for next time!
Prompt To Fix With AI
This is a comment left during a code review.
Path: src/actions/active-sessions.ts
Line: 656:671
Comment:
The code merges `redisSpecialSettings` and `requestAudit?.specialSettings` into `existingSpecialSettings`, then passes this to `buildUnifiedSpecialSettings`. However, there's a potential issue with the merge strategy.
Looking at lines 656-662:
```typescript
const existingSpecialSettings: SpecialSetting[] | null = (() => {
const merged = [
...(Array.isArray(redisSpecialSettings) ? redisSpecialSettings : []),
...(Array.isArray(requestAudit?.specialSettings) ? requestAudit.specialSettings : []),
];
return merged.length > 0 ? merged : null;
})();
```
This concatenates Redis settings and DB settings without deduplication. Then `buildUnifiedSpecialSettings` is called with this merged array as the `existing` parameter (line 665).
The issue is that if the same special setting exists in both Redis and DB (which can happen if data is cached in both places), `buildUnifiedSpecialSettings` will see duplicates in the `existing` array. The `buildSettingKey` and deduplication logic (lines 120-127) should handle this, but it's redundant to have the same data in both places.
More critically, if you look at the deduplication in `buildUnifiedSpecialSettings` (line 124), it uses a Set with `buildSettingKey()`. This means:
- If Redis and DB have the same setting, they will be deduplicated ✓
- BUT if they have slightly different data (e.g., different `reason` field in guard_intercept), they might both appear ✗
This isn't necessarily a bug, but it's a subtle edge case. Consider adding a comment explaining this expected behavior, or consider normalizing the data before merging.
<sub>Note: If this suggestion doesn't match your team's coding style, reply to this and let me know. I'll remember it for next time!</sub>
How can I resolve this? If you propose a fix, please make it concise.| const unifiedSpecialSettings = buildUnifiedSpecialSettings({ | ||
| existing: row.specialSettings as SpecialSetting[] | null, | ||
| blockedBy: row.blockedBy, | ||
| blockedReason: row.blockedReason, | ||
| statusCode: row.statusCode, | ||
| cacheTtlApplied: row.cacheTtlApplied, | ||
| context1mApplied: row.context1mApplied, | ||
| }); |
There was a problem hiding this comment.
In the findUsageLogsBatch function, buildUnifiedSpecialSettings is called with parameters derived from a database row. However, the issue is that row.specialSettings is cast to SpecialSetting[] | null without validation:
const unifiedSpecialSettings = buildUnifiedSpecialSettings({
existing: row.specialSettings as SpecialSetting[] | null,
blockedBy: row.blockedBy,
blockedReason: row.blockedReason,
statusCode: row.statusCode,
cacheTtlApplied: row.cacheTtlApplied,
context1mApplied: row.context1mApplied,
});If row.specialSettings is malformed JSON data from the database (e.g., invalid structure), the cast will silently allow invalid data to pass through. This could cause issues downstream when the UI tries to render the specialSettings.
The same issue exists in findUsageLogsWithDetails (line 461-468) and in virtualized-logs-table.tsx where the data is used.
While this is primarily a data integrity issue (bad data in the DB), it's worth considering adding runtime validation:
| const unifiedSpecialSettings = buildUnifiedSpecialSettings({ | |
| existing: row.specialSettings as SpecialSetting[] | null, | |
| blockedBy: row.blockedBy, | |
| blockedReason: row.blockedReason, | |
| statusCode: row.statusCode, | |
| cacheTtlApplied: row.cacheTtlApplied, | |
| context1mApplied: row.context1mApplied, | |
| }); | |
| const existingSettings = Array.isArray(row.specialSettings) | |
| ? (row.specialSettings as SpecialSetting[]) | |
| : null; | |
| const unifiedSpecialSettings = buildUnifiedSpecialSettings({ | |
| existing: existingSettings, | |
| blockedBy: row.blockedBy, | |
| blockedReason: row.blockedReason, | |
| statusCode: row.statusCode, | |
| cacheTtlApplied: row.cacheTtlApplied, | |
| context1mApplied: row.context1mApplied, | |
| }); |
This adds a simple runtime check that specialSettings is actually an array before treating it as such.
Prompt To Fix With AI
This is a comment left during a code review.
Path: src/repository/usage-logs.ts
Line: 245:252
Comment:
In the `findUsageLogsBatch` function, `buildUnifiedSpecialSettings` is called with parameters derived from a database row. However, the issue is that `row.specialSettings` is cast to `SpecialSetting[] | null` without validation:
```typescript
const unifiedSpecialSettings = buildUnifiedSpecialSettings({
existing: row.specialSettings as SpecialSetting[] | null,
blockedBy: row.blockedBy,
blockedReason: row.blockedReason,
statusCode: row.statusCode,
cacheTtlApplied: row.cacheTtlApplied,
context1mApplied: row.context1mApplied,
});
```
If `row.specialSettings` is malformed JSON data from the database (e.g., invalid structure), the cast will silently allow invalid data to pass through. This could cause issues downstream when the UI tries to render the specialSettings.
The same issue exists in `findUsageLogsWithDetails` (line 461-468) and in `virtualized-logs-table.tsx` where the data is used.
While this is primarily a data integrity issue (bad data in the DB), it's worth considering adding runtime validation:
```suggestion
const existingSettings = Array.isArray(row.specialSettings)
? (row.specialSettings as SpecialSetting[])
: null;
const unifiedSpecialSettings = buildUnifiedSpecialSettings({
existing: existingSettings,
blockedBy: row.blockedBy,
blockedReason: row.blockedReason,
statusCode: row.statusCode,
cacheTtlApplied: row.cacheTtlApplied,
context1mApplied: row.context1mApplied,
});
```
This adds a simple runtime check that `specialSettings` is actually an array before treating it as such.
How can I resolve this? If you propose a fix, please make it concise.There was a problem hiding this comment.
Actionable comments posted: 1
🤖 Fix all issues with AI agents
In @tests/unit/dashboard-logs-virtualized-special-settings-ui.test.tsx:
- Around line 136-162: Replace all Chinese characters in the test file: change
the test suite and test case names in describe("VirtualizedLogsTable -
specialSettings 展示") and test("当 log.specialSettings 存在时应显示 Special 标记") to
English, update the waitForText error message throw new Error(`等待文本超时: ${text}`)
to an English message, and convert any Chinese inline comments (e.g., the
comment before waitForText and the comment about waiting for first-screen data)
into English; ensure any user-visible asserted strings remain appropriate (use
i18n where required) and keep function names like waitForText, renderWithIntl,
flushMicrotasks, and VirtualizedLogsTable unchanged.
🧹 Nitpick comments (2)
src/lib/utils/special-settings.ts (1)
31-68: exhaustive switch 模式与去重键设计使用
never类型进行穷举检查是良好实践。但provider_parameter_override的去重键未包含changes数组,若同一 provider 的不同changes需区分,可能被误判为重复。当前场景下(同请求内同 provider 的覆写通常唯一)应无问题,但建议在注释中说明该约束。
src/repository/message.ts (1)
274-316: 函数实现正确,考虑添加运行时验证。函数逻辑清晰,查询条件正确使用了复合索引(
idx_message_request_session_seq)。Line 314 的类型断言依赖数据库数据完整性,如果 DB 中的specialSettingsJSON 结构不符合SpecialSetting[]类型定义,可能导致运行时类型错误。💡 可选:添加运行时验证以提高类型安全
if (!row) return null; return { statusCode: row.statusCode, blockedBy: row.blockedBy, blockedReason: row.blockedReason, cacheTtlApplied: row.cacheTtlApplied, context1mApplied: row.context1mApplied, - specialSettings: row.specialSettings as SpecialSetting[] | null, + specialSettings: Array.isArray(row.specialSettings) ? row.specialSettings as SpecialSetting[] : null, };这样可以在类型断言前添加基础的数组类型检查,提高代码健壮性。
📜 Review details
Configuration used: Organization UI
Review profile: CHILL
Plan: Pro
Cache: Disabled due to Reviews > Disable Cache setting
📒 Files selected for processing (9)
src/actions/active-sessions.tssrc/app/[locale]/dashboard/logs/_components/virtualized-logs-table.tsxsrc/lib/utils/special-settings.tssrc/repository/message.tssrc/repository/usage-logs.tssrc/types/special-settings.tstests/unit/actions/active-sessions-special-settings.test.tstests/unit/dashboard-logs-virtualized-special-settings-ui.test.tsxtests/unit/lib/utils/special-settings.test.ts
🧰 Additional context used
📓 Path-based instructions (4)
**/*.{js,ts,tsx,jsx}
📄 CodeRabbit inference engine (CLAUDE.md)
No emoji characters in any code, comments, or string literals
Files:
src/types/special-settings.tstests/unit/lib/utils/special-settings.test.tssrc/lib/utils/special-settings.tssrc/actions/active-sessions.tstests/unit/actions/active-sessions-special-settings.test.tssrc/repository/usage-logs.tssrc/app/[locale]/dashboard/logs/_components/virtualized-logs-table.tsxsrc/repository/message.tstests/unit/dashboard-logs-virtualized-special-settings-ui.test.tsx
**/*.{ts,tsx,jsx,js}
📄 CodeRabbit inference engine (CLAUDE.md)
**/*.{ts,tsx,jsx,js}: All user-facing strings must use i18n (5 languages supported: zh-CN, en, ja, ko, de). Never hardcode display text
Use path alias @/ to map to ./src/
Use Biome for code formatting with configuration: double quotes, trailing commas, 2-space indent, 100 character line width
Prefer named exports over default exports
Use next-intl for internationalization
Use Next.js 16 App Router with Hono for API routes
Files:
src/types/special-settings.tstests/unit/lib/utils/special-settings.test.tssrc/lib/utils/special-settings.tssrc/actions/active-sessions.tstests/unit/actions/active-sessions-special-settings.test.tssrc/repository/usage-logs.tssrc/app/[locale]/dashboard/logs/_components/virtualized-logs-table.tsxsrc/repository/message.tstests/unit/dashboard-logs-virtualized-special-settings-ui.test.tsx
**/*.test.{ts,tsx,js,jsx}
📄 CodeRabbit inference engine (CLAUDE.md)
Place unit tests in tests/unit/, integration tests in tests/integration/, and source-adjacent tests in src/**/*.test.ts
Files:
tests/unit/lib/utils/special-settings.test.tstests/unit/actions/active-sessions-special-settings.test.tstests/unit/dashboard-logs-virtualized-special-settings-ui.test.tsx
**/*.{tsx,jsx}
📄 CodeRabbit inference engine (CLAUDE.md)
Use React 19, shadcn/ui, Tailwind CSS, and Recharts for the UI layer
Files:
src/app/[locale]/dashboard/logs/_components/virtualized-logs-table.tsxtests/unit/dashboard-logs-virtualized-special-settings-ui.test.tsx
🧠 Learnings (2)
📚 Learning: 2026-01-05T03:01:39.354Z
Learnt from: NieiR
Repo: ding113/claude-code-hub PR: 539
File: src/types/user.ts:158-170
Timestamp: 2026-01-05T03:01:39.354Z
Learning: In TypeScript interfaces, explicitly document and enforce distinct meanings for null and undefined. Example: for numeric limits like limitTotalUsd, use 'number | null | undefined' when null signifies explicitly unlimited (e.g., matches DB schema or special UI logic) and undefined signifies 'inherit default'. This pattern should be consistently reflected in type definitions across related fields to preserve semantic clarity between database constraints and UI behavior.
Applied to files:
src/types/special-settings.tssrc/lib/utils/special-settings.tssrc/actions/active-sessions.tssrc/repository/usage-logs.tssrc/repository/message.ts
📚 Learning: 2026-01-07T17:05:36.362Z
Learnt from: CR
Repo: ding113/claude-code-hub PR: 0
File: CLAUDE.md:0-0
Timestamp: 2026-01-07T17:05:36.362Z
Learning: Applies to **/*.test.{ts,tsx,js,jsx} : Place unit tests in tests/unit/, integration tests in tests/integration/, and source-adjacent tests in src/**/*.test.ts
Applied to files:
tests/unit/lib/utils/special-settings.test.tstests/unit/dashboard-logs-virtualized-special-settings-ui.test.tsx
🧬 Code graph analysis (7)
tests/unit/lib/utils/special-settings.test.ts (2)
src/lib/utils/special-settings.ts (1)
buildUnifiedSpecialSettings(76-130)src/types/special-settings.ts (1)
SpecialSetting(8-13)
src/lib/utils/special-settings.ts (2)
src/types/special-settings.ts (1)
SpecialSetting(8-13)src/lib/special-attributes/index.ts (1)
CONTEXT_1M_BETA_HEADER(25-25)
tests/unit/actions/active-sessions-special-settings.test.ts (1)
src/actions/active-sessions.ts (1)
getSessionDetails(511-697)
src/repository/usage-logs.ts (2)
src/lib/utils/special-settings.ts (1)
buildUnifiedSpecialSettings(76-130)src/types/special-settings.ts (1)
SpecialSetting(8-13)
src/app/[locale]/dashboard/logs/_components/virtualized-logs-table.tsx (2)
src/components/ui/badge.tsx (1)
Badge(39-39)scripts/sync-settings-keys.js (1)
t(72-72)
src/repository/message.ts (3)
src/types/special-settings.ts (1)
SpecialSetting(8-13)src/drizzle/db.ts (1)
db(37-44)src/drizzle/schema.ts (1)
messageRequest(276-362)
tests/unit/dashboard-logs-virtualized-special-settings-ui.test.tsx (2)
src/repository/usage-logs.ts (1)
UsageLogRow(30-62)src/app/[locale]/dashboard/logs/_components/virtualized-logs-table.tsx (1)
VirtualizedLogsTable(51-632)
⏰ 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). (6)
- GitHub Check: pr-description
- GitHub Check: pr-review
- GitHub Check: 🌐 API Tests
- GitHub Check: check-codex-status
- GitHub Check: Docker Build Test
- GitHub Check: dev-build-deploy
🔇 Additional comments (23)
src/lib/utils/special-settings.ts (2)
1-29: 类型定义与导入结构清晰参数类型
BuildUnifiedSpecialSettingsParams设计合理,使用| null明确表达"显式为空"与undefined(省略/继承)的语义差异,符合项目中对null与undefined的区分约定。
76-129: 统一构建逻辑正确函数逻辑清晰:
- 优先保留
existing中的设置(先入 Set)- 从审计字段派生
guard_intercept、cache_ttl、context_1m设置- 空结果返回
null而非空数组,与类型签名一致实现符合预期,去重逻辑正确。
src/app/[locale]/dashboard/logs/_components/virtualized-logs-table.tsx (2)
387-394: Special 标记渲染实现正确条件渲染逻辑
log.specialSettings && log.specialSettings.length > 0安全处理了null/undefined和空数组场景。使用 i18n keylogs.table.specialSettings符合国际化规范。
589-589: 透传 specialSettings 至详情弹窗正确将
log.specialSettings传递给ErrorDetailsDialog,与 PR 目标一致。src/repository/usage-logs.ts (2)
245-264: 批量查询中统一 specialSettings 构建在
findUsageLogsBatch中正确应用buildUnifiedSpecialSettings,将 DB 审计字段与既有specialSettings合并。类型断言as SpecialSetting[] | null对 jsonb 列是必要的。
461-480: 分页查询中保持一致的 specialSettings 处理
findUsageLogsWithDetails使用相同的buildUnifiedSpecialSettings调用模式,确保批量与分页查询返回一致的specialSettings结构。两处代码几乎相同,若未来需维护可考虑提取为私有辅助函数,但当前规模下保持内联也可接受。
src/actions/active-sessions.ts (3)
592-593: 动态导入 findMessageRequestAuditBySessionIdAndSequence遵循文件中既有的动态导入模式,有助于代码分割。
636-639: 条件查询 requestAudit仅在
effectiveSequence存在时查询 DB 审计数据,避免无效查询。使用Promise.resolve(null)保持Promise.all类型一致性。
656-671: 合并 Redis 与 DB specialSettings 后统一构建合并逻辑正确处理了
null/非数组场景。Redis 数据优先(先入数组),在后续去重时保留优先级。
buildUnifiedSpecialSettings调用包含所有必要的审计字段,确保派生设置与既有设置正确合并。tests/unit/actions/active-sessions-special-settings.test.ts (2)
1-67: Mock 设置完整正确模拟了所有依赖项:认证、缓存、日志、Session 管理器、消息仓库。使用
vi.fn()而非具体实现,便于测试控制。
110-181: 测试用例覆盖核心场景
- Redis 为空时从 DB 审计字段派生设置
- Redis 与 DB 同时存在时合并去重
验证逻辑使用
.sort()进行顺序无关比较,断言去重后provider_parameter_override仅保留一条。可考虑补充边缘场景(如两者均为空、仅 Redis 有数据),但当前覆盖已满足主要需求。
tests/unit/lib/utils/special-settings.test.ts (4)
1-8: 基础测试用例:空输入返回 null验证
existing: null且无派生字段时返回null,符合函数契约。
10-54: guard_intercept 派生测试覆盖
warmup(action:intercept_response)和sensitive_word(action:block_request)两种场景,验证 guard、scope、action、statusCode 等字段正确派生。
56-92: Header 覆写派生测试分别测试
cacheTtlApplied和context1mApplied的派生逻辑,验证类型、scope、ttl/header 字段。
94-146: 合并与去重测试
- 合并测试:验证
existing中的provider_parameter_override与派生的guard_intercept共存- 去重测试:验证
existing已包含相同guard_intercept时不重复添加测试覆盖全面,符合 PR 目标。
src/types/special-settings.ts (3)
8-13: SpecialSetting 联合类型扩展正确添加三个新变体到联合类型。使用
type字段作为判别器,支持 TypeScript 类型收窄。
46-63: GuardInterceptSpecialSetting 类型定义结构设计合理:
action使用字面量联合"intercept_response" | "block_request"而非stringstatusCode和reason允许null,与 DB 字段可空性一致- 文档注释说明了用途和场景
65-87: Anthropic Header 覆写类型定义两个类型结构清晰:
AnthropicCacheTtlHeaderOverrideSpecialSetting:ttl为string(如 "1h")AnthropicContext1mHeaderOverrideSpecialSetting:header使用字面量"anthropic-beta"确保类型安全src/repository/message.ts (1)
9-9: 导入语句正确。正确引入了
SpecialSetting类型,用于新函数的返回类型定义。tests/unit/dashboard-logs-virtualized-special-settings-ui.test.tsx (4)
93-128: 测试辅助函数实现良好。
renderWithIntl函数正确配置了 React Query 和 Next Intl 的测试环境,使用了适当的 provider 嵌套和清理逻辑。
25-79: Mock 数据结构正确且类型安全。
getUsageLogsBatch的 mock 实现正确模拟了真实数据结构,Line 73 使用satisfies UsageLogRow确保了类型安全,specialSettings数据符合SpecialSetting联合类型的结构。
16-17: 移除代码注释中的中文字符。根据编码规范,
**/*.{js,ts,tsx,jsx}文件中的代码、注释和字符串字面量不得包含非英文字符。🌐 建议的修复
-// 说明:虚拟列表依赖元素测量与 ResizeObserver;在 happy-dom 下行可能不渲染。 -// 这里把 useVirtualizer 固定为"只渲染首行",确保 UI 断言稳定。 +// Note: Virtual lists depend on element measurement and ResizeObserver, which may not render properly in happy-dom. +// Here we fix useVirtualizer to "render only the first row" to ensure stable UI assertions.基于编码规范,所有代码注释应使用英文。
⛔ Skipped due to learnings
Learnt from: CR Repo: ding113/claude-code-hub PR: 0 File: CLAUDE.md:0-0 Timestamp: 2026-01-07T17:05:36.362Z Learning: Applies to **/*.{ts,tsx,jsx,js} : All user-facing strings must use i18n (5 languages supported: zh-CN, en, ja, ko, de). Never hardcode display textLearnt from: CR Repo: ding113/claude-code-hub PR: 0 File: CLAUDE.md:0-0 Timestamp: 2026-01-07T17:05:36.362Z Learning: Applies to **/*.{js,ts,tsx,jsx} : No emoji characters in any code, comments, or string literals
81-81: 移除代码注释中的中文字符。注释应使用英文以符合编码规范。
🌐 建议的修复
-// 测试环境不加载 next-intl/navigation -> next/navigation 的真实实现(避免 Next.js 运行时依赖) +// In test environment, avoid loading the real next-intl/navigation -> next/navigation implementation (to avoid Next.js runtime dependencies)基于编码规范,所有代码注释应使用英文。
⛔ Skipped due to learnings
Learnt from: CR Repo: ding113/claude-code-hub PR: 0 File: CLAUDE.md:0-0 Timestamp: 2026-01-07T17:05:36.362Z Learning: Applies to **/*.{ts,tsx,jsx,js} : All user-facing strings must use i18n (5 languages supported: zh-CN, en, ja, ko, de). Never hardcode display textLearnt from: CR Repo: ding113/claude-code-hub PR: 0 File: CLAUDE.md:0-0 Timestamp: 2026-01-07T17:05:36.362Z Learning: Applies to **/*.{ts,tsx,jsx,js} : Use next-intl for internationalization
There was a problem hiding this comment.
Code Review Summary
This PR successfully unifies the display of request special settings by merging scattered audit fields (blockedBy/blockedReason, cacheTtlApplied, context1mApplied) with existing specialSettings into a single consistent presentation. The implementation is clean and well-tested.
PR Size: L
- Lines changed: 774 (771 additions + 3 deletions)
- Files changed: 9
Issues Found
| Category | Critical | High | Medium | Low |
|---|---|---|---|---|
| Logic/Bugs | 0 | 0 | 0 | 0 |
| Security | 0 | 0 | 0 | 0 |
| Error Handling | 0 | 0 | 0 | 0 |
| Types | 0 | 0 | 0 | 0 |
| Comments/Docs | 0 | 0 | 0 | 0 |
| Tests | 0 | 0 | 0 | 0 |
| Simplification | 0 | 0 | 0 | 0 |
Review Coverage
- Logic and correctness - Clean
- Security (OWASP Top 10) - Clean
- Error handling - Clean
- Type safety - Clean
- Documentation accuracy - Clean
- Test coverage - Adequate (unit tests for utility function, integration tests for session details, UI tests for badge display)
- Code clarity - Good
Analysis Notes
Perspective 1 - Comment Analyzer: All comments accurately describe the code behavior. The Chinese comments provide clear explanations of the purpose of each parameter and function.
Perspective 2 - Test Analyzer: Tests cover the key scenarios:
buildUnifiedSpecialSettingsutility has comprehensive unit tests covering null inputs, each derived setting type, merging, and deduplication- Session details integration test verifies Redis + DB merging
- UI test verifies the Special badge rendering
Perspective 3 - Silent Failure Hunter: No silent failures detected. The utility function handles null/undefined inputs gracefully by returning null when no settings exist. Error handling in the calling code (getSessionDetails) has proper logging via logger.error.
Perspective 4 - Type Design Auditor:
- The new
SpecialSettingunion type is well-designed with proper discriminated unions via thetypefield - The exhaustive switch in
buildSettingKey()with thenevercheck ensures type safety for future extensions - No use of
anytype
Perspective 5 - General Code Reviewer:
- The deduplication logic using
buildSettingKey()is sound and creates unique keys for each setting type - The
guard === "warmup" ? "intercept_response" : "block_request"logic correctly maps guard types to actions - No SQL injection or security concerns in the new repository query
Perspective 6 - Code Simplifier: The code is already well-structured. The utility function has a clear single responsibility and the deduplication algorithm is straightforward.
Automated review by Claude AI
There was a problem hiding this comment.
Code Review Summary
No significant issues identified in this PR.
PR Size: L
- Lines changed: 774
- Files changed: 9
- Split suggestions: If you want smaller PRs, consider separating (1)
src/types/special-settings.ts+src/lib/utils/special-settings.ts, (2) backend plumbingsrc/repository/*+src/actions/active-sessions.ts, (3) UI updates + tests.
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
#574(feat/unify-special-settings-display) at head5581efc71d098a38a85f79a91107a7c67e4a740b. - Applied the PR size label
size/L. - Submitted the required review summary via
gh pr review; no diff-line issues met the >=80 confidence threshold, so no inline comments were posted.
🧪 测试结果
总体结果: ✅ 所有测试通过 |
There was a problem hiding this comment.
Actionable comments posted: 0
🧹 Nitpick comments (2)
tests/unit/lib/utils/special-settings.test.ts (1)
5-8: 可选:补充空数组边界测试用例。当前测试覆盖了
existing: null的情况。可考虑补充existing: [](空数组)且无派生设置时的边界用例,验证返回null:test("existing 为空数组且无派生时应返回 null", () => { expect(buildUnifiedSpecialSettings({ existing: [] })).toBe(null); });src/repository/usage-logs.ts (1)
465-488: 可选:提取统一设置构建逻辑为公共辅助函数。
findUsageLogsBatch与findUsageLogsWithDetails中的统一设置构建逻辑完全相同。如果后续有更多类似场景,可考虑提取为私有辅助函数以减少重复:♻️ 可选重构示例
function buildUnifiedSettingsFromRow(row: { specialSettings: unknown; blockedBy: string | null; blockedReason: string | null; statusCode: number | null; cacheTtlApplied: string | null; context1mApplied: boolean | null; }): SpecialSetting[] | null { const existing = Array.isArray(row.specialSettings) ? (row.specialSettings as SpecialSetting[]) : null; return buildUnifiedSpecialSettings({ existing, blockedBy: row.blockedBy, blockedReason: row.blockedReason, statusCode: row.statusCode, cacheTtlApplied: row.cacheTtlApplied, context1mApplied: row.context1mApplied, }); }当前实现清晰可读,此重构为可选优化。
📜 Review details
Configuration used: Organization UI
Review profile: CHILL
Plan: Pro
Cache: Disabled due to Reviews > Disable Cache setting
📒 Files selected for processing (6)
src/actions/active-sessions.tssrc/lib/utils/special-settings.tssrc/repository/message.tssrc/repository/usage-logs.tstests/unit/dashboard-logs-virtualized-special-settings-ui.test.tsxtests/unit/lib/utils/special-settings.test.ts
🚧 Files skipped from review as they are similar to previous changes (2)
- src/actions/active-sessions.ts
- tests/unit/dashboard-logs-virtualized-special-settings-ui.test.tsx
🧰 Additional context used
📓 Path-based instructions (3)
**/*.{js,ts,tsx,jsx}
📄 CodeRabbit inference engine (CLAUDE.md)
No emoji characters in any code, comments, or string literals
Files:
tests/unit/lib/utils/special-settings.test.tssrc/lib/utils/special-settings.tssrc/repository/usage-logs.tssrc/repository/message.ts
**/*.{ts,tsx,jsx,js}
📄 CodeRabbit inference engine (CLAUDE.md)
**/*.{ts,tsx,jsx,js}: All user-facing strings must use i18n (5 languages supported: zh-CN, en, ja, ko, de). Never hardcode display text
Use path alias @/ to map to ./src/
Use Biome for code formatting with configuration: double quotes, trailing commas, 2-space indent, 100 character line width
Prefer named exports over default exports
Use next-intl for internationalization
Use Next.js 16 App Router with Hono for API routes
Files:
tests/unit/lib/utils/special-settings.test.tssrc/lib/utils/special-settings.tssrc/repository/usage-logs.tssrc/repository/message.ts
**/*.test.{ts,tsx,js,jsx}
📄 CodeRabbit inference engine (CLAUDE.md)
Place unit tests in tests/unit/, integration tests in tests/integration/, and source-adjacent tests in src/**/*.test.ts
Files:
tests/unit/lib/utils/special-settings.test.ts
🧠 Learnings (2)
📚 Learning: 2026-01-07T17:05:36.362Z
Learnt from: CR
Repo: ding113/claude-code-hub PR: 0
File: CLAUDE.md:0-0
Timestamp: 2026-01-07T17:05:36.362Z
Learning: Applies to **/*.test.{ts,tsx,js,jsx} : Place unit tests in tests/unit/, integration tests in tests/integration/, and source-adjacent tests in src/**/*.test.ts
Applied to files:
tests/unit/lib/utils/special-settings.test.ts
📚 Learning: 2026-01-05T03:01:39.354Z
Learnt from: NieiR
Repo: ding113/claude-code-hub PR: 539
File: src/types/user.ts:158-170
Timestamp: 2026-01-05T03:01:39.354Z
Learning: In TypeScript interfaces, explicitly document and enforce distinct meanings for null and undefined. Example: for numeric limits like limitTotalUsd, use 'number | null | undefined' when null signifies explicitly unlimited (e.g., matches DB schema or special UI logic) and undefined signifies 'inherit default'. This pattern should be consistently reflected in type definitions across related fields to preserve semantic clarity between database constraints and UI behavior.
Applied to files:
src/lib/utils/special-settings.tssrc/repository/usage-logs.tssrc/repository/message.ts
🧬 Code graph analysis (4)
tests/unit/lib/utils/special-settings.test.ts (2)
src/lib/utils/special-settings.ts (1)
buildUnifiedSpecialSettings(72-126)src/types/special-settings.ts (1)
SpecialSetting(8-13)
src/lib/utils/special-settings.ts (2)
src/types/special-settings.ts (1)
SpecialSetting(8-13)src/lib/special-attributes/index.ts (1)
CONTEXT_1M_BETA_HEADER(25-25)
src/repository/usage-logs.ts (2)
src/types/special-settings.ts (1)
SpecialSetting(8-13)src/lib/utils/special-settings.ts (1)
buildUnifiedSpecialSettings(72-126)
src/repository/message.ts (2)
src/types/special-settings.ts (1)
SpecialSetting(8-13)src/drizzle/schema.ts (1)
messageRequest(276-362)
⏰ 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). (3)
- GitHub Check: 🌐 API Tests
- GitHub Check: Docker Build Test
- GitHub Check: dev-build-deploy
🔇 Additional comments (6)
src/repository/message.ts (1)
274-318: LGTM!新增审计字段查询函数实现正确。函数设计清晰:
- 查询条件正确使用了
sessionId+requestSequence复合条件,可利用idx_message_request_session_seq索引Array.isArray检查防御性地处理了specialSettings的类型转换- 返回类型明确区分了
null(无记录)与结构化对象tests/unit/lib/utils/special-settings.test.ts (1)
1-8: LGTM!测试覆盖全面,结构清晰。测试文件正确放置于
tests/unit/目录,覆盖了buildUnifiedSpecialSettings的主要场景:空输入、各类派生设置、合并与去重逻辑。src/repository/usage-logs.ts (1)
245-268: LGTM!正确集成统一特殊设置构建逻辑。在
findUsageLogsBatch中正确提取现有设置并调用buildUnifiedSpecialSettings合并派生字段,确保返回的specialSettings是统一视图。src/lib/utils/special-settings.ts (3)
4-29: LGTM!类型定义清晰,文档注释完善。
BuildUnifiedSpecialSettingsParams类型定义遵循了项目中null与undefined的语义区分(基于已有 learnings),每个字段都有中文 JSDoc 说明其用途。
31-64: LGTM!去重键生成逻辑健壮。
- 对
changes和fixersApplied数组排序确保键的确定性guard_intercept的键正确排除了reason字段,符合"去重不受 reason 差异影响"的设计意图default分支的never类型穷尽检查可在新增类型时提供编译期保护
72-126: LGTM!统一设置构建函数实现正确。
- 派生逻辑清晰:
warmup→intercept_response,其他守卫类型 →block_requestcontext1mApplied === true严格比较正确处理了boolean | null | undefined类型- 去重时
base设置优先于derived,确保已有设置不被覆盖
🧪 测试结果
总体结果: ✅ 所有测试通过 |
Summary
Unifies the display of request special settings by merging scattered audit fields (
blockedBy/blockedReason,cacheTtlApplied,context1mApplied) with existingspecialSettingsinto a single, consistent presentation across logs list, log details dialog, and session details page.Problem
Previously, special request information was fragmented:
special_settingsblockedBy/blockedReasonfieldsThis fragmentation made it difficult to see all special conditions affecting a request in one place.
Related PRs:
Solution
New utility function
buildUnifiedSpecialSettings()that:specialSettingsfrom Redis/DBguard_interceptsettings fromblockedBy/blockedReasonanthropic_cache_ttl_header_overridefromcacheTtlAppliedanthropic_context_1m_header_overridefromcontext1mAppliedExtended type system with three new
SpecialSettingvariants:GuardInterceptSpecialSetting- for warmup/sensitive word blocksAnthropicCacheTtlHeaderOverrideSpecialSetting- for cache TTL overridesAnthropicContext1mHeaderOverrideSpecialSetting- for 1M context overridesIntegrated display in:
Changes
Core Changes
src/lib/utils/special-settings.tssrc/types/special-settings.tssrc/repository/message.tsfindMessageRequestAuditBySessionIdAndSequence()src/repository/usage-logs.tssrc/actions/active-sessions.tsUI Changes
src/app/[locale]/dashboard/logs/_components/virtualized-logs-table.tsxTests
tests/unit/lib/utils/special-settings.test.tstests/unit/actions/active-sessions-special-settings.test.tstests/unit/dashboard-logs-virtualized-special-settings-ui.test.tsxTesting
Automated Tests
buildUnifiedSpecialSettings()functionVerification Commands
Checklist
Description enhanced by Claude AI