docs(01): research phase domain

This commit is contained in:
肖应宇 2026-04-07 12:05:50 +08:00
parent 67e7304748
commit 31bb8db442
11 changed files with 711 additions and 1422 deletions

0
.codex Normal file
View File

View File

@ -0,0 +1,304 @@
# Phase 01: conflict-inventory-and-decision-matrix - 研究文档
**Researched:** 2026-04-07 [VERIFIED: local date + `.planning/config.json`]
**Domain:** 合并冲突盘点、Titan 重叠识别、文件级风险分级 [VERIFIED: `.planning/ROADMAP.md`, `.planning/REQUIREMENTS.md`]
**Confidence:** HIGH仓库内证据/ MEDIUM通用 Git 实践)[VERIFIED: git log/show/diff 命令结果][CITED: https://git-scm.com/docs]
<user_constraints>
## User Constraints (from CONTEXT.md)
### Locked Decisions
- 未检测到 `01-CONTEXT.md`,本阶段无 discuss 锁定决策可继承。[VERIFIED: `init phase-op 1 -> "has_context": false`]
### Claude's Discretion
- 由研究阶段自行定义冲突盘点口径、决策矩阵字段、风险分级和验证策略。[VERIFIED: `init phase-op 1`, `.planning/ROADMAP.md`]
### Deferred Ideas (OUT OF SCOPE)
- 未检测到 `CONTEXT.md` 中的延期项;沿用项目级 Out of Scope不做后端无关重构、不做新功能扩展。[VERIFIED: `.planning/PROJECT.md`, `.planning/REQUIREMENTS.md`]
</user_constraints>
<phase_requirements>
## Phase Requirements
| ID | Description | Research Support |
|----|-------------|------------------|
| MERGE-01 | 团队可列出 merge 覆写热点并给出文件级证据与风险等级 | 提供“冲突来源采集 -> 文件分层 -> 风险评分 -> 审计输出”完整流程与评分公式 [VERIFIED: `.planning/REQUIREMENTS.md`, 本文 Architecture Patterns] |
| MERGE-03 | 团队可识别 Titan 重叠路径并形成 keep/replace 决策 | 提供 Titan overlap 识别算法、三向决策规则Keep Legacy UI / Keep New Logic / Hybrid与文件级验证清单 [VERIFIED: `.planning/REQUIREMENTS.md`, git author/commit 证据, 本文 Decision Matrix] |
</phase_requirements>
## Project Constraints (from CLAUDE.md)
- 仓库根目录未发现 `CLAUDE.md`,无额外项目级硬约束覆盖当前研究。[VERIFIED: `ls /home/mt/Project/deerflow2/CLAUDE.md` 返回不存在]
## Summary
Phase 01 的最佳执行路径不是“看当前工作区 diff”而是“回放历史 merge 冲突提交并构建证据矩阵”。当前分支相对 `origin/git-main` 前端无差异,说明风险主要来自历史冲突解决中可能被静默覆盖的逻辑,而非当前未提交改动。[VERIFIED: `git diff --name-status origin/git-main..HEAD -- frontend` 空输出]
仓库中可直接抽取两条高价值证据链1) 含冲突语义的 merge 提交(如 `8a2cac7b`, `0fff2880`, `6a540d84`, `6335424a`, `49503504`对应的前端改动文件2) Titan 作者提交及“移植 Titan main”提交`7342cc08`)触达文件。两条证据求交集可快速锁定高风险文件。[VERIFIED: `git show -m --name-status ...`, `git log --author='[Tt]itan' ...`, `git show 7342cc08`]
**Primary recommendation:** 采用“文件分层 + Titan overlap + 行为关键度”的三轴决策矩阵,优先处理 `workspace/chats/[thread_id]/page.tsx`、`core/threads/hooks.ts`、`core/skills/api.ts`、`components/workspace/chats/use-thread-chat.ts`,并以“旧视觉 + 新逻辑”的分层合并法执行。[VERIFIED: 频次统计与提交历史交集]
## Standard Stack
### Core
| Library/Tool | Version | Purpose | Why Standard |
|---------|---------|---------|--------------|
| Git CLI | 2.43.0 [VERIFIED: `git --version`] | 冲突来源识别、提交追溯、三方比对 | 所有证据链均基于 commit/tree不依赖主观比对 [VERIFIED: 本阶段目标定义 + git 命令输出] |
| ripgrep | 15.1.0 [VERIFIED: `rg --version`] | 快速扫描冲突标记、路径聚合、规则批量匹配 | 对大仓库文本检索稳定且快 [ASSUMED] |
| Node.js | v24.14.0 [VERIFIED: `node --version`] | 运行轻量脚本做矩阵生成与聚合 | 仓库前端工具链已基于 Node [VERIFIED: `frontend/package.json`] |
### Supporting
| Library/Tool | Version | Purpose | When to Use |
|---------|---------|---------|-------------|
| Playwright | `^1.48.0` [VERIFIED: `frontend/package.json`] | 高风险文件回归验证(路由/线程/消息) | 在“逻辑保留 + 视觉替换”后做行为回归 [VERIFIED: `frontend/tests/e2e/*.spec.ts`] |
| ESLint + TypeScript | `^9.23.0` + `^5.8.2` [VERIFIED: `frontend/package.json`] | 冲突修复后快速发现类型/导入回归 | 每次文件级决策后执行快速检查 [VERIFIED: `frontend/package.json` scripts] |
### Alternatives Considered
| Instead of | Could Use | Tradeoff |
|------------|-----------|----------|
| 基于 commit 的盘点 | 纯人工文件目检 | 目检无法追溯“谁覆盖了谁”,审计性差 [ASSUMED] |
| 文件级风险打分 | 全量同优先级处理 | 成本高、无法先处理行为高风险路径 [ASSUMED] |
**Installation:**
```bash
cd frontend
pnpm install
```
[VERIFIED: `frontend/package.json` 存在 `pnpm` 脚本]
**Version verification note:** npm registry 在当前环境超时,未完成在线版本核验;本文版本以仓库锁定信息和本机工具版本为准。[VERIFIED: `timeout 8 npm ping` -> EXIT:124]
## Architecture Patterns
### Recommended Project Structure (for this phase outputs)
```text
.planning/phases/01-conflict-inventory-and-decision-matrix/
├── 01-RESEARCH.md # 研究依据与决策规则
├── conflict-inventory.csv # 文件级证据(提交、作者、风险分)
└── decision-matrix.md # keep/replace/hybrid 决策表
```
[ASSUMED]
### Pattern 1: Merge 覆写风险盘点(文件级)
**What:** 从“冲突语义 merge 提交”反推出可能被覆盖/删除的文件集合,再加行为关键度打分。[VERIFIED: 多个 merge 提交含 `resolve conflict(s)` 信息]
**When to use:** 需要审计“历史 conflict resolution 是否覆盖新逻辑”时。[VERIFIED: Phase 01 Goal in `.planning/ROADMAP.md`]
**Example:**
```bash
# Source: git docs + repo history
git log --all --merges --oneline --decorate
git show -m --name-status 8a2cac7b -- frontend
git show -m --name-status 0fff2880 -- frontend
git show -m --name-status 6a540d84 -- frontend
```
[CITED: https://git-scm.com/docs/git-log][CITED: https://git-scm.com/docs/git-show][VERIFIED: 本仓库命令执行结果]
### Pattern 2: Titan Overlap 识别与保留策略
**What:** 用 `author=Titan` + “移植 Titan main”提交双轨识别 Titan 语义归属,再与 merge 热点求交集。[VERIFIED: `git log --author='[Tt]itan'`, `git show 7342cc08`]
**When to use:** 文件既出现在冲突 merge 中又被 Titan 历史触达时。[VERIFIED: 交集文件统计]
**Example:**
```bash
git log --all --author='[Tt]itan' --name-only --pretty=format: -- frontend
git show --name-only 7342cc08
```
[CITED: https://git-scm.com/docs/git-log][VERIFIED: 本仓库命令执行结果]
### Pattern 3: “旧视觉 + 新逻辑”分层合并
**What:** 将文件变更拆成视觉层与逻辑层,视觉优先对齐 legacy逻辑优先保留 new/Titan 语义。[VERIFIED: 项目核心价值强调“视觉旧、逻辑新” in `.planning/PROJECT.md`]
**When to use:** `frontend` 中混合变更文件UI+状态+路由)如聊天页、线程 hook、message item。[VERIFIED: 热点文件清单]
**Layer Rule执行规则:**
1. L0 路由/查询参数/协议:保留新逻辑(`thread_id/isnew/xclaw_used`, skills bootstrap 合同)。[VERIFIED: `.planning/REQUIREMENTS.md` LOGIC-03/04]
2. L1 数据流与副作用:保留通过 Titan 或后续修复提交验证过的行为路径(避免重复/死分支)。[VERIFIED: Titan commits + merge recovery related commits]
3. L2 视图样式与布局:对齐旧视觉 tokens/spacing/hierarchy不改动 L0/L1 决策点。[VERIFIED: `.planning/PROJECT.md` + `.planning/ROADMAP.md` Phase 3]
### 当前高风险交集文件(建议作为首批审计)
| File | Merge Hotspot Frequency | Titan Touch Frequency | Risk |
|------|-------------------------|-----------------------|------|
| `frontend/src/app/workspace/chats/[thread_id]/page.tsx` | 4 [VERIFIED: merge 频次统计] | 7 [VERIFIED: titan 频次统计] | P0 |
| `frontend/src/core/threads/hooks.ts` | 3 [VERIFIED] | 4 [VERIFIED] | P0 |
| `frontend/src/core/skills/api.ts` | 1 [VERIFIED] | 3 [VERIFIED] | P0 |
| `frontend/src/components/workspace/chats/use-thread-chat.ts` | 1 [VERIFIED] | 1 [VERIFIED] | P1 |
| `frontend/src/components/workspace/messages/message-list-item.tsx` | 7 [VERIFIED] | 1 [VERIFIED] | P1 |
| `frontend/src/components/workspace/artifacts/artifact-file-detail.tsx` | 8 [VERIFIED] | 0 [VERIFIED: titan 文件统计未出现] | P1 |
### Anti-Patterns to Avoid
- **只看当前分支 diff** 会漏掉“历史 merge 冲突后被覆盖”的风险路径。[VERIFIED: 当前分支对 `origin/git-main` 无前端差异]
- **UI 与逻辑同时重写:** 无法定位回归来源,且不符合“按 concern 分提交”的项目约束。[VERIFIED: TEST-02 in `.planning/REQUIREMENTS.md`]
- **未标注来源的 keep/replace 决策:** reviewer 无法审计依据。[ASSUMED]
## Don't Hand-Roll
| Problem | Don't Build | Use Instead | Why |
|---------|-------------|-------------|-----|
| 提交追溯 | 自写 git parser | 原生 `git log/show/diff/blame` | 原生命令可直接复现并审计 [CITED: https://git-scm.com/docs] |
| 风险判级 | 纯主观评级 | 固定权重评分矩阵(见下) | 可重复、可解释、可比较 [ASSUMED] |
| 冲突定位 | 手动逐文件扫 | `git show -m` + 频次聚合脚本 | merge commit 下文件定位更精确 [CITED: https://git-scm.com/docs/git-show] |
**Key insight:** 该阶段核心是“审计可追溯性”,而非“一次性修完所有冲突”;优先构建证据矩阵,后续 phase 才能低风险实施。[VERIFIED: Phase 1/2/3 分工 in `.planning/ROADMAP.md`]
## Common Pitfalls
### Pitfall 1: 将“文件高频变更”误判为“逻辑高风险”
**What goes wrong:** i18n、样式类文件修改频繁但不一定影响核心行为。[VERIFIED: merge 高频文件中含 `i18n` 和样式路径]
**Why it happens:** 未将“行为关键度”纳入评分。[ASSUMED]
**How to avoid:** 评分加入 `BehaviorCritical` 维度(路由/线程/skills 协议加权)。[ASSUMED]
**Warning signs:** P0 文件集中在文案/样式但不包含路由和 core hooks。[ASSUMED]
### Pitfall 2: Titan overlap 仅按作者名判断
**What goes wrong:** 可能漏掉“由他人移植 Titan 逻辑”的提交。[VERIFIED: `7342cc08` 为 MT-Mint 提交但 message 明确“移植 Titan main”]
**Why it happens:** 只用 `--author=Titan` 单一条件。[VERIFIED: git log 结果对比]
**How to avoid:** 采用“双轨识别”:作者轨 + 语义轨commit message/目标文件)。[ASSUMED]
**Warning signs:** 决策矩阵里出现“作者不为 Titan 但逻辑来源是 Titan”的争议。[ASSUMED]
### Pitfall 3: “旧视觉 + 新逻辑”没有技术切面边界
**What goes wrong:** 改视觉时误改路由/状态机,或保逻辑时回带新视觉样式。[ASSUMED]
**Why it happens:** 文件内视图与逻辑耦合(如 page.tsx、input-box。[VERIFIED: `.planning/codebase/CONCERNS.md` 指出前端关键组件耦合大]
**How to avoid:** 在 PR 内按 L0/L1/L2 三层分块提交与评审。[ASSUMED]
**Warning signs:** 单个提交同时修改 query 参数行为和 CSS/token。[ASSUMED]
### Pitfall 4: 决策矩阵没有文件级验证闭环
**What goes wrong:** 决策落地后无法证明“行为未回退”。[ASSUMED]
**Why it happens:** 缺少“决策 -> 测试映射”。[ASSUMED]
**How to avoid:** 每个 P0/P1 文件绑定至少一个自动化验证命令(见 Validation Architecture。[VERIFIED: 本文 Validation Architecture]
**Warning signs:** reviewer 只能靠截图判断是否正确。[ASSUMED]
## Code Examples
### 1) 生成冲突热点文件清单merge 来源)
```bash
# Source: git-show docs + repo commits
for c in 8a2cac7b 0fff2880 588673d0 6a540d84 6335424a 49503504; do
git show -m --name-only --pretty=format: "$c" -- frontend
done | sed '/^$/d' | sort | uniq -c | sort -nr
```
[CITED: https://git-scm.com/docs/git-show][VERIFIED: 本仓库已执行同类命令]
### 2) 生成 Titan 触达文件清单
```bash
# Source: git-log docs + repo history
git log --all --author='[Tt]itan' --name-only --pretty=format: -- frontend \
| sed '/^$/d' | sort | uniq -c | sort -nr
```
[CITED: https://git-scm.com/docs/git-log][VERIFIED: 本仓库已执行]
### 3) 决策矩阵打分(文件级,可脚本化)
```text
RiskScore = 0.35*MergeFreq + 0.30*TitanOverlap + 0.25*BehaviorCritical + 0.10*TestGap
P0: >= 0.75
P1: 0.50 - 0.74
P2: < 0.50
```
[ASSUMED]
## State of the Art
| Old Approach | Current Approach | When Changed | Impact |
|--------------|------------------|--------------|--------|
| 仅按“当前 diff”做修复 | 基于历史 merge + author 证据构建矩阵 | 当前里程碑 Phase 1 定义时 [VERIFIED: `.planning/ROADMAP.md`] | 审计性更强,减少“静默回归” [ASSUMED] |
| 混合提交UI+逻辑+测试) | 按 concern 拆分提交 | 项目约束已明确 [VERIFIED: TEST-02 in `.planning/REQUIREMENTS.md`] | 回滚与评审风险显著降低 [ASSUMED] |
**Deprecated/outdated:**
- “冲突靠人工记忆追溯”应视为过时做法,不满足 Phase 01 的可审计目标。[ASSUMED]
## Assumptions Log
| # | Claim | Section | Risk if Wrong |
|---|-------|---------|---------------|
| A1 | `ripgrep` 是该场景最优扫描器 | Standard Stack | 仅影响效率,不影响正确性 |
| A2 | 风险评分权重0.35/0.30/0.25/0.10)适配本仓库 | Code Examples | 可能导致优先级排序偏差 |
| A3 | “作者轨 + 语义轨”双轨识别足以覆盖 Titan overlap | Pitfall 2 | 可能漏判少量逻辑来源 |
| A4 | L0/L1/L2 三层拆分能稳定隔离视觉与逻辑 | Pattern 3 | 若耦合过深,执行成本上升 |
## Open Questions
1. **Titan overlap 的“最终裁决权”落在谁**
- What we know: 已可机械识别 overlap 文件与提交来源。[VERIFIED: git 证据链]
- What's unclear: 业务上遇到冲突时由谁决定 keep/replace产品、前端 owner、原作者。[ASSUMED]
- Recommendation: 在 planner 阶段把“裁决角色 + SLA”写入 PLAN.md避免执行阻塞。[ASSUMED]
2. **`content_id` vs `content_ids` 的阶段边界**
- What we know: 该协议冲突属于 Phase 2LOGIC-04但 Phase 1 需要在矩阵中标红相关文件。[VERIFIED: `.planning/ROADMAP.md`, `.planning/REQUIREMENTS.md`]
- What's unclear: Phase 1 是否要提前定义兼容窗口(双写/双读)。[ASSUMED]
- Recommendation: 在 Phase 1 仅标注风险与影响范围,不提前改实现。[ASSUMED]
## Environment Availability
| Dependency | Required By | Available | Version | Fallback |
|------------|------------|-----------|---------|----------|
| `git` | 提交追溯与冲突证据采集 | ✓ [VERIFIED] | 2.43.0 [VERIFIED] | — |
| `rg` | 快速路径/文本聚合 | ✓ [VERIFIED] | 15.1.0 [VERIFIED] | `grep -R`(较慢)[ASSUMED] |
| `node` | 矩阵脚本与前端工具链 | ✓ [VERIFIED] | v24.14.0 [VERIFIED] | — |
| `pnpm` | 前端验证命令执行 | ✓ [VERIFIED] | 10.32.1 [VERIFIED] | `npm run`(脚本兼容性待验证)[ASSUMED] |
| npm registry 网络 | 在线版本核验 | ✗ [VERIFIED: `npm ping` timeout] | — | 使用仓库锁定版本 [VERIFIED] |
**Missing dependencies with no fallback:**
- 无阻塞项。[VERIFIED: 本阶段核心命令可本地执行]
**Missing dependencies with fallback:**
- 在线 npm 版本核验不可用,已降级为仓库版本基线。[VERIFIED: `npm ping` timeout]
## Validation Architecture
### Test Framework
| Property | Value |
|----------|-------|
| Framework | Playwright前端 E2E[VERIFIED: `frontend/playwright.config.ts`, `frontend/package.json`] |
| Config file | `frontend/playwright.config.ts` [VERIFIED] |
| Quick run command | `cd frontend && pnpm test:e2e --grep "welcome|routing|message|history"` [VERIFIED: scripts + spec 文件名] |
| Full suite command | `cd frontend && pnpm test:e2e` [VERIFIED: `frontend/package.json`] |
### Phase Requirements → Test Map
| Req ID | Behavior | Test Type | Automated Command | File Exists? |
|--------|----------|-----------|-------------------|-------------|
| MERGE-01 | 冲突文件修复后消息/历史/路由不回归 | e2e | `cd frontend && pnpm test:e2e --grep "message|history|welcome|routing"` | ✅ [VERIFIED: `frontend/tests/e2e/message-and-history.spec.ts`, `welcome-and-routing.spec.ts`] |
| MERGE-03 | Titan 重叠文件thread/skills决策后行为稳定 | e2e | `cd frontend && pnpm test:e2e --grep "artifacts|thread|input|compose"` | ✅ [VERIFIED: `artifacts-and-thread-reuse.spec.ts`, `input-and-compose.spec.ts`] |
### Sampling Rate
- **Per task commit:** `cd frontend && pnpm lint && pnpm typecheck` [VERIFIED: scripts]
- **Per wave merge:** `cd frontend && pnpm test:e2e --grep "welcome|routing|message|history"` [ASSUMED]
- **Phase gate:** `cd frontend && pnpm test:e2e` 全绿 [VERIFIED: TEST-01 expectation + script]
### Wave 0 Gaps
- [ ] 增加“决策矩阵驱动”的文件级 smoke 脚本(读取 `decision-matrix.md` 自动选择 e2e 子集)[ASSUMED]
- [ ] 为 `page.tsx` / `core/threads/hooks.ts` 增加更细粒度单测入口(当前以 E2E 为主)[VERIFIED: 现有 unit 覆盖相对少 in `.planning/codebase/CONCERNS.md`]
## Security Domain
### Applicable ASVS Categories
| ASVS Category | Applies | Standard Control |
|---------------|---------|-----------------|
| V2 Authentication | no本阶段不改 auth 机制)[ASSUMED] | 保持现状,避免引入新入口 [ASSUMED] |
| V3 Session Management | no本阶段不改会话后端[ASSUMED] | 不触碰 session 持久逻辑 [ASSUMED] |
| V4 Access Control | no本阶段为前端冲突盘点[ASSUMED] | 决策矩阵不新增权限路径 [ASSUMED] |
| V5 Input Validation | yes路由参数行为需防回归[VERIFIED: LOGIC-03 对 `thread_id/isnew/xclaw_used` 有明确要求] | 对 query 参数路径做回归校验E2E[ASSUMED] |
| V6 Cryptography | no无密码学改动[ASSUMED] | N/A |
### Known Threat Patterns for this phase
| Pattern | STRIDE | Standard Mitigation |
|---------|--------|---------------------|
| 决策错误导致路由参数语义回退 | Tampering | P0 文件先验回归welcome/routing/thread reuse[VERIFIED: 现有 e2e 覆盖路径] |
| 冲突修复引入重复逻辑路径 | Tampering/DoS | 决策矩阵强制标注 keep/replace + dead-path 检查 [ASSUMED] |
## Sources
### Primary (HIGH confidence)
- `.planning/PROJECT.md` - 项目目标、约束、核心价值 [VERIFIED: local file]
- `.planning/REQUIREMENTS.md` - MERGE-01/MERGE-03/LOGIC 约束 [VERIFIED: local file]
- `.planning/ROADMAP.md` - Phase 01 目标边界 [VERIFIED: local file]
- `.planning/codebase/ARCHITECTURE.md` / `STRUCTURE.md` / `CONCERNS.md` / `CONVENTIONS.md` [VERIFIED: local files]
- `git log`, `git show -m`, `git diff`, `git merge-base` 实测输出 [VERIFIED: local commands in this session]
### Secondary (MEDIUM confidence)
- Git 官方文档:`git-log`, `git-show`, `git-diff`, `git-blame` [CITED: https://git-scm.com/docs/git-log] [CITED: https://git-scm.com/docs/git-show] [CITED: https://git-scm.com/docs/git-diff] [CITED: https://git-scm.com/docs/git-blame]
### Tertiary (LOW confidence)
- 无仅单源且未验证的外部结论;低置信度内容已全部标记为 `[ASSUMED]`。[VERIFIED: 本文 Assumptions Log]
## Metadata
**Confidence breakdown:**
- Standard stack: HIGH - 本机工具与仓库依赖均可本地验证;仅 npm 在线版本核验不可用。[VERIFIED]
- Architecture: HIGH - 完全基于仓库规划文档与 git 历史证据。[VERIFIED]
- Pitfalls: MEDIUM - 根因和预防部分含工程经验推断,已显式标记 `[ASSUMED]`
**Research date:** 2026-04-07 [VERIFIED]
**Valid until:** 2026-05-0730 天,若出现新的大规模 merge 提交需提前刷新)[ASSUMED]

View File

@ -15,9 +15,3 @@
# NEXT_PUBLIC_BACKEND_BASE_URL="http://localhost:8001" # NEXT_PUBLIC_BACKEND_BASE_URL="http://localhost:8001"
# NEXT_PUBLIC_LANGGRAPH_BASE_URL="http://localhost:2024" # NEXT_PUBLIC_LANGGRAPH_BASE_URL="http://localhost:2024"
# LangGraph API base URL
# Default: /api/langgraph (uses langgraph dev server via nginx)
# Set to /api/langgraph-compat to use the experimental Gateway-backed runtime
# Requires: SKIP_LANGGRAPH_SERVER=1 in serve.sh (optional, saves resources)
# NEXT_PUBLIC_LANGGRAPH_BASE_URL=/api/langgraph-compat

3
frontend/.gitignore vendored
View File

@ -5,6 +5,8 @@
/.pnp /.pnp
.pnp.js .pnp.js
.codex
# testing # testing
/coverage /coverage
@ -20,6 +22,7 @@ next-env.d.ts
# production # production
/build /build
docs
# misc # misc
.DS_Store .DS_Store

View File

@ -4,7 +4,6 @@
# --target prod — full build baked in, run `pnpm start` at container start (default if no --target is specified) # --target prod — full build baked in, run `pnpm start` at container start (default if no --target is specified)
ARG PNPM_STORE_PATH=/root/.local/share/pnpm/store ARG PNPM_STORE_PATH=/root/.local/share/pnpm/store
ARG NPM_REGISTRY
# ── Base: shared setup ──────────────────────────────────────────────────────── # ── Base: shared setup ────────────────────────────────────────────────────────
FROM node:22-alpine AS base FROM node:22-alpine AS base

View File

@ -4,58 +4,11 @@
*/ */
import "./src/env.js"; import "./src/env.js";
function getInternalServiceURL(envKey, fallbackURL) {
const configured = process.env[envKey]?.trim();
return configured && configured.length > 0
? configured.replace(/\/+$/, "")
: fallbackURL;
}
import nextra from "nextra";
const withNextra = nextra({});
/** @type {import("next").NextConfig} */ /** @type {import("next").NextConfig} */
const config = { const config = {
i18n: {
locales: ["en", "zh"],
defaultLocale: "en",
},
devIndicators: false, devIndicators: false,
async rewrites() { output: "standalone",
const rewrites = []; productionBrowserSourceMaps: false,
const langgraphURL = getInternalServiceURL(
"DEER_FLOW_INTERNAL_LANGGRAPH_BASE_URL",
"http://127.0.0.1:2024",
);
const gatewayURL = getInternalServiceURL(
"DEER_FLOW_INTERNAL_GATEWAY_BASE_URL",
"http://127.0.0.1:8001",
);
if (!process.env.NEXT_PUBLIC_LANGGRAPH_BASE_URL) {
rewrites.push({
source: "/api/langgraph",
destination: langgraphURL,
});
rewrites.push({
source: "/api/langgraph/:path*",
destination: `${langgraphURL}/:path*`,
});
}
if (!process.env.NEXT_PUBLIC_BACKEND_BASE_URL) {
rewrites.push({
source: "/api/agents",
destination: `${gatewayURL}/api/agents`,
});
rewrites.push({
source: "/api/agents/:path*",
destination: `${gatewayURL}/api/agents/:path*`,
});
}
return rewrites;
},
}; };
export default withNextra(config); export default config;

View File

@ -6,12 +6,15 @@
"scripts": { "scripts": {
"demo:save": "node scripts/save-demo.js", "demo:save": "node scripts/save-demo.js",
"build": "next build", "build": "next build",
"check": "eslint . --ext .ts,.tsx && tsc --noEmit", "check": "eslint . --ext .ts,.tsx --ignore-pattern imports/** && tsc --noEmit",
"dev": "next dev --turbo", "dev": "next dev --turbo",
"format": "prettier --check .", "format": "prettier --check .",
"format:write": "prettier --write .", "format:write": "prettier --write .",
"lint": "eslint . --ext .ts,.tsx", "lint": "eslint . --ext .ts,.tsx --ignore-pattern imports/**",
"lint:fix": "eslint . --ext .ts,.tsx --fix", "lint:fix": "eslint . --ext .ts,.tsx --ignore-pattern imports/** --fix",
"test:e2e": "playwright test",
"test:e2e:ui": "playwright test --ui",
"test:e2e:headed": "playwright test --headed",
"preview": "next build && next start", "preview": "next build && next start",
"start": "next start", "start": "next start",
"typecheck": "tsc --noEmit" "typecheck": "tsc --noEmit"
@ -59,18 +62,19 @@
"cmdk": "^1.1.1", "cmdk": "^1.1.1",
"codemirror": "^6.0.2", "codemirror": "^6.0.2",
"date-fns": "^4.1.0", "date-fns": "^4.1.0",
"docx": "^9.6.1",
"dotenv": "^17.2.3", "dotenv": "^17.2.3",
"embla-carousel-react": "^8.6.0", "embla-carousel-react": "^8.6.0",
"gsap": "^3.13.0", "gsap": "^3.13.0",
"hast": "^1.0.0", "hast": "^1.0.0",
"html2pdf.js": "^0.14.0",
"katex": "^0.16.28", "katex": "^0.16.28",
"lucide-react": "^0.562.0", "lucide-react": "^0.562.0",
"marked": "^17.0.5",
"motion": "^12.26.2", "motion": "^12.26.2",
"nanoid": "^5.1.6", "nanoid": "^5.1.6",
"next": "^16.1.7", "next": "^16.1.7",
"next-themes": "^0.4.6", "next-themes": "^0.4.6",
"nextra": "^4.6.1",
"nextra-theme-docs": "^4.6.1",
"nuxt-og-image": "^5.1.13", "nuxt-og-image": "^5.1.13",
"ogl": "^1.0.11", "ogl": "^1.0.11",
"react": "^19.0.0", "react": "^19.0.0",
@ -92,6 +96,7 @@
}, },
"devDependencies": { "devDependencies": {
"@eslint/eslintrc": "^3.3.1", "@eslint/eslintrc": "^3.3.1",
"@playwright/test": "^1.48.0",
"@tailwindcss/postcss": "^4.0.15", "@tailwindcss/postcss": "^4.0.15",
"@types/gsap": "^3.0.0", "@types/gsap": "^3.0.0",
"@types/node": "^20.14.10", "@types/node": "^20.14.10",

View File

@ -0,0 +1,34 @@
import { defineConfig, devices } from "@playwright/test";
import { config as loadEnv } from "dotenv";
import path from "node:path";
import { fileURLToPath } from "node:url";
const configDir = path.dirname(fileURLToPath(import.meta.url));
// Load local e2e env defaults from frontend/.env(.local), while keeping shell env highest priority.
loadEnv({ path: path.resolve(configDir, ".env.local") });
loadEnv({ path: path.resolve(configDir, ".env") });
const baseURL = process.env.FRONTEND_E2E_BASE_URL ?? "http://127.0.0.1:3000";
export default defineConfig({
testDir: "./tests/e2e",
timeout: 30_000,
expect: {
timeout: 10_000,
},
fullyParallel: true,
retries: process.env.CI ? 1 : 0,
reporter: process.env.CI ? [["list"], ["html", { open: "never" }]] : "list",
use: {
baseURL,
trace: "on-first-retry",
screenshot: "only-on-failure",
video: "retain-on-failure",
},
projects: [
{
name: "chromium",
use: { ...devices["Desktop Chrome"] },
},
],
});

File diff suppressed because it is too large Load Diff

Binary file not shown.

Before

Width:  |  Height:  |  Size: 4.2 KiB

After

Width:  |  Height:  |  Size: 4.3 KiB

View File

@ -8,8 +8,8 @@ import { I18nProvider } from "@/core/i18n/context";
import { detectLocaleServer } from "@/core/i18n/server"; import { detectLocaleServer } from "@/core/i18n/server";
export const metadata: Metadata = { export const metadata: Metadata = {
title: "DeerFlow", title: "XClaw",
description: "A LangChain-based framework for building super agents.", description: "Desscriptions of XClawDesscriptions of XClawDesscriptions of XClaw",
}; };
export default async function RootLayout({ export default async function RootLayout({