Skip to content

refactor(tag): 标签改为文章内联管理 + create_post 支持标签名 - #66

Merged
Starduet merged 1 commit into
mainfrom
fix/agent-loop
Jul 12, 2026
Merged

Starduet merged 1 commit into
mainfrom
fix/agent-loop

Conversation

@OutsrYingq

@OutsrYingq OutsrYingq commented Jul 12, 2026 •

Copy link
Copy Markdown
Contributor

关联

  • 设计文档: docs/design/06-文章模块.md §九(标签管理)、docs/design/02-目录结构与分层规范.md
  • 改动主题: 标签从独立管理页改为文章内联输入

背景

原设计中标签(Tag)有独立的管理页面和 CRUD 接口(admin+ 创建/删除),文章创建时通过 tagIds 关联。实际使用中发现:标签的创建和使用场景几乎完全在文章编辑时发生,独立管理页是过度设计,增加了前端复杂度和用户操作步骤。

本 PR 将标签改为文章创建/编辑时内联输入(传标签名),不存在自动创建,简化了全链路。

改动

后端 (apps/api)

  • modules/tag/tag.repository.ts:新增 findOrCreateBatch(names) 批量按名查找或创建标签
  • modules/tag/tag.service.ts:精简为 list + findOrCreateBatch,移除独立的 create/delete
  • modules/post/post.service.ts:create/update 支持 tags(标签名数组),内部调 findOrCreateBatch 自动创建并关联
  • ai/tools.ts:create_post/update_post 工具的 tagIds 改为 tags(标签名列表),MCP Agent 可直接传标签名
  • ai/runtime.ts:在线 Agent 工具同步更新
  • routes/tags.routes.ts:保留 GET /(公开列表),移除 POST/DELETE(admin+ CRUD)

shared (packages/shared)

  • schemas.ts:createPostSchema 的 tagIds 改为 tags(z.array(z.string()))

前端 (apps/web)

  • 删除 pages/admin/tags.page.tsx(独立标签管理页)
  • pages/admin/post-edit.page.tsx:标签选择改为内联输入(输入标签名,逗号分隔)
  • app/router.tsx:移除标签管理路由
  • components/layout/admin-sidebar.tsx:移除标签管理菜单项
  • api/tags.api.ts + features/tag/use-tags.ts:精简为仅 list 查询

依赖

  • package.json/bun.lock:更新相关依赖

验证

$ cd apps/api && bun run typecheck
# 通过
$ cd apps/web && bun run typecheck
# 通过

风险与未验证项

  • 未做 curl 冒烟(标签创建逻辑变更,需端到端验证 create_post 传标签名能正常创建+关联)
  • 删除的 tags 管理页面如有外部链接引用需排查(前端路由已同步移除)

Review Notes

  • 标签删除是物理删除还是保留?本 PR 只移除了管理接口,DB 中 tag 表和 post_tag 关联表不变,已有标签数据不受影响。
  • findOrCreateBatch 在并发下可能有 UNIQUE 约束冲突(两个请求同时创建同名标签),当前用 catch + retry 模式处理。

Summary by CodeRabbit

  • 新功能

    • AI 助手支持更深入的多步推理与工具调用,最多连续处理 5 个步骤。
    • 发布和编辑文章时可直接输入标签名称,支持去重、移除及最多 10 个标签。
    • 标签名称会自动规范化,已有标签可复用,未存在的标签会自动创建。
  • 功能调整

    • 标签管理页面及标签创建、删除功能已移除,仅保留标签浏览。
    • 后台导航中不再显示标签管理入口。

- 标签 CRUD 从独立管理页改为文章创建/编辑时内联输入(tag names)
- create_post/update_post 工具支持 tags 字段(传标签名,不存在自动创建)
- 删除独立的 tags 管理页面和路由(前端+后端)
- shared schemas 补充 createPostSchema 的 tags 字段
- post.service 支持标签名自动创建/关联
- tag.repository 增加 findOrCreateBatch 批量创建标签
- post-edit 页面重构标签选择为内联输入
Copilot AI review requested due to automatic review settings July 12, 2026 01:21

Copilot AI 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.

Copilot was unable to review this pull request because the user who requested the review has reached their quota limit.

@coderabbitai

coderabbitai Bot commented Jul 12, 2026 •

