Skip to content

PR: 修复 Edge Runtime 下 process.once 构建告警(AsyncTaskManager 导入链)#589

Merged
ding113 merged 14 commits intoding113:devfrom
YangQing-Lin:fix/edge-runtime-process-once
Jan 11, 2026
Merged

PR: 修复 Edge Runtime 下 process.once 构建告警(AsyncTaskManager 导入链)#589
ding113 merged 14 commits intoding113:devfrom
YangQing-Lin:fix/edge-runtime-process-once

Conversation

@YangQing-Lin
Copy link
Collaborator

@YangQing-Lin YangQing-Lin commented Jan 11, 2026

Summary

Fix Edge Runtime build warnings caused by process.once Node.js API usage in AsyncTaskManager import chain. The fix skips initialization in Edge/CI/build environments and uses dynamic imports to prevent static bundling.

Related Issues:


基本信息

  • Target branch: dev
  • Branch: fix/edge-runtime-process-once
  • 范围:后端基础设施(AsyncTaskManager)+ 价格表云端同步触发器(cloud-price-updater)+ 单测/文档

背景与问题

next build(Turbopack/Next)过程中出现 Edge Runtime 告警:process.once 属于 Node.js API,Edge Runtime 不支持。

复现基线(修复前)

  • 基线提交:820b519b
  • 基线命令:bun run build
  • 现象:稳定出现 3 条告警(分别指向 process.once 的 47/48/49 行),Import trace 包含:
    • src/lib/async-task-manager.ts
    • src/lib/price-sync/cloud-price-updater.ts
    • src/instrumentation.ts

问题根因:AsyncTaskManager 在模块初始化时注册 process.once(...) 退出信号 hook,被 instrumentation.ts -> cloud-price-updater.ts 的依赖链拉入 "Edge Instrumentation" bundle,触发静态分析告警。

变更概览

目标:不改变生产 Node runtime 行为的前提下,让 Edge bundle 不再看到 process.once(两层隔离:避免静态拉入 + 运行时 no-op)。

1) AsyncTaskManager:Edge/CI/build 环境跳过初始化(避免 Node-only API 与副作用)

  • 在构造函数中增加环境判断:NEXT_RUNTIME === "edge" || CI === "true" || NEXT_PHASE === "phase-production-build" 时直接 return,避免触发 process.oncesetInterval 等初始化副作用。
  • 相关文件:
    • src/lib/async-task-manager.ts:30

2) cloud-price-updater:移除静态 import,按需动态 import + Edge runtime no-op

  • 移除对 AsyncTaskManager 的顶层静态 import,避免 Edge bundle 静态拉入。
  • requestCloudPriceTableSync() 内部动态 import("@/lib/async-task-manager"),并在 NEXT_RUNTIME === "edge" 时直接 return(no-op)。
  • 额外:增加全局 scheduling flag,避免并发请求在 AsyncTaskManager 加载前重复触发。
  • 相关文件:
    • src/lib/price-sync/cloud-price-updater.ts:56

3) 单测补齐:Edge runtime 分支与调度逻辑可回归

  • 覆盖 NEXT_RUNTIME=edge 时不调用 process.once,以及 Node runtime 下 exit hooks/interval 行为。
    • tests/unit/lib/async-task-manager-edge-runtime.test.ts:17
  • 覆盖 requestCloudPriceTableSync() 在 Edge runtime 下不加载 AsyncTaskManager,以及节流/并发/异常分支。
    • tests/unit/price-sync/cloud-price-updater.test.ts:243

4) 文档:告警基线、修复策略、回滚/备选方案落盘

  • docs/edge-runtime-process-once.md:1

测试与验证

必跑清单(CLAUDE.md)

  • bun run lint
  • bun run typecheck
  • bun run build (不再出现 Edge Runtime process.once 相关告警)

Targeted coverage(仅统计本次相关文件)

说明:项目当前全量 test:coverage 覆盖率未达 90%,本 PR 以"本次变更相关文件 targeted coverage"作为门禁(覆盖率目标 >=90%)。

bunx vitest run tests/unit/lib/async-task-manager-edge-runtime.test.ts tests/unit/price-sync/cloud-price-updater.test.ts --coverage --coverage.provider v8 --coverage.reporter text --coverage.reporter html --coverage.reporter json --coverage.reportsDirectory ./coverage-edgeonce --coverage.include src/lib/async-task-manager.ts --coverage.include src/lib/price-sync/cloud-price-updater.ts && bun run build
  • 结果:All files 100%(Statements / Branches / Functions / Lines)

风险与回滚

风险

  • AsyncTaskManagerCI === "true" / NEXT_PHASE === "phase-production-build" 时跳过初始化:不会注册 exit hooks/cleanup interval;但核心注册/去重能力仍可用(单测覆盖)。需确保不会有依赖"CI 环境也需要 signal hooks"的隐含行为。
  • requestCloudPriceTableSync() 在 Edge runtime 下 no-op:如果未来新增真正运行在 Edge 的触发点,仍需确认该行为符合预期(当前目标是让 Edge bundle 不触发 Node-only API)。

回滚

按提交粒度回退即可(无 schema/数据迁移):

  • 9b54b107 fix: skip async task manager init on edge
  • 56a01255 fix: avoid static async task manager import
  • 1152cdad test: cover edge runtime task scheduling

Commit 列表

  • 9b54b107 fix: skip async task manager init on edge
  • 56a01255 fix: avoid static async task manager import
  • 1152cdad test: cover edge runtime task scheduling
  • cf63b046 chore: document edge runtime process.once fix
  • f968ac4 chore: record edge runtime warning baseline

PR Checklist(提交前自检)

  • 目标分支为 dev
  • 修复前基线可复现:820b519b + bun run build 出现 3 条告警(process.once 47/48/49 行)
  • 修复后 bun run build 不再出现 Edge Runtime process.once 相关告警
  • 不改变生产 Node runtime 行为(仅在 edge/CI/build 环境跳过初始化)
  • 单测覆盖关键分支,targeted coverage >=90%

Description enhanced by Claude AI

Greptile Overview

Greptile Summary

Overview

This PR addresses Edge Runtime build warnings caused by process.once usage in AsyncTaskManager being statically imported into the Edge bundle via instrumentation.ts. The fix employs a two-layer defense: lazy initialization in AsyncTaskManager and dynamic imports in cloud-price-updater.

