Skip to content

release: v0.9.3 - #1402

Merged
ding113 merged 12 commits into
mainfrom
dev
Aug 12, 2026
Merged

release: v0.9.3#1402
ding113 merged 12 commits into
mainfrom
dev

Conversation

@ding113

@ding113 ding113 commented Aug 7, 2026

Copy link
Copy Markdown
Owner

Release summary

This release PR promotes the current dev branch to main as v0.9.3.

Included changes

  • Fix Replay PostgreSQL cleanup failures caused by binding a raw JavaScript Date without the Drizzle timestamp encoder.
  • Preserve nested Drizzle/Postgres cause, name, message, and code in cleanup scheduler logs.
  • Add the database-backed replayCacheTtlMinutes system setting.
    • Default: 30 minutes.
    • Allowed range: 5-120 minutes.
    • PostgreSQL durable Replay expiry follows the setting.
    • Redis hot-cache TTL remains capped by REPLAY_TTL_SECONDS.
  • Add the generated Drizzle migration, REST/OpenAPI contract, runtime/repository wiring, five-language settings UI, and regression tests.
  • The production recovery runbook for historical replay_payloads cleanup remains documented in PR fix(replay): repair cleanup and add configurable cache TTL #1400; merging this release does not immediately reclaim the historical table/TOAST disk space.

Source PR

Validation

Release notes

  • Target version: v0.9.3
  • Base: main
  • Head: dev
  • This PR is intentionally left open for human release review.

Greptile Summary

The release adds configurable Replay retention, repairs Replay cleanup and error logging, bounds and deduplicates session response-body storage, and introduces database-backed availability projections.

  • Adds the replayCacheTtlMinutes setting across migrations, repository access, validation, REST/OpenAPI, runtime caching, and localized settings UI.
  • Reworks Replay spooling, durable persistence, detached-client cleanup, and Redis response-body storage.
  • Adds an outbox-triggered availability projection worker with startup, shutdown, bootstrap, and read-side integration.
  • Expands regression, integration, lifecycle, and load-test coverage.

Confidence Score: 5/5

The PR appears safe to merge because no blocking failure remains.

No blocking failure remains.

Important Files Changed

Filename Overview
src/app/v1/_lib/proxy/replay/replay-spool.ts Replaces full in-process Replay accumulation with bounded Redis-backed spooling and fenced durable completion.
src/app/v1/_lib/proxy/response-handler.ts Coordinates Replay completion with committed billing and reduces detached drain time when Replay becomes inactive.
src/lib/session-manager.ts Adds generation-fenced, request-scoped response-body bundles with deduplication, storage limits, and termination cleanup.
src/app/v1/_lib/proxy/replay/replay-store.ts Adds configurable durable Replay expiry while retaining an environment-capped Redis hot-cache TTL.
src/repository/system-config.ts Wires the Replay TTL setting through singleton configuration reads and writes with stale-schema degradation.
drizzle/0119_tiresome_banshee.sql Adds the non-null Replay cache TTL setting with a 30-minute default.
drizzle/0120_availability_projection.sql Introduces availability outbox and projection tables plus finalization-triggered event creation.
src/lib/availability/projection-worker.ts Implements idempotent historical bootstrap, transactional event processing, bucket updates, and current-state recomputation.
src/lib/availability/availability-service.ts Moves availability queries from raw request-log scans to the new projection tables.
src/instrumentation.ts Starts Replay cleanup and availability projection background work during application initialization.
src/lib/lifecycle/shutdown.ts Adds ordered shutdown handling for the newly introduced background workers.

Flowchart

%%{init: {'theme': 'neutral'}}%%
flowchart LR
  Request[Proxy request] --> ReplaySpool[Bounded Replay spool]
  ReplaySpool --> Redis[(Redis hot Replay)]
  ReplaySpool -->|after billing commit| Postgres[(PostgreSQL durable Replay)]
  Settings[System settings] --> Runtime[Runtime TTL resolver]
  Runtime --> ReplaySpool
  Request --> MessageRequest[Finalized message_request]
  MessageRequest --> Trigger[Outbox trigger]
  Trigger --> Outbox[(outbox_events)]
  Outbox --> Worker[Availability projection worker]
  Worker --> Buckets[(avail_bucket_1m)]
  Worker --> Current[(avail_current)]
  Buckets --> Dashboard[Availability dashboard]
  Current --> Dashboard