Copy link
Copy Markdown

Review Change Stack

📝 Walkthrough

Walkthrough

Changes

标签名称化工作流

Layer / File(s) Summary
标签名称契约与解析
packages/shared/src/schemas.ts, apps/api/src/modules/tag/tag.repository.ts
文章 schema 改用标签名称数组,并新增标签标准化、查找与创建逻辑。
文章创建与更新集成
apps/api/src/modules/post/post.service.ts, apps/api/src/ai/tools.ts
文章服务和 AI 工具将标签名称解析为标签 ID;更新时未提供标签则保持原关联。
标签只读 API 与管理入口收缩
apps/api/src/modules/tag/*, apps/api/src/routes/tags.routes.ts, apps/web/src/api/tags.api.ts, apps/web/src/features/tag/use-tags.ts, apps/web/src/app/router.tsx, apps/web/src/components/layout/admin-sidebar.tsx, apps/web/src/pages/admin/tags.page.tsx
移除标签创建、删除及后台管理入口,仅保留公开列表查询。
后台文章标签编辑器
apps/web/src/pages/admin/post-edit.page.tsx
文章编辑改用标签名称输入,支持添加、去重、删除及数量限制。
Agent 多步执行上限
apps/api/src/ai/runtime.ts
流式 Agent 最多执行五步工具调用与推理循环。

运行时依赖配置

Layer / File(s) Summary
运行时依赖声明
package.json
调整 workspace 格式并新增 docx 与 image-size 运行时依赖。

Estimated code review effort: 4 (Complex) | ~45 minutes

Sequence Diagram(s)

sequenceDiagram
  participant Editor
  participant TagsAPI
  participant PostService
  participant TagRepository
  participant PostRepository
  Editor->>TagsAPI: 读取标签列表
  Editor->>PostService: 提交 tags 名称数组
  PostService->>TagRepository: 查找或创建标签
  TagRepository-->>PostService: 返回 TagRow[]
  PostService->>PostRepository: 使用 tagIds 保存文章关联
  PostRepository-->>Editor: 返回文章结果
Loading

Poem

我是小兔,蹦过标签田,
名字入表,轻轻 trim 一遍。
五步 Agent 转呀转,
新旧标签都相见。
后台写入口悄悄收,
文章编辑更方便!

🚥 Pre-merge checks | ✅ 4 | ❌ 1

❌ Failed checks (1 warning)

Check name Status Explanation Resolution
Docstring Coverage ⚠️ Warning Docstring coverage is 25.00% 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
Description Check ✅ Passed Check skipped - CodeRabbit’s high-level summary is enabled.
Title check ✅ Passed 标题准确概括了标签改为文章内联管理以及 create_post 改为支持标签名的主要变更。
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.
✨ Finishing Touches
📝 Generate docstrings
  • Create stacked PR
  • Commit on current branch
🧪 Generate unit tests (beta)
  • Create PR with unit tests
  • Commit unit tests in branch fix/agent-loop

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.

@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 (3)
package.json (1)

20-23: 📐 Maintainability & Code Quality | 🔵 Trivial | ⚡ Quick win

运行时依赖应声明在实际使用的 workspace 包中,而非 monorepo 根目录。

docx 和 image-size 作为运行时依赖放在根 package.json 中,会使依赖边界模糊——不清楚哪个 workspace 包(很可能是 apps/api)实际使用它们。建议将其移至实际 import 这些库的 workspace 包的 package.json,根目录仅保留 devDependencies 和 workspace 配置。

♻️ 建议的调整

将 docx 和 image-size 从根 package.json 移至实际使用的 workspace 包(如 apps/api/package.json)的 dependencies 中:

-  "dependencies": {
-    "docx": "^9.7.1",
-    "image-size": "^2.0.2"
-  }

然后在 apps/api/package.json(或其他实际 import 的包)中添加:

"dependencies": {
  "docx": "^9.7.1",
  "image-size": "^2.0.2"
}
🤖 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 `@package.json` around lines 20 - 23, 将根 package.json dependencies 中的 docx 和
image-size 移除,并在实际 import 它们的 workspace 包 package.json
中声明相同版本的运行时依赖;确认依赖归属与使用代码所在 workspace 一致,根目录仅保留 workspace 配置及开发依赖。
apps/web/src/pages/admin/post-edit.page.tsx (1)

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

标签删除按钮缺少 aria-label。

屏幕阅读器会朗读 "标签名 ×",语义不够明确。建议添加 aria-label 以提升可访问性。

♿ 建议添加 aria-label
                             <button
                               key={name}
                               type="button"
+                              aria-label={`移除标签 ${name}`}
                               onClick={() => {
🤖 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 `@apps/web/src/pages/admin/post-edit.page.tsx` around lines 228 - 275,
在标签删除按钮中补充明确的 aria-label,定位 currentTags.map 渲染的
button,并将当前标签名包含在删除语义中;保持现有点击删除逻辑不变。
apps/api/src/ai/tools.ts (1)

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

标签解析逻辑与 post.service.ts 重复。

normalizeTagNames → findOrCreateMany → map(t => t.id) 的三步逻辑在 post.service.ts (lines 177-179) 和此处完全重复。若后续标签解析规则变更,需同步修改两处。考虑提取为共享辅助函数(如 resolveTagIds(names): Promise<number[] | undefined>)。

🤖 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 `@apps/api/src/ai/tools.ts` around lines 180 - 182, Extract the duplicated
tag-resolution flow from the current tool logic and post.service.ts into a
shared helper such as resolveTagIds(names), preserving the undefined result for
absent tags and the existing normalized findOrCreateMany-to-ID behavior. Update
both callers to use the shared helper so future tag-resolution changes require
only one implementation.
🤖 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 `@apps/api/src/ai/tools.ts`:
- Around line 180-183: 将 tags 处理与 updateWithTags 统一放入同一个 db.transaction
回调中:在事务回调内调用 tagRepository.findOrCreateMany 时传入 tx,并将其结果映射为 tagIds,再调用
postRepository.updateWithTags 使用同一 tx;无 tags 时保持 undefined。

In `@apps/api/src/modules/tag/tag.repository.ts`:
- Around line 79-93: Update the tag creation branch in the names loop to catch
unique-constraint failures from create, then query by lowercased name and reuse
the existing tag. Preserve normal successful creation and only suppress errors
when the conflicting tag is found; rethrow other failures so the surrounding
transaction behavior remains intact.

In `@package.json`:
- Around line 21-22: Replace the vulnerable image-size dependency in
package.json with a maintained alternative that provides the required
image-dimension functionality, and update the corresponding import and usage
symbols throughout the codebase while preserving existing behavior for untrusted
images.

---

Nitpick comments:
In `@apps/api/src/ai/tools.ts`:
- Around line 180-182: Extract the duplicated tag-resolution flow from the
current tool logic and post.service.ts into a shared helper such as
resolveTagIds(names), preserving the undefined result for absent tags and the
existing normalized findOrCreateMany-to-ID behavior. Update both callers to use
the shared helper so future tag-resolution changes require only one
implementation.

In `@apps/web/src/pages/admin/post-edit.page.tsx`:
- Around line 228-275: 在标签删除按钮中补充明确的 aria-label,定位 currentTags.map 渲染的
button,并将当前标签名包含在删除语义中;保持现有点击删除逻辑不变。

In `@package.json`:
- Around line 20-23: 将根 package.json dependencies 中的 docx 和 image-size 移除,并在实际
import 它们的 workspace 包 package.json 中声明相同版本的运行时依赖;确认依赖归属与使用代码所在 workspace
一致,根目录仅保留 workspace 配置及开发依赖。
🪄 Autofix (Beta)

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

Run ID: 639e623e-4f4f-4ac8-85cb-aeddf84eda2d

📥 Commits

Reviewing files that changed from the base of the PR and between 4ba93f9 and f8af3c6.

⛔ Files ignored due to path filters (1)
  • bun.lock is excluded by !**/*.lock