Implementation Strategy

AsyncTaskManager (src/lib/async-task-manager.ts)

  • Converts from constructor-based to lazy initialization pattern
  • Defers Node.js API calls (process.once, setInterval) until first register() call
  • Skips initialization in Edge/CI environments

cloud-price-updater (src/lib/price-sync/cloud-price-updater.ts)

  • Removes static import of AsyncTaskManager (prevents bundler from pulling it into Edge bundle)
  • Uses dynamic import() inside async function, only in Node.js runtime
  • Adds early return for NEXT_RUNTIME === "edge"
  • Implements global scheduling flag to prevent concurrent loading races

Critical Issue Found

⚠️ Missing NEXT_PHASE Check: The PR description explicitly states that the code should check for NEXT_PHASE === "phase-production-build", and the original code had this check. However, the new implementation at line 39 of async-task-manager.ts only checks:

if (process.env.NEXT_RUNTIME === "edge" || process.env.CI === "true")

The NEXT_PHASE === "phase-production-build" condition is missing. This is inconsistent with:

  1. The PR description's stated implementation
  2. Other files in the codebase (redis/client.ts, cache/provider-cache.ts) which still check this condition
  3. The original code that was replaced

Without this check, AsyncTaskManager may initialize during the production build phase, potentially causing the same process.once warnings this PR aims to eliminate.

Other Issues

  1. Documentation Mismatch: The documentation doesn't fully reflect what the code actually does (doesn't mention CI check, incorrectly describes NEXT_PHASE behavior)
  2. Test Gap: Tests don't explicitly verify that CI environment skips Node-only initialization (exit hooks and cleanup interval)

Positive Aspects

  • Dynamic import strategy is sound and properly prevents static bundling
  • Scheduling flag correctly prevents race conditions
  • Error handling is comprehensive with proper logging
  • Test coverage is generally thorough (100% as claimed)
  • The lazy initialization pattern is well-implemented

Confidence Score: 2/5

  • This PR has a critical discrepancy between description and implementation that could leave the original issue unresolved
  • Score of 2 reflects a critical logic issue: the missing NEXT_PHASE check means the code may not fully achieve its stated goal of eliminating build warnings. While the dynamic import strategy is sound, the incomplete environment detection in AsyncTaskManager could allow process.once to be called during production builds. This creates a high risk that the PR's primary objective - eliminating Edge Runtime warnings during build - may not be achieved. The implementation is otherwise well-structured with good test coverage, but the core fix is incomplete.
  • Primary attention needed: src/lib/async-task-manager.ts (line 39 - add missing NEXT_PHASE check). Secondary: docs/edge-runtime-process-once.md (update to match actual implementation)

Important Files Changed

File Analysis

Filename Score Overview
src/lib/async-task-manager.ts 3/5 Implements lazy initialization to defer Node-only APIs, but missing NEXT_PHASE check mentioned in PR description, creating potential build-time warnings
src/lib/price-sync/cloud-price-updater.ts 4/5 Successfully moves to dynamic import with proper edge runtime guard and concurrency protection via scheduling flag
docs/edge-runtime-process-once.md 3/5 Documentation doesn't fully match implementation - omits CI check and mentions missing NEXT_PHASE condition

Sequence Diagram

sequenceDiagram
    participant App as Application Code
    participant CPU as cloud-price-updater
    participant ATM as AsyncTaskManager
    participant Node as Node.js APIs

    Note over App,Node: Edge Runtime Bundle Analysis
    App->>CPU: import (static)
    Note over CPU: ❌ Old: static import ATM
    Note over CPU: ✅ New: no static import

    Note over App,Node: Runtime Execution Flow
    App->>CPU: requestCloudPriceTableSync()
    
    alt NEXT_RUNTIME === "edge"
        CPU-->>App: return early (no-op)
    else Node.js runtime
        CPU->>CPU: Check throttle
        alt Within throttle window
            CPU-->>App: return early
        else Can proceed
            CPU->>CPU: Set scheduling flag
            CPU->>ATM: dynamic import()
            ATM->>ATM: initializeIfNeeded()
            
            alt edge/CI environment
                ATM->>ATM: Set initialized=true
                ATM-->>ATM: Skip hooks (return early)
            else Normal Node.js
                ATM->>ATM: Set initialized=true
                ATM->>Node: process.once(SIGTERM)
                ATM->>Node: process.once(SIGINT)
                ATM->>Node: process.once(beforeExit)
                ATM->>Node: setInterval(cleanup, 60s)
            end
            
            CPU->>ATM: getActiveTasks()
            alt Task already running
                CPU-->>CPU: return early
            else No active task
                CPU->>ATM: register(taskId, promise)
                ATM->>ATM: Track task
            end
            
            CPU->>CPU: Clear scheduling flag
        end
    end
Loading

@coderabbitai
Copy link

coderabbitai bot commented Jan 11, 2026

📝 Walkthrough

Walkthrough

在 Edge 运行时跳过 AsyncTaskManager 的 Node 特定初始化;cloud-price-updater 改为运行时动态导入 AsyncTaskManager 并添加节流与并发保护;新增文档与针对 Edge/非 Edge 行为的单元测试及测试改造。

Changes

内聚体 / 文件(s) 变更摘要
文档新增
docs/edge-runtime-process-once.md
新增文档,说明 Edge Runtime 中抑制 Node API process.once 警告的背景、复现步骤、变更点、验证、回滚与快速定位命令。
AsyncTaskManager 核心库
src/lib/async-task-manager.ts
添加延迟初始化(私有已初始化标志与 initializeIfNeeded()),在 NEXT_RUNTIME === "edge" / CI === "true" / 构建环境下跳过初始化;在 register 前触发初始化以避免导入时副作用;保留现有生命周期与清理逻辑并增强日志。
价格同步模块
src/lib/price-sync/cloud-price-updater.ts
移除静态导入,改为受保护的异步块内动态导入 AsyncTaskManager;在 Edge 运行时提前返回;引入全局节流(last-at)、并发调度保护标志、重复任务检测、错误处理与更详尽日志;确保调度标志在异常时重置。
新增单元测试(AsyncTaskManager Edge 行为)
tests/unit/lib/async-task-manager-edge-runtime.test.ts
新增全面测试,覆盖 Edge 与 Node 运行时差异、exit 钩子与清理、任务注册/取消/老化逻辑、错误分支与间隔管理,使用动态导入与环境切换隔离测试状态。
更新单元测试(price-sync)
tests/unit/price-sync/cloud-price-updater.test.ts
将测试改为按需动态导入与按测试切换模拟;新增 flush/reset 辅助、节流与调度标志用例、Edge 路径无导入断言、错误与日志断言,验证新的异步调度与重试/失败路径。