Loading

Reviews (10): Last reviewed commit: "style(availability): apply Biome formatt..." | Re-trigger Greptile

Context used (5)

Introduce replayCacheTtlMinutes (5-120 min, default 30) as a
database-backed system setting controlling how long completed
Replay payloads remain reusable in the PostgreSQL durable layer.
The Redis hot-layer TTL is capped to the same window so both
tiers expire in sync. This replaces the removed
REPLAY_COMPLETED_TTL_SECONDS environment variable, moving the
durable TTL into the admin-editable settings surface with full
validation, i18n labels, API schema, and UI input.

Also fix the replay cleanup query to bind the cutoff Date through
sql.param for correct PostgreSQL type coercion, and preserve
wrapped database error causes in the cleanup scheduler logging.
@chatgpt-codex-connector

Copy link
Copy Markdown

You have reached your Codex usage limits for code reviews. You can see your limits in the Codex usage dashboard.

@coderabbitai

coderabbitai Bot commented Aug 7, 2026

Copy link
Copy Markdown

Review Change Stack

Note

Reviews paused

It looks like this branch is under active development. To avoid overwhelming you with review comments due to an influx of new commits, CodeRabbit has automatically paused this review. You can configure this behavior by changing the reviews.auto_review.auto_pause_after_reviewed_commits setting.

Use the following commands to manage reviews:

  • @coderabbitai resume to resume automatic reviews.
  • @coderabbitai review to trigger a single review.

Use the checkboxes below for quick actions:

  • ▶️ Resume reviews
  • 🔍 Trigger review
📝 Walkthrough

Walkthrough

新增 Replay 完成载荷缓存 TTL 配置。系统支持数据库存储、API 校验、设置界面、运行时 TTL 计算和清理日志。代理新增 Remote Compaction v2 处理、请求体同步和流帧识别。ReplaySpool 改进终止清理。密钥禁用失败使用专用错误码。

Changes

Replay 缓存 TTL

Layer / File(s) Summary
设置契约与持久化
drizzle/*, src/drizzle/schema.ts, src/types/system-config.ts, src/lib/validation/*, src/lib/config/*, src/lib/system-settings/*, src/repository/*, tests/unit/repository/*
新增 replayCacheTtlMinutes 字段,默认值为 30,范围为 5–120。系统设置缓存、数据库转换、默认记录和旧 schema 降级逻辑同步支持该字段。
设置 API 与界面
src/actions/system-config.ts, src/app/[locale]/settings/config/*, src/app/api/v1/resources/system/*, src/lib/api/*, messages/*, tests/api/*, tests/unit/actions/*, tests/unit/settings/*
系统设置 API 和表单支持 Replay TTL。表单提供整数输入、范围限制和多语言错误提示。
Replay 运行时 TTL
src/app/v1/_lib/proxy/replay/replay-store.ts, src/lib/system-settings/proxy-runtime.ts, tests/unit/proxy/replay-store.test.ts
完成载荷 PG TTL 改为读取系统设置。Redis TTL 不超过完成载荷 TTL。清理查询使用类型安全的 SQL 参数绑定。
清理任务日志
src/instrumentation.ts, tests/unit/instrumentation-replay-cleanup.test.ts
清理成功时记录删除数量和批次数。失败及初始化错误使用结构化错误描述。

Remote Compaction v2

Layer / File(s) Summary
压缩请求路由与管理端点
src/app/v1/_lib/proxy/{remote-compaction,session,message-service,response-handler}.ts, tests/unit/proxy/{remote-compaction-v2,message-service,response-handler-bill-non-success}.test.ts
识别 Responses 端点中的 compaction_trigger,并将其映射到 /v1/responses/compact 管理端点。消息记录和非计费判断使用管理端点。
请求体规范化与透传
src/app/v1/_lib/proxy/{session,response-input-rectifier,proxy-handler}.ts, tests/unit/proxy/{proxy-forwarder-raw-passthrough-regression,proxy-handler-public-success}.test.ts
单对象 input 规范化为数组,并同步请求缓冲区和审计日志。raw passthrough 端点不进入假流式路径。
压缩流帧处理
src/app/v1/_lib/proxy/stream-gate/*, tests/unit/proxy/{stream-gate-content-gate,stream-gate-frame-classifier}.test.ts
Responses 流分类器识别有效 compaction 输出帧,并在 response.completed 前提交内容。
规范化错误与整流测试
src/lib/utils/error-messages.ts, messages/*/errors.json, tests/unit/i18n/session-request-errors.test.ts, tests/unit/proxy/response-input-rectifier.test.ts
新增 INVALID_NORMALIZED_BODY 错误码和多语言消息。测试覆盖序列化失败和请求体同步条件。