📒 Files selected for processing (15)
  • apps/api/src/ai/runtime.ts
  • apps/api/src/ai/tools.ts
  • apps/api/src/modules/post/post.service.ts
  • apps/api/src/modules/tag/tag.repository.ts
  • apps/api/src/modules/tag/tag.schema.ts
  • apps/api/src/modules/tag/tag.service.ts
  • apps/api/src/routes/tags.routes.ts
  • apps/web/src/api/tags.api.ts
  • apps/web/src/app/router.tsx
  • apps/web/src/components/layout/admin-sidebar.tsx
  • apps/web/src/features/tag/use-tags.ts
  • apps/web/src/pages/admin/post-edit.page.tsx
  • apps/web/src/pages/admin/tags.page.tsx
  • package.json
  • packages/shared/src/schemas.ts
💤 Files with no reviewable changes (2)
  • apps/web/src/pages/admin/tags.page.tsx
  • apps/web/src/app/router.tsx

Comment thread apps/api/src/ai/tools.ts
Comment on lines +180 to 183
const tagIds = tags !== undefined
? (await tagRepository.findOrCreateMany(normalizeTagNames(tags))).map((t) => t.id)
: undefined
const updated = await db.transaction(() => postRepository.updateWithTags(id, data, tagIds))

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

🗄️ Data Integrity & Integration | 🟠 Major | ⚡ Quick win