Estimated code review effort

🎯 3 (中等) | ⏱️ ~25 分钟

🚥 Pre-merge checks | ✅ 2 | ❌ 1
❌ Failed checks (1 warning)
Check name Status Explanation Resolution
Docstring Coverage ⚠️ Warning Docstring coverage is 50.00% which is insufficient. The required threshold is 80.00%. Write docstrings for the functions missing them to satisfy the coverage threshold.
✅ Passed checks (2 passed)
Check name Status Explanation
Title check ✅ Passed 标题清晰准确地总结了PR的主要目标:修复 Edge Runtime 下 process.once 构建告警,并指出了问题所在的 AsyncTaskManager 导入链。
Description check ✅ Passed PR描述详细阐述了问题背景、修改概览、测试验证和风险回滚计划,与变更集高度相关,包括所有相关文件的具体改动。

✏️ Tip: You can configure your own custom pre-merge checks in the settings.

✨ Finishing touches
  • 📝 Generate docstrings
🧪 Generate unit tests (beta)
  • Create PR with unit tests
  • Post copyable unit tests in a comment

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

@gemini-code-assist
Copy link
Contributor

Summary of Changes

Hello @YangQing-Lin, 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!

此拉取请求旨在解决 Next.js 应用在 Edge Runtime 下构建时出现的 process.once 告警。通过对 AsyncTaskManager 的初始化逻辑进行环境判断,并修改 cloud-price-updater 以动态导入 AsyncTaskManager 并在 Edge 环境下禁用其功能,确保了构建过程的顺利进行,同时不影响 Node.js 生产环境的正常行为。这些变更有效地隔离了 Node.js 专属 API,使其不会被静态分析工具误判为 Edge Runtime 的一部分。

Highlights

  • AsyncTaskManager 初始化优化: 在 Edge Runtime、CI 环境和生产构建阶段跳过 AsyncTaskManager 的初始化,以避免引入 Node.js 独有的 API(如 process.once)和副作用。
  • cloud-price-updater 动态导入: 移除了 cloud-price-updaterAsyncTaskManager 的静态导入,改为在 requestCloudPriceTableSync() 函数内部按需动态导入,并在 Edge Runtime 环境下直接执行 no-op,进一步隔离 Node.js API。
  • 新增与完善单元测试: 新增了针对 AsyncTaskManager 在 Edge Runtime 环境下行为的单元测试,并完善了 cloud-price-updater 的测试,覆盖了 Edge Runtime 分支、调度逻辑、节流和并发处理。
  • 新增修复文档: 添加了详细的文档,记录了 process.once 告警的背景、复现基线、修复策略、验证步骤、回滚方案以及备选方案。
Using Gemini Code Assist

The 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 /gemini <command> or @gemini-code-assist <command>. Below is a summary of the supported commands on the current page.

Feature Command Description
Code Review /gemini review Performs a code review for the current pull request in its current state.
Pull Request Summary /gemini summary Provides a summary of the current pull request in its current state.
Comment @gemini-code-assist Responds in comments when explicitly tagged, both in pull request comments and review comments.
Help /gemini help Displays a list of available commands.

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 .gemini/ folder in the base of the repository. Detailed instructions can be found here.

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

  1. Review the Privacy Notices, Generative AI Prohibited Use Policy, Terms of Service, and learn how to configure Gemini Code Assist in GitHub here. Gemini can make mistakes, so double check it and use code with caution.

@github-actions github-actions bot added bug Something isn't working area:core labels Jan 11, 2026
Copy link
Contributor

@gemini-code-assist gemini-code-assist bot left a comment

Choose a reason for hiding this comment

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

Code Review

本次 PR 成功解决了 Edge Runtime 下的构建告警问题,实现方式清晰且健壮。通过将 AsyncTaskManager 的静态导入改为动态导入,并增加环境判断,有效地避免了在 Edge 环境中引入 Node.js 专用的 API。值得称赞的是,在 cloud-price-updater 中引入的 __CCH_CLOUD_PRICE_SYNC_SCHEDULING__ 标志,这是一个非常周全的考虑,有效地防止了并发请求可能导致的竞态条件。此外,本次提交附带了非常详尽的单元测试,覆盖了新的逻辑分支和各种边缘情况,确保了代码的质量和稳定性。新添加的文档也清晰地说明了问题背景、解决方案和验证步骤。总体而言,这是一次高质量的修复,代码结构清晰,考虑周全,测试充分。


## 备注

`.codex/plan/` 与 `.codex/issues/` 属于本地任务落盘目录,不应提交到 Git。
Copy link
Contributor

Choose a reason for hiding this comment

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

medium

这条备注很有用。为了从根本上防止这些目录被意外提交,强烈建议将 .codex/ 添加到项目根目录的 .gitignore 文件中。这样可以利用版本控制系统自动忽略这些文件,比依赖开发者阅读文档更可靠。

Comment on lines +68 to +71
const g = globalThis as unknown as {
__CCH_CLOUD_PRICE_SYNC_LAST_AT__?: number;
__CCH_CLOUD_PRICE_SYNC_SCHEDULING__?: boolean;
};
Copy link
Contributor

Choose a reason for hiding this comment

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

medium

globalThis 的类型断言目前是局部定义的。为了提高代码的可维护性和类型安全性,建议在项目中创建一个全局声明文件(例如 src/types/global.d.ts)来扩展 globalThis 的类型。这样做可以避免在多处重复使用 as unknown as ...,并为这些全局属性提供一个单一、可信的类型定义来源,使得代码更清晰、更易于管理。

例如,在 src/types/global.d.ts 中可以这样定义:

declare global {
  // eslint-disable-next-line no-var
  var __CCH_CLOUD_PRICE_SYNC_LAST_AT__: number | undefined;
  // eslint-disable-next-line no-var
  var __CCH_CLOUD_PRICE_SYNC_SCHEDULING__: boolean | undefined;
}

之后在此文件中就可以直接使用 globalThis,无需类型断言。