密钥禁用错误码

Layer / File(s) Summary
最后一个启用密钥错误码
src/actions/keys.ts, src/lib/utils/error-messages.ts, tests/unit/actions/keys-self-service-authz.test.ts, tests/unit/api/v1/api-client-actions.test.ts
单密钥和批量禁用操作返回 CANNOT_DISABLE_LAST_KEY。测试验证更新操作被阻止,并验证 API 客户端保留错误详情。

代理数据隔离与 ReplaySpool

Layer / File(s) Summary
代理消息复制与请求体类型
src/app/v1/_lib/proxy/forwarder.ts, src/app/v1/_lib/proxy/billing-header-rectifier.ts, src/lib/api/v1/_shared/request-body.ts, src/app/api/v1/resources/providers/handlers.ts, tests/unit/proxy/*
消息整流和 TTL 覆写使用复制写入。shadow session 共享只读请求数据。请求体解析使用 Zod schema 输出类型。
ReplaySpool 生命周期
src/app/v1/_lib/proxy/replay/replay-spool.ts, tests/unit/proxy/replay-spool.test.ts
ReplaySpool 跟踪排队批次。终止期间停止写入。重复终止共享清理屏障,并在清理完成后释放 payload、心跳和并发配额。

Estimated code review effort: 5 (Critical) | ~100 minutes

Possibly related PRs

🚥 Pre-merge checks | ✅ 4 | ❌ 1

❌ Failed checks (1 warning)

Check name Status Explanation Resolution
Docstring Coverage ⚠️ Warning Docstring coverage is 20.59% which is insufficient. The required threshold is 80.00%. Write docstrings for the functions missing them to satisfy the coverage threshold.
✅ Passed checks (4 passed)
Check name Status Explanation
Linked Issues check ✅ Passed Check skipped because no linked issues were found for this pull request.
Out of Scope Changes check ✅ Passed Check skipped because no linked issues were found for this pull request.
Title check ✅ Passed 标题明确说明这是 v0.9.3 发布,符合将 dev 分支提升到 main 的主要变更。
Description check ✅ Passed 描述详细说明了 Replay 修复、TTL 配置、相关集成、测试和发布目标,与变更内容一致。
✨ Finishing Touches 💡 1
📝 Generate docstrings 💡
  • Create stacked PR
  • Commit on current branch
🧪 Generate unit tests (beta)
  • Create PR with unit tests
  • Commit unit tests in branch dev

Thanks for using CodeRabbit! It's free for OSS, and your support helps us grow. If you like it, consider giving us a shout-out.

❤️ Share

Comment @coderabbitai help to get the list of available commands.

@github-actions github-actions Bot added the size/XL Extra Large PR (> 1000 lines) label Aug 7, 2026

@coderabbitai coderabbitai Bot left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Actionable comments posted: 3

🧹 Nitpick comments (6)
tests/unit/repository/system-config-degradation-ladder.test.ts (1)

317-317: 📐 Maintainability & Code Quality | 🔵 Trivial | 💤 Low value

建议将更新调用次数改为派生值。

读取路径的断言已改为由 RECENT_COLUMNS.length 派生(第 194、227-229 行)。写入路径仍使用字面量 23。每次新增系统设置列,都需要手工修改此数字。如果写入降级阶梯与 RECENT_COLUMNS 存在固定关系,请改为派生表达式,保持两条路径一致。

🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In `@tests/unit/repository/system-config-degradation-ladder.test.ts` at line 317,
将 system-config degradation ladder 写入路径中 updateMock 的固定调用次数 23 改为基于
RECENT_COLUMNS.length 的派生表达式,复用读取路径的既有关系,确保新增系统设置列时读写断言保持一致。
tests/api/v1/system/system-config.test.ts (1)

183-191: 🎯 Functional Correctness | 🔵 Trivial | ⚡ Quick win

建议补充上界与边界值用例。

当前只覆盖了下界外的 4。允许范围为 5-120。建议再加 121(上界外,期望 400)与 5120(边界内,期望 200),以锁定范围两端的行为。

🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In `@tests/api/v1/system/system-config.test.ts` around lines 183 - 191, Extend the
replayCacheTtlMinutes validation cases in the system settings test to cover 121
as an invalid upper-bound value expecting 400, and 5 and 120 as valid boundary
values expecting 200. Keep the existing invalid value 4 assertion and reuse the
same authorized PUT request flow.
tests/unit/settings/system-settings-form-replay-cache-toggles.test.tsx (1)

249-251: 📐 Maintainability & Code Quality | 🔵 Trivial | 💤 Low value

建议避免硬编码本地化文案。

此处断言完整的英文文案。如果 messages/en/settings/config.jsonreplayCacheTtlInvalid 的措辞调整,此测试会失败,但功能并未回归。建议从消息文件读取该键的值再断言,使测试只验证“显示了对应错误码的本地化消息”。

♻️ 参考改法
+import enConfigMessages from "`@/`../messages/en/settings/config.json";
+
...
     expect(sonnerMocks.toast.error).toHaveBeenCalledWith(
-      "Replay cache duration must be a whole number from 5 to 120 minutes."
+      enConfigMessages.form.replayCacheTtlInvalid
     );

导入路径需按仓库现有的 messages 导入方式调整。

🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In `@tests/unit/settings/system-settings-form-replay-cache-toggles.test.tsx`
around lines 249 - 251, Update the assertion in the replay-cache validation test
to import and use the localized value for the replayCacheTtlInvalid message from
the repository’s established messages-loading mechanism, instead of hardcoding
the English text. Keep the assertion focused on verifying that toast.error
receives that message.
src/drizzle/schema.ts (1)

1059-1060: 📐 Maintainability & Code Quality | 🔵 Trivial | 💤 Low value

建议复用默认值常量,避免多处硬编码。

此处默认值硬编码为 30。仓库其他位置(src/repository/system-config.tssrc/repository/_shared/transformers.ts)使用 REPLAY_CACHE_TTL_MINUTES_DEFAULT。如果该常量将来调整,本行不会同步。可以引入该常量以保持单一事实来源。注意:修改后仍需保证生成的迁移 SQL 默认值不变。

🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In `@src/drizzle/schema.ts` around lines 1059 - 1060, 将 replayCacheTtlMinutes
的默认值改为复用 REPLAY_CACHE_TTL_MINUTES_DEFAULT,并补充必要的导入,避免继续硬编码 30;同时确认生成的迁移 SQL
默认值仍保持为 30。
tests/unit/actions/system-config-save.test.ts (1)

164-173: 🎯 Functional Correctness | 🔵 Trivial | ⚡ Quick win

补充 5 和 120 的有效边界测试。

当前测试只验证 30 通过,验证 4、121 和 30.5 被拒绝。请增加 5120 的有效参数化案例。这样可以确认允许范围是闭区间 [5, 120],并防止边界条件回归。

🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In `@tests/unit/actions/system-config-save.test.ts` around lines 164 - 173, 在
Replay cache TTL 参数化测试中补充有效值 5 和 120 的测试案例,分别验证 saveSystemSettings 返回成功并调用
updateSystemSettingsMock。保留现有对 4、121 和 30.5 的拒绝断言,以确认允许范围为闭区间 [5, 120]。
src/repository/system-config.ts (1)

287-292: 🗄️ Data Integrity & Integration | 🔵 Trivial | 💤 Low value

将 old-schema Replay 列更新降级的回归测试补在现有退化阶梯测试中。

replayCacheTtlMinutes 已进入近代阶梯并被旧 schema 更新路径处理;system-config-update-missing-columns.test.ts 没有覆盖 replayCacheTtlMinutes + 旧世代 set/returning 组合,而 system-config-degradation-ladder.test.ts 已覆盖更新路径的完整降阶梯列集合。避免为同一场景新增分散测试文件。

🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In `@src/repository/system-config.ts` around lines 287 - 292, 在现有
system-config-degradation-ladder.test.ts 的完整降阶梯测试中补充 replayCacheTtlMinutes 的旧
schema 更新回归覆盖,验证缺少该列时旧世代 set/returning 组合仍按预期降级。不要新增分散测试文件,并保持
system-config-update-missing-columns.test.ts 的职责不变。
🤖 Prompt for all review comments with AI agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

Inline comments:
In `@src/instrumentation.ts`:
- Around line 331-340: 调整 runReplayCleanupTick 的成功与失败日志调用,将结构化对象参数放在消息字符串之前,确保
deleted 统计和 describeSchedulerError(error) 返回的字段被 Pino 合并为日志字段;同步更新
tests/unit/instrumentation-replay-cleanup.test.ts 中对应的参数顺序断言。

In `@src/lib/validation/schemas.ts`:
- Around line 24-28: Update the import of REPLAY_CACHE_TTL_INVALID_ERROR_CODE,
REPLAY_CACHE_TTL_MINUTES_MAX, and REPLAY_CACHE_TTL_MINUTES_MIN in schemas.ts to
use the `@/lib/validation/replay-settings` path alias instead of the relative
./replay-settings path.

In `@src/repository/_shared/transformers.ts`:
- Line 324: Update the replayCacheTtlMinutes handling in toSystemSettings to
validate database values are within the allowed 5–120 minute range before
returning them; fall back to REPLAY_CACHE_TTL_MINUTES_DEFAULT for missing or
out-of-range values, while preserving valid configured values.

---

Nitpick comments:
In `@src/drizzle/schema.ts`:
- Around line 1059-1060: 将 replayCacheTtlMinutes 的默认值改为复用
REPLAY_CACHE_TTL_MINUTES_DEFAULT,并补充必要的导入,避免继续硬编码 30;同时确认生成的迁移 SQL 默认值仍保持为 30。

In `@src/repository/system-config.ts`:
- Around line 287-292: 在现有 system-config-degradation-ladder.test.ts 的完整降阶梯测试中补充
replayCacheTtlMinutes 的旧 schema 更新回归覆盖,验证缺少该列时旧世代 set/returning
组合仍按预期降级。不要新增分散测试文件,并保持 system-config-update-missing-columns.test.ts 的职责不变。

In `@tests/api/v1/system/system-config.test.ts`:
- Around line 183-191: Extend the replayCacheTtlMinutes validation cases in the
system settings test to cover 121 as an invalid upper-bound value expecting 400,
and 5 and 120 as valid boundary values expecting 200. Keep the existing invalid
value 4 assertion and reuse the same authorized PUT request flow.

In `@tests/unit/actions/system-config-save.test.ts`:
- Around line 164-173: 在 Replay cache TTL 参数化测试中补充有效值 5 和 120 的测试案例,分别验证
saveSystemSettings 返回成功并调用 updateSystemSettingsMock。保留现有对 4、121 和 30.5
的拒绝断言,以确认允许范围为闭区间 [5, 120]。

In `@tests/unit/repository/system-config-degradation-ladder.test.ts`:
- Line 317: 将 system-config degradation ladder 写入路径中 updateMock 的固定调用次数 23 改为基于
RECENT_COLUMNS.length 的派生表达式,复用读取路径的既有关系,确保新增系统设置列时读写断言保持一致。

In `@tests/unit/settings/system-settings-form-replay-cache-toggles.test.tsx`:
- Around line 249-251: Update the assertion in the replay-cache validation test
to import and use the localized value for the replayCacheTtlInvalid message from
the repository’s established messages-loading mechanism, instead of hardcoding
the English text. Keep the assertion focused on verifying that toast.error
receives that message.
🪄 Autofix

Fix all unresolved CodeRabbit comments on this PR:

  • Push a commit to this branch (recommended)
  • Create a new PR with the fixes

ℹ️ Review info
⚙️ Run configuration

Configuration used: Organization UI

Review profile: CHILL

Plan: Pro Plus

Run ID: 95c21ff2-fc4c-45fb-bdae-fca91ade7d71

📥 Commits

Reviewing files that changed from the base of the PR and between ccbad37 and b37db15.

📒 Files selected for processing (34)
  • drizzle/0119_tiresome_banshee.sql
  • drizzle/meta/0119_snapshot.json
  • drizzle/meta/_journal.json
  • messages/en/settings/config.json
  • messages/ja/settings/config.json
  • messages/ru/settings/config.json
  • messages/zh-CN/settings/config.json
  • messages/zh-TW/settings/config.json
  • src/actions/system-config.ts
  • src/app/[locale]/settings/config/_components/system-settings-form.tsx
  • src/app/[locale]/settings/config/page.tsx
  • src/app/api/v1/resources/system/router.ts
  • src/app/v1/_lib/proxy/replay/replay-store.ts
  • src/drizzle/schema.ts
  • src/instrumentation.ts
  • src/lib/api-client/v1/openapi-types.gen.ts
  • src/lib/api/v1/schemas/system-config.ts
  • src/lib/config/env.schema.ts
  • src/lib/config/system-settings-cache.ts
  • src/lib/system-settings/proxy-runtime.ts
  • src/lib/validation/replay-settings.ts
  • src/lib/validation/schemas.ts
  • src/repository/_shared/transformers.test.ts
  • src/repository/_shared/transformers.ts
  • src/repository/system-config.ts
  • src/types/system-config.ts
  • tests/api/v1/system/system-config.test.ts
  • tests/unit/actions/system-config-save.test.ts
  • tests/unit/instrumentation-replay-cleanup.test.ts
  • tests/unit/proxy/replay-store.test.ts
  • tests/unit/proxy/stream-gate-mode-resolution.test.ts
  • tests/unit/repository/system-config-degradation-ladder.test.ts
  • tests/unit/repository/system-config-update-missing-columns.test.ts
  • tests/unit/settings/system-settings-form-replay-cache-toggles.test.tsx
💤 Files with no reviewable changes (1)
  • src/lib/config/env.schema.ts

Comment thread src/instrumentation.ts Outdated
Comment thread src/lib/validation/schemas.ts Outdated
Comment thread src/repository/_shared/transformers.ts Outdated
@github-actions

github-actions Bot commented Aug 7, 2026

Copy link
Copy Markdown
Contributor

🧪 测试结果

测试类型 状态
代码质量
单元测试
集成测试
API 测试

总体结果: ✅ 所有测试通过

@github-actions

github-actions Bot commented Aug 7, 2026

Copy link
Copy Markdown
Contributor

🧪 测试结果

测试类型 状态
代码质量
单元测试
集成测试
API 测试

总体结果: ✅ 所有测试通过

@github-actions github-actions Bot left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Code Review Summary

No significant issues identified in this PR.

PR Size: XL

  • Lines changed: 5932
  • Files changed: 34
  • Split suggestions:
    • Separate the generated Drizzle migration/snapshot artifacts from the hand-written runtime changes.
    • Separate the replay TTL/settings surface work from the replay cleanup SQL/logging fix.
    • Separate generated OpenAPI client/types updates from UI and test updates.

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

@github-actions github-actions Bot left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

  • Review for PR #1402 is complete.
  • Applied the size/XL label and posted the required summary review comment on the PR.
  • No inline review comments were added because no changed-line issues survived validation at the required confidence threshold.
  • The posted XL split suggestions recommend separating generated Drizzle artifacts, replay TTL/settings changes, and generated OpenAPI updates from the runtime/UI/test work.
  • Validation notes: git diff --check passed; targeted vitest execution was not possible here because bunx is unavailable in this environment.

If you want, I can still do a second-pass review focused on one area such as replay cleanup, settings validation, or the UI form changes.

ding113 added 2 commits August 7, 2026 19:45
The toSystemSettings transformer now validates that
replayCacheTtlMinutes is an integer within the min/max bounds
(5–120), falling back to the default for any out-of-range or
non-integer value. Previously, arbitrary values from the database
would pass through unchecked.

The API update handler now maps replay TTL validation failures to
the REPLAY_CACHE_TTL_INVALID error code via
getReplayCacheTtlValidationErrorCode, so clients receive a precise
error instead of a generic validation failure.

Additional review-driven fixes:
- Schema default references the shared REPLAY_CACHE_TTL_MINUTES_DEFAULT
  constant instead of a magic number
- Import paths in schemas.ts normalized to absolute module specifiers
- Tests cover boundary values (5, 120), upper-limit rejection (121),
  and invalid-value fallback in the transformer
- Degradation ladder test includes replayCacheTtlMinutes in its
  update payload and returning-column assertions
- Form test uses the i18n message key instead of a hardcoded string
The replay cleanup scheduler passed the message string as the first
argument and the structured data object as the second, which is the
reverse of the pino calling convention. Swap them so the data object
is first and the message string is second, matching the rest of the
codebase. Test expectations updated accordingly.
@github-actions

github-actions Bot commented Aug 7, 2026

Copy link
Copy Markdown
Contributor

🧪 测试结果

测试类型 状态
代码质量
单元测试
集成测试
API 测试

总体结果: ✅ 所有测试通过

* fix(proxy): support remote compaction v2 passthrough

* fix(proxy): address remote compaction review feedback

* fix(proxy): localize normalized request errors

* test(proxy): cover localized normalization errors
@github-actions

github-actions Bot commented Aug 7, 2026

Copy link
Copy Markdown
Contributor

🧪 测试结果

测试类型 状态
代码质量
单元测试
集成测试
API 测试

总体结果: ✅ 所有测试通过

* fix(proxy): prevent shared mutation and replay memory retention

Rectifiers and cache TTL overrides mutated shared nested arrays in
place, leaking attempt-specific edits across concurrent shadow
sessions and the original request. Switch to copy-on-write: filtered
arrays are assigned through the top-level message object, TTL
override rebuilds only changed message entries, and shadow sessions
shallow-copy the request message while sharing the readonly buffer
instead of deep-cloning multi-MB request bodies per shadow.

ReplaySpool retained full payload while Redis or PG writes blocked
and abort/disable raced with in-flight flushes. Payload is now
snapshotted and cleared before persistence; abort immediately
releases accumulated parts and queued batches, deduplicates
concurrent calls through a shared barrier, and fences store cleanup
through the writeChain so concurrency quota is freed only after
cleanup completes.

Streaming detection now reads the stream flag directly from the
outgoing message instead of re-parsing the serialized body.

* fix(types): resolve tsgo type inference failures for zod 4 body parsing

tsgo (TypeScript native preview) could not infer the generic output type
from JsonBodySchema<T>'s structural safeParse signature because zod 4
uses this-type polymorphism (core.output<this>) instead of a plain
generic. This left body.data as unknown across all v1 API handlers,
producing 36 TS18046/TS2698/TS2345 errors.

Switch parseHonoJsonBody/parseJsonBody/parseJson to infer the schema
type directly (<S extends z.ZodType>) and extract the output via
z.output<S>, which tsgo resolves correctly. Add explicit parameter
annotations to four zod .transform()/.refine() callbacks where tsgo
also failed to infer the this-dependent input type.

CI Run: https://github.com/ding113/claude-code-hub/actions/runs/31245382874

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>

---------

Co-authored-by: claude[bot] <41898282+claude[bot]@users.noreply.github.com>
Co-authored-by: Claude Opus 4.6 <noreply@anthropic.com>
@github-actions

Copy link
Copy Markdown
Contributor

🧪 测试结果

测试类型 状态
代码质量
单元测试
集成测试
API 测试

总体结果: ✅ 所有测试通过

@coderabbitai coderabbitai Bot left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

🧹 Nitpick comments (1)
src/app/v1/_lib/proxy/replay/replay-spool.ts (1)

410-412: 📐 Maintainability & Code Quality | 🔵 Trivial | 💤 Low value

建议把新增字段声明移到类顶部的字段块。

releasedabortingabortPromise 声明在 teardown() 之后、release() 之前。类字段在构造时初始化,因此方法体内读取 this.aborting 没有运行时问题。但这三个字段被第 129、150、180、201、249、334 行等多处方法引用,声明位置分散会降低可读性。

♻️ 建议的调整
   private writeChain: Promise<void> = Promise.resolve();
   private metaWritten = false;
+  private released = false;
+  private aborting = false;
+  private abortPromise: Promise<void> | null = null;
-  private released = false;
-  private aborting = false;
-  private abortPromise: Promise<void> | null = null;
-
   private release(): void {
🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In `@src/app/v1/_lib/proxy/replay/replay-spool.ts` around lines 410 - 412, 将
released、aborting 和 abortPromise
三个字段声明移到类顶部的字段声明区域,位于其他实例字段附近;保留其现有初始化值和类型不变,并移除 teardown() 与 release()
之间的重复声明,不修改 teardown()、release() 及其他方法的行为。
🤖 Prompt for all review comments with AI agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

Nitpick comments:
In `@src/app/v1/_lib/proxy/replay/replay-spool.ts`:
- Around line 410-412: 将 released、aborting 和 abortPromise
三个字段声明移到类顶部的字段声明区域,位于其他实例字段附近;保留其现有初始化值和类型不变,并移除 teardown() 与 release()
之间的重复声明,不修改 teardown()、release() 及其他方法的行为。

ℹ️ Review info
⚙️ Run configuration

Configuration used: Organization UI

Review profile: CHILL

Plan: Pro Plus

Run ID: a995a0f9-999e-41d2-9a41-5eb918e75ca7

📥 Commits

Reviewing files that changed from the base of the PR and between 191bb19 and 1ac2b8f.

📒 Files selected for processing (13)
  • src/app/api/v1/resources/providers/handlers.ts
  • src/app/v1/_lib/proxy/billing-header-rectifier.ts
  • src/app/v1/_lib/proxy/forwarder.ts
  • src/app/v1/_lib/proxy/replay/replay-spool.ts
  • src/lib/api/v1/_shared/request-body.ts
  • src/lib/api/v1/schemas/audit-logs.ts
  • src/lib/api/v1/schemas/me.ts
  • src/lib/api/v1/schemas/system-config.ts
  • src/lib/api/v1/schemas/usage-logs.ts
  • tests/unit/proxy/billing-header-rectifier.test.ts
  • tests/unit/proxy/cache-ttl-override.test.ts
  • tests/unit/proxy/proxy-forwarder-hedge-first-byte.test.ts
  • tests/unit/proxy/replay-spool.test.ts
🚧 Files skipped from review as they are similar to previous changes (1)
  • src/lib/api/v1/schemas/system-config.ts

…1411)

* fix(stream-gate): recognize Responses compaction in terminal frames

Some Responses upstreams return compaction output only in
response.completed without first emitting response.output_item.done,
so the content gate treated the stream as empty and triggered false
failover with circuit-breaking.

classifyParsedFrame now accepts the protocol family and, for
openai-responses, detects a compaction output item with non-empty
encrypted_content inside response.completed, classifying the frame
as content so the gate commits the stream.

Regression tests cover compaction-only terminal frames and custom
tool-call input deltas across the classifier, content gate, and
forwarder integration paths.

Fixes #1410

* fix(stream-gate): require non-empty string for compaction encrypted_content

The compaction signal rule on response.output_item.done accepted any
truthy encrypted_content value, allowing non-string types (booleans,
numbers, objects) to be misclassified as content. Consolidate the
per-item type guard into isNonEmptyCompactionItem and apply it to both
response.output_item.done and response.completed paths so the opaque
state must be a non-empty string before a frame is committed as
content.

Add regression tests covering malformed encrypted_content types across
event variants.
@github-actions

Copy link
Copy Markdown
Contributor

🧪 测试结果

测试类型 状态
代码质量
单元测试
集成测试
API 测试

总体结果: ✅ 所有测试通过

fix(proxy): bound Replay disconnect memory retention (#1408)
@github-actions

Copy link
Copy Markdown
Contributor

🧪 测试结果

测试类型 状态
代码质量
单元测试
集成测试
API 测试

总体结果: ✅ 所有测试通过

LamClod and others added 2 commits August 12, 2026 15:49
* feat(availability): outbox + 1m projection buckets for admin monitoring

Replace on-the-fly message_request scans with trigger/outbox-fed
avail_bucket_1m/avail_current so availability APIs stay fast under load.

* fix(availability): address review on projection freshness and worker safety

* fix(availability): stable provider lock order in projection worker

Sort provider/bucket ids before upsert and recompute so concurrent
worker instances take avail_current locks in the same order.
Co-authored-by: GPT-5 <noreply@openai.com>
Deduplicate request-scoped Redis session response bodies while preserving legacy reader compatibility, response snapshot semantics, redaction boundaries, TTL behavior, and termination cleanup.\n\nAdd generation fencing for late writers, atomic legacy fallback reads, full-session cleanup coverage, Redis integration regression tests, and the 64 x 5 MiB RDB load fixture.\n\nCloses #1415
Reformats floorToUtcMinute and projection-worker test mocks to
satisfy Biome line-width rules. Reorders CURRENT_PROVIDER_STATUS_WINDOW_MINUTES
ahead of the calculateAvailabilityScore export in index.ts to
match alphabetical sorting.
@github-actions

Copy link
Copy Markdown
Contributor

🧪 测试结果

测试类型 状态
代码质量
单元测试
集成测试
API 测试

总体结果: ✅ 所有测试通过

@ding113
ding113 merged commit c1a392f into main Aug 12, 2026
15 checks passed
@github-project-automation github-project-automation Bot moved this from Backlog to Done in Claude Code Hub Roadmap Aug 12, 2026
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

size/XL Extra Large PR (> 1000 lines)

Projects

Status: Done

Development

Successfully merging this pull request may close these issues.

4 participants