🧩 Analysis chain

🏁 Script executed:

#!/bin/bash
# 检查 tagRepository.findOrCreateMany 是否使用内部事务
ast-grep outline apps/api/src/modules/tag/tag.repository.ts --match findOrCreateMany --view expanded

Repository: BqLee-AI/AgentBlog

Length of output: 213


🏁 Script executed:

#!/bin/bash
set -euo pipefail

echo '--- locate tag repository files ---'
git ls-files | rg 'apps/api/src/modules/tag/.*repository.*|apps/api/src/ai/tools.ts|post.service.ts|tag' || true

echo
echo '--- search for findOrCreateMany and tagRepository references ---'
rg -n "findOrCreateMany|tagRepository|updateWithTags|update_post|normalizeTagNames" apps/api/src -g '!**/*.map' || true

echo
echo '--- outline candidate tag repository file(s) if present ---'
for f in $(git ls-files | rg 'apps/api/src/modules/tag/.*repository.*'); do
  echo "### $f"
  ast-grep outline "$f" --view expanded || true
done

Repository: BqLee-AI/AgentBlog

Length of output: 3690


🏁 Script executed:

#!/bin/bash
set -euo pipefail

echo '--- apps/api/src/modules/tag/tag.repository.ts ---'
cat -n apps/api/src/modules/tag/tag.repository.ts | sed -n '1,220p'

echo
echo '--- apps/api/src/modules/post/post.service.ts ---'
cat -n apps/api/src/modules/post/post.service.ts | sed -n '150,220p'

echo
echo '--- apps/api/src/modules/post/post.repository.ts (updateWithTags) ---'
cat -n apps/api/src/modules/post/post.repository.ts | sed -n '220,290p'

Repository: BqLee-AI/AgentBlog

Length of output: 7871


🏁 Script executed:

#!/bin/bash
set -euo pipefail

echo '--- db client ---'
cat -n apps/api/src/db/client.ts | sed -n '1,220p'

echo
echo '--- search for tx-aware repository patterns ---'
rg -n "\btx\b|db\.transaction\(" apps/api/src/modules apps/api/src/db apps/api/src/ai -g '!**/*.map' || true

echo
echo '--- any repository methods that accept tx parameter ---'
rg -n "async .*tx|tx:\s*.*Transaction|Transaction<|Database|DB" apps/api/src/modules -g '!**/*.map' || true

Repository: BqLee-AI/AgentBlog

Length of output: 3040


🌐 Web query:

Drizzle ORM bun-sqlite db.transaction callback global db vs tx object transaction methods repository uses db inside transaction

💡 Result:

In Drizzle ORM, when using the transaction API, you must use the transaction object (typically named tx) provided within the callback [1]. Using the global db object inside a transaction callback will not execute those operations within the transaction scope; instead, they will execute outside the transaction, potentially leading to race conditions or data inconsistencies [1][2]. The tx object mirrors the API of your main db instance, supporting the same query methods (e.g., select, insert, update, delete) and relational queries [1]. For repository patterns, it is a recommended best practice to design your repository methods to accept an optional transaction object (e.g., tx: MyDb | MyTransaction) [2]. This allows your business logic—typically housed in a service layer—to control the transaction boundary [2]. By passing the tx object into these repository methods when inside a transaction callback, you ensure that the repository's operations are correctly included within that transaction [1][2]. Example of the recommended pattern: // Repository layer class UserRepository { constructor(private db: MyDatabaseType) {} async createUser(data: UserInsert, tx?: MyTransactionType) { const client = tx || this.db; return await client.insert(users).values(data).returning; } } // Service layer async function performBusinessLogic(data: UserInsert) { return await db.transaction(async (tx) => { // Pass 'tx' to ensure operation is part of the transaction await userRepo.createUser(data, tx); await otherRepo.doSomethingElse(data, tx); }); } If you do not pass the tx object into your repository methods, and those methods instead rely exclusively on the global db instance, they will run outside the transaction scope [1][2].