Copy link

@greptile-apps greptile-apps bot left a comment

Choose a reason for hiding this comment

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

1 file reviewed, no comments

Edit Code Review Agent Settings | Greptile

@github-actions github-actions bot added the size/L Large PR (< 1000 lines) label Jan 11, 2026
Copy link

@coderabbitai coderabbitai bot left a comment

Choose a reason for hiding this comment

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

Actionable comments posted: 3

🤖 Fix all issues with AI agents
In @docs/edge-runtime-process-once.md:
- Around line 7-24: The doc currently binds fragile details (specific line
numbers "process.once at line: 47/48/49" and commit hash "820b519b") which can
drift; update docs/edge-runtime-process-once.md to remove fixed line numbers and
the raw commit hash: replace line-number mentions with a note like "line number
shown in the build output" or omit them and keep only the import trace, and
change the commit reference to a stable identifier (e.g., commit message + PR
#589 or a tag/link) while keeping the import trace entries
(`src/lib/async-task-manager.ts`, `src/lib/price-sync/cloud-price-updater.ts`,
`src/instrumentation.ts`) and the `process.once` API name for context.

In @src/lib/async-task-manager.ts:
- Around line 31-41: The initialization conditional in AsyncTaskManager
currently checks process.env.NEXT_PHASE (a build-time variable) which shouldn't
be relied on at runtime; replace the NEXT_PHASE check with runtime-based checks
using process.env.NEXT_RUNTIME (e.g., compare to "edge" or "nodejs") and remove
dependence on NEXT_PHASE, updating the same conditional that calls logger.debug;
if you need canonical names for Next phases or constants, import the appropriate
symbols from 'next/constants' instead of hardcoding strings, but ensure the
runtime guard uses process.env.NEXT_RUNTIME and process.env.CI only.

In @tests/unit/price-sync/cloud-price-updater.test.ts:
- Around line 244-255: The tests rely on non-Edge behavior so explicitly clear
or set NEXT_RUNTIME in the beforeEach to avoid external env interference: inside
the beforeEach that already calls vi.clearAllMocks/vi.resetModules and
manipulates asyncTasks, add logic to delete or set process.env.NEXT_RUNTIME
(e.g., delete process.env.NEXT_RUNTIME or set to "nodejs") so
requestCloudPriceTableSync won't short-circuit when process.env.NEXT_RUNTIME is
"edge"; target the beforeEach surrounding the describe for
requestCloudPriceTableSync and reference process.env.NEXT_RUNTIME and the
requestCloudPriceTableSync tests when making the change.
🧹 Nitpick comments (4)
src/lib/async-task-manager.ts (1)

30-43: 环境 guard 的“早返回”语义建议显式化(避免误以为禁用整个管理器)

当前做法会“跳过 exit hooks/interval 注册”,但实例仍会被创建、register/cancel 等仍可用。建议加一个内部标记(如 this.initialized = false)或在类注释里明确:仅跳过 Node side-effects,而不是禁用任务管理能力,避免后续维护者误判。

src/lib/price-sync/cloud-price-updater.ts (2)

60-63: Edge runtime 直接 no-op OK,但建议留一个 debug 级别可观测点(可选)

现在 Edge 下静默返回;如果未来有人误以为 Edge 会触发同步,排查会更慢。可以考虑 logger.debug 记录一次被短路的 reason(注意避免过于频繁)。


68-83: 并发/去重策略整体合理;建议补一个“失败退避”以防持续调度失败时刷屏

scheduling 标记能防止 AsyncTaskManager 尚未加载前的并发重复触发,这是关键点,且 finally 里复位也很稳。

但如果动态 import/调度链路持续失败(例如运行环境缺依赖),当前会在每次请求都尝试并打 warn。可选优化:

  • catch 里也更新 __CCH_CLOUD_PRICE_SYNC_LAST_AT__ = Date.now()(或引入单独的 failure throttle),降低失败时的日志与开销。

Also applies to: 84-128

tests/unit/lib/async-task-manager-edge-runtime.test.ts (1)

282-311: cleanupAll 用例里最后的 clearInterval 可能是冗余调用(可选精简)

managerAny.cleanupAll() 已经会 clearInterval(intervalId) 并将 cleanupInterval 置空;这里再 clearInterval(intervalId) 会重复一次调用(虽然不影响断言)。可以考虑删掉最后一行,减少噪音。

📜 Review details

Configuration used: Organization UI

Review profile: CHILL

Plan: Pro

Cache: Disabled due to Reviews > Disable Cache setting

📥 Commits

Reviewing files that changed from the base of the PR and between 820b519 and f968ac4.

📒 Files selected for processing (5)
  • docs/edge-runtime-process-once.md
  • src/lib/async-task-manager.ts
  • src/lib/price-sync/cloud-price-updater.ts
  • tests/unit/lib/async-task-manager-edge-runtime.test.ts
  • tests/unit/price-sync/cloud-price-updater.test.ts
🧰 Additional context used
📓 Path-based instructions (5)
**/*.{js,ts,tsx,jsx}

📄 CodeRabbit inference engine (CLAUDE.md)

Never use emoji characters in any code, comments, or string literals

Files:

  • src/lib/price-sync/cloud-price-updater.ts
  • tests/unit/lib/async-task-manager-edge-runtime.test.ts
  • src/lib/async-task-manager.ts
  • tests/unit/price-sync/cloud-price-updater.test.ts
**/*.{ts,tsx,js,jsx}

📄 CodeRabbit inference engine (CLAUDE.md)

**/*.{ts,tsx,js,jsx}: All user-facing strings must use i18n (5 languages supported: zh-CN, zh-TW, en, ja, ru). Never hardcode display text
Use path alias @/ to reference files in ./src/ directory
Format code with Biome using: double quotes, trailing commas, 2-space indent, 100 character line width

Files:

  • src/lib/price-sync/cloud-price-updater.ts
  • tests/unit/lib/async-task-manager-edge-runtime.test.ts
  • src/lib/async-task-manager.ts
  • tests/unit/price-sync/cloud-price-updater.test.ts
**/*.{ts,tsx}

📄 CodeRabbit inference engine (CLAUDE.md)

Prefer named exports over default exports

Files:

  • src/lib/price-sync/cloud-price-updater.ts
  • tests/unit/lib/async-task-manager-edge-runtime.test.ts
  • src/lib/async-task-manager.ts
  • tests/unit/price-sync/cloud-price-updater.test.ts
**/*.test.{ts,tsx,js,jsx}

📄 CodeRabbit inference engine (CLAUDE.md)

All new features must have unit test coverage of at least 80%

Files:

  • tests/unit/lib/async-task-manager-edge-runtime.test.ts
  • tests/unit/price-sync/cloud-price-updater.test.ts
tests/**/*.test.{ts,tsx,js,jsx}

📄 CodeRabbit inference engine (CLAUDE.md)

Use Vitest for unit testing and happy-dom for DOM testing

Files:

  • tests/unit/lib/async-task-manager-edge-runtime.test.ts
  • tests/unit/price-sync/cloud-price-updater.test.ts
🧠 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/lib/price-sync/cloud-price-updater.ts
  • src/lib/async-task-manager.ts
📚 Learning: 2026-01-10T17:53:25.066Z
Learnt from: CR
Repo: ding113/claude-code-hub PR: 0
File: CLAUDE.md:0-0
Timestamp: 2026-01-10T17:53:25.066Z
Learning: Applies to tests/**/*.test.{ts,tsx,js,jsx} : Use Vitest for unit testing and happy-dom for DOM testing

Applied to files:

  • tests/unit/lib/async-task-manager-edge-runtime.test.ts
  • tests/unit/price-sync/cloud-price-updater.test.ts
🧬 Code graph analysis (3)
src/lib/price-sync/cloud-price-updater.ts (2)
src/lib/async-task-manager.ts (1)
  • AsyncTaskManager (240-241)
src/lib/logger.ts (1)
  • logger (168-187)
tests/unit/lib/async-task-manager-edge-runtime.test.ts (3)
src/lib/async-task-manager.ts (1)
  • AsyncTaskManager (240-241)
src/lib/logger.ts (1)
  • logger (168-187)
src/app/v1/_lib/proxy/errors.ts (1)
  • isClientAbortError (617-636)
src/lib/async-task-manager.ts (1)
src/lib/logger.ts (1)
  • logger (168-187)
⏰ 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: 🌐 API Tests
  • GitHub Check: Docker Build Test
  • GitHub Check: pr-review
  • GitHub Check: check-codex-status
  • GitHub Check: pr-label
  • GitHub Check: pr-description
🔇 Additional comments (4)
docs/edge-runtime-process-once.md (1)

25-57: 变更/验证/回滚结构清晰,可作为后续排障模板保留

变更点与验证命令写得很具体,且明确了 Edge no-op 与动态 import 的策略;“本地任务落盘目录不应提交”也很有用。

tests/unit/lib/async-task-manager-edge-runtime.test.ts (1)

17-50: 测试隔离做得比较到位(env + global 单例 + resetModules)

vi.resetModules() 配合清理 globalThis.__ASYNC_TASK_MANAGER__,能保证每个 case 都从“模块初始化”重新走一遍,覆盖 edge/nodejs 分支也更可信。

tests/unit/price-sync/cloud-price-updater.test.ts (1)

18-29: Edge no-op 覆盖方式合理:用“是否加载 AsyncTaskManager”作为可观测信号

通过 mock 工厂里翻转 asyncTaskManagerLoaded 来判定模块是否被动态 import,能直接验证“Edge 下不应进入导入链”,与本 PR 目标一致。

Also applies to: 256-267

src/lib/price-sync/cloud-price-updater.ts (1)

86-119: 动态 import 方案确认有效

验证结果:

  • src/instrumentation.ts(Next.js instrumentation 入口)无静态导入 AsyncTaskManager,所有导入均为动态导入
  • src/lib/price-sync/cloud-price-updater.ts 已正确改用动态导入
  • src/app/v1/_lib/proxy/response-handler.ts 虽有静态导入,但仅在声明 runtime = "nodejs" 的 Node.js 运行时路由中使用,不涉及 Edge 打包

核心入口点已消除 Edge 打包的静态导入告警,当前实现符合目标。

Copy link
Contributor

@github-actions github-actions bot left a comment

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: L

  • Lines changed: 684
  • Files changed: 5
  • Split suggestion: consider splitting into (1) runtime fix (src/lib/*) and (2) tests/docs (tests/, docs/) to reduce review and rollback surface.

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

Copy link
Contributor

@github-actions github-actions bot left a comment

Choose a reason for hiding this comment

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

  • Completed a multi-perspective review of PR #589 (files in src/lib/*, tests/unit/*, and docs/*).
  • Applied PR size label: size/L (684 lines changed across 5 files).
  • Posted the required review summary via gh pr review; no inline review comments were filed because no issues met the reporting threshold.

Copy link
Contributor

@github-actions github-actions bot left a comment

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. The implementation correctly addresses the Edge Runtime process.once build warnings by:

  1. AsyncTaskManager: Adding environment checks to skip Node-only API initialization in Edge/CI/build environments
  2. cloud-price-updater: Converting static import to dynamic import with Edge runtime no-op guard
  3. Concurrency protection: Adding a scheduling flag to prevent duplicate task scheduling during dynamic import

PR Size: L

  • Lines changed: 684 (630 additions, 54 deletions)
  • Files changed: 5

Review Coverage

  • Logic and correctness - Clean
  • Security (OWASP Top 10) - Clean
  • Error handling - Clean (proper logging in catch blocks at lines 119-122)
  • Type safety - Clean
  • Documentation accuracy - Clean
  • Test coverage - Adequate (new tests cover Edge runtime branches, scheduling guards, and error paths)
  • Code clarity - Good

Analysis Notes

Perspective 1 (Comment Analyzer): No inaccurate or outdated comments found. Comments accurately describe the intent (e.g., "Skip initialization in non-Node runtimes").

Perspective 2 (Test Analyzer): The new test files provide comprehensive coverage:

  • async-task-manager-edge-runtime.test.ts: Covers Edge runtime skipping, Node runtime initialization, signal handlers, cleanup interval, and task lifecycle
  • cloud-price-updater.test.ts: Covers Edge runtime no-op, throttling, scheduling flag, error handling branches

Perspective 3 (Silent Failure Hunter): Error handling is appropriate:

  • cloud-price-updater.ts:119-122: Errors are caught and logged with context
  • The Edge runtime early returns are intentional no-ops as documented

Perspective 4 (Type Design Auditor): No any types introduced. TypeScript types are properly maintained.

Perspective 5 (General Code Review):

  • No logic bugs detected
  • No security vulnerabilities introduced
  • Dynamic import pattern is correct for Edge compatibility
  • Scheduling flag prevents race conditions during async import

Perspective 6 (Code Simplifier): Code structure is clean and straightforward. The IIFE pattern for fire-and-forget async is appropriate.


Automated review by Claude AI

@github-project-automation github-project-automation bot moved this from Backlog to Done in Claude Code Hub Roadmap Jan 11, 2026
@YangQing-Lin YangQing-Lin reopened this Jan 11, 2026
@YangQing-Lin
Copy link
Collaborator Author

修复 coderabbitai 提到的三个问题

Copy link

@coderabbitai coderabbitai bot left a comment

Choose a reason for hiding this comment

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

Actionable comments posted: 0

🧹 Nitpick comments (1)
tests/unit/price-sync/cloud-price-updater.test.ts (1)

268-279: 变量名遮蔽问题。

第 269 行声明的 prevRuntime 遮蔽了外层作用域(第 244 行)声明的同名变量。虽然功能正确,但降低了代码可读性。

♻️ 建议的重构
  it("no-ops in Edge runtime (does not load AsyncTaskManager)", async () => {
-   const prevRuntime = process.env.NEXT_RUNTIME;
    process.env.NEXT_RUNTIME = "edge";

    const { requestCloudPriceTableSync } = await import("@/lib/price-sync/cloud-price-updater");
    requestCloudPriceTableSync({ reason: "missing-model", throttleMs: 0 });
    await flushAsync();

    expect(asyncTaskManagerLoaded).toBe(false);
-
-   process.env.NEXT_RUNTIME = prevRuntime;
  });

说明:由于 afterEach 钩子已经负责恢复 NEXT_RUNTIME,测试内部不需要重复保存和恢复。

📜 Review details

Configuration used: Organization UI

Review profile: CHILL

Plan: Pro

Cache: Disabled due to Reviews > Disable Cache setting

📥 Commits

Reviewing files that changed from the base of the PR and between f968ac4 and 4bc4d15.

📒 Files selected for processing (4)
  • docs/edge-runtime-process-once.md
  • src/lib/async-task-manager.ts
  • tests/unit/lib/async-task-manager-edge-runtime.test.ts
  • tests/unit/price-sync/cloud-price-updater.test.ts
🚧 Files skipped from review as they are similar to previous changes (1)
  • src/lib/async-task-manager.ts
🧰 Additional context used
📓 Path-based instructions (5)
**/*.{js,ts,tsx,jsx}

📄 CodeRabbit inference engine (CLAUDE.md)

Never use emoji characters in any code, comments, or string literals

Files:

  • tests/unit/price-sync/cloud-price-updater.test.ts
  • tests/unit/lib/async-task-manager-edge-runtime.test.ts
**/*.test.{ts,tsx,js,jsx}

📄 CodeRabbit inference engine (CLAUDE.md)

All new features must have unit test coverage of at least 80%

Files:

  • tests/unit/price-sync/cloud-price-updater.test.ts
  • tests/unit/lib/async-task-manager-edge-runtime.test.ts
**/*.{ts,tsx,js,jsx}

📄 CodeRabbit inference engine (CLAUDE.md)

**/*.{ts,tsx,js,jsx}: All user-facing strings must use i18n (5 languages supported: zh-CN, zh-TW, en, ja, ru). Never hardcode display text
Use path alias @/ to reference files in ./src/ directory
Format code with Biome using: double quotes, trailing commas, 2-space indent, 100 character line width

Files:

  • tests/unit/price-sync/cloud-price-updater.test.ts
  • tests/unit/lib/async-task-manager-edge-runtime.test.ts
**/*.{ts,tsx}

📄 CodeRabbit inference engine (CLAUDE.md)

Prefer named exports over default exports

Files:

  • tests/unit/price-sync/cloud-price-updater.test.ts
  • tests/unit/lib/async-task-manager-edge-runtime.test.ts
tests/**/*.test.{ts,tsx,js,jsx}

📄 CodeRabbit inference engine (CLAUDE.md)

Use Vitest for unit testing and happy-dom for DOM testing

Files:

  • tests/unit/price-sync/cloud-price-updater.test.ts
  • tests/unit/lib/async-task-manager-edge-runtime.test.ts
🧠 Learnings (3)
📚 Learning: 2026-01-10T17:53:25.066Z
Learnt from: CR
Repo: ding113/claude-code-hub PR: 0
File: CLAUDE.md:0-0
Timestamp: 2026-01-10T17:53:25.066Z
Learning: Applies to tests/**/*.test.{ts,tsx,js,jsx} : Use Vitest for unit testing and happy-dom for DOM testing

Applied to files:

  • tests/unit/price-sync/cloud-price-updater.test.ts
  • tests/unit/lib/async-task-manager-edge-runtime.test.ts
📚 Learning: 2026-01-10T17:53:25.066Z
Learnt from: CR
Repo: ding113/claude-code-hub PR: 0
File: CLAUDE.md:0-0
Timestamp: 2026-01-10T17:53:25.066Z
Learning: Applies to **/*.test.{ts,tsx,js,jsx} : All new features must have unit test coverage of at least 80%

Applied to files:

  • tests/unit/lib/async-task-manager-edge-runtime.test.ts
📚 Learning: 2026-01-10T06:20:04.478Z
Learnt from: NieiR
Repo: ding113/claude-code-hub PR: 573
File: src/actions/model-prices.ts:275-335
Timestamp: 2026-01-10T06:20:04.478Z
Learning: In the `ding113/claude-code-hub` repository, Server Actions (files under `src/actions/*.ts`) currently return hardcoded Chinese error messages directly. This is a codebase-wide architectural decision that applies to all action files (e.g., model-prices.ts, users.ts, system-config.ts). Changing this pattern requires a coordinated i18n refactor across all Server Actions, which should be handled as a separate unified task rather than piecemeal changes in individual PRs.

Applied to files:

  • docs/edge-runtime-process-once.md
🧬 Code graph analysis (2)
tests/unit/price-sync/cloud-price-updater.test.ts (5)
src/actions/model-prices.ts (1)
  • processPriceTableInternal (75-195)
src/lib/price-sync/cloud-price-table.ts (1)
  • CloudPriceTableResult (12-12)
src/lib/price-sync/cloud-price-updater.ts (2)
  • syncCloudPriceTableToDatabase (16-46)
  • requestCloudPriceTableSync (56-129)
src/lib/async-task-manager.ts (1)
  • AsyncTaskManager (244-245)
src/lib/logger.ts (1)
  • logger (168-187)
tests/unit/lib/async-task-manager-edge-runtime.test.ts (3)
src/lib/async-task-manager.ts (1)
  • AsyncTaskManager (244-245)
src/lib/logger.ts (1)
  • logger (168-187)
src/app/v1/_lib/proxy/errors.ts (1)
  • isClientAbortError (617-636)
⏰ 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: Docker Build Test
🔇 Additional comments (11)
docs/edge-runtime-process-once.md (1)

1-73: 文档结构清晰,内容完整。

文档详细记录了 Edge Runtime process.once 告警的修复过程,包括:

  • 问题背景和复现步骤
  • 具体变更说明
  • 验证和测试方法
  • 回滚指南
  • 备选方案

文档结构合理,为后续维护提供了充分的参考信息。

tests/unit/price-sync/cloud-price-updater.test.ts (4)

1-29: 测试基础设施设置合理。

测试正确使用了 Vitest,并通过 asyncTaskManagerLoaded 标志跟踪 AsyncTaskManager 的加载状态,这与 PR 中动态导入策略一致。模拟配置恰当地支持了隔离测试。


175-240: 错误处理测试覆盖全面。

新增的三个测试用例有效覆盖了 syncCloudPriceTableToDatabase 中的错误处理路径:

  • 缺少 error 字段时的默认消息
  • Error 异常的处理
  • 非 Error 值的处理

这些测试确保了错误场景下的健壮性。


243-266: 环境变量管理正确。

测试套件正确地在 beforeEach 中设置 NEXT_RUNTIME 环境变量,并在 afterEach 中恢复,确保测试之间的隔离。


268-434: 测试覆盖全面,验证了关键行为。

测试套件有效验证了 requestCloudPriceTableSync 的所有关键路径:

  • Edge runtime 下的 no-op 行为
  • 节流机制(包括默认值)
  • 调度标志防止并发
  • 错误处理(Error 和非 Error)
  • 任务注册和完成后的日志

测试结构清晰,使用动态导入确保了隔离性。

tests/unit/lib/async-task-manager-edge-runtime.test.ts (6)

1-44: 测试设置严谨,隔离性良好。

测试套件使用 describe.sequential 确保顺序执行,避免并发问题。beforeEachafterEach 钩子正确地清理全局状态(包括 __ASYNC_TASK_MANAGER__)并恢复环境变量,确保测试之间完全隔离。


45-68: 核心行为验证正确。

这两个测试有效验证了 PR 的核心目标:

  • Edge runtime 下不调用 process.once(避免告警)
  • Node runtime 下正确注册 3 个退出钩子(SIGTERM、SIGINT、beforeExit)

测试直接针对问题根源,确保修复有效。


70-117: 退出处理和定时清理验证充分。

测试正确验证了:

  • 退出信号处理器能触发 cleanupAll
  • 任务被正确取消(signal.aborted 为 true)
  • 清理定时器被正确清除
  • 定时清理按预期间隔运行

测试技术得当,使用 spy 和 fake timers 有效控制测试环境。


119-201: 任务生命周期管理测试完整。

测试覆盖了任务管理的关键场景:

  • 任务注册后的自动清理
  • 取消不存在任务的处理
  • 任务元数据的正确返回(包括 age 字段)
  • 相同 taskId 注册时自动取消旧任务

这些测试确保了 AsyncTaskManager 的核心功能正常工作。


203-237: 错误处理区分清晰。

测试正确验证了错误处理逻辑根据错误类型使用不同的日志级别:

  • 客户端中止错误 → logger.info
  • 真实错误 → logger.error

这种区分有助于减少日志噪音,提高可观测性。


239-307: 清理功能测试全面。

测试有效验证了清理机制:

  • cleanupCompletedTasks 能识别并取消陈旧任务(超过 10 分钟),同时保留新任务
  • cleanupAll 正确取消所有任务并清理定时器
  • 适当的警告日志被记录

测试使用类型断言访问私有成员,这是测试内部行为的合理做法。

Copy link

@greptile-apps greptile-apps bot left a comment

Choose a reason for hiding this comment

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

3 files reviewed, 1 comment

Edit Code Review Agent Settings | Greptile

YangQing-Lin and others added 2 commits January 11, 2026 23:45
补充 NEXT_PHASE === "phase-production-build" 检查

Co-authored-by: greptile-apps[bot] <165735046+greptile-apps[bot]@users.noreply.github.com>
Copy link

@coderabbitai coderabbitai bot left a comment

Choose a reason for hiding this comment

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

Actionable comments posted: 0

🧹 Nitpick comments (1)
src/lib/async-task-manager.ts (1)

44-47: 日志信息不完整

日志消息仅提到 "edge/CI environment",但实际检查了三个条件(包括 NEXT_PHASE)。建议更新日志描述和数据以包含所有跳过初始化的环境条件。

♻️ 建议的修复
-      logger.debug("[AsyncTaskManager] Skipping initialization in edge/CI environment", {
+      logger.debug("[AsyncTaskManager] Skipping initialization in edge/CI/build environment", {
         nextRuntime: process.env.NEXT_RUNTIME,
         ci: process.env.CI,
+        nextPhase: process.env.NEXT_PHASE,
       });
📜 Review details

Configuration used: Organization UI

Review profile: CHILL

Plan: Pro

Cache: Disabled due to Reviews > Disable Cache setting

📥 Commits

Reviewing files that changed from the base of the PR and between 4bc4d15 and 65ae2aa.

📒 Files selected for processing (1)
  • src/lib/async-task-manager.ts
🧰 Additional context used
📓 Path-based instructions (3)
**/*.{js,ts,tsx,jsx}

📄 CodeRabbit inference engine (CLAUDE.md)

Never use emoji characters in any code, comments, or string literals

Files:

  • src/lib/async-task-manager.ts
**/*.{ts,tsx,js,jsx}

📄 CodeRabbit inference engine (CLAUDE.md)

**/*.{ts,tsx,js,jsx}: All user-facing strings must use i18n (5 languages supported: zh-CN, zh-TW, en, ja, ru). Never hardcode display text
Use path alias @/ to reference files in ./src/ directory
Format code with Biome using: double quotes, trailing commas, 2-space indent, 100 character line width

Files:

  • src/lib/async-task-manager.ts
**/*.{ts,tsx}

📄 CodeRabbit inference engine (CLAUDE.md)

Prefer named exports over default exports

Files:

  • src/lib/async-task-manager.ts
🧠 Learnings (1)
📚 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/async-task-manager.ts
🧬 Code graph analysis (1)
src/lib/async-task-manager.ts (1)
src/lib/logger.ts (1)
  • logger (168-187)
🔇 Additional comments (2)
src/lib/async-task-manager.ts (2)

28-30: 延迟初始化字段定义正确

新增的 cleanupIntervalinitialized 字段类型正确,注释清晰说明了延迟初始化的目的。


79-81: 延迟初始化正确实现

register() 方法中调用 initializeIfNeeded() 确保了初始化延迟到首次使用,避免了导入时的副作用,有效解决了 Edge Runtime 构建告警问题。

@ding113 ding113 merged commit 6c79b88 into ding113:dev Jan 11, 2026
2 checks passed
ding113 added a commit that referenced this pull request Jan 12, 2026
* PR: 修复 Edge Runtime 下 `process.once` 构建告警(AsyncTaskManager 导入链) (#589)

* fix: skip async task manager init on edge

* fix: avoid static async task manager import

* test: cover edge runtime task scheduling

* chore: document edge runtime process.once fix

* chore: record edge runtime warning baseline

* fix: drop NEXT_PHASE and lazy-init async task manager

* test: isolate NEXT_RUNTIME in cloud price sync tests

* docs: stabilize edge process.once repro baseline

* docs: make rollback instructions hashless

* docs: add grep checklist for edge warning audit

* chore: run regression gate and align docs

* test: cover edge runtime guard on register

* Update src/lib/async-task-manager.ts

补充 NEXT_PHASE === "phase-production-build" 检查

Co-authored-by: greptile-apps[bot] <165735046+greptile-apps[bot]@users.noreply.github.com>

* chore: format code (fix-edge-runtime-process-once-bee7e19)

* PR:i18n settings 拆分与翻译质量门禁 (#588)

* refactor(i18n): split settings json into smaller files

* refactor(i18n): load settings from split module

* refactor(i18n): remove legacy settings.json

* chore(i18n): update sync-settings-keys for split layout

* test(i18n): add split settings guards

* chore: align biome schema version

* chore(i18n): document messages loading contract

* chore(i18n): add settings split verification notes

* chore: format code (refactor-i18n-split-settings-3f48fec)

* chore: fix i18n request formatting

* chore: format code (refactor-i18n-split-settings-a1eff62)

* fix: replace settings placeholder translations

* chore: verify settings sync script is idempotent

* test: run i18n settings split guards

* test: add audit for zh-CN placeholder settings strings

* chore: apply biome formatting

* chore: document manual i18n settings verification

* fix: translate all providers filter in ja

* fix: translate all providers filter in zh-TW

* fix: translate providers section copy in zh-TW

* fix: translate providers section copy in ja

* feat: extend placeholder audit output

* feat: add allowlist for placeholder audit

* docs: define i18n translation quality rules

* chore: add i18n audit fail commands

* docs: add i18n PR checklist

* chore: format i18n audit tests

* fix: translate dashboard placeholders

* fix: translate myUsage placeholders

* fix: enforce locale-specific parentheses

* fix: start translating provider form strings

* fix: translate provider form strings

* fix: translate provider guide content

* test: add ja dashboard parentheses guard

* test: add zh-TW dashboard parentheses guard

* test: add zh-TW myUsage parentheses guard

* chore: translate ja provider form strings

* chore: translate zh-TW provider form strings

* chore: translate ja providers guide

* chore: translate zh-TW providers guide

* chore: refine zh-TW dashboard strings

* chore: translate ja providers strings

* chore: translate zh-TW providers strings

* chore: refine zh-TW api test strings

* chore: translate zh-TW settings small modules

* chore: translate ja settings small modules

* chore: clear i18n placeholders in settings

* chore: format code (refactor-i18n-split-settings-2437d19)

* test: fix biome formatting in i18n test

* chore: verify Biome lint gate (I18NE-030)

* chore: add messages emoji audit script (I18NE-010)

* fix: remove emoji from messages warnings (I18NE-040)

* test: add messages no-emoji audit gate (I18NE-050)

* docs: add zh-CN i18n docs (I18NE-020)

* docs: add messages no-emoji rule (I18NE-060)

* chore: run full regression checks (I18NE-070)

* docs: add i18n PR evidence template (I18NE-080)

* fix: make messages no-emoji audit path-sep safe

* docs: add bun alias for messages no-emoji audit

* fix: detect keycap and flag emoji sequences in i18n message audits

* fix(provider): allow removing custom whitelisted models (#592) (#593)

* fix(rectifier): detect 'signature: Field required' error and trigger rectifier (#594)

- Extend detectThinkingSignatureRectifierTrigger to match 'signature: Field required'
- Add Rule 72 for friendly error message when signature field is missing
- Add comprehensive test cases for the new detection logic

This fixes an issue where switching from non-Anthropic to Anthropic channels
with thinking blocks missing signature fields would fail without proper handling.

* feat(users): increase provider group length to 200 (#591)

close #590

* feat(usage-doc): update OpenCode config example with GPT-5.2 and Gemini v1beta (#597)

- Add OpenAI GPT-5.2 model configuration with reasoningEffort options
- Add GPT-5.2-small variant using medium reasoning effort
- Fix Gemini baseURL to use /v1beta endpoint
- Update i18n strings to reflect different baseURLs per provider

* feat: auto-complete Codex session identifiers (#599)

* fix: Codex session completion must not inject metadata (#601)

* feat: auto-complete Codex session identifiers

* fix: avoid Codex metadata injection

---------

Co-authored-by: YangQing-Lin <56943790+YangQing-Lin@users.noreply.github.com>
Co-authored-by: Hwwwww-dev <47653238+Hwwwww-dev@users.noreply.github.com>
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

area:core bug Something isn't working size/L Large PR (< 1000 lines)

Projects

Status: Done

Development

Successfully merging this pull request may close these issues.

2 participants