Citations:


🌐 Web query:

Drizzle ORM transaction callback use tx object not global db docs bun sqlite

💡 Result:

When using transactions in Drizzle ORM with Bun SQLite, you should use the transaction object (commonly named tx) provided by the transaction callback to ensure your operations are part of the same transaction [1][2][3]. The transaction callback receives a tx object that mirrors the API of your global db instance [1][2]. By using tx instead of the global db instance inside your transaction block, you guarantee that all queries executed within that function share the same connection and transaction context [2][3]. Example usage with Bun SQLite: import { drizzle } from 'drizzle-orm/bun-sqlite'; import { Database } from 'bun:sqlite'; import { users } from './schema'; const sqlite = new Database('sqlite.db'); const db = drizzle(sqlite); await db.transaction(async (tx) => { // Use 'tx' for all operations within the transaction await tx.insert(users).values({ name: 'Alice' }).run; await tx.update(users).set({ active: true }).where(...).run; }); Key points: - Atomicity: The tx object ensures that if any operation inside the callback fails or throws an error, the entire transaction is automatically rolled back [2]. - Nested Transactions: Drizzle supports nested transactions (savepoints) by calling db.transaction or tx.transaction inside the callback [3]. - Global vs. Transactional Object: While some users may attempt to use the global db instance inside a transaction, the tx object is the intended way to maintain the correct transactional scope [1][2][3]. Using the global db might bypass the transaction context or lead to unexpected behavior depending on the driver and configuration [4].

Citations:


findOrCreateMany 也要纳入同一事务 tagRepository.findOrCreateMany 现在直接用全局 db,所以这里只把 updateWithTags 包进 db.transaction 还不够;新建标签仍可能在失败后残留。把 tx 传进 findOrCreateMany,并用同一个事务执行。

🤖 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 `@apps/api/src/ai/tools.ts` around lines 180 - 183, 将 tags 处理与 updateWithTags
统一放入同一个 db.transaction 回调中:在事务回调内调用 tagRepository.findOrCreateMany 时传入
tx,并将其结果映射为 tagIds,再调用 postRepository.updateWithTags 使用同一 tx;无 tags 时保持
undefined。

Comment on lines +79 to +93
for (const name of names) {
const key = name.toLowerCase()
if (seen.has(key)) continue
seen.add(key)
const hit = existingByLower.get(key)
if (hit) {
result.push(hit)
} else {
// 不存在则创建(UNIQUE(name) 兜底并发,catch 后回查)
const created = await this.create({ name, slug: generateSlug(name) })
if (created) {
existingByLower.set(key, created)
result.push(created)
}
}

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

🩺 Stability & Availability | 🟠 Major | ⚡ Quick win

🧩 Analysis chain

🏁 Script executed:

#!/bin/bash
# 查看 create 实现与 better-sqlite3 驱动配置,确认冲突时的抛错行为
fd -t f 'client.ts' apps/api/src/db --exec cat -n {}
rg -nP 'better-sqlite3|drizzle' apps/api/src/db -C2

Repository: BqLee-AI/AgentBlog

Length of output: 4169


🏁 Script executed:

#!/bin/bash
set -euo pipefail

echo '--- tag.repository.ts ---'
cat -n apps/api/src/modules/tag/tag.repository.ts | sed -n '1,220p'

echo '--- schema.ts (tags) ---'
rg -n 'export const tags|unique|slug|name' apps/api/src/db/schema.ts -A6 -B4

echo '--- repository create usages ---'
rg -n 'async create\\(|create\\(' apps/api/src/modules/tag -A6 -B4

Repository: BqLee-AI/AgentBlog

Length of output: 6793


🏁 Script executed:

#!/bin/bash
set -euo pipefail

echo '--- tag.repository.ts around findOrCreateMany/create ---'
cat -n apps/api/src/modules/tag/tag.repository.ts | sed -n '1,180p'

echo '--- tag schema ---'
cat -n apps/api/src/db/schema.ts | sed -n '1,220p'

Repository: BqLee-AI/AgentBlog

Length of output: 9524


🏁 Script executed:

#!/bin/bash
set -euo pipefail

echo '--- findOrCreateMany call sites ---'
rg -n 'findOrCreateMany\(' apps/api/src -A6 -B6

echo '--- tagRepository call sites ---'
rg -n 'tagRepository\.' apps/api/src -A4 -B4

echo '--- transaction usages near post service ---'
rg -n 'db\.transaction|transaction\(' apps/api/src/modules/post -A8 -B8

Repository: BqLee-AI/AgentBlog

Length of output: 14917


并发兜底要补回查

apps/api/src/modules/tag/tag.repository.ts:87-92 这里还没有实现注释里说的“catch 后回查”。tag.name/tag.slug 都有 UNIQUE 约束,并发创建同名标签时会直接抛错,回滚外层 post 事务。这里应在唯一冲突后按 lower(name) 回查并复用已存在的标签。

🤖 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 `@apps/api/src/modules/tag/tag.repository.ts` around lines 79 - 93, Update the
tag creation branch in the names loop to catch unique-constraint failures from
create, then query by lowercased name and reuse the existing tag. Preserve
normal successful creation and only suppress errors when the conflicting tag is
found; rethrow other failures so the surrounding transaction behavior remains
intact.

Comment thread package.json
Comment on lines +21 to +22
"docx": "^9.7.1",
"image-size": "^2.0.2"

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

🔒 Security & Privacy | 🟠 Major | ⚡ Quick win

🧩 Analysis chain

🌐 Web query:

What is the latest stable version of the npm packages "docx" and "image-size"?

💡 Result:

As of July 12, 2026, the latest stable versions of the requested npm packages are as follows: - docx: 9.7.1 (published May 27, 2026) [1][2][3]. - image-size: 2.0.2 [4]. Please note that the image-size repository has been marked as archived [5][6].

Citations:


🌐 Web query:

docx 9.7.1 security advisory npm vulnerability image-size 2.0.2 security advisory npm vulnerability

💡 Result:

As of July 12, 2026, the security status of the requested packages is as follows: image-size The image-size package versions up to and including 2.0.2 are associated with multiple Denial of Service (DoS) vulnerabilities [1][2]. Specifically, versions through 2.0.2 contain vulnerabilities that allow remote attackers to cause an infinite loop in the JXL, HEIF, and ICNS image parsers, which can permanently block the Node.js event loop and hang the application [1][2]. These vulnerabilities are tracked under identifiers such as CVE-2025-71319, CVE-2025-71329, and CVE-2025-71330 [1][3][2][4]. Users are advised to verify if later versions have been released that address these issues, as the referenced advisories identify 2.0.2 as an affected version [1][2]. docx The docx package version 9.7.1 does not have a formal CVE-based security advisory linked to it in major vulnerability databases [5]. However, automated security analysis tools have flagged this version for high-risk behaviors [6][7]. Security research platforms, such as Shoulder, have noted concerns regarding install-time payloads, potential dynamic code execution, and dependency-related flags in recent versions of the docx package [6][7]. Users are encouraged to exercise caution and perform manual reviews or use dependency-analysis tools when integrating this package, as these flags indicate potentially anomalous or suspicious supply-chain characteristics rather than a confirmed exploit [6][8].

Citations:


image-size 仍有已知 DoS 风险,建议替换
docx@^9.7.1 没有明显的公开 CVE 问题;image-size@^2.0.2 仍受已知 DoS 漏洞影响,若会处理不受信任图片,建议改用维护中的替代方案或加严格隔离。

🤖 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 `@package.json` around lines 21 - 22, Replace the vulnerable image-size
dependency in package.json with a maintained alternative that provides the
required image-dimension functionality, and update the corresponding import and
usage symbols throughout the codebase while preserving existing behavior for
untrusted images.

@Starduet
Starduet merged commit caf320e into main Jul 12, 2026
1 check passed
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

3 participants