From 9e63915f4277babfcf92b727a5e35e23789181bb Mon Sep 17 00:00:00 2001 From: chiguyong Date: Sat, 23 May 2026 21:35:10 +0800 Subject: [PATCH] =?UTF-8?q?=E2=9C=A8=20feat:=20=E5=AE=8C=E6=88=90=E7=B3=BB?= =?UTF-8?q?=E7=BB=9F=E7=9C=9F=E5=AE=9E=E5=8C=96=E6=94=B9=E9=80=A0=20+=20Mo?= =?UTF-8?q?ck=E6=B8=85=E9=99=A4=20+=20=E6=96=87=E6=A1=A3=E7=BC=96=E5=86=99?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit - 实现 Onboarding 后端 API(6个端点完整对接) - 接入百炼 DashScope LLM(qwen3-coder-plus 真实引用检测) - 修复知识库 MockEmbedder(自动检测 API Key 切换真实 Embedder) - 内容生成对接 RAG 知识库检索 - 清除前端 onboarding 硬编码假数据(改为错误提示+重试) - 移除模拟加载延迟(setTimeout) - Pipeline dry-run 模式添加生产环境告警 - 添加操作流程文档和后续待办事项文档 - 更新 .gitignore 排除测试产物和临时文件 --- .dockerignore | 14 + .env.example | 90 +- .github/workflows/ci.yml | 101 + .github/workflows/pr-check.yml | 99 + .gitignore | 14 + .../zh/content/API接口文档/API接口文档.md | 444 +++- .../zh/content/前端系统架构/前端系统架构.md | 265 +- .../zh/content/后端系统架构/后端系统架构.md | 501 +++- .../repowiki/zh/content/开发指南/开发指南.md | 602 +++-- .../zh/content/扩展与定制/扩展与定制.md | 224 +- .../zh/content/数据库设计/数据库设计.md | 1338 ++++++++-- .../repowiki/zh/content/测试策略/测试策略.md | 409 +++- .../zh/content/部署与运维/部署与运维.md | 367 ++- .../zh/content/项目概述/核心功能/核心功能.md | 418 +++- .../repowiki/zh/meta/repowiki-metadata.json | 2 +- README.md | 3 + backend/.dockerignore | 13 + backend/Dockerfile | 7 +- ...724556401_add_missing_sentiment_fields.py} | 16 +- ...75_add_citation_source_analysis_fields.py} | 16 +- ...34_add_alerts_and_alert_settings_tables.py | 4 +- ... => e5f7a9b1cd35_add_suggestions_table.py} | 8 +- backend/app/agent_framework/base.py | 19 +- .../app/agent_framework/pipeline/engine.py | 12 +- backend/app/api/admin.py | 6 +- backend/app/api/agents.py | 79 +- backend/app/api/analytics.py | 37 +- backend/app/api/auth.py | 61 +- backend/app/api/base.py | 46 + backend/app/api/brands.py | 45 +- backend/app/api/content.py | 50 +- backend/app/api/dashboard.py | 21 +- backend/app/api/lifecycle.py | 98 +- backend/app/api/onboarding.py | 514 ++++ backend/app/api/queries.py | 10 +- backend/app/config.py | 43 +- backend/app/database.py | 19 +- backend/app/logging_config.py | 57 + backend/app/main.py | 124 +- backend/app/middleware/metrics.py | 60 + backend/app/middleware/rate_limit.py | 71 +- backend/app/middleware/request_id.py | 29 + backend/app/schemas/auth.py | 12 + backend/app/schemas/common.py | 45 + backend/app/schemas/lifecycle.py | 36 +- backend/app/services/admin.py | 23 +- backend/app/services/auth.py | 33 +- backend/app/services/cache.py | 106 + backend/app/services/citation.py | 9 + backend/app/services/knowledge/rag_service.py | 11 +- backend/app/services/llm/__init__.py | 3 + backend/app/services/llm/deepseek_provider.py | 7 + backend/app/services/llm/openai_provider.py | 7 + backend/app/services/llm/rate_limiter.py | 105 + backend/app/workers/llm_adapter.py | 29 +- backend/fix_citation_schema.py | 54 + backend/pyproject.toml | 17 + backend/requirements.txt | 1 + backend/tests/test_performance.py | 381 +++ backend/tests/test_security.py | 667 +++++ backend/update_email.py | 39 - csrf.json | 1 + csrf_headers.txt | 13 + csrf_resp.json | 1 + docker-compose.prod.yml | 140 ++ docker-compose.yml | 28 + docs/后续待办事项.md | 116 + docs/操作流程.md | 399 +++ frontend/.dockerignore | 11 + frontend/Dockerfile | 39 +- frontend/__tests__/hooks/use-api.test.ts | 314 +++ frontend/__tests__/lib/api/client.test.ts | 239 ++ frontend/__tests__/stores/brand-store.test.ts | 440 ++++ .../stores/notification-store.test.ts | 232 ++ frontend/app/(auth)/login/page.tsx | 8 +- frontend/app/(dashboard)/brands/page.tsx | 101 +- .../app/(dashboard)/dashboard/admin/page.tsx | 283 +-- .../(dashboard)/dashboard/analytics/page.tsx | 270 +-- .../(dashboard)/dashboard/citations/page.tsx | 100 +- .../(dashboard)/dashboard/content/page.tsx | 33 +- .../dashboard/distribution/page.tsx | 72 +- .../(dashboard)/dashboard/knowledge/page.tsx | 142 +- frontend/app/(dashboard)/dashboard/page.tsx | 352 ++- .../(dashboard)/dashboard/queries/page.tsx | 151 +- .../(dashboard)/dashboard/reports/page.tsx | 97 +- frontend/app/(dashboard)/layout.tsx | 203 +- .../onboarding/Step2Competitors.tsx | 56 +- .../onboarding/Step4HealthReport.tsx | 83 +- .../onboarding/Step5ActionSuggestions.tsx | 95 +- frontend/app/globals.css | 13 +- frontend/app/layout.tsx | 5 +- frontend/components/ErrorBoundary.tsx | 130 + frontend/components/business/metric-card.tsx | 162 +- frontend/components/layout/header.tsx | 40 +- frontend/components/layout/side-nav.tsx | 221 +- frontend/components/ui/api-states.tsx | 137 ++ frontend/components/ui/button.tsx | 10 +- frontend/components/ui/card.tsx | 4 +- .../components/ui/notification-container.tsx | 90 + .../login-redirect-system-chrome.spec.ts | 27 + frontend/e2e/tests/login-redirect.spec.ts | 53 + frontend/lib/api.ts | 4 + frontend/lib/api/admin.ts | 39 +- frontend/lib/api/alerts.ts | 49 + frontend/lib/api/brands.ts | 89 + frontend/lib/api/citations.ts | 29 +- frontend/lib/api/client.ts | 22 +- frontend/lib/api/index.ts | 16 + frontend/lib/api/knowledge.ts | 2 +- frontend/lib/api/onboarding.ts | 47 + frontend/lib/api/queries.ts | 43 +- frontend/lib/api/suggestions.ts | 44 + frontend/lib/auth.ts | 68 +- frontend/lib/hooks/use-api.ts | 171 ++ frontend/lib/stores/brand-store.ts | 306 +++ frontend/lib/stores/index.ts | 30 + frontend/lib/stores/notification-store.ts | 134 + frontend/lib/stores/user-store.ts | 104 + frontend/next.config.mjs | 4 +- frontend/package-lock.json | 2155 ++++++++++++++++- frontend/package.json | 18 +- ...c38299aac52370c08620b8c68905e55ba39c4b.png | Bin 27041 -> 0 bytes ...0b25ad409e051f9fc12fa8d03dd42cc4eb465a.zip | Bin 356984 -> 0 bytes ...aa98d58fee49c33b668c9262312fba8fbbc8b8b.md | 163 -- ...f630aa468fe7ee067da8e5a5eab9ce0475d05c.zip | Bin 1132197 -> 0 bytes ...70454080c2b67f718462fa287b42ea71165a06.png | Bin 94320 -> 0 bytes ...08296d1ab8d4f03cce50a6e50dfd7a19a360922.md | 326 --- ...d1096a19c3b50b45a2152b014a556e77478e7a.zip | Bin 403483 -> 0 bytes ...cb5d781ba020854958d9fb3ba23df08bbfc43b.png | Bin 33322 -> 0 bytes ...dab206a1be07b21d163a356f73e82c7e838e003.md | 163 -- frontend/playwright-report/index.html | 26 +- .../trace/assets/codeMirrorModule-DS0FLvoc.js | 32 - .../assets/defaultSettingsView-GTWI-W_B.js | 262 -- .../trace/defaultSettingsView.B4dS75f0.css | 1 - .../playwright-report/trace/index.C5466mMT.js | 2 - frontend/playwright-report/trace/index.html | 7 +- .../playwright-report/trace/snapshot.html | 19 +- frontend/playwright-report/trace/sw.bundle.js | 8 +- .../trace/uiMode.Vipi55dB.js | 6 - frontend/playwright-report/trace/uiMode.html | 7 +- frontend/tailwind.config.ts | 11 +- frontend/test-results/.last-run.json | 22 +- .../error-context.md | 163 -- .../test-failed-1.png | Bin 27041 -> 0 bytes .../trace.zip | Bin 350094 -> 0 bytes .../error-context.md | 163 -- .../test-failed-1.png | Bin 27041 -> 0 bytes frontend/types/next-auth.d.ts | 6 + frontend/vitest.config.ts | 27 + frontend/vitest.setup.ts | 43 + 150 files changed, 13957 insertions(+), 3726 deletions(-) create mode 100644 .dockerignore create mode 100644 .github/workflows/ci.yml create mode 100644 .github/workflows/pr-check.yml create mode 100644 backend/.dockerignore rename backend/alembic/versions/{d4e6f8a0bc13_add_sentiment_fields.py => 059724556401_add_missing_sentiment_fields.py} (75%) rename backend/alembic/versions/{d4e6f8a0bc23_add_citation_source_analysis_fields.py => 8ccb553ff975_add_citation_source_analysis_fields.py} (81%) rename backend/alembic/versions/{e5f7a9b1cd34_add_suggestions_table.py => e5f7a9b1cd35_add_suggestions_table.py} (95%) create mode 100644 backend/app/api/base.py create mode 100644 backend/app/api/onboarding.py create mode 100644 backend/app/logging_config.py create mode 100644 backend/app/middleware/metrics.py create mode 100644 backend/app/middleware/request_id.py create mode 100644 backend/app/schemas/common.py create mode 100644 backend/app/services/cache.py create mode 100644 backend/app/services/llm/rate_limiter.py create mode 100644 backend/fix_citation_schema.py create mode 100644 backend/pyproject.toml create mode 100644 backend/tests/test_performance.py create mode 100644 backend/tests/test_security.py delete mode 100644 backend/update_email.py create mode 100644 csrf.json create mode 100644 csrf_headers.txt create mode 100644 csrf_resp.json create mode 100644 docker-compose.prod.yml create mode 100644 docs/后续待办事项.md create mode 100644 docs/操作流程.md create mode 100644 frontend/.dockerignore create mode 100644 frontend/__tests__/hooks/use-api.test.ts create mode 100644 frontend/__tests__/lib/api/client.test.ts create mode 100644 frontend/__tests__/stores/brand-store.test.ts create mode 100644 frontend/__tests__/stores/notification-store.test.ts create mode 100644 frontend/components/ErrorBoundary.tsx create mode 100644 frontend/components/ui/api-states.tsx create mode 100644 frontend/components/ui/notification-container.tsx create mode 100644 frontend/e2e/tests/login-redirect-system-chrome.spec.ts create mode 100644 frontend/e2e/tests/login-redirect.spec.ts create mode 100644 frontend/lib/api/alerts.ts create mode 100644 frontend/lib/api/brands.ts create mode 100644 frontend/lib/api/onboarding.ts create mode 100644 frontend/lib/api/suggestions.ts create mode 100644 frontend/lib/hooks/use-api.ts create mode 100644 frontend/lib/stores/brand-store.ts create mode 100644 frontend/lib/stores/index.ts create mode 100644 frontend/lib/stores/notification-store.ts create mode 100644 frontend/lib/stores/user-store.ts delete mode 100644 frontend/playwright-report/data/02c38299aac52370c08620b8c68905e55ba39c4b.png delete mode 100644 frontend/playwright-report/data/050b25ad409e051f9fc12fa8d03dd42cc4eb465a.zip delete mode 100644 frontend/playwright-report/data/0aa98d58fee49c33b668c9262312fba8fbbc8b8b.md delete mode 100644 frontend/playwright-report/data/0af630aa468fe7ee067da8e5a5eab9ce0475d05c.zip delete mode 100644 frontend/playwright-report/data/a770454080c2b67f718462fa287b42ea71165a06.png delete mode 100644 frontend/playwright-report/data/e08296d1ab8d4f03cce50a6e50dfd7a19a360922.md delete mode 100644 frontend/playwright-report/data/e9d1096a19c3b50b45a2152b014a556e77478e7a.zip delete mode 100644 frontend/playwright-report/data/f1cb5d781ba020854958d9fb3ba23df08bbfc43b.png delete mode 100644 frontend/playwright-report/data/fdab206a1be07b21d163a356f73e82c7e838e003.md delete mode 100644 frontend/playwright-report/trace/assets/codeMirrorModule-DS0FLvoc.js delete mode 100644 frontend/playwright-report/trace/assets/defaultSettingsView-GTWI-W_B.js delete mode 100644 frontend/playwright-report/trace/defaultSettingsView.B4dS75f0.css delete mode 100644 frontend/playwright-report/trace/index.C5466mMT.js delete mode 100644 frontend/playwright-report/trace/uiMode.Vipi55dB.js delete mode 100644 frontend/test-results/dashboard-health-健康状态Dashboard---响应式设计测试-移动端视口下概览卡片堆叠显示-chromium-retry1/error-context.md delete mode 100644 frontend/test-results/dashboard-health-健康状态Dashboard---响应式设计测试-移动端视口下概览卡片堆叠显示-chromium-retry1/test-failed-1.png delete mode 100644 frontend/test-results/dashboard-health-健康状态Dashboard---响应式设计测试-移动端视口下概览卡片堆叠显示-chromium-retry1/trace.zip delete mode 100644 frontend/test-results/dashboard-health-健康状态Dashboard---响应式设计测试-移动端视口下概览卡片堆叠显示-chromium/error-context.md delete mode 100644 frontend/test-results/dashboard-health-健康状态Dashboard---响应式设计测试-移动端视口下概览卡片堆叠显示-chromium/test-failed-1.png create mode 100644 frontend/vitest.config.ts create mode 100644 frontend/vitest.setup.ts diff --git a/.dockerignore b/.dockerignore new file mode 100644 index 0000000..d517c48 --- /dev/null +++ b/.dockerignore @@ -0,0 +1,14 @@ +# 根目录 .dockerignore(用于 docker-compose 构建上下文) +.git/ +.gitignore +docs/ +tests/ +*.md +*.log +*.txt +.env +.env.* +.pytest_cache/ +__pycache__/ +*.pyc +*.pyo diff --git a/.env.example b/.env.example index 4dc1674..eeed042 100644 --- a/.env.example +++ b/.env.example @@ -1,34 +1,90 @@ -# 数据库 +# ============================================================================= +# GEO 平台环境变量配置模板 +# 复制此文件为 .env 并填入真实值,切勿将 .env 提交到 Git +# ============================================================================= + +# ----------------------------------------------------------------------------- +# 数据库(PostgreSQL) +# ----------------------------------------------------------------------------- DATABASE_URL=postgresql+asyncpg://postgres:postgres123@db:5432/geo_platform -# Redis +# ----------------------------------------------------------------------------- +# Redis(缓存 / 任务队列) +# ----------------------------------------------------------------------------- REDIS_URL=redis://redis:6379/0 -# JWT -JWT_SECRET=your-secret-key-change-in-production +# ----------------------------------------------------------------------------- +# JWT 认证密钥 +# 必须 >= 32 字符,可用以下命令生成: +# python3 -c "import secrets; print(secrets.token_hex(32))" +# ----------------------------------------------------------------------------- +JWT_SECRET=your-jwt-secret-at-least-32-characters-long JWT_EXPIRE_HOURS=24 -# 前端 -NEXT_PUBLIC_API_URL=http://localhost:8000 +# ----------------------------------------------------------------------------- +# NextAuth / 前端 Session 密钥(如使用 NextAuth,必须 >= 32 字符) +# ----------------------------------------------------------------------------- +SECRET_KEY=your-nextauth-secret-at-least-32-characters-long -# Playwright +# ----------------------------------------------------------------------------- +# 前端 & CORS +# ----------------------------------------------------------------------------- +NEXT_PUBLIC_API_URL=http://localhost:8000 +CORS_ORIGINS=http://localhost:3000,http://localhost:3001 + +# ----------------------------------------------------------------------------- +# Playwright(用于 SEO 抓取,Docker 内路径) +# ----------------------------------------------------------------------------- PLAYWRIGHT_BROWSERS_PATH=/ms-playwright -# 国内大模型API(可选) -ZHIPU_API_KEY= -TONGYI_API_KEY= +# ----------------------------------------------------------------------------- +# LLM 功能开关 +# ----------------------------------------------------------------------------- +ENABLE_LLM=true -# ---- LLM Provider 配置 ---- -# 默认LLM提供商: openai | deepseek +# ----------------------------------------------------------------------------- +# LLM Provider 配置 +# 支持: openai | deepseek +# 使用 OpenAI 兼容协议,可对接 DashScope、DeepSeek 等平台 +# ----------------------------------------------------------------------------- DEFAULT_LLM_PROVIDER=openai +DEFAULT_LLM_MODEL=qwen3-coder-plus -# OpenAI -OPENAI_API_KEY= -OPENAI_MODEL=gpt-4o-mini -OPENAI_BASE_URL=https://api.openai.com/v1 +# OpenAI 层配置(百炼 DashScope Coding Plan 优先) +# 百炼 API Key: 癷67 https://bailian.console.aliyun.com/ 申请 +OPENAI_API_KEY=your-dashscope-api-key-here +OPENAI_MODEL=qwen3-coder-plus +OPENAI_BASE_URL=https://coding.dashscope.aliyuncs.com/v1 # DeepSeek -DEEPSEEK_API_KEY= +DEEPSEEK_API_KEY=your-deepseek-api-key-here DEEPSEEK_MODEL=deepseek-chat DEEPSEEK_BASE_URL=https://api.deepseek.com/v1 DEEPSEEK_MAX_CONTEXT=64000 + +# ----------------------------------------------------------------------------- +# 国内 AI 平台 API(可选,按需填写) +# ----------------------------------------------------------------------------- + +# 智谱 AI(ChatGLM 系列) +ZHIPU_API_KEY=your-zhipu-api-key-here + +# 阿里云通义千问 +TONGYI_API_KEY=your-tongyi-api-key-here + +# Kimi(月之暗面) +MOONSHOT_API_KEY=your-moonshot-api-key-here + +# 百度千帆(文心一言) +BAIDU_QIANFAN_API_KEY=your-baidu-qianfan-api-key-here +BAIDU_QIANFAN_SECRET_KEY=your-baidu-qianfan-secret-key-here + +# 豆包(字节跳动) +DOUBAO_API_KEY=your-doubao-api-key-here +DOUBAO_ENDPOINT_ID=your-doubao-endpoint-id-here + +# ----------------------------------------------------------------------------- +# API 调用频率限制 +# ----------------------------------------------------------------------------- +# 每分钟最大请求数(防止触发平台限速) +API_RATE_LIMIT_RPM=10 diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml new file mode 100644 index 0000000..9cc3c4e --- /dev/null +++ b/.github/workflows/ci.yml @@ -0,0 +1,101 @@ +name: CI Pipeline + +on: + push: + branches: [main, develop] + pull_request: + branches: [main] + +jobs: + # ── 后端 ────────────────────────────────────────────── + backend-lint-test: + runs-on: ubuntu-latest + services: + postgres: + image: postgres:15 + env: + POSTGRES_USER: test + POSTGRES_PASSWORD: test + POSTGRES_DB: geo_test + ports: ['5432:5432'] + options: >- + --health-cmd pg_isready + --health-interval 10s + --health-timeout 5s + --health-retries 5 + redis: + image: redis:7 + ports: ['6379:6379'] + options: >- + --health-cmd "redis-cli ping" + --health-interval 10s + --health-timeout 5s + --health-retries 5 + + steps: + - uses: actions/checkout@v4 + + - uses: actions/setup-python@v5 + with: + python-version: '3.11' + cache: 'pip' + + - name: Install dependencies + run: | + cd backend + pip install -r requirements.txt + pip install ruff pytest-cov + + - name: Lint (ruff) + run: cd backend && ruff check app/ + + - name: Type check (optional) + run: cd backend && ruff check app/ --select=E,W + continue-on-error: true + + - name: Run tests + env: + DATABASE_URL: postgresql+asyncpg://test:test@localhost:5432/geo_test + REDIS_URL: redis://localhost:6379/0 + JWT_SECRET: test-secret-key-minimum-32-characters-long + ENVIRONMENT: test + run: | + cd backend + pytest tests/ -v --tb=short + + # ── 前端 ────────────────────────────────────────────── + frontend-lint-test: + runs-on: ubuntu-latest + steps: + - uses: actions/checkout@v4 + + - uses: actions/setup-node@v4 + with: + node-version: '20' + cache: 'npm' + cache-dependency-path: frontend/package-lock.json + + - name: Install dependencies + run: cd frontend && npm ci + + - name: Lint (ESLint) + run: cd frontend && npm run lint + + - name: Type check + run: cd frontend && npx tsc --noEmit + + - name: Unit tests + run: cd frontend && npm run test:ci + + # ── Docker build 验证 ────────────────────────────────── + docker-build: + runs-on: ubuntu-latest + needs: [backend-lint-test, frontend-lint-test] + steps: + - uses: actions/checkout@v4 + + - name: Build backend image + run: docker build -t geo-backend:test ./backend + + - name: Build frontend image + run: docker build -t geo-frontend:test ./frontend diff --git a/.github/workflows/pr-check.yml b/.github/workflows/pr-check.yml new file mode 100644 index 0000000..425831f --- /dev/null +++ b/.github/workflows/pr-check.yml @@ -0,0 +1,99 @@ +name: PR Check + +on: + pull_request: + branches: [main, develop] + types: [opened, synchronize, reopened] + +jobs: + pr-lint-test: + name: Lint & Test (PR) + runs-on: ubuntu-latest + services: + postgres: + image: postgres:15 + env: + POSTGRES_USER: test + POSTGRES_PASSWORD: test + POSTGRES_DB: geo_test + ports: ['5432:5432'] + options: >- + --health-cmd pg_isready + --health-interval 10s + --health-timeout 5s + --health-retries 5 + redis: + image: redis:7 + ports: ['6379:6379'] + options: >- + --health-cmd "redis-cli ping" + --health-interval 10s + --health-timeout 5s + --health-retries 5 + + steps: + - uses: actions/checkout@v4 + with: + fetch-depth: 0 + + # ── 后端检查 ────────────────────────────────── + - uses: actions/setup-python@v5 + with: + python-version: '3.11' + cache: 'pip' + + - name: Install backend dependencies + run: | + cd backend + pip install -r requirements.txt + pip install ruff pytest-cov + + - name: Backend lint + run: cd backend && ruff check app/ + + - name: Backend tests + env: + DATABASE_URL: postgresql+asyncpg://test:test@localhost:5432/geo_test + REDIS_URL: redis://localhost:6379/0 + JWT_SECRET: test-secret-key-minimum-32-characters-long + ENVIRONMENT: test + run: | + cd backend + pytest tests/ -v --tb=short --cov=app --cov-report=xml + + # ── 前端检查 ────────────────────────────────── + - uses: actions/setup-node@v4 + with: + node-version: '20' + cache: 'npm' + cache-dependency-path: frontend/package-lock.json + + - name: Install frontend dependencies + run: cd frontend && npm ci + + - name: Frontend lint + run: cd frontend && npm run lint + + - name: Frontend type check + run: cd frontend && npx tsc --noEmit + + - name: Frontend unit tests + run: cd frontend && npm run test:ci + + # ── PR 状态注释 ────────────────────────────────── + - name: Comment PR status + if: always() + uses: actions/github-script@v7 + with: + script: | + const { context, github } = require('@actions/github'); + const status = '${{ job.status }}'; + const emoji = status === 'success' ? '✅' : '❌'; + const body = `## CI 检查结果 ${emoji}\n\n**状态**: ${status}\n\n| 检查项 | 状态 |\n|--------|------|\n| 后端 Lint | ${{ steps.Backend lint.outcome || 'N/A' }} |\n| 后端测试 | ${{ steps.Backend tests.outcome || 'N/A' }} |\n| 前端 Lint | ${{ steps.Frontend lint.outcome || 'N/A' }} |\n| 前端测试 | ${{ steps.Frontend unit tests.outcome || 'N/A' }} |`; + github.rest.issues.createComment({ + issue_number: context.issue.number, + owner: context.repo.owner, + repo: context.repo.repo, + body: body + }); + continue-on-error: true diff --git a/.gitignore b/.gitignore index 326ac6f..4e1e925 100644 --- a/.gitignore +++ b/.gitignore @@ -14,7 +14,10 @@ backend/.venv/ # Environment .env +backend/.env frontend/.env.local +# 不忽略 .env.example(供新成员参考) +!.env.example # IDE .idea/ @@ -41,3 +44,14 @@ redis_data/ .npm-cache/ .pytest_cache/ tsconfig.tsbuildinfo + +# Test artifacts +frontend/test-results/ +frontend/playwright-report/ + +# Temp debug files +login_headers.txt +login_resp.json +test_login.js +test_login2.js +testfile2.txt diff --git a/.qoder/repowiki/zh/content/API接口文档/API接口文档.md b/.qoder/repowiki/zh/content/API接口文档/API接口文档.md index 49176b4..b7c433b 100644 --- a/.qoder/repowiki/zh/content/API接口文档/API接口文档.md +++ b/.qoder/repowiki/zh/content/API接口文档/API接口文档.md @@ -9,34 +9,49 @@ - [backend/app/api/reports.py](file://backend/app/api/reports.py) - [backend/app/api/subscriptions.py](file://backend/app/api/subscriptions.py) - [backend/app/api/admin.py](file://backend/app/api/admin.py) +- [backend/app/api/agents.py](file://backend/app/api/agents.py) +- [backend/app/api/analytics.py](file://backend/app/api/analytics.py) +- [backend/app/api/lifecycle.py](file://backend/app/api/lifecycle.py) +- [backend/app/api/knowledge.py](file://backend/app/api/knowledge.py) - [backend/app/api/deps.py](file://backend/app/api/deps.py) - [backend/app/middleware/rate_limit.py](file://backend/app/middleware/rate_limit.py) - [backend/app/schemas/auth.py](file://backend/app/schemas/auth.py) - [backend/app/schemas/query.py](file://backend/app/schemas/query.py) - [backend/app/schemas/citation.py](file://backend/app/schemas/citation.py) - [backend/app/schemas/subscription.py](file://backend/app/schemas/subscription.py) +- [backend/app/schemas/analytics.py](file://backend/app/schemas/analytics.py) +- [backend/app/schemas/lifecycle.py](file://backend/app/schemas/lifecycle.py) +- [backend/app/schemas/knowledge.py](file://backend/app/schemas/knowledge.py) - [backend/app/services/auth.py](file://backend/app/services/auth.py) - [backend/app/services/query.py](file://backend/app/services/query.py) - [backend/app/services/citation.py](file://backend/app/services/citation.py) - [backend/app/services/subscription.py](file://backend/app/services/subscription.py) - [backend/app/services/admin.py](file://backend/app/services/admin.py) +- [backend/app/services/analytics/insights.py](file://backend/app/services/analytics/insights.py) +- [backend/app/services/analytics/tracker.py](file://backend/app/services/analytics/tracker.py) +- [backend/app/services/knowledge/rag_service.py](file://backend/app/services/knowledge/rag_service.py) +- [backend/app/services/knowledge/chunker.py](file://backend/app/services/knowledge/chunker.py) +- [backend/app/services/knowledge/embedder.py](file://backend/app/services/knowledge/embedder.py) +- [backend/app/services/knowledge/retriever.py](file://backend/app/services/knowledge/retriever.py) - [backend/app/config.py](file://backend/app/config.py) - [backend/app/models/user.py](file://backend/app/models/user.py) - [backend/app/models/query.py](file://backend/app/models/query.py) - [backend/app/models/citation_record.py](file://backend/app/models/citation_record.py) - [backend/app/models/query_task.py](file://backend/app/models/query_task.py) - [backend/app/models/subscription.py](file://backend/app/models/subscription.py) +- [backend/app/models/agent.py](file://backend/app/models/agent.py) +- [backend/app/models/lifecycle.py](file://backend/app/models/lifecycle.py) +- [backend/app/models/knowledge.py](file://backend/app/models/knowledge.py) ## 更新摘要 **所做更改** -- 新增订阅管理API模块,包含套餐查询、订阅管理、历史记录等功能 -- 新增管理员API模块,包含系统统计、用户管理、权限控制等功能 -- 新增限流中间件,提供多层级请求限制保护 -- 新增PDF报告导出功能,扩展报告导出格式 -- 更新认证API,新增忘记密码、邮箱验证、密码修改等端点 -- 完善错误处理和状态码说明 -- 更新架构图以反映新增模块 +- 新增代理管理API模块,支持AI Agent的注册、配置管理、任务分发与监控 +- 新增分析监控API模块,提供内容发布追踪、效果指标管理、洞察生成与排行榜功能 +- 新增生命周期管理API模块,支持品牌项目全生命周期管理与阶段进度跟踪 +- 新增知识库API模块,提供知识库CRUD、文档管理、向量化检索与RAG服务 +- 更新架构图以反映新增的四个核心API模块 +- 完善错误处理和状态码说明,新增各模块特有的错误场景 ## 目录 1. [简介](#简介) @@ -50,10 +65,10 @@ 9. [结论](#结论) ## 简介 -本文件为GEO平台的完整API接口文档,涵盖认证、查询管理、引用数据、报告导出、订阅管理和管理员管理等核心功能模块。文档详细记录了所有RESTful API端点的HTTP方法、URL模式、请求参数与响应格式,并说明了JWT令牌管理、用户注册登录、权限验证机制、任务创建与执行、数据查询与统计分析、CSV和PDF格式报告导出流程,以及订阅管理和系统管理功能。 +本文件为GEO平台的完整API接口文档,涵盖认证、查询管理、引用数据、报告导出、订阅管理、管理员管理、代理管理、分析监控、生命周期管理和知识库等核心功能模块。文档详细记录了所有RESTful API端点的HTTP方法、URL模式、请求参数与响应格式,并说明了JWT令牌管理、用户注册登录、权限验证机制、任务创建与执行、数据查询与统计分析、CSV和PDF格式报告导出流程,以及订阅管理、系统管理、AI代理调度、内容分析追踪、项目生命周期管理和智能知识检索功能。 ## 项目结构 -后端采用FastAPI框架,按功能模块组织API路由:认证(/api/v1/auth)、查询词(/api/v1/queries)、引用数据(/api/v1/citations)、报告(/api/v1/reports)、订阅管理(/api/v1/subscriptions)、管理员(/api/v1/admin)。应用启动时初始化数据库模型并启动查询调度器,同时启用CORS允许前端localhost:3000访问,集成限流中间件和请求日志中间件。 +后端采用FastAPI框架,按功能模块组织API路由:认证(/api/v1/auth)、查询词(/api/v1/queries)、引用数据(/api/v1/citations)、报告(/api/v1/reports)、订阅管理(/api/v1/subscriptions)、管理员(/api/v1/admin)、代理管理(/api/v1/agents)、分析监控(/api/v1/analytics)、生命周期管理(/api/v1/lifecycle)、知识库(/api/v1/knowledge)。应用启动时初始化数据库模型并启动查询调度器,同时启用CORS允许前端localhost:3000访问,集成限流中间件和请求日志中间件。 ```mermaid graph TB @@ -63,22 +78,25 @@ A --> D["引用数据路由
backend/app/api/citations.py"] A --> E["报告路由
backend/app/api/reports.py"] A --> F["订阅管理路由
backend/app/api/subscriptions.py"] A --> G["管理员路由
backend/app/api/admin.py"] -A --> H["依赖注入与认证中间件
backend/app/api/deps.py"] -A --> I["限流中间件
backend/app/middleware/rate_limit.py"] -A --> J["配置中心
backend/app/config.py"] -A --> K["数据库模型
backend/app/models/*.py"] -A --> L["业务服务层
backend/app/services/*.py"] -A --> M["数据传输对象
backend/app/schemas/*.py"] +A --> H["代理管理路由
backend/app/api/agents.py"] +A --> I["分析监控路由
backend/app/api/analytics.py"] +A --> J["生命周期管理路由
backend/app/api/lifecycle.py"] +A --> K["知识库路由
backend/app/api/knowledge.py"] +A --> L["依赖注入与认证中间件
backend/app/api/deps.py"] +A --> M["限流中间件
backend/app/middleware/rate_limit.py"] +A --> N["配置中心
backend/app/config.py"] +A --> O["数据库模型
backend/app/models/*.py"] +A --> P["业务服务层
backend/app/services/*.py"] +A --> Q["数据传输对象
backend/app/schemas/*.py"] ``` **图表来源** - [backend/app/main.py:12-78](file://backend/app/main.py#L12-L78) - [backend/app/api/auth.py:30](file://backend/app/api/auth.py#L30) -- [backend/app/api/queries.py:12](file://backend/app/api/queries.py#L12) -- [backend/app/api/citations.py:21](file://backend/app/api/citations.py#L21) -- [backend/app/api/reports.py:15](file://backend/app/api/reports.py#L15) -- [backend/app/api/subscriptions.py:23](file://backend/app/api/subscriptions.py#L23) -- [backend/app/api/admin.py:17](file://backend/app/api/admin.py#L17) +- [backend/app/api/agents.py:29](file://backend/app/api/agents.py#L29) +- [backend/app/api/analytics.py:26](file://backend/app/api/analytics.py#L26) +- [backend/app/api/lifecycle.py:24](file://backend/app/api/lifecycle.py#L24) +- [backend/app/api/knowledge.py:38](file://backend/app/api/knowledge.py#L38) **章节来源** - [backend/app/main.py:1-84](file://backend/app/main.py#L1-L84) @@ -91,22 +109,29 @@ A --> M["数据传输对象
backend/app/schemas/*.py"] - 报告导出:支持CSV和PDF格式导出指定查询的引用记录。 - 订阅管理:提供套餐查询、订阅创建、取消订阅、历史记录查看等功能,支持多层级权限控制。 - 管理员管理:提供系统统计、用户管理、权限控制、计划更新等后台管理功能。 -- 数据模型与服务:用户、查询、引用记录、查询任务、订阅等模型及对应的服务逻辑。 +- 代理管理:支持AI Agent的注册、配置管理、任务分发与监控,提供任务创建、状态查询、日志查看和取消功能。 +- 分析监控:提供内容发布追踪、效果指标管理、洞察生成与排行榜功能,支持组织级别的数据分析。 +- 生命周期管理:支持品牌项目的全生命周期管理,包括项目快速启动、阶段进度跟踪、时间线事件和统计分析。 +- 知识库管理:提供知识库CRUD、文档管理、向量化检索与RAG服务,支持多种文档源和智能搜索。 +- 数据模型与服务:用户、查询、引用记录、查询任务、订阅、代理、分析、生命周期、知识库等模型及对应的服务逻辑。 **章节来源** - [backend/app/main.py:39-84](file://backend/app/main.py#L39-L84) - [backend/app/api/auth.py:33-115](file://backend/app/api/auth.py#L33-L115) -- [backend/app/api/subscriptions.py:26-77](file://backend/app/api/subscriptions.py#L26-L77) -- [backend/app/api/admin.py:29-108](file://backend/app/api/admin.py#L29-L108) +- [backend/app/api/agents.py:66-299](file://backend/app/api/agents.py#L66-L299) +- [backend/app/api/analytics.py:47-243](file://backend/app/api/analytics.py#L47-L243) +- [backend/app/api/lifecycle.py:85-297](file://backend/app/api/lifecycle.py#L85-L297) +- [backend/app/api/knowledge.py:81-502](file://backend/app/api/knowledge.py#L81-L502) - [backend/app/middleware/rate_limit.py:10-83](file://backend/app/middleware/rate_limit.py#L10-L83) ## 架构概览 -下图展示了客户端与后端各模块之间的交互关系,包括认证流程、查询管理、引用数据处理、报告导出、订阅管理和管理员管理。 +下图展示了客户端与后端各模块之间的交互关系,包括认证流程、查询管理、引用数据处理、报告导出、订阅管理、管理员管理、代理调度、分析监控、生命周期管理和知识库检索。 ```mermaid graph TB subgraph "客户端" FE["前端应用
localhost:3000"] +ENDUSER["终端用户"] end subgraph "后端服务" AUTH["认证模块
/api/v1/auth"] @@ -115,6 +140,10 @@ CITATIONS["引用数据模块
/api/v1/citations"] REPORTS["报告模块
/api/v1/reports"] SUBSCRIPTIONS["订阅管理模块
/api/v1/subscriptions"] ADMIN["管理员模块
/api/v1/admin"] +AGENTS["代理管理模块
/api/v1/agents"] +ANALYTICS["分析监控模块
/api/v1/analytics"] +LIFECYCLE["生命周期管理模块
/api/v1/lifecycle"] +KNOWLEDGE["知识库模块
/api/v1/knowledge"] DEPS["依赖注入与认证中间件"] RATELIMIT["限流中间件"] LOGGING["请求日志中间件"] @@ -128,30 +157,54 @@ FE --> CITATIONS FE --> REPORTS FE --> SUBSCRIPTIONS FE --> ADMIN +FE --> AGENTS +FE --> ANALYTICS +FE --> LIFECYCLE +FE --> KNOWLEDGE +ENDUSER --> AGENTS +ENDUSER --> ANALYTICS +ENDUSER --> LIFECYCLE +ENDUSER --> KNOWLEDGE AUTH --> DEPS QUERIES --> DEPS CITATIONS --> DEPS REPORTS --> DEPS SUBSCRIPTIONS --> DEPS ADMIN --> DEPS +AGENTS --> DEPS +ANALYTICS --> DEPS +LIFECYCLE --> DEPS +KNOWLEDGE --> DEPS AUTH --> RATELIMIT QUERIES --> RATELIMIT CITATIONS --> RATELIMIT REPORTS --> RATELIMIT SUBSCRIPTIONS --> RATELIMIT ADMIN --> RATELIMIT +AGENTS --> RATELIMIT +ANALYTICS --> RATELIMIT +LIFECYCLE --> RATELIMIT +KNOWLEDGE --> RATELIMIT AUTH --> LOGGING QUERIES --> LOGGING CITATIONS --> LOGGING REPORTS --> LOGGING SUBSCRIPTIONS --> LOGGING ADMIN --> LOGGING +AGENTS --> LOGGING +ANALYTICS --> LOGGING +LIFECYCLE --> LOGGING +KNOWLEDGE --> LOGGING AUTH --> SERVICES QUERIES --> SERVICES CITATIONS --> SERVICES REPORTS --> SERVICES SUBSCRIPTIONS --> SERVICES ADMIN --> SERVICES +AGENTS --> SERVICES +ANALYTICS --> SERVICES +LIFECYCLE --> SERVICES +KNOWLEDGE --> SERVICES SERVICES --> MODELS MODELS --> CONFIG ``` @@ -450,6 +503,208 @@ AdminAPI-->>Admin : 200 用户列表 - [backend/app/api/admin.py:29-108](file://backend/app/api/admin.py#L29-L108) - [backend/app/services/admin.py:14-188](file://backend/app/services/admin.py#L14-L188) +### 代理管理接口 +- 接口前缀:/api/v1/agents +- 路由与功能: + - GET /:列出所有Agent,支持按类型和状态筛选 + - GET /{agent_name}:获取Agent详情 + - GET /{agent_name}/config:获取Agent配置 + - PUT /{agent_name}/config:更新Agent配置 + - GET /tasks/:列出任务,支持按Agent、状态、类型筛选 + - POST /tasks/:创建任务(分发给Agent),支持优先级、回调URL、超时设置 + - GET /tasks/{task_id}:获取任务状态 + - POST /tasks/{task_id}/cancel:取消任务 + - GET /tasks/{task_id}/logs:获取任务日志 +- 权限与限制: + - 需要登录用户权限 + - 任务分发需要有效的Agent名称和配置 +- 请求参数与响应格式: + - Agent列表:items数组与total总数 + - Agent详情:包含名称、类型、状态、描述、版本、端点、能力等 + - 配置更新:返回更新的键列表和成功消息 + - 任务创建:返回任务ID、初始状态和成功消息 + - 任务状态:包含状态、错误消息、开始/完成时间等 + - 任务日志:包含日志级别、消息、元数据和时间戳 +- 错误处理: + - Agent不存在返回404 + - 任务不存在返回404 + - 任务分发错误返回400 + - 参数校验失败返回422 + +```mermaid +sequenceDiagram +participant Client as "客户端" +participant AgentsAPI as "代理管理API" +participant Dispatcher as "任务调度器" +participant Registry as "Agent注册表" +participant DB as "数据库" +Client->>AgentsAPI : POST /api/v1/agents/tasks/ +AgentsAPI->>Dispatcher : 创建任务消息 +Dispatcher->>Registry : 查找可用Agent +Registry-->>Dispatcher : Agent信息 +Dispatcher->>DB : 存储任务记录 +DB-->>Dispatcher : 任务ID +Dispatcher-->>AgentsAPI : 任务ID与状态 +AgentsAPI-->>Client : 201 任务信息 +``` + +**图表来源** +- [backend/app/api/agents.py:186-222](file://backend/app/api/agents.py#L186-L222) +- [backend/app/models/agent.py:98-155](file://backend/app/models/agent.py#L98-L155) + +**章节来源** +- [backend/app/api/agents.py:66-299](file://backend/app/api/agents.py#L66-L299) +- [backend/app/models/agent.py:12-206](file://backend/app/models/agent.py#L12-L206) + +### 分析监控接口 +- 接口前缀:/api/v1/analytics +- 路由与功能: + - POST /publish:记录内容发布,支持内容标题、ID、平台、URL、状态、发布时间 + - PUT /metrics/{publish_id}:更新内容效果指标(追加快照),支持浏览量、点赞数、评论数、分享数、书签数、AI引用数、搜索展示量、搜索点击量、平均阅读时长、阅读完成率 + - GET /overview:获取全局效果概览,包含发布总数、总浏览量、总互动数、总AI引用数、平均参与率、平台分布 + - GET /content/{publish_id}:获取单条内容详细表现 + - GET /top:获取表现最好内容排行,支持按浏览量、点赞数、评论数、分享数、AI引用数、阅读完成率排序 + - GET /insights:获取洞察列表,支持限制数量和类型筛选 + - POST /insights/generate:触发AI生成洞察建议 + - POST /insights/{insight_id}/apply:标记洞察已应用 +- 权限与限制: + - 需要用户关联组织权限 + - 发布记录必须属于当前组织 +- 请求参数与响应格式: + - 发布记录:包含组织ID、内容标题、内容ID、平台、URL、状态、发布时间、创建时间 + - 指标更新:返回更新后的指标快照 + - 全局概览:包含统计指标和平台分布 + - 内容表现:包含最新指标和历史指标列表 + - 洞察列表:包含洞察ID、类型、标题、描述、建议、严重程度、应用状态 +- 错误处理: + - 用户未关联组织返回403 + - 发布记录不存在或无权限返回404 + - 参数校验失败返回422 + +```mermaid +sequenceDiagram +participant Client as "客户端" +participant AnalyticsAPI as "分析监控API" +participant Tracker as "分析追踪器" +participant Generator as "洞察生成器" +participant DB as "数据库" +Client->>AnalyticsAPI : POST /api/v1/analytics/publish +AnalyticsAPI->>Tracker : 记录发布 +Tracker->>DB : 存储发布记录 +DB-->>Tracker : 发布ID +Tracker-->>AnalyticsAPI : 发布记录 +AnalyticsAPI-->>Client : 201 发布记录 +Client->>AnalyticsAPI : POST /api/v1/analytics/insights/generate +AnalyticsAPI->>Generator : 生成洞察 +Generator->>DB : 查询数据分析 +DB-->>Generator : 分析结果 +Generator-->>AnalyticsAPI : 洞察建议 +AnalyticsAPI-->>Client : 洞察列表 +``` + +**图表来源** +- [backend/app/api/analytics.py:47-60](file://backend/app/api/analytics.py#L47-L60) +- [backend/app/api/analytics.py:206-212](file://backend/app/api/analytics.py#L206-L212) + +**章节来源** +- [backend/app/api/analytics.py:47-243](file://backend/app/api/analytics.py#L47-L243) +- [backend/app/schemas/analytics.py:14-145](file://backend/app/schemas/analytics.py#L14-L145) +- [backend/app/services/analytics/insights.py](file://backend/app/services/analytics/insights.py) +- [backend/app/services/analytics/tracker.py](file://backend/app/services/analytics/tracker.py) + +### 生命周期管理接口 +- 接口前缀:/api/v1/lifecycle +- 路由与功能: + - GET /projects/stats:获取项目统计信息,包含项目总数、活跃项目数、阶段分布、完成率 + - GET /projects/{project_id}/timeline:获取项目时间线事件,包含创建事件和各阶段开始/完成事件 + - POST /projects/quick-start:项目快速启动,创建品牌基建阶段的项目 + - GET /projects/{project_id}/stages:获取项目阶段列表 + - PUT /projects/{project_id}/stages/{stage_number}:更新项目阶段状态,支持开始时间、完成时间、备注、指标 +- 权限与限制: + - 需要用户关联组织权限 + - 项目必须属于当前组织 +- 请求参数与响应格式: + - 项目统计:包含总数、活跃数、阶段分布、完成率 + - 时间线事件:包含事件类型、描述、时间戳、阶段编号 + - 项目创建:返回创建的项目和成功消息 + - 阶段更新:返回更新后的阶段详情 +- 错误处理: + - 用户未关联组织返回404 + - 项目不存在返回404 + - 阶段不存在返回404 + +```mermaid +sequenceDiagram +participant Client as "客户端" +participant LifecycleAPI as "生命周期API" +participant DB as "数据库" +Client->>LifecycleAPI : POST /api/v1/lifecycle/projects/quick-start +LifecycleAPI->>DB : 创建组织如不存在 +DB-->>LifecycleAPI : 组织ID +LifecycleAPI->>DB : 创建项目 +DB-->>LifecycleAPI : 项目ID +LifecycleAPI->>DB : 创建5个阶段 +DB-->>LifecycleAPI : 阶段列表 +LifecycleAPI-->>Client : 201 项目详情 +``` + +**图表来源** +- [backend/app/api/lifecycle.py:190-230](file://backend/app/api/lifecycle.py#L190-L230) + +**章节来源** +- [backend/app/api/lifecycle.py:85-297](file://backend/app/api/lifecycle.py#L85-L297) +- [backend/app/schemas/lifecycle.py:9-68](file://backend/app/schemas/lifecycle.py#L9-L68) +- [backend/app/models/lifecycle.py:12-92](file://backend/app/models/lifecycle.py#L12-L92) + +### 知识库接口 +- 接口前缀:/api/v1/knowledge +- 路由与功能: + - POST /bases:创建知识库,支持名称、类型、描述 + - GET /bases:列出知识库,支持按类型筛选 + - GET /bases/{kb_id}:获取知识库详情 + - DELETE /bases/{kb_id}:删除知识库(级联删除文档和块) + - POST /bases/{kb_id}/documents:上传文档,支持文本、URL、Markdown源 + - GET /bases/{kb_id}/documents:列出文档 + - DELETE /bases/{kb_id}/documents/{doc_id}:删除文档(级联删除块) + - GET /bases/{kb_id}/documents/{doc_id}/chunks:预览文档块 + - POST /search:知识库搜索,支持查询、知识库ID列表、返回数量 +- 权限与限制: + - 需要用户关联组织权限 + - 文档上传需要有效的知识库ID +- 请求参数与响应格式: + - 知识库创建:返回知识库ID、名称、类型、描述、文档数量、状态、创建时间 + - 文档上传:返回文档ID、标题、源类型、URL、块数量、状态、错误消息、创建时间 + - 搜索结果:包含块ID、内容、分数、文档ID、标题、元数据 +- 错误处理: + - 用户未关联组织返回400 + - 知识库不存在返回404 + - 文档不存在返回404 + - URL内容获取失败返回400 + +```mermaid +sequenceDiagram +participant Client as "客户端" +participant KnowledgeAPI as "知识库API" +participant RAGService as "RAG服务" +participant DB as "数据库" +Client->>KnowledgeAPI : POST /api/v1/knowledge/search +KnowledgeAPI->>RAGService : 执行向量搜索 +RAGService->>DB : 查询相似文档 +DB-->>RAGService : 匹配结果 +RAGService-->>KnowledgeAPI : 搜索结果 +KnowledgeAPI->>DB : 记录搜索日志 +DB-->>KnowledgeAPI : 日志ID +KnowledgeAPI-->>Client : 200 搜索结果 +``` + +**图表来源** +- [backend/app/api/knowledge.py:424-501](file://backend/app/api/knowledge.py#L424-L501) + +**章节来源** +- [backend/app/api/knowledge.py:81-502](file://backend/app/api/knowledge.py#L81-L502) +- [backend/app/schemas/knowledge.py:9-77](file://backend/app/schemas/knowledge.py#L9-L77) +- [backend/app/models/knowledge.py:22-213](file://backend/app/models/knowledge.py#L22-L213) + ### 限流中间件 - 功能特性: - 基于内存的简易限流中间件,无需Redis依赖 @@ -503,12 +758,19 @@ PassThrough --> Next - User与Subscription一对多,级联删除 - Query与CitationRecord、QueryTask一对多,级联删除 - CitationRecord外键关联Query + - AgentRegistry与AgentConfig、AgentTask、AgentTaskLog一对多,级联删除 + - LifecycleProject与ProjectStage一对多,级联删除 + - KnowledgeBase与KnowledgeDocument、KnowledgeChunk一对多,级联删除 - 服务层职责: - 认证服务:密码哈希、JWT签发与校验、用户注册与登录、密码重置、邮箱验证 - 查询服务:分页查询、创建/更新/删除、频率与下次查询时间计算 - 引用服务:引用记录查询、统计分析、立即执行任务、CSV和PDF导出 - 订阅服务:套餐管理、订阅创建与取消、历史记录查询 - 管理员服务:系统统计、用户管理、权限控制、计划更新 + - 代理服务:Agent注册表管理、任务调度、配置管理、日志记录 + - 分析服务:发布追踪、指标管理、洞察生成、排行榜计算 + - 生命周期服务:项目管理、阶段跟踪、统计分析 + - 知识库服务:文档管理、向量化处理、RAG检索、搜索日志 ```mermaid classDiagram @@ -554,13 +816,19 @@ class CitationRecord { } class QueryTask { +UUID id -+UUID query_id -+string platform ++UUID agent_id ++string task_type +string status ++int priority ++dict input_data ++dict output_data +string error_message ++UUID organization_id ++UUID project_id +datetime scheduled_at +datetime started_at +datetime completed_at ++datetime created_at } class Subscription { +UUID id @@ -573,12 +841,106 @@ class Subscription { +string payment_method +datetime created_at } +class AgentRegistry { ++UUID id ++string name ++string display_name ++string agent_type ++string description ++string version ++string endpoint ++string status ++dict capabilities ++datetime last_heartbeat ++datetime created_at ++datetime updated_at +} +class AgentTask { ++UUID id ++UUID agent_id ++string task_type ++string status ++int priority ++dict input_data ++dict output_data ++string error_message ++UUID organization_id ++UUID project_id ++datetime scheduled_at ++datetime started_at ++datetime completed_at ++datetime created_at +} +class LifecycleProject { ++UUID id ++UUID organization_id ++string brand_name ++list brand_aliases ++int current_stage ++string status ++UUID created_by ++datetime created_at ++datetime updated_at +} +class ProjectStage { ++UUID id ++UUID project_id ++int stage_number ++string status ++datetime started_at ++datetime completed_at ++string notes ++dict metrics +} +class KnowledgeBase { ++UUID id ++UUID organization_id ++string name ++string type ++string description ++int document_count ++string status ++UUID created_by ++datetime created_at ++datetime updated_at +} +class KnowledgeDocument { ++UUID id ++UUID knowledge_base_id ++string title ++string source_type ++string source_url ++string content ++string content_hash ++int chunk_count ++string status ++string error_message ++dict extra_metadata ++datetime created_at ++datetime updated_at +} +class KnowledgeChunk { ++UUID id ++UUID document_id ++string content ++Vector embedding ++int chunk_index ++int token_count ++dict extra_metadata ++datetime created_at +} User "1" --> "many" Query : "拥有" User "1" --> "many" Subscription : "订阅" +User "1" --> "many" AgentTask : "创建" Query "1" --> "many" CitationRecord : "产生" Query "1" --> "many" QueryTask : "触发任务" CitationRecord "many" --> "1" Query : "属于" Subscription "many" --> "1" User : "属于" +AgentRegistry "1" --> "many" AgentTask : "执行" +AgentTask "many" --> "1" AgentRegistry : "属于" +LifecycleProject "1" --> "many" ProjectStage : "包含" +KnowledgeBase "1" --> "many" KnowledgeDocument : "包含" +KnowledgeDocument "1" --> "many" KnowledgeChunk : "包含" ``` **图表来源** @@ -587,6 +949,9 @@ Subscription "many" --> "1" User : "属于" - [backend/app/models/citation_record.py:11-42](file://backend/app/models/citation_record.py#L11-L42) - [backend/app/models/query_task.py:11-39](file://backend/app/models/query_task.py#L11-L39) - [backend/app/models/subscription.py:11-37](file://backend/app/models/subscription.py#L11-L37) +- [backend/app/models/agent.py:12-206](file://backend/app/models/agent.py#L12-L206) +- [backend/app/models/lifecycle.py:12-92](file://backend/app/models/lifecycle.py#L12-L92) +- [backend/app/models/knowledge.py:22-213](file://backend/app/models/knowledge.py#L22-L213) **章节来源** - [backend/app/api/deps.py:16-42](file://backend/app/api/deps.py#L16-L42) @@ -603,6 +968,9 @@ Subscription "many" --> "1" User : "属于" - 批量操作:任务创建采用批量插入,减少事务开销。 - 限流保护:多层级限流中间件防止恶意请求和滥用,保护系统稳定性。 - PDF生成:PDF导出使用FPDF库,支持中文字体加载,提供完整的品牌曝光度分析报告。 +- 向量检索:知识库模块使用pgvector扩展进行高效相似性搜索,支持大规模文档向量化处理。 +- 代理调度:Agent任务采用Redis队列进行异步处理,支持高并发任务分发与监控。 +- 分析追踪:分析模块使用专门的追踪器和洞察生成器,优化大数据量的统计分析性能。 ## 故障排除指南 - 认证相关 @@ -625,6 +993,24 @@ Subscription "many" --> "1" User : "属于" - 管理员功能 - 403 非管理员权限:确认当前用户具有管理员权限(is_admin=true)。 - 404 用户不存在:确认用户ID是否有效。 +- 代理管理 + - 404 Agent不存在:确认Agent名称是否正确。 + - 404 任务不存在:确认任务ID格式和权限。 + - 400 任务分发错误:检查Agent配置和可用性。 + - 422 参数校验失败:检查请求体格式和字段约束。 +- 分析监控 + - 403 用户未关联组织:确认用户已加入有效组织。 + - 404 发布记录不存在或无权限:检查发布ID和组织权限。 + - 422 指标更新失败:检查数值范围和字段类型。 +- 生命周期管理 + - 404 用户未关联组织:确认用户已创建或加入组织。 + - 404 项目不存在:检查项目ID和组织归属。 + - 404 阶段不存在:检查阶段编号和项目归属。 +- 知识库管理 + - 400 用户未关联组织:确认用户已加入组织。 + - 404 知识库不存在:检查知识库ID和组织权限。 + - 404 文档不存在:检查文档ID和知识库归属。 + - 400 URL内容获取失败:检查URL可访问性和内容格式。 - 限流保护 - 429 请求过于频繁:检查是否超过限流阈值,等待冷却时间后重试。 - 429 查询执行过于频繁:确认查询执行频率是否超过每小时10次限制。 @@ -636,7 +1022,11 @@ Subscription "many" --> "1" User : "属于" - [backend/app/api/reports.py:25-29](file://backend/app/api/reports.py#L25-L29) - [backend/app/api/subscriptions.py:53-57](file://backend/app/api/subscriptions.py#L53-L57) - [backend/app/api/admin.py:22-25](file://backend/app/api/admin.py#L22-L25) +- [backend/app/api/agents.py:84-88](file://backend/app/api/agents.py#L84-L88) +- [backend/app/api/analytics.py:36-40](file://backend/app/api/analytics.py#L36-L40) +- [backend/app/api/lifecycle.py:146](file://backend/app/api/lifecycle.py#L146) +- [backend/app/api/knowledge.py:92-96](file://backend/app/api/knowledge.py#L92-L96) - [backend/app/middleware/rate_limit.py:47-49](file://backend/app/middleware/rate_limit.py#L47-L49) ## 结论 -GEO平台API采用清晰的模块化设计,围绕用户、查询、引用、报告、订阅与管理六大领域构建RESTful接口。通过JWT认证与严格的资源所有权校验,保障了数据安全;通过统计分析与CSV/PDF导出,满足了业务洞察与合规需求;通过订阅管理和管理员功能,提供了完整的商业运营支持;通过多层级限流中间件,确保了系统的稳定性和安全性。建议在生产环境中进一步完善错误日志、监控指标与缓存策略,持续优化查询性能与用户体验。 \ No newline at end of file +GEO平台API采用清晰的模块化设计,围绕用户、查询、引用、报告、订阅、管理、代理、分析、生命周期和知识库十大领域构建RESTful接口。通过JWT认证与严格的资源所有权校验,保障了数据安全;通过统计分析与CSV/PDF导出,满足了业务洞察与合规需求;通过订阅管理、管理员功能、AI代理调度、内容分析追踪、项目生命周期管理和智能知识检索,提供了完整的商业运营支持;通过多层级限流中间件,确保了系统的稳定性和安全性。新增的四个核心API模块显著增强了平台的智能化水平,包括AI代理的自动化任务处理能力、深度的内容分析与优化建议、完整的项目生命周期管理以及强大的智能知识检索功能。建议在生产环境中进一步完善错误日志、监控指标与缓存策略,持续优化查询性能与用户体验。 \ No newline at end of file diff --git a/.qoder/repowiki/zh/content/前端系统架构/前端系统架构.md b/.qoder/repowiki/zh/content/前端系统架构/前端系统架构.md index 668136e..14fc302 100644 --- a/.qoder/repowiki/zh/content/前端系统架构/前端系统架构.md +++ b/.qoder/repowiki/zh/content/前端系统架构/前端系统架构.md @@ -25,16 +25,24 @@ - [components/layout/sidebar.tsx](file://frontend/components/layout/sidebar.tsx) - [components/ui/tabs.tsx](file://frontend/components/ui/tabs.tsx) - [app/api/auth/[...nextauth]/route.ts](file://frontend/app/api/auth/[...nextauth]/route.ts) +- [playwright.config.ts](file://frontend/playwright.config.ts) +- [e2e/tests/dashboard-health.spec.ts](file://frontend/e2e/tests/dashboard-health.spec.ts) +- [e2e/tests/login.spec.ts](file://frontend/e2e/tests/login.spec.ts) +- [e2e/pages/dashboard.page.ts](file://frontend/e2e/pages/dashboard.page.ts) +- [e2e/pages/login.page.ts](file://frontend/e2e/pages/login.page.ts) +- [components/business/index.ts](file://frontend/components/business/index.ts) +- [components/business/agent-status-card.tsx](file://frontend/components/business/agent-status-card.tsx) +- [components/business/alert-card.tsx](file://frontend/components/business/alert-card.tsx) +- [components/dashboard/index.ts](file://frontend/components/dashboard/index.ts) ## 更新摘要 **所做变更** -- 新增认证页面体系:忘记密码、重置密码、邮箱验证、注册页面 -- 新增管理员仪表板页面,支持用户管理和系统统计 -- 新增设置页面重构,采用标签页布局管理个人资料、密码修改和订阅管理 -- 新增API客户端增强,支持完整认证端点(注册、忘记密码、重置密码、邮箱验证、密码修改、个人资料更新) -- 新增认证状态管理,支持管理员权限和会话状态扩展 -- 更新组件结构,新增Tabs组件和增强的侧边栏导航 +- 新增E2E测试框架:引入Playwright测试套件,包含登录页面测试、健康状态Dashboard测试、响应式设计测试 +- 新增业务组件库:扩展GEO特定业务组件,包括Agent状态卡片、告警卡片、指标卡片等 +- 新增仪表板布局重构:改进侧边导航结构,支持固定侧边栏和头部导航 +- 新增测试脚本:添加E2E测试命令,支持多浏览器测试和并行执行 +- 新增业务组件索引:提供统一的业务组件导出接口 ## 目录 1. [引言](#引言) @@ -42,15 +50,19 @@ 3. [核心组件](#核心组件) 4. [架构总览](#架构总览) 5. [详细组件分析](#详细组件分析) -6. [依赖分析](#依赖分析) -7. [性能考虑](#性能考虑) -8. [故障排除指南](#故障排除指南) -9. [结论](#结论) -10. [附录](#附录) +6. [E2E测试框架](#e2e测试框架) +7. [业务组件库](#业务组件库) +8. [依赖分析](#依赖分析) +9. [性能考虑](#性能考虑) +10. [故障排除指南](#故障排除指南) +11. [结论](#结论) +12. [附录](#附录) ## 引言 本文件为 GEO 前端系统的架构文档,聚焦于基于 Next.js 14 的应用架构设计,涵盖 App Router 页面组织、服务器组件与客户端组件的混合使用模式;认证系统(NextAuth.js 集成、会话管理与路由保护);UI 组件库设计理念与复用策略;数据获取与状态管理;错误处理机制;以及响应式设计、可访问性与性能优化等最佳实践。 +**更新** 新增E2E测试框架集成、业务组件库扩展、仪表板布局重构等前端架构变化。 + ## 项目结构 前端采用 Next.js 14 App Router 结构,页面按功能域分组(通过路由组 `(auth)` 和 `(dashboard)` 实现),根布局统一注入全局样式与 Provider,认证相关 API 路由集中于 `/api/auth/[...nextauth]`。系统现已扩展为完整的认证体系,包含登录、注册、忘记密码、重置密码、邮箱验证等页面,以及管理员仪表板和设置页面。 @@ -72,13 +84,19 @@ A --> O["tailwind.config.ts
Tailwind 配置"] A --> P["next.config.mjs
Next 配置"] Q["components/layout/sidebar.tsx
侧边栏导航"] --> D R["components/ui/tabs.tsx
标签页组件"] --> M +S["e2e/ 目录
E2E测试框架"] --> T["playwright.config.ts
测试配置"] +S --> U["e2e/tests/ 目录
测试用例"] +S --> V["e2e/pages/ 目录
页面对象"] +W["components/business/ 目录
业务组件库"] --> X["agent-status-card.tsx
代理状态卡片"] +W --> Y["alert-card.tsx
告警卡片"] +W --> Z["metric-card.tsx
指标卡片"] ``` **图表来源** - [app/layout.tsx:1-37](file://frontend/app/layout.tsx#L1-L37) - [components/providers.tsx:1-9](file://frontend/components/providers.tsx#L1-L9) - [app/(auth)/layout.tsx](file://frontend/app/(auth)/layout.tsx#L1-L12) -- [app/(dashboard)/layout.tsx](file://frontend/app/(dashboard)/layout.tsx#L1-L27) +- [app/(dashboard)/layout.tsx:1-146](file://frontend/app/(dashboard)/layout.tsx#L1-L146) - [app/(auth)/login/page.tsx](file://frontend/app/(auth)/login/page.tsx#L1-L93) - [app/(auth)/register/page.tsx](file://frontend/app/(auth)/register/page.tsx#L1-L128) - [app/(auth)/forgot-password/page.tsx](file://frontend/app/(auth)/forgot-password/page.tsx#L1-L101) @@ -90,22 +108,24 @@ R["components/ui/tabs.tsx
标签页组件"] --> M - [components/layout/sidebar.tsx:1-63](file://frontend/components/layout/sidebar.tsx#L1-L63) - [components/ui/tabs.tsx:1-56](file://frontend/components/ui/tabs.tsx#L1-L56) - [app/api/auth/[...nextauth]/route.ts](file://frontend/app/api/auth/[...nextauth]/route.ts#L1-L7) -- [tailwind.config.ts:1-57](file://frontend/tailwind.config.ts#L1-L57) +- [tailwind.config.ts:1-121](file://frontend/tailwind.config.ts#L1-L121) - [next.config.mjs:1-5](file://frontend/next.config.mjs#L1-L5) +- [playwright.config.ts:1-39](file://frontend/playwright.config.ts#L1-L39) +- [components/business/index.ts:1-29](file://frontend/components/business/index.ts#L1-L29) **章节来源** - [app/layout.tsx:1-37](file://frontend/app/layout.tsx#L1-L37) - [components/providers.tsx:1-9](file://frontend/components/providers.tsx#L1-L9) - [app/(auth)/layout.tsx](file://frontend/app/(auth)/layout.tsx#L1-L12) -- [app/(dashboard)/layout.tsx](file://frontend/app/(dashboard)/layout.tsx#L1-L27) -- [tailwind.config.ts:1-57](file://frontend/tailwind.config.ts#L1-L57) +- [app/(dashboard)/layout.tsx:1-146](file://frontend/app/(dashboard)/layout.tsx#L1-L146) +- [tailwind.config.ts:1-121](file://frontend/tailwind.config.ts#L1-L121) - [next.config.mjs:1-5](file://frontend/next.config.mjs#L1-L5) ## 核心组件 - 根布局与全局样式:定义站点元数据、字体变量与全局样式入口,并包裹应用上下文 Provider。 - 会话提供者:在客户端注入 SessionProvider,使整个应用可访问 NextAuth 会话状态。 - 认证路由组:提供登录/注册/忘记密码/重置密码/邮箱验证等认证页面的统一容器样式。 -- 仪表盘路由组:提供侧边栏与头部导航,同时在服务器端校验会话,未登录则重定向至登录页。 +- 仪表盘路由组:提供侧边栏与头部导航,支持固定布局和活动状态跟踪,未登录则重定向至登录页。 - 认证配置:NextAuth 选项,使用凭据提供者对接后端认证接口,JWT 会话策略,回调处理 token 与 session 映射,支持管理员权限。 - 类型扩展:为 NextAuth 的 Session 与 JWT 扩展自定义字段,确保类型安全,包含管理员标识。 - API 客户端:封装带鉴权头的通用请求方法,统一错误处理与响应解析,支持完整认证端点。 @@ -117,7 +137,7 @@ R["components/ui/tabs.tsx
标签页组件"] --> M - [app/layout.tsx:1-37](file://frontend/app/layout.tsx#L1-L37) - [components/providers.tsx:1-9](file://frontend/components/providers.tsx#L1-L9) - [app/(auth)/layout.tsx](file://frontend/app/(auth)/layout.tsx#L1-L12) -- [app/(dashboard)/layout.tsx](file://frontend/app/(dashboard)/layout.tsx#L1-L27) +- [app/(dashboard)/layout.tsx:1-146](file://frontend/app/(dashboard)/layout.tsx#L1-L146) - [lib/auth.ts:1-73](file://frontend/lib/auth.ts#L1-L73) - [types/next-auth.d.ts:1-29](file://frontend/types/next-auth.d.ts#L1-L29) - [lib/api.ts:1-154](file://frontend/lib/api.ts#L1-L154) @@ -151,6 +171,8 @@ AH["NextAuth 路由
app/api/auth/[...nextauth]/route.ts"] UI["UI 组件库
components/ui/*"] LH["头部组件
components/layout/header.tsx"] LS["侧边栏组件
components/layout/sidebar.tsx"] +BC["业务组件库
components/business/*"] +DP["Dashboard组件
components/dashboard/*"] end subgraph "认证服务" NA["NextAuth 服务
lib/auth.ts"] @@ -159,6 +181,13 @@ subgraph "后端 API" API["业务 API 客户端
lib/api.ts"] BE["后端服务
backend/app/*"] end +subgraph "E2E测试框架" +PW["Playwright
playwright.config.ts"] +DS["Dashboard测试
e2e/tests/dashboard-health.spec.ts"] +LSpec["登录测试
e2e/tests/login.spec.ts"] +DPg["Dashboard页面
e2e/pages/dashboard.page.ts"] +LPg["Login页面
e2e/pages/login.page.ts"] +end U --> RL RL --> PR PR --> AL @@ -181,13 +210,17 @@ ADMIN --> API SETTINGS --> API NA --> BE API --> BE +PW --> DS +PW --> LSpec +DS --> DPg +LSpec --> LPg ``` **图表来源** - [app/layout.tsx:1-37](file://frontend/app/layout.tsx#L1-L37) - [components/providers.tsx:1-9](file://frontend/components/providers.tsx#L1-L9) - [app/(auth)/layout.tsx](file://frontend/app/(auth)/layout.tsx#L1-L12) -- [app/(dashboard)/layout.tsx](file://frontend/app/(dashboard)/layout.tsx#L1-L27) +- [app/(dashboard)/layout.tsx:1-146](file://frontend/app/(dashboard)/layout.tsx#L1-L146) - [app/(auth)/login/page.tsx](file://frontend/app/(auth)/login/page.tsx#L1-L93) - [app/(auth)/register/page.tsx](file://frontend/app/(auth)/register/page.tsx#L1-L128) - [app/(auth)/forgot-password/page.tsx](file://frontend/app/(auth)/forgot-password/page.tsx#L1-L101) @@ -201,6 +234,9 @@ API --> BE - [app/api/auth/[...nextauth]/route.ts](file://frontend/app/api/auth/[...nextauth]/route.ts#L1-L7) - [lib/auth.ts:1-73](file://frontend/lib/auth.ts#L1-L73) - [lib/api.ts:1-154](file://frontend/lib/api.ts#L1-L154) +- [playwright.config.ts:1-39](file://frontend/playwright.config.ts#L1-L39) +- [e2e/tests/dashboard-health.spec.ts:1-264](file://frontend/e2e/tests/dashboard-health.spec.ts#L1-L264) +- [e2e/tests/login.spec.ts:1-126](file://frontend/e2e/tests/login.spec.ts#L1-L126) ## 详细组件分析 @@ -208,7 +244,7 @@ API --> BE - 凭据提供者:使用邮箱/密码进行认证,调用后端登录接口,成功后返回包含用户信息与访问令牌的对象,支持管理员权限标识。 - JWT 会话策略:在回调中将访问令牌与用户 ID 写入 JWT,并在 session 回调中回填到 session 对象,包含 is_admin 字段。 - 完整认证流程:支持注册、登录、忘记密码、重置密码、邮箱验证、密码修改、个人资料更新等完整认证生命周期。 -- 路由保护:仪表盘布局在服务器端通过 getServerSession 获取会话,若无会话则重定向至登录页。 +- 路由保护:仪表盘布局在客户端通过 useSession 获取会话状态,若无会话则重定向至登录页。 - NextAuth 路由:统一暴露 GET/POST,交由 NextAuth 处理认证生命周期。 ```mermaid @@ -260,7 +296,7 @@ LOGIN-->>C : "跳转到 /dashboard 或显示错误" - [app/(auth)/forgot-password/page.tsx](file://frontend/app/(auth)/forgot-password/page.tsx#L1-L101) - [app/(auth)/reset-password/page.tsx](file://frontend/app/(auth)/reset-password/page.tsx#L1-L148) - [app/(auth)/verify-email/page.tsx](file://frontend/app/(auth)/verify-email/page.tsx#L1-L155) -- [app/(dashboard)/layout.tsx](file://frontend/app/(dashboard)/layout.tsx#L1-L27) +- [app/(dashboard)/layout.tsx:1-146](file://frontend/app/(dashboard)/layout.tsx#L1-L146) ### 管理员仪表板系统 - 用户管理:支持用户列表查看、搜索、分页,提供启用/禁用用户和修改套餐功能。 @@ -417,15 +453,15 @@ Tabs --> UIComponents : "标签页导航" **图表来源** - [components/ui/button.tsx:1-57](file://frontend/components/ui/button.tsx#L1-L57) - [components/ui/tabs.tsx:1-56](file://frontend/components/ui/tabs.tsx#L1-L56) -- [tailwind.config.ts:1-57](file://frontend/tailwind.config.ts#L1-L57) +- [tailwind.config.ts:1-121](file://frontend/tailwind.config.ts#L1-L121) **章节来源** - [components/ui/button.tsx:1-57](file://frontend/components/ui/button.tsx#L1-L57) - [components/ui/tabs.tsx:1-56](file://frontend/components/ui/tabs.tsx#L1-L56) -- [tailwind.config.ts:1-57](file://frontend/tailwind.config.ts#L1-L57) +- [tailwind.config.ts:1-121](file://frontend/tailwind.config.ts#L1-L121) ### 服务器组件与客户端组件的混合使用 -- 服务器组件:仪表盘布局在服务器端通过 getServerSession 校验会话并进行重定向,避免客户端渲染无意义内容。 +- 服务器组件:仪表盘布局在客户端通过 useSession 校验会话并进行重定向,避免客户端渲染无意义内容。 - 客户端组件:登录页、注册页、忘记密码页、重置密码页、邮箱验证页、仪表盘页、管理员仪表板、设置页均标记为客户端组件,以便使用 hooks(如 useSession、useRouter)与交互逻辑。 - Provider 注入:根布局注入 Providers,使子树中的客户端组件可共享会话状态。 - 权限路由:侧边栏根据用户权限动态渲染,管理员用户显示额外的管理后台入口。 @@ -444,13 +480,13 @@ C->>C : "根据权限渲染侧边栏" ``` **图表来源** -- [app/(dashboard)/layout.tsx](file://frontend/app/(dashboard)/layout.tsx#L1-L27) +- [app/(dashboard)/layout.tsx:1-146](file://frontend/app/(dashboard)/layout.tsx#L1-L146) - [app/(dashboard)/dashboard/page.tsx](file://frontend/app/(dashboard)/dashboard/page.tsx#L1-L227) - [components/providers.tsx:1-9](file://frontend/components/providers.tsx#L1-L9) - [components/layout/sidebar.tsx:1-63](file://frontend/components/layout/sidebar.tsx#L1-L63) **章节来源** -- [app/(dashboard)/layout.tsx](file://frontend/app/(dashboard)/layout.tsx#L1-L27) +- [app/(dashboard)/layout.tsx:1-146](file://frontend/app/(dashboard)/layout.tsx#L1-L146) - [app/(dashboard)/dashboard/page.tsx](file://frontend/app/(dashboard)/dashboard/page.tsx#L1-L227) - [components/providers.tsx:1-9](file://frontend/components/providers.tsx#L1-L9) - [components/layout/sidebar.tsx:1-63](file://frontend/components/layout/sidebar.tsx#L1-L63) @@ -458,7 +494,7 @@ C->>C : "根据权限渲染侧边栏" ### 错误处理机制 - API 层:fetchWithAuth 在非 2xx 时解析错误消息并抛出异常,401 状态自动重定向到登录页,保证上层统一处理。 - 页面层:各认证页面在认证失败时显示错误提示,管理员仪表板和设置页面提供详细的错误反馈和重试机制。 -- 路由保护:服务器端无会话时直接重定向,避免进入受保护页面。 +- 路由保护:客户端无会话时直接重定向,避免进入受保护页面。 - 表单验证:设置页面各表单包含客户端验证,提供即时反馈。 **章节来源** @@ -470,7 +506,148 @@ C->>C : "根据权限渲染侧边栏" - [app/(auth)/verify-email/page.tsx](file://frontend/app/(auth)/verify-email/page.tsx#L1-L155) - [app/(dashboard)/dashboard/admin/page.tsx](file://frontend/app/(dashboard)/dashboard/admin/page.tsx#L1-L435) - [app/(dashboard)/dashboard/settings/page.tsx](file://frontend/app/(dashboard)/dashboard/settings/page.tsx#L1-L445) -- [app/(dashboard)/layout.tsx](file://frontend/app/(dashboard)/layout.tsx#L1-L27) +- [app/(dashboard)/layout.tsx:1-146](file://frontend/app/(dashboard)/layout.tsx#L1-L146) + +## E2E测试框架 + +### Playwright测试配置 +系统集成了完整的E2E测试框架,基于Playwright提供跨浏览器测试能力: + +- **测试环境配置**:支持Chrome、Firefox、Safari三种浏览器并行测试 +- **测试执行策略**:串行执行,失败重试2次,截图仅在失败时捕获 +- **测试报告**:生成HTML格式的详细测试报告 +- **自动化启动**:测试服务器自动启动,支持热重载 + +```mermaid +flowchart TD +Start(["开始E2E测试"]) --> Config["加载Playwright配置"] +Config --> Browser["启动浏览器实例"] +Browser --> Server["启动本地开发服务器"] +Server --> Tests["执行测试用例"] +Tests --> Report["生成测试报告"] +Report --> End(["测试完成"]) +subgraph "测试用例" +Test1["登录页面测试"] +Test2["Dashboard健康状态测试"] +Test3["响应式设计测试"] +Test4["行动建议测试"] +end +subgraph "页面对象" +Page1["LoginPage对象"] +Page2["DashboardPage对象"] +end +``` + +**图表来源** +- [playwright.config.ts:1-39](file://frontend/playwright.config.ts#L1-L39) +- [e2e/tests/login.spec.ts:1-126](file://frontend/e2e/tests/login.spec.ts#L1-L126) +- [e2e/tests/dashboard-health.spec.ts:1-264](file://frontend/e2e/tests/dashboard-health.spec.ts#L1-L264) + +### 测试用例覆盖范围 +- **登录页面测试**:验证页面重定向、表单元素、HTML5验证、错误处理、链接功能 +- **Dashboard健康状态测试**:验证页面标题、概览卡片、平台评分、行动建议、骨架屏 +- **响应式设计测试**:验证移动端和桌面端的不同布局表现 +- **颜色传达状态测试**:验证不同健康状态的颜色编码 + +### 页面对象模式 +采用Page Object模式封装测试逻辑: + +- **LoginPage**:封装登录表单的所有交互操作 +- **DashboardPage**:封装Dashboard页面的元素定位和数据提取 + +**章节来源** +- [playwright.config.ts:1-39](file://frontend/playwright.config.ts#L1-L39) +- [e2e/tests/login.spec.ts:1-126](file://frontend/e2e/tests/login.spec.ts#L1-L126) +- [e2e/tests/dashboard-health.spec.ts:1-264](file://frontend/e2e/tests/dashboard-health.spec.ts#L1-L264) +- [e2e/pages/login.page.ts:1-36](file://frontend/e2e/pages/login.page.ts#L1-L36) +- [e2e/pages/dashboard.page.ts:1-74](file://frontend/e2e/pages/dashboard.page.ts#L1-L74) + +## 业务组件库 + +### 组件库架构 +GEO业务组件库专注于企业级业务场景,提供高度可定制化的组件解决方案: + +- **组件分类**:按业务领域划分,包括代理管理、监控告警、指标展示等 +- **类型安全**:完整的TypeScript类型定义,确保开发时的类型安全 +- **可复用性**:模块化设计,支持单独导入和批量导出 +- **主题适配**:深度集成Tailwind CSS,支持品牌色彩定制 + +### 核心业务组件 + +#### AgentStatusCard - 代理状态卡片 +提供AI代理的状态可视化展示,支持多种状态指示和详细信息展示: + +- **状态类型**:online(在线)、offline(离线)、busy(繁忙)、error(错误) +- **视觉反馈**:脉冲动画、颜色编码、状态徽章 +- **信息维度**:代理名称、描述、当前任务、活跃时间、完成统计 +- **交互设计**:悬停效果、响应式布局 + +#### AlertCard - 告警卡片 +企业级告警管理系统,支持多级别告警状态和操作: + +- **严重级别**:critical(严重)、warning(警告)、info(信息)、success(成功) +- **视觉层次**:图标、颜色、脉冲动画、状态点 +- **操作功能**:告警关闭、查看详情、批量处理 +- **扩展性**:自定义图标、动作按钮、时间戳 + +#### 其他业务组件 +- **MetricCard**:指标卡片,支持趋势方向和数据点配置 +- **TimelineStep**:时间轴步骤组件,支持多状态展示 +- **PlatformBadge**:平台标识组件,支持配置化平台信息 +- **ClientSwitcher**:客户切换器,支持多租户场景 +- **StageProgress**:阶段进度组件,支持工作流状态展示 + +```mermaid +classDiagram +class BusinessComponents { +<> ++StageProgress ++MetricCard ++AgentStatusCard ++TimelineStep ++PlatformBadge ++ClientSwitcher ++AlertCard +} +class AgentStatusCard { ++name : string ++status : AgentStatus ++currentTask? : string ++lastActiveAt? : string ++completedCount? : number ++render() : JSX.Element +} +class AlertCard { ++alerts : AlertCardItem[] ++title? : string ++onDismiss? : Function ++maxVisible? : number ++render() : JSX.Element +} +class BusinessComponentsIndex { ++exportAll() : void ++importSpecific() : void +} +BusinessComponents --> AgentStatusCard +BusinessComponents --> AlertCard +BusinessComponentsIndex --> BusinessComponents +``` + +**图表来源** +- [components/business/index.ts:1-29](file://frontend/components/business/index.ts#L1-L29) +- [components/business/agent-status-card.tsx:1-134](file://frontend/components/business/agent-status-card.tsx#L1-L134) +- [components/business/alert-card.tsx:1-203](file://frontend/components/business/alert-card.tsx#L1-L203) + +### 组件导出策略 +提供两种导出方式满足不同使用场景: + +- **统一索引导出**:通过index.ts文件提供集中导出,便于批量导入 +- **按需导入**:支持单独导入特定组件,优化打包体积 + +**章节来源** +- [components/business/index.ts:1-29](file://frontend/components/business/index.ts#L1-L29) +- [components/business/agent-status-card.tsx:1-134](file://frontend/components/business/agent-status-card.tsx#L1-L134) +- [components/business/alert-card.tsx:1-203](file://frontend/components/business/alert-card.tsx#L1-L203) ## 依赖分析 - 核心框架:Next.js 14(App Router)、React 18。 @@ -479,6 +656,7 @@ C->>C : "根据权限渲染侧边栏" - 样式:Tailwind CSS、Tailwind 插件(动画)、class-variance-authority、clsx、tailwind-merge。 - 图表:Recharts 用于可视化展示。 - 开发工具:ESLint、TypeScript、PostCSS、Tailwind。 +- **新增**:Playwright(E2E测试框架)、测试工具链。 ```mermaid graph LR @@ -495,16 +673,19 @@ TS["TypeScript"] --> N ESL["ESLint"] --> N PC["PostCSS"] --> TW TABS["Tabs 组件"] --> UI +PW["Playwright"] --> TEST["E2E测试"] +BC["Business Components"] --> UI ``` **图表来源** -- [package.json:1-40](file://frontend/package.json#L1-L40) -- [tailwind.config.ts:1-57](file://frontend/tailwind.config.ts#L1-L57) +- [package.json:1-45](file://frontend/package.json#L1-L45) +- [tailwind.config.ts:1-121](file://frontend/tailwind.config.ts#L1-L121) - [components/ui/tabs.tsx:1-56](file://frontend/components/ui/tabs.tsx#L1-L56) +- [playwright.config.ts:1-39](file://frontend/playwright.config.ts#L1-L39) **章节来源** -- [package.json:1-40](file://frontend/package.json#L1-L40) -- [tailwind.config.ts:1-57](file://frontend/tailwind.config.ts#L1-L57) +- [package.json:1-45](file://frontend/package.json#L1-L45) +- [tailwind.config.ts:1-121](file://frontend/tailwind.config.ts#L1-L121) - [components/ui/tabs.tsx:1-56](file://frontend/components/ui/tabs.tsx#L1-L56) ## 性能考虑 @@ -514,17 +695,19 @@ TABS["Tabs 组件"] --> UI - 图表渲染:对大数据集使用虚拟化或采样策略(建议项)。 - 资源优化:开启图片与静态资源优化(Next.js 默认支持),按需加载第三方库。 - 构建优化:使用生产构建与代码分割,避免打包体积过大。 -- 权限控制:服务器端权限检查,减少客户端无意义的渲染。 +- 权限控制:客户端权限检查,减少无意义的渲染。 +- **新增**:E2E测试性能:并行测试执行,智能重试机制,减少测试时间。 ## 故障排除指南 - 登录失败:检查凭据是否正确,确认后端认证接口可用;查看登录页错误提示与 NextAuth 回调日志。 - 会话丢失:确认 Cookie 设置、SameSite 与跨域配置;检查 NextAuth 回调是否正确写入 token。 -- 仪表盘空白:确认服务器端 getServerSession 返回有效会话;检查客户端 useSession 是否拿到访问令牌。 +- 仪表盘空白:确认客户端 useSession 返回有效会话;检查客户端状态管理。 - 认证页面异常:检查对应认证页面的错误状态和网络请求;确认 API 端点是否正确。 - 管理员功能不可用:确认用户 is_admin 标识;检查侧边栏权限渲染逻辑。 - 设置页面问题:检查各标签页的状态管理;确认 API 调用和表单验证逻辑。 - API 请求失败:查看 fetchWithAuth 抛出的错误信息,确认后端接口路径与鉴权头是否正确。 - 样式异常:检查 Tailwind 配置 content 路径与 CSS 变量是否生效;确认暗色模式 class 是否正确切换。 +- **新增**:E2E测试失败:检查测试环境配置、页面元素定位、网络请求超时;查看测试报告详细信息。 **章节来源** - [app/(auth)/login/page.tsx](file://frontend/app/(auth)/login/page.tsx#L1-L93) @@ -534,21 +717,27 @@ TABS["Tabs 组件"] --> UI - [app/(auth)/verify-email/page.tsx](file://frontend/app/(auth)/verify-email/page.tsx#L1-L155) - [app/(dashboard)/dashboard/admin/page.tsx](file://frontend/app/(dashboard)/dashboard/admin/page.tsx#L1-L435) - [app/(dashboard)/dashboard/settings/page.tsx](file://frontend/app/(dashboard)/dashboard/settings/page.tsx#L1-L445) -- [app/(dashboard)/layout.tsx](file://frontend/app/(dashboard)/layout.tsx#L1-L27) +- [app/(dashboard)/layout.tsx:1-146](file://frontend/app/(dashboard)/layout.tsx#L1-L146) - [lib/api.ts:1-154](file://frontend/lib/api.ts#L1-L154) -- [tailwind.config.ts:1-57](file://frontend/tailwind.config.ts#L1-L57) +- [tailwind.config.ts:1-121](file://frontend/tailwind.config.ts#L1-L121) +- [playwright.config.ts:1-39](file://frontend/playwright.config.ts#L1-L39) ## 结论 -本架构以 Next.js 14 App Router 为核心,结合服务器组件与客户端组件的混合模式,实现了清晰的页面组织与路由保护;通过 NextAuth.js 的凭据提供者与 JWT 会话策略,完成了前后端认证协作,支持完整的认证生命周期;UI 组件库以 Radix UI 与 Tailwind 为基础,具备良好的可维护性与一致性,新增的 Tabs 组件支持复杂的多标签页界面;API 客户端统一处理鉴权与错误,配合页面层的状态与错误处理,形成完整的前端数据流。系统现已扩展为完整的认证体系和管理功能,支持管理员权限和用户自助管理。建议在后续迭代中进一步完善缓存与重试、图表渲染优化与构建体积治理,持续提升用户体验与可维护性。 +本架构以 Next.js 14 App Router 为核心,结合服务器组件与客户端组件的混合模式,实现了清晰的页面组织与路由保护;通过 NextAuth.js 的凭据提供者与 JWT 会话策略,完成了前后端认证协作,支持完整的认证生命周期;UI 组件库以 Radix UI 与 Tailwind 为基础,具备良好的可维护性与一致性,新增的 Tabs 组件支持复杂的多标签页界面;API 客户端统一处理鉴权与错误,配合页面层的状态与错误处理,形成完整的前端数据流。 + +**更新** 新增的E2E测试框架显著提升了代码质量保证能力,通过Playwright实现跨浏览器兼容性测试;业务组件库扩展了企业级应用场景的组件支持,包括代理状态管理、告警系统、指标展示等功能;仪表板布局重构提供了更好的用户体验和导航效率。建议在后续迭代中进一步完善测试覆盖率、组件文档化和性能监控,持续提升系统的稳定性和可维护性。 ## 附录 - 最佳实践清单 - 使用路由组隔离功能域,保持页面组织清晰。 - - 将路由保护放在服务器端,优先保障安全性。 + - 将路由保护放在客户端,优先保障用户体验。 - 仅在需要时标记客户端组件,减少水合成本。 - 统一错误处理与用户反馈,提供明确的重试与刷新能力。 - 严格类型约束,结合 TypeScript 与自定义类型扩展,降低运行时风险。 - 支持管理员权限的渐进式增强,避免过度设计。 - 使用标签页组件组织复杂设置界面,提升用户体验。 - 实施细粒度的权限控制,确保数据安全。 - - 持续优化构建产物与运行时性能,关注首屏与交互延迟。 \ No newline at end of file + - 持续优化构建产物与运行时性能,关注首屏与交互延迟。 + - **新增**:建立完善的E2E测试流程,确保跨浏览器兼容性。 + - **新增**:文档化业务组件使用规范,提升团队协作效率。 + - **新增**:实施测试驱动开发,提高代码质量和稳定性。 \ No newline at end of file diff --git a/.qoder/repowiki/zh/content/后端系统架构/后端系统架构.md b/.qoder/repowiki/zh/content/后端系统架构/后端系统架构.md index 168e46d..21f4d87 100644 --- a/.qoder/repowiki/zh/content/后端系统架构/后端系统架构.md +++ b/.qoder/repowiki/zh/content/后端系统架构/后端系统架构.md @@ -26,17 +26,30 @@ - [backend/app/services/subscription.py](file://backend/app/services/subscription.py) - [backend/app/workers/scheduler.py](file://backend/app/workers/scheduler.py) - [backend/app/workers/citation_engine.py](file://backend/app/workers/citation_engine.py) +- [backend/app/workers/llm_adapter.py](file://backend/app/workers/llm_adapter.py) +- [backend/app/agent_framework/base.py](file://backend/app/agent_framework/base.py) +- [backend/app/agent_framework/dispatcher.py](file://backend/app/agent_framework/dispatcher.py) +- [backend/app/agent_framework/registry.py](file://backend/app/agent_framework/registry.py) +- [backend/app/agent_framework/pipeline/engine.py](file://backend/app/agent_framework/pipeline/engine.py) +- [backend/app/agent_framework/pipeline/loader.py](file://backend/app/agent_framework/pipeline/loader.py) +- [backend/app/agent_framework/pipeline/schema.py](file://backend/app/agent_framework/pipeline/schema.py) +- [backend/app/agent_framework/protocol.py](file://backend/app/agent_framework/protocol.py) +- [backend/app/agent_framework/agents/content_generator_agent.py](file://backend/app/agent_framework/agents/content_generator_agent.py) +- [backend/app/agent_framework/agents/geo_optimizer_agent.py](file://backend/app/agent_framework/agents/geo_optimizer_agent.py) +- [backend/app/services/llm/factory.py](file://backend/app/services/llm/factory.py) +- [backend/app/models/agent.py](file://backend/app/models/agent.py) +- [backend/pipelines/content_production.yaml](file://backend/pipelines/content_production.yaml) +- [backend/pipelines/diagnosis.yaml](file://backend/pipelines/diagnosis.yaml) ## 更新摘要 **所做更改** -- 新增中间件系统章节,包含限流中间件和日志中间件 -- 新增管理员服务和API路由,支持系统管理和用户管理 -- 新增订阅服务和API路由,支持套餐管理和订阅管理 -- 新增PDF报告服务,支持CSV和PDF格式导出 -- 更新项目结构图,反映新增模块和文件 -- 更新数据模型关系图,包含订阅和查询任务模型 -- 更新架构总览图,展示新增中间件和服务层 +- 新增代理框架架构章节,包含Agent基类、注册中心、任务分发器和工作流引擎 +- 新增LLM服务集成章节,包含LLM工厂模式和多提供商支持 +- 新增工作器系统扩展章节,包含LLM适配器和平台适配器 +- 新增分布式发布系统章节,包含Pipeline编排和任务编排 +- 更新项目结构图,反映新增的代理框架和LLM服务模块 +- 更新架构总览图,展示新增的代理系统和LLM集成 ## 目录 1. [引言](#引言) @@ -44,20 +57,24 @@ 3. [核心组件](#核心组件) 4. [架构总览](#架构总览) 5. [详细组件分析](#详细组件分析) -6. [中间件系统](#中间件系统) -7. [管理员服务](#管理员服务) -8. [订阅服务](#订阅服务) -9. [报告服务](#报告服务) -10. [依赖关系分析](#依赖关系分析) -11. [性能考量](#性能考量) -12. [故障排查指南](#故障排查指南) -13. [结论](#结论) -14. [附录](#附录) +6. [代理框架架构](#代理框架架构) +7. [LLM服务集成](#llm服务集成) +8. [工作器系统扩展](#工作器系统扩展) +9. [分布式发布系统](#分布式发布系统) +10. [中间件系统](#中间件系统) +11. [管理员服务](#管理员服务) +12. [订阅服务](#订阅服务) +13. [报告服务](#报告服务) +14. [依赖关系分析](#依赖关系分析) +15. [性能考量](#性能考量) +16. [故障排查指南](#故障排查指南) +17. [结论](#结论) +18. [附录](#附录) ## 引言 本文件为 GEO 平台后端系统的架构文档,基于 FastAPI 构建,采用异步 SQLAlchemy ORM、APScheduler 定时任务与多平台适配器模式,实现查询词管理、引用检测与报告统计等功能。文档覆盖应用配置、中间件、路由组织、生命周期管理、数据库连接与 ORM、异步处理、认证与权限控制、API 设计与错误处理、系统监控与日志、性能优化策略,并给出架构决策的技术背景与权衡。 -**更新** 本次更新反映了应用的重大功能扩展,包括中间件系统的引入、管理员管理功能、订阅管理系统和报告导出功能。 +**更新** 本次更新显著扩展了系统架构,新增代理框架架构、LLM服务集成、工作器系统扩展和分布式发布系统等核心组件,形成了更加完整的企业级AI内容生产与管理平台。 ## 项目结构 后端采用分层与功能域结合的组织方式: @@ -68,7 +85,10 @@ - 中间件层:app/middleware/(logging_middleware、rate_limit) - 模型层:app/models/(SQLAlchemy ORM 映射) - 服务层:app/services/(business logic encapsulation) -- 工作器与调度:app/workers/(APScheduler 调度器、引用检测引擎、平台适配器) +- 代理框架:app/agent_framework/(Agent基类、注册中心、任务分发器、工作流引擎) +- LLM服务:app/services/llm/(LLM工厂、提供商适配器) +- 工作器与调度:app/workers/(APScheduler 调度器、引用检测引擎、平台适配器、LLM适配器) +- 流水线定义:pipelines/(YAML配置文件) - 测试:tests/(pytest) ```mermaid @@ -93,20 +113,41 @@ REPORTS["api/reports.py"] SUBSCRIPTIONS["api/subscriptions.py"] DEPS["api/deps.py"] end +subgraph "代理框架" +AGENT_BASE["agent_framework/base.py"] +REGISTRY["agent_framework/registry.py"] +DISPATCHER["agent_framework/dispatcher.py"] +PIPELINE_ENGINE["agent_framework/pipeline/engine.py"] +PIPELINE_LOADER["agent_framework/pipeline/loader.py"] +PIPELINE_SCHEMA["agent_framework/pipeline/schema.py"] +PROTOCOL["agent_framework/protocol.py"] +END +subgraph "LLM服务" +LLM_FACTORY["services/llm/factory.py"] +OPENAI_PROVIDER["services/llm/openai_provider.py"] +DEEPSEEK_PROVIDER["services/llm/deepseek_provider.py"] +END subgraph "模型与服务" MODEL_USER["models/user.py"] MODEL_QUERY["models/query.py"] MODEL_CIT["models/citation_record.py"] MODEL_SUB["models/subscription.py"] MODEL_TASK["models/query_task.py"] +MODEL_AGENT["models/agent.py"] SVC_AUTH["services/auth.py"] SVC_ADMIN["services/admin.py"] SVC_SUB["services/subscription.py"] -end +END subgraph "工作器与调度" SCHED["workers/scheduler.py"] ENGINE["workers/citation_engine.py"] -end +LLM_ADAPTER["workers/llm_adapter.py"] +PLATFORMS["workers/platforms/"] +END +subgraph "流水线定义" +CONTENT_PRODUCTION["pipelines/content_production.yaml"] +DIAGNOSIS["pipelines/diagnosis.yaml"] +END MAIN --> LOGMW MAIN --> RATEMW MAIN --> AUTH @@ -132,7 +173,14 @@ SCHED --> DB SCHED --> ENGINE ENGINE --> MODEL_QUERY ENGINE --> MODEL_CIT -DB --> CFG +LLM_ADAPTER --> CFG +REGISTRY --> DB +DISPATCHER --> DB +DISPATCHER --> AGENT_BASE +PIPELINE_ENGINE --> DISPATCHER +PIPELINE_LOADER --> PIPELINE_SCHEMA +LLM_FACTORY --> OPENAI_PROVIDER +LLM_FACTORY --> DEEPSEEK_PROVIDER ``` **图表来源** @@ -141,11 +189,14 @@ DB --> CFG - [backend/app/database.py:1-29](file://backend/app/database.py#L1-L29) - [backend/app/middleware/logging_middleware.py:1-24](file://backend/app/middleware/logging_middleware.py#L1-L24) - [backend/app/middleware/rate_limit.py:1-83](file://backend/app/middleware/rate_limit.py#L1-L83) -- [backend/app/api/admin.py:1-108](file://backend/app/api/admin.py#L1-L108) -- [backend/app/api/reports.py:1-75](file://backend/app/api/reports.py#L1-L75) -- [backend/app/api/subscriptions.py:1-77](file://backend/app/api/subscriptions.py#L1-L77) -- [backend/app/services/admin.py:1-188](file://backend/app/services/admin.py#L1-L188) -- [backend/app/services/subscription.py:1-155](file://backend/app/services/subscription.py#L1-L155) +- [backend/app/agent_framework/base.py:1-223](file://backend/app/agent_framework/base.py#L1-L223) +- [backend/app/agent_framework/registry.py:1-219](file://backend/app/agent_framework/registry.py#L1-L219) +- [backend/app/agent_framework/dispatcher.py:1-367](file://backend/app/agent_framework/dispatcher.py#L1-L367) +- [backend/app/agent_framework/pipeline/engine.py:1-536](file://backend/app/agent_framework/pipeline/engine.py#L1-L536) +- [backend/app/services/llm/factory.py:1-66](file://backend/app/services/llm/factory.py#L1-L66) +- [backend/app/workers/llm_adapter.py:1-281](file://backend/app/workers/llm_adapter.py#L1-L281) +- [backend/pipelines/content_production.yaml:1-65](file://backend/pipelines/content_production.yaml#L1-L65) +- [backend/pipelines/diagnosis.yaml:1-30](file://backend/pipelines/diagnosis.yaml#L1-L30) **章节来源** - [backend/app/main.py:1-48](file://backend/app/main.py#L1-L48) @@ -159,8 +210,11 @@ DB --> CFG - 数据库:异步 SQLAlchemy 引擎与会话工厂,依赖注入式获取会话。 - 认证与权限:OAuth2 密码流 + JWT,依赖注入解析当前用户,未授权时抛出 401。 - 引擎与调度:APScheduler 定时扫描到期查询,调用 CitationEngine 执行并持久化结果。 +- **新增** 代理框架:基于Redis的消息队列,支持Agent注册、发现、任务分发和工作流编排。 +- **新增** LLM服务:统一的LLM提供商工厂,支持OpenAI和DeepSeek等多种提供商。 +- **新增** 分布式发布:基于YAML的流水线编排系统,支持复杂的内容生产工作流。 -**更新** 新增中间件系统提供限流和日志功能,增强系统的安全性和可观测性。 +**更新** 新增代理框架、LLM服务集成和分布式发布系统,显著增强了系统的智能化和自动化能力。 **章节来源** - [backend/app/main.py:13-48](file://backend/app/main.py#L13-L48) @@ -168,7 +222,7 @@ DB --> CFG - [backend/app/api/deps.py:13-43](file://backend/app/api/deps.py#L13-L43) ## 架构总览 -系统采用"API 层-中间件层-服务层-模型层-基础设施"的分层架构,配合异步 I/O 与定时任务,实现高并发与可扩展的查询与检测能力。 +系统采用"API 层-中间件层-服务层-模型层-基础设施"的分层架构,配合异步 I/O 与定时任务,实现高并发与可扩展的查询与检测能力。新增的代理框架通过Redis实现分布式任务调度,LLM服务提供统一的AI能力接口,分布式发布系统支持复杂的工作流编排。 ```mermaid graph TB @@ -188,6 +242,12 @@ SVC_SUB["订阅服务
套餐管理/订阅流程"] DB["异步数据库
Session 工厂"] SCHED["查询调度器
APScheduler"] ENGINE["引用检测引擎
平台适配器"] +LLM_ADAPTER["LLM适配器
DeepSeek API"] +AGENT_FRAMEWORK["代理框架
Redis队列/Agent管理"] +REGISTRY["注册中心
Agent注册/发现"] +DISPATCHER["任务分发器
消息队列/状态管理"] +PIPELINE_ENGINE["工作流引擎
YAML编排/DAG执行"] +LLM_SERVICE["LLM服务
工厂模式/多提供商"] CLIENT --> FASTAPI FASTAPI --> MIDDLEWARE MIDDLEWARE --> ROUTER_AUTH @@ -215,6 +275,14 @@ SVC_SUB --> DB SCHED --> DB SCHED --> ENGINE ENGINE --> DB +LLM_ADAPTER --> DB +AGENT_FRAMEWORK --> REGISTRY +AGENT_FRAMEWORK --> DISPATCHER +AGENT_FRAMEWORK --> PIPELINE_ENGINE +DISPATCHER --> DB +REGISTRY --> DB +PIPELINE_ENGINE --> DB +LLM_SERVICE --> DB ``` **图表来源** @@ -227,6 +295,12 @@ ENGINE --> DB - [backend/app/services/subscription.py:69-155](file://backend/app/services/subscription.py#L69-L155) - [backend/app/workers/scheduler.py:25-95](file://backend/app/workers/scheduler.py#L25-L95) - [backend/app/workers/citation_engine.py:148-309](file://backend/app/workers/citation_engine.py#L148-L309) +- [backend/app/workers/llm_adapter.py:1-281](file://backend/app/workers/llm_adapter.py#L1-L281) +- [backend/app/agent_framework/base.py:1-223](file://backend/app/agent_framework/base.py#L1-L223) +- [backend/app/agent_framework/registry.py:1-219](file://backend/app/agent_framework/registry.py#L1-L219) +- [backend/app/agent_framework/dispatcher.py:1-367](file://backend/app/agent_framework/dispatcher.py#L1-L367) +- [backend/app/agent_framework/pipeline/engine.py:1-536](file://backend/app/agent_framework/pipeline/engine.py#L1-L536) +- [backend/app/services/llm/factory.py:1-66](file://backend/app/services/llm/factory.py#L1-L66) ## 详细组件分析 @@ -380,6 +454,9 @@ Wait --> Tick - 引用记录:外键查询、平台、是否引用、位置、文本、竞争品牌、原始响应、时间戳。 - 订阅:外键用户、套餐类型、状态、开始结束日期、金额、支付方式、时间戳。 - 查询任务:外键查询、平台、状态、错误信息、调度时间、开始完成时间。 +- **新增** Agent注册表:Agent元数据、状态、能力声明、心跳时间。 +- **新增** Agent任务表:任务执行状态、输入输出数据、执行指标。 +- **新增** Agent任务日志表:任务执行日志、进度跟踪、错误信息。 ```mermaid erDiagram @@ -440,11 +517,55 @@ text error_message timestamp scheduled_at timestamp started_at timestamp completed_at +timestamp created_at +timestamp updated_at +} +AGENT_REGISTRY { +uuid id PK +string name UK +string display_name +string agent_type +string description +string version +string endpoint +string status +jsonb capabilities +timestamp last_heartbeat +timestamp created_at +timestamp updated_at +} +AGENT_TASKS { +uuid id PK +uuid agent_id FK +string task_type +string status +int priority +jsonb input_data +jsonb output_data +text error_message +uuid created_by +uuid organization_id FK +uuid project_id FK +timestamp scheduled_at +timestamp started_at +timestamp completed_at +timestamp created_at +} +AGENT_TASK_LOGS { +uuid id PK +uuid task_id FK +uuid agent_id FK +string log_level +text message +jsonb extra_metadata +timestamp created_at } USERS ||--o{ QUERIES : "拥有" QUERIES ||--o{ CITATION_RECORDS : "产生" USERS ||--o{ SUBSCRIPTIONS : "订阅" QUERIES ||--o{ QUERY_TASKS : "包含" +AGENT_REGISTRY ||--o{ AGENT_TASKS : "执行" +AGENT_TASKS ||--o{ AGENT_TASK_LOGS : "记录" ``` **图表来源** @@ -453,6 +574,7 @@ QUERIES ||--o{ QUERY_TASKS : "包含" - [backend/app/models/citation_record.py:11-42](file://backend/app/models/citation_record.py#L11-L42) - [backend/app/models/subscription.py:11-37](file://backend/app/models/subscription.py#L11-L37) - [backend/app/models/query_task.py:11-39](file://backend/app/models/query_task.py#L11-L39) +- [backend/app/models/agent.py:12-206](file://backend/app/models/agent.py#L12-L206) **章节来源** - [backend/app/models/user.py:1-41](file://backend/app/models/user.py#L1-L41) @@ -460,6 +582,292 @@ QUERIES ||--o{ QUERY_TASKS : "包含" - [backend/app/models/citation_record.py:1-42](file://backend/app/models/citation_record.py#L1-L42) - [backend/app/models/subscription.py:1-37](file://backend/app/models/subscription.py#L1-L37) - [backend/app/models/query_task.py:1-39](file://backend/app/models/query_task.py#L1-L39) +- [backend/app/models/agent.py:1-206](file://backend/app/models/agent.py#L1-L206) + +## 代理框架架构 + +### Agent基类与生命周期管理 +代理框架的核心是BaseAgent基类,它定义了所有Agent的标准生命周期和行为: +- **启动流程**:初始化Redis连接、注册到注册中心、启动心跳、开始监听任务队列 +- **任务执行**:异步监听Redis队列,执行具体任务逻辑,上报进度和结果 +- **状态管理**:维护Agent在线状态、忙碌状态,支持优雅停机 +- **心跳机制**:定期向注册中心上报心跳,保持活跃状态 + +```mermaid +sequenceDiagram +participant Agent as "Agent实例" +participant Redis as "Redis服务器" +participant Registry as "注册中心" +participant Dispatcher as "任务分发器" +Agent->>Agent : start() +Agent->>Redis : 连接Redis +Agent->>Registry : register(capabilities) +Registry-->>Agent : 注册成功 +Agent->>Agent : 启动心跳循环 +Agent->>Agent : 启动任务监听 +loop 每30秒 +Agent->>Registry : update_heartbeat() +end +Redis-->>Agent : 任务消息 +Agent->>Agent : execute(task) +Agent->>Dispatcher : handle_result(result) +Agent->>Agent : report_progress(progress) +``` + +**图表来源** +- [backend/app/agent_framework/base.py:52-114](file://backend/app/agent_framework/base.py#L52-L114) +- [backend/app/agent_framework/base.py:148-182](file://backend/app/agent_framework/base.py#L148-L182) + +### 注册中心与Agent发现 +注册中心负责管理所有Agent的生命周期和状态: +- **注册流程**:Agent启动时向注册中心注册,保存能力声明和端点信息 +- **状态维护**:实时更新Agent心跳时间,超时自动标记为离线 +- **发现机制**:根据任务类型动态查找可用的Agent实例 +- **健康检查**:定期扫描超时的Agent并更新状态 + +```mermaid +flowchart TD +Start["Agent启动"] --> Connect["连接Redis"] +Connect --> Register["向注册中心注册"] +Register --> SaveInfo["保存Agent信息
能力声明/端点/状态"] +SaveInfo --> Heartbeat["启动心跳循环"] +Heartbeat --> Monitor["监控Agent状态"] +Monitor --> Timeout{"心跳超时?"} +Timeout -- 是 --> MarkOffline["标记为离线"] +Timeout -- 否 --> Monitor +Monitor --> Discover["Agent发现"] +Discover --> Match{"任务类型匹配?"} +Match -- 是 --> Dispatch["分发任务"] +Match -- 否 --> Wait["等待其他Agent"] +``` + +**图表来源** +- [backend/app/agent_framework/registry.py:29-80](file://backend/app/agent_framework/registry.py#L29-L80) +- [backend/app/agent_framework/registry.py:156-172](file://backend/app/agent_framework/registry.py#L156-L172) +- [backend/app/agent_framework/registry.py:174-201](file://backend/app/agent_framework/registry.py#L174-L201) + +### 任务分发器与消息队列 +任务分发器通过Redis实现Agent间的异步通信: +- **任务分发**:将TaskMessage推送到指定Agent的队列 +- **状态管理**:维护AgentTask表,跟踪任务执行状态 +- **结果处理**:接收Agent返回的TaskResult,更新数据库状态 +- **进度上报**:处理TaskProgress消息,记录执行进度 + +```mermaid +sequenceDiagram +participant API as "API服务" +participant Dispatcher as "任务分发器" +participant Redis as "Redis队列" +participant Agent as "目标Agent" +participant DB as "数据库" +API->>Dispatcher : dispatch(task) +Dispatcher->>DB : 写入AgentTask记录 +DB-->>Dispatcher : 确认写入 +Dispatcher->>Redis : LPUSH agent : {name} : tasks +Redis-->>Agent : 任务消息 +Agent->>Agent : execute(task) +Agent->>Dispatcher : handle_result(result) +Dispatcher->>DB : 更新任务状态 +DB-->>API : 任务完成 +``` + +**图表来源** +- [backend/app/agent_framework/dispatcher.py:54-117](file://backend/app/agent_framework/dispatcher.py#L54-L117) +- [backend/app/agent_framework/dispatcher.py:169-218](file://backend/app/agent_framework/dispatcher.py#L169-L218) + +**章节来源** +- [backend/app/agent_framework/base.py:1-223](file://backend/app/agent_framework/base.py#L1-L223) +- [backend/app/agent_framework/registry.py:1-219](file://backend/app/agent_framework/registry.py#L1-L219) +- [backend/app/agent_framework/dispatcher.py:1-367](file://backend/app/agent_framework/dispatcher.py#L1-L367) + +## LLM服务集成 + +### LLM工厂模式与多提供商支持 +LLM服务采用工厂模式统一管理不同的AI提供商: +- **OpenAI提供商**:支持GPT系列模型,提供标准的ChatCompletion接口 +- **DeepSeek提供商**:支持DeepSeek系列模型,提供高性能的推理能力 +- **统一接口**:所有提供商实现相同的LLMProvider接口,支持透明切换 +- **配置管理**:通过环境变量和配置文件管理API密钥和模型参数 + +```mermaid +flowchart TD +Factory["LLM工厂"] --> OpenAI["OpenAI提供商"] +Factory --> DeepSeek["DeepSeek提供商"] +OpenAI --> GPT4["GPT-4模型"] +OpenAI --> GPT35["GPT-3.5模型"] +DeepSeek --> DeepSeekChat["DeepSeek-chat模型"] +DeepSeek --> DeepSeekCoder["DeepSeek-coder模型"] +Factory --> Config["配置管理"] +Config --> Env["环境变量"] +Config --> Settings["应用配置"] +Env --> Factory +Settings --> Factory +``` + +**图表来源** +- [backend/app/services/llm/factory.py:8-66](file://backend/app/services/llm/factory.py#L8-L66) +- [backend/app/services/llm/factory.py:25-50](file://backend/app/services/llm/factory.py#L25-L50) + +### LLM适配器与品牌引用检测 +LLM适配器专门用于品牌引用检测任务,集成DeepSeek API: +- **提示词工程**:精心设计的提示词模板,确保准确的品牌识别 +- **JSON输出解析**:标准化的JSON格式输出,包含引用状态、置信度等信息 +- **错误处理**:完善的异常处理和重试机制,确保服务稳定性 +- **模拟模式**:在禁用LLM时提供模拟结果,保证系统可用性 + +```mermaid +sequenceDiagram +participant Engine as "引用检测引擎" +participant Adapter as "LLM适配器" +participant DeepSeek as "DeepSeek API" +Engine->>Adapter : query_brand_citation(keyword, brand, aliases) +Adapter->>Adapter : 构建提示词 +Adapter->>DeepSeek : chat.completions.create +DeepSeek-->>Adapter : JSON响应 +Adapter->>Adapter : 解析JSON输出 +Adapter-->>Engine : CitationResult +``` + +**图表来源** +- [backend/app/workers/llm_adapter.py:71-110](file://backend/app/workers/llm_adapter.py#L71-L110) +- [backend/app/workers/llm_adapter.py:220-270](file://backend/app/workers/llm_adapter.py#L220-L270) + +**章节来源** +- [backend/app/services/llm/factory.py:1-66](file://backend/app/services/llm/factory.py#L1-L66) +- [backend/app/workers/llm_adapter.py:1-281](file://backend/app/workers/llm_adapter.py#L1-L281) + +## 工作器系统扩展 + +### 平台适配器与多平台支持 +工作器系统扩展了原有的平台适配器,支持更多AI平台: +- **现有平台**:Doubao、Kimi、Qingyan、Tiangong、Tongyi、Wenxin、Xinghuo +- **搜索引擎**:通用搜索平台适配器 +- **统一接口**:所有平台实现相同的BasePlatform接口 +- **配置管理**:通过配置文件管理平台API密钥和参数 + +```mermaid +graph TB +PlatformBase["平台基类
BasePlatform"] +Doubao["Doubao平台
doubao.py"] +Kimi["Kimi平台
kimi.py"] +Qingyan["Qingyan平台
qingyan.py"] +SearchEngine["搜索引擎
search_engine.py"] +Tiangong["Tiangong平台
tiangong.py"] +Tongyi["Tongyi平台
tongyi.py"] +Wenxin["Wenxin平台
wenxin.py"] +Xinghuo["Xinghuo平台
xinghuo.py"] +PlatformBase --> Doubao +PlatformBase --> Kimi +PlatformBase --> Qingyan +PlatformBase --> SearchEngine +PlatformBase --> Tiangong +PlatformBase --> Tongyi +PlatformBase --> Wenxin +PlatformBase --> Xinghuo +``` + +**图表来源** +- [backend/app/workers/platforms/base.py](file://backend/app/workers/platforms/base.py) +- [backend/app/workers/platforms/doubao.py](file://backend/app/workers/platforms/doubao.py) +- [backend/app/workers/platforms/kimi.py](file://backend/app/workers/platforms/kimi.py) +- [backend/app/workers/platforms/qingyan.py](file://backend/app/workers/platforms/qingyan.py) +- [backend/app/workers/platforms/search_engine.py](file://backend/app/workers/platforms/search_engine.py) +- [backend/app/workers/platforms/tiangong.py](file://backend/app/workers/platforms/tiangong.py) +- [backend/app/workers/platforms/tongyi.py](file://backend/app/workers/platforms/tongyi.py) +- [backend/app/workers/platforms/wenxin.py](file://backend/app/workers/platforms/wenxin.py) +- [backend/app/workers/platforms/xinghuo.py](file://backend/app/workers/platforms/xinghuo.py) + +### 内容生成Agent与GEO优化Agent +新增的专业Agent实现了特定的AI内容生成功能: +- **内容生成Agent**:支持选题生成和文章生成,集成RAG知识库检索 +- **GEO优化Agent**:专门优化内容在AI搜索引擎中的可见性 +- **进度上报**:实时上报任务执行进度,支持用户监控 +- **错误处理**:完善的异常处理和重试机制 + +```mermaid +flowchart TD +ContentAgent["内容生成Agent"] --> Topics["选题生成"] +ContentAgent --> Article["文章生成"] +Topics --> RAG["RAG知识库检索"] +Article --> LLM["LLM调用"] +GEOAgent["GEO优化Agent"] --> Optimize["内容优化"] +Optimize --> LLM2["LLM调用"] +RAG --> LLM +``` + +**图表来源** +- [backend/app/agent_framework/agents/content_generator_agent.py:111-182](file://backend/app/agent_framework/agents/content_generator_agent.py#L111-L182) +- [backend/app/agent_framework/agents/content_generator_agent.py:184-252](file://backend/app/agent_framework/agents/content_generator_agent.py#L184-L252) +- [backend/app/agent_framework/agents/geo_optimizer_agent.py:104-180](file://backend/app/agent_framework/agents/geo_optimizer_agent.py#L104-L180) + +**章节来源** +- [backend/app/agent_framework/agents/content_generator_agent.py:1-299](file://backend/app/agent_framework/agents/content_generator_agent.py#L1-L299) +- [backend/app/agent_framework/agents/geo_optimizer_agent.py:1-198](file://backend/app/agent_framework/agents/geo_optimizer_agent.py#L1-L198) + +## 分布式发布系统 + +### Pipeline工作流编排 +分布式发布系统基于YAML配置实现复杂的工作流编排: +- **内容生产流水线**:从选题到发布的完整内容生产流程 +- **诊断分析流水线**:引用检测与竞争分析的诊断流程 +- **DAG执行**:支持有向无环图的任务依赖关系 +- **变量解析**:支持复杂的变量引用和上下文传递 + +```mermaid +graph TB +ContentProduction["内容生产流水线"] --> TopicSelection["选题选择"] +ContentProduction --> ContentGeneration["内容生成"] +ContentProduction --> DeAIProcessing["去AI化处理"] +ContentProduction --> GEOOptimization["GEO优化"] +ContentProduction --> RuleValidation["规则验证"] +TopicSelection --> ContentGeneration +ContentGeneration --> DeAIProcessing +DeAIProcessing --> GEOOptimization +GEOOptimization --> RuleValidation +Diagnosis["诊断分析流水线"] --> CitationDetection["引用检测"] +Diagnosis --> CompetitorAnalysis["竞争分析"] +CitationDetection --> CompetitorAnalysis +``` + +**图表来源** +- [backend/pipelines/content_production.yaml:9-65](file://backend/pipelines/content_production.yaml#L9-L65) +- [backend/pipelines/diagnosis.yaml:8-30](file://backend/pipelines/diagnosis.yaml#L8-L30) + +### 工作流引擎与任务编排 +工作流引擎负责执行复杂的任务编排逻辑: +- **拓扑排序**:使用Kahn算法进行DAG拓扑排序 +- **条件执行**:支持基于条件表达式的任务执行 +- **重试机制**:支持任务级别的重试和超时控制 +- **进度跟踪**:实时跟踪每个阶段的执行进度 + +```mermaid +sequenceDiagram +participant User as "用户" +participant Engine as "工作流引擎" +participant Dispatcher as "任务分发器" +participant Agent as "Agent实例" +User->>Engine : execute(pipeline, context) +Engine->>Engine : 拓扑排序 +Engine->>Engine : 变量解析 +Engine->>Dispatcher : 分发阶段任务 +Dispatcher->>Agent : 任务消息 +Agent->>Agent : 执行任务 +Agent->>Dispatcher : 任务结果 +Dispatcher->>Engine : 更新状态 +Engine->>Engine : 下一阶段执行 +Engine-->>User : 完整执行结果 +``` + +**图表来源** +- [backend/app/agent_framework/pipeline/engine.py:51-176](file://backend/app/agent_framework/pipeline/engine.py#L51-L176) +- [backend/app/agent_framework/pipeline/engine.py:256-327](file://backend/app/agent_framework/pipeline/engine.py#L256-L327) + +**章节来源** +- [backend/app/agent_framework/pipeline/engine.py:1-536](file://backend/app/agent_framework/pipeline/engine.py#L1-L536) +- [backend/app/agent_framework/pipeline/loader.py:1-283](file://backend/app/agent_framework/pipeline/loader.py#L1-L283) +- [backend/app/agent_framework/pipeline/schema.py:1-102](file://backend/app/agent_framework/pipeline/schema.py#L1-L102) +- [backend/pipelines/content_production.yaml:1-65](file://backend/pipelines/content_production.yaml#L1-L65) +- [backend/pipelines/diagnosis.yaml:1-30](file://backend/pipelines/diagnosis.yaml#L1-L30) ## 中间件系统 @@ -619,6 +1027,9 @@ Reports-->>Client : Response PDF ## 依赖关系分析 - 组件内聚:API 路由与服务层职责清晰,模型仅负责映射。 - 组件耦合:API 依赖服务,服务依赖数据库与配置;调度器依赖引擎与数据库;引擎依赖平台适配器。 +- **新增** 代理框架:Agent依赖Redis和注册中心,任务分发器依赖数据库和Redis。 +- **新增** LLM服务:Agent依赖LLM工厂,LLM工厂依赖具体的提供商实现。 +- **新增** 工作流引擎:依赖任务分发器和管道加载器,支持复杂的任务编排。 - 依赖注入:通过 FastAPI 依赖系统注入数据库会话与当前用户。 - 循环依赖:未见明显循环依赖。 @@ -642,6 +1053,13 @@ DEPS --> DB SCHED["workers/scheduler.py"] --> DB SCHED --> ENGINE["workers/citation_engine.py"] ENGINE --> MODELS["models/*.py"] +LLM_ADAPTER["workers/llm_adapter.py"] --> LLM_FACTORY["services/llm/factory.py"] +LLM_FACTORY --> PROVIDERS["services/llm/*"] +AGENT_FRAMEWORK["agent_framework/*"] --> REGISTRY["agent_framework/registry.py"] +AGENT_FRAMEWORK --> DISPATCHER["agent_framework/dispatcher.py"] +DISPATCHER --> MODELS["models/agent.py"] +PIPELINE_ENGINE["agent_framework/pipeline/engine.py"] --> DISPATCHER +PIPELINE_LOADER["agent_framework/pipeline/loader.py"] --> PIPELINE_SCHEMA["agent_framework/pipeline/schema.py"] ``` **图表来源** @@ -652,6 +1070,13 @@ ENGINE --> MODELS["models/*.py"] - [backend/app/api/subscriptions.py:1-77](file://backend/app/api/subscriptions.py#L1-L77) - [backend/app/services/admin.py:1-188](file://backend/app/services/admin.py#L1-L188) - [backend/app/services/subscription.py:1-155](file://backend/app/services/subscription.py#L1-L155) +- [backend/app/workers/llm_adapter.py:1-281](file://backend/app/workers/llm_adapter.py#L1-L281) +- [backend/app/services/llm/factory.py:1-66](file://backend/app/services/llm/factory.py#L1-L66) +- [backend/app/agent_framework/registry.py:1-219](file://backend/app/agent_framework/registry.py#L1-L219) +- [backend/app/agent_framework/dispatcher.py:1-367](file://backend/app/agent_framework/dispatcher.py#L1-L367) +- [backend/app/agent_framework/pipeline/engine.py:1-536](file://backend/app/agent_framework/pipeline/engine.py#L1-L536) +- [backend/app/agent_framework/pipeline/loader.py:1-283](file://backend/app/agent_framework/pipeline/loader.py#L1-L283) +- [backend/app/agent_framework/pipeline/schema.py:1-102](file://backend/app/agent_framework/pipeline/schema.py#L1-L102) **章节来源** - [backend/app/api/auth.py:1-43](file://backend/app/api/auth.py#L1-L43) @@ -665,17 +1090,21 @@ ENGINE --> MODELS["models/*.py"] - [backend/app/models/user.py:1-41](file://backend/app/models/user.py#L1-L41) - [backend/app/models/query.py:1-55](file://backend/app/models/query.py#L1-L55) - [backend/app/models/citation_record.py:1-42](file://backend/app/models/citation_record.py#L1-L42) +- [backend/app/models/agent.py:1-206](file://backend/app/models/agent.py#L1-L206) ## 性能考量 - 异步 I/O:数据库与平台查询均采用异步,提升并发吞吐。 - 会话管理:显式事务边界,避免长事务占用连接池。 - 定时任务:APScheduler 异步调度,事件循环兼容处理,降低阻塞风险。 - 索引优化:查询与引用表建立复合索引,加速过滤与排序。 +- **新增** Redis缓存:代理框架使用Redis作为消息队列,支持高并发任务分发。 +- **新增** LLM优化:LLM调用采用异步模式,支持批量处理和错误重试。 +- **新增** 工作流优化:DAG拓扑排序确保任务执行顺序,避免死锁和循环依赖。 - 缓存建议:可引入 Redis 缓存热点查询结果与用户会话信息(当前配置已准备)。 - 日志采样:生产环境建议开启采样与结构化日志,避免高频日志影响性能。 - **中间件性能**:限流中间件使用内存存储,性能开销低;日志中间件仅记录必要信息。 -**更新** 新增中间件系统的性能考量,包括内存存储的限流机制和结构化日志的性能影响。 +**更新** 新增代理框架、LLM服务和工作流系统的性能考量,包括Redis缓存、异步LLM调用和DAG执行优化。 ## 故障排查指南 - 认证失败:检查 JWT 秘钥、过期时间与前端令牌传递;确认 OAuth2 tokenUrl 与 Bearer 头正确。 @@ -683,11 +1112,14 @@ ENGINE --> MODELS["models/*.py"] - 定时任务异常:关注调度器日志,检查查询状态与平台适配器可用性;确认 next_query_at 计算逻辑。 - 引擎执行失败:查看平台适配器错误与原始响应;检查品牌匹配器与竞争品牌检测逻辑。 - CORS 问题:确认前端域名与请求头是否在允许范围内。 +- **新增** 代理框架问题:检查Redis连接、Agent注册状态、任务队列是否正常。 +- **新增** LLM服务问题:检查API密钥配置、提供商可用性、请求超时设置。 +- **新增** 工作流执行问题:检查YAML配置语法、依赖关系、变量引用是否正确。 - **中间件问题**:检查限流规则配置,确认健康检查路径是否被正确豁免;验证日志中间件的logger配置。 - **管理员权限**:确认用户 is_admin 字段,检查管理员路由的权限验证逻辑。 - **订阅状态**:检查用户套餐与订阅状态的一致性,验证订阅历史记录的查询逻辑。 -**更新** 新增中间件、管理员服务、订阅服务相关的故障排查指导。 +**更新** 新增代理框架、LLM服务和分布式发布系统的故障排查指导。 **章节来源** - [backend/app/api/deps.py:16-43](file://backend/app/api/deps.py#L16-L43) @@ -696,15 +1128,18 @@ ENGINE --> MODELS["models/*.py"] - [backend/app/workers/citation_engine.py:211-227](file://backend/app/workers/citation_engine.py#L211-L227) - [backend/app/middleware/rate_limit.py:34-83](file://backend/app/middleware/rate_limit.py#L34-L83) - [backend/app/middleware/logging_middleware.py:8-24](file://backend/app/middleware/logging_middleware.py#L8-L24) +- [backend/app/agent_framework/base.py:148-182](file://backend/app/agent_framework/base.py#L148-L182) +- [backend/app/workers/llm_adapter.py:141-218](file://backend/app/workers/llm_adapter.py#L141-L218) +- [backend/app/agent_framework/pipeline/loader.py:124-134](file://backend/app/agent_framework/pipeline/loader.py#L124-L134) ## 结论 -该架构以 FastAPI 为核心,结合异步数据库、定时任务与多平台适配器,形成高可用、可扩展的查询与引用检测系统。通过明确的分层与依赖注入,系统具备良好的可测试性与可维护性。新增的中间件系统提供了安全防护和性能监控能力,管理员服务增强了系统管理功能,订阅服务完善了商业化运营能力,报告服务提升了用户体验。建议在生产环境中完善日志与监控、接入缓存与告警,并持续优化索引与查询计划。 +该架构以 FastAPI 为核心,结合异步数据库、定时任务与多平台适配器,形成高可用、可扩展的查询与引用检测系统。通过明确的分层与依赖注入,系统具备良好的可测试性与可维护性。新增的代理框架、LLM服务集成、工作器系统扩展和分布式发布系统,显著增强了系统的智能化、自动化和企业级服务能力。系统现已支持复杂的AI内容生产工作流、多提供商的LLM集成、分布式任务调度和实时进度监控,为GEO平台的商业化运营奠定了坚实的技术基础。 -**更新** 本次更新显著增强了系统的功能完整性,包括安全防护、管理能力、商业运营和用户体验等方面。 +**更新** 本次更新大幅扩展了系统功能,新增代理框架、LLM服务集成、工作器系统扩展和分布式发布系统,形成了更加完整的企业级AI内容生产与管理平台。 ## 附录 - API 设计原则:统一前缀与标签、明确响应模型、一致的状态码与错误消息。 - 错误处理:在路由层捕获业务异常并转换为标准 HTTP 状态码;在依赖层统一 401 未授权。 - 响应格式:遵循 Pydantic 模型序列化,确保前后端契约一致。 - 架构决策背景:选择异步栈以提升 I/O 密集场景性能;APScheduler 简化定时任务编排;JWT 适合无状态认证场景;中间件系统提供安全防护和性能监控。 -- **新增功能背景**:中间件系统满足安全需求;管理员服务满足系统管理需求;订阅服务满足商业化需求;报告服务满足用户体验需求。 \ No newline at end of file +- **新增功能背景**:代理框架满足分布式任务调度需求;LLM服务满足AI能力集成需求;工作器系统扩展满足多平台适配需求;分布式发布系统满足复杂工作流编排需求。 \ No newline at end of file diff --git a/.qoder/repowiki/zh/content/开发指南/开发指南.md b/.qoder/repowiki/zh/content/开发指南/开发指南.md index 2915315..3174235 100644 --- a/.qoder/repowiki/zh/content/开发指南/开发指南.md +++ b/.qoder/repowiki/zh/content/开发指南/开发指南.md @@ -18,22 +18,45 @@ - [backend/app/schemas/auth.py](file://backend/app/schemas/auth.py) - [backend/app/models/user.py](file://backend/app/models/user.py) - [README.md](file://README.md) +- [docs/03-development/coding-standards.md](file://docs/03-development/coding-standards.md) +- [docs/03-development/dev-guide.md](file://docs/03-development/dev-guide.md) +- [docs/05-deployment/deployment-guide.md](file://docs/05-deployment/deployment-guide.md) +- [docs/04-testing/test-strategy.md](file://docs/04-testing/test-strategy.md) +- [docs/03-development/tdd-workflow.md](file://docs/03-development/tdd-workflow.md) +- [docs/00-project/tech-stack.md](file://docs/00-project/tech-stack.md) +## 更新摘要 +**所做更改** +- 新增完整的代码规范文档,包含Python和TypeScript开发标准 +- 新增TDD测试驱动开发流程规范,定义RED-GREEN-REFACTOR循环 +- 新增开发指南文档,涵盖环境搭建和开发流程 +- 新增部署指南文档,定义多环境部署策略 +- 新增测试策略文档,建立四层测试金字塔 +- 新增技术栈说明文档,详细阐述各技术选型 +- 更新模块设计指南,增加Agent框架开发指导 +- 完善开发工具使用方法,包含调试和性能分析工具 + ## 目录 1. 引言 2. 项目结构 3. 核心组件 4. 架构总览 5. 详细组件分析 -6. 依赖分析 -7. 性能考虑 -8. 故障排查指南 -9. 结论 -10. 附录 +6. 代码规范与最佳实践 +7. 开发流程与工作流 +8. 开发工具使用方法 +9. 新功能开发指导原则 +10. 测试策略与实施 +11. 部署管理 +12. 常见问题与解决方案 +13. 结论 +14. 附录 ## 引言 -本开发指南面向GEO项目的开发者,旨在统一前后端代码规范与最佳实践,明确开发流程与工作流(包括分支策略、代码评审与版本发布),并提供开发工具使用方法(IDE配置、调试与性能分析、**Git部署自动化脚本**)、新功能开发指导原则(模块设计、接口定义与测试要求),以及常见问题的排查方案。本指南以仓库中现有实现为依据,确保内容可落地、可执行。 +本开发指南面向GEO项目的开发者,旨在统一前后端代码规范与最佳实践,明确开发流程与工作流(包括分支策略、代码评审与版本发布),并提供开发工具使用方法(IDE配置、调试与性能分析、Git部署自动化脚本)、新功能开发指导原则(模块设计、接口定义与测试要求),以及常见问题的排查方案。本指南以仓库中现有实现为依据,确保内容可落地、可执行。 + +**更新** 新增完整的开发文档体系,包括代码规范、开发流程、测试策略和部署管理等核心内容。 ## 项目结构 GEO采用前后端分离架构,后端基于FastAPI,前端基于Next.js,数据库使用PostgreSQL,缓存使用Redis,任务调度使用APScheduler,浏览器自动化使用Playwright。项目通过Docker与docker-compose进行容器化编排,便于本地开发与部署。 @@ -75,20 +98,20 @@ DC --> REDIS - [docker-compose.yml:1-71](file://docker-compose.yml#L1-L71) - [frontend/Dockerfile:1-15](file://frontend/Dockerfile#L1-L15) - [backend/Dockerfile:1-41](file://backend/Dockerfile#L1-L41) -- [frontend/package.json:1-40](file://frontend/package.json#L1-L40) -- [backend/requirements.txt:1-35](file://backend/requirements.txt#L1-L35) +- [frontend/package.json:1-45](file://frontend/package.json#L1-L45) +- [backend/requirements.txt:1-42](file://backend/requirements.txt#L1-L42) - [backend/app/main.py:1-48](file://backend/app/main.py#L1-L48) -- [backend/app/config.py:1-17](file://backend/app/config.py#L1-L17) +- [backend/app/config.py:1-46](file://backend/app/config.py#L1-L46) - [backend/alembic.ini:1-150](file://backend/alembic.ini#L1-L150) **章节来源** - [docker-compose.yml:1-71](file://docker-compose.yml#L1-L71) - [frontend/Dockerfile:1-15](file://frontend/Dockerfile#L1-L15) - [backend/Dockerfile:1-41](file://backend/Dockerfile#L1-L41) -- [frontend/package.json:1-40](file://frontend/package.json#L1-L40) -- [backend/requirements.txt:1-35](file://backend/requirements.txt#L1-L35) +- [frontend/package.json:1-45](file://frontend/package.json#L1-L45) +- [backend/requirements.txt:1-42](file://backend/requirements.txt#L1-L42) - [backend/app/main.py:1-48](file://backend/app/main.py#L1-L48) -- [backend/app/config.py:1-17](file://backend/app/config.py#L1-L17) +- [backend/app/config.py:1-46](file://backend/app/config.py#L1-L46) - [backend/alembic.ini:1-150](file://backend/alembic.ini#L1-L150) ## 核心组件 @@ -101,10 +124,10 @@ DC --> REDIS **章节来源** - [backend/app/main.py:1-48](file://backend/app/main.py#L1-L48) -- [backend/app/config.py:1-17](file://backend/app/config.py#L1-L17) -- [frontend/package.json:1-40](file://frontend/package.json#L1-L40) +- [backend/app/config.py:1-46](file://backend/app/config.py#L1-L46) +- [frontend/package.json:1-45](file://frontend/package.json#L1-L45) - [frontend/tsconfig.json:1-27](file://frontend/tsconfig.json#L1-L27) -- [frontend/.eslintrc.json:1-4](file://frontend/.eslintrc.json#L1-L4) +- [frontend/.eslintrc.json:1-14](file://frontend/.eslintrc.json#L1-L14) - [frontend/tailwind.config.ts:1-57](file://frontend/tailwind.config.ts#L1-L57) - [backend/alembic.ini:86-114](file://backend/alembic.ini#L86-L114) - [tests/conftest.py:1-71](file://tests/conftest.py#L1-L71) @@ -129,7 +152,7 @@ FastAPI --> Playwright **图表来源** - [backend/app/main.py:24-47](file://backend/app/main.py#L24-L47) -- [backend/app/config.py:7-13](file://backend/app/config.py#L7-L13) +- [backend/app/config.py:12-18](file://backend/app/config.py#L12-L18) - [backend/Dockerfile:31-33](file://backend/Dockerfile#L31-L33) - [docker-compose.yml:4-20](file://docker-compose.yml#L4-L20) - [docker-compose.yml:22-34](file://docker-compose.yml#L22-L34) @@ -238,7 +261,7 @@ SkipHooks --> Done **章节来源** - [backend/alembic.ini:1-150](file://backend/alembic.ini#L1-L150) -- [backend/app/config.py:7-8](file://backend/app/config.py#L7-L8) +- [backend/app/config.py:12-13](file://backend/app/config.py#L12-L13) ### 前端工程化 - 构建与运行:dev/build/start/lint脚本由Next.js提供。 @@ -247,9 +270,9 @@ SkipHooks --> Done - Tailwind:按需扫描pages/components/app目录,启用动画插件。 **章节来源** -- [frontend/package.json:1-40](file://frontend/package.json#L1-L40) +- [frontend/package.json:1-45](file://frontend/package.json#L1-L45) - [frontend/tsconfig.json:1-27](file://frontend/tsconfig.json#L1-L27) -- [frontend/.eslintrc.json:1-4](file://frontend/.eslintrc.json#L1-L4) +- [frontend/.eslintrc.json:1-14](file://frontend/.eslintrc.json#L1-L14) - [frontend/tailwind.config.ts:1-57](file://frontend/tailwind.config.ts#L1-L57) ### Git部署自动化脚本 @@ -286,219 +309,374 @@ SkipHooks --> Done **章节来源** - [README.md:1-3](file://README.md#L1-L3) -## 依赖分析 -- 后端依赖:FastAPI、SQLAlchemy、Pydantic、Redis、APScheduler、Playwright、HTTPX、dotenv、pytest等。 -- 前端依赖:Next.js、React、Radix UI、Recharts、Tailwind CSS等;开发依赖包括TypeScript、ESLint、Tailwind等。 -- 容器化:后端镜像安装Playwright浏览器与系统依赖;前端镜像安装Node依赖;Compose编排db、redis、backend、frontend四类服务。 -- **部署工具**:Git、Docker CLI、Docker Compose等部署相关工具。 +## 代码规范与最佳实践 -```mermaid -graph LR -subgraph "后端" -FastAPI["FastAPI"] -SQLA["SQLAlchemy"] -Pydantic["Pydantic"] -RedisDep["Redis"] -APS["APScheduler"] -PW["Playwright"] -HTTPX["HTTPX"] -DOTENV["python-dotenv"] -PyTest["pytest"] -end -subgraph "前端" -Next["Next.js"] -React["React"] -Radix["Radix UI"] -Recharts["Recharts"] -Tailwind["Tailwind CSS"] -TS["TypeScript"] -ESL["ESLint"] -end -subgraph "部署工具" -Git["Git"] -Docker["Docker CLI"] -DockerCompose["Docker Compose"] -PushScript["push_script.sh"] -end -FastAPI --> SQLA -FastAPI --> Pydantic -FastAPI --> RedisDep -FastAPI --> APS -FastAPI --> PW -FastAPI --> HTTPX -FastAPI --> DOTENV -Next --> React -Next --> Tailwind -Next --> Radix -Next --> Recharts -Next --> TS -Next --> ESL -Docker --> DockerCompose -Docker --> PushScript -Git --> PushScript -``` +### Python代码规范 +- **命名约定** + - 模块与类使用PascalCase(如:UserService、CitationDetector) + - 函数与变量使用snake_case(如:get_user_by_id、process_data) + - 常量使用UPPER_CASE(如:MAX_RETRY_COUNT、DEFAULT_TIMEOUT) + - 私有成员使用单下划线前缀(如:_internal_method) -**图表来源** -- [backend/requirements.txt:1-35](file://backend/requirements.txt#L1-L35) -- [frontend/package.json:11-38](file://frontend/package.json#L11-L38) -- [docker-compose.yml:1-71](file://docker-compose.yml#L1-L71) +- **代码格式化** + - 使用Black进行代码格式化,统一代码风格 + - Pydantic v2进行数据校验与配置管理 + - 字段约束与默认值清晰明确 + +- **类型注解** + - 严格使用类型注解,包括函数参数、返回值和变量声明 + - 使用Union、Optional等类型组合器处理可选类型 + - 利用Generic类型支持泛型编程 + +- **错误处理** + - 对外抛出HTTPException并设置合适的状态码与错误信息 + - 使用try-except捕获特定异常,避免裸except + - 实现统一的异常处理器 + +- **模块化设计** + - API、Schema、Model、Service分层清晰,职责单一 + - 配置通过Pydantic Settings从.env加载,区分开发与生产环境 **章节来源** -- [backend/requirements.txt:1-35](file://backend/requirements.txt#L1-L35) -- [frontend/package.json:1-40](file://frontend/package.json#L1-L40) -- [docker-compose.yml:1-71](file://docker-compose.yml#L1-L71) +- [backend/requirements.txt:1-42](file://backend/requirements.txt#L1-L42) +- [backend/app/config.py:9-46](file://backend/app/config.py#L9-L46) -## 性能考虑 -- 异步化:后端使用异步数据库驱动与异步HTTP客户端,减少阻塞,提升并发能力。 -- 缓存:Redis用于任务调度与会话等场景,建议在热点数据访问处引入缓存层。 -- 任务调度:APScheduler负责周期性任务,注意避免重复任务与资源泄漏,结合优雅停机逻辑。 -- 前端构建:严格模式与按需扫描Tailwind可降低包体与构建开销;生产构建建议开启压缩与Tree Shaking。 -- 数据库:合理索引与查询优化,避免N+1查询;批量写入与事务合并可减少往返次数。 -- **部署性能**:使用push_script.sh的增量构建功能,避免不必要的镜像重建;合理配置Docker构建缓存。 +### TypeScript/React代码规范 +- **命名约定** + - 接口与类型使用PascalCase(如:UserData、ApiResponse) + - 变量与函数使用camelCase(如:getUserData、processFormData) + - 枚举使用UPPER_CASE(如:UserRole.ADMIN) -## 故障排查指南 -- 启动失败(后端):检查数据库与Redis健康状态,确认连接字符串与端口映射正确;查看Uvicorn日志与容器重启策略。 -- 认证异常:核对JWT密钥与过期时间配置;确认请求头携带正确的Bearer Token;检查依赖覆盖与用户mock是否生效。 -- 数据迁移问题:检查Alembic日志级别与钩子配置;确认数据库URL与凭据;必要时手动回滚或修复迁移脚本。 -- 前端样式异常:确认Tailwind content扫描路径与组件目录一致;清理.next缓存后重新构建。 -- 测试失败:确认pytest会话注入后端路径;检查调度器mock与依赖覆盖;使用异步HTTP客户端发起请求。 -- **部署失败**:检查push_script.sh权限设置;确认Git配置与远程仓库访问权限;验证Docker守护进程状态;查看部署日志输出。 +- **类型系统** + - 严格模式开启,禁用输出JS + - 使用bundler解析模块,确保类型安全 + - 路径别名@/*映射根目录,简化导入路径 + +- **组件设计** + - 使用React Hooks管理状态和副作用 + - 实现受控组件模式,确保数据流清晰 + - 组件Props使用TypeScript接口定义 + +- **ESLint配置** + - 继承Next.js核心Web Vitals与TypeScript规则 + - 自定义规则:忽略未使用变量警告,支持下划线前缀 + +**章节来源** +- [frontend/package.json:1-45](file://frontend/package.json#L1-L45) +- [frontend/tsconfig.json:1-27](file://frontend/tsconfig.json#L1-L27) +- [frontend/.eslintrc.json:1-14](file://frontend/.eslintrc.json#L1-L14) + +### 注释规范 +- **Python文档字符串** + - 使用Google风格的docstring格式 + - 函数文档包含:参数说明、返回值、异常说明 + - 类文档包含:构造函数说明、主要方法列表 + +- **TypeScript JSDoc** + - 接口和类型使用JSDoc注释 + - 复杂函数添加详细说明和使用示例 + - 导出的公共API必须有完整注释 + +- **代码注释** + - 重要算法添加算法思路说明 + - 外部依赖添加版本和用途说明 + - 临时解决方案添加TODO注释 + +**章节来源** +- [docs/03-development/coding-standards.md:1-29](file://docs/03-development/coding-standards.md#L1-L29) + +## 开发流程与工作流 + +### Git分支策略 +- **主分支(main)**:保护分支,仅允许通过Pull Request合并 +- **功能分支(feature/*)**:开发新功能,完成后合并到develop +- **发布分支(release/x.y.z)**:用于预发布与回归测试 +- **热修复分支(hotfix/*)**:直接修改main分支并回放至develop + +### 代码评审流程 +- Pull Request必须包含变更说明、测试用例与性能影响评估 +- 至少一名Reviewer同意后方可合并 +- 评审关注点:代码质量、安全性、可维护性与兼容性 + +### 版本发布管理 +- **语义化版本控制**:小版本用于新增功能,补丁版本用于修复 +- **发布前检查**:更新CHANGELOG,运行全量测试,检查依赖安全漏洞 +- **发布后验证**:同步文档与环境配置,监控线上指标 + +**章节来源** +- [docs/03-development/dev-guide.md:1-32](file://docs/03-development/dev-guide.md#L1-L32) + +## 开发工具使用方法 + +### IDE配置 +- **VS Code**:安装Python与TypeScript扩展,启用ESLint与Prettier +- **前端**:启用TypeScript智能提示与ESLint实时检查;Tailwind IntelliSense增强CSS类提示 + +### 调试技巧 +- **后端**:使用Uvicorn的reload选项热重载;在FastAPI中设置调试日志级别 +- **前端**:使用Next.js dev模式热更新;在浏览器开发者工具中检查网络与状态 + +### 性能分析工具 +- **后端**:使用cProfile或py-spy分析CPU与内存;结合APScheduler监控任务耗时 +- **前端**:使用Chrome DevTools Performance面板分析渲染与网络 + +### 部署工具使用 +- **push_script.sh使用**:确保脚本具有执行权限,基本使用./push_script.sh +- **Docker部署**:使用docker-compose up -d启动服务,logs查看日志 + +**章节来源** +- [docs/03-development/dev-guide.md:1-32](file://docs/03-development/dev-guide.md#L1-L32) + +## 新功能开发指导原则 + +### 模块设计 +- 遵循"API-Service-Model"三层架构,保持关注点分离 +- 将业务逻辑封装在Service层,避免在API层直接操作数据库 + +### 接口定义 +- 使用Pydantic模型定义请求与响应结构,明确字段类型与约束 +- 对外暴露RESTful接口,遵循统一的前缀与标签组织路由 + +### 测试要求 +- **单元测试**:覆盖关键业务逻辑与边界条件 +- **集成测试**:使用pytest与AsyncClient发起HTTP请求,验证端到端流程 +- **Mock策略**:对调度器、外部服务与数据库进行合理Mock + +### 部署要求 +- 新功能开发完成后,使用push_script.sh进行部署测试 +- 确保所有环境变量正确配置,包括数据库连接、Redis配置等 + +**章节来源** +- [docs/03-development/dev-guide.md:1-32](file://docs/03-development/dev-guide.md#L1-L32) + +## 测试策略与实施 + +### TDD测试驱动开发 +**新增** GEO平台采用完整的TDD(测试驱动开发)流程: + +#### RED-GREEN-REFACTOR循环 +- **RED阶段**:编写失败测试,验证具体功能点 +- **GREEN阶段**:编写最少量生产代码使测试通过 +- **REFACTOR阶段**:优化代码结构、消除重复、提升可读性 + +#### 测试层次金字塔 +``` + ▲ + /│\ + / │ \ E2E 测试(端到端) + / │ \ 覆盖关键用户旅程 + /───┼───\ 占比:5% + / │ \ + /─────┼─────\ 集成测试 + / │ \ 模块间交互验证 + /───────┼───────\ 占比:15% + / │ \ + /─────────┼─────────\ 单元测试 + / │ \ 单个函数/类验证 + /───────────┼───────────\ 占比:60% + / │ \ + /─────────────┼─────────────\ Agent 测试 + / │ \ Agent 行为验证 + /───────────────┼───────────────\ 占比:20% + ─────────────────────────────────── +``` + +#### 单元测试(Unit Tests) +- **目标**:验证单个函数、类或方法的行为 +- **原则**:FIRST原则(Fast、Independent、Repeatable、Self-validating、Timely) +- **工具**:pytest + unittest.mock + +#### 集成测试(Integration Tests) +- **目标**:验证多个模块之间的交互是否正确 +- **范围**:数据库、缓存、消息队列等真实组件 +- **工具**:pytest + TestClient(FastAPI) + testcontainers + +#### E2E测试(End-to-End Tests) +- **目标**:模拟真实用户操作,验证完整业务流程 +- **工具**:Playwright(前端)+ pytest(后端 API) + +#### Agent测试(Agent Tests) +- **目标**:验证 AI Agent 的行为和输出质量 +- **特殊要求**:使用固定测试输入,验证输出结构和质量 + +**章节来源** +- [docs/03-development/tdd-workflow.md:1-583](file://docs/03-development/tdd-workflow.md#L1-L583) + +### 测试覆盖要求 +- **单元测试**:>= 80%覆盖率 +- **集成测试**:覆盖所有API端点 +- **E2E测试**:覆盖所有P0用户旅程 +- **Agent测试**:覆盖核心场景 + +### 测试数据管理 +- **Fixtures**:使用pytest.fixture管理测试数据 +- **工厂模式**:复杂对象使用工厂函数创建 +- **数据清理**:每个测试前后清理数据,失败时回滚 + +**章节来源** +- [docs/04-testing/test-strategy.md:1-33](file://docs/04-testing/test-strategy.md#L1-L33) + +## 部署管理 + +### 部署架构 +**新增** GEO平台支持多环境部署: + +#### 开发环境部署 +- 使用本地Docker Compose启动 +- 开发数据库和Redis实例 +- 支持热重载和调试模式 + +#### 测试环境部署 +- 使用独立的测试数据库 +- 配置测试专用的API密钥 +- 自动化测试流水线集成 + +#### 生产环境部署 +- 使用Nginx反向代理 +- 配置SSL证书和域名 +- 负载均衡和滚动更新 + +### 部署检查清单 +- **环境配置**:数据库连接、Redis配置、API密钥 +- **服务健康**:容器状态、端口映射、网络连通性 +- **数据迁移**:Alembic迁移执行、数据完整性检查 +- **安全配置**:JWT密钥、CORS配置、SSL证书 + +**章节来源** +- [docs/05-deployment/deployment-guide.md:1-32](file://docs/05-deployment/deployment-guide.md#L1-L32) + +## 常见问题与解决方案 + +### 数据库连接失败 +- 检查PostgreSQL容器健康状态与端口映射 +- 确认DATABASE_URL与凭据 + +### Redis连接失败 +- 检查Redis容器健康状态与端口映射 +- 确认REDIS_URL + +### Playwright无法启动浏览器 +- 确认Dockerfile中已安装Playwright浏览器与系统依赖 +- 检查PLAYWRIGHT_BROWSERS_PATH + +### CORS跨域问题 +- 核对CORS中间件配置的allow_origins与headers +- 确保前端域名与端口匹配 + +### JWT认证失败 +- 检查JWT_SECRET与过期时间 +- 确认请求头Authorization格式为Bearer Token + +### 测试失败排查 +- **单元测试**:检查Mock配置和依赖注入 +- **集成测试**:验证数据库连接和事务处理 +- **E2E测试**:检查浏览器自动化和页面元素定位 + +### 性能问题诊断 +- **后端**:使用cProfile分析CPU使用率,检查数据库查询 +- **前端**:使用Chrome DevTools分析渲染性能,检查组件重渲染 **章节来源** - [docker-compose.yml:4-34](file://docker-compose.yml#L4-L34) -- [backend/app/config.py:7-13](file://backend/app/config.py#L7-L13) +- [backend/app/config.py:12-18](file://backend/app/config.py#L12-L18) - [tests/conftest.py:19-50](file://tests/conftest.py#L19-L50) - [backend/alembic.ini:115-150](file://backend/alembic.ini#L115-L150) - [frontend/tailwind.config.ts:5-9](file://frontend/tailwind.config.ts#L5-L9) ## 结论 -本指南基于仓库现有实现,给出了统一的代码规范、开发流程与工具使用建议。建议在后续迭代中补充更详细的Git分支策略、代码评审清单与发布流程文档,并持续完善测试覆盖率与性能监控体系。**新增的部署脚本push_script.sh显著提升了开发者的部署效率,建议在团队内部推广使用并定期更新其功能特性。** +本指南基于仓库现有实现,建立了完整的开发文档体系,包括代码规范、开发流程、测试策略和部署管理等核心内容。建议在后续迭代中持续完善文档内容,补充更详细的Git分支策略、代码评审清单与发布流程文档,并持续完善测试覆盖率与性能监控体系。 + +**更新** 新增的开发文档体系显著提升了项目的规范化程度,为团队协作和项目维护奠定了坚实基础。 ## 附录 -### 代码规范与最佳实践 +### 技术栈说明 +**新增** GEO平台采用现代化技术栈: -- **Python(后端)** - - 使用Pydantic v2进行数据校验与配置管理,字段约束与默认值清晰明确。 - - 异步编程:优先使用异步数据库与HTTP客户端,避免阻塞操作。 - - 错误处理:对外抛出HTTPException并设置合适的状态码与错误信息。 - - 模块化:API、Schema、Model、Service分层清晰,职责单一。 - - 配置:通过Pydantic Settings从.env加载配置,区分开发与生产环境。 +#### 前端技术栈 +- **Next.js 14**:React框架,支持SSR和静态生成 +- **TypeScript**:强类型语言,提升代码质量和开发体验 +- **Tailwind CSS**:原子化CSS框架,快速构建UI界面 +- **shadcn/ui**:高质量组件库,支持主题定制 +- **NextAuth.js**:认证解决方案,支持多种登录方式 -- **TypeScript(前端)** - - 严格模式开启,禁用输出JS,使用bundler解析模块,确保类型安全。 - - ESLint规则继承Next.js核心Web Vitals与TypeScript默认规则,保持一致性。 - - Tailwind按需扫描组件与页面目录,减少CSS体积;启用动画插件提升交互体验。 - - 路径别名@/*映射根目录,简化导入路径。 +#### 后端技术栈 +- **FastAPI**:高性能异步Web框架 +- **Python 3.12**:类型提示最佳实践 +- **SQLAlchemy 2.0**:ORM对象关系映射 +- **Alembic**:数据库迁移管理 +- **Celery**:异步任务队列(可选) +- **Redis**:缓存与消息代理 -- **命名约定** - - Python:模块与类使用PascalCase;函数与变量使用snake_case;常量使用UPPER_CASE。 - - TypeScript:接口与类型使用PascalCase;变量与函数使用camelCase;枚举使用UPPER_CASE。 +#### AI Agent技术栈 +- **Agent框架**:可扩展的AI代理框架 +- **LLM模型**:支持多种大语言模型 +- **提示工程**:结构化的提示模板管理 +- **向量数据库**:可选的向量相似度检索 -- **部署脚本规范** - - 使用push_script.sh进行标准化部署,避免手动操作导致的不一致。 - - 遵循语义化版本控制,合理选择版本类型(patch/minor/major)。 - - 在团队内统一部署流程,确保所有成员使用相同的部署脚本参数。 - -### 开发流程与工作流 - -- **Git分支策略(建议)** - - 主分支:保护分支,仅允许通过PR合并。 - - 功能分支:feature/xxx,完成后合并到develop。 - - 发布分支:release/x.y.z,用于预发布与回归测试。 - - 热修复分支:hotfix/xxx,直接修改主分支并回放至develop。 - -- **代码评审(建议)** - - PR必须包含变更说明、测试用例与性能影响评估。 - - 至少一名Reviewer同意后方可合并。 - - 评审关注点:代码质量、安全性、可维护性与兼容性。 - -- **版本发布管理(建议)** - - 语义化版本:小版本用于新增功能,补丁版本用于修复。 - - 发布前:更新CHANGELOG,运行全量测试,检查依赖安全漏洞。 - - 发布后:同步文档与环境配置,监控线上指标。 - - **使用push_script.sh自动化版本标记与发布流程**。 - -### 开发工具使用方法 - -- **IDE配置(建议)** - - VS Code:安装Python与TypeScript扩展,启用ESLint与Prettier;配置Python解释器为虚拟环境。 - - 前端:启用TypeScript智能提示与ESLint实时检查;Tailwind IntelliSense增强CSS类提示。 - -- **调试技巧** - - 后端:使用Uvicorn的reload选项热重载;在FastAPI中设置调试日志级别;利用依赖注入覆盖与mock替换真实外部服务。 - - 前端:使用Next.js dev模式热更新;在浏览器开发者工具中检查网络与状态;Tailwind调试辅助类辅助布局。 - -- **性能分析工具(建议)** - - 后端:使用cProfile或py-spy分析CPU与内存;结合APScheduler监控任务耗时。 - - 前端:使用Chrome DevTools Performance面板分析渲染与网络;使用Lighthouse评估SEO与可访问性。 - -- **部署工具使用方法** - - **push_script.sh使用**: - - 确保脚本具有执行权限:chmod +x push_script.sh - - 基本使用:./push_script.sh - - 指定版本类型:./push_script.sh patch/minor/major - - 指定环境:./push_script.sh -e development/production - - 查看帮助:./push_script.sh -h - - **Docker部署**: - - 使用docker-compose up -d启动服务 - - 使用docker-compose down停止服务 - - 使用docker-compose logs查看日志 - -### 新功能开发指导原则 - -- **模块设计** - - 遵循"API-Service-Model"三层架构,保持关注点分离。 - - 将业务逻辑封装在Service层,避免在API层直接操作数据库。 - -- **接口定义** - - 使用Pydantic模型定义请求与响应结构,明确字段类型与约束。 - - 对外暴露RESTful接口,遵循统一的前缀与标签组织路由。 - -- **测试要求** - - 单元测试:覆盖关键业务逻辑与边界条件。 - - 集成测试:使用pytest与AsyncClient发起HTTP请求,验证端到端流程。 - - Mock策略:对调度器、外部服务与数据库进行合理Mock,保证测试稳定性。 - -- **部署要求** - - 新功能开发完成后,使用push_script.sh进行部署测试。 - - 确保所有环境变量正确配置,包括数据库连接、Redis配置等。 - - 部署前进行完整的功能测试和性能测试。 - -### 常见问题与解决方案 - -- **数据库连接失败** - - 检查PostgreSQL容器健康状态与端口映射;确认DATABASE_URL与凭据。 - -- **Redis连接失败** - - 检查Redis容器健康状态与端口映射;确认REDIS_URL。 - -- **Playwright无法启动浏览器** - - 确认Dockerfile中已安装Playwright浏览器与系统依赖;检查PLAYWRIGHT_BROWSERS_PATH。 - -- **CORS跨域问题** - - 核对CORS中间件配置的allow_origins与headers;确保前端域名与端口匹配。 - -- **JWT认证失败** - - 检查JWT_SECRET与过期时间;确认请求头Authorization格式为Bearer Token。 - -- **部署脚本执行失败** - - 检查脚本权限:chmod +x push_script.sh - - 确认Git配置:git config --global user.name 和 git config --global user.email - - 验证Docker守护进程:systemctl status docker - - 检查网络连接:确保可以访问远程Git仓库 - - 查看详细错误日志:./push_script.sh -v - -- **Docker构建失败** - - 清理Docker缓存:docker system prune - - 检查Dockerfile语法:docker build --no-cache -t geo-app . - - 确认网络连接:代理设置或防火墙配置 - - 检查磁盘空间:清理不必要的镜像和容器 +#### 基础设施技术栈 +- **Docker**:容器化部署 +- **Docker Compose**:服务编排 +- **PostgreSQL**:关系型数据库 +- **Redis集群**:生产环境缓存 +- **Nginx**:反向代理与负载均衡 +- **日志收集**:集中化日志管理 **章节来源** -- [backend/app/main.py:30-36](file://backend/app/main.py#L30-L36) -- [backend/app/config.py:9-13](file://backend/app/config.py#L9-L13) -- [backend/Dockerfile:31-33](file://backend/Dockerfile#L31-L33) -- [docker-compose.yml:4-20](file://docker-compose.yml#L4-L20) -- [docker-compose.yml:22-34](file://docker-compose.yml#L22-L34) -- [README.md:1-3](file://README.md#L1-L3) \ No newline at end of file +- [docs/00-project/tech-stack.md:1-71](file://docs/00-project/tech-stack.md#L1-L71) + +### 模块指南 +**新增** 为不同模块提供专门的开发指导: + +#### Agent框架开发 +- **Agent设计原则**:单一职责、可扩展性、可测试性 +- **提示工程**:结构化提示模板设计 +- **模型集成**:统一的LLM调用接口 +- **错误处理**:健壮的异常处理机制 + +#### API开发规范 +- **路由设计**:RESTful API设计原则 +- **错误处理**:统一的错误响应格式 +- **文档生成**:OpenAPI规范自动生成 +- **版本控制**:API版本管理策略 + +#### 数据模型设计 +- **ORM映射**:SQLAlchemy模型定义 +- **关系设计**:实体关系建模 +- **索引优化**:数据库性能优化 +- **数据迁移**:版本化的数据库变更 + +**章节来源** +- [docs/03-development/module-guides/](file://docs/03-development/module-guides/) + +### 开发环境搭建 +**新增** 详细的环境搭建步骤: + +#### 系统要求 +- **操作系统**:Windows 10+/macOS 10.15+/Linux Ubuntu 18.04+ +- **内存**:至少8GB RAM(推荐16GB+) +- **存储**:至少20GB可用空间 +- **网络**:稳定的互联网连接 + +#### 开发工具 +- **Python**:3.12+(推荐使用pyenv管理版本) +- **Node.js**:18.x LTS版本 +- **Docker**:20.10+(包含Docker Compose) +- **Git**:2.0+ +- **IDE**:VS Code + 推荐插件 + +#### 环境变量配置 +- **数据库连接**:DATABASE_URL +- **Redis配置**:REDIS_URL +- **JWT配置**:JWT_SECRET、JWT_EXPIRE_HOURS +- **LLM配置**:各种AI平台API密钥 + +#### 本地开发工作流 +1. 克隆仓库并安装依赖 +2. 配置环境变量文件 +3. 启动Docker容器 +4. 初始化数据库 +5. 开始开发和测试 + +**章节来源** +- [docs/03-development/dev-guide.md:1-32](file://docs/03-development/dev-guide.md#L1-L32) \ No newline at end of file diff --git a/.qoder/repowiki/zh/content/扩展与定制/扩展与定制.md b/.qoder/repowiki/zh/content/扩展与定制/扩展与定制.md index 32f82ff..1b3d7ef 100644 --- a/.qoder/repowiki/zh/content/扩展与定制/扩展与定制.md +++ b/.qoder/repowiki/zh/content/扩展与定制/扩展与定制.md @@ -8,6 +8,7 @@ - [backend/app/api/queries.py](file://backend/app/api/queries.py) - [backend/app/api/reports.py](file://backend/app/api/reports.py) - [backend/app/api/citations.py](file://backend/app/api/citations.py) +- [backend/app/api/agents.py](file://backend/app/api/agents.py) - [backend/app/models/query.py](file://backend/app/models/query.py) - [backend/app/schemas/query.py](file://backend/app/schemas/query.py) - [backend/app/workers/scheduler.py](file://backend/app/workers/scheduler.py) @@ -28,13 +29,29 @@ - [frontend/app/layout.tsx](file://frontend/app/layout.tsx) - [frontend/components/providers.tsx](file://frontend/components/providers.tsx) - [frontend/lib/api.ts](file://frontend/lib/api.ts) +- [frontend/lib/api/agents.ts](file://frontend/lib/api/agents.ts) - [frontend/package.json](file://frontend/package.json) - [docker-compose.yml](file://docker-compose.yml) - [backend/Dockerfile](file://backend/Dockerfile) - [frontend/Dockerfile](file://frontend/Dockerfile) - [backend/alembic/versions/488d0bd5ab01_initial_migration.py](file://backend/alembic/versions/488d0bd5ab01_initial_migration.py) +- [backend/app/agent_framework/registry.py](file://backend/app/agent_framework/registry.py) +- [backend/app/agent_framework/config_manager.py](file://backend/app/agent_framework/config_manager.py) +- [backend/app/agent_framework/dispatcher.py](file://backend/app/agent_framework/dispatcher.py) +- [backend/app/agent_framework/protocol.py](file://backend/app/agent_framework/protocol.py) +- [backend/app/agent_framework/pipeline/engine.py](file://backend/app/agent_framework/pipeline/engine.py) +- [backend/app/models/agent.py](file://backend/app/models/agent.py) +- [.env.example](file://.env.example) +## 更新摘要 +**所做更改** +- 新增了智能体框架扩展指南,包括 Agent 注册中心、配置管理和任务调度 +- 扩展了前端 API 封装,新增 agents 模块的完整实现 +- 更新了配置定制方法,增加了 LLM 提供商配置和 AI 平台集成 +- 完善了第三方集成方案,涵盖智能体系统、Redis 集成和管道编排 +- 增加了系统定制化案例研究和实施建议 + ## 目录 1. [简介](#简介) 2. [项目结构](#项目结构) @@ -48,18 +65,22 @@ 10. [附录](#附录) ## 简介 -本文件面向需要对 GEO 平台进行扩展与定制的工程师与产品团队,系统性阐述后端 API 扩展、前端页面扩展、数据模型扩展、配置定制、第三方集成(AI 平台、数据库、认证)以及插件化扩展的最佳实践。文档同时提供可落地的实施建议与案例研究,帮助快速实现业务定制化目标。 +本文件面向需要对 GEO 平台进行扩展与定制的工程师与产品团队,系统性阐述后端 API 扩展、前端页面扩展、数据模型扩展、配置定制、第三方集成(AI 平台、数据库、认证)以及智能体框架扩展的最佳实践。文档同时提供可落地的实施建议与案例研究,帮助快速实现业务定制化目标。 + +**更新** 本次更新重点加强了智能体框架的扩展能力,新增了完整的 Agent 管理、配置热更新、任务调度和管道编排功能。 ## 项目结构 GEO 采用前后端分离架构: - 后端基于 FastAPI,提供 REST API;通过 Alembic 管理数据库迁移;使用 SQLAlchemy ORM 定义模型;APScheduler 实现定时任务;Playwright 支持 AI 平台网页抓取。 - 前端基于 Next.js 14,使用 TypeScript、TailwindCSS、Radix UI 组件库;通过自定义 API 封装层与后端交互;NextAuth v4 提供会话管理。 +- **新增** 智能体框架支持,包括 Agent 注册中心、配置管理、任务调度和管道编排。 ```mermaid graph TB subgraph "前端" FE_APP["Next.js 应用
路由与页面"] FE_LIB["API 封装
lib/api.ts"] +FE_LIB_AGENTS["智能体API
lib/api/agents.ts"] FE_PROV["会话提供者
components/providers.tsx"] end subgraph "后端" @@ -68,51 +89,69 @@ BE_ROUTER_AUTH["认证路由
app/api/auth.py"] BE_ROUTER_QUERIES["查询路由
app/api/queries.py"] BE_ROUTER_CITATIONS["引用路由
app/api/citations.py"] BE_ROUTER_REPORTS["报告路由
app/api/reports.py"] +BE_ROUTER_AGENTS["智能体路由
app/api/agents.py"] BE_SCHED["调度器
app/workers/scheduler.py"] BE_PLAT_BASE["平台适配器基类
app/workers/platforms/base.py"] BE_PLAT_KIMI["Kimi 适配器
app/workers/platforms/kimi.py"] BE_PLAT_WENXIN["文心一言适配器
app/workers/platforms/wenxin.py"] BE_DB["数据库与模型
app/database.py + models/*"] +BE_AGENT_REGISTRY["Agent注册中心
agent_framework/registry.py"] +BE_AGENT_CONFIG["配置管理
agent_framework/config_manager.py"] +BE_AGENT_DISPATCH["任务调度
agent_framework/dispatcher.py"] +BE_AGENT_PIPELINE["管道引擎
agent_framework/pipeline/engine.py"] end FE_APP --> FE_LIB FE_LIB --> BE_MAIN +FE_LIB_AGENTS --> BE_ROUTER_AGENTS BE_MAIN --> BE_ROUTER_AUTH BE_MAIN --> BE_ROUTER_QUERIES BE_MAIN --> BE_ROUTER_CITATIONS BE_MAIN --> BE_ROUTER_REPORTS +BE_MAIN --> BE_ROUTER_AGENTS BE_MAIN --> BE_SCHED BE_SCHED --> BE_PLAT_BASE BE_PLAT_BASE --> BE_PLAT_KIMI BE_PLAT_BASE --> BE_PLAT_WENXIN BE_MAIN --> BE_DB +BE_ROUTER_AGENTS --> BE_AGENT_REGISTRY +BE_ROUTER_AGENTS --> BE_AGENT_CONFIG +BE_ROUTER_AGENTS --> BE_AGENT_DISPATCH +BE_AGENT_DISPATCH --> BE_AGENT_PIPELINE ``` -图表来源 +**图表来源** - [backend/app/main.py:1-48](file://backend/app/main.py#L1-L48) - [frontend/lib/api.ts:1-58](file://frontend/lib/api.ts#L1-L58) +- [frontend/lib/api/agents.ts:1-57](file://frontend/lib/api/agents.ts#L1-L57) - [backend/app/workers/scheduler.py:1-95](file://backend/app/workers/scheduler.py#L1-L95) - [backend/app/workers/platforms/base.py:1-18](file://backend/app/workers/platforms/base.py#L1-L18) - [backend/app/workers/platforms/kimi.py:1-206](file://backend/app/workers/platforms/kimi.py#L1-L206) - [backend/app/workers/platforms/wenxin.py:1-205](file://backend/app/workers/platforms/wenxin.py#L1-L205) - [backend/app/database.py](file://backend/app/database.py) +- [backend/app/agent_framework/registry.py:1-219](file://backend/app/agent_framework/registry.py#L1-L219) +- [backend/app/agent_framework/config_manager.py:1-191](file://backend/app/agent_framework/config_manager.py#L1-L191) +- [backend/app/agent_framework/dispatcher.py:1-367](file://backend/app/agent_framework/dispatcher.py#L1-L367) +- [backend/app/agent_framework/pipeline/engine.py:1-376](file://backend/app/agent_framework/pipeline/engine.py#L1-L376) -章节来源 +**章节来源** - [backend/app/main.py:1-48](file://backend/app/main.py#L1-L48) - [frontend/app/layout.tsx:1-37](file://frontend/app/layout.tsx#L1-L37) - [frontend/components/providers.tsx:1-9](file://frontend/components/providers.tsx#L1-L9) ## 核心组件 -- API 层:认证、查询词、引用数据、报告导出等模块化路由,统一挂载于主应用。 -- 服务层:封装业务逻辑,如用户认证、查询 CRUD、引用处理等。 -- 数据层:SQLAlchemy 模型与 Pydantic Schema,定义实体与请求/响应结构。 -- 工作器与调度:APScheduler 驱动定时任务,CitationEngine 协调平台适配器执行查询。 -- 前端:Next.js 页面与组件,通过 lib/api.ts 统一访问后端接口;NextAuth 提供会话状态。 +- API 层:认证、查询词、引用数据、报告导出、**新增**智能体管理等模块化路由,统一挂载于主应用。 +- 服务层:封装业务逻辑,如用户认证、查询 CRUD、引用处理、**新增**智能体配置管理等。 +- 数据层:SQLAlchemy 模型与 Pydantic Schema,定义实体与请求/响应结构,**新增**智能体相关模型。 +- 工作器与调度:APScheduler 驱动定时任务,CitationEngine 协调平台适配器执行查询,**新增**智能体任务调度。 +- 前端:Next.js 页面与组件,通过 lib/api.ts 统一访问后端接口,**新增**智能体 API 封装。 +- **新增** 智能体框架:Agent 注册中心、配置管理、任务调度和管道编排系统。 -章节来源 +**章节来源** - [backend/app/api/auth.py:1-43](file://backend/app/api/auth.py#L1-L43) - [backend/app/api/queries.py:1-86](file://backend/app/api/queries.py#L1-L86) - [backend/app/api/citations.py](file://backend/app/api/citations.py) - [backend/app/api/reports.py](file://backend/app/api/reports.py) +- [backend/app/api/agents.py:1-299](file://backend/app/api/agents.py#L1-L299) - [backend/app/services/auth.py](file://backend/app/services/auth.py) - [backend/app/services/query.py](file://backend/app/services/query.py) - [backend/app/services/citation.py](file://backend/app/services/citation.py) @@ -120,9 +159,10 @@ BE_MAIN --> BE_DB - [backend/app/schemas/query.py:1-94](file://backend/app/schemas/query.py#L1-L94) - [backend/app/workers/scheduler.py:1-95](file://backend/app/workers/scheduler.py#L1-L95) - [frontend/lib/api.ts:1-58](file://frontend/lib/api.ts#L1-L58) +- [frontend/lib/api/agents.ts:1-57](file://frontend/lib/api/agents.ts#L1-L57) ## 架构总览 -下图展示从浏览器到后端 API、数据库与外部 AI 平台的完整链路: +下图展示从浏览器到后端 API、数据库与外部 AI 平台的完整链路,包括新增的智能体框架: ```mermaid sequenceDiagram @@ -134,9 +174,12 @@ participant DB as "数据库" participant Scheduler as "调度器" participant Engine as "CitationEngine" participant Plat as "平台适配器" +participant AgentFramework as "智能体框架" Browser->>Frontend : 用户操作 Frontend->>API : 发起 HTTP 请求 API->>Svc : 路由分发与校验 +svc->>AgentFramework : 智能体管理请求 +AgentFramework->>DB : 读写智能体配置 Svc->>DB : 读写数据 DB-->>Svc : 返回结果 Svc-->>API : 业务结果 @@ -148,13 +191,17 @@ Plat-->>Engine : 返回原始响应 Engine->>DB : 写入引用记录 ``` -图表来源 +**图表来源** - [frontend/lib/api.ts:1-58](file://frontend/lib/api.ts#L1-L58) +- [frontend/lib/api/agents.ts:1-57](file://frontend/lib/api/agents.ts#L1-L57) - [backend/app/main.py:1-48](file://backend/app/main.py#L1-L48) - [backend/app/workers/scheduler.py:1-95](file://backend/app/workers/scheduler.py#L1-L95) - [backend/app/workers/platforms/base.py:1-18](file://backend/app/workers/platforms/base.py#L1-L18) - [backend/app/workers/platforms/kimi.py:1-206](file://backend/app/workers/platforms/kimi.py#L1-L206) - [backend/app/workers/platforms/wenxin.py:1-205](file://backend/app/workers/platforms/wenxin.py#L1-L205) +- [backend/app/agent_framework/registry.py:1-219](file://backend/app/agent_framework/registry.py#L1-L219) +- [backend/app/agent_framework/config_manager.py:1-191](file://backend/app/agent_framework/config_manager.py#L1-L191) +- [backend/app/agent_framework/dispatcher.py:1-367](file://backend/app/agent_framework/dispatcher.py#L1-L367) ## 详细组件分析 @@ -169,6 +216,7 @@ Engine->>DB : 写入引用记录 - 示例参考路径 - [认证路由示例:1-43](file://backend/app/api/auth.py#L1-L43) - [查询路由示例:1-86](file://backend/app/api/queries.py#L1-L86) + - [智能体路由示例:1-299](file://backend/app/api/agents.py#L1-L299) - [主应用挂载示例:38-42](file://backend/app/main.py#L38-L42) - [服务层示例](file://backend/app/services/query.py) - [Schema 示例:1-94](file://backend/app/schemas/query.py#L1-L94) @@ -186,10 +234,11 @@ Alembic --> Test["编写单元测试"] Test --> End(["完成"]) ``` -章节来源 +**章节来源** - [backend/app/main.py:38-42](file://backend/app/main.py#L38-L42) - [backend/app/api/auth.py:1-43](file://backend/app/api/auth.py#L1-L43) - [backend/app/api/queries.py:1-86](file://backend/app/api/queries.py#L1-L86) +- [backend/app/api/agents.py:1-299](file://backend/app/api/agents.py#L1-L299) - [backend/app/schemas/query.py:1-94](file://backend/app/schemas/query.py#L1-L94) - [backend/app/models/query.py:1-55](file://backend/app/models/query.py#L1-L55) @@ -200,6 +249,7 @@ Test --> End(["完成"]) - 在 components/ui 下新增或复用 UI 组件,保持一致的设计语言。 - API 调用 - 在 frontend/lib/api.ts 中新增方法,遵循现有命名与错误处理模式。 + - **新增** 在 frontend/lib/api/agents.ts 中新增智能体相关 API 方法。 - 在页面中通过 hooks 或直接调用 api.* 方法获取数据。 - 会话与权限 - 使用 frontend/components/providers.tsx 包裹应用,确保 NextAuth 会话可用。 @@ -210,13 +260,15 @@ flowchart TD NewPage["新增页面
frontend/app/(group)/new/page.tsx"] --> Layout["布局与 Providers
frontend/app/layout.tsx"] Layout --> UI["UI 组件
frontend/components/ui/*"] UI --> API["API 封装
frontend/lib/api.ts"] -API --> Backend["后端 API
backend/app/api/*"] +API --> AgentsAPI["智能体API
frontend/lib/api/agents.ts"] +AgentsAPI --> Backend["后端 API
backend/app/api/*"] ``` -章节来源 +**章节来源** - [frontend/app/layout.tsx:1-37](file://frontend/app/layout.tsx#L1-L37) - [frontend/components/providers.tsx:1-9](file://frontend/components/providers.tsx#L1-L9) - [frontend/lib/api.ts:1-58](file://frontend/lib/api.ts#L1-L58) +- [frontend/lib/api/agents.ts:1-57](file://frontend/lib/api/agents.ts#L1-L57) ### 数据模型扩展指南 - 字段与约束 @@ -262,16 +314,37 @@ string platform text raw_response timestamp created_at } +AGENT_REGISTRY { +uuid id PK +string name UK +string agent_type +string status +jsonb capabilities +timestamp last_heartbeat +timestamp created_at +timestamp updated_at +} +AGENT_CONFIGS { +uuid id PK +uuid agent_id FK +string config_key +jsonb config_value +uuid updated_by FK +timestamp updated_at +} QUERIES ||--o{ CITATION_RECORDS : "包含" USERS ||--o{ QUERIES : "拥有" +AGENT_REGISTRY ||--o{ AGENT_CONFIGS : "包含" ``` -图表来源 +**图表来源** - [backend/app/models/query.py:1-55](file://backend/app/models/query.py#L1-L55) +- [backend/app/models/agent.py:1-206](file://backend/app/models/agent.py#L1-L206) - [backend/alembic/versions/488d0bd5ab01_initial_migration.py](file://backend/alembic/versions/488d0bd5ab01_initial_migration.py) -章节来源 +**章节来源** - [backend/app/models/query.py:1-55](file://backend/app/models/query.py#L1-L55) +- [backend/app/models/agent.py:1-206](file://backend/app/models/agent.py#L1-L206) - [backend/app/schemas/query.py:1-94](file://backend/app/schemas/query.py#L1-L94) - [backend/alembic/versions/488d0bd5ab01_initial_migration.py](file://backend/alembic/versions/488d0bd5ab01_initial_migration.py) @@ -279,19 +352,22 @@ USERS ||--o{ QUERIES : "拥有" - 环境变量 - 通过 app/config.py 的 Settings 类集中管理,支持 .env 文件覆盖。 - 关键配置项包括数据库连接、Redis、JWT 密钥与过期时间、Playwright 浏览器路径、第三方平台密钥等。 + - **新增** LLM 提供商配置,包括默认提供商、模型选择和 API 密钥管理。 - 功能开关与性能参数 - 平台列表、频率策略、状态枚举在 Schema 中集中校验,便于扩展与限制。 - 调度周期(每小时)可在 app/workers/scheduler.py 中调整。 - 前端 NEXT_PUBLIC_API_URL 控制后端域名,lib/api.ts 中统一拼接。 + - **新增** 智能体框架配置,包括 Redis URL 和心跳超时设置。 - 建议 - 生产环境务必替换默认密钥与数据库密码。 - 将敏感信息放入 .env 并加入 .gitignore。 -章节来源 -- [backend/app/config.py:1-17](file://backend/app/config.py#L1-L17) +**章节来源** +- [backend/app/config.py:1-46](file://backend/app/config.py#L1-L46) - [backend/app/schemas/query.py:6-8](file://backend/app/schemas/query.py#L6-L8) - [backend/app/workers/scheduler.py:32-38](file://backend/app/workers/scheduler.py#L32-L38) - [frontend/lib/api.ts:1](file://frontend/lib/api.ts#L1) +- [.env.example:1-35](file://.env.example#L1-L35) ### 第三方集成扩展指南 @@ -325,12 +401,12 @@ BasePlatformAdapter <|-- KimiAdapter BasePlatformAdapter <|-- WenxinAdapter ``` -图表来源 +**图表来源** - [backend/app/workers/platforms/base.py:1-18](file://backend/app/workers/platforms/base.py#L1-L18) - [backend/app/workers/platforms/kimi.py:1-206](file://backend/app/workers/platforms/kimi.py#L1-L206) - [backend/app/workers/platforms/wenxin.py:1-205](file://backend/app/workers/platforms/wenxin.py#L1-L205) -章节来源 +**章节来源** - [backend/app/workers/platforms/base.py:1-18](file://backend/app/workers/platforms/base.py#L1-L18) - [backend/app/workers/platforms/kimi.py:1-206](file://backend/app/workers/platforms/kimi.py#L1-L206) - [backend/app/workers/platforms/wenxin.py:1-205](file://backend/app/workers/platforms/wenxin.py#L1-L205) @@ -343,7 +419,7 @@ BasePlatformAdapter <|-- WenxinAdapter - 在 requirements.txt 中替换驱动包。 - 重新生成/更新 Alembic 迁移以适配新方言。 -章节来源 +**章节来源** - [backend/app/database.py](file://backend/app/database.py) - [backend/app/config.py:7](file://backend/app/config.py#L7) - [backend/requirements.txt:5-8](file://backend/requirements.txt#L5-L8) @@ -357,26 +433,91 @@ BasePlatformAdapter <|-- WenxinAdapter - 保持 Authorization 头格式与后端解析一致。 - 在 app/api/deps.py 中的依赖注入中校验用户身份。 -章节来源 +**章节来源** - [backend/app/services/auth.py](file://backend/app/services/auth.py) - [frontend/components/providers.tsx:1-9](file://frontend/components/providers.tsx#L1-L9) - [frontend/lib/api.ts:3-21](file://frontend/lib/api.ts#L3-L21) - [backend/app/api/deps.py](file://backend/app/api/deps.py) +#### 智能体框架集成 +- Agent 注册中心 + - 通过 AgentRegistry 管理 Agent 的注册、发现与状态。 + - 支持心跳检测与自动离线标记。 +- 配置管理 + - AgentConfigManager 支持配置的热更新与批量修改。 + - 提供配置历史查询功能。 +- 任务调度 + - TaskDispatcher 通过 Redis Queue 实现任务分发。 + - 支持任务取消、状态查询和日志记录。 +- 管道编排 + - PipelineEngine 支持 YAML 定义的多阶段任务编排。 + - 实现拓扑排序、变量传递和条件执行。 + +```mermaid +classDiagram +class AgentRegistry { ++register(capability, endpoint) str ++unregister(agent_name) ++update_heartbeat(agent_name) ++get_agent(agent_name) dict ++list_agents(agent_type, status) list ++get_available_agent(task_type) str ++check_health() +} +class AgentConfigManager { ++get_config(agent_name) dict ++set_config(agent_name, key, value, updated_by) ++bulk_update_config(agent_name, configs, updated_by) ++get_config_history(agent_name, key) list +} +class TaskDispatcher { ++dispatch(task, organization_id, created_by) str ++cancel_task(task_id) ++get_task_status(task_id) dict ++handle_result(result) ++handle_progress(progress) ++retry_failed_tasks(max_retries) +} +class PipelineEngine { ++execute(pipeline, context) PipelineResult ++_topological_sort(stages) list ++dry_run_stage(stage, resolved_inputs) StageResult +} +AgentRegistry <.. TaskDispatcher : "任务分配" +AgentConfigManager <.. TaskDispatcher : "配置管理" +TaskDispatcher <.. PipelineEngine : "任务执行" +``` + +**图表来源** +- [backend/app/agent_framework/registry.py:1-219](file://backend/app/agent_framework/registry.py#L1-L219) +- [backend/app/agent_framework/config_manager.py:1-191](file://backend/app/agent_framework/config_manager.py#L1-L191) +- [backend/app/agent_framework/dispatcher.py:1-367](file://backend/app/agent_framework/dispatcher.py#L1-L367) +- [backend/app/agent_framework/pipeline/engine.py:1-376](file://backend/app/agent_framework/pipeline/engine.py#L1-L376) + +**章节来源** +- [backend/app/agent_framework/registry.py:1-219](file://backend/app/agent_framework/registry.py#L1-L219) +- [backend/app/agent_framework/config_manager.py:1-191](file://backend/app/agent_framework/config_manager.py#L1-L191) +- [backend/app/agent_framework/dispatcher.py:1-367](file://backend/app/agent_framework/dispatcher.py#L1-L367) +- [backend/app/agent_framework/pipeline/engine.py:1-376](file://backend/app/agent_framework/pipeline/engine.py#L1-L376) + ### 插件系统使用指南与最佳实践 - 插件化思路 - - 平台适配器采用“插件”式扩展:通过继承基类与工厂/映射注册,实现多平台并行。 - - 调度器与 CitationEngine 作为“核心引擎”,通过适配器接口解耦平台差异。 + - 平台适配器采用"插件"式扩展:通过继承基类与工厂/映射注册,实现多平台并行。 + - 调度器与 CitationEngine 作为"核心引擎",通过适配器接口解耦平台差异。 + - **新增** 智能体框架采用注册中心模式,支持动态 Agent 注册与发现。 - 最佳实践 - 明确职责边界:路由负责协议与鉴权,服务层负责业务规则,模型负责数据结构。 - 统一错误处理:前端统一捕获 HTTP 错误并提示;后端抛出明确异常码与消息。 - 可观测性:为关键流程增加日志与指标,便于定位问题。 - 安全:严格校验输入、最小权限原则、HTTPS 传输、密钥轮换。 + - **新增** 智能体安全:验证 Agent 能力声明,限制并发执行,监控心跳状态。 -章节来源 +**章节来源** - [backend/app/workers/platforms/base.py:1-18](file://backend/app/workers/platforms/base.py#L1-L18) - [backend/app/workers/scheduler.py:1-95](file://backend/app/workers/scheduler.py#L1-L95) - [frontend/lib/api.ts:16-21](file://frontend/lib/api.ts#L16-L21) +- [backend/app/agent_framework/registry.py:1-219](file://backend/app/agent_framework/registry.py#L1-L219) +- [backend/app/agent_framework/dispatcher.py:1-367](file://backend/app/agent_framework/dispatcher.py#L1-L367) ## 依赖分析 - 后端依赖 @@ -387,6 +528,7 @@ BasePlatformAdapter <|-- WenxinAdapter - 任务调度:APScheduler - 浏览器自动化:Playwright - HTTP 客户端:httpx + - **新增** 智能体框架:Redis async(aioredis)、SQLAlchemy JSONB - 前端依赖 - 框架与 UI:Next.js + Radix UI + TailwindCSS - 认证:NextAuth v4 @@ -403,6 +545,7 @@ J["python-jose/passlib"] R["Redis/APScheduler"] PW["Playwright"] H["httpx/python-dotenv"] +AIO["aioredis/sqlalchemy-jsonb"] end subgraph "前端依赖" N["Next.js"] @@ -412,26 +555,33 @@ RC["Recharts"] end ``` -图表来源 +**图表来源** - [backend/requirements.txt:1-35](file://backend/requirements.txt#L1-L35) - [frontend/package.json:11-27](file://frontend/package.json#L11-L27) -章节来源 +**章节来源** - [backend/requirements.txt:1-35](file://backend/requirements.txt#L1-L35) - [frontend/package.json:11-27](file://frontend/package.json#L11-L27) ## 性能考虑 - 数据库 - 为高频查询字段建立索引;避免 N+1 查询;使用分页参数限制单页规模。 + - **新增** 智能体相关表建立复合索引,优化查询性能。 - API - 合理设置分页参数(skip/limit),避免一次性返回大量数据。 - 对热点接口启用缓存(如 Redis)减少重复计算。 + - **新增** 智能体配置缓存,减少频繁查询数据库。 - 定时任务 - 调度周期可根据业务需求调整;在高负载时降低频率或增加并发控制。 - 浏览器自动化 - Playwright 启动成本较高,尽量复用上下文;失败重试与超时控制要合理设置。 - 前端 - 按需加载页面与组件;减少不必要的 re-render;利用浏览器缓存与静态资源优化。 + - **新增** 智能体状态管理,避免频繁重新获取配置。 +- **新增** 智能体框架性能 + - Redis 连接池管理,避免频繁创建连接。 + - 任务队列长度监控,防止内存泄漏。 + - 心跳超时阈值调优,平衡实时性与资源消耗。 ## 故障排查指南 - 常见问题定位 @@ -439,13 +589,16 @@ end - CORS:确认 app/main.py 中允许的源与方法。 - 数据库连接:检查 DATABASE_URL 与网络连通性。 - Playwright:确保已安装浏览器二进制;查看适配器初始化日志。 + - **新增** 智能体框架:检查 Redis 连接状态,验证 Agent 注册与心跳。 - 日志与监控 - 调度器与平台适配器均输出详细日志,定位失败原因。 - 前端统一错误处理:lib/api.ts 在请求失败时抛出错误,便于 UI 提示。 + - **新增** 智能体框架日志:监控任务状态变化和配置更新历史。 - 快速恢复 - 重启后端服务与前端构建;检查 .env 配置是否正确;核对迁移是否执行。 + - **新增** 智能体框架恢复:重启 Redis 服务,重新注册 Agent,检查任务队列。 -章节来源 +**章节来源** - [backend/app/main.py:45-47](file://backend/app/main.py#L45-L47) - [backend/app/main.py:30-36](file://backend/app/main.py#L30-L36) - [backend/app/config.py:7](file://backend/app/config.py#L7) @@ -453,7 +606,7 @@ end - [frontend/lib/api.ts:16-21](file://frontend/lib/api.ts#L16-L21) ## 结论 -GEO 平台提供了清晰的分层架构与可扩展点:路由层、服务层、数据层与工作器层相互解耦,配合配置中心与前端统一 API 封装,能够高效支撑业务扩展。通过平台适配器插件化、Schema/模型标准化、调度器与任务队列机制,团队可以快速接入新 AI 平台、扩展前端页面与数据模型,并在生产环境中保持稳定与可观测。 +GEO 平台提供了清晰的分层架构与可扩展点:路由层、服务层、数据层与工作器层相互解耦,配合配置中心与前端统一 API 封装,能够高效支撑业务扩展。**新增的智能体框架进一步增强了平台的扩展能力**:通过 Agent 注册中心、配置管理、任务调度和管道编排,团队可以快速接入新 AI 平台、扩展前端页面与数据模型,并在生产环境中保持稳定与可观测。通过平台适配器插件化、Schema/模型标准化、调度器与任务队列机制,以及智能体框架的动态扩展能力,团队可以构建更加灵活和强大的 AI 应用平台。 ## 附录 @@ -467,15 +620,24 @@ GEO 平台提供了清晰的分层架构与可扩展点:路由层、服务层 - 案例三:前端新增报表页面 - 步骤:新增页面与路由 → 引入图表组件 → 调用后端报表接口 → 权限控制与数据可视化。 - 建议:复用现有 UI 组件库,保持设计一致性。 +- **新增** 案例四:智能体系统集成 + - 步骤:实现 Agent 能力声明 → 注册到 AgentRegistry → 配置管理 → 任务分发 → 管道编排。 + - 建议:使用心跳机制监控 Agent 状态,实现自动故障转移。 +- **新增** 案例五:LLM 提供商扩展 + - 步骤:在配置中添加新提供商 → 实现工厂模式 → 更新默认配置 → 前端配置界面适配。 + - 建议:实现统一的 API 调用抽象,支持多提供商切换。 ### 部署与运行要点 - 使用 Docker Compose 启动后端与前端服务,确保端口映射与网络互通。 - 后端 Dockerfile 与 requirements.txt 已配置,注意镜像构建缓存与依赖锁定。 - 前端 Dockerfile 与 Next.js 版本已固定,构建产物由 Next.js 管理。 +- **新增** 智能体框架部署:确保 Redis 服务可用,配置正确的 REDIS_URL。 +- **新增** 环境配置:使用 .env.example 作为模板,配置所有必要的环境变量。 -章节来源 +**章节来源** - [docker-compose.yml](file://docker-compose.yml) - [backend/Dockerfile](file://backend/Dockerfile) - [frontend/Dockerfile](file://frontend/Dockerfile) - [backend/requirements.txt:1-35](file://backend/requirements.txt#L1-L35) -- [frontend/package.json:11-27](file://frontend/package.json#L11-L27) \ No newline at end of file +- [frontend/package.json:11-27](file://frontend/package.json#L11-L27) +- [.env.example:1-35](file://.env.example#L1-L35) \ No newline at end of file diff --git a/.qoder/repowiki/zh/content/数据库设计/数据库设计.md b/.qoder/repowiki/zh/content/数据库设计/数据库设计.md index 3456045..eff2fc2 100644 --- a/.qoder/repowiki/zh/content/数据库设计/数据库设计.md +++ b/.qoder/repowiki/zh/content/数据库设计/数据库设计.md @@ -8,11 +8,19 @@ - [backend/app/models/citation_record.py](file://backend/app/models/citation_record.py) - [backend/app/models/query_task.py](file://backend/app/models/query_task.py) - [backend/app/models/subscription.py](file://backend/app/models/subscription.py) +- [backend/app/models/lifecycle.py](file://backend/app/models/lifecycle.py) +- [backend/app/models/analytics.py](file://backend/app/models/analytics.py) +- [backend/app/models/alert.py](file://backend/app/models/alert.py) +- [backend/app/models/knowledge.py](file://backend/app/models/knowledge.py) - [backend/app/models/__init__.py](file://backend/app/models/__init__.py) - [backend/alembic/env.py](file://backend/alembic/env.py) - [backend/alembic/versions/488d0bd5ab01_initial_migration.py](file://backend/alembic/versions/488d0bd5ab01_initial_migration.py) - [backend/alembic/versions/b2c4d6e8fa10_add_confidence_match_type_to_citation_records.py](file://backend/alembic/versions/b2c4d6e8fa10_add_confidence_match_type_to_citation_records.py) - [backend/alembic/versions/c3d5e7f9ab12_add_user_management_fields.py](file://backend/alembic/versions/c3d5e7f9ab12_add_user_management_fields.py) +- [backend/alembic/versions/d4f6g8h0ab23_add_geo_lifecycle_tables.py](file://backend/alembic/versions/d4f6g8h0ab23_add_geo_lifecycle_tables.py) +- [backend/alembic/versions/e5f7a9b1cd34_add_alerts_and_alert_settings_tables.py](file://backend/alembic/versions/e5f7a9b1cd34_add_alerts_and_alert_settings_tables.py) +- [backend/alembic/versions/e5f7g9h1cd45_add_knowledge_base_tables.py](file://backend/alembic/versions/e5f7g9h1cd45_add_knowledge_base_tables.py) +- [backend/alembic/versions/f6g8h0i2de56_add_analytics_tables.py](file://backend/alembic/versions/f6g8h0i2de56_add_analytics_tables.py) - [backend/alembic.ini](file://backend/alembic.ini) - [backend/app/config.py](file://backend/app/config.py) - [docker-compose.yml](file://docker-compose.yml) @@ -23,15 +31,19 @@ - [backend/app/api/auth.py](file://backend/app/api/auth.py) - [backend/app/api/citations.py](file://backend/app/api/citations.py) - [backend/app/api/reports.py](file://backend/app/api/reports.py) +- [backend/app/api/lifecycle.py](file://backend/app/api/lifecycle.py) +- [backend/app/api/analytics.py](file://backend/app/api/analytics.py) +- [backend/app/api/alerts.py](file://backend/app/api/alerts.py) +- [backend/app/api/knowledge.py](file://backend/app/api/knowledge.py) ## 更新摘要 **变更内容** -- 新增用户管理相关字段的数据库迁移(email_verified、verification_code、reset_token等) -- 更新User模型以支持完整的用户认证和管理功能 -- 新增用户注册、登录、邮箱验证、密码重置等认证API -- 增强用户角色管理,支持管理员权限控制 -- 更新数据库迁移版本链,从初始版本到最新版本 +- 新增业务生命周期管理系统:组织、项目、阶段、代理、内容、规则、知识库等表 +- 新增分析监控系统:发布记录、内容指标、优化洞察等表 +- 新增告警系统:告警记录和告警设置表 +- 新增知识库系统:支持向量检索的完整知识管理架构 +- 更新数据库迁移版本链,包含11个版本的完整架构演进 ## 目录 1. [简介](#简介) @@ -55,11 +67,13 @@ - 性能优化、查询分析与缓存策略 - 备份、恢复与维护最佳实践 +**更新** 新增完整的业务生命周期、分析监控、告警系统、知识库等企业级功能架构,形成从用户管理到智能代理的完整数据体系。 + ## 项目结构 后端采用 FastAPI + SQLAlchemy Async + Alembic 迁移的典型分层架构: - 配置层:读取环境变量,提供数据库连接字符串 - 数据库引擎与会话:异步连接池与会话工厂 -- ORM 模型层:用户、查询、引用记录、任务、订阅 +- ORM 模型层:用户、查询、引用记录、任务、订阅、生命周期、分析监控、告警、知识库 - 迁移层:Alembic 初始化迁移脚本 - 服务层:业务查询封装,统一事务边界 - 容器编排:Docker Compose 启动 Postgres 与 Redis @@ -68,24 +82,37 @@ graph TB subgraph "应用层" AuthAPI["API: 认证
backend/app/api/auth.py"] -API["API: 引用
backend/app/api/citations.py"] -Reports["API: 报告
backend/app/api/reports.py"] +LifeCycleAPI["API: 生命周期
backend/app/api/lifecycle.py"] +AnalyticsAPI["API: 分析监控
backend/app/api/analytics.py"] +AlertsAPI["API: 告警系统
backend/app/api/alerts.py"] +KnowledgeAPI["API: 知识库
backend/app/api/knowledge.py"] +CitationsAPI["API: 引用
backend/app/api/citations.py"] +ReportsAPI["API: 报告
backend/app/api/reports.py"] end subgraph "服务层" SvcAuth["服务: 认证
backend/app/services/auth.py"] -SvcQ["服务: 查询
backend/app/services/query.py"] -SvcC["服务: 引用
backend/app/services/citation.py"] +SvcLifeCycle["服务: 生命周期
backend/app/services/lifecycle.py"] +SvcAnalytics["服务: 分析监控
backend/app/services/analytics.py"] +SvcAlerts["服务: 告警系统
backend/app/services/alert_engine.py"] +SvcKnowledge["服务: 知识库
backend/app/services/knowledge/"] +SvcCitations["服务: 引用
backend/app/services/citation.py"] +SvcReports["服务: 报告
backend/app/services/reports.py"] end subgraph "ORM 层" MUser["模型: 用户
backend/app/models/user.py"] +MLifeCycle["模型: 生命周期
backend/app/models/lifecycle.py"] +MAnalytics["模型: 分析监控
backend/app/models/analytics.py"] +MAlerts["模型: 告警系统
backend/app/models/alert.py"] +MKnowledge["模型: 知识库
backend/app/models/knowledge.py"] MQuery["模型: 查询
backend/app/models/query.py"] -MCit["模型: 引用记录
backend/app/models/citation_record.py"] +MCitation["模型: 引用记录
backend/app/models/citation_record.py"] MTask["模型: 查询任务
backend/app/models/query_task.py"] -MSub["模型: 订阅
backend/app/models/subscription.py"] +MSubscription["模型: 订阅
backend/app/models/subscription.py"] end subgraph "基础设施" DB["PostgreSQL 数据库"] RD["Redis 缓存"] +Vector["向量数据库"] end Cfg["配置: DATABASE_URL
backend/app/config.py"] Eng["引擎与会话
backend/app/database.py"] @@ -93,33 +120,46 @@ Alembic["迁移: Alembic
backend/alembic/*"] Cfg --> Eng Eng --> DB AuthAPI --> SvcAuth -API --> SvcC -Reports --> SvcC +LifeCycleAPI --> SvcLifeCycle +AnalyticsAPI --> SvcAnalytics +AlertsAPI --> SvcAlerts +KnowledgeAPI --> SvcKnowledge +CitationsAPI --> SvcCitations +ReportsAPI --> SvcReports SvcAuth --> Eng -SvcQ --> Eng -SvcC --> Eng +SvcLifeCycle --> Eng +SvcAnalytics --> Eng +SvcAlerts --> Eng +SvcKnowledge --> Eng +SvcCitations --> Eng +SvcReports --> Eng MUser --> Eng +MLifeCycle --> Eng +MAnalytics --> Eng +MAlerts --> Eng +MKnowledge --> Eng MQuery --> Eng -MCit --> Eng +MCitation --> Eng MTask --> Eng -MSub --> Eng +MSubscription --> Eng Alembic --> DB SvcAuth --> RD -SvcC --> RD +SvcCitations --> RD +SvcKnowledge --> Vector ``` -图表来源 +**图表来源** - [backend/app/config.py:1-23](file://backend/app/config.py#L1-L23) - [backend/app/database.py:1-29](file://backend/app/database.py#L1-L29) - [backend/app/models/user.py:1-48](file://backend/app/models/user.py#L1-L48) -- [backend/app/models/query.py:1-55](file://backend/app/models/query.py#L1-L55) -- [backend/app/models/citation_record.py:1-44](file://backend/app/models/citation_record.py#L1-L44) -- [backend/app/models/query_task.py:1-39](file://backend/app/models/query_task.py#L1-L39) -- [backend/app/models/subscription.py:1-37](file://backend/app/models/subscription.py#L1-L37) +- [backend/app/models/lifecycle.py:1-92](file://backend/app/models/lifecycle.py#L1-L92) +- [backend/app/models/analytics.py:1-64](file://backend/app/models/analytics.py#L1-L64) +- [backend/app/models/alert.py:1-75](file://backend/app/models/alert.py#L1-L75) +- [backend/app/models/knowledge.py:1-213](file://backend/app/models/knowledge.py#L1-L213) - [backend/alembic/env.py:1-89](file://backend/alembic/env.py#L1-L89) - [docker-compose.yml:1-71](file://docker-compose.yml#L1-L71) -章节来源 +**章节来源** - [backend/app/config.py:1-23](file://backend/app/config.py#L1-L23) - [backend/app/database.py:1-29](file://backend/app/database.py#L1-L29) - [backend/alembic/env.py:1-89](file://backend/alembic/env.py#L1-L89) @@ -136,18 +176,30 @@ SvcC --> RD - Alembic 环境集成 SQLAlchemy Base 元数据,支持离线/在线迁移。 - 初始迁移脚本定义了用户、查询、引用记录、查询任务、订阅五张表及必要索引。 - 新增迁移版本支持confidence和match_type字段,增强报告功能。 + - **新增** 生命周期迁移(d4f6g8h0ab23):新增组织、项目、阶段、代理、内容、规则、知识库等完整业务架构。 + - **新增** 分析监控迁移(f6g8h0i2de56):新增发布记录、内容指标、优化洞察等分析监控表。 + - **新增** 告警系统迁移(e5f7a9b1cd34):新增告警记录和告警设置表。 + - **新增** 知识库迁移(e5f7g9h1cd45):新增支持向量检索的知识库完整架构。 - **新增** 最新迁移版本添加用户管理相关字段,支持完整的用户认证和管理功能。 - 服务层封装 - 查询与引用统计、导出等业务逻辑封装在服务层,统一执行 SQL 并返回结果。 - 对外暴露清晰的查询接口,内部进行权限校验与计数限制。 - **新增** 认证服务封装用户注册、登录、验证等功能。 + - **新增** 生命周期服务管理项目全生命周期。 + - **新增** 分析监控服务处理内容发布和指标收集。 + - **新增** 告警引擎服务处理实时告警。 + - **新增** 知识库服务处理向量检索和RAG。 -章节来源 +**章节来源** - [backend/app/database.py:1-29](file://backend/app/database.py#L1-L29) - [backend/app/models/__init__.py:1-14](file://backend/app/models/__init__.py#L1-L14) - [backend/alembic/versions/488d0bd5ab01_initial_migration.py:1-128](file://backend/alembic/versions/488d0bd5ab01_initial_migration.py#L1-L128) - [backend/alembic/versions/b2c4d6e8fa10_add_confidence_match_type_to_citation_records.py:1-37](file://backend/alembic/versions/b2c4d6e8fa10_add_confidence_match_type_to_citation_records.py#L1-L37) - [backend/alembic/versions/c3d5e7f9ab12_add_user_management_fields.py:1-41](file://backend/alembic/versions/c3d5e7f9ab12_add_user_management_fields.py#L1-L41) +- [backend/alembic/versions/d4f6g8h0ab23_add_geo_lifecycle_tables.py:1-398](file://backend/alembic/versions/d4f6g8h0ab23_add_geo_lifecycle_tables.py#L1-L398) +- [backend/alembic/versions/f6g8h0i2de56_add_analytics_tables.py:1-125](file://backend/alembic/versions/f6g8h0i2de56_add_analytics_tables.py#L1-L125) +- [backend/alembic/versions/e5f7a9b1cd34_add_alerts_and_alert_settings_tables.py:1-86](file://backend/alembic/versions/e5f7a9b1cd34_add_alerts_and_alert_settings_tables.py#L1-L86) +- [backend/alembic/versions/e5f7g9h1cd45_add_knowledge_base_tables.py:1-224](file://backend/alembic/versions/e5f7g9h1cd45_add_knowledge_base_tables.py#L1-L224) - [backend/app/services/query.py:1-130](file://backend/app/services/query.py#L1-L130) - [backend/app/services/citation.py:1-429](file://backend/app/services/citation.py#L1-L429) - [backend/app/services/auth.py:1-175](file://backend/app/services/auth.py#L1-L175) @@ -159,31 +211,48 @@ SvcC --> RD sequenceDiagram participant Client as "客户端" participant AuthAPI as "认证API" -participant API as "FastAPI 应用" +participant LifeCycleAPI as "生命周期API" +participant AnalyticsAPI as "分析监控API" +participant AlertsAPI as "告警API" +participant KnowledgeAPI as "知识库API" participant SvcAuth as "认证服务" -participant SvcC as "引用服务" -participant Reports as "报告服务" +participant SvcLifeCycle as "生命周期服务" +participant SvcAnalytics as "分析监控服务" +participant SvcAlerts as "告警引擎服务" +participant SvcKnowledge as "知识库服务" participant DB as "PostgreSQL" participant Alembic as "迁移工具" Client->>AuthAPI : 请求 /auth/register 登录 AuthAPI->>SvcAuth : 调用认证服务 SvcAuth->>DB : 执行用户注册/验证 -Client->>API : 请求 /citations 或 /reports -API->>SvcC : 调用引用服务 -SvcC->>DB : 执行查询/统计/插入 -API->>Reports : 调用报告服务 -Reports->>DB : 执行导出查询 -DB-->>Reports : 返回统计数据 -DB-->>SvcC : 返回引用记录 +Client->>LifeCycleAPI : 请求生命周期管理 +LifeCycleAPI->>SvcLifeCycle : 调用生命周期服务 +SvcLifeCycle->>DB : 执行项目/阶段管理 +Client->>AnalyticsAPI : 请求分析监控 +AnalyticsAPI->>SvcAnalytics : 调用分析监控服务 +SvcAnalytics->>DB : 执行发布记录/指标收集 +Client->>AlertsAPI : 请求告警管理 +AlertsAPI->>SvcAlerts : 调用告警引擎服务 +SvcAlerts->>DB : 执行告警记录/设置 +Client->>KnowledgeAPI : 请求知识检索 +KnowledgeAPI->>SvcKnowledge : 调用知识库服务 +SvcKnowledge->>DB : 执行向量检索 +SvcKnowledge->>Vector : 执行相似度搜索 +DB-->>SvcKnowledge : 返回检索结果 +DB-->>SvcAlerts : 返回告警数据 +DB-->>SvcAnalytics : 返回监控数据 +DB-->>SvcLifeCycle : 返回生命周期数据 DB-->>SvcAuth : 返回用户信息 -Reports-->>API : 返回CSV内容 -SvcC-->>API : 返回查询列表/详情 +SvcKnowledge-->>KnowledgeAPI : 返回检索结果 +SvcAlerts-->>AlertsAPI : 返回告警数据 +SvcAnalytics-->>AnalyticsAPI : 返回监控数据 +SvcLifeCycle-->>LifeCycleAPI : 返回生命周期数据 SvcAuth-->>AuthAPI : 返回认证结果 AuthAPI-->>Client : 响应认证数据 Note over Alembic,DB : 首次启动或升级时执行迁移 ``` -图表来源 +**图表来源** - [backend/app/services/citation.py:1-429](file://backend/app/services/citation.py#L1-L429) - [backend/app/services/auth.py:1-175](file://backend/app/services/auth.py#L1-L175) - [backend/alembic/env.py:1-89](file://backend/alembic/env.py#L1-L89) @@ -191,13 +260,31 @@ Note over Alembic,DB : 首次启动或升级时执行迁移 ## 详细组件分析 ### 实体关系映射(ER) -- 用户(users):主键 id,唯一邮箱,计划与配额字段,活跃状态,**新增**邮箱验证状态、验证码及其过期时间、重置令牌及其过期时间、头像URL、管理员权限,时间戳。 -- 查询(queries):外键 user_id,关键词、目标品牌、别名列表、平台列表、频率、状态、下次查询时间,时间戳。 -- 引用记录(citation_records):外键 query_id,平台、是否引用、引用位置、引用文本、竞争品牌列表、原始响应、匹配置信度、匹配类型、查询时间。 -- 查询任务(query_tasks):外键 query_id,平台、状态、错误信息、调度/开始/完成时间。 -- 订阅(subscriptions):外键 user_id,计划、状态、起止日期、金额、支付方式与流水号,时间戳。 +- 用户(users):主键 id,唯一邮箱,计划与配额字段,活跃状态,**新增**组织关联、角色字段,邮箱验证状态、验证码及其过期时间、重置令牌及其过期时间、头像URL、管理员权限,时间戳。 +- 组织(organizations):主键 id,名称、slug唯一约束、描述、logo、计划、最大成员数,时间戳。 +- 生命周期项目(lifecycle_projects):主键 id,组织外键,品牌名称、别名列表、当前阶段、状态、创建者外键,时间戳。 +- 项目阶段(project_stages):主键 id,项目外键,阶段编号、状态、开始/完成时间、备注、指标,唯一索引(project_id, stage_number)。 +- 代理注册表(agent_registry):主键 id,名称唯一约束、显示名称、代理类型、描述、版本、端点、状态、能力、心跳时间,索引(name, agent_type, status)。 +- 代理配置(agent_configs):主键 id,代理外键,配置键唯一约束,配置值、描述、更新时间、更新者外键。 +- 代理任务(agent_tasks):主键 id,代理外键,任务类型、状态、优先级、输入输出数据、错误信息、创建者、组织、项目外键,索引(agent_id, status, organization_id, project_id, created_by, task_type)。 +- 代理任务日志(agent_task_logs):主键 id,任务外键,代理外键,日志级别、消息、元数据,索引(task_id, agent_id, created_at)。 +- 内容(contents):主键 id,组织外键,项目外键,标题、类型、正文、状态、目标平台、关键词、元数据、创建者外键,索引(organization_id, project_id, status, content_type, created_by)。 +- 内容版本(content_versions):主键 id,内容外键,版本号、标题、正文、变更摘要、创建者外键,唯一索引(content_id, version_number)。 +- 内容审核(content_reviews):主键 id,内容外键,审核者外键,状态、评论,索引(content_id, reviewer_id)。 +- 平台规则(platform_rules):主键 id,平台、规则类别、规则名称、描述、检查标准、严重程度、激活状态,索引(platform, rule_category, is_active)。 +- 品牌知识(brand_knowledge):主键 id,组织外键,类别、标题、内容、元数据、激活状态、创建者外键,索引(organization_id, category, is_active)。 +- 关键词(keywords):主键 id,组织外键,项目外键,关键词、类别、优先级、搜索量、竞争等级、状态,索引(organization_id, project_id, category, status, keyword)。 +- 发布记录(publish_records):主键 id,组织外键,内容标题、内容ID、平台、发布URL、状态、发布时间,索引(organization_id, platform, status, created_at)。 +- 内容指标(content_metrics):主键 id,发布记录外键,记录时间,互动指标、AI引用次数、搜索曝光点击、阅读指标,索引(publish_record_id, recorded_at)。 +- 优化洞察(optimization_insights):主键 id,组织外键,内容ID、洞察类型、标题、描述、建议、严重程度、是否已应用,索引(organization_id, insight_type, created_at)。 +- 告警(alerts):主键 id,品牌外键,用户外键,告警类型、严重程度、标题、消息、数据、是否已读,索引(user_id, brand_id, alert_type, is_read, created_at)。 +- 告警设置(alert_settings):主键 id,品牌外键,用户外键,告警类型、是否启用、阈值,索引(brand_id, user_id, brand_id, alert_type)。 +- 知识库(knowledge_bases):主键 id,组织外键,名称、类型、描述、文档数量、状态、创建者外键,索引(organization_id, type, status)。 +- 知识文档(knowledge_documents):主键 id,知识库外键,标题、来源类型、URL、内容、内容哈希、分块数量、状态、错误信息、元数据,索引(knowledge_base_id, status, content_hash)。 +- 知识分块(knowledge_chunks):主键 id,文档外键,内容、嵌入向量、分块索引、token数量、元数据,索引(document_id, document_id, chunk_index)。 +- 知识检索日志(knowledge_search_logs):主键 id,组织外键,用户外键,查询、知识库ID列表、结果数量、延迟毫秒,索引(organization_id, user_id, created_at)。 -**更新** 用户表新增完整的用户管理字段,支持邮箱验证、密码重置、头像管理和管理员权限控制。 +**更新** 新增完整的业务生命周期、分析监控、告警系统、知识库等企业级功能架构,形成从用户管理到智能代理的完整数据体系。 ```mermaid erDiagram @@ -209,6 +296,8 @@ string name string plan integer max_queries boolean is_active +uuid organization_id FK +string role boolean email_verified string verification_code timestamptz verification_code_expires @@ -219,74 +308,308 @@ boolean is_admin timestamptz created_at timestamptz updated_at } -QUERIES { +ORGANIZATIONS { uuid id PK -uuid user_id FK -string keyword -string target_brand -jsonb brand_aliases -jsonb platforms -string frequency -string status -timestamptz last_queried_at -timestamptz next_query_at +string name +string slug UK +text description +string logo_url +string plan +integer max_members timestamptz created_at timestamptz updated_at } -CITATION_RECORDS { +LIFECYCLE_PROJECTS { uuid id PK -uuid query_id FK -string platform -boolean cited -integer citation_position -text citation_text -jsonb competitor_brands -text raw_response -float confidence -string match_type -timestamptz queried_at -} -QUERY_TASKS { -uuid id PK -uuid query_id FK -string platform +uuid organization_id FK +string brand_name +jsonb brand_aliases +integer current_stage string status +uuid created_by FK +timestamptz created_at +timestamptz updated_at +} +PROJECT_STAGES { +uuid id PK +uuid project_id FK +integer stage_number +string status +timestamptz started_at +timestamptz completed_at +text notes +jsonb metrics +} +AGENT_REGISTRY { +uuid id PK +string name UK +string display_name +string agent_type +text description +string version +string endpoint +string status +jsonb capabilities +timestamptz last_heartbeat +timestamptz created_at +timestamptz updated_at +} +AGENT_CONFIGS { +uuid id PK +uuid agent_id FK +string config_key +jsonb config_value +string description +timestamptz updated_at +uuid updated_by FK +} +AGENT_TASKS { +uuid id PK +uuid agent_id FK +string task_type +string status +integer priority +jsonb input_data +jsonb output_data text error_message +uuid created_by FK +uuid organization_id FK +uuid project_id FK timestamptz scheduled_at timestamptz started_at timestamptz completed_at -} -SUBSCRIPTIONS { -uuid id PK -uuid user_id FK -string plan -string status -date start_date -date end_date -numeric amount -string payment_method -string payment_id timestamptz created_at } -USERS ||--o{ QUERIES : "拥有" -QUERIES ||--o{ CITATION_RECORDS : "产生" -QUERIES ||--o{ QUERY_TASKS : "触发" -USERS ||--o{ SUBSCRIPTIONS : "订阅" +AGENT_TASK_LOGS { +uuid id PK +uuid task_id FK +uuid agent_id FK +string log_level +text message +jsonb metadata +timestamptz created_at +} +CONTENTS { +uuid id PK +uuid organization_id FK +uuid project_id FK +string title +string content_type +text body +string status +jsonb target_platforms +jsonb keywords +jsonb metadata +uuid created_by FK +integer current_version +timestamptz created_at +timestamptz updated_at +} +CONTENT_VERSIONS { +uuid id PK +uuid content_id FK +integer version_number +string title +text body +string change_summary +uuid created_by FK +timestamptz created_at +} +CONTENT_REVIEWS { +uuid id PK +uuid content_id FK +uuid reviewer_id FK +string status +text comments +timestamptz created_at +} +PLATFORM_RULES { +uuid id PK +string platform +string rule_category +string rule_name +text description +jsonb check_criteria +string severity +boolean is_active +timestamptz updated_at +} +BRAND_KNOWLEDGE { +uuid id PK +uuid organization_id FK +string category +string title +text content +jsonb metadata +boolean is_active +uuid created_by FK +timestamptz created_at +timestamptz updated_at +} +KEYWORDS { +uuid id PK +uuid organization_id FK +uuid project_id FK +string keyword +string category +integer priority +integer search_volume +string competition_level +string status +timestamptz created_at +} +PUBLISH_RECORDS { +string id PK +string organization_id FK +string content_title +string content_id +string platform +string published_url +string status +timestamptz published_at +timestamptz created_at +} +CONTENT_METRICS { +string id PK +string publish_record_id FK +timestamptz recorded_at +integer views +integer likes +integer comments +integer shares +integer bookmarks +integer ai_citation_count +integer search_impressions +integer search_clicks +float avg_read_duration +float read_completion_rate +} +OPTIMIZATION_INSIGHTS { +string id PK +string organization_id FK +string content_id +string insight_type +string title +text description +text recommendation +string severity +boolean applied +timestamptz created_at +} +ALERTS { +uuid id PK +uuid brand_id FK +uuid user_id FK +string alert_type +string severity +string title +text message +jsonb data +boolean is_read +timestamptz created_at +} +ALERT_SETTINGS { +uuid id PK +uuid brand_id FK +uuid user_id FK +string alert_type +boolean enabled +float threshold +timestamptz created_at +timestamptz updated_at +} +KNOWLEDGE_BASES { +uuid id PK +uuid organization_id FK +string name +string type +text description +integer document_count +string status +uuid created_by FK +timestamptz created_at +timestamptz updated_at +} +KNOWLEDGE_DOCUMENTS { +uuid id PK +uuid knowledge_base_id FK +string title +string source_type +string source_url +text content +string content_hash +integer chunk_count +string status +text error_message +jsonb metadata +timestamptz created_at +timestamptz updated_at +} +KNOWLEDGE_CHUNKS { +uuid id PK +uuid document_id FK +text content +vector embedding +integer chunk_index +integer token_count +jsonb metadata +timestamptz created_at +} +KNOWLEDGE_SEARCH_LOGS { +uuid id PK +uuid organization_id FK +uuid user_id FK +text query +jsonb knowledge_base_ids +integer results_count +integer latency_ms +timestamptz created_at +} +USERS ||--o{ ORGANIZATIONS : "属于" +ORGANIZATIONS ||--o{ LIFECYCLE_PROJECTS : "拥有" +LIFECYCLE_PROJECTS ||--o{ PROJECT_STAGES : "包含" +USERS ||--o{ LIFECYCLE_PROJECTS : "创建" +USERS ||--o{ AGENT_TASKS : "创建" +ORGANIZATIONS ||--o{ AGENT_TASKS : "拥有" +LIFECYCLE_PROJECTS ||--o{ AGENT_TASKS : "关联" +AGENT_REGISTRY ||--o{ AGENT_TASKS : "注册" +AGENT_TASKS ||--o{ AGENT_TASK_LOGS : "产生" +ORGANIZATIONS ||--o{ CONTENTS : "拥有" +LIFECYCLE_PROJECTS ||--o{ CONTENTS : "关联" +USERS ||--o{ CONTENTS : "创建" +CONTENTS ||--o{ CONTENT_VERSIONS : "版本化" +CONTENTS ||--o{ CONTENT_REVIEWS : "审核" +ORGANIZATIONS ||--o{ PLATFORM_RULES : "拥有" +ORGANIZATIONS ||--o{ BRAND_KNOWLEDGE : "拥有" +ORGANIZATIONS ||--o{ KEYWORDS : "拥有" +LIFECYCLE_PROJECTS ||--o{ KEYWORDS : "关联" +ORGANIZATIONS ||--o{ PUBLISH_RECORDS : "拥有" +PUBLISH_RECORDS ||--o{ CONTENT_METRICS : "产生" +ORGANIZATIONS ||--o{ OPTIMIZATION_INSIGHTS : "拥有" +USERS ||--o{ ALERTS : "拥有" +BRANDS ||--o{ ALERTS : "关联" +USERS ||--o{ ALERT_SETTINGS : "拥有" +BRANDS ||--o{ ALERT_SETTINGS : "关联" +ORGANIZATIONS ||--o{ KNOWLEDGE_BASES : "拥有" +KNOWLEDGE_BASES ||--o{ KNOWLEDGE_DOCUMENTS : "包含" +KNOWLEDGE_DOCUMENTS ||--o{ KNOWLEDGE_CHUNKS : "分块" +ORGANIZATIONS ||--o{ KNOWLEDGE_SEARCH_LOGS : "拥有" +USERS ||--o{ KNOWLEDGE_SEARCH_LOGS : "使用" ``` -图表来源 +**图表来源** - [backend/app/models/user.py:11-48](file://backend/app/models/user.py#L11-L48) -- [backend/app/models/query.py:11-48](file://backend/app/models/query.py#L11-L48) -- [backend/app/models/citation_record.py:11-44](file://backend/app/models/citation_record.py#L11-L44) -- [backend/app/models/query_task.py:11-34](file://backend/app/models/query_task.py#L11-L34) -- [backend/app/models/subscription.py:11-36](file://backend/app/models/subscription.py#L11-L36) +- [backend/app/models/lifecycle.py:12-92](file://backend/app/models/lifecycle.py#L12-L92) +- [backend/app/models/analytics.py:9-64](file://backend/app/models/analytics.py#L9-L64) +- [backend/app/models/alert.py:24-75](file://backend/app/models/alert.py#L24-L75) +- [backend/app/models/knowledge.py:22-213](file://backend/app/models/knowledge.py#L22-L213) -章节来源 +**章节来源** - [backend/app/models/user.py:1-48](file://backend/app/models/user.py#L1-L48) -- [backend/app/models/query.py:1-55](file://backend/app/models/query.py#L1-L55) -- [backend/app/models/citation_record.py:1-44](file://backend/app/models/citation_record.py#L1-L44) -- [backend/app/models/query_task.py:1-39](file://backend/app/models/query_task.py#L1-L39) -- [backend/app/models/subscription.py:1-37](file://backend/app/models/subscription.py#L1-L37) +- [backend/app/models/lifecycle.py:1-92](file://backend/app/models/lifecycle.py#L1-L92) +- [backend/app/models/analytics.py:1-64](file://backend/app/models/analytics.py#L1-L64) +- [backend/app/models/alert.py:1-75](file://backend/app/models/alert.py#L1-L75) +- [backend/app/models/knowledge.py:1-213](file://backend/app/models/knowledge.py#L1-L213) ### 索引策略 - 查询表(queries) @@ -301,25 +624,107 @@ USERS ||--o{ SUBSCRIPTIONS : "订阅" - **新增** idx_citation_records_match_type:按匹配类型过滤(建议) - **新增** 用户表(users) - idx_users_email:按邮箱快速查找 + - idx_users_organization_id:按组织关联 - idx_users_verification_code:按验证码快速验证 - idx_users_reset_token:按重置令牌快速验证 +- **新增** 组织表(organizations) + - idx_organizations_slug:按slug快速查找 +- **新增** 生命周期项目表(lifecycle_projects) + - idx_lifecycle_projects_organization_id:按组织过滤 + - idx_lifecycle_projects_status:按状态过滤 + - idx_lifecycle_projects_brand_name:按品牌名称过滤 +- **新增** 项目阶段表(project_stages) + - idx_project_stages_project_id:按项目过滤 + - idx_project_stages_status:按状态过滤 + - idx_project_stages_project_stage:按项目和阶段唯一约束 +- **新增** 代理注册表(agent_registry) + - idx_agent_registry_name:按名称快速查找 + - idx_agent_registry_agent_type:按代理类型过滤 + - idx_agent_registry_status:按状态过滤 +- **新增** 代理任务表(agent_tasks) + - idx_agent_tasks_agent_id:按代理过滤 + - idx_agent_tasks_status:按状态过滤 + - idx_agent_tasks_organization_id:按组织过滤 + - idx_agent_tasks_project_id:按项目过滤 + - idx_agent_tasks_created_by:按创建者过滤 + - idx_agent_tasks_task_type:按任务类型过滤 +- **新增** 内容表(contents) + - idx_contents_organization_id:按组织过滤 + - idx_contents_project_id:按项目过滤 + - idx_contents_status:按状态过滤 + - idx_contents_content_type:按类型过滤 + - idx_contents_created_by:按创建者过滤 +- **新增** 知识库表(knowledge_bases) + - idx_knowledge_bases_organization_id:按组织过滤 + - idx_knowledge_bases_type:按类型过滤 + - idx_knowledge_bases_status:按状态过滤 +- **新增** 知识文档表(knowledge_documents) + - idx_knowledge_documents_knowledge_base_id:按知识库过滤 + - idx_knowledge_documents_status:按状态过滤 + - idx_knowledge_documents_content_hash:按内容哈希过滤 +- **新增** 知识分块表(knowledge_chunks) + - idx_knowledge_chunks_document_id:按文档过滤 + - idx_knowledge_chunks_chunk_index:按分块索引过滤 + - **新增** 向量索引:ix_knowledge_chunks_embedding(HNSW近似最近邻搜索) +- **新增** 分析监控表 + - idx_publish_records_organization_id:按组织过滤 + - idx_publish_records_platform:按平台过滤 + - idx_publish_records_status:按状态过滤 + - idx_publish_records_created_at:按创建时间过滤 + - idx_content_metrics_publish_record_id:按发布记录过滤 + - idx_content_metrics_recorded_at:按记录时间过滤 + - idx_optimization_insights_organization_id:按组织过滤 + - idx_optimization_insights_insight_type:按洞察类型过滤 + - idx_optimization_insights_created_at:按创建时间过滤 +- **新增** 告警系统表 + - idx_alerts_user_id:按用户过滤 + - idx_alerts_brand_id:按品牌过滤 + - idx_alerts_alert_type:按告警类型过滤 + - idx_alerts_is_read:按是否已读过滤 + - idx_alerts_created_at:按创建时间过滤 + - idx_alerts_user_read:按用户和已读状态组合过滤 + - idx_alert_settings_brand_id:按品牌过滤 + - idx_alert_settings_user_id:按用户过滤 + - idx_alert_settings_brand_type:按品牌和类型组合唯一约束 -**更新** 新增针对用户管理字段的索引建议,支持高效的用户认证和验证操作。 +**更新** 新增针对所有新增表的索引策略,特别是知识库的向量索引和告警系统的复合索引。 这些索引覆盖了常见查询路径与统计场景,有助于提升分页、过滤、排序与聚合的性能。 -章节来源 +**章节来源** - [backend/alembic/versions/488d0bd5ab01_initial_migration.py:57-94](file://backend/alembic/versions/488d0bd5ab01_initial_migration.py#L57-L94) - [backend/alembic/versions/b2c4d6e8fa10_add_confidence_match_type_to_citation_records.py:21-37](file://backend/alembic/versions/b2c4d6e8fa10_add_confidence_match_type_to_citation_records.py#L21-L37) - [backend/alembic/versions/c3d5e7f9ab12_add_user_management_fields.py:21-41](file://backend/alembic/versions/c3d5e7f9ab12_add_user_management_fields.py#L21-L41) -- [backend/app/models/query.py:50-54](file://backend/app/models/query.py#L50-L54) -- [backend/app/models/citation_record.py:37-44](file://backend/app/models/citation_record.py#L37-L44) -- [backend/app/models/query_task.py:36-38](file://backend/app/models/query_task.py#L36-L38) +- [backend/alembic/versions/d4f6g8h0ab23_add_geo_lifecycle_tables.py:24-398](file://backend/alembic/versions/d4f6g8h0ab23_add_geo_lifecycle_tables.py#L24-L398) +- [backend/alembic/versions/f6g8h0i2de56_add_analytics_tables.py:24-125](file://backend/alembic/versions/f6g8h0i2de56_add_analytics_tables.py#L24-L125) +- [backend/alembic/versions/e5f7a9b1cd34_add_alerts_and_alert_settings_tables.py:24-86](file://backend/alembic/versions/e5f7a9b1cd34_add_alerts_and_alert_settings_tables.py#L24-L86) +- [backend/alembic/versions/e5f7g9h1cd45_add_knowledge_base_tables.py:30-224](file://backend/alembic/versions/e5f7g9h1cd45_add_knowledge_base_tables.py#L30-L224) ### SQLAlchemy ORM 模型实现 - 字段类型与默认值 - UUID 主键与外键,JSONB 存储数组/字典,布尔、整数、文本、数值、时间戳等。 - 默认值通过 server_default/onupdate 设置,减少应用层重复逻辑。 + - **新增** 组织表:slug唯一约束,max_members默认5,plan默认'free'。 + - **新增** 生命周期项目表:current_stage默认1,status默认'active'。 + - **新增** 项目阶段表:status默认'pending',stage_number非空。 + - **新增** 代理注册表:name唯一约束,status默认'offline'。 + - **新增** 代理配置表:config_key唯一约束,updated_at自动更新。 + - **新增** 代理任务表:多个索引字段,status默认'pending',priority默认0。 + - **新增** 内容表:status默认'draft',current_version默认1。 + - **新增** 内容版本表:version_number非空,unique约束。 + - **新增** 内容审核表:status非空。 + - **新增** 平台规则表:severity非空,is_active默认true。 + - **新增** 品牌知识表:is_active默认true。 + - **新增** 关键词表:priority默认0,status默认'active'。 + - **新增** 发布记录表:status默认'draft'。 + - **新增** 内容指标表:多个默认值,avg_read_duration默认0.0。 + - **新增** 优化洞察表:severity默认'info',applied默认false。 + - **新增** 告警表:is_read默认false。 + - **新增** 告警设置表:enabled默认true,threshold可为空。 + - **新增** 知识库表:document_count默认0,status默认'active'。 + - **新增** 知识文档表:chunk_count默认0,status默认'processing'。 + - **新增** 知识分块表:token_count默认0。 + - **新增** 知识检索日志表:results_count默认0,latency_ms默认0。 - **新增** email_verified字段(Boolean类型,默认False)用于邮箱验证状态。 - **新增** verification_code字段(String类型,长度6,nullable=True)用于存储6位验证码。 - **新增** verification_code_expires字段(DateTime类型,nullable=True)用于验证码过期时间。 @@ -330,13 +735,40 @@ USERS ||--o{ SUBSCRIPTIONS : "订阅" - **新增** confidence字段(Float类型,nullable=True)用于存储匹配的可信度评分。 - **新增** match_type字段(String类型,长度20,nullable=True)用于标识匹配类型。 - 关系配置 - - 用户与查询、订阅为一对多;查询与引用记录、任务为一对多。 - - 级联删除与孤儿对象清理(delete-orphan),避免悬挂数据。 + - 用户与组织:多对一,支持NULL值(用户未加入组织)。 + - 组织与生命周期项目:一对多,级联删除。 + - 项目与阶段:一对多,级联删除与孤儿对象清理。 + - 代理注册与配置:一对多,级联删除。 + - 代理注册与任务:一对多,级联删除。 + - 代理任务与日志:一对多,级联删除。 + - 组织与内容:一对多,级联删除。 + - 内容与版本:一对多,级联删除与唯一约束。 + - 内容与审核:一对多,级联删除。 + - 组织与平台规则:一对多,级联删除。 + - 组织与品牌知识:一对多,级联删除。 + - 组织与关键词:一对多,级联删除。 + - 项目与关键词:一对多,级联删除。 + - 知识库与文档:一对多,级联删除。 + - 文档与分块:一对多,级联删除。 + - 组织与发布记录:一对多,级联删除。 + - 发布记录与指标:一对多,级联删除。 + - 组织与优化洞察:一对多,级联删除。 + - 用户与告警:一对多,级联删除。 + - 品牌与告警:一对多,级联删除。 + - 用户与告警设置:一对多,级联删除。 + - 品牌与告警设置:一对多,级联删除。 + - 组织与知识库:一对多,级联删除。 + - 组织与知识检索日志:一对多,级联删除。 + - 用户与知识检索日志:一对多,级联删除。 - 查询封装 - 服务层使用 select + func + join 封装复杂查询,统一处理分页与计数。 - 权限校验:仅允许访问当前用户的资源,防止越权。 + - **新增** 生命周期服务:管理项目全生命周期,支持阶段转换和状态管理。 + - **新增** 分析监控服务:处理内容发布流程和指标收集。 + - **新增** 告警引擎服务:实时处理告警规则和通知。 + - **新增** 知识库服务:处理向量检索和RAG应用。 -**更新** User模型新增完整的用户管理字段,支持邮箱验证、密码重置、头像管理和管理员权限控制。 +**更新** 新增完整的生命周期、分析监控、告警系统、知识库等ORM模型实现,支持复杂的业务关系和查询需求。 ```mermaid classDiagram @@ -348,6 +780,8 @@ class User { +plan : string +max_queries : int +is_active : bool ++organization_id : uuid ++role : string +email_verified : bool +verification_code : string +verification_code_expires : datetime @@ -357,83 +791,360 @@ class User { +is_admin : bool +created_at : datetime +updated_at : datetime ++organization +queries +subscriptions ++lifecycle_projects ++agent_tasks ++contents ++knowledge_bases } -class Query { +class Organization { +id : uuid -+user_id : uuid -+keyword : string -+target_brand : string -+brand_aliases : list -+platforms : list -+frequency : string -+status : string -+last_queried_at : datetime -+next_query_at : datetime ++name : string ++slug : string ++description : string ++logo_url : string ++plan : string ++max_members : int +created_at : datetime +updated_at : datetime -+user -+citation_records -+query_tasks ++users ++lifecycle_projects ++agent_tasks ++contents ++platform_rules ++brand_knowledge ++keywords ++knowledge_bases ++publish_records ++optimization_insights ++knowledge_search_logs } -class CitationRecord { +class LifecycleProject { +id : uuid -+query_id : uuid -+platform : string -+cited : bool -+citation_position : int -+citation_text : text -+competitor_brands : list -+raw_response : text -+confidence : float -+match_type : string -+queried_at : datetime -+query -} -class QueryTask { -+id : uuid -+query_id : uuid -+platform : string ++organization_id : uuid ++brand_name : string ++brand_aliases : list ++current_stage : int +status : string -+error_message : text ++created_by : uuid ++created_at : datetime ++updated_at : datetime ++organization ++stages ++creator ++agent_tasks ++contents ++keywords +} +class ProjectStage { ++id : uuid ++project_id : uuid ++stage_number : int ++status : string ++started_at : datetime ++completed_at : datetime ++notes : string ++metrics : dict ++project +} +class AgentRegistry { ++id : uuid ++name : string ++display_name : string ++agent_type : string ++description : string ++version : string ++endpoint : string ++status : string ++capabilities : dict ++last_heartbeat : datetime ++created_at : datetime ++updated_at : datetime ++configs ++tasks +} +class AgentConfig { ++id : uuid ++agent_id : uuid ++config_key : string ++config_value : dict ++description : string ++updated_at : datetime ++updated_by : uuid ++agent +} +class AgentTask { ++id : uuid ++agent_id : uuid ++task_type : string ++status : string ++priority : int ++input_data : dict ++output_data : dict ++error_message : string ++created_by : uuid ++organization_id : uuid ++project_id : uuid +scheduled_at : datetime +started_at : datetime +completed_at : datetime -+query -} -class Subscription { -+id : uuid -+user_id : uuid -+plan : string -+status : string -+start_date : date -+end_date : date -+amount : float -+payment_method : string -+payment_id : string +created_at : datetime ++agent ++logs +} +class AgentTaskLog { ++id : uuid ++task_id : uuid ++agent_id : uuid ++log_level : string ++message : string ++metadata : dict ++created_at : datetime ++task ++agent +} +class Content { ++id : uuid ++organization_id : uuid ++project_id : uuid ++title : string ++content_type : string ++body : string ++status : string ++target_platforms : list ++keywords : list ++metadata : dict ++created_by : uuid ++current_version : int ++created_at : datetime ++updated_at : datetime ++versions ++reviews ++metrics +} +class ContentVersion { ++id : uuid ++content_id : uuid ++version_number : int ++title : string ++body : string ++change_summary : string ++created_by : uuid ++created_at : datetime ++content +} +class ContentReview { ++id : uuid ++content_id : uuid ++reviewer_id : uuid ++status : string ++comments : string ++created_at : datetime ++content ++reviewer +} +class PlatformRule { ++id : uuid ++platform : string ++rule_category : string ++rule_name : string ++description : string ++check_criteria : dict ++severity : string ++is_active : bool ++updated_at : datetime +} +class BrandKnowledge { ++id : uuid ++organization_id : uuid ++category : string ++title : string ++content : string ++metadata : dict ++is_active : bool ++created_by : uuid ++created_at : datetime ++updated_at : datetime ++organization ++creator +} +class Keyword { ++id : uuid ++organization_id : uuid ++project_id : uuid ++keyword : string ++category : string ++priority : int ++search_volume : int ++competition_level : string ++status : string ++created_at : datetime ++organization ++project +} +class PublishRecord { ++id : string ++organization_id : string ++content_title : string ++content_id : string ++platform : string ++published_url : string ++status : string ++published_at : datetime ++created_at : datetime ++metrics +} +class ContentMetrics { ++id : string ++publish_record_id : string ++recorded_at : datetime ++views : int ++likes : int ++comments : int ++shares : int ++bookmarks : int ++ai_citation_count : int ++search_impressions : int ++search_clicks : int ++avg_read_duration : float ++read_completion_rate : float ++publish_record +} +class OptimizationInsight { ++id : string ++organization_id : string ++content_id : string ++insight_type : string ++title : string ++description : string ++recommendation : string ++severity : string ++applied : bool ++created_at : datetime ++organization +} +class Alert { ++id : uuid ++brand_id : uuid ++user_id : uuid ++alert_type : string ++severity : string ++title : string ++message : string ++data : dict ++is_read : bool ++created_at : datetime ++brand +} +class AlertSetting { ++id : uuid ++brand_id : uuid ++user_id : uuid ++alert_type : string ++enabled : bool ++threshold : float ++created_at : datetime ++updated_at : datetime ++brand +user } -User "1" <-- "many" Query : "拥有" -Query "1" <-- "many" CitationRecord : "产生" -Query "1" <-- "many" QueryTask : "触发" -User "1" <-- "many" Subscription : "订阅" +class KnowledgeBase { ++id : uuid ++organization_id : uuid ++name : string ++type : string ++description : string ++document_count : int ++status : string ++created_by : uuid ++created_at : datetime ++updated_at : datetime ++organization ++creator ++documents +} +class KnowledgeDocument { ++id : uuid ++knowledge_base_id : uuid ++title : string ++source_type : string ++source_url : string ++content : string ++content_hash : string ++chunk_count : int ++status : string ++error_message : string ++metadata : dict ++created_at : datetime ++updated_at : datetime ++knowledge_base ++chunks +} +class KnowledgeChunk { ++id : uuid ++document_id : uuid ++content : string ++embedding : vector ++chunk_index : int ++token_count : int ++metadata : dict ++created_at : datetime ++document +} +class KnowledgeSearchLog { ++id : uuid ++organization_id : uuid ++user_id : uuid ++query : string ++knowledge_base_ids : list ++results_count : int ++latency_ms : int ++created_at : datetime ++organization ++user +} +User "1" <-- "many" Organization : "属于" +Organization "1" <-- "many" LifecycleProject : "拥有" +LifecycleProject "1" <-- "many" ProjectStage : "包含" +User "1" <-- "many" LifecycleProject : "创建" +AgentRegistry "1" <-- "many" AgentTask : "注册" +AgentTask "1" <-- "many" AgentTaskLog : "产生" +Organization "1" <-- "many" Content : "拥有" +LifecycleProject "1" <-- "many" Content : "关联" +User "1" <-- "many" Content : "创建" +Content "1" <-- "many" ContentVersion : "版本化" +Content "1" <-- "many" ContentReview : "审核" +Organization "1" <-- "many" PlatformRule : "拥有" +Organization "1" <-- "many" BrandKnowledge : "拥有" +Organization "1" <-- "many" Keyword : "拥有" +LifecycleProject "1" <-- "many" Keyword : "关联" +Organization "1" <-- "many" KnowledgeBase : "拥有" +KnowledgeBase "1" <-- "many" KnowledgeDocument : "包含" +KnowledgeDocument "1" <-- "many" KnowledgeChunk : "分块" +Organization "1" <-- "many" PublishRecord : "拥有" +PublishRecord "1" <-- "many" ContentMetrics : "产生" +Organization "1" <-- "many" OptimizationInsight : "拥有" +User "1" <-- "many" Alert : "拥有" +User "1" <-- "many" AlertSetting : "拥有" +Organization "1" <-- "many" KnowledgeSearchLog : "拥有" +User "1" <-- "many" KnowledgeSearchLog : "使用" ``` -图表来源 +**图表来源** - [backend/app/models/user.py:11-48](file://backend/app/models/user.py#L11-L48) -- [backend/app/models/query.py:11-48](file://backend/app/models/query.py#L11-L48) -- [backend/app/models/citation_record.py:11-44](file://backend/app/models/citation_record.py#L11-L44) -- [backend/app/models/query_task.py:11-34](file://backend/app/models/query_task.py#L11-L34) -- [backend/app/models/subscription.py:11-36](file://backend/app/models/subscription.py#L11-L36) +- [backend/app/models/lifecycle.py:12-92](file://backend/app/models/lifecycle.py#L12-L92) +- [backend/app/models/analytics.py:9-64](file://backend/app/models/analytics.py#L9-L64) +- [backend/app/models/alert.py:24-75](file://backend/app/models/alert.py#L24-L75) +- [backend/app/models/knowledge.py:22-213](file://backend/app/models/knowledge.py#L22-L213) -章节来源 +**章节来源** - [backend/app/models/user.py:1-48](file://backend/app/models/user.py#L1-L48) -- [backend/app/models/query.py:1-55](file://backend/app/models/query.py#L1-L55) -- [backend/app/models/citation_record.py:1-44](file://backend/app/models/citation_record.py#L1-L44) -- [backend/app/models/query_task.py:1-39](file://backend/app/models/query_task.py#L1-L39) -- [backend/app/models/subscription.py:1-37](file://backend/app/models/subscription.py#L1-L37) +- [backend/app/models/lifecycle.py:1-92](file://backend/app/models/lifecycle.py#L1-L92) +- [backend/app/models/analytics.py:1-64](file://backend/app/models/analytics.py#L1-L64) +- [backend/app/models/alert.py:1-75](file://backend/app/models/alert.py#L1-L75) +- [backend/app/models/knowledge.py:1-213](file://backend/app/models/knowledge.py#L1-L213) ### 数据库迁移管理、版本控制与部署策略 - 迁移入口 @@ -442,13 +1153,19 @@ User "1" <-- "many" Subscription : "订阅" - 迁移版本 - **初始版本** (488d0bd5ab01):创建 users、queries、citation_records、query_tasks、subscriptions 表,并建立必要索引。 - **版本2** (b2c4d6e8fa10):向 citation_records 表添加 confidence 和 match_type 字段,支持增强的报告功能。 - - **新增版本3** (c3d5e7f9ab12):向 users 表添加 email_verified、verification_code、verification_code_expires、reset_token、reset_token_expires、avatar_url、is_admin 等用户管理字段。 + - **版本3** (c3d5e7f9ab12):向 users 表添加 email_verified、verification_code、verification_code_expires、reset_token、reset_token_expires、avatar_url、is_admin 等用户管理字段。 + - **新增版本4** (d4f6g8h0ab23):新增完整的业务生命周期架构,包括 organizations、lifecycle_projects、project_stages、agent_registry、agent_configs、agent_tasks、agent_task_logs、contents、content_versions、content_reviews、platform_rules、brand_knowledge、keywords 等表。 + - **新增版本5** (e5f7a9b1cd34):新增告警系统,包括 alerts 和 alert_settings 表,支持品牌监控和用户告警。 + - **新增版本6** (e5f7g9h1cd45):新增知识库系统,包括 knowledge_bases、knowledge_documents、knowledge_chunks(含向量索引)、knowledge_search_logs 表,支持pgvector向量检索。 + - **新增版本7** (f6g8h0i2de56):新增分析监控系统,包括 publish_records、content_metrics、optimization_insights 表。 - 外键约束与级联删除策略明确,确保数据一致性。 - 部署策略 - Docker Compose 启动 PostgreSQL 与 Redis,应用容器依赖数据库健康检查。 - 生产环境建议将数据库与缓存分离,使用独立卷持久化数据。 + - **新增** 向量数据库部署:知识库功能需要pgvector扩展支持。 + - **新增** 分区策略:大数据量表建议按时间分区,如content_metrics、knowledge_search_logs。 -**更新** 新增c3d5e7f9ab12迁移版本,支持完整的用户管理功能。 +**更新** 新增完整的7个版本迁移,涵盖业务生命周期、分析监控、告警系统、知识库等企业级功能。 ```mermaid flowchart TD @@ -463,44 +1180,74 @@ RunMigs --> Version{"检查版本"} Version --> |488d0bd5ab01| InitMigration["初始迁移"] Version --> |b2c4d6e8fa10| AddConfidence["添加置信度字段"] Version --> |c3d5e7f9ab12| AddUserFields["添加用户管理字段"] -InitMigration --> AddConfidence --> AddUserFields --> Done(["完成"]) +Version --> |d4f6g8h0ab23| AddLifecycle["添加生命周期架构"] +Version --> |e5f7a9b1cd34| AddAlerts["添加告警系统"] +Version --> |e5f7g9h1cd45| AddKnowledge["添加知识库系统"] +Version --> |f6g8h0i2de56| AddAnalytics["添加分析监控"] +InitMigration --> AddConfidence --> AddUserFields --> AddLifecycle --> AddAlerts --> AddKnowledge --> AddAnalytics --> Done(["完成"]) ``` -图表来源 +**图表来源** - [backend/alembic/env.py:33-88](file://backend/alembic/env.py#L33-L88) - [backend/alembic/versions/488d0bd5ab01_initial_migration.py:21-128](file://backend/alembic/versions/488d0bd5ab01_initial_migration.py#L21-L128) - [backend/alembic/versions/b2c4d6e8fa10_add_confidence_match_type_to_citation_records.py:21-37](file://backend/alembic/versions/b2c4d6e8fa10_add_confidence_match_type_to_citation_records.py#L21-L37) - [backend/alembic/versions/c3d5e7f9ab12_add_user_management_fields.py:21-41](file://backend/alembic/versions/c3d5e7f9ab12_add_user_management_fields.py#L21-L41) +- [backend/alembic/versions/d4f6g8h0ab23_add_geo_lifecycle_tables.py:21-398](file://backend/alembic/versions/d4f6g8h0ab23_add_geo_lifecycle_tables.py#L21-L398) +- [backend/alembic/versions/e5f7a9b1cd34_add_alerts_and_alert_settings_tables.py:21-86](file://backend/alembic/versions/e5f7a9b1cd34_add_alerts_and_alert_settings_tables.py#L21-L86) +- [backend/alembic/versions/e5f7g9h1cd45_add_knowledge_base_tables.py:21-224](file://backend/alembic/versions/e5f7g9h1cd45_add_knowledge_base_tables.py#L21-L224) +- [backend/alembic/versions/f6g8h0i2de56_add_analytics_tables.py:20-125](file://backend/alembic/versions/f6g8h0i2de56_add_analytics_tables.py#L20-L125) - [docker-compose.yml:1-71](file://docker-compose.yml#L1-L71) -章节来源 +**章节来源** - [backend/alembic/env.py:1-89](file://backend/alembic/env.py#L1-L89) - [backend/alembic/versions/488d0bd5ab01_initial_migration.py:1-128](file://backend/alembic/versions/488d0bd5ab01_initial_migration.py#L1-L128) - [backend/alembic/versions/b2c4d6e8fa10_add_confidence_match_type_to_citation_records.py:1-37](file://backend/alembic/versions/b2c4d6e8fa10_add_confidence_match_type_to_citation_records.py#L1-L37) - [backend/alembic/versions/c3d5e7f9ab12_add_user_management_fields.py:1-41](file://backend/alembic/versions/c3d5e7f9ab12_add_user_management_fields.py#L1-L41) +- [backend/alembic/versions/d4f6g8h0ab23_add_geo_lifecycle_tables.py:1-398](file://backend/alembic/versions/d4f6g8h0ab23_add_geo_lifecycle_tables.py#L1-L398) +- [backend/alembic/versions/e5f7a9b1cd34_add_alerts_and_alert_settings_tables.py:1-86](file://backend/alembic/versions/e5f7a9b1cd34_add_alerts_and_alert_settings_tables.py#L1-L86) +- [backend/alembic/versions/e5f7g9h1cd45_add_knowledge_base_tables.py:1-224](file://backend/alembic/versions/e5f7g9h1cd45_add_knowledge_base_tables.py#L1-L224) +- [backend/alembic/versions/f6g8h0i2de56_add_analytics_tables.py:1-125](file://backend/alembic/versions/f6g8h0i2de56_add_analytics_tables.py#L1-L125) - [docker-compose.yml:1-71](file://docker-compose.yml#L1-L71) ### 数据完整性约束、事务处理与并发控制 - 完整性约束 - - 唯一约束:用户邮箱唯一 - - 外键约束:查询、任务、订阅均对用户做级联删除 - - JSONB 字段默认值:空数组/字典,避免 NULL 导致的条件判断复杂化 - - **新增** email_verified字段默认False,is_admin字段默认False - - **新增** verification_code长度限制为6位,reset_token长度限制为255位 - - **新增** avatar_url长度限制为500字符,match_type长度限制为20字符 + - 唯一约束:用户邮箱唯一,组织slug唯一,代理name唯一,关键词(organization_id, project_id, keyword)唯一,代理配置(agent_id, config_key)唯一,项目阶段(project_id, stage_number)唯一,告警设置(brand_id, alert_type)唯一。 + - 外键约束:所有外键均设置适当的ondelete策略(CASCADE/SET NULL),确保数据一致性。 + - JSONB字段默认值:空数组/字典,避免NULL导致的条件判断复杂化。 + - **新增** 组织表:max_members默认5,plan默认'free'。 + - **新增** 生命周期项目表:current_stage默认1,status默认'active'。 + - **新增** 项目阶段表:stage_number非空,status默认'pending'。 + - **新增** 代理注册表:name唯一,status默认'offline'。 + - **新增** 代理配置表:config_key唯一,updated_at自动更新。 + - **新增** 代理任务表:多个默认值和索引字段。 + - **新增** 内容表:status默认'draft',current_version默认1。 + - **新增** 知识库表:document_count默认0,status默认'active'。 + - **新增** email_verified字段默认False,is_admin字段默认False。 + - **新增** verification_code长度限制为6位,reset_token长度限制为255位。 + - **新增** avatar_url长度限制为500字符,match_type长度限制为20字符。 - 事务处理 - - 服务层方法在单个事务内执行插入/更新/删除,提交后刷新对象状态 - - 会话工厂设置 expire_on_commit=False,减少后续查询的额外开销 + - 服务层方法在单个事务内执行插入/更新/删除,提交后刷新对象状态。 + - 会话工厂设置 expire_on_commit=False,减少后续查询的额外开销。 + - **新增** 生命周期服务:事务边界严格控制项目状态转换。 + - **新增** 分析监控服务:发布记录与指标的原子性操作。 + - **新增** 告警引擎服务:告警规则评估的事务一致性。 + - **新增** 知识库服务:文档处理与向量嵌入的事务保障。 - 并发控制 - - 异步连接池与会话隔离,避免阻塞 - - 服务层在执行前进行权限校验与配额检查,降低并发冲突概率 + - 异步连接池与会话隔离,避免阻塞。 + - 服务层在执行前进行权限校验与配额检查,降低并发冲突概率。 + - **新增** 向量索引并发:HNSW索引支持高并发相似度搜索。 + - **新增** 分布式锁:代理任务的分布式并发控制。 -**更新** 新增用户管理字段的完整性约束说明,包括长度限制和默认值设置。 +**更新** 新增针对所有新增表的完整性约束说明,包括复合唯一约束和外键策略。 -章节来源 +**章节来源** - [backend/alembic/versions/488d0bd5ab01_initial_migration.py:36-111](file://backend/alembic/versions/488d0bd5ab01_initial_migration.py#L36-L111) - [backend/alembic/versions/b2c4d6e8fa10_add_confidence_match_type_to_citation_records.py:21-37](file://backend/alembic/versions/b2c4d6e8fa10_add_confidence_match_type_to_citation_records.py#L21-L37) - [backend/alembic/versions/c3d5e7f9ab12_add_user_management_fields.py:21-41](file://backend/alembic/versions/c3d5e7f9ab12_add_user_management_fields.py#L21-L41) +- [backend/alembic/versions/d4f6g8h0ab23_add_geo_lifecycle_tables.py:24-398](file://backend/alembic/versions/d4f6g8h0ab23_add_geo_lifecycle_tables.py#L24-L398) +- [backend/alembic/versions/e5f7a9b1cd34_add_alerts_and_alert_settings_tables.py:24-86](file://backend/alembic/versions/e5f7a9b1cd34_add_alerts_and_alert_settings_tables.py#L24-L86) +- [backend/alembic/versions/e5f7g9h1cd45_add_knowledge_base_tables.py:30-224](file://backend/alembic/versions/e5f7g9h1cd45_add_knowledge_base_tables.py#L30-L224) +- [backend/alembic/versions/f6g8h0i2de56_add_analytics_tables.py:24-125](file://backend/alembic/versions/f6g8h0i2de56_add_analytics_tables.py#L24-L125) - [backend/app/services/query.py:45-81](file://backend/app/services/query.py#L45-L81) - [backend/app/database.py:12-18](file://backend/app/database.py#L12-L18) @@ -519,26 +1266,30 @@ InitMigration --> AddConfidence --> AddUserFields --> Done(["完成"]) - **新增** 用户管理查询 - 支持按邮箱验证状态、管理员权限等条件过滤用户 - 支持验证码和重置令牌的有效性检查 +- **新增** 生命周期查询 + - 支持按组织、状态、品牌名称过滤项目 + - 支持按阶段状态和项目阶段组合查询 + - 支持项目全生命周期统计分析 +- **新增** 分析监控查询 + - 支持按平台、状态、时间范围过滤发布记录 + - 支持内容指标的时间序列分析 + - 支持优化洞察的分类统计 +- **新增** 告警查询 + - 支持按用户、品牌、告警类型、严重程度过滤 + - 支持告警设置的阈值比较查询 + - 支持用户未读告警的统计 +- **新增** 知识库查询 + - 支持向量相似度搜索(cosine距离) + - 支持知识库文档的状态过滤 + - 支持关键词检索和内容哈希去重 +- **新增** 性能优化 + - 知识库向量索引:HNSW近似最近邻搜索,支持大规模向量相似度计算 + - 复合索引:告警系统(brand_id, alert_type)、关键词(keyword)等 + - 分区策略:大表按时间分区,如content_metrics、knowledge_search_logs -**更新** 增强查询流程,支持新的用户管理字段和认证功能。 +**更新** 新增针对所有新增功能的查询流程和优化策略,特别是向量检索和复合查询的性能优化。 -```mermaid -sequenceDiagram -participant AuthAPI as "认证API" -participant SvcAuth as "认证服务" -participant DB as "数据库" -AuthAPI->>SvcAuth : register_user(email, password, name) -SvcAuth->>DB : INSERT INTO users (email, password_hash, name) -DB-->>SvcAuth : 新用户ID -SvcAuth->>DB : SELECT * FROM users WHERE email = ? -DB-->>SvcAuth : 用户信息 -SvcAuth-->>AuthAPI : UserResponse -``` - -图表来源 -- [backend/app/services/auth.py:40-56](file://backend/app/services/auth.py#L40-L56) - -章节来源 +**章节来源** - [backend/app/services/query.py:12-32](file://backend/app/services/query.py#L12-L32) - [backend/app/services/citation.py:30-79](file://backend/app/services/citation.py#L30-L79) - [backend/app/services/auth.py:40-56](file://backend/app/services/auth.py#L40-L56) @@ -558,7 +1309,7 @@ SvcAuth-->>AuthAPI : UserResponse **新增** 报告功能章节,详细介绍新增的confidence和match_type字段的应用。 -章节来源 +**章节来源** - [backend/app/services/citation.py:298-308](file://backend/app/services/citation.py#L298-L308) - [backend/app/services/citation.py:342-429](file://backend/app/services/citation.py#L342-L429) - [backend/app/schemas/citation.py:7-18](file://backend/app/schemas/citation.py#L7-L18) @@ -578,15 +1329,121 @@ SvcAuth-->>AuthAPI : UserResponse - **管理员权限控制** - is_admin字段标识管理员身份 - 支持管理员专用功能和权限控制 +- **组织管理** + - **新增** organization_id字段关联用户到组织 + - **新增** role字段标识用户在组织中的角色 + - **新增** 支持多组织成员管理 **新增** 用户管理功能章节,详细介绍新增的用户管理字段和相关API。 -章节来源 +**章节来源** - [backend/app/services/auth.py:74-107](file://backend/app/services/auth.py#L74-L107) - [backend/app/services/auth.py:110-140](file://backend/app/services/auth.py#L110-L140) - [backend/app/schemas/auth.py:8-55](file://backend/app/schemas/auth.py#L8-L55) - [backend/app/api/auth.py:33-115](file://backend/app/api/auth.py#L33-L115) +### 业务生命周期管理 +- **组织管理** + - 组织作为业务单元,支持多用户协作 + - plan字段支持免费/付费计划管理 + - max_members限制组织规模 +- **项目管理** + - lifecycle_projects表管理品牌项目全生命周期 + - current_stage跟踪项目当前所处阶段 + - status支持active/inactive状态管理 +- **阶段管理** + - project_stages表管理项目各阶段状态 + - 支持started_at/completed_at时间跟踪 + - metrics字段存储阶段关键指标 +- **代理系统** + - agent_registry注册可用代理 + - agent_configs管理代理配置 + - agent_tasks执行代理任务 + - agent_task_logs记录任务执行日志 +- **内容管理** + - contents表管理内容创作 + - content_versions支持版本控制 + - content_reviews支持审核流程 +- **规则管理** + - platform_rules定义平台合规规则 + - 支持不同严重程度的规则 +- **知识管理** + - brand_knowledge存储品牌知识 + - 支持分类和激活状态管理 +- **关键词管理** + - keywords管理SEO关键词 + - 支持优先级和搜索量统计 + +**新增** 业务生命周期管理章节,详细介绍完整的项目管理架构。 + +**章节来源** +- [backend/app/models/lifecycle.py:12-92](file://backend/app/models/lifecycle.py#L12-L92) +- [backend/app/api/lifecycle.py](file://backend/app/api/lifecycle.py) + +### 分析监控系统 +- **发布管理** + - publish_records跟踪内容发布状态 + - 支持多平台发布(微信、知乎、小红书等) + - published_url记录发布链接 +- **指标分析** + - content_metrics收集互动指标(点赞、评论、分享等) + - GEO核心指标:AI引用次数、搜索曝光、搜索点击 + - 阅读指标:平均阅读时长、完读率 +- **优化洞察** + - optimization_insights提供内容优化建议 + - 支持不同类型洞察(趋势、异常、机会、建议) + - severity字段标识严重程度 + - applied字段跟踪建议实施状态 + +**新增** 分析监控系统章节,详细介绍内容发布和指标分析架构。 + +**章节来源** +- [backend/app/models/analytics.py:9-64](file://backend/app/models/analytics.py#L9-L64) +- [backend/app/api/analytics.py](file://backend/app/api/analytics.py) + +### 告警系统 +- **告警类型** + - score_drop:评分下降告警 + - score_rise:评分上升告警 + - negative_sentiment:负面情绪告警 + - competitor_overtake:竞争对手超越告警 + - new_platform_mention:新平台提及告警 +- **严重程度** + - critical:严重 + - warning:警告 + - info:信息 +- **告警设置** + - alert_settings表管理用户告警偏好 + - 支持阈值设置和启用状态控制 + - 支持按品牌和用户维度配置 + +**新增** 告警系统章节,详细介绍实时监控和告警机制。 + +**章节来源** +- [backend/app/models/alert.py:24-75](file://backend/app/models/alert.py#L24-L75) +- [backend/app/api/alerts.py](file://backend/app/api/alerts.py) + +### 知识库系统 +- **向量检索** + - knowledge_chunks表存储文档分块 + - embedding字段使用pgvector向量类型 + - HNSW索引支持近似最近邻搜索 + - 维度1536匹配OpenAI text-embedding-3-small +- **文档管理** + - knowledge_documents管理知识文档 + - content_hash去重机制 + - 支持多种文档类型(text、url、pdf、markdown) +- **检索日志** + - knowledge_search_logs记录检索行为 + - 支持延迟毫秒统计 + - 支持知识库ID列表过滤 + +**新增** 知识库系统章节,详细介绍向量检索和RAG应用架构。 + +**章节来源** +- [backend/app/models/knowledge.py:22-213](file://backend/app/models/knowledge.py#L22-L213) +- [backend/app/api/knowledge.py](file://backend/app/api/knowledge.py) + ## 依赖分析 - 模块耦合 - 模型层仅依赖 Base 与 SQLAlchemy 类型,低耦合 @@ -594,11 +1451,17 @@ SvcAuth-->>AuthAPI : UserResponse - Alembic 依赖 Base 与配置,迁移脚本与模型同步演进 - **新增** API层依赖服务层,提供RESTful接口 - **新增** 认证API依赖认证服务,处理用户注册、登录、验证等 + - **新增** 生命周期API依赖生命周期服务,管理项目全生命周期 + - **新增** 分析监控API依赖分析监控服务,处理发布和指标 + - **新增** 告警API依赖告警引擎服务,处理实时告警 + - **新增** 知识库API依赖知识库服务,处理向量检索 - 外部依赖 - PostgreSQL 异步驱动(asyncpg) - Redis(用于缓存,如需要) + - **新增** pgvector扩展(向量检索) + - **新增** 向量数据库(可选) -**更新** 新增API层依赖关系,支持新的认证和报告功能接口。 +**更新** 新增针对所有新增功能模块的依赖关系分析。 ```mermaid graph LR @@ -606,19 +1469,25 @@ Cfg["配置
config.py"] --> DB["数据库引擎
database.py"] DB --> Models["ORM 模型
models/*"] Models --> Services["服务层
services/*"] Services --> AuthAPI["认证API
api/auth.py"] -Services --> API["API层
api/*"] +Services --> LifeCycleAPI["生命周期API
api/lifecycle.py"] +Services --> AnalyticsAPI["分析监控API
api/analytics.py"] +Services --> AlertsAPI["告警API
api/alerts.py"] +Services --> KnowledgeAPI["知识库API
api/knowledge.py"] +Services --> CitationsAPI["引用API
api/citations.py"] +Services --> ReportsAPI["报告API
api/reports.py"] Alembic["迁移
alembic/*"] --> DB Docker["编排
docker-compose.yml"] --> DB +Vector["向量数据库
pgvector"] --> DB ``` -图表来源 +**图表来源** - [backend/app/config.py:1-23](file://backend/app/config.py#L1-L23) - [backend/app/database.py:1-29](file://backend/app/database.py#L1-L29) - [backend/app/models/__init__.py:1-14](file://backend/app/models/__init__.py#L1-L14) - [backend/alembic/env.py:1-89](file://backend/alembic/env.py#L1-L89) - [docker-compose.yml:1-71](file://docker-compose.yml#L1-L71) -章节来源 +**章节来源** - [backend/app/config.py:1-23](file://backend/app/config.py#L1-L23) - [backend/app/database.py:1-29](file://backend/app/database.py#L1-L29) - [backend/app/models/__init__.py:1-14](file://backend/app/models/__init__.py#L1-L14) @@ -629,7 +1498,12 @@ Docker["编排
docker-compose.yml"] --> DB - 索引优化 - 为高频过滤字段建立单列索引(user_id/status/next_query_at/platform/queried_at/confidence/match_type) - 对 JSONB 字段可考虑 GIN 索引(如需复杂查询),当前迁移脚本未启用 - - **新增** 为用户管理字段建立索引:email、verification_code、reset_token + - **新增** 为用户管理字段建立索引:email、organization_id、verification_code、reset_token + - **新增** 为生命周期表建立复合索引:(organization_id, status)、(project_id, stage_number)、(brand_id, keyword) + - **新增** 为代理系统建立复合索引:(agent_id, status)、(organization_id, project_id)、(created_by, task_type) + - **新增** 为分析监控建立复合索引:(organization_id, platform)、(publish_record_id, recorded_at) + - **新增** 为告警系统建立复合索引:(brand_id, alert_type)、(user_id, is_read)、(organization_id, insight_type) + - **新增** 为知识库建立向量索引:HNSW(cosine)支持大规模相似度搜索 - **新增** 建议为confidence和match_type字段建立单独索引,支持高效过滤 - 查询优化 - 分页与计数分离,避免重复扫描 @@ -637,16 +1511,26 @@ Docker["编排
docker-compose.yml"] --> DB - 时间范围查询使用索引覆盖 - **新增** 支持按confidence范围和match_type进行高效过滤 - **新增** 支持按邮箱验证状态和管理员权限进行高效过滤 + - **新增** 支持向量相似度搜索的性能优化 + - **新增** 复合查询的索引选择性分析 - 缓存策略 - 引用统计与趋势数据可缓存至 Redis,设置合理过期时间 - 导出 CSV 可缓存热点查询结果,降低数据库压力 - **新增** 认证令牌和用户会话可缓存,提高认证效率 - **新增** 报告统计数据可缓存,提高频繁访问的响应速度 + - **新增** 知识库检索结果可缓存,降低向量搜索压力 + - **新增** 代理任务状态可缓存,提高任务调度效率 - 连接与并发 - 使用异步连接池,避免阻塞 - 控制并发度,避免大量写入导致锁争用 + - **新增** 向量索引并发控制,避免HNSW索引锁定 + - **新增** 分布式锁机制,确保代理任务并发安全 +- 存储优化 + - **新增** 分区策略:按月/季度分区content_metrics、knowledge_search_logs + - **新增** 归档策略:历史数据归档到冷存储 + - **新增** 压缩策略:JSONB字段压缩存储 -**更新** 新增针对用户管理字段和新功能的性能优化建议。 +**更新** 新增针对所有新增功能的性能优化建议,特别是向量检索和复合查询的优化策略。 ## 故障排查指南 - 迁移失败 @@ -654,23 +1538,44 @@ Docker["编排
docker-compose.yml"] --> DB - 确认数据库已初始化且用户具备权限 - **新增** 检查新字段的默认值和约束条件 - **新增** 验证用户管理字段的数据类型和长度限制 + - **新增** 验证pgvector扩展是否正确安装 + - **新增** 检查向量索引创建是否成功 - 查询异常 - 核对服务层权限校验逻辑,确认 user_id 与查询归属一致 - 检查索引是否存在,必要时重建索引 - **新增** 验证confidence和match_type字段的数据类型和取值范围 - **新增** 检查用户管理字段的验证逻辑和过期时间 + - **新增** 验证生命周期表的外键约束和级联删除 + - **新增** 检查向量索引的HNSW配置和性能 - 导出失败 - 确认查询所有权校验通过 - 检查 CSV 写入逻辑与字符编码 - **新增** 验证新字段在导出过程中的处理逻辑 + - **新增** 检查向量数据的序列化处理 - **新增** 认证功能故障 - 检查JWT密钥配置和令牌生成 - 验证验证码和重置令牌的有效性 - 确认邮箱验证流程的正确性 +- **新增** 生命周期功能故障 + - 检查项目阶段转换的业务规则 + - 验证代理任务的调度和执行 + - 确认内容版本控制的完整性 +- **新增** 分析监控故障 + - 检查发布记录的状态流转 + - 验证指标数据的采集和存储 + - 确认优化洞察的生成逻辑 +- **新增** 告警系统故障 + - 检查告警规则的配置和阈值 + - 验证告警通知的发送机制 + - 确认告警设置的用户偏好 +- **新增** 知识库故障 + - 检查向量嵌入的生成和存储 + - 验证相似度搜索的准确性 + - 确认文档去重和分块的处理 -**更新** 新增针对用户管理功能和新字段的故障排查指导。 +**更新** 新增针对所有新增功能的故障排查指导,包括向量检索和生命周期管理的专项排查。 -章节来源 +**章节来源** - [backend/alembic/env.py:33-88](file://backend/alembic/env.py#L33-L88) - [backend/app/services/citation.py:14-22](file://backend/app/services/citation.py#L14-L22) - [backend/app/services/auth.py:74-107](file://backend/app/services/auth.py#L74-L107) @@ -678,7 +1583,9 @@ Docker["编排
docker-compose.yml"] --> DB ## 结论 本数据库设计围绕用户、查询、引用记录、任务与订阅五大实体展开,采用 PostgreSQL + SQLAlchemy Async + Alembic 的成熟技术栈,具备良好的扩展性与可维护性。通过合理的索引策略、事务边界与服务层封装,能够满足日常查询、统计与导出需求。 -**更新** 新增的用户管理功能显著增强了系统的完整性和安全性,提供了完整的认证、授权和用户管理能力。新增的confidence和match_type字段显著增强了报告功能,提供了更精细的引用质量分析能力。建议在生产环境中进一步引入缓存与监控,持续优化查询路径与索引覆盖。 +**更新** 新增的完整业务生命周期、分析监控、告警系统、知识库等企业级功能架构,形成了从用户管理到智能代理的完整数据体系。新增的组织管理、项目阶段、代理系统、向量检索等功能显著增强了系统的业务能力和智能化水平。 + +**更新** 新增的7个迁移版本涵盖了从基础用户管理到高级AI功能的完整演进路径。建议在生产环境中进一步引入缓存与监控,持续优化查询路径与索引覆盖,特别是向量检索和复合查询的性能优化。 ## 附录 - 部署与运维 @@ -686,15 +1593,30 @@ Docker["编排
docker-compose.yml"] --> DB - 生产环境建议使用独立数据库实例与只读副本,配合连接池与慢查询日志 - **新增** 升级时确保迁移脚本按顺序执行,从初始版本到最新版本 - **新增** 配置JWT密钥和Redis缓存,确保认证功能正常运行 + - **新增** 部署pgvector扩展,确保向量检索功能正常 + - **新增** 配置向量数据库集群,支持大规模向量相似度搜索 - 备份与恢复 - 使用 pg_dump/pg_restore 进行逻辑备份与恢复 - 对关键表定期增量备份,结合 WAL 归档实现点-in-time 恢复 - **新增** 新字段变更需要纳入备份策略,确保数据完整性 - **新增** 用户管理字段包含敏感信息,需要特别注意备份安全 + - **新增** 向量数据需要特殊备份策略,确保embedding数据完整性 - 监控与告警 - 监控连接数、查询延迟、索引命中率与慢查询 - 对迁移脚本变更进行版本化管理与回滚演练 - **新增** 监控新字段的使用情况和性能影响 - **新增** 监控用户认证和验证功能的运行状态 + - **新增** 监控代理任务的执行状态和性能 + - **新增** 监控向量索引的查询性能和内存使用 + - **新增** 监控知识库的检索准确性和响应时间 +- 性能调优 + - **新增** 向量检索性能调优:HNSW索引参数优化、并发查询控制 + - **新增** 复合查询性能调优:索引选择性分析、查询计划优化 + - **新增** 分区表性能调优:分区策略选择、数据分布优化 + - **新增** 缓存策略优化:热点数据识别、缓存失效策略 +- 安全加固 + - **新增** 向量数据加密存储:敏感embedding数据保护 + - **新增** 访问控制增强:基于组织的角色权限管理 + - **新增** 审计日志完善:所有数据变更的审计追踪 -**更新** 新增针对用户管理功能和新字段的部署和运维指导。 \ No newline at end of file +**更新** 新增针对所有新增功能的部署和运维指导,包括向量数据库部署、性能调优和安全加固等专项内容。 \ No newline at end of file diff --git a/.qoder/repowiki/zh/content/测试策略/测试策略.md b/.qoder/repowiki/zh/content/测试策略/测试策略.md index 65727ca..66116f3 100644 --- a/.qoder/repowiki/zh/content/测试策略/测试策略.md +++ b/.qoder/repowiki/zh/content/测试策略/测试策略.md @@ -7,8 +7,15 @@ - [tests/test_business_flow.py](file://tests/test_business_flow.py) - [tests/test_citation_engine.py](file://tests/test_citation_engine.py) - [tests/test_citations.py](file://tests/test_citations.py) +- [tests/test_content_agents.py](file://tests/test_content_agents.py) +- [tests/test_llm_provider.py](file://tests/test_llm_provider.py) +- [tests/test_pipeline_engine.py](file://tests/test_pipeline_engine.py) +- [tests/test_platform_rules.py](file://tests/test_platform_rules.py) +- [tests/test_prompt_template.py](file://tests/test_prompt_template.py) - [tests/test_queries.py](file://tests/test_queries.py) +- [tests/test_rag_service.py](file://tests/test_rag_service.py) - [tests/test_scheduler.py](file://tests/test_scheduler.py) +- [backend/tests/test_integration/test_full_flow.py](file://backend/tests/test_integration/test_full_flow.py) - [backend/app/main.py](file://backend/app/main.py) - [backend/app/api/deps.py](file://backend/app/api/deps.py) - [backend/app/services/auth.py](file://backend/app/services/auth.py) @@ -19,14 +26,22 @@ - [backend/app/api/queries.py](file://backend/app/api/queries.py) - [backend/app/database.py](file://backend/app/database.py) - [backend/app/config.py](file://backend/app/config.py) +- [backend/app/agent_framework/agents/content_generator_agent.py](file://backend/app/agent_framework/agents/content_generator_agent.py) +- [backend/app/agent_framework/agents/deai_agent.py](file://backend/app/agent_framework/agents/deai_agent.py) +- [backend/app/agent_framework/agents/geo_optimizer_agent.py](file://backend/app/agent_framework/agents/geo_optimizer_agent.py) +- [backend/app/agent_framework/pipeline/engine.py](file://backend/app/agent_framework/pipeline/engine.py) +- [backend/app/agent_framework/pipeline/loader.py](file://backend/app/agent_framework/pipeline/loader.py) +- [backend/app/services/llm/factory.py](file://backend/app/services/llm/factory.py) ## 更新摘要 **变更内容** -- 新增业务流程测试章节,涵盖端到端业务场景测试 -- 新增调度器测试章节,包括定时任务调度和频率计算测试 -- 完善测试最佳实践,增加业务流程测试和调度器测试的最佳实践指导 -- 更新测试策略以反映新增的测试覆盖范围 +- 新增代理框架测试章节,涵盖ContentGeneratorAgent、DeAIAgent、GEOOptimizerAgent的单元测试策略 +- 新增LLM提供者测试章节,包括LLMFactory工厂模式测试、OpenAIProvider和DeepSeekProvider测试 +- 新增管道引擎测试章节,涵盖PipelineLoader和PipelineEngine的单元测试策略 +- 新增端到端工作流测试章节,涵盖完整业务流程的集成测试 +- 完善测试最佳实践,增加代理框架测试、LLM提供者测试、管道引擎测试和端到端工作流测试的最佳实践指导 +- 更新测试策略以反映新增的测试覆盖范围和架构扩展 ## 目录 1. [引言](#引言) @@ -34,19 +49,23 @@ 3. [核心组件](#核心组件) 4. [架构总览](#架构总览) 5. [详细组件分析](#详细组件分析) -6. [业务流程测试策略](#业务流程测试策略) -7. [调度器测试策略](#调度器测试策略) -8. [依赖分析](#依赖分析) -9. [性能考虑](#性能考虑) -10. [故障排查指南](#故障排查指南) -11. [结论](#结论) -12. [附录](#附录) +6. [代理框架测试策略](#代理框架测试策略) +7. [LLM提供者测试策略](#llm提供者测试策略) +8. [管道引擎测试策略](#管道引擎测试策略) +9. [端到端工作流测试策略](#端到端工作流测试策略) +10. [业务流程测试策略](#业务流程测试策略) +11. [调度器测试策略](#调度器测试策略) +12. [依赖分析](#依赖分析) +13. [性能考虑](#性能考虑) +14. [故障排查指南](#故障排查指南) +15. [结论](#结论) +16. [附录](#附录) ## 引言 -本测试策略文档面向GEO项目的Pytest测试体系,覆盖单元测试、集成测试和业务流程测试的设计与实施要点。内容包括:测试夹具与模拟对象的组织方式、测试数据管理策略、认证模块、引用引擎、查询处理、业务流程和调度器等关键功能的测试用例设计思路;同时给出测试最佳实践,包括覆盖率目标、持续集成配置建议以及测试环境管理方案,并提供调试技巧与性能测试方法。 +本测试策略文档面向GEO项目的Pytest测试体系,覆盖单元测试、集成测试、业务流程测试和端到端工作流测试的设计与实施要点。内容包括:测试夹具与模拟对象的组织方式、测试数据管理策略、认证模块、引用引擎、查询处理、代理框架、LLM提供者、管道引擎、业务流程和调度器等关键功能的测试用例设计思路;同时给出测试最佳实践,包括覆盖率目标、持续集成配置建议以及测试环境管理方案,并提供调试技巧与性能测试方法。 ## 项目结构 -测试目录位于仓库根目录下的tests,采用按功能模块划分的组织方式,配合Pytest的conftest集中式夹具与模拟对象,确保测试隔离与可重复性。后端应用以FastAPI为核心,API层通过依赖注入获取当前用户与数据库会话,服务层封装业务逻辑,工作器(worker)负责异步任务与平台适配。 +测试目录位于仓库根目录下的tests,采用按功能模块划分的组织方式,配合Pytest的conftest集中式夹具与模拟对象,确保测试隔离与可重复性。后端应用以FastAPI为核心,API层通过依赖注入获取当前用户与数据库会话,服务层封装业务逻辑,工作器(worker)负责异步任务与平台适配。新增的代理框架、LLM提供者和管道引擎测试进一步完善了测试体系。 ```mermaid graph TB @@ -58,6 +77,10 @@ TC["tests/test_citations.py"] TCE["tests/test_citation_engine.py"] TB["tests/test_business_flow.py"] TS["tests/test_scheduler.py"] +TCA["tests/test_content_agents.py"] +TLP["tests/test_llm_provider.py"] +TPE["tests/test_pipeline_engine.py"] +TF["backend/tests/test_integration/test_full_flow.py"] end subgraph "后端应用" M["backend/app/main.py"] @@ -69,6 +92,12 @@ QUERIES_API["backend/app/api/queries.py"] CITATIONS_API["backend/app/api/citations.py"] CE["backend/app/workers/citation_engine.py"] QS["backend/app/workers/scheduler.py"] +CGA["backend/app/agent_framework/agents/content_generator_agent.py"] +DEAI["backend/app/agent_framework/agents/deai_agent.py"] +GEO["backend/app/agent_framework/agents/geo_optimizer_agent.py"] +PL["backend/app/agent_framework/pipeline/engine.py"] +LOADER["backend/app/agent_framework/pipeline/loader.py"] +FACTORY["backend/app/services/llm/factory.py"] end C --> TA C --> TQ @@ -76,6 +105,18 @@ C --> TC C --> TCE C --> TB C --> TS +C --> TCA +C --> TLP +C --> TPE +TF --> AUTH_API +TF --> QUERIES_API +TF --> CITATIONS_API +TCA --> CGA +TCA --> DEAI +TCA --> GEO +TLP --> FACTORY +TPE --> PL +TPE --> LOADER TA --> AUTH_API TQ --> QUERIES_API TC --> CITATIONS_API @@ -102,6 +143,12 @@ M --> CITATIONS_API - [backend/app/workers/scheduler.py:1-182](file://backend/app/workers/scheduler.py#L1-L182) - [backend/app/database.py:1-29](file://backend/app/database.py#L1-L29) - [backend/app/config.py:1-23](file://backend/app/config.py#L1-L23) +- [backend/app/agent_framework/agents/content_generator_agent.py:1-299](file://backend/app/agent_framework/agents/content_generator_agent.py#L1-L299) +- [backend/app/agent_framework/agents/deai_agent.py:1-156](file://backend/app/agent_framework/agents/deai_agent.py#L1-L156) +- [backend/app/agent_framework/agents/geo_optimizer_agent.py:1-198](file://backend/app/agent_framework/agents/geo_optimizer_agent.py#L1-L198) +- [backend/app/agent_framework/pipeline/engine.py:1-536](file://backend/app/agent_framework/pipeline/engine.py#L1-L536) +- [backend/app/agent_framework/pipeline/loader.py:1-283](file://backend/app/agent_framework/pipeline/loader.py#L1-L283) +- [backend/app/services/llm/factory.py:1-66](file://backend/app/services/llm/factory.py#L1-L66) **章节来源** - [tests/conftest.py:1-123](file://tests/conftest.py#L1-L123) @@ -114,19 +161,25 @@ M --> CITATIONS_API - 异步HTTP客户端:基于ASGI传输创建异步HTTP客户端,用于端到端API测试。 - 依赖覆盖:通过依赖注入覆盖当前用户解析逻辑,简化认证流程。 - 内存数据库:使用SQLite内存数据库进行集成测试,确保测试隔离性。 + - FakeLLMProvider:自定义FakeLLMProvider类,模拟LLM调用返回预设响应,避免真实网络请求。 + - AsyncMock:广泛使用AsyncMock替代真实异步操作,确保测试的确定性和可重复性。 - 测试数据管理 - 使用pytest fixture生成模拟模型对象(如查询、引用记录),保证测试数据一致性与可读性。 - 通过patch对服务层函数进行桩替,隔离外部依赖,提升测试确定性。 - 直接操作数据库模型进行复杂场景测试,如权限隔离和统计计算。 + - 代理框架测试中使用TaskMessage构建测试任务,模拟Agent执行流程。 - 测试运行与并发 - 使用pytest-asyncio标记异步测试,确保事件循环正确初始化与清理。 - 支持并行执行多个测试文件,提高测试执行效率。 + - 管道引擎测试中使用dry-run模式,通过dispatcher=None实现无真实任务分发的测试。 **章节来源** - [tests/conftest.py:19-123](file://tests/conftest.py#L19-L123) +- [tests/test_content_agents.py:26-54](file://tests/test_content_agents.py#L26-L54) +- [tests/test_pipeline_engine.py:148-166](file://tests/test_pipeline_engine.py#L148-L166) ## 架构总览 -下图展示了测试与被测系统的交互关系:测试通过异步HTTP客户端直接调用FastAPI路由,路由依赖当前用户与数据库会话,服务层完成业务逻辑,工作器负责平台查询与品牌匹配。 +下图展示了测试与被测系统的交互关系:测试通过异步HTTP客户端直接调用FastAPI路由,路由依赖当前用户与数据库会话,服务层完成业务逻辑,工作器负责平台查询与品牌匹配。新增的代理框架测试通过FakeLLMProvider模拟LLM调用,管道引擎测试通过dry-run模式验证Pipeline执行流程。 ```mermaid sequenceDiagram @@ -363,6 +416,275 @@ AC-->>T : 断言 - [tests/test_queries.py:1-154](file://tests/test_queries.py#L1-L154) - [backend/app/api/queries.py:1-86](file://backend/app/api/queries.py#L1-L86) +## 代理框架测试策略 + +### 测试目标 +代理框架测试专注于验证GEO平台的智能代理执行逻辑,包括内容生成代理、去AI化代理和GEO优化代理的功能完整性、错误处理能力和与LLM提供者的集成测试。 + +### 关键测试场景 +- **ContentGeneratorAgent测试**:选题生成、文章生成、RAG知识检索、JSON解析、错误处理 +- **DeAIAgent测试**:内容去AI化处理、温度参数验证、输入验证 +- **GEOOptimizerAgent测试**:SEO/GEO优化、JSON降级处理、关键词注入 +- **FakeLLMProvider测试**:模拟LLM调用、流式响应、错误模拟 + +### 测试实现策略 +- **FakeLLMProvider**:自定义FakeLLMProvider类,模拟LLM调用返回预设响应,避免真实网络请求 +- **AsyncMock**:广泛使用AsyncMock替代Redis、数据库和RAG服务调用 +- **patch技术**:通过patch替换LLMFactory.get_default和RAGService,隔离外部依赖 +- **TaskMessage构建**:使用_test_make_task辅助函数创建测试任务消息 + +```mermaid +classDiagram +class ContentGeneratorAgent { ++execute(task) TaskResult ++_generate_topics(task) dict ++_generate_article(task) dict ++_retrieve_knowledge(kb_ids, query) str ++_extract_json(text) str +} +class DeAIAgent { ++execute(task) TaskResult ++_process(task) dict +} +class GEOOptimizerAgent { ++execute(task) TaskResult ++_optimize(task) dict ++_extract_json(text) str +} +class FakeLLMProvider { ++chat(messages, **kwargs) LLMResponse ++chat_stream(messages, **kwargs) AsyncGenerator ++provider_name str ++model_name str ++max_context_length int +} +ContentGeneratorAgent --> FakeLLMProvider : "使用" +DeAIAgent --> FakeLLMProvider : "使用" +GEOOptimizerAgent --> FakeLLMProvider : "使用" +``` + +**图表来源** +- [tests/test_content_agents.py:26-54](file://tests/test_content_agents.py#L26-L54) +- [tests/test_content_agents.py:75-116](file://tests/test_content_agents.py#L75-L116) +- [tests/test_content_agents.py:200-236](file://tests/test_content_agents.py#L200-L236) +- [tests/test_content_agents.py:268-320](file://tests/test_content_agents.py#L268-L320) + +### 测试用例设计要点 +- **内容生成测试**:验证topics字段解析、article内容生成、word count计算、usage统计 +- **RAG集成测试**:通过AsyncSessionLocal mock验证知识检索上下文注入 +- **错误处理测试**:模拟LLMError验证failed状态返回和错误消息处理 +- **温度参数测试**:验证DeAIAgent的temperature=0.9配置 +- **JSON解析测试**:测试```json```包裹和普通文本两种输出格式 + +**章节来源** +- [tests/test_content_agents.py:1-358](file://tests/test_content_agents.py#L1-L358) +- [backend/app/agent_framework/agents/content_generator_agent.py:1-299](file://backend/app/agent_framework/agents/content_generator_agent.py#L1-L299) +- [backend/app/agent_framework/agents/deai_agent.py:1-156](file://backend/app/agent_framework/agents/deai_agent.py#L1-L156) +- [backend/app/agent_framework/agents/geo_optimizer_agent.py:1-198](file://backend/app/agent_framework/agents/geo_optimizer_agent.py#L1-L198) + +## LLM提供者测试策略 + +### 测试目标 +LLM提供者测试专注于验证GEO平台的LLM抽象层,包括工厂模式、OpenAIProvider和DeepSeekProvider的功能完整性、错误处理和流式响应处理。 + +### 关键测试场景 +- **LLMFactory测试**:工厂创建、默认提供者选择、未知提供者处理、提供者列表 +- **OpenAIProvider测试**:聊天响应、重试机制、错误处理、SSE流解析 +- **DeepSeekProvider测试**:基础功能验证、与OpenAIProvider对比 +- **LLMResponse测试**:响应结构验证、usage统计 + +### 测试实现策略 +- **环境变量设置**:通过monkeypatch设置OPENAI_API_KEY和DEEPSEEK_API_KEY +- **httpx模拟**:使用MagicMock模拟HTTP响应,测试各种状态码场景 +- **AsyncMock**:模拟异步HTTP客户端和SSE流响应 +- **重试机制测试**:通过patch asyncio.sleep避免真实等待时间 + +```mermaid +classDiagram +class LLMFactory { ++create(provider, model) LLMProvider ++get_default() LLMProvider ++list_providers() list[str] ++register(name, provider_cls) void +} +class OpenAIProvider { ++chat(messages) LLMResponse ++chat_stream(messages) AsyncGenerator ++provider_name str ++model_name str ++max_context_length int +} +class DeepSeekProvider { ++chat(messages) LLMResponse ++chat_stream(messages) AsyncGenerator ++provider_name str ++model_name str ++max_context_length int +} +class LLMProvider { +<> ++chat(messages) LLMResponse ++chat_stream(messages) AsyncGenerator ++provider_name str ++model_name str ++max_context_length int +} +LLMFactory --> LLMProvider : "创建" +LLMProvider <|-- OpenAIProvider +LLMProvider <|-- DeepSeekProvider +``` + +**图表来源** +- [tests/test_llm_provider.py:24-67](file://tests/test_llm_provider.py#L24-L67) +- [tests/test_llm_provider.py:94-153](file://tests/test_llm_provider.py#L94-L153) +- [tests/test_llm_provider.py:200-204](file://tests/test_llm_provider.py#L200-L204) +- [backend/app/services/llm/factory.py:8-66](file://backend/app/services/llm/factory.py#L8-L66) + +### 测试用例设计要点 +- **工厂模式测试**:验证create方法、默认提供者、未知提供者异常处理 +- **HTTP响应测试**:模拟200、429、401等不同状态码的处理逻辑 +- **重试机制测试**:验证429速率限制的重试行为和401不可重试的处理 +- **流式响应测试**:验证SSE流的逐token解析和完成信号处理 +- **响应结构测试**:验证LLMResponse的字段完整性和默认值 + +**章节来源** +- [tests/test_llm_provider.py:1-205](file://tests/test_llm_provider.py#L1-L205) +- [backend/app/services/llm/factory.py:1-66](file://backend/app/services/llm/factory.py#L1-L66) + +## 管道引擎测试策略 + +### 测试目标 +管道引擎测试专注于验证GEO平台的Pipeline编排能力,包括YAML加载、DAG验证、拓扑排序、变量解析和dry-run执行模式。 + +### 关键测试场景 +- **PipelineLoader测试**:YAML加载、DAG验证、拓扑排序、变量解析 +- **PipelineEngine测试**:dry-run模式、阶段执行、超时处理、重试机制 +- **变量解析测试**:简单变量替换、嵌套路径解析、上下文传递 +- **依赖关系测试**:有环图检测、无环图验证、执行顺序保证 + +### 测试实现策略 +- **YAML模板**:使用textwrap.dedent创建测试用YAML配置 +- **dry-run模式**:通过dispatcher=None实现无真实任务分发的测试 +- **AsyncMock**:模拟Agent执行和任务状态查询 +- **拓扑排序**:验证依赖关系的正确执行顺序 + +```mermaid +classDiagram +class PipelineLoader { ++load(pipeline_name) Pipeline ++load_from_yaml(yaml_content, pipeline_name) Pipeline ++validate_dag(stages) bool ++resolve_variables(template, context) Any +} +class PipelineEngine { ++execute(pipeline, context) PipelineResult ++_execute_stage(stage, exec_context, stages_context) StageResult ++_topological_sort(stages) list[PipelineStage] ++_resolve_stage_inputs(inputs, context) dict ++_should_skip(stage, failed_stages, skipped_stages) bool ++_evaluate_condition(condition, exec_context, stages_context) bool ++_extract_outputs(stage, output_data) dict +} +class Pipeline { ++name str ++version str ++description str ++variables dict ++stages list[PipelineStage] +} +class PipelineStage { ++name str ++agent str ++action str ++depends_on list[str] ++inputs dict ++outputs list[str] ++timeout_seconds int ++retry_count int ++condition str ++continue_on_failure bool +} +PipelineLoader --> Pipeline : "创建" +PipelineEngine --> Pipeline : "执行" +Pipeline --> PipelineStage : "包含" +``` + +**图表来源** +- [tests/test_pipeline_engine.py:55-98](file://tests/test_pipeline_engine.py#L55-L98) +- [tests/test_pipeline_engine.py:148-223](file://tests/test_pipeline_engine.py#L148-L223) +- [backend/app/agent_framework/pipeline/loader.py:41-134](file://backend/app/agent_framework/pipeline/loader.py#L41-L134) +- [backend/app/agent_framework/pipeline/engine.py:31-176](file://backend/app/agent_framework/pipeline/engine.py#L31-L176) + +### 测试用例设计要点 +- **YAML加载测试**:验证正常YAML的解析和Pipeline对象创建 +- **DAG验证测试**:测试有环图的异常处理和无环图的验证通过 +- **变量解析测试**:验证${var}和${stages.step1.outputs.result}等变量引用 +- **dry-run模式测试**:验证无dispatcher时的模拟执行和结果收集 +- **超时和重试测试**:验证阶段级别的超时控制和重试机制 + +**章节来源** +- [tests/test_pipeline_engine.py:1-255](file://tests/test_pipeline_engine.py#L1-L255) +- [backend/app/agent_framework/pipeline/loader.py:1-283](file://backend/app/agent_framework/pipeline/loader.py#L1-L283) +- [backend/app/agent_framework/pipeline/engine.py:1-536](file://backend/app/agent_framework/pipeline/engine.py#L1-L536) + +## 端到端工作流测试策略 + +### 测试目标 +端到端工作流测试专注于验证GEO平台的完整业务流程,包括品牌查询、竞争品牌管理、引用数据收集、评分计算和CSV导出的完整链路。 + +### 关键测试场景 +- **完整品牌查询流程**:品牌创建、竞争品牌添加、查询创建、引用数据模拟、评分计算、历史记录、统计聚合 +- **CSV导出流程**:品牌创建、查询创建、引用数据创建、CSV导出、内容验证 +- **错误处理流程**:不存在的品牌ID处理、404错误验证 + +### 测试实现策略 +- **异步数据库**:使用SQLite内存数据库和async_sessionmaker +- **依赖覆盖**:通过app.dependency_overrides覆盖get_db和get_current_user +- **测试数据构建**:直接操作模型类创建测试数据 +- **HTTP客户端**:使用AsyncClient和ASGITransport进行端到端测试 + +```mermaid +sequenceDiagram +participant T as "端到端测试" +participant AC as "AsyncClient" +participant API as "FastAPI路由" +participant DB as "异步数据库" +T->>AC : POST /api/v1/brands/ +AC->>API : 品牌创建 +API->>DB : 插入品牌记录 +API-->>AC : 201 + 品牌数据 +T->>AC : POST /api/v1/brands/{brand_id}/competitors/ +AC->>API : 添加竞争品牌 +API->>DB : 插入竞争品牌记录 +API-->>AC : 201 + 竞争品牌数据 +T->>AC : POST /api/v1/queries/ +AC->>API : 创建查询 +API->>DB : 插入查询记录 +API-->>AC : 201 + 查询数据 +T->>AC : POST /api/v1/citations/ +AC->>API : 创建引用记录 +API->>DB : 插入引用记录 +API-->>AC : 201 + 引用数据 +T->>AC : GET /api/v1/brands/{brand_id}/score/ +AC->>API : 获取品牌评分 +API->>DB : 查询引用统计 +API-->>AC : 200 + 评分数据 +``` + +**图表来源** +- [backend/tests/test_integration/test_full_flow.py:94-223](file://backend/tests/test_integration/test_full_flow.py#L94-L223) +- [backend/tests/test_integration/test_full_flow.py:228-298](file://backend/tests/test_integration/test_full_flow.py#L228-L298) + +### 测试用例设计要点 +- **数据隔离**:使用独立的异步数据库连接和会话 +- **依赖注入**:通过dependency_overrides确保测试环境的一致性 +- **流程完整性**:覆盖从品牌创建到最终评分的完整业务流程 +- **数据验证**:验证统计计算的准确性,如提及率、引用率等指标 +- **CSV内容验证**:验证导出文件的格式和关键字段存在性 + +**章节来源** +- [backend/tests/test_integration/test_full_flow.py:1-322](file://backend/tests/test_integration/test_full_flow.py#L1-L322) + ## 业务流程测试策略 ### 测试目标 @@ -484,11 +806,15 @@ QueryScheduler --> AsyncIOScheduler : "使用" - 测试通过ASGI传输直接调用路由,避免引入额外适配层 - 通过依赖覆盖与patch解耦服务层与数据库、第三方平台 - 业务流程测试直接操作数据库模型,确保测试数据的准确性 + - 代理框架测试通过FakeLLMProvider和AsyncMock解耦LLM调用 + - LLM提供者测试通过httpx模拟和AsyncMock解耦HTTP请求 + - 管道引擎测试通过dry-run模式解耦真实任务分发 - 外部依赖与集成点 - 数据库:通过异步引擎与会话管理,测试中可使用内存数据库或独立测试库 - JWT:通过服务层令牌生成与校验,测试中直接构造令牌头 - 平台适配器:通过patch替换,避免真实网络请求 - 调度器:通过patch替换真实的APScheduler,使用AsyncMock控制调度行为 + - LLM提供者:通过LLMFactory统一管理,测试中可通过patch替换具体实现 - 循环依赖与风险 - 当前结构清晰,无明显循环依赖;注意在测试中避免对真实调度器的依赖 @@ -500,6 +826,14 @@ T_CIT["测试: 引用"] --> A_CIT["路由: 引用"] T_BUSINESS["测试: 业务流程"] --> A_QUERIES T_BUSINESS --> A_CIT T_SCHED["测试: 调度器"] --> QS["调度器: QueryScheduler"] +T_AGENTS["测试: 代理框架"] --> CGA["代理: ContentGeneratorAgent"] +T_AGENTS --> DEAI["代理: DeAIAgent"] +T_AGENTS --> GEO["代理: GEOOptimizerAgent"] +T_LLM["测试: LLM提供者"] --> FACTORY["工厂: LLMFactory"] +T_PIPE["测试: 管道引擎"] --> ENGINE["引擎: PipelineEngine"] +T_FULL["测试: 端到端"] --> A_AUTH +T_FULL --> A_QUERIES +T_FULL --> A_CIT A_AUTH --> S_AUTH["服务: 认证"] A_QUERIES --> S_QUERY["服务: 查询"] A_CIT --> S_CIT["服务: 引用"] @@ -508,6 +842,10 @@ S_QUERY --> DB S_CIT --> DB QS --> CE["引擎: CitationEngine"] QS --> DB +CGA --> LLM["LLM提供者"] +DEAI --> LLM +GEO --> LLM +ENGINE --> LOADER["加载器: PipelineLoader"] DB --> CFG["配置"] ``` @@ -515,10 +853,20 @@ DB --> CFG["配置"] - [tests/test_auth.py:1-104](file://tests/test_auth.py#L1-L104) - [tests/test_business_flow.py:1-441](file://tests/test_business_flow.py#L1-L441) - [tests/test_scheduler.py:1-123](file://tests/test_scheduler.py#L1-L123) +- [tests/test_content_agents.py:1-358](file://tests/test_content_agents.py#L1-L358) +- [tests/test_llm_provider.py:1-205](file://tests/test_llm_provider.py#L1-L205) +- [tests/test_pipeline_engine.py:1-255](file://tests/test_pipeline_engine.py#L1-L255) +- [backend/tests/test_integration/test_full_flow.py:1-322](file://backend/tests/test_integration/test_full_flow.py#L1-L322) - [backend/app/api/auth.py:1-43](file://backend/app/api/auth.py#L1-L43) - [backend/app/api/queries.py:1-86](file://backend/app/api/queries.py#L1-L86) - [backend/app/api/citations.py:1-78](file://backend/app/api/citations.py#L1-L78) - [backend/app/workers/scheduler.py:1-182](file://backend/app/workers/scheduler.py#L1-L182) +- [backend/app/agent_framework/agents/content_generator_agent.py:1-299](file://backend/app/agent_framework/agents/content_generator_agent.py#L1-L299) +- [backend/app/agent_framework/agents/deai_agent.py:1-156](file://backend/app/agent_framework/agents/deai_agent.py#L1-L156) +- [backend/app/agent_framework/agents/geo_optimizer_agent.py:1-198](file://backend/app/agent_framework/agents/geo_optimizer_agent.py#L1-L198) +- [backend/app/services/llm/factory.py:1-66](file://backend/app/services/llm/factory.py#L1-L66) +- [backend/app/agent_framework/pipeline/engine.py:1-536](file://backend/app/agent_framework/pipeline/engine.py#L1-L536) +- [backend/app/agent_framework/pipeline/loader.py:1-283](file://backend/app/agent_framework/pipeline/loader.py#L1-L283) - [backend/app/database.py:1-29](file://backend/app/database.py#L1-L29) - [backend/app/config.py:1-23](file://backend/app/config.py#L1-L23) @@ -531,16 +879,22 @@ DB --> CFG["配置"] - 使用pytest-asyncio并行执行异步测试,减少总耗时 - 通过会话级调度器模拟避免真实后台任务带来的不稳定因素 - 业务流程测试使用内存数据库,避免磁盘I/O开销 + - 代理框架测试使用FakeLLMProvider,避免真实LLM调用的网络延迟 + - LLM提供者测试使用httpx模拟,避免真实HTTP请求的网络开销 + - 管道引擎测试使用dry-run模式,避免真实任务分发的系统开销 - 数据库与缓存 - 建议使用独立测试数据库实例,避免与开发/生产数据冲突 - 对高频查询场景,可在测试中模拟数据库延迟,评估路由与服务层的超时与重试策略 - 调度器测试使用AsyncMock,避免真实的定时任务执行 + - 代理框架测试使用AsyncMock,避免真实Redis和数据库调用 - 接口响应与序列化 - 对大列表与统计聚合接口,关注JSON序列化开销与分页参数边界 - 业务流程测试中直接操作数据库模型,避免不必要的API调用 + - 端到端测试中合理使用AsyncClient,避免过多的HTTP请求 - 平台适配器性能 - 通过patch模拟不同响应时延与错误率,评估引擎的容错与降级策略 - 调度器测试中使用精确的时间控制,避免真实的等待时间 + - LLM提供者测试中使用AsyncMock,避免真实网络请求的等待时间 ## 故障排查指南 - 常见问题定位 @@ -549,18 +903,26 @@ DB --> CFG["配置"] - 403配额:检查服务层权限异常抛出与HTTP状态映射 - 调度器异常:检查APScheduler的启动状态和job配置 - 业务流程失败:检查数据库事务和fixture的使用 + - 代理执行失败:检查FakeLLMProvider的mock配置和report_progress的patch + - LLM提供者异常:检查API密钥设置和httpx模拟配置 + - 管道执行失败:检查YAML配置和依赖关系验证 + - 端到端测试失败:检查数据库连接和依赖覆盖配置 - 调试技巧 - 在conftest中临时打印依赖解析过程,定位get_current_user解析失败原因 - 使用pytest的-v与-s选项查看详细输出,结合patch的side_effect观察异常传播 - 对数据库相关测试,开启SQLAlchemy echo以查看生成的SQL - 调度器测试中使用AsyncMock的assert_called_once()验证调度器行为 + - 代理框架测试中检查report_progress的调用次数和参数 + - LLM提供者测试中验证httpx.post的调用参数和返回值 + - 管道引擎测试中检查拓扑排序和变量解析的中间结果 - 性能与稳定性 - 对于长时间运行的异步测试,确保事件循环正确关闭 - 对需要真实网络请求的场景,优先使用patch模拟,必要时增加超时与重试 - 业务流程测试中合理使用fixture,避免重复创建昂贵的对象 + - 代理框架测试中使用AsyncMock,确保异步操作的正确模拟 ## 结论 -本测试策略以Pytest为核心,结合会话级调度器模拟、依赖覆盖与patch技术,实现了对认证、查询、引用、引擎模块以及业务流程和调度器的全面覆盖。通过明确的夹具与测试数据管理,确保测试的可维护性与可重复性。新增的业务流程测试和调度器测试进一步完善了测试体系,涵盖了端到端业务场景和定时任务调度的关键功能。建议在CI中启用并行执行与覆盖率统计,并为数据库与平台适配器建立稳定的模拟层,持续提升测试效率与质量。 +本测试策略以Pytest为核心,结合会话级调度器模拟、依赖覆盖与patch技术,实现了对认证、查询、引用、引擎模块、业务流程、调度器、代理框架、LLM提供者、管道引擎和端到端工作流的全面覆盖。通过明确的夹具与测试数据管理,确保测试的可维护性与可重复性。新增的代理框架测试、LLM提供者测试、管道引擎测试和端到端工作流测试进一步完善了测试体系,涵盖了智能代理执行、LLM抽象层、Pipeline编排和完整业务流程的关键功能。建议在CI中启用并行执行与覆盖率统计,并为数据库、LLM提供者、代理框架和管道引擎建立稳定的模拟层,持续提升测试效率与质量。 ## 附录 - 测试覆盖率要求建议 @@ -570,16 +932,29 @@ DB --> CFG["配置"] - 函数/方法覆盖率:≥90% - 业务流程覆盖率:≥95% - 调度器覆盖率:≥90% + - 代理框架覆盖率:≥90% + - LLM提供者覆盖率:≥90% + - 管道引擎覆盖率:≥90% + - 端到端工作流覆盖率:≥95% - 持续集成配置建议 - 使用GitHub Actions或GitLab CI,包含Python版本矩阵、依赖安装、数据库准备、pytest执行与覆盖率上传 - 将测试与lint、类型检查并行,确保主干分支质量 - - 为业务流程测试和调度器测试单独配置执行时间限制 + - 为业务流程测试、调度器测试、代理框架测试、LLM提供者测试、管道引擎测试和端到端工作流测试单独配置执行时间限制 + - 为LLM提供者测试配置环境变量,确保API密钥正确设置 - 测试环境管理 - 使用独立测试数据库与Redis实例,避免污染 - 通过环境变量切换测试配置,确保敏感信息不泄露 - 业务流程测试使用内存数据库,调度器测试使用AsyncMock + - 代理框架测试使用FakeLLMProvider和AsyncMock + - LLM提供者测试使用httpx模拟和环境变量 + - 管道引擎测试使用dry-run模式 + - 端到端测试使用AsyncClient和依赖覆盖 - 性能测试方法 - 使用pytest-benchmark或locust对高频路由进行基准测试 - 对引擎执行流程进行压力测试,评估平台适配器与数据库写入瓶颈 - 调度器测试中使用时间控制和AsyncMock,避免真实的定时等待 - - 业务流程测试中评估端到端流程的响应时间和吞吐量 \ No newline at end of file + - 业务流程测试中评估端到端流程的响应时间和吞吐量 + - 代理框架测试中评估LLM调用的性能和错误处理 + - LLM提供者测试中评估HTTP请求的性能和重试机制 + - 管道引擎测试中评估Pipeline执行的性能和超时处理 + - 端到端测试中评估完整业务流程的性能和稳定性 \ No newline at end of file diff --git a/.qoder/repowiki/zh/content/部署与运维/部署与运维.md b/.qoder/repowiki/zh/content/部署与运维/部署与运维.md index c36c8ef..0874f2a 100644 --- a/.qoder/repowiki/zh/content/部署与运维/部署与运维.md +++ b/.qoder/repowiki/zh/content/部署与运维/部署与运维.md @@ -15,20 +15,35 @@ - [backend/app/models/query.py](file://backend/app/models/query.py) - [backend/alembic.ini](file://backend/alembic.ini) - [backend/alembic/env.py](file://backend/alembic/env.py) +- [backend/app/middleware/logging_middleware.py](file://backend/app/middleware/logging_middleware.py) +- [backend/app/middleware/rate_limit.py](file://backend/app/middleware/rate_limit.py) - [tests/test_auth.py](file://tests/test_auth.py) +## 更新摘要 +**所做更改** +- 新增完整的Docker容器化部署配置说明 +- 补充生产环境部署策略与最佳实践 +- 完善监控日志管理方案与运维指南 +- 增加CI/CD流水线与自动化部署配置 +- 更新环境配置与安全加固措施 + ## 目录 1. [简介](#简介) 2. [项目结构](#项目结构) 3. [核心组件](#核心组件) 4. [架构总览](#架构总览) 5. [详细组件分析](#详细组件分析) -6. [依赖分析](#依赖分析) -7. [性能考虑](#性能考虑) -8. [故障排查指南](#故障排查指南) -9. [结论](#结论) -10. [附录](#附录) +6. [Docker容器化部署](#docker容器化部署) +7. [生产环境部署策略](#生产环境部署策略) +8. [监控与日志管理](#监控与日志管理) +9. [运维最佳实践](#运维最佳实践) +10. [CI/CD流水线配置](#cicd流水线配置) +11. [依赖分析](#依赖分析) +12. [性能考虑](#性能考虑) +13. [故障排查指南](#故障排查指南) +14. [结论](#结论) +15. [附录](#附录) ## 简介 本文件面向GEO项目的部署与运维团队,提供从开发到生产的完整落地指南。内容覆盖Docker容器化部署、镜像构建、服务编排与环境配置;生产部署策略(Nginx反向代理、SSL证书、负载均衡);监控与日志管理(健康检查、错误追踪、性能监控);运维最佳实践(备份、安全、故障恢复)以及CI/CD流水线与自动化部署建议。文档严格基于仓库现有配置与实现进行说明,避免臆测。 @@ -69,18 +84,18 @@ SCH --> RD FE --> API ``` -图表来源 +**图表来源** - [docker-compose.yml:1-71](file://docker-compose.yml#L1-L71) - [backend/Dockerfile:1-41](file://backend/Dockerfile#L1-L41) - [frontend/Dockerfile:1-15](file://frontend/Dockerfile#L1-L15) -- [backend/app/main.py:1-48](file://backend/app/main.py#L1-L48) -- [backend/app/config.py:1-17](file://backend/app/config.py#L1-L17) +- [backend/app/main.py:1-100](file://backend/app/main.py#L1-L100) +- [backend/app/config.py:1-46](file://backend/app/config.py#L1-L46) - [backend/app/database.py:1-29](file://backend/app/database.py#L1-L29) -- [backend/app/workers/scheduler.py:1-95](file://backend/app/workers/scheduler.py#L1-L95) +- [backend/app/workers/scheduler.py:1-189](file://backend/app/workers/scheduler.py#L1-L189) - [backend/alembic.ini:1-150](file://backend/alembic.ini#L1-L150) - [backend/alembic/env.py:1-89](file://backend/alembic/env.py#L1-L89) -章节来源 +**章节来源** - [docker-compose.yml:1-71](file://docker-compose.yml#L1-L71) - [backend/Dockerfile:1-41](file://backend/Dockerfile#L1-L41) - [frontend/Dockerfile:1-15](file://frontend/Dockerfile#L1-L15) @@ -98,11 +113,11 @@ FE --> API - 迁移与版本控制(Alembic) - 异步迁移环境、配置文件与日志级别。 -章节来源 -- [backend/app/main.py:1-48](file://backend/app/main.py#L1-L48) -- [backend/app/config.py:1-17](file://backend/app/config.py#L1-L17) +**章节来源** +- [backend/app/main.py:1-100](file://backend/app/main.py#L1-L100) +- [backend/app/config.py:1-46](file://backend/app/config.py#L1-L46) - [backend/app/database.py:1-29](file://backend/app/database.py#L1-L29) -- [backend/app/workers/scheduler.py:1-95](file://backend/app/workers/scheduler.py#L1-L95) +- [backend/app/workers/scheduler.py:1-189](file://backend/app/workers/scheduler.py#L1-L189) - [backend/alembic.ini:1-150](file://backend/alembic.ini#L1-L150) - [backend/alembic/env.py:1-89](file://backend/alembic/env.py#L1-L89) @@ -118,7 +133,7 @@ subgraph "边缘层" NGINX["Nginx 反向代理
SSL/TLS 终止"] end subgraph "应用层" -LB["负载均衡器/反向代理" +LB["负载均衡器/反向代理"] subgraph "后端实例" API1["API 实例 1"] API2["API 实例 2"] @@ -143,7 +158,9 @@ API2 --> RDS API3 --> RDS ``` -(本图为概念性架构示意,不对应具体源码文件) +**图表来源** +- [docker-compose.yml:36-66](file://docker-compose.yml#L36-L66) +- [backend/app/main.py:97-100](file://backend/app/main.py#L97-L100) ## 详细组件分析 @@ -180,19 +197,19 @@ S->>D : "周期性查询待执行任务" S->>A : "触发执行逻辑" ``` -图表来源 +**图表来源** - [backend/Dockerfile:1-41](file://backend/Dockerfile#L1-L41) -- [backend/app/main.py:1-48](file://backend/app/main.py#L1-L48) -- [backend/app/config.py:1-17](file://backend/app/config.py#L1-L17) +- [backend/app/main.py:33-45](file://backend/app/main.py#L33-L45) +- [backend/app/config.py:12-14](file://backend/app/config.py#L12-L14) - [backend/app/database.py:1-29](file://backend/app/database.py#L1-L29) -- [backend/app/workers/scheduler.py:1-95](file://backend/app/workers/scheduler.py#L1-L95) +- [backend/app/workers/scheduler.py:33-51](file://backend/app/workers/scheduler.py#L33-L51) -章节来源 +**章节来源** - [backend/Dockerfile:1-41](file://backend/Dockerfile#L1-L41) -- [backend/app/main.py:1-48](file://backend/app/main.py#L1-L48) -- [backend/app/config.py:1-17](file://backend/app/config.py#L1-L17) +- [backend/app/main.py:1-100](file://backend/app/main.py#L1-L100) +- [backend/app/config.py:1-46](file://backend/app/config.py#L1-L46) - [backend/app/database.py:1-29](file://backend/app/database.py#L1-L29) -- [backend/app/workers/scheduler.py:1-95](file://backend/app/workers/scheduler.py#L1-L95) +- [backend/app/workers/scheduler.py:1-189](file://backend/app/workers/scheduler.py#L1-L189) ### 前端(Next.js)与容器化 - 容器镜像构建要点 @@ -201,10 +218,10 @@ S->>A : "触发执行逻辑" - 与后端交互 - 默认CORS允许来自前端开发地址的请求,生产环境需根据域名调整。 -章节来源 +**章节来源** - [frontend/Dockerfile:1-15](file://frontend/Dockerfile#L1-L15) -- [frontend/package.json:1-40](file://frontend/package.json#L1-L40) -- [backend/app/main.py:30-36](file://backend/app/main.py#L30-L36) +- [frontend/package.json:1-45](file://frontend/package.json#L1-L45) +- [backend/app/main.py:53-63](file://backend/app/main.py#L53-L63) ### 数据库与迁移(PostgreSQL + Alembic) - 连接与会话 @@ -259,13 +276,13 @@ QUERIES ||--o{ CITATION_RECORDS : "生成" QUERIES ||--o{ QUERY_TASKS : "拆分任务" ``` -图表来源 +**图表来源** - [backend/app/models/query.py:1-55](file://backend/app/models/query.py#L1-L55) - [backend/app/database.py:1-29](file://backend/app/database.py#L1-L29) - [backend/alembic.ini:86-89](file://backend/alembic.ini#L86-L89) - [backend/alembic/env.py:1-89](file://backend/alembic/env.py#L1-L89) -章节来源 +**章节来源** - [backend/app/database.py:1-29](file://backend/app/database.py#L1-L29) - [backend/app/models/query.py:1-55](file://backend/app/models/query.py#L1-L55) - [backend/alembic.ini:1-150](file://backend/alembic.ini#L1-L150) @@ -278,9 +295,9 @@ QUERIES ||--o{ QUERY_TASKS : "拆分任务" - JWT密钥默认值仅用于开发,生产必须替换。 - CORS在开发环境允许前端地址,生产需限定来源。 -章节来源 -- [backend/app/api/auth.py:1-43](file://backend/app/api/auth.py#L1-L43) -- [backend/app/config.py:9-9](file://backend/app/config.py#L9-L9) +**章节来源** +- [backend/app/api/auth.py:1-115](file://backend/app/api/auth.py#L1-L115) +- [backend/app/config.py:14](file://backend/app/config.py#L14) ### 编排与健康检查(Docker Compose) - 服务编排 @@ -290,9 +307,259 @@ QUERIES ||--o{ QUERY_TASKS : "拆分任务" - 依赖顺序 - 后端等待数据库与Redis健康后再启动,前端依赖后端。 -章节来源 +**章节来源** - [docker-compose.yml:1-71](file://docker-compose.yml#L1-L71) -- [backend/app/main.py:45-48](file://backend/app/main.py#L45-L48) +- [backend/app/main.py:97-100](file://backend/app/main.py#L97-L100) + +## Docker容器化部署 + +### 镜像构建配置 +GEO项目采用多阶段容器化部署,后端和前端分别构建独立镜像: + +**后端镜像构建流程** +- 基础镜像:python:3.11-slim +- 系统依赖:安装Playwright运行所需的系统库 +- 依赖安装:pip安装requirements.txt中的所有依赖 +- 浏览器安装:预装Chromium浏览器驱动 +- 应用部署:复制源码并暴露8000端口 + +**前端镜像构建流程** +- 基础镜像:node:20-alpine +- 依赖安装:使用npm ci安装生产依赖 +- 应用部署:复制源码并暴露3000端口 + +**章节来源** +- [backend/Dockerfile:1-41](file://backend/Dockerfile#L1-L41) +- [frontend/Dockerfile:1-15](file://frontend/Dockerfile#L1-L15) +- [backend/requirements.txt:1-42](file://backend/requirements.txt#L1-L42) + +### 服务编排配置 +Docker Compose定义了完整的微服务架构: + +**数据库服务(db)** +- 镜像:postgres:15-alpine +- 端口映射:5432:5432 +- 健康检查:使用pg_isready检测数据库可用性 +- 数据持久化:挂载postgres_data卷 + +**缓存服务(redis)** +- 镜像:redis:7-alpine +- 端口映射:6379:6379 +- 健康检查:使用redis-cli ping检测 +- 数据持久化:挂载redis_data卷 + +**后端服务(backend)** +- 构建:使用./backend目录作为构建上下文 +- 端口映射:8000:8000 +- 环境配置:加载.env文件 +- 依赖关系:等待db和redis健康检查通过 +- 命令:uvicorn启动FastAPI应用 + +**前端服务(frontend)** +- 构建:使用./frontend目录作为构建上下文 +- 端口映射:3000:3000 +- 环境配置:加载.env文件 +- 依赖关系:依赖backend服务 +- 命令:npm run dev启动开发服务器 + +**章节来源** +- [docker-compose.yml:1-71](file://docker-compose.yml#L1-L71) + +### 环境配置管理 +项目使用Pydantic Settings进行环境变量管理,支持不同环境的配置分离: + +**核心配置项** +- 数据库连接:DATABASE_URL(默认指向db容器) +- Redis连接:REDIS_URL(默认指向redis容器) +- JWT配置:JWT_SECRET、JWT_EXPIRE_HOURS +- LLM提供商:支持OpenAI、DeepSeek、通义千问等 +- CORS配置:CORS_ORIGINS允许跨域请求的来源列表 + +**章节来源** +- [backend/app/config.py:1-46](file://backend/app/config.py#L1-L46) + +## 生产环境部署策略 + +### Nginx反向代理配置 +生产环境推荐使用Nginx作为反向代理和SSL终止: + +**基础反向代理配置** +``` +upstream backend { + server backend:8000; +} + +server { + listen 80; + server_name geo.example.com; + + location / { + proxy_pass http://backend; + proxy_set_header Host $host; + proxy_set_header X-Real-IP $remote_addr; + proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for; + proxy_set_header X-Forwarded-Proto $scheme; + } +} +``` + +**SSL证书配置** +- 使用Let's Encrypt自动签发免费SSL证书 +- 配置HTTP到HTTPS重定向 +- 启用现代TLS协议和加密套件 + +**负载均衡配置** +- 使用Nginx内置负载均衡器 +- 配置健康检查和故障转移 +- 支持多实例后端部署 + +### 容器编排与扩展 +生产环境建议使用Docker Swarm或Kubernetes进行容器编排: + +**服务扩展** +- 后端API:根据负载情况动态扩展实例数量 +- 数据库:配置主从复制和只读副本 +- 缓存:使用Redis集群提高可用性 + +**存储管理** +- 使用持久化存储卷确保数据安全 +- 配置定期备份策略 +- 实施数据同步和灾备方案 + +**章节来源** +- [docker-compose.yml:36-66](file://docker-compose.yml#L36-L66) +- [backend/app/config.py:12-14](file://backend/app/config.py#L12-L14) + +## 监控与日志管理 + +### 健康检查与监控 +项目已内置基本的健康检查功能,生产环境需要增强监控能力: + +**应用级监控** +- 健康检查端点:/health +- 性能指标:响应时间、错误率、吞吐量 +- 资源使用:CPU、内存、磁盘空间 + +**基础设施监控** +- 数据库连接池监控 +- Redis连接状态监控 +- 文件系统空间监控 + +**日志管理方案** +- 结构化日志输出到标准输出 +- 使用集中式日志收集系统(如ELK Stack) +- 日志轮转和保留策略 + +**章节来源** +- [backend/app/main.py:97-100](file://backend/app/main.py#L97-L100) +- [backend/app/middleware/logging_middleware.py:1-24](file://backend/app/middleware/logging_middleware.py#L1-L24) + +### 错误追踪与告警 +**错误追踪配置** +- 使用结构化日志记录异常信息 +- 集成错误追踪服务(如Sentry) +- 设置错误阈值和告警规则 + +**性能监控** +- 数据库查询性能监控 +- API响应时间监控 +- 缓存命中率监控 + +**章节来源** +- [backend/app/middleware/rate_limit.py:1-83](file://backend/app/middleware/rate_limit.py#L1-L83) + +## 运维最佳实践 + +### 备份策略 +**数据库备份** +- 定时全量备份:每周日凌晨2点执行 +- 增量备份:每小时执行 +- 多地备份:本地和云端同时保存 + +**配置备份** +- 环境变量文件备份 +- Docker Compose配置备份 +- SSL证书备份 + +**恢复流程** +- 制定详细的灾难恢复计划 +- 定期进行恢复演练 +- 建立快速恢复机制 + +### 安全配置 +**网络安全** +- 最小权限原则 +- 网络隔离和防火墙配置 +- 入站/出站流量控制 + +**应用安全** +- 定期更新依赖包 +- 密钥轮换策略 +- 安全审计日志 + +**数据安全** +- 敏感数据加密存储 +- 数据传输加密 +- 访问权限控制 + +### 故障恢复 +**故障分类与响应** +- 一级故障:系统完全不可用,立即启动应急预案 +- 二级故障:部分功能受影响,优先保证核心业务 +- 三级故障:性能下降但可正常运行,监控观察 + +**恢复流程** +- 快速诊断和定位问题 +- 实施临时修复措施 +- 执行永久性修复 +- 验证系统恢复正常 + +**章节来源** +- [backend/app/config.py:14](file://backend/app/config.py#L14) +- [backend/app/middleware/rate_limit.py:34-69](file://backend/app/middleware/rate_limit.py#L34-L69) + +## CI/CD流水线配置 + +### 自动化部署流程 +**开发到生产的完整流程** +1. 代码提交触发CI流水线 +2. 自动化测试(单元测试、集成测试) +3. 代码质量检查 +4. 构建Docker镜像 +5. 推送镜像到镜像仓库 +6. 自动部署到测试环境 +7. 手动审批进入生产环境 +8. 部署到生产环境并监控 + +**流水线阶段配置** +- 代码检出和分支管理 +- 依赖安装和缓存优化 +- 测试执行和覆盖率报告 +- 安全扫描和漏洞检测 +- 镜像构建和标签管理 +- 多环境部署策略 + +**回滚机制** +- 支持一键回滚到上一个稳定版本 +- 自动化回滚测试 +- 回滚通知和审计 + +**章节来源** +- [backend/requirements.txt:35-42](file://backend/requirements.txt#L35-L42) + +### 部署检查清单 +**生产部署前检查** +- 所有测试通过 +- 配置文件验证 +- 环境变量检查 +- 数据库迁移验证 +- 服务健康检查 + +**部署后验证** +- 健康检查端点验证 +- 核心功能测试 +- 性能基准测试 +- 监控告警检查 ## 依赖分析 - 后端依赖 @@ -318,13 +585,13 @@ REQ --> PLT PKGJSON --> NODE ``` -图表来源 -- [backend/requirements.txt:1-35](file://backend/requirements.txt#L1-L35) -- [frontend/package.json:1-40](file://frontend/package.json#L1-L40) +**图表来源** +- [backend/requirements.txt:1-42](file://backend/requirements.txt#L1-L42) +- [frontend/package.json:1-45](file://frontend/package.json#L1-L45) -章节来源 -- [backend/requirements.txt:1-35](file://backend/requirements.txt#L1-L35) -- [frontend/package.json:1-40](file://frontend/package.json#L1-L40) +**章节来源** +- [backend/requirements.txt:1-42](file://backend/requirements.txt#L1-L42) +- [frontend/package.json:1-45](file://frontend/package.json#L1-L45) ## 性能考虑 - 数据库 @@ -338,8 +605,6 @@ PKGJSON --> NODE - 容器 - 后端与前端镜像体积较小,建议启用只读根文件系统与最小权限运行。 -(本节为通用指导,不直接分析具体文件) - ## 故障排查指南 - 健康检查 - 后端/CORS与健康检查端点可用于快速判断服务可用性。 @@ -352,14 +617,14 @@ PKGJSON --> NODE - 单元测试 - 认证模块测试覆盖注册、登录与当前用户接口,可作为回归测试基线。 -章节来源 -- [backend/app/main.py:45-48](file://backend/app/main.py#L45-L48) +**章节来源** +- [backend/app/main.py:97-100](file://backend/app/main.py#L97-L100) - [backend/alembic.ini:115-150](file://backend/alembic.ini#L115-L150) - [backend/alembic/env.py:64-89](file://backend/alembic/env.py#L64-L89) - [tests/test_auth.py:1-104](file://tests/test_auth.py#L1-L104) ## 结论 -本部署与运维文档基于仓库现有配置,给出了从容器化到生产部署的实施路径与最佳实践建议。建议在生产环境中补充Nginx反向代理与SSL、集中化日志与监控、完善的备份与灾难恢复策略,并通过CI/CD实现自动化部署与回滚。 +本部署与运维文档基于仓库现有配置,给出了从容器化到生产部署的实施路径与最佳实践建议。建议在生产环境中补充Nginx反向代理与SSL、集中化日志与监控、完善的备份与灾难恢复策略,并通过CI/CD实现自动化部署与回滚。文档涵盖了Docker容器化部署、生产环境策略、监控日志管理、运维最佳实践和CI/CD流水线等关键内容,为GEO项目的稳定运行提供了全面的技术保障。 ## 附录 @@ -374,7 +639,7 @@ PKGJSON --> NODE - 数据库:localhost:5432 - Redis:localhost:6379 -章节来源 +**章节来源** - [docker-compose.yml:1-71](file://docker-compose.yml#L1-L71) ### B. 生产环境部署策略 @@ -385,8 +650,6 @@ PKGJSON --> NODE - 环境隔离 - 区分开发、测试、预发布与生产环境,严格管理环境变量与密钥。 -(本节为通用指导,不直接分析具体文件) - ### C. 监控与日志管理 - 健康检查 - 利用/CORS与健康检查端点,结合探针实现自动发现与告警。 @@ -395,8 +658,6 @@ PKGJSON --> NODE - 性能监控 - 关注数据库慢查询、Redis命中率、API响应时间与错误率。 -(本节为通用指导,不直接分析具体文件) - ### D. 运维最佳实践 - 备份策略 - 数据库与Redis定期快照与归档,验证恢复流程。 @@ -405,14 +666,10 @@ PKGJSON --> NODE - 故障恢复 - 制定回滚预案与演练计划,确保快速恢复。 -(本节为通用指导,不直接分析具体文件) - ### E. CI/CD流水线与自动化部署 - 建议阶段 - 代码提交触发测试(含认证接口测试),通过后构建镜像并推送制品库,随后部署到目标环境。 - 回滚机制 - 支持一键回滚至上一个稳定版本。 - 配置管理 - - 环境变量与密钥通过安全渠道注入,避免硬编码。 - -(本节为通用指导,不直接分析具体文件) \ No newline at end of file + - 环境变量与密钥通过安全渠道注入,避免硬编码。 \ No newline at end of file diff --git a/.qoder/repowiki/zh/content/项目概述/核心功能/核心功能.md b/.qoder/repowiki/zh/content/项目概述/核心功能/核心功能.md index 48412cb..9ed3306 100644 --- a/.qoder/repowiki/zh/content/项目概述/核心功能/核心功能.md +++ b/.qoder/repowiki/zh/content/项目概述/核心功能/核心功能.md @@ -7,18 +7,48 @@ - [backend/app/api/queries.py](file://backend/app/api/queries.py) - [backend/app/api/citations.py](file://backend/app/api/citations.py) - [backend/app/api/reports.py](file://backend/app/api/reports.py) +- [backend/app/api/lifecycle.py](file://backend/app/api/lifecycle.py) +- [backend/app/api/knowledge.py](file://backend/app/api/knowledge.py) - [backend/app/services/auth.py](file://backend/app/services/auth.py) - [backend/app/services/query.py](file://backend/app/services/query.py) - [backend/app/services/citation.py](file://backend/app/services/citation.py) +- [backend/app/services/analytics/tracker.py](file://backend/app/services/analytics/tracker.py) +- [backend/app/services/analytics/insights.py](file://backend/app/services/analytics/insights.py) +- [backend/app/services/knowledge/rag_service.py](file://backend/app/services/knowledge/rag_service.py) +- [backend/app/agent_framework/agents/__init__.py](file://backend/app/agent_framework/agents/__init__.py) +- [backend/app/agent_framework/agents/citation_detector.py](file://backend/app/agent_framework/agents/citation_detector.py) +- [backend/app/agent_framework/agents/content_generator_agent.py](file://backend/app/agent_framework/agents/content_generator_agent.py) +- [backend/app/agent_framework/agents/deai_agent.py](file://backend/app/agent_framework/agents/deai_agent.py) +- [backend/app/agent_framework/agents/geo_optimizer_agent.py](file://backend/app/agent_framework/agents/geo_optimizer_agent.py) +- [backend/app/agent_framework/pipeline/engine.py](file://backend/app/agent_framework/pipeline/engine.py) +- [backend/app/agent_framework/pipeline/loader.py](file://backend/app/agent_framework/pipeline/loader.py) +- [backend/app/agent_framework/dispatcher.py](file://backend/app/agent_framework/dispatcher.py) - [backend/app/models/query.py](file://backend/app/models/query.py) - [backend/app/models/citation_record.py](file://backend/app/models/citation_record.py) -- [backend/app/workers/scheduler.py](file://backend/app/workers/scheduler.py) -- [backend/app/workers/citation_engine.py](file://backend/app/workers/citation_engine.py) -- [backend/app/workers/platforms/base.py](file://backend/app/workers/platforms/base.py) +- [backend/app/models/lifecycle.py](file://backend/app/models/lifecycle.py) +- [backend/app/models/knowledge.py](file://backend/app/models/knowledge.py) +- [backend/alembic/versions/d4f6g8h0ab23_add_geo_lifecycle_tables.py](file://backend/alembic/versions/d4f6g8h0ab23_add_geo_lifecycle_tables.py) +- [backend/workers/scheduler.py](file://backend/workers/scheduler.py) +- [backend/workers/citation_engine.py](file://backend/workers/citation_engine.py) +- [backend/workers/platforms/base.py](file://backend/workers/platforms/base.py) - [frontend/app/(dashboard)/dashboard/page.tsx](file://frontend/app/(dashboard)/dashboard/page.tsx) +- [frontend/app/(dashboard)/dashboard/admin/page.tsx](file://frontend/app/(dashboard)/dashboard/admin/page.tsx) +- [frontend/app/(dashboard)/dashboard/agents/page.tsx](file://frontend/app/(dashboard)/dashboard/agents/page.tsx) +- [frontend/app/(dashboard)/dashboard/analytics/page.tsx](file://frontend/app/(dashboard)/dashboard/analytics/page.tsx) +- [frontend/app/(dashboard)/dashboard/lifecycle/page.tsx](file://frontend/app/(dashboard)/dashboard/lifecycle/page.tsx) +- [frontend/app/(dashboard)/dashboard/knowledge/page.tsx](file://frontend/app/(dashboard)/dashboard/knowledge/page.tsx) - [frontend/components/charts/trend-chart.tsx](file://frontend/components/charts/trend-chart.tsx) +- [frontend/lib/api/lifecycle.ts](file://frontend/lib/api/lifecycle.ts) +## 更新摘要 +**变更内容** +- 新增AI代理框架模块,包含引用检测、内容生成、去AI化、GEO优化等智能代理 +- 新增业务生命周期管理系统,支持品牌项目全生命周期管理 +- 新增分析监控系统,提供发布追踪、效果分析和智能洞察生成功能 +- 新增知识库服务模块,支持RAG检索、文档管理和知识库CRUD操作 +- 扩展前端界面,新增代理管理、分析监控、生命周期管理和知识库管理页面 + ## 目录 1. [简介](#简介) 2. [项目结构](#项目结构) @@ -36,11 +66,15 @@ - 用户认证与权限管理:基于邮箱/密码注册登录、JWT 访问令牌签发与校验、会话保护接口。 - 智能查询任务管理:查询词创建、更新、删除、分页查询;按日/周/月频率自动调度;手动触发即时查询。 - 品牌引用检测引擎:多阶段匹配(精确/别名/模糊)、置信度评分、竞争品牌识别、上下文片段抽取。 -- 多 AI 平台数据集成:抽象适配器模式对接不同大模型平台,统一查询与结果处理。 +- 多AI平台数据集成:抽象适配器模式对接不同大模型平台,统一查询与结果处理。 +- AI代理框架:基于Pipeline的多代理协作系统,支持引用检测、内容生成、去AI化、GEO优化等智能任务编排。 +- 业务生命周期管理:品牌项目全生命周期管理,包含5个阶段的项目推进和状态跟踪。 +- 分析监控系统:发布效果追踪、内容表现分析、智能洞察生成和性能监控。 +- 知识库服务:RAG检索、文档管理、知识库CRUD操作和搜索日志记录。 - 数据分析与可视化:统计指标(总查询/引用次数、引用率、平均位置)、平台对比、30 天趋势折线图。 - 报告导出:CSV 导出引用记录,便于离线分析与归档。 -这些功能围绕“查询—检测—统计—可视—导出”的闭环展开,既满足管理员对系统运行与任务调度的掌控,也服务于研究人员对品牌监测与趋势分析的需求。 +这些功能围绕"查询—检测—智能代理—生命周期—分析监控—知识库—统计—可视—导出"的完整生态展开,既满足管理员对系统运行与任务调度的掌控,也服务于研究人员对品牌监测与趋势分析的需求。 ## 项目结构 后端采用 FastAPI + SQLAlchemy 异步 ORM,按领域划分 API、服务、模型与工作器;前端使用 Next.js + React,通过自定义 API 客户端与后端交互;数据库为 PostgreSQL。 @@ -49,21 +83,37 @@ graph TB subgraph "后端" A["FastAPI 应用
app/main.py"] -B["API 层
auth/queries/citations/reports"] -C["服务层
auth/query/citation"] -D["模型层
Query/CitationRecord"] +B["API 层
auth/queries/citations/reports/lifecycle/knowledge"] +C["服务层
auth/query/citation/analytics/knowledge"] +D["模型层
Query/CitationRecord/Lifecycle/Knowledge"] E["工作器
Scheduler/CitationEngine/Platforms"] +F["AI代理框架
Agents/Pipeline/Dispatcher"] +G["分析监控
Tracker/Insights"] +H["知识库服务
RAGService/Chunker/Embedder"] end subgraph "前端" -F["仪表盘页面
dashboard/page.tsx"] -G["趋势图表组件
trend-chart.tsx"] +I["仪表盘页面
dashboard/page.tsx"] +J["管理员页面
admin/page.tsx"] +K["代理管理页面
agents/page.tsx"] +L["分析监控页面
analytics/page.tsx"] +M["生命周期页面
lifecycle/page.tsx"] +N["知识库页面
knowledge/page.tsx"] +O["趋势图表组件
trend-chart.tsx"] end A --> B B --> C C --> D C --> E -F --> G -F --> B +C --> F +C --> G +C --> H +I --> O +I --> B +J --> B +K --> F +L --> G +M --> D +N --> H ``` **图表来源** @@ -72,14 +122,29 @@ F --> B - [backend/app/api/queries.py:1-86](file://backend/app/api/queries.py#L1-L86) - [backend/app/api/citations.py:1-78](file://backend/app/api/citations.py#L1-L78) - [backend/app/api/reports.py:1-47](file://backend/app/api/reports.py#L1-L47) +- [backend/app/api/lifecycle.py:1-297](file://backend/app/api/lifecycle.py#L1-L297) +- [backend/app/api/knowledge.py:1-502](file://backend/app/api/knowledge.py#L1-L502) - [backend/app/services/auth.py:1-69](file://backend/app/services/auth.py#L1-L69) - [backend/app/services/query.py:1-130](file://backend/app/services/query.py#L1-L130) - [backend/app/services/citation.py:1-269](file://backend/app/services/citation.py#L1-L269) +- [backend/app/services/analytics/tracker.py:1-230](file://backend/app/services/analytics/tracker.py#L1-L230) +- [backend/app/services/analytics/insights.py:1-313](file://backend/app/services/analytics/insights.py#L1-L313) +- [backend/app/services/knowledge/rag_service.py:1-43](file://backend/app/services/knowledge/rag_service.py#L1-L43) +- [backend/app/agent_framework/agents/__init__.py:1-14](file://backend/app/agent_framework/agents/__init__.py#L1-L14) +- [backend/app/agent_framework/pipeline/engine.py:1-536](file://backend/app/agent_framework/pipeline/engine.py#L1-L536) +- [backend/app/agent_framework/dispatcher.py:1-367](file://backend/app/agent_framework/dispatcher.py#L1-L367) - [backend/app/models/query.py:1-55](file://backend/app/models/query.py#L1-L55) - [backend/app/models/citation_record.py:1-42](file://backend/app/models/citation_record.py#L1-L42) -- [backend/app/workers/scheduler.py:1-95](file://backend/app/workers/scheduler.py#L1-L95) -- [backend/app/workers/citation_engine.py:1-309](file://backend/app/workers/citation_engine.py#L1-L309) +- [backend/app/models/lifecycle.py:1-91](file://backend/app/models/lifecycle.py#L1-L91) +- [backend/app/models/knowledge.py:1-43](file://backend/app/models/knowledge.py#L1-L43) +- [backend/workers/scheduler.py:1-95](file://backend/workers/scheduler.py#L1-L95) +- [backend/workers/citation_engine.py:1-309](file://backend/workers/citation_engine.py#L1-L309) - [frontend/app/(dashboard)/dashboard/page.tsx:1-156](file://frontend/app/(dashboard)/dashboard/page.tsx#L1-L156) +- [frontend/app/(dashboard)/dashboard/admin/page.tsx:1-200](file://frontend/app/(dashboard)/dashboard/admin/page.tsx#L1-L200) +- [frontend/app/(dashboard)/dashboard/agents/page.tsx:1-200](file://frontend/app/(dashboard)/dashboard/agents/page.tsx#L1-L200) +- [frontend/app/(dashboard)/dashboard/analytics/page.tsx:1-200](file://frontend/app/(dashboard)/dashboard/analytics/page.tsx#L1-L200) +- [frontend/app/(dashboard)/dashboard/lifecycle/page.tsx:1-200](file://frontend/app/(dashboard)/dashboard/lifecycle/page.tsx#L1-L200) +- [frontend/app/(dashboard)/dashboard/knowledge/page.tsx:1-200](file://frontend/app/(dashboard)/dashboard/knowledge/page.tsx#L1-L200) - [frontend/components/charts/trend-chart.tsx:1-60](file://frontend/components/charts/trend-chart.tsx#L1-L60) **章节来源** @@ -88,7 +153,7 @@ F --> B ## 核心组件 - 认证与权限 - 注册/登录:邮箱唯一性校验、密码哈希、JWT 签发;当前用户信息读取。 - - 权限边界:所有业务接口均通过当前用户上下文进行资源归属校验(查询、引用、统计、导出)。 + - 权限边界:所有业务接口均通过当前用户上下文进行资源归属校验(查询、引用、统计、导出、生命周期、知识库)。 - 查询任务管理 - 查询 CRUD:分页列表、创建、读取、更新、删除;创建时校验用户配额上限;更新时可重算下次执行时间。 - 自动调度:每小时扫描到期查询,自动触发引用检测;手动触发即时查询。 @@ -97,7 +162,23 @@ F --> B - 竞争品牌:基于预设行业品牌库识别竞品。 - 结果持久化:生成引用记录,包含平台、是否引用、位置、文本、竞品集合、原始响应。 - 多 AI 平台集成 - - 适配器基类定义统一接口;内置“文心”“Kimi”适配器;未来可扩展更多平台。 + - 适配器基类定义统一接口;内置"文心""Kimi"适配器;未来可扩展更多平台。 +- AI代理框架 + - 代理实现:引用检测代理、内容生成代理、去AI化代理、GEO优化代理。 + - Pipeline编排:基于YAML的多阶段任务编排,支持变量解析、依赖管理、条件执行。 + - 任务分发:Redis队列驱动的任务分发器,支持任务状态跟踪和重试机制。 +- 业务生命周期管理 + - 项目管理:品牌基建、内容生产、AI适配优化、权威信号构建、持续运维5个阶段。 + - 状态跟踪:项目进度、阶段状态、完成率统计和时间轴事件记录。 + - 快速启动:一键创建项目并初始化5个阶段。 +- 分析监控系统 + - 发布追踪:内容发布记录、效果指标快照和平台分布统计。 + - 性能分析:内容表现排行、单篇内容深度分析和历史趋势追踪。 + - 智能洞察:基于LLM的自动化洞察生成和优化建议。 +- 知识库服务 + - RAG检索:文档分块、向量化嵌入和混合检索。 + - 文档管理:URL抓取、文本上传和分块预览。 + - 知识库CRUD:多租户知识库管理和搜索日志记录。 - 数据分析与可视化 - 统计聚合:总查询/引用数、引用率、平均位置、按平台汇总、30 天趋势。 - 前端展示:仪表盘卡片与趋势折线图组件。 @@ -113,12 +194,21 @@ F --> B - [backend/app/services/citation.py:1-269](file://backend/app/services/citation.py#L1-L269) - [backend/app/workers/citation_engine.py:148-309](file://backend/app/workers/citation_engine.py#L148-L309) - [backend/app/workers/platforms/base.py:1-18](file://backend/app/workers/platforms/base.py#L1-L18) +- [backend/app/agent_framework/agents/__init__.py:1-14](file://backend/app/agent_framework/agents/__init__.py#L1-L14) +- [backend/app/agent_framework/pipeline/engine.py:1-536](file://backend/app/agent_framework/pipeline/engine.py#L1-L536) +- [backend/app/agent_framework/dispatcher.py:1-367](file://backend/app/agent_framework/dispatcher.py#L1-L367) +- [backend/app/api/lifecycle.py:1-297](file://backend/app/api/lifecycle.py#L1-L297) +- [backend/app/models/lifecycle.py:1-91](file://backend/app/models/lifecycle.py#L1-L91) +- [backend/app/services/analytics/tracker.py:1-230](file://backend/app/services/analytics/tracker.py#L1-L230) +- [backend/app/services/analytics/insights.py:1-313](file://backend/app/services/analytics/insights.py#L1-L313) +- [backend/app/api/knowledge.py:1-502](file://backend/app/api/knowledge.py#L1-L502) +- [backend/app/services/knowledge/rag_service.py:1-43](file://backend/app/services/knowledge/rag_service.py#L1-L43) - [frontend/app/(dashboard)/dashboard/page.tsx:1-156](file://frontend/app/(dashboard)/dashboard/page.tsx#L1-L156) - [frontend/components/charts/trend-chart.tsx:1-60](file://frontend/components/charts/trend-chart.tsx#L1-L60) - [backend/app/api/reports.py:1-47](file://backend/app/api/reports.py#L1-L47) ## 架构总览 -下图展示从用户请求到数据落库与可视化的整体流程,以及定时调度与即时查询的协同机制。 +下图展示从用户请求到数据落库与可视化的整体流程,以及定时调度、智能代理编排、生命周期管理和分析监控的协同机制。 ```mermaid sequenceDiagram @@ -130,10 +220,12 @@ participant DB as "数据库" participant W as "工作器" participant CE as "引用检测引擎" participant P as "AI平台适配器" -U->>FE : 登录/访问仪表盘 -FE->>API : 获取统计/查询/引用/导出 +participant AG as "AI代理框架" +participant PL as "Pipeline引擎" +U->>FE : 登录/访问各功能页面 +FE->>API : 获取统计/查询/引用/导出/生命周期/知识库 API->>S : 参数校验与业务处理 -S->>DB : 读写查询/引用/任务 +S->>DB : 读写查询/引用/任务/项目/知识库 Note over S,DB : 权限校验:仅允许访问本人资源 API->>W : 触发/查询任务 W->>CE : 执行查询 @@ -141,6 +233,10 @@ CE->>P : 平台查询 P-->>CE : 原始响应 CE->>S : 写入引用记录 S->>DB : 持久化 +S->>AG : 分发代理任务 +AG->>PL : 执行Pipeline编排 +PL->>AG : 代理执行结果 +S->>DB : 更新代理状态 DB-->>S : 成功 S-->>API : 结果 API-->>FE : 响应数据/流式下载 @@ -149,9 +245,11 @@ API-->>FE : 响应数据/流式下载 **图表来源** - [backend/app/main.py:13-21](file://backend/app/main.py#L13-L21) - [backend/app/api/citations.py:59-77](file://backend/app/api/citations.py#L59-L77) -- [backend/app/workers/scheduler.py:51-84](file://backend/app/workers/scheduler.py#L51-L84) -- [backend/app/workers/citation_engine.py:159-234](file://backend/app/workers/citation_engine.py#L159-L234) +- [backend/app/workers/scheduler.py:51-84](file://backend/workers/scheduler.py#L51-L84) +- [backend/app/workers/citation_engine.py:159-234](file://backend/workers/citation_engine.py#L159-L234) - [backend/app/services/citation.py:204-234](file://backend/app/services/citation.py#L204-L234) +- [backend/app/agent_framework/dispatcher.py:54-117](file://backend/app/agent_framework/dispatcher.py#L54-L117) +- [backend/app/agent_framework/pipeline/engine.py:51-176](file://backend/app/agent_framework/pipeline/engine.py#L51-L176) ## 详细组件分析 @@ -202,7 +300,7 @@ API-->>U : {access_token,user} - 减少人工干预:按计划自动抓取与检测,提升研究效率。 - 灵活控制:支持日/周/月频率与手动触发,兼顾实时性与成本。 - 典型场景 - - 研究员创建查询(关键词、目标品牌、平台、频率),系统按时自动执行;也可随时“立即执行”。 + - 研究员创建查询(关键词、目标品牌、平台、频率),系统按时自动执行;也可随时"立即执行"。 ```mermaid flowchart TD @@ -220,13 +318,13 @@ UpdateTime --> Done(["完成一轮周期"]) **图表来源** - [backend/app/services/query.py:45-81](file://backend/app/services/query.py#L45-L81) -- [backend/app/workers/scheduler.py:51-84](file://backend/app/workers/scheduler.py#L51-L84) +- [backend/app/workers/scheduler.py:51-84](file://backend/workers/scheduler.py#L51-L84) - [backend/app/workers/citation_engine.py:291-300](file://backend/app/workers/citation_engine.py#L291-L300) **章节来源** - [backend/app/api/queries.py:1-86](file://backend/app/api/queries.py#L1-L86) - [backend/app/services/query.py:1-130](file://backend/app/services/query.py#L1-L130) -- [backend/app/workers/scheduler.py:1-95](file://backend/app/workers/scheduler.py#L1-L95) +- [backend/app/workers/scheduler.py:1-95](file://backend/workers/scheduler.py#L1-L95) ### 品牌引用检测引擎 - 功能要点 @@ -237,7 +335,7 @@ UpdateTime --> Done(["完成一轮周期"]) - 置信度评分:帮助判断引用可靠性;模糊匹配提供兜底发现。 - 上下文定位:快速定位品牌在原文中的首次出现段落,便于人工复核。 - 典型场景 - - 文本中提及“XX品牌”,匹配器判定为“别名命中”,置信度0.9,并返回首次出现段落片段。 + - 文本中提及"XX品牌",匹配器判定为"别名命中",置信度0.9,并返回首次出现段落片段。 ```mermaid classDiagram @@ -272,12 +370,12 @@ CitationEngine --> BasePlatformAdapter : "委托查询" ### 多 AI 平台数据集成 - 功能要点 - 适配器基类定义统一接口(平台名、URL、查询方法)。 - - 内置“文心”“Kimi”适配器;引擎按查询配置的平台列表逐一执行。 + - 内置"文心""Kimi"适配器;引擎按查询配置的平台列表逐一执行。 - 核心价值 - 解耦平台差异:统一调用入口,便于扩展更多平台。 - 可观测性:每个平台独立任务状态(pending/running/success/failed)。 - 典型场景 - - 查询配置包含“wenxin,kimi”,引擎为两者分别创建任务并行执行,最终汇总结果。 + - 查询配置包含"wenxin,kimi",引擎为两者分别创建任务并行执行,最终汇总结果。 ```mermaid sequenceDiagram @@ -303,6 +401,204 @@ end - [backend/app/workers/platforms/base.py:1-18](file://backend/app/workers/platforms/base.py#L1-L18) - [backend/app/workers/citation_engine.py:151-157](file://backend/app/workers/citation_engine.py#L151-L157) +### AI代理框架 +- 功能要点 + - 代理实现:CitationDetectorAgent、ContentGeneratorAgent、DeAIAgent、GEOOptimizerAgent。 + - Pipeline编排:支持变量解析、依赖管理、条件执行、重试机制。 + - 任务分发:Redis队列驱动,支持任务状态跟踪、进度上报和回调机制。 +- 核心价值 + - 智能化编排:将复杂的多步骤任务分解为可组合的代理单元。 + - 可扩展性:新的代理类型可通过简单接口接入框架。 + - 可观测性:完整的任务生命周期跟踪和性能监控。 +- 典型场景 + - 内容生产Pipeline:主题选择 → 文章生成 → 去AI化 → GEO优化 → 发布。 + +```mermaid +classDiagram +class BaseAgent { +<> ++execute(task) TaskResult ++report_progress(task_id, progress, message) ++get_capabilities() AgentCapability +} +class CitationDetectorAgent { ++execute_full_detect(task) dict ++execute_single_detect(task) dict +} +class ContentGeneratorAgent { ++_generate_topics(task) dict ++_generate_article(task) dict +} +class DeAIAgent { ++_process(task) dict +} +class GEOOptimizerAgent { ++_optimize(task) dict +} +class PipelineEngine { ++execute(pipeline, context) PipelineResult ++_execute_stage(stage, ctx, stages_ctx) StageResult +} +class TaskDispatcher { ++dispatch(task, org_id, user_id) str ++get_task_status(task_id) dict ++handle_result(result) +} +BaseAgent <|-- CitationDetectorAgent +BaseAgent <|-- ContentGeneratorAgent +BaseAgent <|-- DeAIAgent +BaseAgent <|-- GEOOptimizerAgent +PipelineEngine --> BaseAgent : "编排执行" +TaskDispatcher --> BaseAgent : "任务分发" +``` + +**图表来源** +- [backend/app/agent_framework/agents/citation_detector.py:24-218](file://backend/app/agent_framework/agents/citation_detector.py#L24-L218) +- [backend/app/agent_framework/agents/content_generator_agent.py:23-299](file://backend/app/agent_framework/agents/content_generator_agent.py#L23-L299) +- [backend/app/agent_framework/agents/deai_agent.py:21-156](file://backend/app/agent_framework/agents/deai_agent.py#L21-L156) +- [backend/app/agent_framework/agents/geo_optimizer_agent.py:23-198](file://backend/app/agent_framework/agents/geo_optimizer_agent.py#L23-L198) +- [backend/app/agent_framework/pipeline/engine.py:31-536](file://backend/app/agent_framework/pipeline/engine.py#L31-L536) +- [backend/app/agent_framework/dispatcher.py:32-367](file://backend/app/agent_framework/dispatcher.py#L32-L367) + +**章节来源** +- [backend/app/agent_framework/agents/__init__.py:1-14](file://backend/app/agent_framework/agents/__init__.py#L1-L14) +- [backend/app/agent_framework/agents/citation_detector.py:1-218](file://backend/app/agent_framework/agents/citation_detector.py#L1-L218) +- [backend/app/agent_framework/agents/content_generator_agent.py:1-299](file://backend/app/agent_framework/agents/content_generator_agent.py#L1-L299) +- [backend/app/agent_framework/agents/deai_agent.py:1-156](file://backend/app/agent_framework/agents/deai_agent.py#L1-L156) +- [backend/app/agent_framework/agents/geo_optimizer_agent.py:1-198](file://backend/app/agent_framework/agents/geo_optimizer_agent.py#L1-L198) +- [backend/app/agent_framework/pipeline/engine.py:1-536](file://backend/app/agent_framework/pipeline/engine.py#L1-L536) +- [backend/app/agent_framework/dispatcher.py:1-367](file://backend/app/agent_framework/dispatcher.py#L1-L367) + +### 业务生命周期管理 +- 功能要点 + - 项目创建:快速启动功能,自动生成5个阶段的项目。 + - 阶段管理:品牌基建、内容生产、AI适配优化、权威信号构建、持续运维。 + - 状态跟踪:项目进度、阶段状态、完成率统计和时间轴事件记录。 + - 统计分析:组织级别的项目统计和阶段分布。 +- 核心价值 + - 全生命周期视角:从品牌建设到持续运营的完整流程管理。 + - 可视化跟踪:阶段进度卡片和时间轴展示项目进展。 + - 数据驱动决策:基于统计数据的项目管理和资源配置。 +- 典型场景 + - 管理员创建品牌项目 → 各阶段负责人推进 → 实时查看进度 → 生成项目报告。 + +```mermaid +sequenceDiagram +participant Admin as "管理员" +participant API as "生命周期API" +participant S as "生命周期服务" +participant DB as "数据库" +Admin->>API : POST /api/v1/lifecycle/projects/quick-start +API->>S : 创建项目和5个阶段 +S->>DB : 插入LifecycleProject和ProjectStage +DB-->>S : 成功 +S-->>API : 返回项目详情 +API-->>Admin : 项目创建成功 +Admin->>API : GET /api/v1/lifecycle/projects/{id}/timeline +API->>S : 获取时间轴事件 +S->>DB : 查询项目和阶段 +DB-->>S : 事件列表 +S-->>API : 时间轴数据 +API-->>Admin : 渲染时间轴 +``` + +**图表来源** +- [backend/app/api/lifecycle.py:190-230](file://backend/app/api/lifecycle.py#L190-L230) +- [backend/app/api/lifecycle.py:138-187](file://backend/app/api/lifecycle.py#L138-L187) +- [backend/app/models/lifecycle.py:12-91](file://backend/app/models/lifecycle.py#L12-L91) + +**章节来源** +- [backend/app/api/lifecycle.py:1-297](file://backend/app/api/lifecycle.py#L1-L297) +- [backend/app/models/lifecycle.py:1-91](file://backend/app/models/lifecycle.py#L1-L91) +- [frontend/lib/api/lifecycle.ts:53-95](file://frontend/lib/api/lifecycle.ts#L53-L95) + +### 分析监控系统 +- 功能要点 + - 发布追踪:记录内容发布事件、更新效果指标和生成快照。 + - 性能分析:内容表现排行、单篇内容深度分析和历史趋势。 + - 智能洞察:基于LLM的自动化洞察生成,包含趋势、异常、机会和建议。 + - 统计概览:组织级别的发布统计、平台分布和互动率分析。 +- 核心价值 + - 数据驱动优化:基于真实效果数据的自动化洞察和建议。 + - 全面监控:从发布到效果的全流程数据追踪。 + - 智能辅助:AI驱动的分析和优化建议,提升内容质量。 +- 典型场景 + - 内容发布后自动记录效果 → 定期生成洞察报告 → 基于建议优化内容策略。 + +```mermaid +sequenceDiagram +participant CMS as "内容管理系统" +participant API as "分析API" +participant S as "分析服务" +participant DB as "数据库" +CMS->>API : POST /api/v1/analytics/publish +API->>S : 记录发布事件 +S->>DB : 插入PublishRecord +DB-->>S : 成功 +S->>DB : 插入ContentMetrics快照 +CMS->>API : GET /api/v1/analytics/insights +API->>S : 生成洞察 +S->>S : 调用LLM分析数据 +S->>DB : 插入OptimizationInsight +DB-->>S : 成功 +S-->>API : 返回洞察结果 +API-->>CMS : 洞察报告 +``` + +**图表来源** +- [backend/app/services/analytics/tracker.py:16-51](file://backend/app/services/analytics/tracker.py#L16-L51) +- [backend/app/services/analytics/insights.py:40-103](file://backend/app/services/analytics/insights.py#L40-L103) +- [backend/app/services/analytics/tracker.py:53-128](file://backend/app/services/analytics/tracker.py#L53-L128) + +**章节来源** +- [backend/app/services/analytics/tracker.py:1-230](file://backend/app/services/analytics/tracker.py#L1-L230) +- [backend/app/services/analytics/insights.py:1-313](file://backend/app/services/analytics/insights.py#L1-L313) + +### 知识库服务 +- 功能要点 + - RAG检索:文档分块、向量化嵌入和混合检索,支持多知识库查询。 + - 文档管理:支持URL抓取和文本上传,自动计算内容哈希和分块数量。 + - 知识库CRUD:多租户知识库管理,支持文档级联删除和统计更新。 + - 搜索日志:记录搜索查询、结果数量和延迟时间。 +- 核心价值 + - 智能检索:基于向量和关键词的混合检索,提升相关性。 + - 知识管理:结构化的知识库管理和版本控制。 + - 效率提升:自动化的文档处理和检索,减少人工维护成本。 +- 典型场景 + - 研究员上传行业报告 → 系统自动分块嵌入 → 搜索相关知识 → 生成内容。 + +```mermaid +sequenceDiagram +participant User as "用户" +participant API as "知识库API" +participant S as "RAG服务" +participant DB as "数据库" +User->>API : POST /api/v1/knowledge/bases/{kb_id}/documents +API->>S : 上传文档 +S->>DB : 插入KnowledgeDocument +S->>S : 分块 → 向量化 → 存储 +S->>DB : 插入KnowledgeChunk +DB-->>S : 成功 +S-->>API : 返回文档详情 +API-->>User : 上传完成 +User->>API : POST /api/v1/knowledge/search +API->>S : 执行RAG检索 +S->>DB : 查询向量相似度 +DB-->>S : 相关文档 +S-->>API : 返回检索结果 +API-->>User : 检索结果 +``` + +**图表来源** +- [backend/app/api/knowledge.py:217-293](file://backend/app/api/knowledge.py#L217-L293) +- [backend/app/api/knowledge.py:424-501](file://backend/app/api/knowledge.py#L424-L501) +- [backend/app/services/knowledge/rag_service.py:33-43](file://backend/app/services/knowledge/rag_service.py#L33-L43) + +**章节来源** +- [backend/app/api/knowledge.py:1-502](file://backend/app/api/knowledge.py#L1-L502) +- [backend/app/services/knowledge/rag_service.py:1-43](file://backend/app/services/knowledge/rag_service.py#L1-L43) +- [backend/app/models/knowledge.py:1-43](file://backend/app/models/knowledge.py#L1-L43) + ### 数据分析与可视化 - 功能要点 - 统计接口:总查询/引用数、引用率、平均位置、按平台汇总、30 天趋势(按自然周聚合)。 @@ -311,7 +607,7 @@ end - 快速洞察:总览指标帮助评估监测效果与变化趋势。 - 易用性:图表直观呈现,降低阅读成本。 - 典型场景 - - 研究人员查看“过去30天引用趋势”,发现某周显著上升,结合上下文进一步分析。 + - 研究人员查看"过去30天引用趋势",发现某周显著上升,结合上下文进一步分析。 ```mermaid sequenceDiagram @@ -377,43 +673,65 @@ API-->>FE : 流式响应(Attachment) - API 层仅负责参数解析与鉴权,业务逻辑集中在服务层,降低控制器复杂度。 - 引擎与平台适配器通过抽象接口解耦,便于替换与扩展。 - 调度器与引擎通过 ORM 与任务表协作,避免直接耦合业务数据。 + - AI代理框架通过任务分发器与代理实现松耦合。 + - 生命周期管理与项目阶段通过外键关联,确保数据一致性。 - 外部依赖 - FastAPI/SQLAlchemy:Web 框架与 ORM。 - APScheduler:异步定时任务调度。 - Recharts:前端图表渲染。 + - Redis:异步任务队列和缓存。 + - LLM提供商:OpenAI、DeepSeek等大模型服务。 - 潜在风险 - 平台适配器异常需隔离,避免影响其他平台任务。 - 大量并发查询可能带来数据库与外部平台压力,建议限流与重试策略。 + - AI代理任务的LLM调用可能存在成本控制和速率限制问题。 ```mermaid graph LR API["API层"] --> SVC["服务层"] SVC --> MODEL["模型层"] SVC --> WORKER["工作器"] +SVC --> AGENT["AI代理框架"] +SVC --> ANALYTICS["分析监控"] +SVC --> KNOWLEDGE["知识库服务"] WORKER --> ADAPTER["平台适配器"] +AGENT --> DISPATCHER["任务分发器"] +ANALYTICS --> LLM["LLM提供商"] +KNOWLEDGE --> VECTOR["向量数据库"] FE["前端"] --> API ``` **图表来源** - [backend/app/main.py:38-42](file://backend/app/main.py#L38-L42) - [backend/app/workers/citation_engine.py:151-157](file://backend/app/workers/citation_engine.py#L151-L157) +- [backend/app/agent_framework/dispatcher.py:35-46](file://backend/app/agent_framework/dispatcher.py#L35-L46) **章节来源** - [backend/app/main.py:1-48](file://backend/app/main.py#L1-L48) - [backend/app/workers/citation_engine.py:148-309](file://backend/app/workers/citation_engine.py#L148-L309) +- [backend/app/agent_framework/dispatcher.py:1-367](file://backend/app/agent_framework/dispatcher.py#L1-L367) ## 性能考虑 - 数据库 - 查询索引:查询与引用记录表均建立常用过滤字段索引,减少扫描开销。 - 分页与聚合:统计接口使用分组与聚合,避免一次性拉取全量数据。 + - 连接池:合理配置数据库连接池大小,避免连接争用。 - 引擎与平台 - 并行执行:同一查询的不同平台可并行处理,缩短总耗时。 - 错误隔离:单平台失败不影响其他平台,保证整体可用性。 + - 缓存策略:对频繁查询的结果进行缓存,减少重复计算。 - 前端 - 图表懒加载与响应式容器,提升大屏体验。 - 导出采用流式响应,避免内存峰值。 - -[本节为通用指导,无需具体文件分析] + - 代理状态轮询优化,避免过度请求。 +- AI代理框架 + - 任务队列:Redis队列支持高并发任务处理。 + - 超时控制:为LLM调用设置合理的超时时间。 + - 重试机制:失败任务自动重试,支持指数退避。 +- 知识库服务 + - 向量索引:优化向量相似度查询性能。 + - 分块策略:合理设置分块大小,平衡精度与性能。 + - 批量处理:批量插入和更新操作,减少数据库往返。 ## 故障排查指南 - 认证问题 @@ -421,8 +739,24 @@ FE["前端"] --> API - 登录失败:邮箱或密码错误;确认凭据正确与网络可达。 - 查询任务 - 创建被拒:超出配额;联系管理员提升限额或清理历史查询。 - - 无法执行:查询状态非“active”或未配置平台;检查状态与平台列表。 + - 无法执行:查询状态非"active"或未配置平台;检查状态与平台列表。 - 即时查询无响应:平台适配器异常或网络超时;查看任务状态与错误信息。 +- AI代理框架 + - 代理任务失败:检查代理配置、LLM提供商连接和任务输入参数。 + - Pipeline执行错误:验证YAML语法、依赖关系和变量引用。 + - 任务超时:调整超时设置或优化LLM调用参数。 +- 生命周期管理 + - 项目创建失败:检查组织权限和品牌名称唯一性。 + - 阶段推进异常:确认阶段状态和前置条件满足。 + - 统计数据缺失:验证项目数据完整性和时间范围设置。 +- 分析监控 + - 发布记录丢失:检查发布事件记录和数据库连接。 + - 洞察生成失败:确认LLM提供商可用性和API密钥配置。 + - 性能数据异常:验证指标计算逻辑和数据完整性。 +- 知识库服务 + - 文档上传失败:检查文件大小限制和内容格式。 + - 检索结果不准确:验证向量嵌入质量和检索参数设置。 + - 搜索日志缺失:确认日志记录和数据库写入权限。 - 统计与导出 - 统计为空:可能因筛选条件导致无数据;尝试放宽时间范围或移除查询筛选。 - 导出失败:查询不存在或无权限;确认 query_id 与登录态。 @@ -435,21 +769,27 @@ FE["前端"] --> API - [backend/app/services/citation.py:204-234](file://backend/app/services/citation.py#L204-L234) - [backend/app/api/reports.py:16-46](file://backend/app/api/reports.py#L16-L46) - [backend/app/workers/scheduler.py:30-40](file://backend/app/workers/scheduler.py#L30-L40) +- [backend/app/agent_framework/dispatcher.py:118-154](file://backend/app/agent_framework/dispatcher.py#L118-L154) +- [backend/app/api/lifecycle.py:190-230](file://backend/app/api/lifecycle.py#L190-L230) +- [backend/app/services/analytics/tracker.py:16-51](file://backend/app/services/analytics/tracker.py#L16-L51) +- [backend/app/api/knowledge.py:217-293](file://backend/app/api/knowledge.py#L217-L293) ## 结论 -GEO 平台以“查询—检测—统计—可视—导出”为主线,构建了从自动化采集到深度分析的完整链路。通过严格的权限控制、可扩展的平台适配器、稳健的定时调度与清晰的可视化输出,既能满足管理员对系统运行的掌控,也能为研究人员提供高效、可靠的品牌监测工具。建议后续在平台适配器层面引入重试与熔断、在数据库侧增加慢查询监控与索引优化,持续提升稳定性与性能。 - -[本节为总结性内容,无需具体文件分析] +GEO 平台以"查询—检测—智能代理—生命周期—分析监控—知识库—统计—可视—导出"为主线,构建了从自动化采集到深度分析的完整链路。通过严格的权限控制、可扩展的平台适配器、稳健的定时调度、智能化的AI代理编排、全生命周期的项目管理和全面的分析监控体系,既能满足管理员对系统运行的掌控,也能为研究人员提供高效、可靠的品牌监测工具。新增的AI代理框架、业务生命周期管理、分析监控系统和知识库服务等核心功能模块,进一步增强了平台的智能化水平和业务服务能力。建议后续在代理任务的成本控制、生命周期管理的自动化程度、分析洞察的准确性以及知识库的规模扩展等方面持续优化,以提升整体用户体验和平台价值。 ## 附录 - 典型使用流程(管理员) - - 新建用户/分配配额 → 配置平台密钥 → 监控调度器运行 → 查看任务状态与错误日志 → 调整频率策略。 + - 新建用户/分配配额 → 配置平台密钥 → 监控调度器运行 → 查看任务状态与错误日志 → 调整频率策略 → 管理代理任务 → 监控分析数据 → 维护知识库内容。 - 典型使用流程(研究人员) - - 登录 → 创建查询(关键词/目标品牌/平台/频率) → 查看仪表盘趋势 → 导出报告 → 深度分析与汇报。 + - 登录 → 创建查询(关键词/目标品牌/平台/频率) → 查看仪表盘趋势 → 导出报告 → 使用知识库检索相关信息 → 生成内容并进行优化 → 发布内容并跟踪效果。 +- 典型使用流程(项目经理) + - 登录 → 快速启动品牌项目 → 分配各阶段任务 → 跟踪项目进度 → 查看阶段报告 → 管理团队成员 → 生成项目总结。 - 关键接口路径参考 - 认证:POST /api/v1/auth/register, POST /api/v1/auth/login, GET /api/v1/auth/me - 查询:GET/POST/GET/PATCH/DELETE /api/v1/queries - 引用:GET /api/v1/citations, GET /api/v1/citations/stats, POST /api/v1/queries/{query_id}/run-now - 报告:GET /api/v1/reports/export/csv - -[本节为概览性内容,无需具体文件分析] \ No newline at end of file + - 生命周期:POST /api/v1/lifecycle/projects/quick-start, GET /api/v1/lifecycle/projects/{id}/timeline + - 知识库:POST /api/v1/knowledge/bases, POST /api/v1/knowledge/bases/{kb_id}/documents, POST /api/v1/knowledge/search + - 分析监控:POST /api/v1/analytics/publish, GET /api/v1/analytics/insights + - AI代理:POST /api/v1/agents/{agent_name}/{task_type} \ No newline at end of file diff --git a/.qoder/repowiki/zh/meta/repowiki-metadata.json b/.qoder/repowiki/zh/meta/repowiki-metadata.json index d5b88d2..d9ccc89 100644 --- a/.qoder/repowiki/zh/meta/repowiki-metadata.json +++ b/.qoder/repowiki/zh/meta/repowiki-metadata.json @@ -1 +1 @@ -{"code_snippets":[{"id":"8a466b0c6eac2ccb54c5da7e13854646","path":"frontend/app/layout.tsx","line_range":"1-37","gmt_create":"2026-04-23T15:19:43.759937+08:00","gmt_modified":"2026-04-23T15:19:43.759937+08:00"},{"id":"3bd4eedea376e3a3d9f9fbff4fe27a65","path":"frontend/components/layout/sidebar.tsx","line_range":"1-54","gmt_create":"2026-04-23T15:19:43.760535+08:00","gmt_modified":"2026-04-23T15:19:43.760535+08:00"},{"id":"0d903468b55bdc63cc7e25a87a89c522","path":"frontend/components/layout/header.tsx","line_range":"1-30","gmt_create":"2026-04-23T15:19:43.760868+08:00","gmt_modified":"2026-04-23T15:19:43.760868+08:00"},{"id":"3bab92a09e9fb456e0303bb1e04afc7e","path":"frontend/components/ui/table.tsx","line_range":"1-118","gmt_create":"2026-04-23T15:19:43.762327+08:00","gmt_modified":"2026-04-23T15:19:43.762327+08:00"},{"id":"0eed9f61572209dd754611fc7c690d5a","path":"frontend/components/ui/dialog.tsx","line_range":"1-123","gmt_create":"2026-04-23T15:19:43.762637+08:00","gmt_modified":"2026-04-23T15:19:43.762637+08:00"},{"id":"b7796fc6197ecce5beb461b9466e54a0","path":"frontend/components/charts/trend-chart.tsx","line_range":"1-60","gmt_create":"2026-04-23T15:19:43.762953+08:00","gmt_modified":"2026-04-23T15:19:43.762953+08:00"},{"id":"6b9f52af0b6d78c17ff9bbc42d760ea2","path":"frontend/components/charts/platform-chart.tsx","line_range":"1-68","gmt_create":"2026-04-23T15:19:43.763292+08:00","gmt_modified":"2026-04-23T15:19:43.763292+08:00"},{"id":"a829403082cc3460c01e0110229c53c4","path":"frontend/lib/platforms.ts","line_range":"1-18","gmt_create":"2026-04-23T15:19:43.763596+08:00","gmt_modified":"2026-04-23T15:19:43.763596+08:00"},{"id":"dcfa308ef4ec368c5a51a17acbfc8e2c","path":"frontend/lib/utils.ts","line_range":"1-7","gmt_create":"2026-04-23T15:19:43.763899+08:00","gmt_modified":"2026-04-23T15:19:43.763899+08:00"},{"id":"0f87c8089f548883d056f0a0d79e273f","path":"frontend/lib/api.ts","line_range":"1-79","gmt_create":"2026-04-23T15:19:43.764207+08:00","gmt_modified":"2026-04-23T15:19:43.764207+08:00"},{"id":"9beee1f41fe8f0750fd97155f9d54bbb","path":"frontend/lib/api.ts","line_range":"67-70","gmt_create":"2026-04-23T15:19:43.7681+08:00","gmt_modified":"2026-04-23T15:19:43.7681+08:00"},{"id":"8fe2e22a963442076e1ce16ab777573c","path":"frontend/lib/api.ts","line_range":"56-66","gmt_create":"2026-04-23T15:19:43.769967+08:00","gmt_modified":"2026-04-23T15:19:43.769967+08:00"},{"id":"3124ad882ca2cf8fecb6b93696c7f233","path":"frontend/lib/api.ts","line_range":"72-77","gmt_create":"2026-04-23T15:19:43.77323+08:00","gmt_modified":"2026-04-23T15:19:43.773231+08:00"},{"id":"17a97b4ac37fb67b8eda7ce2887c38e7","path":"frontend/app/layout.tsx","line_range":"17-20","gmt_create":"2026-04-23T15:19:43.777372+08:00","gmt_modified":"2026-04-23T15:19:43.777372+08:00"},{"id":"84cba1e0d516e8c9859402fd5c1bc83c","path":"frontend/lib/api.ts","line_range":"3-40","gmt_create":"2026-04-23T15:19:43.777696+08:00","gmt_modified":"2026-04-23T15:19:43.777696+08:00"},{"id":"b55a164add5a8fec2ef0e489f7234829","path":"backend/app/main.py","line_range":"24-47","gmt_create":"2026-04-23T15:19:45.591156+08:00","gmt_modified":"2026-04-23T15:19:45.591157+08:00"},{"id":"fa1ee5e3822128a37e9d03af74083392","path":"backend/app/api/queries.py","line_range":"12","gmt_create":"2026-04-23T15:19:45.591868+08:00","gmt_modified":"2026-04-23T15:19:45.591868+08:00"},{"id":"7e908f05baccdfcf7f4a3ef3c9cd5c38","path":"backend/app/api/citations.py","line_range":"21","gmt_create":"2026-04-23T15:19:45.592191+08:00","gmt_modified":"2026-04-23T15:19:45.592191+08:00"},{"id":"ae9de874df4a46f4197b6c157c25ec6e","path":"backend/app/api/queries.py","line_range":"15-85","gmt_create":"2026-04-23T15:19:45.594458+08:00","gmt_modified":"2026-04-23T15:19:45.594458+08:00"},{"id":"c066a8d4bffabed87a2e38ccad81c107","path":"backend/app/api/citations.py","line_range":"25-77","gmt_create":"2026-04-23T15:19:45.594783+08:00","gmt_modified":"2026-04-23T15:19:45.594783+08:00"},{"id":"bcdf50f6234651cb9863ab210e6473e5","path":"backend/app/api/deps.py","line_range":"16-42","gmt_create":"2026-04-23T15:19:45.595733+08:00","gmt_modified":"2026-04-23T15:19:45.595733+08:00"},{"id":"6df0277c2486b148fa26c2682dbdaa4c","path":"backend/app/services/auth.py","line_range":"37-68","gmt_create":"2026-04-23T15:19:45.59605+08:00","gmt_modified":"2026-04-23T15:19:45.59605+08:00"},{"id":"5ea5f192d580031ffe57e1582b70c67e","path":"backend/app/services/query.py","line_range":"12-123","gmt_create":"2026-04-23T15:19:45.596359+08:00","gmt_modified":"2026-04-23T15:19:45.596359+08:00"},{"id":"fe4a793f16cd4e12b56253c0a6d53ae0","path":"backend/app/services/citation.py","line_range":"24-359","gmt_create":"2026-04-23T15:19:45.596722+08:00","gmt_modified":"2026-04-23T15:19:45.596723+08:00"},{"id":"4aad38dfc00a0877bd965c3d0b3c280c","path":"backend/app/schemas/auth.py","line_range":"7-34","gmt_create":"2026-04-23T15:19:45.598915+08:00","gmt_modified":"2026-04-23T15:19:45.598915+08:00"},{"id":"9b10dac7dbbb1327afc8a525bf4bd0c3","path":"backend/app/services/query.py","line_range":"45-81","gmt_create":"2026-04-23T15:19:45.599689+08:00","gmt_modified":"2026-04-23T15:19:45.599689+08:00"},{"id":"69118807690ef351a9de910414d5e676","path":"backend/app/schemas/query.py","line_range":"11-94","gmt_create":"2026-04-23T15:19:45.6004+08:00","gmt_modified":"2026-04-23T15:19:45.6004+08:00"},{"id":"212d822d207a4c0bd7825bbf20e188e9","path":"backend/app/api/citations.py","line_range":"59-77","gmt_create":"2026-04-23T15:19:45.601069+08:00","gmt_modified":"2026-04-23T15:19:45.601069+08:00"},{"id":"b0777c7da17be89abb333c81c0dcf349","path":"backend/app/services/citation.py","line_range":"204-261","gmt_create":"2026-04-23T15:19:45.601383+08:00","gmt_modified":"2026-04-23T15:19:45.601384+08:00"},{"id":"26288877e8e1f6c4ff5aca12610b0218","path":"backend/app/schemas/citation.py","line_range":"7-50","gmt_create":"2026-04-23T15:19:45.602042+08:00","gmt_modified":"2026-04-23T15:19:45.602042+08:00"},{"id":"56e46969bdb790a5e8f333184b878d6d","path":"backend/app/models/user.py","line_range":"11-41","gmt_create":"2026-04-23T15:19:45.605045+08:00","gmt_modified":"2026-04-23T15:19:45.605046+08:00"},{"id":"4fb8856be3a581fe8303d11b2284ca29","path":"backend/app/models/query.py","line_range":"11-55","gmt_create":"2026-04-23T15:19:45.605965+08:00","gmt_modified":"2026-04-23T15:19:45.605965+08:00"},{"id":"fd541971cebf8a7c167d717f5c5d1ff6","path":"backend/app/models/citation_record.py","line_range":"11-42","gmt_create":"2026-04-23T15:19:45.606627+08:00","gmt_modified":"2026-04-23T15:19:45.606627+08:00"},{"id":"b84f46f058847733347974841f613688","path":"backend/app/models/query_task.py","line_range":"11-39","gmt_create":"2026-04-23T15:19:45.607023+08:00","gmt_modified":"2026-04-23T15:19:45.607023+08:00"},{"id":"1a2657244414b5681afded9565a86422","path":"backend/app/models/user.py","line_range":"35-40","gmt_create":"2026-04-23T15:19:45.60817+08:00","gmt_modified":"2026-04-23T15:19:45.60817+08:00"},{"id":"acd5a29be2bdd4ae251e10ca266ffe13","path":"backend/app/models/query.py","line_range":"43-48","gmt_create":"2026-04-23T15:19:45.608565+08:00","gmt_modified":"2026-04-23T15:19:45.608565+08:00"},{"id":"27a5e2dd1d197b2e3a45be41c57a6183","path":"backend/app/models/citation_record.py","line_range":"35","gmt_create":"2026-04-23T15:19:45.609141+08:00","gmt_modified":"2026-04-23T15:19:45.609141+08:00"},{"id":"c43e8fc0c04c5ed2db7798d99c8c77b8","path":"backend/app/models/query_task.py","line_range":"34","gmt_create":"2026-04-23T15:19:45.609534+08:00","gmt_modified":"2026-04-23T15:19:45.609534+08:00"},{"id":"a50f983ec39bac67dff5df80f6dad837","path":"backend/app/services/query.py","line_range":"59-60","gmt_create":"2026-04-23T15:19:45.61019+08:00","gmt_modified":"2026-04-23T15:19:45.61019+08:00"},{"id":"55f1628f1ab6f323710e367e12146b1a","path":"backend/app/api/citations.py","line_range":"67-71","gmt_create":"2026-04-23T15:19:45.610496+08:00","gmt_modified":"2026-04-23T15:19:45.610496+08:00"},{"id":"096856da621e23e78422a15e2bfce1f1","path":"backend/app/main.py","line_range":"13-22","gmt_create":"2026-04-23T15:20:08.95664+08:00","gmt_modified":"2026-04-23T15:20:08.95664+08:00"},{"id":"e230904202fcf7a861c6f49b84f9f863","path":"backend/app/workers/scheduler.py","line_range":"25-95","gmt_create":"2026-04-23T15:20:08.956979+08:00","gmt_modified":"2026-04-23T15:20:08.956979+08:00"},{"id":"309607c54b12a6340edc086ffb4737c9","path":"backend/app/workers/citation_engine.py","line_range":"148-309","gmt_create":"2026-04-23T15:20:08.957311+08:00","gmt_modified":"2026-04-23T15:20:08.957311+08:00"},{"id":"d7c319a04abbc6704da53107e07dd8e7","path":"backend/app/services/query.py","line_range":"12-130","gmt_create":"2026-04-23T15:20:08.958773+08:00","gmt_modified":"2026-04-23T15:20:08.958773+08:00"},{"id":"9bfc041fe426da2eb78353827e8d9163","path":"backend/app/database.py","line_range":"1-29","gmt_create":"2026-04-23T15:20:08.95909+08:00","gmt_modified":"2026-04-23T15:20:08.95909+08:00"},{"id":"ad67863041d9eea2b0fb542b5aa33aca","path":"backend/app/workers/platforms/base.py","line_range":"4-18","gmt_create":"2026-04-23T15:20:08.959413+08:00","gmt_modified":"2026-04-23T15:20:08.959413+08:00"},{"id":"eecf9581dbaa0a515cf11514175e7ef9","path":"backend/app/workers/platforms/kimi.py","line_range":"11-206","gmt_create":"2026-04-23T15:20:08.959726+08:00","gmt_modified":"2026-04-23T15:20:08.959726+08:00"},{"id":"5563c29185326a59be61ee0a6eec4463","path":"backend/app/workers/platforms/wenxin.py","line_range":"11-205","gmt_create":"2026-04-23T15:20:08.960155+08:00","gmt_modified":"2026-04-23T15:20:08.960155+08:00"},{"id":"2d35e1345d25020f8e7ac1318db06f7b","path":"backend/app/workers/scheduler.py","line_range":"30-90","gmt_create":"2026-04-23T15:20:08.96886+08:00","gmt_modified":"2026-04-23T15:20:08.968861+08:00"},{"id":"91bda120c0ab69e0e7103a1c89c82424","path":"backend/app/workers/scheduler.py","line_range":"95-172","gmt_create":"2026-04-23T15:20:08.969219+08:00","gmt_modified":"2026-04-23T15:20:08.969219+08:00"},{"id":"160b5326537d25444c40a459a01e79c6","path":"backend/app/workers/citation_engine.py","line_range":"159-234","gmt_create":"2026-04-23T15:20:08.969565+08:00","gmt_modified":"2026-04-23T15:20:08.969565+08:00"},{"id":"6712051c987e10a7c26b089063367398","path":"backend/app/models/query.py","line_range":"24-31","gmt_create":"2026-04-23T15:20:08.970051+08:00","gmt_modified":"2026-04-23T15:20:08.970052+08:00"},{"id":"ac5982063da5f04315f3e82a0d653902","path":"backend/app/models/query_task.py","line_range":"24-32","gmt_create":"2026-04-23T15:20:08.970717+08:00","gmt_modified":"2026-04-23T15:20:08.970717+08:00"},{"id":"06ed912983db33bb8aca162fed68282b","path":"backend/app/models/citation_record.py","line_range":"24-29","gmt_create":"2026-04-23T15:20:08.971135+08:00","gmt_modified":"2026-04-23T15:20:08.971135+08:00"},{"id":"b624be78e3bffd876e403cff2557b088","path":"backend/app/workers/citation_engine.py","line_range":"19-120","gmt_create":"2026-04-23T15:20:08.973448+08:00","gmt_modified":"2026-04-23T15:20:08.973448+08:00"},{"id":"40d0b169aad65c8bb38077deb052fc72","path":"backend/app/workers/platforms/kimi.py","line_range":"33-125","gmt_create":"2026-04-23T15:20:08.97414+08:00","gmt_modified":"2026-04-23T15:20:08.97414+08:00"},{"id":"8b5af998852596e1e08b0e0216bc4b93","path":"backend/app/workers/platforms/wenxin.py","line_range":"33-124","gmt_create":"2026-04-23T15:20:08.974449+08:00","gmt_modified":"2026-04-23T15:20:08.974449+08:00"},{"id":"fe70b1fef9f36e73d26d84987e927c7a","path":"backend/app/api/queries.py","line_range":"15-86","gmt_create":"2026-04-23T15:20:08.978743+08:00","gmt_modified":"2026-04-23T15:20:08.978743+08:00"},{"id":"e1d2b027678118df4d0a50ce9269271d","path":"backend/app/workers/scheduler.py","line_range":"42-90","gmt_create":"2026-04-23T15:20:08.982815+08:00","gmt_modified":"2026-04-23T15:20:08.982815+08:00"},{"id":"e79301a4bc26aa6b49f3f52c3182c3f9","path":"backend/app/workers/citation_engine.py","line_range":"175-234","gmt_create":"2026-04-23T15:20:08.983609+08:00","gmt_modified":"2026-04-23T15:20:08.983609+08:00"},{"id":"1e85186eded8743ff5f231df4aa6df3f","path":"backend/app/workers/platforms/kimi.py","line_range":"21-48","gmt_create":"2026-04-23T15:20:08.98454+08:00","gmt_modified":"2026-04-23T15:20:08.98454+08:00"},{"id":"e2b1718570fb714b2f4342221898ab30","path":"backend/app/workers/platforms/wenxin.py","line_range":"21-48","gmt_create":"2026-04-23T15:20:08.985237+08:00","gmt_modified":"2026-04-23T15:20:08.985237+08:00"},{"id":"e4a49039dae40b7433896c81737fcf8c","path":"backend/app/config.py","line_range":"7-14","gmt_create":"2026-04-23T15:20:08.985763+08:00","gmt_modified":"2026-04-23T15:20:08.985763+08:00"},{"id":"2ee31d68c409e96e951f6cfa7027bca7","path":"backend/app/main.py","line_range":"24-42","gmt_create":"2026-04-23T15:20:08.986265+08:00","gmt_modified":"2026-04-23T15:20:08.986265+08:00"},{"id":"79d6e169e36e6b7493898b5f863e07dc","path":"backend/app/workers/citation_engine.py","line_range":"152-157","gmt_create":"2026-04-23T15:20:08.987693+08:00","gmt_modified":"2026-04-23T15:20:08.987693+08:00"},{"id":"1552315d5fb9f6d7aba5f7e8fa93a975","path":"backend/app/database.py","line_range":"6-10","gmt_create":"2026-04-23T15:20:08.988709+08:00","gmt_modified":"2026-04-23T15:20:08.988709+08:00"},{"id":"599cca7536cae4a7e0ae93043c476a7f","path":"tests/test_queries.py","line_range":"10-154","gmt_create":"2026-04-23T15:20:08.989011+08:00","gmt_modified":"2026-04-23T15:20:08.989011+08:00"},{"id":"2ec3d45edd6221e0cedf7f8887fe090d","path":"tests/test_scheduler.py","line_range":"17-123","gmt_create":"2026-04-23T15:20:08.989312+08:00","gmt_modified":"2026-04-23T15:20:08.989312+08:00"},{"id":"4d323bf0aaf4078f09726dc0890e5955","path":"backend/app/models/subscription.py","line_range":"11-37","gmt_create":"2026-04-23T15:21:46.688165+08:00","gmt_modified":"2026-04-23T15:21:46.688166+08:00"},{"id":"4cef9e740b6feb68c6bd22b660c47320","path":"backend/app/services/query.py","line_range":"1-123","gmt_create":"2026-04-23T15:21:46.688903+08:00","gmt_modified":"2026-04-23T15:21:46.688903+08:00"},{"id":"121203f7f9f539ffb1456c3f5cdfd842","path":"backend/app/services/citation.py","line_range":"1-359","gmt_create":"2026-04-23T15:21:46.689338+08:00","gmt_modified":"2026-04-23T15:21:46.689338+08:00"},{"id":"10d1e37bdc9f353c189b7a2fe79dc85e","path":"backend/app/api/queries.py","line_range":"1-86","gmt_create":"2026-04-23T15:21:46.689691+08:00","gmt_modified":"2026-04-23T15:21:46.689691+08:00"},{"id":"cbd0101fa84d957bcb1baaa623c6b31c","path":"backend/app/api/citations.py","line_range":"1-78","gmt_create":"2026-04-23T15:21:46.690036+08:00","gmt_modified":"2026-04-23T15:21:46.690036+08:00"},{"id":"afe4138895492c26aac5c0120ef46cd8","path":"backend/app/models/__init__.py","line_range":"1-14","gmt_create":"2026-04-23T15:21:46.69035+08:00","gmt_modified":"2026-04-23T15:21:46.69035+08:00"},{"id":"4d11ddf7abb8076d81b30c4315786f9a","path":"backend/alembic/versions/488d0bd5ab01_initial_migration.py","line_range":"21-128","gmt_create":"2026-04-23T15:21:46.693035+08:00","gmt_modified":"2026-04-23T15:21:46.693035+08:00"},{"id":"e454b4a54500bd81e7599e6ec97bf12b","path":"backend/alembic/versions/488d0bd5ab01_initial_migration.py","line_range":"23-37","gmt_create":"2026-04-23T15:21:46.695671+08:00","gmt_modified":"2026-04-23T15:21:46.695671+08:00"},{"id":"1965adf7cfc65447e3c1ae21fbf6d1c5","path":"backend/alembic/versions/488d0bd5ab01_initial_migration.py","line_range":"39-59","gmt_create":"2026-04-23T15:21:46.696432+08:00","gmt_modified":"2026-04-23T15:21:46.696432+08:00"},{"id":"c730faefb34bb87c40c5f636b4ff7f41","path":"backend/alembic/versions/488d0bd5ab01_initial_migration.py","line_range":"80-94","gmt_create":"2026-04-23T15:21:46.697413+08:00","gmt_modified":"2026-04-23T15:21:46.697413+08:00"},{"id":"b9978c3eccea3ef566b003216e5047af","path":"backend/alembic/versions/488d0bd5ab01_initial_migration.py","line_range":"61-78","gmt_create":"2026-04-23T15:21:46.698274+08:00","gmt_modified":"2026-04-23T15:21:46.698274+08:00"},{"id":"eb6ff4361d7413b57f1f70b1ec2f0c94","path":"backend/alembic/versions/488d0bd5ab01_initial_migration.py","line_range":"96-111","gmt_create":"2026-04-23T15:21:46.699021+08:00","gmt_modified":"2026-04-23T15:21:46.699021+08:00"},{"id":"f6c9f1b4e8646c366a31426a4537675d","path":"backend/app/models/query_task.py","line_range":"36-38","gmt_create":"2026-04-23T15:21:46.700462+08:00","gmt_modified":"2026-04-23T15:21:46.700462+08:00"},{"id":"a2adbf02c71e4eb2cf1f120e1a2ff517","path":"backend/app/models/citation_record.py","line_range":"37-41","gmt_create":"2026-04-23T15:21:46.70082+08:00","gmt_modified":"2026-04-23T15:21:46.700821+08:00"},{"id":"0907fc2974ec31c23aaaef02076700a1","path":"backend/app/models/user.py","line_range":"25-33","gmt_create":"2026-04-23T15:21:46.702342+08:00","gmt_modified":"2026-04-23T15:21:46.702342+08:00"},{"id":"842f74e2cc054608242e93fbefd96b45","path":"backend/app/models/query.py","line_range":"32-40","gmt_create":"2026-04-23T15:21:46.702652+08:00","gmt_modified":"2026-04-23T15:21:46.702652+08:00"},{"id":"aed9e839038c45e6ce2023c4e05adb76","path":"backend/app/models/query_task.py","line_range":"27-32","gmt_create":"2026-04-23T15:21:46.702999+08:00","gmt_modified":"2026-04-23T15:21:46.703+08:00"},{"id":"2181318c993526c86458f5eef134aed6","path":"backend/app/services/query.py","line_range":"62-77","gmt_create":"2026-04-23T15:21:46.703419+08:00","gmt_modified":"2026-04-23T15:21:46.703419+08:00"},{"id":"a817488dc968d761a8977fb5bb8d01a2","path":"backend/app/services/query.py","line_range":"45-129","gmt_create":"2026-04-23T15:21:46.703795+08:00","gmt_modified":"2026-04-23T15:21:46.703795+08:00"},{"id":"d20fc729a5d3986b1c077f9e07ece9c4","path":"backend/app/config.py","line_range":"7","gmt_create":"2026-04-23T15:21:46.704958+08:00","gmt_modified":"2026-04-23T15:21:46.704958+08:00"},{"id":"ea655c6d147bc98beb42955d437260cc","path":"backend/app/config.py","line_range":"1-23","gmt_create":"2026-04-23T15:21:46.705746+08:00","gmt_modified":"2026-04-23T15:21:46.705746+08:00"},{"id":"37868a5af96edcdad149caf9a184435a","path":"backend/app/api/queries.py","line_range":"42-85","gmt_create":"2026-04-23T15:21:46.706426+08:00","gmt_modified":"2026-04-23T15:21:46.706426+08:00"},{"id":"601b981b00d93b941843f046a163d5a3","path":"backend/app/schemas/query.py","line_range":"18-33","gmt_create":"2026-04-23T15:21:46.706755+08:00","gmt_modified":"2026-04-23T15:21:46.706755+08:00"},{"id":"290df8332b3d104e5ea8d71dc39315b5","path":"tests/conftest.py","line_range":"1-123","gmt_create":"2026-04-23T15:22:15.985975+08:00","gmt_modified":"2026-04-23T15:22:15.985975+08:00"},{"id":"c2747ca16b879bca0f68955534c3c4fc","path":"backend/app/main.py","line_range":"1-48","gmt_create":"2026-04-23T15:22:15.986592+08:00","gmt_modified":"2026-04-23T15:22:15.986592+08:00"},{"id":"76e6c0abb49fec57cac4892837a143c9","path":"backend/app/api/deps.py","line_range":"1-43","gmt_create":"2026-04-23T15:22:15.987077+08:00","gmt_modified":"2026-04-23T15:22:15.987077+08:00"},{"id":"f66d9907b467b110c638bd527efd95c5","path":"backend/app/api/auth.py","line_range":"1-43","gmt_create":"2026-04-23T15:22:15.987417+08:00","gmt_modified":"2026-04-23T15:22:15.987417+08:00"},{"id":"116584ea9162c1bc05911f39f9ef82b6","path":"backend/app/workers/citation_engine.py","line_range":"1-309","gmt_create":"2026-04-23T15:22:15.988451+08:00","gmt_modified":"2026-04-23T15:22:15.988451+08:00"},{"id":"9630036e63fc15cb81b202cf79671aab","path":"backend/app/workers/scheduler.py","line_range":"1-182","gmt_create":"2026-04-23T15:22:15.988885+08:00","gmt_modified":"2026-04-23T15:22:15.988885+08:00"},{"id":"84fbed7d35f7752e2117a74fcaf5f0e9","path":"backend/app/config.py","line_range":"1-17","gmt_create":"2026-04-23T15:22:15.989594+08:00","gmt_modified":"2026-04-23T15:22:15.989594+08:00"},{"id":"5ddf0c8d7b38e4f6126a5d85da1dfeda","path":"tests/conftest.py","line_range":"19-123","gmt_create":"2026-04-23T15:22:15.990689+08:00","gmt_modified":"2026-04-23T15:22:15.990689+08:00"},{"id":"9df233ef1be4b95068ed91bf01083ae7","path":"tests/conftest.py","line_range":"117-123","gmt_create":"2026-04-23T15:22:15.99106+08:00","gmt_modified":"2026-04-23T15:22:15.99106+08:00"},{"id":"6286d4be455dc058c8be2ee4e0d1175a","path":"backend/app/main.py","line_range":"38-42","gmt_create":"2026-04-23T15:22:15.991399+08:00","gmt_modified":"2026-04-23T15:22:15.991399+08:00"},{"id":"069243fafe60a85cf16a0ca40fa07180","path":"backend/app/api/deps.py","line_range":"16-43","gmt_create":"2026-04-23T15:22:15.991722+08:00","gmt_modified":"2026-04-23T15:22:15.991722+08:00"},{"id":"d5a1fb0bd23ce9240fbf79529ef94a45","path":"backend/app/api/auth.py","line_range":"13-43","gmt_create":"2026-04-23T15:22:15.992045+08:00","gmt_modified":"2026-04-23T15:22:15.992045+08:00"},{"id":"735aef72b4fe6ca4f407e69b7dda8b43","path":"backend/app/api/citations.py","line_range":"25-78","gmt_create":"2026-04-23T15:22:15.992721+08:00","gmt_modified":"2026-04-23T15:22:15.992721+08:00"},{"id":"8128dd67cf376d2cadf7c2d3831c380a","path":"backend/app/database.py","line_range":"23-29","gmt_create":"2026-04-23T15:22:15.993159+08:00","gmt_modified":"2026-04-23T15:22:15.993159+08:00"},{"id":"1721defc3d6206478d3c0692cc821761","path":"tests/test_auth.py","line_range":"25-104","gmt_create":"2026-04-23T15:22:15.9936+08:00","gmt_modified":"2026-04-23T15:22:15.9936+08:00"},{"id":"753a437d837246ead62b0e16c6331284","path":"backend/app/services/auth.py","line_range":"37-69","gmt_create":"2026-04-23T15:22:15.994329+08:00","gmt_modified":"2026-04-23T15:22:15.994329+08:00"},{"id":"d820e2daf2ea133a7aa17cdc475e44a4","path":"tests/test_auth.py","line_range":"1-104","gmt_create":"2026-04-23T15:22:15.99504+08:00","gmt_modified":"2026-04-23T15:22:15.99504+08:00"},{"id":"1a439c5fed6cfd188c646e1614d56371","path":"backend/app/services/auth.py","line_range":"1-69","gmt_create":"2026-04-23T15:22:15.995715+08:00","gmt_modified":"2026-04-23T15:22:15.995715+08:00"},{"id":"5c67e2f70283956b2d29a3c1443eb514","path":"backend/app/workers/citation_engine.py","line_range":"122-146","gmt_create":"2026-04-23T15:22:15.996787+08:00","gmt_modified":"2026-04-23T15:22:15.996787+08:00"},{"id":"a57acd9da5287c915ac823784a409292","path":"tests/test_citation_engine.py","line_range":"1-127","gmt_create":"2026-04-23T15:22:15.99744+08:00","gmt_modified":"2026-04-23T15:22:15.99744+08:00"},{"id":"2a4f741f31f62dce8ad63be2e831f520","path":"tests/test_citations.py","line_range":"23-93","gmt_create":"2026-04-23T15:22:15.998141+08:00","gmt_modified":"2026-04-23T15:22:15.998141+08:00"},{"id":"692ac240965eff7e66945aa3c4c270f7","path":"tests/test_citations.py","line_range":"1-93","gmt_create":"2026-04-23T15:22:15.998797+08:00","gmt_modified":"2026-04-23T15:22:15.998797+08:00"},{"id":"32a0a52faca2d8d488e49c63c86075b1","path":"tests/test_queries.py","line_range":"29-154","gmt_create":"2026-04-23T15:22:15.999443+08:00","gmt_modified":"2026-04-23T15:22:15.999444+08:00"},{"id":"7804331f5f8c1ba5a3b6d9c1ae1c78c1","path":"tests/test_queries.py","line_range":"1-154","gmt_create":"2026-04-23T15:22:16.000539+08:00","gmt_modified":"2026-04-23T15:22:16.000539+08:00"},{"id":"3a6e1b738967bf8cc651e57f48e2e126","path":"tests/test_business_flow.py","line_range":"83-126","gmt_create":"2026-04-23T15:22:16.00171+08:00","gmt_modified":"2026-04-23T15:22:16.00171+08:00"},{"id":"b1afd377757f1d0e9bdf87edfff3ad88","path":"tests/test_business_flow.py","line_range":"131-186","gmt_create":"2026-04-23T15:22:16.002219+08:00","gmt_modified":"2026-04-23T15:22:16.002219+08:00"},{"id":"de05ec7eed033e432991e5a88e1b5a06","path":"tests/test_business_flow.py","line_range":"192-222","gmt_create":"2026-04-23T15:22:16.002653+08:00","gmt_modified":"2026-04-23T15:22:16.002653+08:00"},{"id":"7fd61a451248b6b129299d6246f711c7","path":"tests/test_business_flow.py","line_range":"228-296","gmt_create":"2026-04-23T15:22:16.003121+08:00","gmt_modified":"2026-04-23T15:22:16.003121+08:00"},{"id":"53eedffff456a566fa7b0cecc7169f56","path":"tests/test_business_flow.py","line_range":"1-441","gmt_create":"2026-04-23T15:22:16.003614+08:00","gmt_modified":"2026-04-23T15:22:16.003615+08:00"},{"id":"906f7a8288e38d4244211f3f538fe7b6","path":"backend/app/workers/scheduler.py","line_range":"27-182","gmt_create":"2026-04-23T15:22:16.004044+08:00","gmt_modified":"2026-04-23T15:22:16.004044+08:00"},{"id":"1647ee2066de2ae59ba8cf88e33c5e02","path":"tests/test_scheduler.py","line_range":"1-123","gmt_create":"2026-04-23T15:22:16.004461+08:00","gmt_modified":"2026-04-23T15:22:16.004461+08:00"},{"id":"fd18328b6582e68c30b130b912891992","path":"frontend/components/providers.tsx","line_range":"1-9","gmt_create":"2026-04-23T15:22:23.501815+08:00","gmt_modified":"2026-04-23T15:22:23.501815+08:00"},{"id":"71a37a516437e94fd82a87efc70a3f16","path":"frontend/package.json","line_range":"1-40","gmt_create":"2026-04-23T15:22:23.503888+08:00","gmt_modified":"2026-04-23T15:22:23.503888+08:00"},{"id":"89d70e5f89be23a229e3ee59982b8e6e","path":"frontend/tailwind.config.ts","line_range":"1-57","gmt_create":"2026-04-23T15:22:23.504853+08:00","gmt_modified":"2026-04-23T15:22:23.504853+08:00"},{"id":"95be577a89fbeb02578e4c3718c6ec86","path":"frontend/components/ui/button.tsx","line_range":"1-57","gmt_create":"2026-04-23T15:22:23.505579+08:00","gmt_modified":"2026-04-23T15:22:23.505579+08:00"},{"id":"607bb628918a7a5d54cbf74763f94d07","path":"frontend/components/ui/input.tsx","line_range":"1-23","gmt_create":"2026-04-23T15:22:23.506257+08:00","gmt_modified":"2026-04-23T15:22:23.506257+08:00"},{"id":"325e25d1dda0f7bfd9d7adfe35ecf3b5","path":"frontend/components/ui/select.tsx","line_range":"1-161","gmt_create":"2026-04-23T15:22:23.507044+08:00","gmt_modified":"2026-04-23T15:22:23.507044+08:00"},{"id":"ad6ff021b2126ad5c42323305eb6d8b0","path":"frontend/components/ui/dropdown-menu.tsx","line_range":"1-201","gmt_create":"2026-04-23T15:22:23.507926+08:00","gmt_modified":"2026-04-23T15:22:23.507926+08:00"},{"id":"a85f004dca63614b4e734ba63b45ef9e","path":"frontend/components/ui/card.tsx","line_range":"1-80","gmt_create":"2026-04-23T15:22:23.508411+08:00","gmt_modified":"2026-04-23T15:22:23.508411+08:00"},{"id":"bd3042a8d9b602334720b0d7b4e8ab3d","path":"frontend/components/ui/tabs.tsx","line_range":"1-56","gmt_create":"2026-04-23T15:22:23.509355+08:00","gmt_modified":"2026-04-23T15:22:23.509355+08:00"},{"id":"379443f450513b5492e2d9d5fca94a42","path":"frontend/components/ui/label.tsx","line_range":"1-27","gmt_create":"2026-04-23T15:22:23.509832+08:00","gmt_modified":"2026-04-23T15:22:23.509832+08:00"},{"id":"4aa6ad434a73143bb7a2072124f63be0","path":"frontend/components/ui/badge.tsx","line_range":"1-37","gmt_create":"2026-04-23T15:22:23.510286+08:00","gmt_modified":"2026-04-23T15:22:23.510286+08:00"},{"id":"c45dbdda70a8b9f02b52af4991644d0b","path":"frontend/package.json","line_range":"11-27","gmt_create":"2026-04-23T15:22:23.511056+08:00","gmt_modified":"2026-04-23T15:22:23.511056+08:00"},{"id":"6ac6943c93570294e4fb15a862be2616","path":"frontend/components/ui/button.tsx","line_range":"36-54","gmt_create":"2026-04-23T15:22:23.51229+08:00","gmt_modified":"2026-04-23T15:22:23.51229+08:00"},{"id":"4bfb5059c685e9878aed64cb5347ccec","path":"frontend/components/ui/dialog.tsx","line_range":"9-54","gmt_create":"2026-04-23T15:22:23.513266+08:00","gmt_modified":"2026-04-23T15:22:23.513266+08:00"},{"id":"0af48b69fe8fb9e480fa1656f36a4330","path":"frontend/components/ui/dropdown-menu.tsx","line_range":"21-75","gmt_create":"2026-04-23T15:22:23.514127+08:00","gmt_modified":"2026-04-23T15:22:23.514127+08:00"},{"id":"09971e31ab658e119d4c0ad948282107","path":"frontend/components/ui/select.tsx","line_range":"15-100","gmt_create":"2026-04-23T15:22:23.514956+08:00","gmt_modified":"2026-04-23T15:22:23.514956+08:00"},{"id":"31aa8777de6043883950d2668094e388","path":"frontend/components/ui/table.tsx","line_range":"5-106","gmt_create":"2026-04-23T15:22:23.515769+08:00","gmt_modified":"2026-04-23T15:22:23.515769+08:00"},{"id":"28baf3cedb89a21c6d542b7ce2439b24","path":"frontend/components/ui/tabs.tsx","line_range":"8-53","gmt_create":"2026-04-23T15:22:23.516573+08:00","gmt_modified":"2026-04-23T15:22:23.516573+08:00"},{"id":"28b0f4797c6084272244175a24b961cb","path":"frontend/components/ui/card.tsx","line_range":"5-77","gmt_create":"2026-04-23T15:22:23.518527+08:00","gmt_modified":"2026-04-23T15:22:23.518527+08:00"},{"id":"a6e0b3fa65906c3c3cd88707e1d40059","path":"frontend/components/ui/label.tsx","line_range":"9-23","gmt_create":"2026-04-23T15:22:23.520181+08:00","gmt_modified":"2026-04-23T15:22:23.520181+08:00"},{"id":"9a909775022010b4686c2b00cdf1c165","path":"frontend/components/ui/badge.tsx","line_range":"6-34","gmt_create":"2026-04-23T15:22:23.521343+08:00","gmt_modified":"2026-04-23T15:22:23.521343+08:00"},{"id":"ce1cd184945ae56cf63f55168afd8050","path":"frontend/components/ui/dialog.tsx","line_range":"47-50","gmt_create":"2026-04-23T15:22:23.523823+08:00","gmt_modified":"2026-04-23T15:22:23.523823+08:00"},{"id":"4a2a06e1efcbc85deaa013dca155f20c","path":"frontend/tailwind.config.ts","line_range":"10-54","gmt_create":"2026-04-23T15:22:23.524333+08:00","gmt_modified":"2026-04-23T15:22:23.524333+08:00"},{"id":"8b00ea4aba57ea6ed982287fb7840805","path":"frontend/lib/utils.ts","line_range":"4-6","gmt_create":"2026-04-23T15:22:23.524876+08:00","gmt_modified":"2026-04-23T15:22:23.524876+08:00"},{"id":"7c0831c17e8c65eaed9511e17ed2a2ef","path":"backend/app/services/citation.py","line_range":"1-269","gmt_create":"2026-04-23T20:31:36.482111+08:00","gmt_modified":"2026-04-23T20:31:36.482111+08:00"},{"id":"71f98c8993fb42b108e34a554247869b","path":"backend/app/workers/scheduler.py","line_range":"1-95","gmt_create":"2026-04-23T20:31:36.482732+08:00","gmt_modified":"2026-04-23T20:31:36.482732+08:00"},{"id":"8d5aac2ae0671f05d7c0807ba9296cdf","path":"backend/app/workers/citation_engine.py","line_range":"1-330","gmt_create":"2026-04-23T20:31:36.4831+08:00","gmt_modified":"2026-04-23T20:31:36.4831+08:00"},{"id":"debd789847d1eed2d54198772edf68a2","path":"backend/app/workers/platforms/tongyi.py","line_range":"1-38","gmt_create":"2026-04-23T20:31:36.483423+08:00","gmt_modified":"2026-04-23T20:31:36.483423+08:00"},{"id":"3bde521d18cc7221ae2f14637e163aac","path":"backend/app/workers/platforms/doubao.py","line_range":"1-38","gmt_create":"2026-04-23T20:31:36.483821+08:00","gmt_modified":"2026-04-23T20:31:36.483821+08:00"},{"id":"c26862d9e0fc878b51a2668cfd2ec827","path":"backend/app/workers/platforms/qingyan.py","line_range":"1-38","gmt_create":"2026-04-23T20:31:36.484113+08:00","gmt_modified":"2026-04-23T20:31:36.484114+08:00"},{"id":"0fcc9c2e0d33b887c5f18a3807b64a1e","path":"backend/app/workers/platforms/tiangong.py","line_range":"1-38","gmt_create":"2026-04-23T20:31:36.484512+08:00","gmt_modified":"2026-04-23T20:31:36.484512+08:00"},{"id":"a4baa2444208b3f9a3f42bc492038207","path":"backend/app/workers/platforms/xinghuo.py","line_range":"1-38","gmt_create":"2026-04-23T20:31:36.485041+08:00","gmt_modified":"2026-04-23T20:31:36.485041+08:00"},{"id":"9f82f6d82bf914a608d6afa3d9854abf","path":"backend/app/workers/platforms/search_engine.py","line_range":"1-174","gmt_create":"2026-04-23T20:31:36.485492+08:00","gmt_modified":"2026-04-23T20:31:36.485492+08:00"},{"id":"6281fff17a86ec1895c64d87c2ae7fb1","path":"backend/app/models/query.py","line_range":"1-55","gmt_create":"2026-04-23T20:31:36.486251+08:00","gmt_modified":"2026-04-23T20:31:36.486251+08:00"},{"id":"943c18db69a04b3137fba4cebcfea87e","path":"backend/app/models/citation_record.py","line_range":"1-42","gmt_create":"2026-04-23T20:31:36.48687+08:00","gmt_modified":"2026-04-23T20:31:36.48687+08:00"},{"id":"6628e006b8e5ca16160743528b6b0506","path":"backend/app/models/query_task.py","line_range":"1-39","gmt_create":"2026-04-23T20:31:36.487305+08:00","gmt_modified":"2026-04-23T20:31:36.487305+08:00"},{"id":"72a110dca58d8152758e2fdab4e94761","path":"backend/app/workers/platforms/base.py","line_range":"1-18","gmt_create":"2026-04-23T20:31:36.490327+08:00","gmt_modified":"2026-04-23T20:31:36.490328+08:00"},{"id":"300e43c7a648440163f81039eaa47b5a","path":"frontend/lib/platforms.ts","line_range":"1-24","gmt_create":"2026-04-23T20:31:36.494718+08:00","gmt_modified":"2026-04-23T20:31:36.494718+08:00"},{"id":"caf1970ded8fc5d3921005e166e2100b","path":"backend/app/api/citations.py","line_range":"59-78","gmt_create":"2026-04-23T20:31:36.499676+08:00","gmt_modified":"2026-04-23T20:31:36.499677+08:00"},{"id":"4ded871d02b8119cdd985de8b220b084","path":"backend/app/services/citation.py","line_range":"204-234","gmt_create":"2026-04-23T20:31:36.500626+08:00","gmt_modified":"2026-04-23T20:31:36.500626+08:00"},{"id":"448970b02d89d5e1576f70bdb0063363","path":"backend/app/workers/scheduler.py","line_range":"51-84","gmt_create":"2026-04-23T20:31:36.501136+08:00","gmt_modified":"2026-04-23T20:31:36.501136+08:00"},{"id":"362d22f423631cda39404660b3317a2f","path":"backend/app/workers/citation_engine.py","line_range":"177-254","gmt_create":"2026-04-23T20:31:36.501596+08:00","gmt_modified":"2026-04-23T20:31:36.501596+08:00"},{"id":"b475ff5225ac403c7fcf3dd7e14cbac6","path":"backend/app/workers/platforms/tongyi.py","line_range":"16-33","gmt_create":"2026-04-23T20:31:36.502032+08:00","gmt_modified":"2026-04-23T20:31:36.502032+08:00"},{"id":"557ae34b57a5dd8e8fa3bb2a6ce178a7","path":"backend/app/workers/platforms/search_engine.py","line_range":"163-174","gmt_create":"2026-04-23T20:31:36.502504+08:00","gmt_modified":"2026-04-23T20:31:36.502504+08:00"},{"id":"75c6ab0599d304bf36d290d4143d3d2f","path":"backend/app/models/query.py","line_range":"29-31","gmt_create":"2026-04-23T20:31:36.502934+08:00","gmt_modified":"2026-04-23T20:31:36.502934+08:00"},{"id":"2a6780838f1415dcb7d0fa611f64cee7","path":"backend/app/workers/platforms/base.py","line_range":"4-17","gmt_create":"2026-04-23T20:31:36.504228+08:00","gmt_modified":"2026-04-23T20:31:36.504228+08:00"},{"id":"c5ae7697193b2b93425ff25d2d7d54a9","path":"backend/app/workers/platforms/tongyi.py","line_range":"10-38","gmt_create":"2026-04-23T20:31:36.505069+08:00","gmt_modified":"2026-04-23T20:31:36.505069+08:00"},{"id":"aa8c3fa3bc509dafe64d113bdd09eafa","path":"backend/app/workers/platforms/doubao.py","line_range":"10-38","gmt_create":"2026-04-23T20:31:36.505502+08:00","gmt_modified":"2026-04-23T20:31:36.505503+08:00"},{"id":"eabb031e538ea62cab69b01368740d20","path":"backend/app/workers/platforms/qingyan.py","line_range":"10-38","gmt_create":"2026-04-23T20:31:36.505932+08:00","gmt_modified":"2026-04-23T20:31:36.505932+08:00"},{"id":"b1c09e372a63e9854886adaea1663bea","path":"backend/app/workers/platforms/tiangong.py","line_range":"10-38","gmt_create":"2026-04-23T20:31:36.50633+08:00","gmt_modified":"2026-04-23T20:31:36.50633+08:00"},{"id":"79793bcd507f9d287d19014b60d963d3","path":"backend/app/workers/platforms/xinghuo.py","line_range":"10-38","gmt_create":"2026-04-23T20:31:36.506717+08:00","gmt_modified":"2026-04-23T20:31:36.506717+08:00"},{"id":"102223dd13475177a1ade8b9be14fbd1","path":"backend/app/workers/platforms/search_engine.py","line_range":"79-144","gmt_create":"2026-04-23T20:31:36.509667+08:00","gmt_modified":"2026-04-23T20:31:36.509667+08:00"},{"id":"8565f299083b4dcba5a328c947f06fee","path":"backend/app/workers/citation_engine.py","line_range":"256-287","gmt_create":"2026-04-23T20:31:36.512515+08:00","gmt_modified":"2026-04-23T20:31:36.512515+08:00"},{"id":"8af91caf063c12c8236f9675769ce4a1","path":"tests/test_citation_engine.py","line_range":"1-54","gmt_create":"2026-04-23T20:31:36.51401+08:00","gmt_modified":"2026-04-23T20:31:36.51401+08:00"},{"id":"005172b71dc742cf6803c5eb0185091e","path":"backend/requirements.txt","line_range":"1-36","gmt_create":"2026-04-23T20:31:36.516249+08:00","gmt_modified":"2026-04-23T20:31:36.516249+08:00"},{"id":"b55cc5936c299f819b57b899858438e6","path":"backend/app/workers/platforms/search_engine.py","line_range":"139-144","gmt_create":"2026-04-23T20:31:36.518228+08:00","gmt_modified":"2026-04-23T20:31:36.518228+08:00"},{"id":"384b1939e53970ce7ae75d241a49da5f","path":"backend/app/workers/platforms/tongyi.py","line_range":"22-29","gmt_create":"2026-04-23T20:31:36.518493+08:00","gmt_modified":"2026-04-23T20:31:36.518493+08:00"},{"id":"f096aa3ea82e9fa625a9acb1309b4c50","path":"backend/app/workers/citation_engine.py","line_range":"231-247","gmt_create":"2026-04-23T20:31:36.518795+08:00","gmt_modified":"2026-04-23T20:31:36.518795+08:00"},{"id":"15b8ebf74b0a5dfac58024d323ca8d0a","path":"backend/app/workers/citation_engine.py","line_range":"164-175","gmt_create":"2026-04-23T20:31:36.519395+08:00","gmt_modified":"2026-04-23T20:31:36.519395+08:00"},{"id":"bcfade20d923c8efa713808ca9af94ca","path":"backend/app/workers/platforms/wenxin.py","line_range":"10-38","gmt_create":"2026-04-23T20:31:50.45294+08:00","gmt_modified":"2026-04-23T20:31:50.45294+08:00"},{"id":"ca7e1232fbba5fb75e04ab8e491bfbd1","path":"backend/app/workers/platforms/kimi.py","line_range":"10-38","gmt_create":"2026-04-23T20:31:50.453339+08:00","gmt_modified":"2026-04-23T20:31:50.453339+08:00"},{"id":"9720b93ed7247efb685e2825e5f964bf","path":"backend/app/workers/citation_engine.py","line_range":"161-176","gmt_create":"2026-04-23T20:31:50.454207+08:00","gmt_modified":"2026-04-23T20:31:50.454207+08:00"},{"id":"0d226400124ba891a46f59c36781ccd8","path":"backend/app/config.py","line_range":"9-23","gmt_create":"2026-04-23T20:31:50.454503+08:00","gmt_modified":"2026-04-23T20:31:50.454503+08:00"},{"id":"412695e5de2014514a8f62f98c573656","path":"backend/Dockerfile","line_range":"1-41","gmt_create":"2026-04-23T20:31:50.454798+08:00","gmt_modified":"2026-04-23T20:31:50.454798+08:00"},{"id":"485e15eb30a5b08da38a628c9dd5053e","path":"backend/app/workers/platforms/search_engine.py","line_range":"16-77","gmt_create":"2026-04-23T20:31:50.459138+08:00","gmt_modified":"2026-04-23T20:31:50.459138+08:00"},{"id":"77158a6f887e224a03552893bfec7c92","path":"backend/app/workers/platforms/wenxin.py","line_range":"16-33","gmt_create":"2026-04-23T20:31:50.461662+08:00","gmt_modified":"2026-04-23T20:31:50.461662+08:00"},{"id":"5c3f336b5a7b4af4cc2f2ac183539218","path":"backend/app/workers/platforms/search_engine.py","line_range":"79-145","gmt_create":"2026-04-23T20:31:50.464823+08:00","gmt_modified":"2026-04-23T20:31:50.464823+08:00"},{"id":"3894c1ed9dca2ebf2359f40ebdb1959e","path":"backend/app/workers/platforms/search_engine.py","line_range":"147-174","gmt_create":"2026-04-23T20:31:50.465221+08:00","gmt_modified":"2026-04-23T20:31:50.465221+08:00"},{"id":"e27bcba24aaadeec1922d2b4e5b8386b","path":"backend/app/api/queries.py","line_range":"1-109","gmt_create":"2026-04-23T20:31:50.46721+08:00","gmt_modified":"2026-04-23T20:31:50.46721+08:00"},{"id":"5f893f5078aa8e549284feb057aa45da","path":"backend/app/workers/platforms/wenxin.py","line_range":"16-29","gmt_create":"2026-04-23T20:31:50.469467+08:00","gmt_modified":"2026-04-23T20:31:50.469467+08:00"},{"id":"e0b68d2d24760689a0f4f00dfee5f9f2","path":"backend/app/workers/platforms/search_engine.py","line_range":"28-76","gmt_create":"2026-04-23T20:31:50.470319+08:00","gmt_modified":"2026-04-23T20:31:50.470319+08:00"},{"id":"e9b98ae83632342d8e06cde39e9c9462","path":"backend/app/workers/platforms/search_engine.py","line_range":"105-137","gmt_create":"2026-04-23T20:31:50.470672+08:00","gmt_modified":"2026-04-23T20:31:50.470672+08:00"},{"id":"c86edb7a95fbe4b431ac65a0e2b8636e","path":"backend/app/api/queries.py","line_range":"90-109","gmt_create":"2026-04-23T20:31:50.471824+08:00","gmt_modified":"2026-04-23T20:31:50.471825+08:00"},{"id":"6e054d9a78c0c8c9da8dec4c4bda62ab","path":"backend/app/database.py","line_range":"6-28","gmt_create":"2026-04-23T20:33:29.972803+08:00","gmt_modified":"2026-04-23T20:33:29.972803+08:00"},{"id":"9c16a069e5154660bfdfa48f3518fc6a","path":"backend/app/models/query_task.py","line_range":"11-38","gmt_create":"2026-04-23T20:33:29.980385+08:00","gmt_modified":"2026-04-23T20:33:29.980385+08:00"},{"id":"a4918fcbd21492ad996d7f5496f03a4b","path":"backend/app/workers/platforms/kimi.py","line_range":"33-48","gmt_create":"2026-04-23T20:33:29.982795+08:00","gmt_modified":"2026-04-23T20:33:29.982795+08:00"},{"id":"bc38d046b4b1410ae2165cee2272839e","path":"backend/app/workers/platforms/wenxin.py","line_range":"33-48","gmt_create":"2026-04-23T20:33:29.983597+08:00","gmt_modified":"2026-04-23T20:33:29.983597+08:00"},{"id":"72f6d334026866e8a61d2ffb1d83370a","path":"backend/app/workers/citation_engine.py","line_range":"19-100","gmt_create":"2026-04-23T20:33:29.986927+08:00","gmt_modified":"2026-04-23T20:33:29.986928+08:00"},{"id":"1d84b9a7eb013882953a2d1d948299e4","path":"backend/app/workers/platforms/kimi.py","line_range":"126-197","gmt_create":"2026-04-23T20:33:29.990308+08:00","gmt_modified":"2026-04-23T20:33:29.990308+08:00"},{"id":"ba687f2c64aff92b3906658359ed953a","path":"backend/app/workers/platforms/wenxin.py","line_range":"124-195","gmt_create":"2026-04-23T20:33:29.991213+08:00","gmt_modified":"2026-04-23T20:33:29.991213+08:00"},{"id":"52ee729b02c992c689522c7956c14128","path":"backend/app/workers/scheduler.py","line_range":"57-62","gmt_create":"2026-04-23T20:33:29.992799+08:00","gmt_modified":"2026-04-23T20:33:29.992799+08:00"},{"id":"c9e32b7324cce60c8887deb8404ee759","path":"backend/app/workers/scheduler.py","line_range":"107-112","gmt_create":"2026-04-23T20:33:29.99333+08:00","gmt_modified":"2026-04-23T20:33:29.99333+08:00"},{"id":"8355d3821337334caee57a75dc8c8865","path":"backend/app/services/query.py","line_range":"116-130","gmt_create":"2026-04-23T20:33:29.994505+08:00","gmt_modified":"2026-04-23T20:33:29.994505+08:00"},{"id":"4fe27d4d1323b500e72d870aa6212a1a","path":"backend/app/workers/scheduler.py","line_range":"13-20","gmt_create":"2026-04-23T20:33:29.996199+08:00","gmt_modified":"2026-04-23T20:33:29.996199+08:00"},{"id":"3729543092bccad8926c5ea852db1e69","path":"backend/app/workers/citation_engine.py","line_range":"148-157","gmt_create":"2026-04-23T20:33:29.996517+08:00","gmt_modified":"2026-04-23T20:33:29.996517+08:00"},{"id":"1ee5153c867fc6e9d277a3067963a1fc","path":"backend/app/workers/scheduler.py","line_range":"32-38","gmt_create":"2026-04-23T20:33:29.997154+08:00","gmt_modified":"2026-04-23T20:33:29.997154+08:00"},{"id":"ed527c7a549ec333c2b30b59614343df","path":"backend/app/models/query.py","line_range":"50-54","gmt_create":"2026-04-23T20:33:29.997453+08:00","gmt_modified":"2026-04-23T20:33:29.997453+08:00"},{"id":"1a3351698ecc7cd4e508b7a792804fc4","path":"backend/app/workers/citation_engine.py","line_range":"302-309","gmt_create":"2026-04-23T20:33:29.999284+08:00","gmt_modified":"2026-04-23T20:33:29.999284+08:00"},{"id":"e3e9710c7eead933c936519395f792e0","path":"backend/app/workers/scheduler.py","line_range":"44-49","gmt_create":"2026-04-23T20:33:30.00043+08:00","gmt_modified":"2026-04-23T20:33:30.000431+08:00"},{"id":"a4143cc29b14f1f5bc75a5e021690666","path":"backend/app/workers/platforms/kimi.py","line_range":"23-31","gmt_create":"2026-04-23T20:33:30.001466+08:00","gmt_modified":"2026-04-23T20:33:30.001466+08:00"},{"id":"7192cfda5508e7587efd91d26cf1f018","path":"backend/app/workers/platforms/wenxin.py","line_range":"23-31","gmt_create":"2026-04-23T20:33:30.002099+08:00","gmt_modified":"2026-04-23T20:33:30.002099+08:00"},{"id":"38142b7d7016c5590e638fafcdcb1a19","path":"backend/app/workers/citation_engine.py","line_range":"211-227","gmt_create":"2026-04-23T20:33:30.002775+08:00","gmt_modified":"2026-04-23T20:33:30.002775+08:00"},{"id":"fb5276346dcc4e7044d8765a8572e7a8","path":"backend/app/config.py","line_range":"4-16","gmt_create":"2026-04-23T20:33:30.003374+08:00","gmt_modified":"2026-04-23T20:33:30.003377+08:00"},{"id":"482d573f97b482b99bcde1c399eceb73","path":"backend/app/api/queries.py","line_range":"90-108","gmt_create":"2026-04-23T20:33:37.21132+08:00","gmt_modified":"2026-04-23T20:33:37.21132+08:00"},{"id":"56f44cc97867cee3e5663424134d6072","path":"backend/app/workers/platforms/kimi.py","line_range":"1-37","gmt_create":"2026-04-23T20:33:37.212923+08:00","gmt_modified":"2026-04-23T20:33:37.212923+08:00"},{"id":"2e326ef8322619f1e8b3873022cb0437","path":"backend/app/workers/platforms/wenxin.py","line_range":"1-37","gmt_create":"2026-04-23T20:33:37.213348+08:00","gmt_modified":"2026-04-23T20:33:37.213348+08:00"},{"id":"4cac57dbc530f0335c913ec5725dfa4f","path":"backend/app/workers/scheduler.py","line_range":"1-121","gmt_create":"2026-04-23T20:33:37.215373+08:00","gmt_modified":"2026-04-23T20:33:37.215373+08:00"},{"id":"db174cfe219fc84d0dd26529f047b1d0","path":"backend/app/workers/citation_engine.py","line_range":"161-330","gmt_create":"2026-04-23T20:33:37.22028+08:00","gmt_modified":"2026-04-23T20:33:37.22028+08:00"},{"id":"f36452f78aabfb0c46da03bbe25dff06","path":"backend/app/services/citation.py","line_range":"219-295","gmt_create":"2026-04-23T20:33:37.223165+08:00","gmt_modified":"2026-04-23T20:33:37.223165+08:00"},{"id":"52c01d7b9c17aa16944cbfcf8885be61","path":"backend/app/workers/platforms/kimi.py","line_range":"16-33","gmt_create":"2026-04-23T20:33:37.227954+08:00","gmt_modified":"2026-04-23T20:33:37.227954+08:00"},{"id":"9d352899554ab41b65b2e9f32558d811","path":"backend/app/workers/citation_engine.py","line_range":"39-113","gmt_create":"2026-04-23T20:33:37.229053+08:00","gmt_modified":"2026-04-23T20:33:37.229053+08:00"},{"id":"b1ee5a992230844ba898765be63f7b27","path":"backend/app/workers/citation_engine.py","line_range":"32-133","gmt_create":"2026-04-23T20:33:37.229555+08:00","gmt_modified":"2026-04-23T20:33:37.229555+08:00"},{"id":"cb098a3cd32339e99f755dfd0fc35b5c","path":"tests/test_citation_engine.py","line_range":"6-127","gmt_create":"2026-04-23T20:33:37.230048+08:00","gmt_modified":"2026-04-23T20:33:37.230049+08:00"},{"id":"3d2dab79f7a3fedf24f0212cc9ef7aa1","path":"backend/app/workers/citation_engine.py","line_range":"145-158","gmt_create":"2026-04-23T20:33:37.230491+08:00","gmt_modified":"2026-04-23T20:33:37.230491+08:00"},{"id":"4e9b3d0e94282f4bc6fa500f4eed61a1","path":"backend/app/workers/citation_engine.py","line_range":"135-159","gmt_create":"2026-04-23T20:33:37.231003+08:00","gmt_modified":"2026-04-23T20:33:37.231003+08:00"},{"id":"8e3201561a9dd9a06ee3bf68ffdb3f99","path":"tests/test_citation_engine.py","line_range":"39-109","gmt_create":"2026-04-23T20:33:37.231501+08:00","gmt_modified":"2026-04-23T20:33:37.231501+08:00"},{"id":"c3a417be3d61f5bcd3fbf976e0c4f15a","path":"backend/app/workers/scheduler.py","line_range":"33-121","gmt_create":"2026-04-23T20:33:37.238099+08:00","gmt_modified":"2026-04-23T20:33:37.238099+08:00"},{"id":"7ce954ed7d3bc4dcf78630124cc0dd88","path":"backend/app/services/citation.py","line_range":"264-295","gmt_create":"2026-04-23T20:33:37.244499+08:00","gmt_modified":"2026-04-23T20:33:37.244499+08:00"},{"id":"7289a3568c137c8a671fc8c963bb8d28","path":"backend/requirements.txt","line_range":"1-35","gmt_create":"2026-04-23T20:33:37.24795+08:00","gmt_modified":"2026-04-23T20:33:37.24795+08:00"},{"id":"ef82ce4377c549013c200e19701a6805","path":"backend/app/workers/platforms/kimi.py","line_range":"21-32","gmt_create":"2026-04-23T20:33:37.254004+08:00","gmt_modified":"2026-04-23T20:33:37.254004+08:00"},{"id":"c7986eb1be0ffdd9ec4e243be4270119","path":"backend/app/workers/platforms/wenxin.py","line_range":"21-32","gmt_create":"2026-04-23T20:33:37.254558+08:00","gmt_modified":"2026-04-23T20:33:37.254558+08:00"},{"id":"5563b3bd56550648dc70302c1762ce5a","path":"backend/app/workers/platforms/tongyi.py","line_range":"18-29","gmt_create":"2026-04-23T20:33:37.255643+08:00","gmt_modified":"2026-04-23T20:33:37.255643+08:00"},{"id":"91852ef8dcc844a2f85e9fce0227ab74","path":"backend/app/workers/platforms/doubao.py","line_range":"18-29","gmt_create":"2026-04-23T20:33:37.25603+08:00","gmt_modified":"2026-04-23T20:33:37.25603+08:00"},{"id":"1b46fab9e22f53db30ead5677d03e3e2","path":"backend/app/workers/citation_engine.py","line_range":"11-16","gmt_create":"2026-04-23T20:33:37.256413+08:00","gmt_modified":"2026-04-23T20:33:37.256413+08:00"},{"id":"4a2fa09aa3a948dec5ef8ba873b0e716","path":"backend/app/services/citation.py","line_range":"14-42","gmt_create":"2026-04-23T20:33:37.257057+08:00","gmt_modified":"2026-04-23T20:33:37.257057+08:00"},{"id":"e7afbab5932c93c3469f1a225e6c7156","path":"backend/app/api/citations.py","line_range":"1-55","gmt_create":"2026-04-23T20:33:57.479092+08:00","gmt_modified":"2026-04-23T20:33:57.479092+08:00"},{"id":"a0eac56d622a2fff529bc2b796064bcd","path":"backend/app/schemas/query.py","line_range":"1-94","gmt_create":"2026-04-23T20:33:57.479659+08:00","gmt_modified":"2026-04-23T20:33:57.479659+08:00"},{"id":"174be58163b6f72b4cd4a493f3463ce4","path":"backend/app/schemas/citation.py","line_range":"1-52","gmt_create":"2026-04-23T20:33:57.480222+08:00","gmt_modified":"2026-04-23T20:33:57.480222+08:00"},{"id":"136f172c732d0cc130532a4f0df475a4","path":"backend/app/models/user.py","line_range":"1-41","gmt_create":"2026-04-23T20:33:57.481714+08:00","gmt_modified":"2026-04-23T20:33:57.481714+08:00"},{"id":"916551131bd9ac8c9f9c8bb762af1fa4","path":"backend/app/services/query.py","line_range":"1-130","gmt_create":"2026-04-23T20:33:57.482172+08:00","gmt_modified":"2026-04-23T20:33:57.482172+08:00"},{"id":"5d2836286eb7d4eb6039b004a9744d26","path":"backend/app/services/citation.py","line_range":"1-429","gmt_create":"2026-04-23T20:33:57.482643+08:00","gmt_modified":"2026-04-23T20:33:57.482643+08:00"},{"id":"39a3b2d9301fa4eff7bef0fda3352790","path":"backend/app/workers/platforms/kimi.py","line_range":"1-206","gmt_create":"2026-04-23T20:33:57.484464+08:00","gmt_modified":"2026-04-23T20:33:57.484464+08:00"},{"id":"fbcfae3b1238b3da5329ebafe4294861","path":"backend/app/workers/platforms/wenxin.py","line_range":"1-205","gmt_create":"2026-04-23T20:33:57.484977+08:00","gmt_modified":"2026-04-23T20:33:57.484977+08:00"},{"id":"c4273407c88f470df7daf6a8ad5ce969","path":"backend/app/api/queries.py","line_range":"15-109","gmt_create":"2026-04-23T20:33:57.485748+08:00","gmt_modified":"2026-04-23T20:33:57.485748+08:00"},{"id":"35774e0a09ac5459c868914d7182ca95","path":"backend/app/api/citations.py","line_range":"19-55","gmt_create":"2026-04-23T20:33:57.486195+08:00","gmt_modified":"2026-04-23T20:33:57.486195+08:00"},{"id":"f639b566c26dfd18b24e3dfd2e9853ac","path":"backend/app/schemas/citation.py","line_range":"7-52","gmt_create":"2026-04-23T20:33:57.486916+08:00","gmt_modified":"2026-04-23T20:33:57.486916+08:00"},{"id":"b46654006178160f12897e2c5baac8fa","path":"backend/app/services/citation.py","line_range":"219-429","gmt_create":"2026-04-23T20:33:57.488934+08:00","gmt_modified":"2026-04-23T20:33:57.488934+08:00"},{"id":"82265d393c20d0af96beec6b9c657c27","path":"backend/app/api/queries.py","line_range":"28-41","gmt_create":"2026-04-23T20:33:57.49175+08:00","gmt_modified":"2026-04-23T20:33:57.49175+08:00"},{"id":"93e5c95b1691bb81a36bf9a0ac889030","path":"backend/app/services/citation.py","line_range":"219-261","gmt_create":"2026-04-23T20:33:57.493276+08:00","gmt_modified":"2026-04-23T20:33:57.493276+08:00"},{"id":"374200f0bf946f0399351756977d0495","path":"backend/app/workers/citation_engine.py","line_range":"176-234","gmt_create":"2026-04-23T20:33:57.498134+08:00","gmt_modified":"2026-04-23T20:33:57.498134+08:00"},{"id":"9a8d9100a6bc34ebae9ee065def7e88a","path":"backend/app/schemas/query.py","line_range":"44-72","gmt_create":"2026-04-23T20:33:57.500036+08:00","gmt_modified":"2026-04-23T20:33:57.500036+08:00"},{"id":"93c23bcc3456826af17e26a6d4c32116","path":"backend/app/schemas/query.py","line_range":"6-9","gmt_create":"2026-04-23T20:33:57.500633+08:00","gmt_modified":"2026-04-23T20:33:57.500633+08:00"},{"id":"c17eeb8726297096cd5542283f11494f","path":"backend/app/api/queries.py","line_range":"17-109","gmt_create":"2026-04-23T20:33:57.5019+08:00","gmt_modified":"2026-04-23T20:33:57.5019+08:00"},{"id":"08fec4718be6991260c00ca532f9173a","path":"backend/app/api/citations.py","line_range":"22-55","gmt_create":"2026-04-23T20:33:57.502347+08:00","gmt_modified":"2026-04-23T20:33:57.502347+08:00"},{"id":"08007199eea846dd14f15f7dc70419e2","path":"backend/app/schemas/citation.py","line_range":"48-52","gmt_create":"2026-04-23T20:33:57.50265+08:00","gmt_modified":"2026-04-23T20:33:57.50265+08:00"},{"id":"4caff756fd4da029bd64cd16e7ef5960","path":"backend/app/api/queries.py","line_range":"32-39","gmt_create":"2026-04-23T20:33:57.50293+08:00","gmt_modified":"2026-04-23T20:33:57.50293+08:00"},{"id":"b0220895f66f1273966ad5b2c3266952","path":"backend/app/api/queries.py","line_range":"49-53","gmt_create":"2026-04-23T20:33:57.503622+08:00","gmt_modified":"2026-04-23T20:33:57.503622+08:00"},{"id":"44f88f9664fdf6e84ffb7e0675a86a28","path":"backend/app/api/queries.py","line_range":"64-69","gmt_create":"2026-04-23T20:33:57.504188+08:00","gmt_modified":"2026-04-23T20:33:57.504188+08:00"},{"id":"91f280f51389bd1cf711dcf33a4da681","path":"backend/app/api/queries.py","line_range":"79-84","gmt_create":"2026-04-23T20:33:57.504712+08:00","gmt_modified":"2026-04-23T20:33:57.504712+08:00"},{"id":"ab50466a57c77659d7b469d3a8a04ddb","path":"backend/app/api/queries.py","line_range":"96-103","gmt_create":"2026-04-23T20:33:57.505025+08:00","gmt_modified":"2026-04-23T20:33:57.505025+08:00"},{"id":"572c2dece1fbc13aa2bb7d6b61b0fd5c","path":"backend/app/api/citations.py","line_range":"65-71","gmt_create":"2026-04-23T20:33:57.505311+08:00","gmt_modified":"2026-04-23T20:33:57.505311+08:00"},{"id":"82386bc7ca57d9ccc94b656e52bc89f6","path":"backend/app/api/queries.py","line_range":"1-14","gmt_create":"2026-04-23T20:33:57.506573+08:00","gmt_modified":"2026-04-23T20:33:57.506573+08:00"},{"id":"7ab79ab21d7d6e4dbcb224572516f6f6","path":"backend/app/api/citations.py","line_range":"1-19","gmt_create":"2026-04-23T20:33:57.507421+08:00","gmt_modified":"2026-04-23T20:33:57.507422+08:00"},{"id":"8433204d7a82a1f480e57df9ceee5581","path":"backend/app/services/query.py","line_range":"1-10","gmt_create":"2026-04-23T20:33:57.507906+08:00","gmt_modified":"2026-04-23T20:33:57.507906+08:00"},{"id":"3957ee6f15a01b7b541490438ef18684","path":"backend/app/services/citation.py","line_range":"1-17","gmt_create":"2026-04-23T20:33:57.508376+08:00","gmt_modified":"2026-04-23T20:33:57.508376+08:00"},{"id":"fcae8d1d281ad7186999cc4ca8e43db7","path":"backend/app/workers/scheduler.py","line_range":"25-39","gmt_create":"2026-04-23T20:33:57.509666+08:00","gmt_modified":"2026-04-23T20:33:57.509666+08:00"},{"id":"ee12a84ac6334b13e20132181454488b","path":"backend/app/workers/scheduler.py","line_range":"13-19","gmt_create":"2026-04-23T20:33:57.510112+08:00","gmt_modified":"2026-04-23T20:33:57.510112+08:00"},{"id":"897e047b94772e5a0ff57cf773a7f965","path":"backend/app/workers/platforms/kimi.py","line_range":"17-32","gmt_create":"2026-04-23T20:33:57.510534+08:00","gmt_modified":"2026-04-23T20:33:57.510534+08:00"},{"id":"53e8ec81b4d2dbb13c831048e5897036","path":"backend/app/workers/platforms/wenxin.py","line_range":"17-32","gmt_create":"2026-04-23T20:33:57.510845+08:00","gmt_modified":"2026-04-23T20:33:57.510845+08:00"},{"id":"fd3145047b9c813cc8e64b9322e531f9","path":"backend/app/services/citation.py","line_range":"219-327","gmt_create":"2026-04-23T20:33:57.516693+08:00","gmt_modified":"2026-04-23T20:33:57.516693+08:00"},{"id":"b09a0f415030d91b25e6cabd8a0a93fc","path":"backend/app/models/query_task.py","line_range":"176-289","gmt_create":"2026-04-23T20:33:57.51758+08:00","gmt_modified":"2026-04-23T20:33:57.51758+08:00"},{"id":"e2168959b26c386940370b5f1bf48d7d","path":"backend/app/models/citation_record.py","line_range":"194-204","gmt_create":"2026-04-23T20:33:57.517939+08:00","gmt_modified":"2026-04-23T20:33:57.517939+08:00"},{"id":"129573d2bbcde48697ed0e75dea12396","path":"backend/app/workers/scheduler.py","line_range":"25-40","gmt_create":"2026-04-23T20:35:18.586153+08:00","gmt_modified":"2026-04-23T20:35:18.586153+08:00"},{"id":"cf18c97a9be6c78aa43cc229ed3dad20","path":"backend/app/workers/citation_engine.py","line_range":"164-173","gmt_create":"2026-04-23T20:35:18.586656+08:00","gmt_modified":"2026-04-23T20:35:18.586656+08:00"},{"id":"3c7ca5d582dca31c2530b1ce9c058e95","path":"backend/app/workers/platforms/kimi.py","line_range":"10-37","gmt_create":"2026-04-23T20:35:18.587239+08:00","gmt_modified":"2026-04-23T20:35:18.587239+08:00"},{"id":"27047f868643e5457d4f242b4298a9f6","path":"frontend/lib/platforms.ts","line_range":"1-23","gmt_create":"2026-04-23T20:35:18.590782+08:00","gmt_modified":"2026-04-23T20:35:18.590782+08:00"},{"id":"1526e4e02133a48eac04befb74ec5bd1","path":"backend/app/workers/citation_engine.py","line_range":"161-173","gmt_create":"2026-04-23T20:35:18.592183+08:00","gmt_modified":"2026-04-23T20:35:18.592183+08:00"},{"id":"98c02d9bb7aa6e2b6be5f7381e64fd99","path":"backend/app/api/queries.py","line_range":"26-39","gmt_create":"2026-04-23T20:35:18.594026+08:00","gmt_modified":"2026-04-23T20:35:18.594026+08:00"},{"id":"2a971cb83924013902324eceeab22559","path":"backend/app/workers/platforms/kimi.py","line_range":"16-29","gmt_create":"2026-04-23T20:35:18.596805+08:00","gmt_modified":"2026-04-23T20:35:18.596805+08:00"},{"id":"99326fedad9275392719105b5b6782d6","path":"backend/app/workers/platforms/kimi.py","line_range":"31-33","gmt_create":"2026-04-23T20:35:18.597389+08:00","gmt_modified":"2026-04-23T20:35:18.597389+08:00"},{"id":"5e5dacc623918c0f1eba234154c99291","path":"backend/app/workers/platforms/search_engine.py","line_range":"16-76","gmt_create":"2026-04-23T20:35:18.598978+08:00","gmt_modified":"2026-04-23T20:35:18.598978+08:00"},{"id":"5be7e6cf82d6359efddaf131aaf92615","path":"backend/app/workers/citation_engine.py","line_range":"323-330","gmt_create":"2026-04-23T20:35:18.604342+08:00","gmt_modified":"2026-04-23T20:35:18.604342+08:00"},{"id":"129b746e71a9013ceb1b0fcc59942b39","path":"backend/app/workers/scheduler.py","line_range":"86-90","gmt_create":"2026-04-23T20:35:18.611167+08:00","gmt_modified":"2026-04-23T20:35:18.611167+08:00"},{"id":"d780e807ee751f39f331a658b47c4ed3","path":"backend/app/services/citation.py","line_range":"24-269","gmt_create":"2026-04-23T20:35:18.619146+08:00","gmt_modified":"2026-04-23T20:35:18.619146+08:00"},{"id":"8eea43550951387ac740b5e3e64c7691","path":"backend/app/workers/platforms/search_engine.py","line_range":"94-96","gmt_create":"2026-04-23T20:35:18.629044+08:00","gmt_modified":"2026-04-23T20:35:18.629044+08:00"},{"id":"37769b7e6b5588be0065681dedf514ed","path":"backend/app/workers/platforms/search_engine.py","line_range":"140-144","gmt_create":"2026-04-23T20:35:18.631486+08:00","gmt_modified":"2026-04-23T20:35:18.631486+08:00"},{"id":"518d184988b97ebc7ef0c0bf5c10f42c","path":"backend/app/workers/platforms/kimi.py","line_range":"24-29","gmt_create":"2026-04-23T20:35:18.631835+08:00","gmt_modified":"2026-04-23T20:35:18.631835+08:00"},{"id":"818504ee2e17d2f9cc8fe115ca321138","path":"backend/app/api/queries.py","line_range":"34-38","gmt_create":"2026-04-23T20:35:18.632132+08:00","gmt_modified":"2026-04-23T20:35:18.632132+08:00"},{"id":"8a1a0ffd82ac6ff54d3410e4ce59a6b8","path":"backend/app/api/citations.py","line_range":"25-56","gmt_create":"2026-04-23T20:35:18.633686+08:00","gmt_modified":"2026-04-23T20:35:18.633686+08:00"},{"id":"d4f99d3dd9fe489c354edf5fe2f8803d","path":"backend/app/models/citation_record.py","line_range":"1-44","gmt_create":"2026-04-23T20:35:45.581649+08:00","gmt_modified":"2026-04-23T20:35:45.58165+08:00"},{"id":"86e37040be1aeb400fab9b529f5404c8","path":"backend/app/models/subscription.py","line_range":"1-37","gmt_create":"2026-04-23T20:35:45.583254+08:00","gmt_modified":"2026-04-23T20:35:45.583254+08:00"},{"id":"211463f5b49610f09594c40c0a235943","path":"backend/alembic/env.py","line_range":"1-89","gmt_create":"2026-04-23T20:35:45.584058+08:00","gmt_modified":"2026-04-23T20:35:45.584058+08:00"},{"id":"48d22eaee09e364a293ad6c4750f5c5a","path":"docker-compose.yml","line_range":"1-71","gmt_create":"2026-04-23T20:35:45.587653+08:00","gmt_modified":"2026-04-23T20:35:45.587653+08:00"},{"id":"98cc82f62b83678f06a33cf9231ecdf8","path":"backend/alembic/versions/488d0bd5ab01_initial_migration.py","line_range":"1-128","gmt_create":"2026-04-23T20:35:45.597037+08:00","gmt_modified":"2026-04-23T20:35:45.597037+08:00"},{"id":"e1aabd52989e47806fb997157381e1cf","path":"backend/alembic/versions/b2c4d6e8fa10_add_confidence_match_type_to_citation_records.py","line_range":"1-37","gmt_create":"2026-04-23T20:35:45.597747+08:00","gmt_modified":"2026-04-23T20:35:45.597747+08:00"},{"id":"ac77e4875817616194b7b5997d4fb1ae","path":"backend/alembic/versions/488d0bd5ab01_initial_migration.py","line_range":"57-94","gmt_create":"2026-04-23T20:35:45.611901+08:00","gmt_modified":"2026-04-23T20:35:45.611901+08:00"},{"id":"0e57efd98dacc85da21f995980371ee4","path":"backend/alembic/versions/b2c4d6e8fa10_add_confidence_match_type_to_citation_records.py","line_range":"21-37","gmt_create":"2026-04-23T20:35:45.61338+08:00","gmt_modified":"2026-04-23T20:35:45.61338+08:00"},{"id":"717eb27184726e4f78d694984d29420c","path":"backend/app/models/citation_record.py","line_range":"37-44","gmt_create":"2026-04-23T20:35:45.615494+08:00","gmt_modified":"2026-04-23T20:35:45.615495+08:00"},{"id":"bfdf3479f244dc6794628d9df10ab6d0","path":"backend/app/models/query.py","line_range":"11-48","gmt_create":"2026-04-23T20:35:45.618458+08:00","gmt_modified":"2026-04-23T20:35:45.618458+08:00"},{"id":"f5f9f0d96263ae84631c7a8d7e9b3648","path":"backend/app/models/citation_record.py","line_range":"11-44","gmt_create":"2026-04-23T20:35:45.61929+08:00","gmt_modified":"2026-04-23T20:35:45.619291+08:00"},{"id":"818d1354dc0665798f3d91a2ca5153d6","path":"backend/app/models/query_task.py","line_range":"11-34","gmt_create":"2026-04-23T20:35:45.620036+08:00","gmt_modified":"2026-04-23T20:35:45.620036+08:00"},{"id":"24aade4c34609a8ab28e4643a3692201","path":"backend/app/models/subscription.py","line_range":"11-36","gmt_create":"2026-04-23T20:35:45.62075+08:00","gmt_modified":"2026-04-23T20:35:45.62075+08:00"},{"id":"d34337b9ff77246979252d2fd8fb8018","path":"backend/alembic/env.py","line_range":"33-88","gmt_create":"2026-04-23T20:35:45.628352+08:00","gmt_modified":"2026-04-23T20:35:45.628353+08:00"},{"id":"eb63042f04a22f9a67bd498df1684d20","path":"backend/alembic/versions/488d0bd5ab01_initial_migration.py","line_range":"36-111","gmt_create":"2026-04-23T20:35:45.634829+08:00","gmt_modified":"2026-04-23T20:35:45.634829+08:00"},{"id":"c651c7ad6747a92ee96eabb2eb82afdd","path":"backend/app/database.py","line_range":"12-18","gmt_create":"2026-04-23T20:35:45.637195+08:00","gmt_modified":"2026-04-23T20:35:45.637195+08:00"},{"id":"dd01eee487298a28e950f6345196f1d4","path":"backend/app/services/citation.py","line_range":"30-79","gmt_create":"2026-04-23T20:35:45.637815+08:00","gmt_modified":"2026-04-23T20:35:45.637815+08:00"},{"id":"7dae7237f11c5100bf7889c105193cf6","path":"backend/app/services/query.py","line_range":"12-32","gmt_create":"2026-04-23T20:35:45.638422+08:00","gmt_modified":"2026-04-23T20:35:45.638422+08:00"},{"id":"cc64cf609f5ff218f618e0664ffa7cc7","path":"backend/app/services/citation.py","line_range":"298-308","gmt_create":"2026-04-23T20:35:45.641905+08:00","gmt_modified":"2026-04-23T20:35:45.641905+08:00"},{"id":"ce7e334595a4ce912e0d116314db9a35","path":"backend/app/services/citation.py","line_range":"342-429","gmt_create":"2026-04-23T20:35:45.6442+08:00","gmt_modified":"2026-04-23T20:35:45.6442+08:00"},{"id":"2f46f212597e3c245b9e5dcc5dbc863d","path":"backend/app/schemas/citation.py","line_range":"7-18","gmt_create":"2026-04-23T20:35:45.64501+08:00","gmt_modified":"2026-04-23T20:35:45.64501+08:00"},{"id":"dc40f1dd3e59ee7f046019201068bea1","path":"backend/app/services/citation.py","line_range":"14-22","gmt_create":"2026-04-23T20:35:45.659571+08:00","gmt_modified":"2026-04-23T20:35:45.659571+08:00"},{"id":"01a0c4b40819965823b56e9da858c024","path":"frontend/Dockerfile","line_range":"1-15","gmt_create":"2026-04-23T21:00:59.634151+08:00","gmt_modified":"2026-04-23T21:00:59.634151+08:00"},{"id":"13f6ca76349ef86ae756bb519f122bc5","path":"backend/alembic.ini","line_range":"1-150","gmt_create":"2026-04-23T21:00:59.636129+08:00","gmt_modified":"2026-04-23T21:00:59.636129+08:00"},{"id":"74abd6612105c29b67178fa9dbd04b61","path":"frontend/tsconfig.json","line_range":"1-27","gmt_create":"2026-04-23T21:00:59.639808+08:00","gmt_modified":"2026-04-23T21:00:59.639808+08:00"},{"id":"5bdaabf085a7c3eb6e87c5ad7479e25d","path":"frontend/.eslintrc.json","line_range":"1-4","gmt_create":"2026-04-23T21:00:59.640082+08:00","gmt_modified":"2026-04-23T21:00:59.640082+08:00"},{"id":"9482f4f6279a4f636b77e69b8273b996","path":"backend/alembic.ini","line_range":"86-114","gmt_create":"2026-04-23T21:00:59.64068+08:00","gmt_modified":"2026-04-23T21:00:59.64068+08:00"},{"id":"397b266f19a1addebdf6c32db71ae77f","path":"tests/conftest.py","line_range":"1-71","gmt_create":"2026-04-23T21:00:59.640958+08:00","gmt_modified":"2026-04-23T21:00:59.640958+08:00"},{"id":"eb603ec2611957de67af00756f4b1efa","path":"backend/app/config.py","line_range":"7-13","gmt_create":"2026-04-23T21:00:59.64236+08:00","gmt_modified":"2026-04-23T21:00:59.64236+08:00"},{"id":"c25b39830f3b7734da975acc7f214666","path":"backend/Dockerfile","line_range":"31-33","gmt_create":"2026-04-23T21:00:59.642682+08:00","gmt_modified":"2026-04-23T21:00:59.642682+08:00"},{"id":"4c9d362ecce8e796e6f14850def049b0","path":"docker-compose.yml","line_range":"4-20","gmt_create":"2026-04-23T21:00:59.642976+08:00","gmt_modified":"2026-04-23T21:00:59.642976+08:00"},{"id":"d5827be2cfbe41c8177660ae877e93a4","path":"docker-compose.yml","line_range":"22-34","gmt_create":"2026-04-23T21:00:59.643262+08:00","gmt_modified":"2026-04-23T21:00:59.643262+08:00"},{"id":"03a65cdcfc173217d12ad8a417f8f033","path":"backend/app/main.py","line_range":"13-21","gmt_create":"2026-04-23T21:00:59.643535+08:00","gmt_modified":"2026-04-23T21:00:59.643535+08:00"},{"id":"3365fa8db33d43bab1d0a614e8af3a70","path":"backend/app/main.py","line_range":"45-47","gmt_create":"2026-04-23T21:00:59.644124+08:00","gmt_modified":"2026-04-23T21:00:59.644124+08:00"},{"id":"6f637c2b0796ec533aafb3b865c11cf0","path":"backend/app/schemas/auth.py","line_range":"1-34","gmt_create":"2026-04-23T21:00:59.646408+08:00","gmt_modified":"2026-04-23T21:00:59.646408+08:00"},{"id":"a698e13bfada239280fc9354ff9e2331","path":"backend/app/config.py","line_range":"7-8","gmt_create":"2026-04-23T21:00:59.64811+08:00","gmt_modified":"2026-04-23T21:00:59.64811+08:00"},{"id":"37bbab6e4f16db7eac6eee9d05e80e46","path":"README.md","line_range":"1-3","gmt_create":"2026-04-23T21:00:59.649625+08:00","gmt_modified":"2026-04-23T21:00:59.649625+08:00"},{"id":"63ecbf5e72a0354028b84eb531a58977","path":"frontend/package.json","line_range":"11-38","gmt_create":"2026-04-23T21:00:59.650192+08:00","gmt_modified":"2026-04-23T21:00:59.650193+08:00"},{"id":"bf363deac5ef38c8dc80c73b862e730b","path":"docker-compose.yml","line_range":"4-34","gmt_create":"2026-04-23T21:00:59.651828+08:00","gmt_modified":"2026-04-23T21:00:59.651828+08:00"},{"id":"c6e94075e5f689bfa2fe16f8cf965203","path":"tests/conftest.py","line_range":"19-50","gmt_create":"2026-04-23T21:00:59.65241+08:00","gmt_modified":"2026-04-23T21:00:59.65241+08:00"},{"id":"1a78f5574add6d07a1d7c947dba3f23d","path":"backend/alembic.ini","line_range":"115-150","gmt_create":"2026-04-23T21:00:59.652679+08:00","gmt_modified":"2026-04-23T21:00:59.652679+08:00"},{"id":"f6810849c947471a4b45d7ca01ec8c5f","path":"frontend/tailwind.config.ts","line_range":"5-9","gmt_create":"2026-04-23T21:00:59.653659+08:00","gmt_modified":"2026-04-23T21:00:59.653659+08:00"},{"id":"9f6d9941f3b93e29d714bfec7e83434c","path":"backend/app/main.py","line_range":"30-36","gmt_create":"2026-04-23T21:00:59.653983+08:00","gmt_modified":"2026-04-23T21:00:59.653984+08:00"},{"id":"669d67125dcddb0756f4ff50a43512c6","path":"backend/app/config.py","line_range":"9-13","gmt_create":"2026-04-23T21:00:59.654266+08:00","gmt_modified":"2026-04-23T21:00:59.654266+08:00"},{"id":"85792f0b1e34b5b48b0300aa606ed6e6","path":"backend/app/main.py","line_range":"1-56","gmt_create":"2026-04-23T21:02:44.159246+08:00","gmt_modified":"2026-04-23T21:02:44.159246+08:00"},{"id":"f240c1067c223a019ba05b0fbd718aa4","path":"backend/app/main.py","line_range":"1-84","gmt_create":"2026-04-24T10:58:35.335284+08:00","gmt_modified":"2026-04-24T10:58:35.335284+08:00"},{"id":"a9fb75d1fdb833a11b36bc7b298f19be","path":"frontend/lib/api.ts","line_range":"1-154","gmt_create":"2026-04-24T10:58:35.349742+08:00","gmt_modified":"2026-04-24T10:58:35.349742+08:00"},{"id":"40325db1cb621a9af027150a8c5cf8e9","path":"frontend/lib/auth.ts","line_range":"1-73","gmt_create":"2026-04-24T10:58:35.350062+08:00","gmt_modified":"2026-04-24T10:58:35.350062+08:00"},{"id":"93d8c6a312849c344b6a9713b671840f","path":"backend/requirements.txt","line_range":"1-39","gmt_create":"2026-04-24T10:58:35.35098+08:00","gmt_modified":"2026-04-24T10:58:35.35098+08:00"},{"id":"844b21a35ae39ead76ff8831eb974e5a","path":"backend/app/main.py","line_range":"81-84","gmt_create":"2026-04-24T10:58:35.352287+08:00","gmt_modified":"2026-04-24T10:58:35.352287+08:00"},{"id":"3af33bd686ce3d418e31843cac66f58b","path":"backend/README.md","line_range":"12-67","gmt_create":"2026-04-24T10:58:35.35614+08:00","gmt_modified":"2026-04-24T10:58:35.356141+08:00"},{"id":"06c6dfcd66159d42fa9b9eafd1e36a04","path":"frontend/README.md","line_range":"11-34","gmt_create":"2026-04-24T10:58:35.35673+08:00","gmt_modified":"2026-04-24T10:58:35.35673+08:00"},{"id":"903da86dc3fb26783f45f247d60e9534","path":"backend/README.md","line_range":"69-126","gmt_create":"2026-04-24T10:58:35.357072+08:00","gmt_modified":"2026-04-24T10:58:35.357072+08:00"},{"id":"0ffe337a73c8fb7254f3e48932a8ae7f","path":"backend/README.md","line_range":"209-234","gmt_create":"2026-04-24T10:58:35.357641+08:00","gmt_modified":"2026-04-24T10:58:35.357642+08:00"},{"id":"55369db351eb916a3210b22f3d672162","path":"frontend/README.md","line_range":"161-170","gmt_create":"2026-04-24T10:58:35.358984+08:00","gmt_modified":"2026-04-24T10:58:35.358984+08:00"},{"id":"6c080aba7d0e611bd4e7f268835b630f","path":"backend/app/middleware/logging_middleware.py","line_range":"1-24","gmt_create":"2026-04-24T10:58:51.060864+08:00","gmt_modified":"2026-04-24T10:58:51.060864+08:00"},{"id":"a7bba55ddc4dd5d215e881e8432d83ea","path":"backend/app/middleware/rate_limit.py","line_range":"1-83","gmt_create":"2026-04-24T10:58:51.061198+08:00","gmt_modified":"2026-04-24T10:58:51.061198+08:00"},{"id":"7c7425c51cc43b8840cefd9764b47204","path":"backend/app/api/admin.py","line_range":"1-108","gmt_create":"2026-04-24T10:58:51.061492+08:00","gmt_modified":"2026-04-24T10:58:51.061492+08:00"},{"id":"6e4a52820e780e4b42651a8214ad4493","path":"backend/app/api/reports.py","line_range":"1-75","gmt_create":"2026-04-24T10:58:51.061762+08:00","gmt_modified":"2026-04-24T10:58:51.061763+08:00"},{"id":"4247da3fc00a7e5f8b73775321eccf8e","path":"backend/app/api/subscriptions.py","line_range":"1-77","gmt_create":"2026-04-24T10:58:51.062039+08:00","gmt_modified":"2026-04-24T10:58:51.062039+08:00"},{"id":"9bdd2f6103cf3cc8b3914b9d6d8812fb","path":"backend/app/services/admin.py","line_range":"1-188","gmt_create":"2026-04-24T10:58:51.062452+08:00","gmt_modified":"2026-04-24T10:58:51.062452+08:00"},{"id":"557281ca025f76d0dc2db67e56b44053","path":"backend/app/services/subscription.py","line_range":"1-155","gmt_create":"2026-04-24T10:58:51.062795+08:00","gmt_modified":"2026-04-24T10:58:51.062795+08:00"},{"id":"e2d4838e58acc0eee236ef586abab64e","path":"backend/app/main.py","line_range":"13-48","gmt_create":"2026-04-24T10:58:51.064016+08:00","gmt_modified":"2026-04-24T10:58:51.064016+08:00"},{"id":"8aee7654d1f435ab53d8ddaabd269fed","path":"backend/app/database.py","line_range":"6-29","gmt_create":"2026-04-24T10:58:51.06434+08:00","gmt_modified":"2026-04-24T10:58:51.06434+08:00"},{"id":"acd9e6c32084e589d5aeb1665d918dfd","path":"backend/app/api/deps.py","line_range":"13-43","gmt_create":"2026-04-24T10:58:51.064666+08:00","gmt_modified":"2026-04-24T10:58:51.064667+08:00"},{"id":"33ec8bca51cb9f667bf91088dd6b6a70","path":"backend/app/main.py","line_range":"24-48","gmt_create":"2026-04-24T10:58:51.065096+08:00","gmt_modified":"2026-04-24T10:58:51.065096+08:00"},{"id":"712424bd3bd3d5f39b1a0a72acc9952a","path":"backend/app/middleware/rate_limit.py","line_range":"10-83","gmt_create":"2026-04-24T10:58:51.065564+08:00","gmt_modified":"2026-04-24T10:58:51.065564+08:00"},{"id":"9357a0fcca02068d428f4a191d08fdcd","path":"backend/app/middleware/logging_middleware.py","line_range":"8-24","gmt_create":"2026-04-24T10:58:51.065888+08:00","gmt_modified":"2026-04-24T10:58:51.065888+08:00"},{"id":"8efcce12915471fe5b88fe058bcf238e","path":"backend/app/services/auth.py","line_range":"16-69","gmt_create":"2026-04-24T10:58:51.06648+08:00","gmt_modified":"2026-04-24T10:58:51.06648+08:00"},{"id":"7f81ebbdde3496054e6f43f5eef366dc","path":"backend/app/services/admin.py","line_range":"14-188","gmt_create":"2026-04-24T10:58:51.06683+08:00","gmt_modified":"2026-04-24T10:58:51.06683+08:00"},{"id":"f4d57f9a78585969a006b7451ea8ce84","path":"backend/app/services/subscription.py","line_range":"69-155","gmt_create":"2026-04-24T10:58:51.06716+08:00","gmt_modified":"2026-04-24T10:58:51.06716+08:00"},{"id":"608c00e1835ad72363ef08796961faca","path":"backend/app/config.py","line_range":"4-17","gmt_create":"2026-04-24T10:58:51.068971+08:00","gmt_modified":"2026-04-24T10:58:51.068971+08:00"},{"id":"ec4bf600a513dc2b014c85e141d7582d","path":"backend/app/workers/scheduler.py","line_range":"51-85","gmt_create":"2026-04-24T10:58:51.0746+08:00","gmt_modified":"2026-04-24T10:58:51.0746+08:00"},{"id":"9606b8243736b4a6f5ecfe152b2ab6dd","path":"backend/app/middleware/rate_limit.py","line_range":"34-83","gmt_create":"2026-04-24T10:58:51.079072+08:00","gmt_modified":"2026-04-24T10:58:51.079072+08:00"},{"id":"05664cbd35007caa5290760cc1ef1b99","path":"backend/app/api/admin.py","line_range":"29-108","gmt_create":"2026-04-24T10:58:51.079983+08:00","gmt_modified":"2026-04-24T10:58:51.079983+08:00"},{"id":"3d85cad939ce858f9c6d153d425c19fb","path":"backend/app/services/subscription.py","line_range":"25-155","gmt_create":"2026-04-24T10:58:51.081143+08:00","gmt_modified":"2026-04-24T10:58:51.081143+08:00"},{"id":"36769bd305cd5f664fa6e28f82e4b3e7","path":"backend/app/schemas/subscription.py","line_range":"1-41","gmt_create":"2026-04-24T10:58:51.08184+08:00","gmt_modified":"2026-04-24T10:58:51.08184+08:00"},{"id":"14c2d098319eeab16c64ff7d1447df6b","path":"backend/app/api/reports.py","line_range":"18-75","gmt_create":"2026-04-24T10:58:51.082903+08:00","gmt_modified":"2026-04-24T10:58:51.082904+08:00"},{"id":"1f8d26b6a5da49d89d95bb13c7ace2c6","path":"backend/app/models/user.py","line_range":"1-48","gmt_create":"2026-04-24T10:59:38.896976+08:00","gmt_modified":"2026-04-24T10:59:38.896976+08:00"},{"id":"c8f2dbcb7475bd189a34c7061ea46c6d","path":"backend/alembic/versions/c3d5e7f9ab12_add_user_management_fields.py","line_range":"1-41","gmt_create":"2026-04-24T10:59:38.901742+08:00","gmt_modified":"2026-04-24T10:59:38.901742+08:00"},{"id":"08c1475254a5bc8877ff29a895de3b6a","path":"backend/app/services/auth.py","line_range":"1-175","gmt_create":"2026-04-24T10:59:38.902658+08:00","gmt_modified":"2026-04-24T10:59:38.902658+08:00"},{"id":"f5978358d04c3c917d9ca5044c7f36fa","path":"backend/app/models/user.py","line_range":"11-48","gmt_create":"2026-04-24T10:59:38.903869+08:00","gmt_modified":"2026-04-24T10:59:38.903869+08:00"},{"id":"675ab6c1ae510ca753b5e966b7b6a10c","path":"backend/alembic/versions/c3d5e7f9ab12_add_user_management_fields.py","line_range":"21-41","gmt_create":"2026-04-24T10:59:38.907463+08:00","gmt_modified":"2026-04-24T10:59:38.907463+08:00"},{"id":"fe351bf59a46bec7f77ffe40a68a5993","path":"backend/app/services/auth.py","line_range":"40-56","gmt_create":"2026-04-24T10:59:38.917216+08:00","gmt_modified":"2026-04-24T10:59:38.917216+08:00"},{"id":"46e69841e5c5dc62faa55c9f066586d6","path":"backend/app/services/auth.py","line_range":"74-107","gmt_create":"2026-04-24T10:59:38.919469+08:00","gmt_modified":"2026-04-24T10:59:38.919469+08:00"},{"id":"cecc8857775f7928d465b68e429493d2","path":"backend/app/services/auth.py","line_range":"110-140","gmt_create":"2026-04-24T10:59:38.91977+08:00","gmt_modified":"2026-04-24T10:59:38.91977+08:00"},{"id":"1153d8a149a70bc79ca59a9dcba5945c","path":"backend/app/schemas/auth.py","line_range":"8-55","gmt_create":"2026-04-24T10:59:38.920046+08:00","gmt_modified":"2026-04-24T10:59:38.920046+08:00"},{"id":"35dd08df9c7a562d9c7b8edf740eaf3c","path":"backend/app/api/auth.py","line_range":"33-115","gmt_create":"2026-04-24T10:59:38.920424+08:00","gmt_modified":"2026-04-24T10:59:38.920424+08:00"},{"id":"dc735ee4a0f12140bcee122a67f4a13b","path":"frontend/components/layout/sidebar.tsx","line_range":"1-63","gmt_create":"2026-04-24T11:01:58.065941+08:00","gmt_modified":"2026-04-24T11:01:58.065941+08:00"},{"id":"f990ecd63842b3ab82f5b8c8dcde2a6b","path":"frontend/next.config.mjs","line_range":"1-5","gmt_create":"2026-04-24T11:01:58.066899+08:00","gmt_modified":"2026-04-24T11:01:58.0669+08:00"},{"id":"d5efa0fbc545b778dd913854d860c502","path":"frontend/types/next-auth.d.ts","line_range":"1-29","gmt_create":"2026-04-24T11:01:58.069351+08:00","gmt_modified":"2026-04-24T11:01:58.069351+08:00"},{"id":"46434c04e402674d97a6e2017a3a13c0","path":"backend/app/schemas/auth.py","line_range":"8-62","gmt_create":"2026-04-24T11:02:17.54295+08:00","gmt_modified":"2026-04-24T11:02:17.54295+08:00"},{"id":"3a0fd619768c80d413f8b02b3daec229","path":"backend/app/services/auth.py","line_range":"74-175","gmt_create":"2026-04-24T11:02:17.543584+08:00","gmt_modified":"2026-04-24T11:02:17.543584+08:00"},{"id":"86af0295eebcd62f33207e158db86c81","path":"backend/app/api/auth.py","line_range":"65-115","gmt_create":"2026-04-24T11:02:17.544119+08:00","gmt_modified":"2026-04-24T11:02:17.544119+08:00"},{"id":"809fc86e3ce390a1af1db1e0cd5ad787","path":"frontend/lib/api.ts","line_range":"55-84","gmt_create":"2026-04-24T11:02:17.544907+08:00","gmt_modified":"2026-04-24T11:02:17.544908+08:00"},{"id":"29ee02d164db08d7b9bd4591195e191b","path":"frontend/lib/auth.ts","line_range":"5-56","gmt_create":"2026-04-24T11:02:17.550558+08:00","gmt_modified":"2026-04-24T11:02:17.550559+08:00"},{"id":"73c4889fcacaea737921a568bf20383d","path":"frontend/lib/auth.ts","line_range":"13-32","gmt_create":"2026-04-24T11:02:17.552671+08:00","gmt_modified":"2026-04-24T11:02:17.552672+08:00"},{"id":"11c2505e56ba9a48c50be4c915f22c9d","path":"backend/app/services/auth.py","line_range":"27-37","gmt_create":"2026-04-24T11:02:17.554379+08:00","gmt_modified":"2026-04-24T11:02:17.554379+08:00"},{"id":"5f32b18b18cea3b2bdc9150366c24e5e","path":"backend/app/api/deps.py","line_range":"26-37","gmt_create":"2026-04-24T11:02:17.554832+08:00","gmt_modified":"2026-04-24T11:02:17.554832+08:00"},{"id":"c4abaa8a82ad75d09ee66f97fbad4b96","path":"backend/app/config.py","line_range":"9-10","gmt_create":"2026-04-24T11:02:17.555347+08:00","gmt_modified":"2026-04-24T11:02:17.555347+08:00"},{"id":"08ac91fb508b386f0e6c66e53b03a471","path":"backend/app/schemas/auth.py","line_range":"8-11","gmt_create":"2026-04-24T11:02:17.556938+08:00","gmt_modified":"2026-04-24T11:02:17.556938+08:00"},{"id":"d4ea500c0acb4ebf267a44908e23f787","path":"backend/app/services/auth.py","line_range":"40-55","gmt_create":"2026-04-24T11:02:17.557577+08:00","gmt_modified":"2026-04-24T11:02:17.557577+08:00"},{"id":"b4f0bea37f71296167571d8831ebe6d5","path":"tests/test_auth.py","line_range":"25-58","gmt_create":"2026-04-24T11:02:17.558569+08:00","gmt_modified":"2026-04-24T11:02:17.558569+08:00"},{"id":"46f7431da5eb82bbd7686a71abaddf78","path":"backend/app/api/auth.py","line_range":"42-57","gmt_create":"2026-04-24T11:02:17.558961+08:00","gmt_modified":"2026-04-24T11:02:17.558961+08:00"},{"id":"0ba2ea54873608360c48c8b5aaeea20f","path":"backend/app/services/auth.py","line_range":"58-71","gmt_create":"2026-04-24T11:02:17.559312+08:00","gmt_modified":"2026-04-24T11:02:17.559312+08:00"},{"id":"2d170933ae8c838199f6d68a2b9165c0","path":"tests/test_auth.py","line_range":"61-84","gmt_create":"2026-04-24T11:02:17.560326+08:00","gmt_modified":"2026-04-24T11:02:17.560327+08:00"},{"id":"0ea85b56099b9087bd22eec96b7bb752","path":"backend/app/services/auth.py","line_range":"74-140","gmt_create":"2026-04-24T11:02:17.560916+08:00","gmt_modified":"2026-04-24T11:02:17.560916+08:00"},{"id":"2a4087b6941ca17dd651147f2f23451c","path":"backend/app/api/auth.py","line_range":"65-90","gmt_create":"2026-04-24T11:02:17.561945+08:00","gmt_modified":"2026-04-24T11:02:17.561945+08:00"},{"id":"88c12e200d5c3ea53c695aa4209cecd9","path":"backend/app/api/auth.py","line_range":"65-76","gmt_create":"2026-04-24T11:02:17.562602+08:00","gmt_modified":"2026-04-24T11:02:17.562603+08:00"},{"id":"42b92d878423a23067e9a6da104e3a5e","path":"backend/app/api/auth.py","line_range":"79-90","gmt_create":"2026-04-24T11:02:17.564153+08:00","gmt_modified":"2026-04-24T11:02:17.564153+08:00"},{"id":"abadc99952ad6e00ab4bfb66b84732bb","path":"backend/app/schemas/auth.py","line_range":"33-41","gmt_create":"2026-04-24T11:02:17.56603+08:00","gmt_modified":"2026-04-24T11:02:17.56603+08:00"},{"id":"f784a33e47128515d518555d99103f62","path":"backend/app/services/auth.py","line_range":"143-175","gmt_create":"2026-04-24T11:02:17.566806+08:00","gmt_modified":"2026-04-24T11:02:17.566806+08:00"},{"id":"173f8de5896e18fc81cdd5d72e2a8c07","path":"backend/app/api/auth.py","line_range":"93-115","gmt_create":"2026-04-24T11:02:17.567894+08:00","gmt_modified":"2026-04-24T11:02:17.567894+08:00"},{"id":"3ab144009e705151f69698d2d8a81cea","path":"backend/app/services/auth.py","line_range":"35-37","gmt_create":"2026-04-24T11:02:17.56892+08:00","gmt_modified":"2026-04-24T11:02:17.56892+08:00"},{"id":"570a917d85850ab1208fce5823b110a3","path":"backend/app/api/auth.py","line_range":"60-62","gmt_create":"2026-04-24T11:02:17.569617+08:00","gmt_modified":"2026-04-24T11:02:17.569617+08:00"},{"id":"f92c0c41197c488f04f994bf0f7ea465","path":"tests/test_auth.py","line_range":"87-104","gmt_create":"2026-04-24T11:02:17.570008+08:00","gmt_modified":"2026-04-24T11:02:17.570008+08:00"},{"id":"5688471e2418628ac2a6409451708d06","path":"backend/app/api/auth.py","line_range":"1-115","gmt_create":"2026-04-24T11:02:17.571751+08:00","gmt_modified":"2026-04-24T11:02:17.571751+08:00"},{"id":"7075cde1c771c46dbbd37b3c09dac53d","path":"backend/app/api/deps.py","line_range":"20-41","gmt_create":"2026-04-24T11:02:17.576276+08:00","gmt_modified":"2026-04-24T11:02:17.576276+08:00"},{"id":"607e99e751640281d26516c772548b93","path":"frontend/lib/api.ts","line_range":"17-39","gmt_create":"2026-04-24T11:02:17.576883+08:00","gmt_modified":"2026-04-24T11:02:17.576883+08:00"},{"id":"0fcc0fe680a7ca8b8c7f4d579b77aeec","path":"backend/app/main.py","line_range":"12-78","gmt_create":"2026-04-24T11:02:30.018464+08:00","gmt_modified":"2026-04-24T11:02:30.018464+08:00"},{"id":"10d3948b1394ffa0110796edfa0bfc25","path":"backend/app/api/auth.py","line_range":"30","gmt_create":"2026-04-24T11:02:30.018782+08:00","gmt_modified":"2026-04-24T11:02:30.018782+08:00"},{"id":"3c41910bad9855635d1362efc314463a","path":"backend/app/api/reports.py","line_range":"15","gmt_create":"2026-04-24T11:02:30.019676+08:00","gmt_modified":"2026-04-24T11:02:30.019676+08:00"},{"id":"f32e078c985967af30d2c526290d9acb","path":"backend/app/api/subscriptions.py","line_range":"23","gmt_create":"2026-04-24T11:02:30.020008+08:00","gmt_modified":"2026-04-24T11:02:30.020008+08:00"},{"id":"c10a89cdd47474f51664a239b82cc2e2","path":"backend/app/api/admin.py","line_range":"17","gmt_create":"2026-04-24T11:02:30.020325+08:00","gmt_modified":"2026-04-24T11:02:30.020326+08:00"},{"id":"d6ebce8c7d9e9de127486400670ebed0","path":"backend/app/main.py","line_range":"39-84","gmt_create":"2026-04-24T11:02:30.020913+08:00","gmt_modified":"2026-04-24T11:02:30.020913+08:00"},{"id":"ec3ed02cad3cd8af4bacb5c978273092","path":"backend/app/api/subscriptions.py","line_range":"26-77","gmt_create":"2026-04-24T11:02:30.021508+08:00","gmt_modified":"2026-04-24T11:02:30.021509+08:00"},{"id":"2db9940a42c91fc92f23595491ea93d1","path":"backend/app/main.py","line_range":"67-78","gmt_create":"2026-04-24T11:02:30.022384+08:00","gmt_modified":"2026-04-24T11:02:30.022384+08:00"},{"id":"68fbb2bd365f96a98ea187a9738c4460","path":"backend/app/api/auth.py","line_range":"33-57","gmt_create":"2026-04-24T11:02:30.024114+08:00","gmt_modified":"2026-04-24T11:02:30.024114+08:00"},{"id":"44f9c9f195e096efbd6c6a6f97880944","path":"backend/app/api/reports.py","line_range":"51-75","gmt_create":"2026-04-24T11:02:30.02932+08:00","gmt_modified":"2026-04-24T11:02:30.02932+08:00"},{"id":"cbe8ffc1cfb98ac79c7659e968191837","path":"backend/app/services/citation.py","line_range":"343-466","gmt_create":"2026-04-24T11:02:30.029647+08:00","gmt_modified":"2026-04-24T11:02:30.029647+08:00"},{"id":"97f9b6149bd43feb0f69cf2582ab6305","path":"backend/app/services/subscription.py","line_range":"85-117","gmt_create":"2026-04-24T11:02:30.030707+08:00","gmt_modified":"2026-04-24T11:02:30.030707+08:00"},{"id":"ce4de96353f8f81ca825173ddbec1150","path":"backend/app/schemas/subscription.py","line_range":"12-41","gmt_create":"2026-04-24T11:02:30.031384+08:00","gmt_modified":"2026-04-24T11:02:30.031384+08:00"},{"id":"a87a1a7c1723518159d5818c197996cc","path":"backend/app/services/subscription.py","line_range":"56-155","gmt_create":"2026-04-24T11:02:30.031685+08:00","gmt_modified":"2026-04-24T11:02:30.031686+08:00"},{"id":"0e4bc0a539e0ccc6832031bdaf1eb1ca","path":"backend/app/api/admin.py","line_range":"29-45","gmt_create":"2026-04-24T11:02:30.031966+08:00","gmt_modified":"2026-04-24T11:02:30.031966+08:00"},{"id":"f7314a4515e822cba6f37d7a8f1970f3","path":"backend/app/services/admin.py","line_range":"14-46","gmt_create":"2026-04-24T11:02:30.032241+08:00","gmt_modified":"2026-04-24T11:02:30.032242+08:00"},{"id":"ef31f4aa4fbd1b6ff76eba467b757a04","path":"backend/app/middleware/rate_limit.py","line_range":"34-69","gmt_create":"2026-04-24T11:02:30.033139+08:00","gmt_modified":"2026-04-24T11:02:30.03314+08:00"},{"id":"3a7201f4564dbcf35c5771f1b5d58cb6","path":"backend/app/api/auth.py","line_range":"46-50","gmt_create":"2026-04-24T11:02:30.037193+08:00","gmt_modified":"2026-04-24T11:02:30.037193+08:00"},{"id":"39c3dbe67ab2ae74446fe6a118bd8738","path":"backend/app/api/reports.py","line_range":"25-29","gmt_create":"2026-04-24T11:02:30.038125+08:00","gmt_modified":"2026-04-24T11:02:30.038125+08:00"},{"id":"68d937267aab2509edc0c7b67e1b5ef6","path":"backend/app/api/subscriptions.py","line_range":"53-57","gmt_create":"2026-04-24T11:02:30.038578+08:00","gmt_modified":"2026-04-24T11:02:30.038578+08:00"},{"id":"3d0bf5a05f6a7d2b8b12bb91e8f93642","path":"backend/app/api/admin.py","line_range":"22-25","gmt_create":"2026-04-24T11:02:30.038936+08:00","gmt_modified":"2026-04-24T11:02:30.038936+08:00"},{"id":"a9c1b0716ae36af22fce6148c2e40ce5","path":"backend/app/middleware/rate_limit.py","line_range":"47-49","gmt_create":"2026-04-24T11:02:30.039285+08:00","gmt_modified":"2026-04-24T11:02:30.039285+08:00"}],"knowledge_relations":[{"id":34,"source_id":"98909ecc-fceb-4ab7-a26f-741838eb2e50","target_id":"1ed0b482-3d6a-4bfd-af40-47a5d1f3e802","source_type":"WIKI_ITEM","target_type":"WIKI_ITEM","relationship_type":"PARENT_CHILD","extra":"Wiki parent-child relationship: 98909ecc-fceb-4ab7-a26f-741838eb2e50 -\u003e 1ed0b482-3d6a-4bfd-af40-47a5d1f3e802","gmt_create":"2026-04-22T19:25:18.934991+08:00","gmt_modified":"2026-04-22T19:25:18.934991+08:00"},{"id":35,"source_id":"98909ecc-fceb-4ab7-a26f-741838eb2e50","target_id":"26f80935-eac2-44ee-bcdb-d6a79c537750","source_type":"WIKI_ITEM","target_type":"WIKI_ITEM","relationship_type":"PARENT_CHILD","extra":"Wiki parent-child relationship: 98909ecc-fceb-4ab7-a26f-741838eb2e50 -\u003e 26f80935-eac2-44ee-bcdb-d6a79c537750","gmt_create":"2026-04-22T19:25:18.935426+08:00","gmt_modified":"2026-04-22T19:25:18.935426+08:00"},{"id":36,"source_id":"98909ecc-fceb-4ab7-a26f-741838eb2e50","target_id":"eb1288f7-5ea1-413a-8f54-4f870306d14d","source_type":"WIKI_ITEM","target_type":"WIKI_ITEM","relationship_type":"PARENT_CHILD","extra":"Wiki parent-child relationship: 98909ecc-fceb-4ab7-a26f-741838eb2e50 -\u003e eb1288f7-5ea1-413a-8f54-4f870306d14d","gmt_create":"2026-04-22T19:25:18.935875+08:00","gmt_modified":"2026-04-22T19:25:18.935875+08:00"},{"id":37,"source_id":"98909ecc-fceb-4ab7-a26f-741838eb2e50","target_id":"aa6db9b6-71e1-4497-a0e2-f3ff25358d3a","source_type":"WIKI_ITEM","target_type":"WIKI_ITEM","relationship_type":"PARENT_CHILD","extra":"Wiki parent-child relationship: 98909ecc-fceb-4ab7-a26f-741838eb2e50 -\u003e aa6db9b6-71e1-4497-a0e2-f3ff25358d3a","gmt_create":"2026-04-22T19:25:18.936315+08:00","gmt_modified":"2026-04-22T19:25:18.936316+08:00"},{"id":45,"source_id":"c5849940-e223-4222-be17-aa0a6cb36bc8","target_id":"d2c7157d-157f-4990-8f76-11f3ea5435f7","source_type":"WIKI_ITEM","target_type":"WIKI_ITEM","relationship_type":"PARENT_CHILD","extra":"Wiki parent-child relationship: c5849940-e223-4222-be17-aa0a6cb36bc8 -\u003e d2c7157d-157f-4990-8f76-11f3ea5435f7","gmt_create":"2026-04-22T19:25:18.939978+08:00","gmt_modified":"2026-04-22T19:25:18.939978+08:00"},{"id":46,"source_id":"c5849940-e223-4222-be17-aa0a6cb36bc8","target_id":"e1e0bd0e-01b3-4543-9781-d9beb32b9a57","source_type":"WIKI_ITEM","target_type":"WIKI_ITEM","relationship_type":"PARENT_CHILD","extra":"Wiki parent-child relationship: c5849940-e223-4222-be17-aa0a6cb36bc8 -\u003e e1e0bd0e-01b3-4543-9781-d9beb32b9a57","gmt_create":"2026-04-22T19:25:18.940415+08:00","gmt_modified":"2026-04-22T19:25:18.940415+08:00"},{"id":47,"source_id":"c5849940-e223-4222-be17-aa0a6cb36bc8","target_id":"e9a02c86-236b-49cb-bbed-9462ee123c04","source_type":"WIKI_ITEM","target_type":"WIKI_ITEM","relationship_type":"PARENT_CHILD","extra":"Wiki parent-child relationship: c5849940-e223-4222-be17-aa0a6cb36bc8 -\u003e e9a02c86-236b-49cb-bbed-9462ee123c04","gmt_create":"2026-04-22T19:25:18.941227+08:00","gmt_modified":"2026-04-22T19:25:18.941227+08:00"},{"id":48,"source_id":"ba0390b3-c249-4e92-a3c8-6820343aeda9","target_id":"12e2c3d7b9a92dc44a6ee29b85e10df6","source_type":"WIKI_ITEM","target_type":"SOURCE_FILE","relationship_type":"REFERENCED_BY","extra":"Wiki references source file: frontend/app/layout.tsx","gmt_create":"2026-04-23T15:19:43.777831+08:00","gmt_modified":"2026-04-23T15:19:43.777831+08:00"},{"id":49,"source_id":"ba0390b3-c249-4e92-a3c8-6820343aeda9","target_id":"2a1c745c7b3fb7f600596be3d979bba1","source_type":"WIKI_ITEM","target_type":"SOURCE_FILE","relationship_type":"REFERENCED_BY","extra":"Wiki references source file: frontend/app/(dashboard","gmt_create":"2026-04-23T15:19:43.778774+08:00","gmt_modified":"2026-04-23T15:19:43.778774+08:00"},{"id":50,"source_id":"ba0390b3-c249-4e92-a3c8-6820343aeda9","target_id":"eca13a610badfc5ffc6210827fb96991","source_type":"WIKI_ITEM","target_type":"SOURCE_FILE","relationship_type":"REFERENCED_BY","extra":"Wiki references source file: frontend/components/layout/header.tsx","gmt_create":"2026-04-23T15:19:43.779153+08:00","gmt_modified":"2026-04-23T15:19:43.779154+08:00"},{"id":51,"source_id":"ba0390b3-c249-4e92-a3c8-6820343aeda9","target_id":"18a0651d895fba9bb4e0c0229459efdc","source_type":"WIKI_ITEM","target_type":"SOURCE_FILE","relationship_type":"REFERENCED_BY","extra":"Wiki references source file: frontend/components/layout/sidebar.tsx","gmt_create":"2026-04-23T15:19:43.779524+08:00","gmt_modified":"2026-04-23T15:19:43.779524+08:00"},{"id":52,"source_id":"ba0390b3-c249-4e92-a3c8-6820343aeda9","target_id":"5d7886d0dc99f81073a578b8aefdd375","source_type":"WIKI_ITEM","target_type":"SOURCE_FILE","relationship_type":"REFERENCED_BY","extra":"Wiki references source file: frontend/lib/api.ts","gmt_create":"2026-04-23T15:19:43.779869+08:00","gmt_modified":"2026-04-23T15:19:43.779869+08:00"},{"id":53,"source_id":"ba0390b3-c249-4e92-a3c8-6820343aeda9","target_id":"0c0b0f4e2cf44facd9d5b57de0d0bf0c","source_type":"WIKI_ITEM","target_type":"SOURCE_FILE","relationship_type":"REFERENCED_BY","extra":"Wiki references source file: frontend/components/ui/table.tsx","gmt_create":"2026-04-23T15:19:43.780775+08:00","gmt_modified":"2026-04-23T15:19:43.780775+08:00"},{"id":54,"source_id":"ba0390b3-c249-4e92-a3c8-6820343aeda9","target_id":"108b0c4b4dcfb6aa39a5eb138225c148","source_type":"WIKI_ITEM","target_type":"SOURCE_FILE","relationship_type":"REFERENCED_BY","extra":"Wiki references source file: frontend/components/ui/dialog.tsx","gmt_create":"2026-04-23T15:19:43.781767+08:00","gmt_modified":"2026-04-23T15:19:43.781767+08:00"},{"id":55,"source_id":"ba0390b3-c249-4e92-a3c8-6820343aeda9","target_id":"ef72f0c3cedb9fd9a87352fe493053dc","source_type":"WIKI_ITEM","target_type":"SOURCE_FILE","relationship_type":"REFERENCED_BY","extra":"Wiki references source file: frontend/lib/platforms.ts","gmt_create":"2026-04-23T15:19:43.782177+08:00","gmt_modified":"2026-04-23T15:19:43.782177+08:00"},{"id":56,"source_id":"ba0390b3-c249-4e92-a3c8-6820343aeda9","target_id":"f93ae024fe0a2e69698037dff6df205f","source_type":"WIKI_ITEM","target_type":"SOURCE_FILE","relationship_type":"REFERENCED_BY","extra":"Wiki references source file: frontend/lib/utils.ts","gmt_create":"2026-04-23T15:19:43.782527+08:00","gmt_modified":"2026-04-23T15:19:43.782527+08:00"},{"id":57,"source_id":"ba0390b3-c249-4e92-a3c8-6820343aeda9","target_id":"d5f2266643d2011c66e86af088ec637f","source_type":"WIKI_ITEM","target_type":"SOURCE_FILE","relationship_type":"REFERENCED_BY","extra":"Wiki references source file: frontend/components/charts/trend-chart.tsx","gmt_create":"2026-04-23T15:19:43.782861+08:00","gmt_modified":"2026-04-23T15:19:43.782861+08:00"},{"id":58,"source_id":"ba0390b3-c249-4e92-a3c8-6820343aeda9","target_id":"f1a7d61831cc0a45ac6220294f15c21d","source_type":"WIKI_ITEM","target_type":"SOURCE_FILE","relationship_type":"REFERENCED_BY","extra":"Wiki references source file: frontend/components/charts/platform-chart.tsx","gmt_create":"2026-04-23T15:19:43.783164+08:00","gmt_modified":"2026-04-23T15:19:43.783165+08:00"},{"id":59,"source_id":"ba0390b3-c249-4e92-a3c8-6820343aeda9","target_id":"8a466b0c6eac2ccb54c5da7e13854646","source_type":"WIKI_ITEM","target_type":"CODE_SNIPPET","relationship_type":"CONTAINS","extra":"Wiki contains code snippet: frontend/app/layout.tsx#1-37","gmt_create":"2026-04-23T15:19:43.783668+08:00","gmt_modified":"2026-04-23T15:19:43.783668+08:00"},{"id":60,"source_id":"12e2c3d7b9a92dc44a6ee29b85e10df6","target_id":"8a466b0c6eac2ccb54c5da7e13854646","source_type":"SOURCE_FILE","target_type":"CODE_SNIPPET","relationship_type":"CONTAINS","extra":"Source file contains code snippet: 1-37","gmt_create":"2026-04-23T15:19:43.783987+08:00","gmt_modified":"2026-04-23T15:19:43.783987+08:00"},{"id":61,"source_id":"ba0390b3-c249-4e92-a3c8-6820343aeda9","target_id":"3bd4eedea376e3a3d9f9fbff4fe27a65","source_type":"WIKI_ITEM","target_type":"CODE_SNIPPET","relationship_type":"CONTAINS","extra":"Wiki contains code snippet: frontend/components/layout/sidebar.tsx#1-54","gmt_create":"2026-04-23T15:19:43.784455+08:00","gmt_modified":"2026-04-23T15:19:43.784455+08:00"},{"id":62,"source_id":"18a0651d895fba9bb4e0c0229459efdc","target_id":"3bd4eedea376e3a3d9f9fbff4fe27a65","source_type":"SOURCE_FILE","target_type":"CODE_SNIPPET","relationship_type":"CONTAINS","extra":"Source file contains code snippet: 1-54","gmt_create":"2026-04-23T15:19:43.784807+08:00","gmt_modified":"2026-04-23T15:19:43.784807+08:00"},{"id":63,"source_id":"ba0390b3-c249-4e92-a3c8-6820343aeda9","target_id":"0d903468b55bdc63cc7e25a87a89c522","source_type":"WIKI_ITEM","target_type":"CODE_SNIPPET","relationship_type":"CONTAINS","extra":"Wiki contains code snippet: frontend/components/layout/header.tsx#1-30","gmt_create":"2026-04-23T15:19:43.785303+08:00","gmt_modified":"2026-04-23T15:19:43.785303+08:00"},{"id":64,"source_id":"eca13a610badfc5ffc6210827fb96991","target_id":"0d903468b55bdc63cc7e25a87a89c522","source_type":"SOURCE_FILE","target_type":"CODE_SNIPPET","relationship_type":"CONTAINS","extra":"Source file contains code snippet: 1-30","gmt_create":"2026-04-23T15:19:43.785622+08:00","gmt_modified":"2026-04-23T15:19:43.785622+08:00"},{"id":65,"source_id":"ba0390b3-c249-4e92-a3c8-6820343aeda9","target_id":"3bab92a09e9fb456e0303bb1e04afc7e","source_type":"WIKI_ITEM","target_type":"CODE_SNIPPET","relationship_type":"CONTAINS","extra":"Wiki contains code snippet: frontend/components/ui/table.tsx#1-118","gmt_create":"2026-04-23T15:19:43.78727+08:00","gmt_modified":"2026-04-23T15:19:43.787271+08:00"},{"id":66,"source_id":"0c0b0f4e2cf44facd9d5b57de0d0bf0c","target_id":"3bab92a09e9fb456e0303bb1e04afc7e","source_type":"SOURCE_FILE","target_type":"CODE_SNIPPET","relationship_type":"CONTAINS","extra":"Source file contains code snippet: 1-118","gmt_create":"2026-04-23T15:19:43.788224+08:00","gmt_modified":"2026-04-23T15:19:43.788224+08:00"},{"id":67,"source_id":"ba0390b3-c249-4e92-a3c8-6820343aeda9","target_id":"0eed9f61572209dd754611fc7c690d5a","source_type":"WIKI_ITEM","target_type":"CODE_SNIPPET","relationship_type":"CONTAINS","extra":"Wiki contains code snippet: frontend/components/ui/dialog.tsx#1-123","gmt_create":"2026-04-23T15:19:43.789533+08:00","gmt_modified":"2026-04-23T15:19:43.789533+08:00"},{"id":68,"source_id":"108b0c4b4dcfb6aa39a5eb138225c148","target_id":"0eed9f61572209dd754611fc7c690d5a","source_type":"SOURCE_FILE","target_type":"CODE_SNIPPET","relationship_type":"CONTAINS","extra":"Source file contains code snippet: 1-123","gmt_create":"2026-04-23T15:19:43.790255+08:00","gmt_modified":"2026-04-23T15:19:43.790255+08:00"},{"id":69,"source_id":"ba0390b3-c249-4e92-a3c8-6820343aeda9","target_id":"b7796fc6197ecce5beb461b9466e54a0","source_type":"WIKI_ITEM","target_type":"CODE_SNIPPET","relationship_type":"CONTAINS","extra":"Wiki contains code snippet: frontend/components/charts/trend-chart.tsx#1-60","gmt_create":"2026-04-23T15:19:43.790795+08:00","gmt_modified":"2026-04-23T15:19:43.790795+08:00"},{"id":70,"source_id":"d5f2266643d2011c66e86af088ec637f","target_id":"b7796fc6197ecce5beb461b9466e54a0","source_type":"SOURCE_FILE","target_type":"CODE_SNIPPET","relationship_type":"CONTAINS","extra":"Source file contains code snippet: 1-60","gmt_create":"2026-04-23T15:19:43.791134+08:00","gmt_modified":"2026-04-23T15:19:43.791134+08:00"},{"id":71,"source_id":"ba0390b3-c249-4e92-a3c8-6820343aeda9","target_id":"6b9f52af0b6d78c17ff9bbc42d760ea2","source_type":"WIKI_ITEM","target_type":"CODE_SNIPPET","relationship_type":"CONTAINS","extra":"Wiki contains code snippet: frontend/components/charts/platform-chart.tsx#1-68","gmt_create":"2026-04-23T15:19:43.791601+08:00","gmt_modified":"2026-04-23T15:19:43.791601+08:00"},{"id":72,"source_id":"f1a7d61831cc0a45ac6220294f15c21d","target_id":"6b9f52af0b6d78c17ff9bbc42d760ea2","source_type":"SOURCE_FILE","target_type":"CODE_SNIPPET","relationship_type":"CONTAINS","extra":"Source file contains code snippet: 1-68","gmt_create":"2026-04-23T15:19:43.791902+08:00","gmt_modified":"2026-04-23T15:19:43.791902+08:00"},{"id":73,"source_id":"ba0390b3-c249-4e92-a3c8-6820343aeda9","target_id":"a829403082cc3460c01e0110229c53c4","source_type":"WIKI_ITEM","target_type":"CODE_SNIPPET","relationship_type":"CONTAINS","extra":"Wiki contains code snippet: frontend/lib/platforms.ts#1-18","gmt_create":"2026-04-23T15:19:43.792356+08:00","gmt_modified":"2026-04-23T15:19:43.792356+08:00"},{"id":74,"source_id":"ef72f0c3cedb9fd9a87352fe493053dc","target_id":"a829403082cc3460c01e0110229c53c4","source_type":"SOURCE_FILE","target_type":"CODE_SNIPPET","relationship_type":"CONTAINS","extra":"Source file contains code snippet: 1-18","gmt_create":"2026-04-23T15:19:43.79267+08:00","gmt_modified":"2026-04-23T15:19:43.79267+08:00"},{"id":75,"source_id":"ba0390b3-c249-4e92-a3c8-6820343aeda9","target_id":"dcfa308ef4ec368c5a51a17acbfc8e2c","source_type":"WIKI_ITEM","target_type":"CODE_SNIPPET","relationship_type":"CONTAINS","extra":"Wiki contains code snippet: frontend/lib/utils.ts#1-7","gmt_create":"2026-04-23T15:19:43.79312+08:00","gmt_modified":"2026-04-23T15:19:43.79312+08:00"},{"id":76,"source_id":"f93ae024fe0a2e69698037dff6df205f","target_id":"dcfa308ef4ec368c5a51a17acbfc8e2c","source_type":"SOURCE_FILE","target_type":"CODE_SNIPPET","relationship_type":"CONTAINS","extra":"Source file contains code snippet: 1-7","gmt_create":"2026-04-23T15:19:43.793455+08:00","gmt_modified":"2026-04-23T15:19:43.793455+08:00"},{"id":77,"source_id":"ba0390b3-c249-4e92-a3c8-6820343aeda9","target_id":"0f87c8089f548883d056f0a0d79e273f","source_type":"WIKI_ITEM","target_type":"CODE_SNIPPET","relationship_type":"CONTAINS","extra":"Wiki contains code snippet: frontend/lib/api.ts#1-79","gmt_create":"2026-04-23T15:19:43.793866+08:00","gmt_modified":"2026-04-23T15:19:43.793866+08:00"},{"id":78,"source_id":"5d7886d0dc99f81073a578b8aefdd375","target_id":"0f87c8089f548883d056f0a0d79e273f","source_type":"SOURCE_FILE","target_type":"CODE_SNIPPET","relationship_type":"CONTAINS","extra":"Source file contains code snippet: 1-79","gmt_create":"2026-04-23T15:19:43.794158+08:00","gmt_modified":"2026-04-23T15:19:43.794158+08:00"},{"id":79,"source_id":"ba0390b3-c249-4e92-a3c8-6820343aeda9","target_id":"9beee1f41fe8f0750fd97155f9d54bbb","source_type":"WIKI_ITEM","target_type":"CODE_SNIPPET","relationship_type":"CONTAINS","extra":"Wiki contains code snippet: frontend/lib/api.ts#67-70","gmt_create":"2026-04-23T15:19:43.797877+08:00","gmt_modified":"2026-04-23T15:19:43.797877+08:00"},{"id":80,"source_id":"5d7886d0dc99f81073a578b8aefdd375","target_id":"9beee1f41fe8f0750fd97155f9d54bbb","source_type":"SOURCE_FILE","target_type":"CODE_SNIPPET","relationship_type":"CONTAINS","extra":"Source file contains code snippet: 67-70","gmt_create":"2026-04-23T15:19:43.798244+08:00","gmt_modified":"2026-04-23T15:19:43.798244+08:00"},{"id":81,"source_id":"ba0390b3-c249-4e92-a3c8-6820343aeda9","target_id":"8fe2e22a963442076e1ce16ab777573c","source_type":"WIKI_ITEM","target_type":"CODE_SNIPPET","relationship_type":"CONTAINS","extra":"Wiki contains code snippet: frontend/lib/api.ts#56-66","gmt_create":"2026-04-23T15:19:43.799319+08:00","gmt_modified":"2026-04-23T15:19:43.799319+08:00"},{"id":82,"source_id":"5d7886d0dc99f81073a578b8aefdd375","target_id":"8fe2e22a963442076e1ce16ab777573c","source_type":"SOURCE_FILE","target_type":"CODE_SNIPPET","relationship_type":"CONTAINS","extra":"Source file contains code snippet: 56-66","gmt_create":"2026-04-23T15:19:43.799625+08:00","gmt_modified":"2026-04-23T15:19:43.799625+08:00"},{"id":83,"source_id":"ba0390b3-c249-4e92-a3c8-6820343aeda9","target_id":"3124ad882ca2cf8fecb6b93696c7f233","source_type":"WIKI_ITEM","target_type":"CODE_SNIPPET","relationship_type":"CONTAINS","extra":"Wiki contains code snippet: frontend/lib/api.ts#72-77","gmt_create":"2026-04-23T15:19:43.801555+08:00","gmt_modified":"2026-04-23T15:19:43.801555+08:00"},{"id":84,"source_id":"5d7886d0dc99f81073a578b8aefdd375","target_id":"3124ad882ca2cf8fecb6b93696c7f233","source_type":"SOURCE_FILE","target_type":"CODE_SNIPPET","relationship_type":"CONTAINS","extra":"Source file contains code snippet: 72-77","gmt_create":"2026-04-23T15:19:43.801939+08:00","gmt_modified":"2026-04-23T15:19:43.801939+08:00"},{"id":85,"source_id":"ba0390b3-c249-4e92-a3c8-6820343aeda9","target_id":"17a97b4ac37fb67b8eda7ce2887c38e7","source_type":"WIKI_ITEM","target_type":"CODE_SNIPPET","relationship_type":"CONTAINS","extra":"Wiki contains code snippet: frontend/app/layout.tsx#17-20","gmt_create":"2026-04-23T15:19:43.806186+08:00","gmt_modified":"2026-04-23T15:19:43.806186+08:00"},{"id":86,"source_id":"12e2c3d7b9a92dc44a6ee29b85e10df6","target_id":"17a97b4ac37fb67b8eda7ce2887c38e7","source_type":"SOURCE_FILE","target_type":"CODE_SNIPPET","relationship_type":"CONTAINS","extra":"Source file contains code snippet: 17-20","gmt_create":"2026-04-23T15:19:43.80664+08:00","gmt_modified":"2026-04-23T15:19:43.80664+08:00"},{"id":87,"source_id":"ba0390b3-c249-4e92-a3c8-6820343aeda9","target_id":"84cba1e0d516e8c9859402fd5c1bc83c","source_type":"WIKI_ITEM","target_type":"CODE_SNIPPET","relationship_type":"CONTAINS","extra":"Wiki contains code snippet: frontend/lib/api.ts#3-40","gmt_create":"2026-04-23T15:19:43.815637+08:00","gmt_modified":"2026-04-23T15:19:43.815637+08:00"},{"id":88,"source_id":"5d7886d0dc99f81073a578b8aefdd375","target_id":"84cba1e0d516e8c9859402fd5c1bc83c","source_type":"SOURCE_FILE","target_type":"CODE_SNIPPET","relationship_type":"CONTAINS","extra":"Source file contains code snippet: 3-40","gmt_create":"2026-04-23T15:19:43.817147+08:00","gmt_modified":"2026-04-23T15:19:43.817147+08:00"},{"id":107,"source_id":"9228ff67d4c757a85d9421b71f4b29f5","target_id":"b55a164add5a8fec2ef0e489f7234829","source_type":"SOURCE_FILE","target_type":"CODE_SNIPPET","relationship_type":"CONTAINS","extra":"Source file contains code snippet: 24-47","gmt_create":"2026-04-23T15:19:45.617445+08:00","gmt_modified":"2026-04-23T15:19:45.617445+08:00"},{"id":109,"source_id":"93022c8938ce318f167277cfa65c29a7","target_id":"16d619435094a63740357cd6317b52cb","source_type":"SOURCE_FILE","target_type":"CODE_SNIPPET","relationship_type":"CONTAINS","extra":"Source file contains code snippet: 10","gmt_create":"2026-04-23T15:19:45.618177+08:00","gmt_modified":"2026-04-23T15:19:45.618177+08:00"},{"id":111,"source_id":"6b3d903205941aa9391dd90016e1102c","target_id":"fa1ee5e3822128a37e9d03af74083392","source_type":"SOURCE_FILE","target_type":"CODE_SNIPPET","relationship_type":"CONTAINS","extra":"Source file contains code snippet: 12","gmt_create":"2026-04-23T15:19:45.619215+08:00","gmt_modified":"2026-04-23T15:19:45.619215+08:00"},{"id":113,"source_id":"7538ffe4902ab6041adb28b19844962a","target_id":"7e908f05baccdfcf7f4a3ef3c9cd5c38","source_type":"SOURCE_FILE","target_type":"CODE_SNIPPET","relationship_type":"CONTAINS","extra":"Source file contains code snippet: 21","gmt_create":"2026-04-23T15:19:45.620246+08:00","gmt_modified":"2026-04-23T15:19:45.620246+08:00"},{"id":115,"source_id":"58901c94d975d87e652a4dc6c8dda656","target_id":"ffe6df344be81bde3941ad8f0d77910b","source_type":"SOURCE_FILE","target_type":"CODE_SNIPPET","relationship_type":"CONTAINS","extra":"Source file contains code snippet: 13","gmt_create":"2026-04-23T15:19:45.623067+08:00","gmt_modified":"2026-04-23T15:19:45.623067+08:00"},{"id":117,"source_id":"9d08667997a868fc07c9b4e328e44224","target_id":"c71fb14f8866e34c679c94a4e2432bc7","source_type":"SOURCE_FILE","target_type":"CODE_SNIPPET","relationship_type":"CONTAINS","extra":"Source file contains code snippet: 13","gmt_create":"2026-04-23T15:19:45.624846+08:00","gmt_modified":"2026-04-23T15:19:45.624846+08:00"},{"id":119,"source_id":"9228ff67d4c757a85d9421b71f4b29f5","target_id":"3c68f1581d2fd6aa845dd71111a9aa9d","source_type":"SOURCE_FILE","target_type":"CODE_SNIPPET","relationship_type":"CONTAINS","extra":"Source file contains code snippet: 1-57","gmt_create":"2026-04-23T15:19:45.625985+08:00","gmt_modified":"2026-04-23T15:19:45.625985+08:00"},{"id":121,"source_id":"9228ff67d4c757a85d9421b71f4b29f5","target_id":"39afb05755a93800fd685af7274110cb","source_type":"SOURCE_FILE","target_type":"CODE_SNIPPET","relationship_type":"CONTAINS","extra":"Source file contains code snippet: 13-57","gmt_create":"2026-04-23T15:19:45.626917+08:00","gmt_modified":"2026-04-23T15:19:45.626917+08:00"},{"id":123,"source_id":"93022c8938ce318f167277cfa65c29a7","target_id":"87a177f17800991e1ed1fb7be03abdb2","source_type":"SOURCE_FILE","target_type":"CODE_SNIPPET","relationship_type":"CONTAINS","extra":"Source file contains code snippet: 13-42","gmt_create":"2026-04-23T15:19:45.627772+08:00","gmt_modified":"2026-04-23T15:19:45.627772+08:00"},{"id":125,"source_id":"6b3d903205941aa9391dd90016e1102c","target_id":"ae9de874df4a46f4197b6c157c25ec6e","source_type":"SOURCE_FILE","target_type":"CODE_SNIPPET","relationship_type":"CONTAINS","extra":"Source file contains code snippet: 15-85","gmt_create":"2026-04-23T15:19:45.628538+08:00","gmt_modified":"2026-04-23T15:19:45.628538+08:00"},{"id":127,"source_id":"7538ffe4902ab6041adb28b19844962a","target_id":"c066a8d4bffabed87a2e38ccad81c107","source_type":"SOURCE_FILE","target_type":"CODE_SNIPPET","relationship_type":"CONTAINS","extra":"Source file contains code snippet: 25-77","gmt_create":"2026-04-23T15:19:45.629465+08:00","gmt_modified":"2026-04-23T15:19:45.629465+08:00"},{"id":129,"source_id":"58901c94d975d87e652a4dc6c8dda656","target_id":"177c73dc4e71186d9eaa1157fc0fe97f","source_type":"SOURCE_FILE","target_type":"CODE_SNIPPET","relationship_type":"CONTAINS","extra":"Source file contains code snippet: 16-46","gmt_create":"2026-04-23T15:19:45.630333+08:00","gmt_modified":"2026-04-23T15:19:45.630333+08:00"},{"id":131,"source_id":"9228ff67d4c757a85d9421b71f4b29f5","target_id":"a0be0cbddb559575861620b5b7579634","source_type":"SOURCE_FILE","target_type":"CODE_SNIPPET","relationship_type":"CONTAINS","extra":"Source file contains code snippet: 38-51","gmt_create":"2026-04-23T15:19:45.631178+08:00","gmt_modified":"2026-04-23T15:19:45.631178+08:00"},{"id":133,"source_id":"9d08667997a868fc07c9b4e328e44224","target_id":"bcdf50f6234651cb9863ab210e6473e5","source_type":"SOURCE_FILE","target_type":"CODE_SNIPPET","relationship_type":"CONTAINS","extra":"Source file contains code snippet: 16-42","gmt_create":"2026-04-23T15:19:45.632177+08:00","gmt_modified":"2026-04-23T15:19:45.632177+08:00"},{"id":135,"source_id":"4d2f3847b7c10634733118b70a1aea0b","target_id":"6df0277c2486b148fa26c2682dbdaa4c","source_type":"SOURCE_FILE","target_type":"CODE_SNIPPET","relationship_type":"CONTAINS","extra":"Source file contains code snippet: 37-68","gmt_create":"2026-04-23T15:19:45.63307+08:00","gmt_modified":"2026-04-23T15:19:45.63307+08:00"},{"id":137,"source_id":"88d22de3b2a7419868e8ae19130d860c","target_id":"5ea5f192d580031ffe57e1582b70c67e","source_type":"SOURCE_FILE","target_type":"CODE_SNIPPET","relationship_type":"CONTAINS","extra":"Source file contains code snippet: 12-123","gmt_create":"2026-04-23T15:19:45.633929+08:00","gmt_modified":"2026-04-23T15:19:45.633929+08:00"},{"id":139,"source_id":"04e3926c080e795713bff683e7dc9d3e","target_id":"fe4a793f16cd4e12b56253c0a6d53ae0","source_type":"SOURCE_FILE","target_type":"CODE_SNIPPET","relationship_type":"CONTAINS","extra":"Source file contains code snippet: 24-359","gmt_create":"2026-04-23T15:19:45.634775+08:00","gmt_modified":"2026-04-23T15:19:45.634775+08:00"},{"id":141,"source_id":"93022c8938ce318f167277cfa65c29a7","target_id":"9552bd8a528207f18e4f3a1696f26a55","source_type":"SOURCE_FILE","target_type":"CODE_SNIPPET","relationship_type":"CONTAINS","extra":"Source file contains code snippet: 13-37","gmt_create":"2026-04-23T15:19:45.635763+08:00","gmt_modified":"2026-04-23T15:19:45.635763+08:00"},{"id":143,"source_id":"e0c0ca66b8b81cf66e078a7ab162c07f","target_id":"4aad38dfc00a0877bd965c3d0b3c280c","source_type":"SOURCE_FILE","target_type":"CODE_SNIPPET","relationship_type":"CONTAINS","extra":"Source file contains code snippet: 7-34","gmt_create":"2026-04-23T15:19:45.639659+08:00","gmt_modified":"2026-04-23T15:19:45.63966+08:00"},{"id":145,"source_id":"88d22de3b2a7419868e8ae19130d860c","target_id":"9b10dac7dbbb1327afc8a525bf4bd0c3","source_type":"SOURCE_FILE","target_type":"CODE_SNIPPET","relationship_type":"CONTAINS","extra":"Source file contains code snippet: 45-81","gmt_create":"2026-04-23T15:19:45.641965+08:00","gmt_modified":"2026-04-23T15:19:45.641965+08:00"},{"id":147,"source_id":"f301b79d833233ce39d350e82a71c938","target_id":"69118807690ef351a9de910414d5e676","source_type":"SOURCE_FILE","target_type":"CODE_SNIPPET","relationship_type":"CONTAINS","extra":"Source file contains code snippet: 11-94","gmt_create":"2026-04-23T15:19:45.643362+08:00","gmt_modified":"2026-04-23T15:19:45.643362+08:00"},{"id":149,"source_id":"7538ffe4902ab6041adb28b19844962a","target_id":"212d822d207a4c0bd7825bbf20e188e9","source_type":"SOURCE_FILE","target_type":"CODE_SNIPPET","relationship_type":"CONTAINS","extra":"Source file contains code snippet: 59-77","gmt_create":"2026-04-23T15:19:45.644457+08:00","gmt_modified":"2026-04-23T15:19:45.644457+08:00"},{"id":151,"source_id":"04e3926c080e795713bff683e7dc9d3e","target_id":"b0777c7da17be89abb333c81c0dcf349","source_type":"SOURCE_FILE","target_type":"CODE_SNIPPET","relationship_type":"CONTAINS","extra":"Source file contains code snippet: 204-261","gmt_create":"2026-04-23T15:19:45.645243+08:00","gmt_modified":"2026-04-23T15:19:45.645243+08:00"},{"id":153,"source_id":"1a3336b4af8a39a055e912724338580c","target_id":"26288877e8e1f6c4ff5aca12610b0218","source_type":"SOURCE_FILE","target_type":"CODE_SNIPPET","relationship_type":"CONTAINS","extra":"Source file contains code snippet: 7-50","gmt_create":"2026-04-23T15:19:45.646445+08:00","gmt_modified":"2026-04-23T15:19:45.646445+08:00"},{"id":155,"source_id":"04e3926c080e795713bff683e7dc9d3e","target_id":"dbf5f8a57778cf6363e834081f3d771c","source_type":"SOURCE_FILE","target_type":"CODE_SNIPPET","relationship_type":"CONTAINS","extra":"Source file contains code snippet: 327-359","gmt_create":"2026-04-23T15:19:45.647935+08:00","gmt_modified":"2026-04-23T15:19:45.647935+08:00"},{"id":157,"source_id":"c59f8c276697a070dffc581fe94d809c","target_id":"56e46969bdb790a5e8f333184b878d6d","source_type":"SOURCE_FILE","target_type":"CODE_SNIPPET","relationship_type":"CONTAINS","extra":"Source file contains code snippet: 11-41","gmt_create":"2026-04-23T15:19:45.649807+08:00","gmt_modified":"2026-04-23T15:19:45.649807+08:00"},{"id":159,"source_id":"b74caccb06844efcdb14d8324cff65c2","target_id":"4fb8856be3a581fe8303d11b2284ca29","source_type":"SOURCE_FILE","target_type":"CODE_SNIPPET","relationship_type":"CONTAINS","extra":"Source file contains code snippet: 11-55","gmt_create":"2026-04-23T15:19:45.650642+08:00","gmt_modified":"2026-04-23T15:19:45.650642+08:00"},{"id":161,"source_id":"b4a81ef789630d0af6a8d50859d01bf3","target_id":"fd541971cebf8a7c167d717f5c5d1ff6","source_type":"SOURCE_FILE","target_type":"CODE_SNIPPET","relationship_type":"CONTAINS","extra":"Source file contains code snippet: 11-42","gmt_create":"2026-04-23T15:19:45.651529+08:00","gmt_modified":"2026-04-23T15:19:45.651529+08:00"},{"id":163,"source_id":"069738f21ac2da7349d22683e8c36929","target_id":"b84f46f058847733347974841f613688","source_type":"SOURCE_FILE","target_type":"CODE_SNIPPET","relationship_type":"CONTAINS","extra":"Source file contains code snippet: 11-39","gmt_create":"2026-04-23T15:19:45.65251+08:00","gmt_modified":"2026-04-23T15:19:45.65251+08:00"},{"id":165,"source_id":"c59f8c276697a070dffc581fe94d809c","target_id":"1a2657244414b5681afded9565a86422","source_type":"SOURCE_FILE","target_type":"CODE_SNIPPET","relationship_type":"CONTAINS","extra":"Source file contains code snippet: 35-40","gmt_create":"2026-04-23T15:19:45.655814+08:00","gmt_modified":"2026-04-23T15:19:45.655814+08:00"},{"id":167,"source_id":"b74caccb06844efcdb14d8324cff65c2","target_id":"acd5a29be2bdd4ae251e10ca266ffe13","source_type":"SOURCE_FILE","target_type":"CODE_SNIPPET","relationship_type":"CONTAINS","extra":"Source file contains code snippet: 43-48","gmt_create":"2026-04-23T15:19:45.657941+08:00","gmt_modified":"2026-04-23T15:19:45.657942+08:00"},{"id":169,"source_id":"b4a81ef789630d0af6a8d50859d01bf3","target_id":"27a5e2dd1d197b2e3a45be41c57a6183","source_type":"SOURCE_FILE","target_type":"CODE_SNIPPET","relationship_type":"CONTAINS","extra":"Source file contains code snippet: 35","gmt_create":"2026-04-23T15:19:45.658966+08:00","gmt_modified":"2026-04-23T15:19:45.658966+08:00"},{"id":171,"source_id":"069738f21ac2da7349d22683e8c36929","target_id":"c43e8fc0c04c5ed2db7798d99c8c77b8","source_type":"SOURCE_FILE","target_type":"CODE_SNIPPET","relationship_type":"CONTAINS","extra":"Source file contains code snippet: 34","gmt_create":"2026-04-23T15:19:45.659763+08:00","gmt_modified":"2026-04-23T15:19:45.659763+08:00"},{"id":173,"source_id":"93022c8938ce318f167277cfa65c29a7","target_id":"8868ab86034eecf40e80347ef8cbdebd","source_type":"SOURCE_FILE","target_type":"CODE_SNIPPET","relationship_type":"CONTAINS","extra":"Source file contains code snippet: 26-30","gmt_create":"2026-04-23T15:19:45.660491+08:00","gmt_modified":"2026-04-23T15:19:45.660491+08:00"},{"id":175,"source_id":"88d22de3b2a7419868e8ae19130d860c","target_id":"a50f983ec39bac67dff5df80f6dad837","source_type":"SOURCE_FILE","target_type":"CODE_SNIPPET","relationship_type":"CONTAINS","extra":"Source file contains code snippet: 59-60","gmt_create":"2026-04-23T15:19:45.661271+08:00","gmt_modified":"2026-04-23T15:19:45.661271+08:00"},{"id":177,"source_id":"7538ffe4902ab6041adb28b19844962a","target_id":"55f1628f1ab6f323710e367e12146b1a","source_type":"SOURCE_FILE","target_type":"CODE_SNIPPET","relationship_type":"CONTAINS","extra":"Source file contains code snippet: 67-71","gmt_create":"2026-04-23T15:19:45.662055+08:00","gmt_modified":"2026-04-23T15:19:45.662055+08:00"},{"id":179,"source_id":"58901c94d975d87e652a4dc6c8dda656","target_id":"6ef6d32f97d7b50b7a4da541137423c0","source_type":"SOURCE_FILE","target_type":"CODE_SNIPPET","relationship_type":"CONTAINS","extra":"Source file contains code snippet: 23-27","gmt_create":"2026-04-23T15:19:45.662999+08:00","gmt_modified":"2026-04-23T15:19:45.662999+08:00"},{"id":180,"source_id":"deb919cc-9541-4ed7-a581-ae2876ea67c2","target_id":"5cbb1e3f112aeba62a14b0b8999fc0f5","source_type":"WIKI_ITEM","target_type":"SOURCE_FILE","relationship_type":"REFERENCED_BY","extra":"Wiki references source file: backend/app/workers/scheduler.py","gmt_create":"2026-04-23T15:20:08.989793+08:00","gmt_modified":"2026-04-23T15:20:08.989793+08:00"},{"id":181,"source_id":"deb919cc-9541-4ed7-a581-ae2876ea67c2","target_id":"74040de652d5e57f548bb5c4adc3e1a0","source_type":"WIKI_ITEM","target_type":"SOURCE_FILE","relationship_type":"REFERENCED_BY","extra":"Wiki references source file: backend/app/workers/citation_engine.py","gmt_create":"2026-04-23T15:20:08.990186+08:00","gmt_modified":"2026-04-23T15:20:08.990186+08:00"},{"id":182,"source_id":"deb919cc-9541-4ed7-a581-ae2876ea67c2","target_id":"8f973791233c698b3e64a4fb28a93d4b","source_type":"WIKI_ITEM","target_type":"SOURCE_FILE","relationship_type":"REFERENCED_BY","extra":"Wiki references source file: backend/app/workers/platforms/kimi.py","gmt_create":"2026-04-23T15:20:08.990539+08:00","gmt_modified":"2026-04-23T15:20:08.990539+08:00"},{"id":183,"source_id":"deb919cc-9541-4ed7-a581-ae2876ea67c2","target_id":"f642fc1c2f34e15572d9d98aa6c18813","source_type":"WIKI_ITEM","target_type":"SOURCE_FILE","relationship_type":"REFERENCED_BY","extra":"Wiki references source file: backend/app/workers/platforms/wenxin.py","gmt_create":"2026-04-23T15:20:08.990851+08:00","gmt_modified":"2026-04-23T15:20:08.990851+08:00"},{"id":184,"source_id":"deb919cc-9541-4ed7-a581-ae2876ea67c2","target_id":"a16cf42e9559523c4f96ca4c79f9488d","source_type":"WIKI_ITEM","target_type":"SOURCE_FILE","relationship_type":"REFERENCED_BY","extra":"Wiki references source file: backend/app/workers/platforms/base.py","gmt_create":"2026-04-23T15:20:08.991166+08:00","gmt_modified":"2026-04-23T15:20:08.991166+08:00"},{"id":185,"source_id":"deb919cc-9541-4ed7-a581-ae2876ea67c2","target_id":"b74caccb06844efcdb14d8324cff65c2","source_type":"WIKI_ITEM","target_type":"SOURCE_FILE","relationship_type":"REFERENCED_BY","extra":"Wiki references source file: backend/app/models/query.py","gmt_create":"2026-04-23T15:20:08.991471+08:00","gmt_modified":"2026-04-23T15:20:08.991472+08:00"},{"id":186,"source_id":"deb919cc-9541-4ed7-a581-ae2876ea67c2","target_id":"069738f21ac2da7349d22683e8c36929","source_type":"WIKI_ITEM","target_type":"SOURCE_FILE","relationship_type":"REFERENCED_BY","extra":"Wiki references source file: backend/app/models/query_task.py","gmt_create":"2026-04-23T15:20:08.991772+08:00","gmt_modified":"2026-04-23T15:20:08.991772+08:00"},{"id":187,"source_id":"deb919cc-9541-4ed7-a581-ae2876ea67c2","target_id":"b4a81ef789630d0af6a8d50859d01bf3","source_type":"WIKI_ITEM","target_type":"SOURCE_FILE","relationship_type":"REFERENCED_BY","extra":"Wiki references source file: backend/app/models/citation_record.py","gmt_create":"2026-04-23T15:20:08.992186+08:00","gmt_modified":"2026-04-23T15:20:08.992186+08:00"},{"id":188,"source_id":"deb919cc-9541-4ed7-a581-ae2876ea67c2","target_id":"88d22de3b2a7419868e8ae19130d860c","source_type":"WIKI_ITEM","target_type":"SOURCE_FILE","relationship_type":"REFERENCED_BY","extra":"Wiki references source file: backend/app/services/query.py","gmt_create":"2026-04-23T15:20:08.992542+08:00","gmt_modified":"2026-04-23T15:20:08.992542+08:00"},{"id":189,"source_id":"deb919cc-9541-4ed7-a581-ae2876ea67c2","target_id":"6b3d903205941aa9391dd90016e1102c","source_type":"WIKI_ITEM","target_type":"SOURCE_FILE","relationship_type":"REFERENCED_BY","extra":"Wiki references source file: backend/app/api/queries.py","gmt_create":"2026-04-23T15:20:08.992879+08:00","gmt_modified":"2026-04-23T15:20:08.992879+08:00"},{"id":190,"source_id":"deb919cc-9541-4ed7-a581-ae2876ea67c2","target_id":"b0c428683c8a3e6922d90ca0d8c2736d","source_type":"WIKI_ITEM","target_type":"SOURCE_FILE","relationship_type":"REFERENCED_BY","extra":"Wiki references source file: backend/app/database.py","gmt_create":"2026-04-23T15:20:08.997487+08:00","gmt_modified":"2026-04-23T15:20:08.997487+08:00"},{"id":191,"source_id":"deb919cc-9541-4ed7-a581-ae2876ea67c2","target_id":"9ff19022ef915615911280e3c49ed44b","source_type":"WIKI_ITEM","target_type":"SOURCE_FILE","relationship_type":"REFERENCED_BY","extra":"Wiki references source file: backend/app/config.py","gmt_create":"2026-04-23T15:20:08.998695+08:00","gmt_modified":"2026-04-23T15:20:08.998696+08:00"},{"id":192,"source_id":"deb919cc-9541-4ed7-a581-ae2876ea67c2","target_id":"9228ff67d4c757a85d9421b71f4b29f5","source_type":"WIKI_ITEM","target_type":"SOURCE_FILE","relationship_type":"REFERENCED_BY","extra":"Wiki references source file: backend/app/main.py","gmt_create":"2026-04-23T15:20:08.999402+08:00","gmt_modified":"2026-04-23T15:20:08.999402+08:00"},{"id":193,"source_id":"deb919cc-9541-4ed7-a581-ae2876ea67c2","target_id":"b2f0d46a31a5441594f2e777365fc156","source_type":"WIKI_ITEM","target_type":"SOURCE_FILE","relationship_type":"REFERENCED_BY","extra":"Wiki references source file: tests/test_scheduler.py","gmt_create":"2026-04-23T15:20:09.000067+08:00","gmt_modified":"2026-04-23T15:20:09.000067+08:00"},{"id":194,"source_id":"deb919cc-9541-4ed7-a581-ae2876ea67c2","target_id":"0613e76b9679be7f998fb8fd8056e686","source_type":"WIKI_ITEM","target_type":"SOURCE_FILE","relationship_type":"REFERENCED_BY","extra":"Wiki references source file: tests/test_queries.py","gmt_create":"2026-04-23T15:20:09.000413+08:00","gmt_modified":"2026-04-23T15:20:09.000413+08:00"},{"id":195,"source_id":"deb919cc-9541-4ed7-a581-ae2876ea67c2","target_id":"096856da621e23e78422a15e2bfce1f1","source_type":"WIKI_ITEM","target_type":"CODE_SNIPPET","relationship_type":"CONTAINS","extra":"Wiki contains code snippet: backend/app/main.py#13-22","gmt_create":"2026-04-23T15:20:09.000893+08:00","gmt_modified":"2026-04-23T15:20:09.000893+08:00"},{"id":196,"source_id":"9228ff67d4c757a85d9421b71f4b29f5","target_id":"096856da621e23e78422a15e2bfce1f1","source_type":"SOURCE_FILE","target_type":"CODE_SNIPPET","relationship_type":"CONTAINS","extra":"Source file contains code snippet: 13-22","gmt_create":"2026-04-23T15:20:09.00176+08:00","gmt_modified":"2026-04-23T15:20:09.00176+08:00"},{"id":197,"source_id":"deb919cc-9541-4ed7-a581-ae2876ea67c2","target_id":"e230904202fcf7a861c6f49b84f9f863","source_type":"WIKI_ITEM","target_type":"CODE_SNIPPET","relationship_type":"CONTAINS","extra":"Wiki contains code snippet: backend/app/workers/scheduler.py#25-95","gmt_create":"2026-04-23T15:20:09.003004+08:00","gmt_modified":"2026-04-23T15:20:09.003004+08:00"},{"id":198,"source_id":"5cbb1e3f112aeba62a14b0b8999fc0f5","target_id":"e230904202fcf7a861c6f49b84f9f863","source_type":"SOURCE_FILE","target_type":"CODE_SNIPPET","relationship_type":"CONTAINS","extra":"Source file contains code snippet: 25-95","gmt_create":"2026-04-23T15:20:09.003771+08:00","gmt_modified":"2026-04-23T15:20:09.003771+08:00"},{"id":199,"source_id":"deb919cc-9541-4ed7-a581-ae2876ea67c2","target_id":"309607c54b12a6340edc086ffb4737c9","source_type":"WIKI_ITEM","target_type":"CODE_SNIPPET","relationship_type":"CONTAINS","extra":"Wiki contains code snippet: backend/app/workers/citation_engine.py#148-309","gmt_create":"2026-04-23T15:20:09.005186+08:00","gmt_modified":"2026-04-23T15:20:09.005186+08:00"},{"id":200,"source_id":"74040de652d5e57f548bb5c4adc3e1a0","target_id":"309607c54b12a6340edc086ffb4737c9","source_type":"SOURCE_FILE","target_type":"CODE_SNIPPET","relationship_type":"CONTAINS","extra":"Source file contains code snippet: 148-309","gmt_create":"2026-04-23T15:20:09.00622+08:00","gmt_modified":"2026-04-23T15:20:09.00622+08:00"},{"id":201,"source_id":"deb919cc-9541-4ed7-a581-ae2876ea67c2","target_id":"4fb8856be3a581fe8303d11b2284ca29","source_type":"WIKI_ITEM","target_type":"CODE_SNIPPET","relationship_type":"CONTAINS","extra":"Wiki contains code snippet: backend/app/models/query.py#11-55","gmt_create":"2026-04-23T15:20:09.006997+08:00","gmt_modified":"2026-04-23T15:20:09.006997+08:00"},{"id":202,"source_id":"deb919cc-9541-4ed7-a581-ae2876ea67c2","target_id":"b84f46f058847733347974841f613688","source_type":"WIKI_ITEM","target_type":"CODE_SNIPPET","relationship_type":"CONTAINS","extra":"Wiki contains code snippet: backend/app/models/query_task.py#11-39","gmt_create":"2026-04-23T15:20:09.007995+08:00","gmt_modified":"2026-04-23T15:20:09.007995+08:00"},{"id":203,"source_id":"deb919cc-9541-4ed7-a581-ae2876ea67c2","target_id":"fd541971cebf8a7c167d717f5c5d1ff6","source_type":"WIKI_ITEM","target_type":"CODE_SNIPPET","relationship_type":"CONTAINS","extra":"Wiki contains code snippet: backend/app/models/citation_record.py#11-42","gmt_create":"2026-04-23T15:20:09.009222+08:00","gmt_modified":"2026-04-23T15:20:09.009222+08:00"},{"id":204,"source_id":"deb919cc-9541-4ed7-a581-ae2876ea67c2","target_id":"d7c319a04abbc6704da53107e07dd8e7","source_type":"WIKI_ITEM","target_type":"CODE_SNIPPET","relationship_type":"CONTAINS","extra":"Wiki contains code snippet: backend/app/services/query.py#12-130","gmt_create":"2026-04-23T15:20:09.010245+08:00","gmt_modified":"2026-04-23T15:20:09.010245+08:00"},{"id":205,"source_id":"88d22de3b2a7419868e8ae19130d860c","target_id":"d7c319a04abbc6704da53107e07dd8e7","source_type":"SOURCE_FILE","target_type":"CODE_SNIPPET","relationship_type":"CONTAINS","extra":"Source file contains code snippet: 12-130","gmt_create":"2026-04-23T15:20:09.011044+08:00","gmt_modified":"2026-04-23T15:20:09.011044+08:00"},{"id":206,"source_id":"deb919cc-9541-4ed7-a581-ae2876ea67c2","target_id":"9bfc041fe426da2eb78353827e8d9163","source_type":"WIKI_ITEM","target_type":"CODE_SNIPPET","relationship_type":"CONTAINS","extra":"Wiki contains code snippet: backend/app/database.py#1-29","gmt_create":"2026-04-23T15:20:09.012195+08:00","gmt_modified":"2026-04-23T15:20:09.012195+08:00"},{"id":207,"source_id":"b0c428683c8a3e6922d90ca0d8c2736d","target_id":"9bfc041fe426da2eb78353827e8d9163","source_type":"SOURCE_FILE","target_type":"CODE_SNIPPET","relationship_type":"CONTAINS","extra":"Source file contains code snippet: 1-29","gmt_create":"2026-04-23T15:20:09.01291+08:00","gmt_modified":"2026-04-23T15:20:09.012911+08:00"},{"id":208,"source_id":"deb919cc-9541-4ed7-a581-ae2876ea67c2","target_id":"ad67863041d9eea2b0fb542b5aa33aca","source_type":"WIKI_ITEM","target_type":"CODE_SNIPPET","relationship_type":"CONTAINS","extra":"Wiki contains code snippet: backend/app/workers/platforms/base.py#4-18","gmt_create":"2026-04-23T15:20:09.013886+08:00","gmt_modified":"2026-04-23T15:20:09.013886+08:00"},{"id":209,"source_id":"a16cf42e9559523c4f96ca4c79f9488d","target_id":"ad67863041d9eea2b0fb542b5aa33aca","source_type":"SOURCE_FILE","target_type":"CODE_SNIPPET","relationship_type":"CONTAINS","extra":"Source file contains code snippet: 4-18","gmt_create":"2026-04-23T15:20:09.014746+08:00","gmt_modified":"2026-04-23T15:20:09.014746+08:00"},{"id":210,"source_id":"deb919cc-9541-4ed7-a581-ae2876ea67c2","target_id":"eecf9581dbaa0a515cf11514175e7ef9","source_type":"WIKI_ITEM","target_type":"CODE_SNIPPET","relationship_type":"CONTAINS","extra":"Wiki contains code snippet: backend/app/workers/platforms/kimi.py#11-206","gmt_create":"2026-04-23T15:20:09.015594+08:00","gmt_modified":"2026-04-23T15:20:09.015594+08:00"},{"id":211,"source_id":"8f973791233c698b3e64a4fb28a93d4b","target_id":"eecf9581dbaa0a515cf11514175e7ef9","source_type":"SOURCE_FILE","target_type":"CODE_SNIPPET","relationship_type":"CONTAINS","extra":"Source file contains code snippet: 11-206","gmt_create":"2026-04-23T15:20:09.016313+08:00","gmt_modified":"2026-04-23T15:20:09.016313+08:00"},{"id":212,"source_id":"deb919cc-9541-4ed7-a581-ae2876ea67c2","target_id":"5563c29185326a59be61ee0a6eec4463","source_type":"WIKI_ITEM","target_type":"CODE_SNIPPET","relationship_type":"CONTAINS","extra":"Wiki contains code snippet: backend/app/workers/platforms/wenxin.py#11-205","gmt_create":"2026-04-23T15:20:09.017693+08:00","gmt_modified":"2026-04-23T15:20:09.017693+08:00"},{"id":213,"source_id":"f642fc1c2f34e15572d9d98aa6c18813","target_id":"5563c29185326a59be61ee0a6eec4463","source_type":"SOURCE_FILE","target_type":"CODE_SNIPPET","relationship_type":"CONTAINS","extra":"Source file contains code snippet: 11-205","gmt_create":"2026-04-23T15:20:09.018896+08:00","gmt_modified":"2026-04-23T15:20:09.018896+08:00"},{"id":214,"source_id":"deb919cc-9541-4ed7-a581-ae2876ea67c2","target_id":"2d35e1345d25020f8e7ac1318db06f7b","source_type":"WIKI_ITEM","target_type":"CODE_SNIPPET","relationship_type":"CONTAINS","extra":"Wiki contains code snippet: backend/app/workers/scheduler.py#30-90","gmt_create":"2026-04-23T15:20:09.025147+08:00","gmt_modified":"2026-04-23T15:20:09.025147+08:00"},{"id":215,"source_id":"5cbb1e3f112aeba62a14b0b8999fc0f5","target_id":"2d35e1345d25020f8e7ac1318db06f7b","source_type":"SOURCE_FILE","target_type":"CODE_SNIPPET","relationship_type":"CONTAINS","extra":"Source file contains code snippet: 30-90","gmt_create":"2026-04-23T15:20:09.02579+08:00","gmt_modified":"2026-04-23T15:20:09.02579+08:00"},{"id":216,"source_id":"deb919cc-9541-4ed7-a581-ae2876ea67c2","target_id":"91bda120c0ab69e0e7103a1c89c82424","source_type":"WIKI_ITEM","target_type":"CODE_SNIPPET","relationship_type":"CONTAINS","extra":"Wiki contains code snippet: backend/app/workers/scheduler.py#95-172","gmt_create":"2026-04-23T15:20:09.026853+08:00","gmt_modified":"2026-04-23T15:20:09.026853+08:00"},{"id":217,"source_id":"5cbb1e3f112aeba62a14b0b8999fc0f5","target_id":"91bda120c0ab69e0e7103a1c89c82424","source_type":"SOURCE_FILE","target_type":"CODE_SNIPPET","relationship_type":"CONTAINS","extra":"Source file contains code snippet: 95-172","gmt_create":"2026-04-23T15:20:09.027566+08:00","gmt_modified":"2026-04-23T15:20:09.027566+08:00"},{"id":218,"source_id":"deb919cc-9541-4ed7-a581-ae2876ea67c2","target_id":"160b5326537d25444c40a459a01e79c6","source_type":"WIKI_ITEM","target_type":"CODE_SNIPPET","relationship_type":"CONTAINS","extra":"Wiki contains code snippet: backend/app/workers/citation_engine.py#159-234","gmt_create":"2026-04-23T15:20:09.028202+08:00","gmt_modified":"2026-04-23T15:20:09.028202+08:00"},{"id":219,"source_id":"74040de652d5e57f548bb5c4adc3e1a0","target_id":"160b5326537d25444c40a459a01e79c6","source_type":"SOURCE_FILE","target_type":"CODE_SNIPPET","relationship_type":"CONTAINS","extra":"Source file contains code snippet: 159-234","gmt_create":"2026-04-23T15:20:09.028744+08:00","gmt_modified":"2026-04-23T15:20:09.028744+08:00"},{"id":220,"source_id":"deb919cc-9541-4ed7-a581-ae2876ea67c2","target_id":"6712051c987e10a7c26b089063367398","source_type":"WIKI_ITEM","target_type":"CODE_SNIPPET","relationship_type":"CONTAINS","extra":"Wiki contains code snippet: backend/app/models/query.py#24-31","gmt_create":"2026-04-23T15:20:09.029494+08:00","gmt_modified":"2026-04-23T15:20:09.029494+08:00"},{"id":221,"source_id":"b74caccb06844efcdb14d8324cff65c2","target_id":"6712051c987e10a7c26b089063367398","source_type":"SOURCE_FILE","target_type":"CODE_SNIPPET","relationship_type":"CONTAINS","extra":"Source file contains code snippet: 24-31","gmt_create":"2026-04-23T15:20:09.030084+08:00","gmt_modified":"2026-04-23T15:20:09.030084+08:00"},{"id":222,"source_id":"deb919cc-9541-4ed7-a581-ae2876ea67c2","target_id":"ac5982063da5f04315f3e82a0d653902","source_type":"WIKI_ITEM","target_type":"CODE_SNIPPET","relationship_type":"CONTAINS","extra":"Wiki contains code snippet: backend/app/models/query_task.py#24-32","gmt_create":"2026-04-23T15:20:09.030828+08:00","gmt_modified":"2026-04-23T15:20:09.030828+08:00"},{"id":223,"source_id":"069738f21ac2da7349d22683e8c36929","target_id":"ac5982063da5f04315f3e82a0d653902","source_type":"SOURCE_FILE","target_type":"CODE_SNIPPET","relationship_type":"CONTAINS","extra":"Source file contains code snippet: 24-32","gmt_create":"2026-04-23T15:20:09.031632+08:00","gmt_modified":"2026-04-23T15:20:09.031632+08:00"},{"id":224,"source_id":"deb919cc-9541-4ed7-a581-ae2876ea67c2","target_id":"06ed912983db33bb8aca162fed68282b","source_type":"WIKI_ITEM","target_type":"CODE_SNIPPET","relationship_type":"CONTAINS","extra":"Wiki contains code snippet: backend/app/models/citation_record.py#24-29","gmt_create":"2026-04-23T15:20:09.032417+08:00","gmt_modified":"2026-04-23T15:20:09.032417+08:00"},{"id":225,"source_id":"b4a81ef789630d0af6a8d50859d01bf3","target_id":"06ed912983db33bb8aca162fed68282b","source_type":"SOURCE_FILE","target_type":"CODE_SNIPPET","relationship_type":"CONTAINS","extra":"Source file contains code snippet: 24-29","gmt_create":"2026-04-23T15:20:09.032976+08:00","gmt_modified":"2026-04-23T15:20:09.032976+08:00"},{"id":226,"source_id":"deb919cc-9541-4ed7-a581-ae2876ea67c2","target_id":"b624be78e3bffd876e403cff2557b088","source_type":"WIKI_ITEM","target_type":"CODE_SNIPPET","relationship_type":"CONTAINS","extra":"Wiki contains code snippet: backend/app/workers/citation_engine.py#19-120","gmt_create":"2026-04-23T15:20:09.037331+08:00","gmt_modified":"2026-04-23T15:20:09.037331+08:00"},{"id":227,"source_id":"74040de652d5e57f548bb5c4adc3e1a0","target_id":"b624be78e3bffd876e403cff2557b088","source_type":"SOURCE_FILE","target_type":"CODE_SNIPPET","relationship_type":"CONTAINS","extra":"Source file contains code snippet: 19-120","gmt_create":"2026-04-23T15:20:09.038413+08:00","gmt_modified":"2026-04-23T15:20:09.038413+08:00"},{"id":228,"source_id":"deb919cc-9541-4ed7-a581-ae2876ea67c2","target_id":"40d0b169aad65c8bb38077deb052fc72","source_type":"WIKI_ITEM","target_type":"CODE_SNIPPET","relationship_type":"CONTAINS","extra":"Wiki contains code snippet: backend/app/workers/platforms/kimi.py#33-125","gmt_create":"2026-04-23T15:20:09.040261+08:00","gmt_modified":"2026-04-23T15:20:09.040261+08:00"},{"id":229,"source_id":"8f973791233c698b3e64a4fb28a93d4b","target_id":"40d0b169aad65c8bb38077deb052fc72","source_type":"SOURCE_FILE","target_type":"CODE_SNIPPET","relationship_type":"CONTAINS","extra":"Source file contains code snippet: 33-125","gmt_create":"2026-04-23T15:20:09.04098+08:00","gmt_modified":"2026-04-23T15:20:09.04098+08:00"},{"id":230,"source_id":"deb919cc-9541-4ed7-a581-ae2876ea67c2","target_id":"8b5af998852596e1e08b0e0216bc4b93","source_type":"WIKI_ITEM","target_type":"CODE_SNIPPET","relationship_type":"CONTAINS","extra":"Wiki contains code snippet: backend/app/workers/platforms/wenxin.py#33-124","gmt_create":"2026-04-23T15:20:09.041526+08:00","gmt_modified":"2026-04-23T15:20:09.041526+08:00"},{"id":231,"source_id":"f642fc1c2f34e15572d9d98aa6c18813","target_id":"8b5af998852596e1e08b0e0216bc4b93","source_type":"SOURCE_FILE","target_type":"CODE_SNIPPET","relationship_type":"CONTAINS","extra":"Source file contains code snippet: 33-124","gmt_create":"2026-04-23T15:20:09.041834+08:00","gmt_modified":"2026-04-23T15:20:09.041834+08:00"},{"id":232,"source_id":"deb919cc-9541-4ed7-a581-ae2876ea67c2","target_id":"fe70b1fef9f36e73d26d84987e927c7a","source_type":"WIKI_ITEM","target_type":"CODE_SNIPPET","relationship_type":"CONTAINS","extra":"Wiki contains code snippet: backend/app/api/queries.py#15-86","gmt_create":"2026-04-23T15:20:09.04598+08:00","gmt_modified":"2026-04-23T15:20:09.04598+08:00"},{"id":233,"source_id":"6b3d903205941aa9391dd90016e1102c","target_id":"fe70b1fef9f36e73d26d84987e927c7a","source_type":"SOURCE_FILE","target_type":"CODE_SNIPPET","relationship_type":"CONTAINS","extra":"Source file contains code snippet: 15-86","gmt_create":"2026-04-23T15:20:09.046352+08:00","gmt_modified":"2026-04-23T15:20:09.046352+08:00"},{"id":234,"source_id":"deb919cc-9541-4ed7-a581-ae2876ea67c2","target_id":"e1d2b027678118df4d0a50ce9269271d","source_type":"WIKI_ITEM","target_type":"CODE_SNIPPET","relationship_type":"CONTAINS","extra":"Wiki contains code snippet: backend/app/workers/scheduler.py#42-90","gmt_create":"2026-04-23T15:20:09.050041+08:00","gmt_modified":"2026-04-23T15:20:09.050041+08:00"},{"id":235,"source_id":"5cbb1e3f112aeba62a14b0b8999fc0f5","target_id":"e1d2b027678118df4d0a50ce9269271d","source_type":"SOURCE_FILE","target_type":"CODE_SNIPPET","relationship_type":"CONTAINS","extra":"Source file contains code snippet: 42-90","gmt_create":"2026-04-23T15:20:09.050351+08:00","gmt_modified":"2026-04-23T15:20:09.050351+08:00"},{"id":236,"source_id":"deb919cc-9541-4ed7-a581-ae2876ea67c2","target_id":"e79301a4bc26aa6b49f3f52c3182c3f9","source_type":"WIKI_ITEM","target_type":"CODE_SNIPPET","relationship_type":"CONTAINS","extra":"Wiki contains code snippet: backend/app/workers/citation_engine.py#175-234","gmt_create":"2026-04-23T15:20:09.051815+08:00","gmt_modified":"2026-04-23T15:20:09.051815+08:00"},{"id":237,"source_id":"74040de652d5e57f548bb5c4adc3e1a0","target_id":"e79301a4bc26aa6b49f3f52c3182c3f9","source_type":"SOURCE_FILE","target_type":"CODE_SNIPPET","relationship_type":"CONTAINS","extra":"Source file contains code snippet: 175-234","gmt_create":"2026-04-23T15:20:09.052165+08:00","gmt_modified":"2026-04-23T15:20:09.052166+08:00"},{"id":238,"source_id":"deb919cc-9541-4ed7-a581-ae2876ea67c2","target_id":"1e85186eded8743ff5f231df4aa6df3f","source_type":"WIKI_ITEM","target_type":"CODE_SNIPPET","relationship_type":"CONTAINS","extra":"Wiki contains code snippet: backend/app/workers/platforms/kimi.py#21-48","gmt_create":"2026-04-23T15:20:09.052615+08:00","gmt_modified":"2026-04-23T15:20:09.052615+08:00"},{"id":239,"source_id":"8f973791233c698b3e64a4fb28a93d4b","target_id":"1e85186eded8743ff5f231df4aa6df3f","source_type":"SOURCE_FILE","target_type":"CODE_SNIPPET","relationship_type":"CONTAINS","extra":"Source file contains code snippet: 21-48","gmt_create":"2026-04-23T15:20:09.052947+08:00","gmt_modified":"2026-04-23T15:20:09.052947+08:00"},{"id":240,"source_id":"deb919cc-9541-4ed7-a581-ae2876ea67c2","target_id":"e2b1718570fb714b2f4342221898ab30","source_type":"WIKI_ITEM","target_type":"CODE_SNIPPET","relationship_type":"CONTAINS","extra":"Wiki contains code snippet: backend/app/workers/platforms/wenxin.py#21-48","gmt_create":"2026-04-23T15:20:09.053449+08:00","gmt_modified":"2026-04-23T15:20:09.053449+08:00"},{"id":241,"source_id":"f642fc1c2f34e15572d9d98aa6c18813","target_id":"e2b1718570fb714b2f4342221898ab30","source_type":"SOURCE_FILE","target_type":"CODE_SNIPPET","relationship_type":"CONTAINS","extra":"Source file contains code snippet: 21-48","gmt_create":"2026-04-23T15:20:09.053892+08:00","gmt_modified":"2026-04-23T15:20:09.053892+08:00"},{"id":242,"source_id":"deb919cc-9541-4ed7-a581-ae2876ea67c2","target_id":"e4a49039dae40b7433896c81737fcf8c","source_type":"WIKI_ITEM","target_type":"CODE_SNIPPET","relationship_type":"CONTAINS","extra":"Wiki contains code snippet: backend/app/config.py#7-14","gmt_create":"2026-04-23T15:20:09.05437+08:00","gmt_modified":"2026-04-23T15:20:09.05437+08:00"},{"id":243,"source_id":"9ff19022ef915615911280e3c49ed44b","target_id":"e4a49039dae40b7433896c81737fcf8c","source_type":"SOURCE_FILE","target_type":"CODE_SNIPPET","relationship_type":"CONTAINS","extra":"Source file contains code snippet: 7-14","gmt_create":"2026-04-23T15:20:09.054841+08:00","gmt_modified":"2026-04-23T15:20:09.054841+08:00"},{"id":244,"source_id":"deb919cc-9541-4ed7-a581-ae2876ea67c2","target_id":"2ee31d68c409e96e951f6cfa7027bca7","source_type":"WIKI_ITEM","target_type":"CODE_SNIPPET","relationship_type":"CONTAINS","extra":"Wiki contains code snippet: backend/app/main.py#24-42","gmt_create":"2026-04-23T15:20:09.055328+08:00","gmt_modified":"2026-04-23T15:20:09.055328+08:00"},{"id":245,"source_id":"9228ff67d4c757a85d9421b71f4b29f5","target_id":"2ee31d68c409e96e951f6cfa7027bca7","source_type":"SOURCE_FILE","target_type":"CODE_SNIPPET","relationship_type":"CONTAINS","extra":"Source file contains code snippet: 24-42","gmt_create":"2026-04-23T15:20:09.055781+08:00","gmt_modified":"2026-04-23T15:20:09.055781+08:00"},{"id":246,"source_id":"deb919cc-9541-4ed7-a581-ae2876ea67c2","target_id":"79d6e169e36e6b7493898b5f863e07dc","source_type":"WIKI_ITEM","target_type":"CODE_SNIPPET","relationship_type":"CONTAINS","extra":"Wiki contains code snippet: backend/app/workers/citation_engine.py#152-157","gmt_create":"2026-04-23T15:20:09.056898+08:00","gmt_modified":"2026-04-23T15:20:09.056898+08:00"},{"id":247,"source_id":"74040de652d5e57f548bb5c4adc3e1a0","target_id":"79d6e169e36e6b7493898b5f863e07dc","source_type":"SOURCE_FILE","target_type":"CODE_SNIPPET","relationship_type":"CONTAINS","extra":"Source file contains code snippet: 152-157","gmt_create":"2026-04-23T15:20:09.057188+08:00","gmt_modified":"2026-04-23T15:20:09.057188+08:00"},{"id":248,"source_id":"deb919cc-9541-4ed7-a581-ae2876ea67c2","target_id":"1552315d5fb9f6d7aba5f7e8fa93a975","source_type":"WIKI_ITEM","target_type":"CODE_SNIPPET","relationship_type":"CONTAINS","extra":"Wiki contains code snippet: backend/app/database.py#6-10","gmt_create":"2026-04-23T15:20:09.058217+08:00","gmt_modified":"2026-04-23T15:20:09.058217+08:00"},{"id":249,"source_id":"b0c428683c8a3e6922d90ca0d8c2736d","target_id":"1552315d5fb9f6d7aba5f7e8fa93a975","source_type":"SOURCE_FILE","target_type":"CODE_SNIPPET","relationship_type":"CONTAINS","extra":"Source file contains code snippet: 6-10","gmt_create":"2026-04-23T15:20:09.058503+08:00","gmt_modified":"2026-04-23T15:20:09.058503+08:00"},{"id":250,"source_id":"deb919cc-9541-4ed7-a581-ae2876ea67c2","target_id":"599cca7536cae4a7e0ae93043c476a7f","source_type":"WIKI_ITEM","target_type":"CODE_SNIPPET","relationship_type":"CONTAINS","extra":"Wiki contains code snippet: tests/test_queries.py#10-154","gmt_create":"2026-04-23T15:20:09.058947+08:00","gmt_modified":"2026-04-23T15:20:09.058947+08:00"},{"id":251,"source_id":"0613e76b9679be7f998fb8fd8056e686","target_id":"599cca7536cae4a7e0ae93043c476a7f","source_type":"SOURCE_FILE","target_type":"CODE_SNIPPET","relationship_type":"CONTAINS","extra":"Source file contains code snippet: 10-154","gmt_create":"2026-04-23T15:20:09.059242+08:00","gmt_modified":"2026-04-23T15:20:09.059242+08:00"},{"id":252,"source_id":"deb919cc-9541-4ed7-a581-ae2876ea67c2","target_id":"2ec3d45edd6221e0cedf7f8887fe090d","source_type":"WIKI_ITEM","target_type":"CODE_SNIPPET","relationship_type":"CONTAINS","extra":"Wiki contains code snippet: tests/test_scheduler.py#17-123","gmt_create":"2026-04-23T15:20:09.059776+08:00","gmt_modified":"2026-04-23T15:20:09.059776+08:00"},{"id":253,"source_id":"b2f0d46a31a5441594f2e777365fc156","target_id":"2ec3d45edd6221e0cedf7f8887fe090d","source_type":"SOURCE_FILE","target_type":"CODE_SNIPPET","relationship_type":"CONTAINS","extra":"Source file contains code snippet: 17-123","gmt_create":"2026-04-23T15:20:09.060064+08:00","gmt_modified":"2026-04-23T15:20:09.060064+08:00"},{"id":254,"source_id":"262a3941-fdc6-46b0-b767-be40aa9d5761","target_id":"99fe1b288fd41daa86c2dfbab819abf0","source_type":"WIKI_ITEM","target_type":"SOURCE_FILE","relationship_type":"REFERENCED_BY","extra":"Wiki references source file: backend/app/models/__init__.py","gmt_create":"2026-04-23T15:21:46.707277+08:00","gmt_modified":"2026-04-23T15:21:46.707277+08:00"},{"id":255,"source_id":"262a3941-fdc6-46b0-b767-be40aa9d5761","target_id":"c59f8c276697a070dffc581fe94d809c","source_type":"WIKI_ITEM","target_type":"SOURCE_FILE","relationship_type":"REFERENCED_BY","extra":"Wiki references source file: backend/app/models/user.py","gmt_create":"2026-04-23T15:21:46.707879+08:00","gmt_modified":"2026-04-23T15:21:46.707879+08:00"},{"id":256,"source_id":"262a3941-fdc6-46b0-b767-be40aa9d5761","target_id":"b74caccb06844efcdb14d8324cff65c2","source_type":"WIKI_ITEM","target_type":"SOURCE_FILE","relationship_type":"REFERENCED_BY","extra":"Wiki references source file: backend/app/models/query.py","gmt_create":"2026-04-23T15:21:46.708322+08:00","gmt_modified":"2026-04-23T15:21:46.708322+08:00"},{"id":257,"source_id":"262a3941-fdc6-46b0-b767-be40aa9d5761","target_id":"069738f21ac2da7349d22683e8c36929","source_type":"WIKI_ITEM","target_type":"SOURCE_FILE","relationship_type":"REFERENCED_BY","extra":"Wiki references source file: backend/app/models/query_task.py","gmt_create":"2026-04-23T15:21:46.708702+08:00","gmt_modified":"2026-04-23T15:21:46.708702+08:00"},{"id":258,"source_id":"262a3941-fdc6-46b0-b767-be40aa9d5761","target_id":"b4a81ef789630d0af6a8d50859d01bf3","source_type":"WIKI_ITEM","target_type":"SOURCE_FILE","relationship_type":"REFERENCED_BY","extra":"Wiki references source file: backend/app/models/citation_record.py","gmt_create":"2026-04-23T15:21:46.709093+08:00","gmt_modified":"2026-04-23T15:21:46.709093+08:00"},{"id":259,"source_id":"262a3941-fdc6-46b0-b767-be40aa9d5761","target_id":"bceca00463fe55d3bcafda728f97f723","source_type":"WIKI_ITEM","target_type":"SOURCE_FILE","relationship_type":"REFERENCED_BY","extra":"Wiki references source file: backend/app/models/subscription.py","gmt_create":"2026-04-23T15:21:46.709712+08:00","gmt_modified":"2026-04-23T15:21:46.709713+08:00"},{"id":260,"source_id":"262a3941-fdc6-46b0-b767-be40aa9d5761","target_id":"b0c428683c8a3e6922d90ca0d8c2736d","source_type":"WIKI_ITEM","target_type":"SOURCE_FILE","relationship_type":"REFERENCED_BY","extra":"Wiki references source file: backend/app/database.py","gmt_create":"2026-04-23T15:21:46.710101+08:00","gmt_modified":"2026-04-23T15:21:46.710101+08:00"},{"id":261,"source_id":"262a3941-fdc6-46b0-b767-be40aa9d5761","target_id":"d4f95fcf50683b5bf6167c7d2a6b126d","source_type":"WIKI_ITEM","target_type":"SOURCE_FILE","relationship_type":"REFERENCED_BY","extra":"Wiki references source file: backend/alembic/versions/488d0bd5ab01_initial_migration.py","gmt_create":"2026-04-23T15:21:46.710429+08:00","gmt_modified":"2026-04-23T15:21:46.710429+08:00"},{"id":262,"source_id":"262a3941-fdc6-46b0-b767-be40aa9d5761","target_id":"f301b79d833233ce39d350e82a71c938","source_type":"WIKI_ITEM","target_type":"SOURCE_FILE","relationship_type":"REFERENCED_BY","extra":"Wiki references source file: backend/app/schemas/query.py","gmt_create":"2026-04-23T15:21:46.710829+08:00","gmt_modified":"2026-04-23T15:21:46.710829+08:00"},{"id":263,"source_id":"262a3941-fdc6-46b0-b767-be40aa9d5761","target_id":"1a3336b4af8a39a055e912724338580c","source_type":"WIKI_ITEM","target_type":"SOURCE_FILE","relationship_type":"REFERENCED_BY","extra":"Wiki references source file: backend/app/schemas/citation.py","gmt_create":"2026-04-23T15:21:46.711181+08:00","gmt_modified":"2026-04-23T15:21:46.711181+08:00"},{"id":264,"source_id":"262a3941-fdc6-46b0-b767-be40aa9d5761","target_id":"88d22de3b2a7419868e8ae19130d860c","source_type":"WIKI_ITEM","target_type":"SOURCE_FILE","relationship_type":"REFERENCED_BY","extra":"Wiki references source file: backend/app/services/query.py","gmt_create":"2026-04-23T15:21:46.711568+08:00","gmt_modified":"2026-04-23T15:21:46.711568+08:00"},{"id":265,"source_id":"262a3941-fdc6-46b0-b767-be40aa9d5761","target_id":"6b3d903205941aa9391dd90016e1102c","source_type":"WIKI_ITEM","target_type":"SOURCE_FILE","relationship_type":"REFERENCED_BY","extra":"Wiki references source file: backend/app/api/queries.py","gmt_create":"2026-04-23T15:21:46.711965+08:00","gmt_modified":"2026-04-23T15:21:46.711965+08:00"},{"id":266,"source_id":"262a3941-fdc6-46b0-b767-be40aa9d5761","target_id":"04e3926c080e795713bff683e7dc9d3e","source_type":"WIKI_ITEM","target_type":"SOURCE_FILE","relationship_type":"REFERENCED_BY","extra":"Wiki references source file: backend/app/services/citation.py","gmt_create":"2026-04-23T15:21:46.712296+08:00","gmt_modified":"2026-04-23T15:21:46.712296+08:00"},{"id":267,"source_id":"262a3941-fdc6-46b0-b767-be40aa9d5761","target_id":"7538ffe4902ab6041adb28b19844962a","source_type":"WIKI_ITEM","target_type":"SOURCE_FILE","relationship_type":"REFERENCED_BY","extra":"Wiki references source file: backend/app/api/citations.py","gmt_create":"2026-04-23T15:21:46.712792+08:00","gmt_modified":"2026-04-23T15:21:46.712792+08:00"},{"id":268,"source_id":"262a3941-fdc6-46b0-b767-be40aa9d5761","target_id":"9ff19022ef915615911280e3c49ed44b","source_type":"WIKI_ITEM","target_type":"SOURCE_FILE","relationship_type":"REFERENCED_BY","extra":"Wiki references source file: backend/app/config.py","gmt_create":"2026-04-23T15:21:46.713121+08:00","gmt_modified":"2026-04-23T15:21:46.713121+08:00"},{"id":269,"source_id":"262a3941-fdc6-46b0-b767-be40aa9d5761","target_id":"9d08667997a868fc07c9b4e328e44224","source_type":"WIKI_ITEM","target_type":"SOURCE_FILE","relationship_type":"REFERENCED_BY","extra":"Wiki references source file: backend/app/api/deps.py","gmt_create":"2026-04-23T15:21:46.713538+08:00","gmt_modified":"2026-04-23T15:21:46.713538+08:00"},{"id":270,"source_id":"262a3941-fdc6-46b0-b767-be40aa9d5761","target_id":"56e46969bdb790a5e8f333184b878d6d","source_type":"WIKI_ITEM","target_type":"CODE_SNIPPET","relationship_type":"CONTAINS","extra":"Wiki contains code snippet: backend/app/models/user.py#11-41","gmt_create":"2026-04-23T15:21:46.71408+08:00","gmt_modified":"2026-04-23T15:21:46.71408+08:00"},{"id":271,"source_id":"262a3941-fdc6-46b0-b767-be40aa9d5761","target_id":"4fb8856be3a581fe8303d11b2284ca29","source_type":"WIKI_ITEM","target_type":"CODE_SNIPPET","relationship_type":"CONTAINS","extra":"Wiki contains code snippet: backend/app/models/query.py#11-55","gmt_create":"2026-04-23T15:21:46.714746+08:00","gmt_modified":"2026-04-23T15:21:46.714746+08:00"},{"id":272,"source_id":"262a3941-fdc6-46b0-b767-be40aa9d5761","target_id":"b84f46f058847733347974841f613688","source_type":"WIKI_ITEM","target_type":"CODE_SNIPPET","relationship_type":"CONTAINS","extra":"Wiki contains code snippet: backend/app/models/query_task.py#11-39","gmt_create":"2026-04-23T15:21:46.715399+08:00","gmt_modified":"2026-04-23T15:21:46.7154+08:00"},{"id":273,"source_id":"262a3941-fdc6-46b0-b767-be40aa9d5761","target_id":"fd541971cebf8a7c167d717f5c5d1ff6","source_type":"WIKI_ITEM","target_type":"CODE_SNIPPET","relationship_type":"CONTAINS","extra":"Wiki contains code snippet: backend/app/models/citation_record.py#11-42","gmt_create":"2026-04-23T15:21:46.716178+08:00","gmt_modified":"2026-04-23T15:21:46.716178+08:00"},{"id":274,"source_id":"262a3941-fdc6-46b0-b767-be40aa9d5761","target_id":"4d323bf0aaf4078f09726dc0890e5955","source_type":"WIKI_ITEM","target_type":"CODE_SNIPPET","relationship_type":"CONTAINS","extra":"Wiki contains code snippet: backend/app/models/subscription.py#11-37","gmt_create":"2026-04-23T15:21:46.717324+08:00","gmt_modified":"2026-04-23T15:21:46.717324+08:00"},{"id":275,"source_id":"bceca00463fe55d3bcafda728f97f723","target_id":"4d323bf0aaf4078f09726dc0890e5955","source_type":"SOURCE_FILE","target_type":"CODE_SNIPPET","relationship_type":"CONTAINS","extra":"Source file contains code snippet: 11-37","gmt_create":"2026-04-23T15:21:46.718049+08:00","gmt_modified":"2026-04-23T15:21:46.71805+08:00"},{"id":276,"source_id":"262a3941-fdc6-46b0-b767-be40aa9d5761","target_id":"9bfc041fe426da2eb78353827e8d9163","source_type":"WIKI_ITEM","target_type":"CODE_SNIPPET","relationship_type":"CONTAINS","extra":"Wiki contains code snippet: backend/app/database.py#1-29","gmt_create":"2026-04-23T15:21:46.718816+08:00","gmt_modified":"2026-04-23T15:21:46.718816+08:00"},{"id":277,"source_id":"262a3941-fdc6-46b0-b767-be40aa9d5761","target_id":"4cef9e740b6feb68c6bd22b660c47320","source_type":"WIKI_ITEM","target_type":"CODE_SNIPPET","relationship_type":"CONTAINS","extra":"Wiki contains code snippet: backend/app/services/query.py#1-123","gmt_create":"2026-04-23T15:21:46.719468+08:00","gmt_modified":"2026-04-23T15:21:46.719468+08:00"},{"id":278,"source_id":"88d22de3b2a7419868e8ae19130d860c","target_id":"4cef9e740b6feb68c6bd22b660c47320","source_type":"SOURCE_FILE","target_type":"CODE_SNIPPET","relationship_type":"CONTAINS","extra":"Source file contains code snippet: 1-123","gmt_create":"2026-04-23T15:21:46.720008+08:00","gmt_modified":"2026-04-23T15:21:46.720008+08:00"},{"id":279,"source_id":"262a3941-fdc6-46b0-b767-be40aa9d5761","target_id":"121203f7f9f539ffb1456c3f5cdfd842","source_type":"WIKI_ITEM","target_type":"CODE_SNIPPET","relationship_type":"CONTAINS","extra":"Wiki contains code snippet: backend/app/services/citation.py#1-359","gmt_create":"2026-04-23T15:21:46.720615+08:00","gmt_modified":"2026-04-23T15:21:46.720615+08:00"},{"id":280,"source_id":"04e3926c080e795713bff683e7dc9d3e","target_id":"121203f7f9f539ffb1456c3f5cdfd842","source_type":"SOURCE_FILE","target_type":"CODE_SNIPPET","relationship_type":"CONTAINS","extra":"Source file contains code snippet: 1-359","gmt_create":"2026-04-23T15:21:46.721095+08:00","gmt_modified":"2026-04-23T15:21:46.721095+08:00"},{"id":281,"source_id":"262a3941-fdc6-46b0-b767-be40aa9d5761","target_id":"10d1e37bdc9f353c189b7a2fe79dc85e","source_type":"WIKI_ITEM","target_type":"CODE_SNIPPET","relationship_type":"CONTAINS","extra":"Wiki contains code snippet: backend/app/api/queries.py#1-86","gmt_create":"2026-04-23T15:21:46.721634+08:00","gmt_modified":"2026-04-23T15:21:46.721634+08:00"},{"id":282,"source_id":"6b3d903205941aa9391dd90016e1102c","target_id":"10d1e37bdc9f353c189b7a2fe79dc85e","source_type":"SOURCE_FILE","target_type":"CODE_SNIPPET","relationship_type":"CONTAINS","extra":"Source file contains code snippet: 1-86","gmt_create":"2026-04-23T15:21:46.722019+08:00","gmt_modified":"2026-04-23T15:21:46.722019+08:00"},{"id":283,"source_id":"262a3941-fdc6-46b0-b767-be40aa9d5761","target_id":"cbd0101fa84d957bcb1baaa623c6b31c","source_type":"WIKI_ITEM","target_type":"CODE_SNIPPET","relationship_type":"CONTAINS","extra":"Wiki contains code snippet: backend/app/api/citations.py#1-78","gmt_create":"2026-04-23T15:21:46.722621+08:00","gmt_modified":"2026-04-23T15:21:46.722621+08:00"},{"id":284,"source_id":"7538ffe4902ab6041adb28b19844962a","target_id":"cbd0101fa84d957bcb1baaa623c6b31c","source_type":"SOURCE_FILE","target_type":"CODE_SNIPPET","relationship_type":"CONTAINS","extra":"Source file contains code snippet: 1-78","gmt_create":"2026-04-23T15:21:46.723064+08:00","gmt_modified":"2026-04-23T15:21:46.723064+08:00"},{"id":285,"source_id":"262a3941-fdc6-46b0-b767-be40aa9d5761","target_id":"afe4138895492c26aac5c0120ef46cd8","source_type":"WIKI_ITEM","target_type":"CODE_SNIPPET","relationship_type":"CONTAINS","extra":"Wiki contains code snippet: backend/app/models/__init__.py#1-14","gmt_create":"2026-04-23T15:21:46.72357+08:00","gmt_modified":"2026-04-23T15:21:46.72357+08:00"},{"id":286,"source_id":"99fe1b288fd41daa86c2dfbab819abf0","target_id":"afe4138895492c26aac5c0120ef46cd8","source_type":"SOURCE_FILE","target_type":"CODE_SNIPPET","relationship_type":"CONTAINS","extra":"Source file contains code snippet: 1-14","gmt_create":"2026-04-23T15:21:46.723873+08:00","gmt_modified":"2026-04-23T15:21:46.723873+08:00"},{"id":287,"source_id":"262a3941-fdc6-46b0-b767-be40aa9d5761","target_id":"4d11ddf7abb8076d81b30c4315786f9a","source_type":"WIKI_ITEM","target_type":"CODE_SNIPPET","relationship_type":"CONTAINS","extra":"Wiki contains code snippet: backend/alembic/versions/488d0bd5ab01_initial_migration.py#21-128","gmt_create":"2026-04-23T15:21:46.726415+08:00","gmt_modified":"2026-04-23T15:21:46.726416+08:00"},{"id":288,"source_id":"d4f95fcf50683b5bf6167c7d2a6b126d","target_id":"4d11ddf7abb8076d81b30c4315786f9a","source_type":"SOURCE_FILE","target_type":"CODE_SNIPPET","relationship_type":"CONTAINS","extra":"Source file contains code snippet: 21-128","gmt_create":"2026-04-23T15:21:46.726829+08:00","gmt_modified":"2026-04-23T15:21:46.726829+08:00"},{"id":289,"source_id":"262a3941-fdc6-46b0-b767-be40aa9d5761","target_id":"e454b4a54500bd81e7599e6ec97bf12b","source_type":"WIKI_ITEM","target_type":"CODE_SNIPPET","relationship_type":"CONTAINS","extra":"Wiki contains code snippet: backend/alembic/versions/488d0bd5ab01_initial_migration.py#23-37","gmt_create":"2026-04-23T15:21:46.735019+08:00","gmt_modified":"2026-04-23T15:21:46.735019+08:00"},{"id":290,"source_id":"d4f95fcf50683b5bf6167c7d2a6b126d","target_id":"e454b4a54500bd81e7599e6ec97bf12b","source_type":"SOURCE_FILE","target_type":"CODE_SNIPPET","relationship_type":"CONTAINS","extra":"Source file contains code snippet: 23-37","gmt_create":"2026-04-23T15:21:46.735734+08:00","gmt_modified":"2026-04-23T15:21:46.735734+08:00"},{"id":291,"source_id":"262a3941-fdc6-46b0-b767-be40aa9d5761","target_id":"1965adf7cfc65447e3c1ae21fbf6d1c5","source_type":"WIKI_ITEM","target_type":"CODE_SNIPPET","relationship_type":"CONTAINS","extra":"Wiki contains code snippet: backend/alembic/versions/488d0bd5ab01_initial_migration.py#39-59","gmt_create":"2026-04-23T15:21:46.737007+08:00","gmt_modified":"2026-04-23T15:21:46.737007+08:00"},{"id":292,"source_id":"d4f95fcf50683b5bf6167c7d2a6b126d","target_id":"1965adf7cfc65447e3c1ae21fbf6d1c5","source_type":"SOURCE_FILE","target_type":"CODE_SNIPPET","relationship_type":"CONTAINS","extra":"Source file contains code snippet: 39-59","gmt_create":"2026-04-23T15:21:46.744358+08:00","gmt_modified":"2026-04-23T15:21:46.744358+08:00"},{"id":293,"source_id":"262a3941-fdc6-46b0-b767-be40aa9d5761","target_id":"c730faefb34bb87c40c5f636b4ff7f41","source_type":"WIKI_ITEM","target_type":"CODE_SNIPPET","relationship_type":"CONTAINS","extra":"Wiki contains code snippet: backend/alembic/versions/488d0bd5ab01_initial_migration.py#80-94","gmt_create":"2026-04-23T15:21:46.747533+08:00","gmt_modified":"2026-04-23T15:21:46.747534+08:00"},{"id":294,"source_id":"d4f95fcf50683b5bf6167c7d2a6b126d","target_id":"c730faefb34bb87c40c5f636b4ff7f41","source_type":"SOURCE_FILE","target_type":"CODE_SNIPPET","relationship_type":"CONTAINS","extra":"Source file contains code snippet: 80-94","gmt_create":"2026-04-23T15:21:46.748811+08:00","gmt_modified":"2026-04-23T15:21:46.748811+08:00"},{"id":295,"source_id":"262a3941-fdc6-46b0-b767-be40aa9d5761","target_id":"b9978c3eccea3ef566b003216e5047af","source_type":"WIKI_ITEM","target_type":"CODE_SNIPPET","relationship_type":"CONTAINS","extra":"Wiki contains code snippet: backend/alembic/versions/488d0bd5ab01_initial_migration.py#61-78","gmt_create":"2026-04-23T15:21:46.751629+08:00","gmt_modified":"2026-04-23T15:21:46.751629+08:00"},{"id":296,"source_id":"d4f95fcf50683b5bf6167c7d2a6b126d","target_id":"b9978c3eccea3ef566b003216e5047af","source_type":"SOURCE_FILE","target_type":"CODE_SNIPPET","relationship_type":"CONTAINS","extra":"Source file contains code snippet: 61-78","gmt_create":"2026-04-23T15:21:46.752497+08:00","gmt_modified":"2026-04-23T15:21:46.752497+08:00"},{"id":297,"source_id":"262a3941-fdc6-46b0-b767-be40aa9d5761","target_id":"eb6ff4361d7413b57f1f70b1ec2f0c94","source_type":"WIKI_ITEM","target_type":"CODE_SNIPPET","relationship_type":"CONTAINS","extra":"Wiki contains code snippet: backend/alembic/versions/488d0bd5ab01_initial_migration.py#96-111","gmt_create":"2026-04-23T15:21:46.753732+08:00","gmt_modified":"2026-04-23T15:21:46.753732+08:00"},{"id":298,"source_id":"d4f95fcf50683b5bf6167c7d2a6b126d","target_id":"eb6ff4361d7413b57f1f70b1ec2f0c94","source_type":"SOURCE_FILE","target_type":"CODE_SNIPPET","relationship_type":"CONTAINS","extra":"Source file contains code snippet: 96-111","gmt_create":"2026-04-23T15:21:46.754523+08:00","gmt_modified":"2026-04-23T15:21:46.754523+08:00"},{"id":299,"source_id":"262a3941-fdc6-46b0-b767-be40aa9d5761","target_id":"1a2657244414b5681afded9565a86422","source_type":"WIKI_ITEM","target_type":"CODE_SNIPPET","relationship_type":"CONTAINS","extra":"Wiki contains code snippet: backend/app/models/user.py#35-40","gmt_create":"2026-04-23T15:21:46.755683+08:00","gmt_modified":"2026-04-23T15:21:46.755683+08:00"},{"id":300,"source_id":"262a3941-fdc6-46b0-b767-be40aa9d5761","target_id":"acd5a29be2bdd4ae251e10ca266ffe13","source_type":"WIKI_ITEM","target_type":"CODE_SNIPPET","relationship_type":"CONTAINS","extra":"Wiki contains code snippet: backend/app/models/query.py#43-48","gmt_create":"2026-04-23T15:21:46.756979+08:00","gmt_modified":"2026-04-23T15:21:46.756979+08:00"},{"id":301,"source_id":"262a3941-fdc6-46b0-b767-be40aa9d5761","target_id":"f6c9f1b4e8646c366a31426a4537675d","source_type":"WIKI_ITEM","target_type":"CODE_SNIPPET","relationship_type":"CONTAINS","extra":"Wiki contains code snippet: backend/app/models/query_task.py#36-38","gmt_create":"2026-04-23T15:21:46.75809+08:00","gmt_modified":"2026-04-23T15:21:46.75809+08:00"},{"id":302,"source_id":"069738f21ac2da7349d22683e8c36929","target_id":"f6c9f1b4e8646c366a31426a4537675d","source_type":"SOURCE_FILE","target_type":"CODE_SNIPPET","relationship_type":"CONTAINS","extra":"Source file contains code snippet: 36-38","gmt_create":"2026-04-23T15:21:46.759234+08:00","gmt_modified":"2026-04-23T15:21:46.759234+08:00"},{"id":303,"source_id":"262a3941-fdc6-46b0-b767-be40aa9d5761","target_id":"a2adbf02c71e4eb2cf1f120e1a2ff517","source_type":"WIKI_ITEM","target_type":"CODE_SNIPPET","relationship_type":"CONTAINS","extra":"Wiki contains code snippet: backend/app/models/citation_record.py#37-41","gmt_create":"2026-04-23T15:21:46.760054+08:00","gmt_modified":"2026-04-23T15:21:46.760054+08:00"},{"id":304,"source_id":"b4a81ef789630d0af6a8d50859d01bf3","target_id":"a2adbf02c71e4eb2cf1f120e1a2ff517","source_type":"SOURCE_FILE","target_type":"CODE_SNIPPET","relationship_type":"CONTAINS","extra":"Source file contains code snippet: 37-41","gmt_create":"2026-04-23T15:21:46.761257+08:00","gmt_modified":"2026-04-23T15:21:46.761257+08:00"},{"id":305,"source_id":"262a3941-fdc6-46b0-b767-be40aa9d5761","target_id":"69118807690ef351a9de910414d5e676","source_type":"WIKI_ITEM","target_type":"CODE_SNIPPET","relationship_type":"CONTAINS","extra":"Wiki contains code snippet: backend/app/schemas/query.py#11-94","gmt_create":"2026-04-23T15:21:46.76204+08:00","gmt_modified":"2026-04-23T15:21:46.762041+08:00"},{"id":306,"source_id":"262a3941-fdc6-46b0-b767-be40aa9d5761","target_id":"26288877e8e1f6c4ff5aca12610b0218","source_type":"WIKI_ITEM","target_type":"CODE_SNIPPET","relationship_type":"CONTAINS","extra":"Wiki contains code snippet: backend/app/schemas/citation.py#7-50","gmt_create":"2026-04-23T15:21:46.763512+08:00","gmt_modified":"2026-04-23T15:21:46.763512+08:00"},{"id":307,"source_id":"262a3941-fdc6-46b0-b767-be40aa9d5761","target_id":"0907fc2974ec31c23aaaef02076700a1","source_type":"WIKI_ITEM","target_type":"CODE_SNIPPET","relationship_type":"CONTAINS","extra":"Wiki contains code snippet: backend/app/models/user.py#25-33","gmt_create":"2026-04-23T15:21:46.764956+08:00","gmt_modified":"2026-04-23T15:21:46.764956+08:00"},{"id":308,"source_id":"c59f8c276697a070dffc581fe94d809c","target_id":"0907fc2974ec31c23aaaef02076700a1","source_type":"SOURCE_FILE","target_type":"CODE_SNIPPET","relationship_type":"CONTAINS","extra":"Source file contains code snippet: 25-33","gmt_create":"2026-04-23T15:21:46.766604+08:00","gmt_modified":"2026-04-23T15:21:46.766605+08:00"},{"id":309,"source_id":"262a3941-fdc6-46b0-b767-be40aa9d5761","target_id":"842f74e2cc054608242e93fbefd96b45","source_type":"WIKI_ITEM","target_type":"CODE_SNIPPET","relationship_type":"CONTAINS","extra":"Wiki contains code snippet: backend/app/models/query.py#32-40","gmt_create":"2026-04-23T15:21:46.767787+08:00","gmt_modified":"2026-04-23T15:21:46.767787+08:00"},{"id":310,"source_id":"b74caccb06844efcdb14d8324cff65c2","target_id":"842f74e2cc054608242e93fbefd96b45","source_type":"SOURCE_FILE","target_type":"CODE_SNIPPET","relationship_type":"CONTAINS","extra":"Source file contains code snippet: 32-40","gmt_create":"2026-04-23T15:21:46.769407+08:00","gmt_modified":"2026-04-23T15:21:46.769407+08:00"},{"id":311,"source_id":"262a3941-fdc6-46b0-b767-be40aa9d5761","target_id":"aed9e839038c45e6ce2023c4e05adb76","source_type":"WIKI_ITEM","target_type":"CODE_SNIPPET","relationship_type":"CONTAINS","extra":"Wiki contains code snippet: backend/app/models/query_task.py#27-32","gmt_create":"2026-04-23T15:21:46.770612+08:00","gmt_modified":"2026-04-23T15:21:46.770612+08:00"},{"id":312,"source_id":"069738f21ac2da7349d22683e8c36929","target_id":"aed9e839038c45e6ce2023c4e05adb76","source_type":"SOURCE_FILE","target_type":"CODE_SNIPPET","relationship_type":"CONTAINS","extra":"Source file contains code snippet: 27-32","gmt_create":"2026-04-23T15:21:46.771344+08:00","gmt_modified":"2026-04-23T15:21:46.771345+08:00"},{"id":313,"source_id":"262a3941-fdc6-46b0-b767-be40aa9d5761","target_id":"2181318c993526c86458f5eef134aed6","source_type":"WIKI_ITEM","target_type":"CODE_SNIPPET","relationship_type":"CONTAINS","extra":"Wiki contains code snippet: backend/app/services/query.py#62-77","gmt_create":"2026-04-23T15:21:46.77237+08:00","gmt_modified":"2026-04-23T15:21:46.77237+08:00"},{"id":314,"source_id":"88d22de3b2a7419868e8ae19130d860c","target_id":"2181318c993526c86458f5eef134aed6","source_type":"SOURCE_FILE","target_type":"CODE_SNIPPET","relationship_type":"CONTAINS","extra":"Source file contains code snippet: 62-77","gmt_create":"2026-04-23T15:21:46.773284+08:00","gmt_modified":"2026-04-23T15:21:46.773284+08:00"},{"id":315,"source_id":"262a3941-fdc6-46b0-b767-be40aa9d5761","target_id":"a817488dc968d761a8977fb5bb8d01a2","source_type":"WIKI_ITEM","target_type":"CODE_SNIPPET","relationship_type":"CONTAINS","extra":"Wiki contains code snippet: backend/app/services/query.py#45-129","gmt_create":"2026-04-23T15:21:46.774203+08:00","gmt_modified":"2026-04-23T15:21:46.774203+08:00"},{"id":316,"source_id":"88d22de3b2a7419868e8ae19130d860c","target_id":"a817488dc968d761a8977fb5bb8d01a2","source_type":"SOURCE_FILE","target_type":"CODE_SNIPPET","relationship_type":"CONTAINS","extra":"Source file contains code snippet: 45-129","gmt_create":"2026-04-23T15:21:46.775081+08:00","gmt_modified":"2026-04-23T15:21:46.775081+08:00"},{"id":317,"source_id":"262a3941-fdc6-46b0-b767-be40aa9d5761","target_id":"fe70b1fef9f36e73d26d84987e927c7a","source_type":"WIKI_ITEM","target_type":"CODE_SNIPPET","relationship_type":"CONTAINS","extra":"Wiki contains code snippet: backend/app/api/queries.py#15-86","gmt_create":"2026-04-23T15:21:46.775898+08:00","gmt_modified":"2026-04-23T15:21:46.775898+08:00"},{"id":318,"source_id":"262a3941-fdc6-46b0-b767-be40aa9d5761","target_id":"d20fc729a5d3986b1c077f9e07ece9c4","source_type":"WIKI_ITEM","target_type":"CODE_SNIPPET","relationship_type":"CONTAINS","extra":"Wiki contains code snippet: backend/app/config.py#7","gmt_create":"2026-04-23T15:21:46.777494+08:00","gmt_modified":"2026-04-23T15:21:46.777494+08:00"},{"id":319,"source_id":"9ff19022ef915615911280e3c49ed44b","target_id":"d20fc729a5d3986b1c077f9e07ece9c4","source_type":"SOURCE_FILE","target_type":"CODE_SNIPPET","relationship_type":"CONTAINS","extra":"Source file contains code snippet: 7","gmt_create":"2026-04-23T15:21:46.778103+08:00","gmt_modified":"2026-04-23T15:21:46.778103+08:00"},{"id":320,"source_id":"262a3941-fdc6-46b0-b767-be40aa9d5761","target_id":"ea655c6d147bc98beb42955d437260cc","source_type":"WIKI_ITEM","target_type":"CODE_SNIPPET","relationship_type":"CONTAINS","extra":"Wiki contains code snippet: backend/app/config.py#1-23","gmt_create":"2026-04-23T15:21:46.779313+08:00","gmt_modified":"2026-04-23T15:21:46.779314+08:00"},{"id":321,"source_id":"9ff19022ef915615911280e3c49ed44b","target_id":"ea655c6d147bc98beb42955d437260cc","source_type":"SOURCE_FILE","target_type":"CODE_SNIPPET","relationship_type":"CONTAINS","extra":"Source file contains code snippet: 1-23","gmt_create":"2026-04-23T15:21:46.780075+08:00","gmt_modified":"2026-04-23T15:21:46.780075+08:00"},{"id":322,"source_id":"262a3941-fdc6-46b0-b767-be40aa9d5761","target_id":"37868a5af96edcdad149caf9a184435a","source_type":"WIKI_ITEM","target_type":"CODE_SNIPPET","relationship_type":"CONTAINS","extra":"Wiki contains code snippet: backend/app/api/queries.py#42-85","gmt_create":"2026-04-23T15:21:46.781141+08:00","gmt_modified":"2026-04-23T15:21:46.781141+08:00"},{"id":323,"source_id":"6b3d903205941aa9391dd90016e1102c","target_id":"37868a5af96edcdad149caf9a184435a","source_type":"SOURCE_FILE","target_type":"CODE_SNIPPET","relationship_type":"CONTAINS","extra":"Source file contains code snippet: 42-85","gmt_create":"2026-04-23T15:21:46.781803+08:00","gmt_modified":"2026-04-23T15:21:46.781803+08:00"},{"id":324,"source_id":"262a3941-fdc6-46b0-b767-be40aa9d5761","target_id":"601b981b00d93b941843f046a163d5a3","source_type":"WIKI_ITEM","target_type":"CODE_SNIPPET","relationship_type":"CONTAINS","extra":"Wiki contains code snippet: backend/app/schemas/query.py#18-33","gmt_create":"2026-04-23T15:21:46.783498+08:00","gmt_modified":"2026-04-23T15:21:46.783498+08:00"},{"id":325,"source_id":"f301b79d833233ce39d350e82a71c938","target_id":"601b981b00d93b941843f046a163d5a3","source_type":"SOURCE_FILE","target_type":"CODE_SNIPPET","relationship_type":"CONTAINS","extra":"Source file contains code snippet: 18-33","gmt_create":"2026-04-23T15:21:46.784342+08:00","gmt_modified":"2026-04-23T15:21:46.784343+08:00"},{"id":344,"source_id":"0ef1efea889dba3e1f299626df479571","target_id":"290df8332b3d104e5ea8d71dc39315b5","source_type":"SOURCE_FILE","target_type":"CODE_SNIPPET","relationship_type":"CONTAINS","extra":"Source file contains code snippet: 1-123","gmt_create":"2026-04-23T15:22:16.017503+08:00","gmt_modified":"2026-04-23T15:22:16.017503+08:00"},{"id":346,"source_id":"9228ff67d4c757a85d9421b71f4b29f5","target_id":"c2747ca16b879bca0f68955534c3c4fc","source_type":"SOURCE_FILE","target_type":"CODE_SNIPPET","relationship_type":"CONTAINS","extra":"Source file contains code snippet: 1-48","gmt_create":"2026-04-23T15:22:16.019099+08:00","gmt_modified":"2026-04-23T15:22:16.019099+08:00"},{"id":348,"source_id":"9d08667997a868fc07c9b4e328e44224","target_id":"76e6c0abb49fec57cac4892837a143c9","source_type":"SOURCE_FILE","target_type":"CODE_SNIPPET","relationship_type":"CONTAINS","extra":"Source file contains code snippet: 1-43","gmt_create":"2026-04-23T15:22:16.020577+08:00","gmt_modified":"2026-04-23T15:22:16.020577+08:00"},{"id":350,"source_id":"93022c8938ce318f167277cfa65c29a7","target_id":"f66d9907b467b110c638bd527efd95c5","source_type":"SOURCE_FILE","target_type":"CODE_SNIPPET","relationship_type":"CONTAINS","extra":"Source file contains code snippet: 1-43","gmt_create":"2026-04-23T15:22:16.021841+08:00","gmt_modified":"2026-04-23T15:22:16.021841+08:00"},{"id":354,"source_id":"74040de652d5e57f548bb5c4adc3e1a0","target_id":"116584ea9162c1bc05911f39f9ef82b6","source_type":"SOURCE_FILE","target_type":"CODE_SNIPPET","relationship_type":"CONTAINS","extra":"Source file contains code snippet: 1-309","gmt_create":"2026-04-23T15:22:16.023827+08:00","gmt_modified":"2026-04-23T15:22:16.023827+08:00"},{"id":356,"source_id":"5cbb1e3f112aeba62a14b0b8999fc0f5","target_id":"9630036e63fc15cb81b202cf79671aab","source_type":"SOURCE_FILE","target_type":"CODE_SNIPPET","relationship_type":"CONTAINS","extra":"Source file contains code snippet: 1-182","gmt_create":"2026-04-23T15:22:16.024606+08:00","gmt_modified":"2026-04-23T15:22:16.024606+08:00"},{"id":359,"source_id":"9ff19022ef915615911280e3c49ed44b","target_id":"84fbed7d35f7752e2117a74fcaf5f0e9","source_type":"SOURCE_FILE","target_type":"CODE_SNIPPET","relationship_type":"CONTAINS","extra":"Source file contains code snippet: 1-17","gmt_create":"2026-04-23T15:22:16.026089+08:00","gmt_modified":"2026-04-23T15:22:16.02609+08:00"},{"id":361,"source_id":"0ef1efea889dba3e1f299626df479571","target_id":"5ddf0c8d7b38e4f6126a5d85da1dfeda","source_type":"SOURCE_FILE","target_type":"CODE_SNIPPET","relationship_type":"CONTAINS","extra":"Source file contains code snippet: 19-123","gmt_create":"2026-04-23T15:22:16.02774+08:00","gmt_modified":"2026-04-23T15:22:16.02774+08:00"},{"id":363,"source_id":"0ef1efea889dba3e1f299626df479571","target_id":"9df233ef1be4b95068ed91bf01083ae7","source_type":"SOURCE_FILE","target_type":"CODE_SNIPPET","relationship_type":"CONTAINS","extra":"Source file contains code snippet: 117-123","gmt_create":"2026-04-23T15:22:16.028504+08:00","gmt_modified":"2026-04-23T15:22:16.028504+08:00"},{"id":365,"source_id":"9228ff67d4c757a85d9421b71f4b29f5","target_id":"6286d4be455dc058c8be2ee4e0d1175a","source_type":"SOURCE_FILE","target_type":"CODE_SNIPPET","relationship_type":"CONTAINS","extra":"Source file contains code snippet: 38-42","gmt_create":"2026-04-23T15:22:16.029449+08:00","gmt_modified":"2026-04-23T15:22:16.029449+08:00"},{"id":367,"source_id":"9d08667997a868fc07c9b4e328e44224","target_id":"069243fafe60a85cf16a0ca40fa07180","source_type":"SOURCE_FILE","target_type":"CODE_SNIPPET","relationship_type":"CONTAINS","extra":"Source file contains code snippet: 16-43","gmt_create":"2026-04-23T15:22:16.030648+08:00","gmt_modified":"2026-04-23T15:22:16.030648+08:00"},{"id":369,"source_id":"93022c8938ce318f167277cfa65c29a7","target_id":"d5a1fb0bd23ce9240fbf79529ef94a45","source_type":"SOURCE_FILE","target_type":"CODE_SNIPPET","relationship_type":"CONTAINS","extra":"Source file contains code snippet: 13-43","gmt_create":"2026-04-23T15:22:16.03168+08:00","gmt_modified":"2026-04-23T15:22:16.03168+08:00"},{"id":372,"source_id":"7538ffe4902ab6041adb28b19844962a","target_id":"735aef72b4fe6ca4f407e69b7dda8b43","source_type":"SOURCE_FILE","target_type":"CODE_SNIPPET","relationship_type":"CONTAINS","extra":"Source file contains code snippet: 25-78","gmt_create":"2026-04-23T15:22:16.03298+08:00","gmt_modified":"2026-04-23T15:22:16.03298+08:00"},{"id":374,"source_id":"b0c428683c8a3e6922d90ca0d8c2736d","target_id":"8128dd67cf376d2cadf7c2d3831c380a","source_type":"SOURCE_FILE","target_type":"CODE_SNIPPET","relationship_type":"CONTAINS","extra":"Source file contains code snippet: 23-29","gmt_create":"2026-04-23T15:22:16.035564+08:00","gmt_modified":"2026-04-23T15:22:16.035564+08:00"},{"id":376,"source_id":"389d631bc6c7111ba411b0b79fca455e","target_id":"1721defc3d6206478d3c0692cc821761","source_type":"SOURCE_FILE","target_type":"CODE_SNIPPET","relationship_type":"CONTAINS","extra":"Source file contains code snippet: 25-104","gmt_create":"2026-04-23T15:22:16.036753+08:00","gmt_modified":"2026-04-23T15:22:16.036753+08:00"},{"id":378,"source_id":"4d2f3847b7c10634733118b70a1aea0b","target_id":"753a437d837246ead62b0e16c6331284","source_type":"SOURCE_FILE","target_type":"CODE_SNIPPET","relationship_type":"CONTAINS","extra":"Source file contains code snippet: 37-69","gmt_create":"2026-04-23T15:22:16.038261+08:00","gmt_modified":"2026-04-23T15:22:16.038261+08:00"},{"id":380,"source_id":"389d631bc6c7111ba411b0b79fca455e","target_id":"d820e2daf2ea133a7aa17cdc475e44a4","source_type":"SOURCE_FILE","target_type":"CODE_SNIPPET","relationship_type":"CONTAINS","extra":"Source file contains code snippet: 1-104","gmt_create":"2026-04-23T15:22:16.039369+08:00","gmt_modified":"2026-04-23T15:22:16.039369+08:00"},{"id":382,"source_id":"4d2f3847b7c10634733118b70a1aea0b","target_id":"1a439c5fed6cfd188c646e1614d56371","source_type":"SOURCE_FILE","target_type":"CODE_SNIPPET","relationship_type":"CONTAINS","extra":"Source file contains code snippet: 1-69","gmt_create":"2026-04-23T15:22:16.040483+08:00","gmt_modified":"2026-04-23T15:22:16.040483+08:00"},{"id":385,"source_id":"74040de652d5e57f548bb5c4adc3e1a0","target_id":"5c67e2f70283956b2d29a3c1443eb514","source_type":"SOURCE_FILE","target_type":"CODE_SNIPPET","relationship_type":"CONTAINS","extra":"Source file contains code snippet: 122-146","gmt_create":"2026-04-23T15:22:16.042829+08:00","gmt_modified":"2026-04-23T15:22:16.042829+08:00"},{"id":388,"source_id":"b07a4fb9cecbbd66a6910ccbc7651f19","target_id":"a57acd9da5287c915ac823784a409292","source_type":"SOURCE_FILE","target_type":"CODE_SNIPPET","relationship_type":"CONTAINS","extra":"Source file contains code snippet: 1-127","gmt_create":"2026-04-23T15:22:16.045132+08:00","gmt_modified":"2026-04-23T15:22:16.045132+08:00"},{"id":390,"source_id":"42ff5383133d176cec9eb88682483be3","target_id":"2a4f741f31f62dce8ad63be2e831f520","source_type":"SOURCE_FILE","target_type":"CODE_SNIPPET","relationship_type":"CONTAINS","extra":"Source file contains code snippet: 23-93","gmt_create":"2026-04-23T15:22:16.046367+08:00","gmt_modified":"2026-04-23T15:22:16.046367+08:00"},{"id":392,"source_id":"42ff5383133d176cec9eb88682483be3","target_id":"692ac240965eff7e66945aa3c4c270f7","source_type":"SOURCE_FILE","target_type":"CODE_SNIPPET","relationship_type":"CONTAINS","extra":"Source file contains code snippet: 1-93","gmt_create":"2026-04-23T15:22:16.047995+08:00","gmt_modified":"2026-04-23T15:22:16.047995+08:00"},{"id":394,"source_id":"0613e76b9679be7f998fb8fd8056e686","target_id":"32a0a52faca2d8d488e49c63c86075b1","source_type":"SOURCE_FILE","target_type":"CODE_SNIPPET","relationship_type":"CONTAINS","extra":"Source file contains code snippet: 29-154","gmt_create":"2026-04-23T15:22:16.049251+08:00","gmt_modified":"2026-04-23T15:22:16.049251+08:00"},{"id":396,"source_id":"0613e76b9679be7f998fb8fd8056e686","target_id":"7804331f5f8c1ba5a3b6d9c1ae1c78c1","source_type":"SOURCE_FILE","target_type":"CODE_SNIPPET","relationship_type":"CONTAINS","extra":"Source file contains code snippet: 1-154","gmt_create":"2026-04-23T15:22:16.051952+08:00","gmt_modified":"2026-04-23T15:22:16.051952+08:00"},{"id":398,"source_id":"80a0429cc47931de27ddb17a62b8dd9c","target_id":"3a6e1b738967bf8cc651e57f48e2e126","source_type":"SOURCE_FILE","target_type":"CODE_SNIPPET","relationship_type":"CONTAINS","extra":"Source file contains code snippet: 83-126","gmt_create":"2026-04-23T15:22:16.053692+08:00","gmt_modified":"2026-04-23T15:22:16.053693+08:00"},{"id":400,"source_id":"80a0429cc47931de27ddb17a62b8dd9c","target_id":"b1afd377757f1d0e9bdf87edfff3ad88","source_type":"SOURCE_FILE","target_type":"CODE_SNIPPET","relationship_type":"CONTAINS","extra":"Source file contains code snippet: 131-186","gmt_create":"2026-04-23T15:22:16.054533+08:00","gmt_modified":"2026-04-23T15:22:16.054533+08:00"},{"id":402,"source_id":"80a0429cc47931de27ddb17a62b8dd9c","target_id":"de05ec7eed033e432991e5a88e1b5a06","source_type":"SOURCE_FILE","target_type":"CODE_SNIPPET","relationship_type":"CONTAINS","extra":"Source file contains code snippet: 192-222","gmt_create":"2026-04-23T15:22:16.055495+08:00","gmt_modified":"2026-04-23T15:22:16.055495+08:00"},{"id":404,"source_id":"80a0429cc47931de27ddb17a62b8dd9c","target_id":"7fd61a451248b6b129299d6246f711c7","source_type":"SOURCE_FILE","target_type":"CODE_SNIPPET","relationship_type":"CONTAINS","extra":"Source file contains code snippet: 228-296","gmt_create":"2026-04-23T15:22:16.056294+08:00","gmt_modified":"2026-04-23T15:22:16.056294+08:00"},{"id":406,"source_id":"80a0429cc47931de27ddb17a62b8dd9c","target_id":"53eedffff456a566fa7b0cecc7169f56","source_type":"SOURCE_FILE","target_type":"CODE_SNIPPET","relationship_type":"CONTAINS","extra":"Source file contains code snippet: 1-441","gmt_create":"2026-04-23T15:22:16.05703+08:00","gmt_modified":"2026-04-23T15:22:16.05703+08:00"},{"id":408,"source_id":"5cbb1e3f112aeba62a14b0b8999fc0f5","target_id":"906f7a8288e38d4244211f3f538fe7b6","source_type":"SOURCE_FILE","target_type":"CODE_SNIPPET","relationship_type":"CONTAINS","extra":"Source file contains code snippet: 27-182","gmt_create":"2026-04-23T15:22:16.062545+08:00","gmt_modified":"2026-04-23T15:22:16.062545+08:00"},{"id":410,"source_id":"b2f0d46a31a5441594f2e777365fc156","target_id":"1647ee2066de2ae59ba8cf88e33c5e02","source_type":"SOURCE_FILE","target_type":"CODE_SNIPPET","relationship_type":"CONTAINS","extra":"Source file contains code snippet: 1-123","gmt_create":"2026-04-23T15:22:16.064587+08:00","gmt_modified":"2026-04-23T15:22:16.064587+08:00"},{"id":411,"source_id":"760610d4-dff6-4c6d-831f-7c9078db86a6","target_id":"aaf5bce6be82d2f947bfa5c1806de452","source_type":"WIKI_ITEM","target_type":"SOURCE_FILE","relationship_type":"REFERENCED_BY","extra":"Wiki references source file: frontend/package.json","gmt_create":"2026-04-23T15:22:23.52554+08:00","gmt_modified":"2026-04-23T15:22:23.52554+08:00"},{"id":412,"source_id":"760610d4-dff6-4c6d-831f-7c9078db86a6","target_id":"01056dad8851d3e9bd532eb4cab33792","source_type":"WIKI_ITEM","target_type":"SOURCE_FILE","relationship_type":"REFERENCED_BY","extra":"Wiki references source file: frontend/tailwind.config.ts","gmt_create":"2026-04-23T15:22:23.52643+08:00","gmt_modified":"2026-04-23T15:22:23.526431+08:00"},{"id":413,"source_id":"760610d4-dff6-4c6d-831f-7c9078db86a6","target_id":"f93ae024fe0a2e69698037dff6df205f","source_type":"WIKI_ITEM","target_type":"SOURCE_FILE","relationship_type":"REFERENCED_BY","extra":"Wiki references source file: frontend/lib/utils.ts","gmt_create":"2026-04-23T15:22:23.527272+08:00","gmt_modified":"2026-04-23T15:22:23.527272+08:00"},{"id":414,"source_id":"760610d4-dff6-4c6d-831f-7c9078db86a6","target_id":"ac1acbc54c49ee1de13369f6c6827568","source_type":"WIKI_ITEM","target_type":"SOURCE_FILE","relationship_type":"REFERENCED_BY","extra":"Wiki references source file: frontend/components/ui/button.tsx","gmt_create":"2026-04-23T15:22:23.528155+08:00","gmt_modified":"2026-04-23T15:22:23.528155+08:00"},{"id":415,"source_id":"760610d4-dff6-4c6d-831f-7c9078db86a6","target_id":"108b0c4b4dcfb6aa39a5eb138225c148","source_type":"WIKI_ITEM","target_type":"SOURCE_FILE","relationship_type":"REFERENCED_BY","extra":"Wiki references source file: frontend/components/ui/dialog.tsx","gmt_create":"2026-04-23T15:22:23.529196+08:00","gmt_modified":"2026-04-23T15:22:23.529196+08:00"},{"id":416,"source_id":"760610d4-dff6-4c6d-831f-7c9078db86a6","target_id":"0186dc8a89340139a84e1e3c5571a57f","source_type":"WIKI_ITEM","target_type":"SOURCE_FILE","relationship_type":"REFERENCED_BY","extra":"Wiki references source file: frontend/components/ui/dropdown-menu.tsx","gmt_create":"2026-04-23T15:22:23.530077+08:00","gmt_modified":"2026-04-23T15:22:23.530077+08:00"},{"id":417,"source_id":"760610d4-dff6-4c6d-831f-7c9078db86a6","target_id":"3cf787fa77a15b2b1783560c6d83ed21","source_type":"WIKI_ITEM","target_type":"SOURCE_FILE","relationship_type":"REFERENCED_BY","extra":"Wiki references source file: frontend/components/ui/input.tsx","gmt_create":"2026-04-23T15:22:23.530977+08:00","gmt_modified":"2026-04-23T15:22:23.530977+08:00"},{"id":418,"source_id":"760610d4-dff6-4c6d-831f-7c9078db86a6","target_id":"3c56e1c079959bfcc985183805e5874f","source_type":"WIKI_ITEM","target_type":"SOURCE_FILE","relationship_type":"REFERENCED_BY","extra":"Wiki references source file: frontend/components/ui/select.tsx","gmt_create":"2026-04-23T15:22:23.531664+08:00","gmt_modified":"2026-04-23T15:22:23.531664+08:00"},{"id":419,"source_id":"760610d4-dff6-4c6d-831f-7c9078db86a6","target_id":"0d5ef537f7c0b8c390f8b31d7cf47b56","source_type":"WIKI_ITEM","target_type":"SOURCE_FILE","relationship_type":"REFERENCED_BY","extra":"Wiki references source file: frontend/components/ui/card.tsx","gmt_create":"2026-04-23T15:22:23.532588+08:00","gmt_modified":"2026-04-23T15:22:23.532588+08:00"},{"id":420,"source_id":"760610d4-dff6-4c6d-831f-7c9078db86a6","target_id":"51821ca9ec2a1c972f3c9d111e19db8a","source_type":"WIKI_ITEM","target_type":"SOURCE_FILE","relationship_type":"REFERENCED_BY","extra":"Wiki references source file: frontend/components/ui/badge.tsx","gmt_create":"2026-04-23T15:22:23.53409+08:00","gmt_modified":"2026-04-23T15:22:23.53409+08:00"},{"id":421,"source_id":"760610d4-dff6-4c6d-831f-7c9078db86a6","target_id":"0c0b0f4e2cf44facd9d5b57de0d0bf0c","source_type":"WIKI_ITEM","target_type":"SOURCE_FILE","relationship_type":"REFERENCED_BY","extra":"Wiki references source file: frontend/components/ui/table.tsx","gmt_create":"2026-04-23T15:22:23.535512+08:00","gmt_modified":"2026-04-23T15:22:23.535512+08:00"},{"id":422,"source_id":"760610d4-dff6-4c6d-831f-7c9078db86a6","target_id":"beb87ab5aad9532647e9dbd2db7ef587","source_type":"WIKI_ITEM","target_type":"SOURCE_FILE","relationship_type":"REFERENCED_BY","extra":"Wiki references source file: frontend/components/ui/tabs.tsx","gmt_create":"2026-04-23T15:22:23.536664+08:00","gmt_modified":"2026-04-23T15:22:23.536665+08:00"},{"id":423,"source_id":"760610d4-dff6-4c6d-831f-7c9078db86a6","target_id":"792b8e2c16c9ff2095d83b8972313be4","source_type":"WIKI_ITEM","target_type":"SOURCE_FILE","relationship_type":"REFERENCED_BY","extra":"Wiki references source file: frontend/components/ui/label.tsx","gmt_create":"2026-04-23T15:22:23.537365+08:00","gmt_modified":"2026-04-23T15:22:23.537365+08:00"},{"id":424,"source_id":"760610d4-dff6-4c6d-831f-7c9078db86a6","target_id":"546e01c5f73aaf5140eee922f4b9a441","source_type":"WIKI_ITEM","target_type":"SOURCE_FILE","relationship_type":"REFERENCED_BY","extra":"Wiki references source file: frontend/components/providers.tsx","gmt_create":"2026-04-23T15:22:23.538246+08:00","gmt_modified":"2026-04-23T15:22:23.538246+08:00"},{"id":425,"source_id":"760610d4-dff6-4c6d-831f-7c9078db86a6","target_id":"12e2c3d7b9a92dc44a6ee29b85e10df6","source_type":"WIKI_ITEM","target_type":"SOURCE_FILE","relationship_type":"REFERENCED_BY","extra":"Wiki references source file: frontend/app/layout.tsx","gmt_create":"2026-04-23T15:22:23.53929+08:00","gmt_modified":"2026-04-23T15:22:23.53929+08:00"},{"id":426,"source_id":"760610d4-dff6-4c6d-831f-7c9078db86a6","target_id":"2a1c745c7b3fb7f600596be3d979bba1","source_type":"WIKI_ITEM","target_type":"SOURCE_FILE","relationship_type":"REFERENCED_BY","extra":"Wiki references source file: frontend/app/(dashboard","gmt_create":"2026-04-23T15:22:23.540469+08:00","gmt_modified":"2026-04-23T15:22:23.540469+08:00"},{"id":427,"source_id":"760610d4-dff6-4c6d-831f-7c9078db86a6","target_id":"8a466b0c6eac2ccb54c5da7e13854646","source_type":"WIKI_ITEM","target_type":"CODE_SNIPPET","relationship_type":"CONTAINS","extra":"Wiki contains code snippet: frontend/app/layout.tsx#1-37","gmt_create":"2026-04-23T15:22:23.541484+08:00","gmt_modified":"2026-04-23T15:22:23.541484+08:00"},{"id":428,"source_id":"760610d4-dff6-4c6d-831f-7c9078db86a6","target_id":"fd18328b6582e68c30b130b912891992","source_type":"WIKI_ITEM","target_type":"CODE_SNIPPET","relationship_type":"CONTAINS","extra":"Wiki contains code snippet: frontend/components/providers.tsx#1-9","gmt_create":"2026-04-23T15:22:23.542098+08:00","gmt_modified":"2026-04-23T15:22:23.542098+08:00"},{"id":429,"source_id":"546e01c5f73aaf5140eee922f4b9a441","target_id":"fd18328b6582e68c30b130b912891992","source_type":"SOURCE_FILE","target_type":"CODE_SNIPPET","relationship_type":"CONTAINS","extra":"Source file contains code snippet: 1-9","gmt_create":"2026-04-23T15:22:23.542482+08:00","gmt_modified":"2026-04-23T15:22:23.542482+08:00"},{"id":430,"source_id":"760610d4-dff6-4c6d-831f-7c9078db86a6","target_id":"dcfa308ef4ec368c5a51a17acbfc8e2c","source_type":"WIKI_ITEM","target_type":"CODE_SNIPPET","relationship_type":"CONTAINS","extra":"Wiki contains code snippet: frontend/lib/utils.ts#1-7","gmt_create":"2026-04-23T15:22:23.542958+08:00","gmt_modified":"2026-04-23T15:22:23.542958+08:00"},{"id":431,"source_id":"760610d4-dff6-4c6d-831f-7c9078db86a6","target_id":"71a37a516437e94fd82a87efc70a3f16","source_type":"WIKI_ITEM","target_type":"CODE_SNIPPET","relationship_type":"CONTAINS","extra":"Wiki contains code snippet: frontend/package.json#1-40","gmt_create":"2026-04-23T15:22:23.54348+08:00","gmt_modified":"2026-04-23T15:22:23.54348+08:00"},{"id":432,"source_id":"aaf5bce6be82d2f947bfa5c1806de452","target_id":"71a37a516437e94fd82a87efc70a3f16","source_type":"SOURCE_FILE","target_type":"CODE_SNIPPET","relationship_type":"CONTAINS","extra":"Source file contains code snippet: 1-40","gmt_create":"2026-04-23T15:22:23.543767+08:00","gmt_modified":"2026-04-23T15:22:23.543768+08:00"},{"id":433,"source_id":"760610d4-dff6-4c6d-831f-7c9078db86a6","target_id":"89d70e5f89be23a229e3ee59982b8e6e","source_type":"WIKI_ITEM","target_type":"CODE_SNIPPET","relationship_type":"CONTAINS","extra":"Wiki contains code snippet: frontend/tailwind.config.ts#1-57","gmt_create":"2026-04-23T15:22:23.544176+08:00","gmt_modified":"2026-04-23T15:22:23.544176+08:00"},{"id":434,"source_id":"01056dad8851d3e9bd532eb4cab33792","target_id":"89d70e5f89be23a229e3ee59982b8e6e","source_type":"SOURCE_FILE","target_type":"CODE_SNIPPET","relationship_type":"CONTAINS","extra":"Source file contains code snippet: 1-57","gmt_create":"2026-04-23T15:22:23.544513+08:00","gmt_modified":"2026-04-23T15:22:23.544513+08:00"},{"id":435,"source_id":"760610d4-dff6-4c6d-831f-7c9078db86a6","target_id":"95be577a89fbeb02578e4c3718c6ec86","source_type":"WIKI_ITEM","target_type":"CODE_SNIPPET","relationship_type":"CONTAINS","extra":"Wiki contains code snippet: frontend/components/ui/button.tsx#1-57","gmt_create":"2026-04-23T15:22:23.545023+08:00","gmt_modified":"2026-04-23T15:22:23.545023+08:00"},{"id":436,"source_id":"ac1acbc54c49ee1de13369f6c6827568","target_id":"95be577a89fbeb02578e4c3718c6ec86","source_type":"SOURCE_FILE","target_type":"CODE_SNIPPET","relationship_type":"CONTAINS","extra":"Source file contains code snippet: 1-57","gmt_create":"2026-04-23T15:22:23.545376+08:00","gmt_modified":"2026-04-23T15:22:23.545376+08:00"},{"id":437,"source_id":"760610d4-dff6-4c6d-831f-7c9078db86a6","target_id":"607bb628918a7a5d54cbf74763f94d07","source_type":"WIKI_ITEM","target_type":"CODE_SNIPPET","relationship_type":"CONTAINS","extra":"Wiki contains code snippet: frontend/components/ui/input.tsx#1-23","gmt_create":"2026-04-23T15:22:23.545898+08:00","gmt_modified":"2026-04-23T15:22:23.545899+08:00"},{"id":438,"source_id":"3cf787fa77a15b2b1783560c6d83ed21","target_id":"607bb628918a7a5d54cbf74763f94d07","source_type":"SOURCE_FILE","target_type":"CODE_SNIPPET","relationship_type":"CONTAINS","extra":"Source file contains code snippet: 1-23","gmt_create":"2026-04-23T15:22:23.546272+08:00","gmt_modified":"2026-04-23T15:22:23.546272+08:00"},{"id":439,"source_id":"760610d4-dff6-4c6d-831f-7c9078db86a6","target_id":"325e25d1dda0f7bfd9d7adfe35ecf3b5","source_type":"WIKI_ITEM","target_type":"CODE_SNIPPET","relationship_type":"CONTAINS","extra":"Wiki contains code snippet: frontend/components/ui/select.tsx#1-161","gmt_create":"2026-04-23T15:22:23.546653+08:00","gmt_modified":"2026-04-23T15:22:23.546653+08:00"},{"id":440,"source_id":"3c56e1c079959bfcc985183805e5874f","target_id":"325e25d1dda0f7bfd9d7adfe35ecf3b5","source_type":"SOURCE_FILE","target_type":"CODE_SNIPPET","relationship_type":"CONTAINS","extra":"Source file contains code snippet: 1-161","gmt_create":"2026-04-23T15:22:23.546906+08:00","gmt_modified":"2026-04-23T15:22:23.546907+08:00"},{"id":441,"source_id":"760610d4-dff6-4c6d-831f-7c9078db86a6","target_id":"0eed9f61572209dd754611fc7c690d5a","source_type":"WIKI_ITEM","target_type":"CODE_SNIPPET","relationship_type":"CONTAINS","extra":"Wiki contains code snippet: frontend/components/ui/dialog.tsx#1-123","gmt_create":"2026-04-23T15:22:23.547243+08:00","gmt_modified":"2026-04-23T15:22:23.547244+08:00"},{"id":442,"source_id":"760610d4-dff6-4c6d-831f-7c9078db86a6","target_id":"ad6ff021b2126ad5c42323305eb6d8b0","source_type":"WIKI_ITEM","target_type":"CODE_SNIPPET","relationship_type":"CONTAINS","extra":"Wiki contains code snippet: frontend/components/ui/dropdown-menu.tsx#1-201","gmt_create":"2026-04-23T15:22:23.547645+08:00","gmt_modified":"2026-04-23T15:22:23.547645+08:00"},{"id":443,"source_id":"0186dc8a89340139a84e1e3c5571a57f","target_id":"ad6ff021b2126ad5c42323305eb6d8b0","source_type":"SOURCE_FILE","target_type":"CODE_SNIPPET","relationship_type":"CONTAINS","extra":"Source file contains code snippet: 1-201","gmt_create":"2026-04-23T15:22:23.547892+08:00","gmt_modified":"2026-04-23T15:22:23.547892+08:00"},{"id":444,"source_id":"760610d4-dff6-4c6d-831f-7c9078db86a6","target_id":"a85f004dca63614b4e734ba63b45ef9e","source_type":"WIKI_ITEM","target_type":"CODE_SNIPPET","relationship_type":"CONTAINS","extra":"Wiki contains code snippet: frontend/components/ui/card.tsx#1-80","gmt_create":"2026-04-23T15:22:23.548296+08:00","gmt_modified":"2026-04-23T15:22:23.548296+08:00"},{"id":445,"source_id":"0d5ef537f7c0b8c390f8b31d7cf47b56","target_id":"a85f004dca63614b4e734ba63b45ef9e","source_type":"SOURCE_FILE","target_type":"CODE_SNIPPET","relationship_type":"CONTAINS","extra":"Source file contains code snippet: 1-80","gmt_create":"2026-04-23T15:22:23.548561+08:00","gmt_modified":"2026-04-23T15:22:23.548561+08:00"},{"id":446,"source_id":"760610d4-dff6-4c6d-831f-7c9078db86a6","target_id":"3bab92a09e9fb456e0303bb1e04afc7e","source_type":"WIKI_ITEM","target_type":"CODE_SNIPPET","relationship_type":"CONTAINS","extra":"Wiki contains code snippet: frontend/components/ui/table.tsx#1-118","gmt_create":"2026-04-23T15:22:23.548946+08:00","gmt_modified":"2026-04-23T15:22:23.548946+08:00"},{"id":447,"source_id":"760610d4-dff6-4c6d-831f-7c9078db86a6","target_id":"bd3042a8d9b602334720b0d7b4e8ab3d","source_type":"WIKI_ITEM","target_type":"CODE_SNIPPET","relationship_type":"CONTAINS","extra":"Wiki contains code snippet: frontend/components/ui/tabs.tsx#1-56","gmt_create":"2026-04-23T15:22:23.549383+08:00","gmt_modified":"2026-04-23T15:22:23.549383+08:00"},{"id":448,"source_id":"beb87ab5aad9532647e9dbd2db7ef587","target_id":"bd3042a8d9b602334720b0d7b4e8ab3d","source_type":"SOURCE_FILE","target_type":"CODE_SNIPPET","relationship_type":"CONTAINS","extra":"Source file contains code snippet: 1-56","gmt_create":"2026-04-23T15:22:23.549652+08:00","gmt_modified":"2026-04-23T15:22:23.549653+08:00"},{"id":449,"source_id":"760610d4-dff6-4c6d-831f-7c9078db86a6","target_id":"379443f450513b5492e2d9d5fca94a42","source_type":"WIKI_ITEM","target_type":"CODE_SNIPPET","relationship_type":"CONTAINS","extra":"Wiki contains code snippet: frontend/components/ui/label.tsx#1-27","gmt_create":"2026-04-23T15:22:23.550013+08:00","gmt_modified":"2026-04-23T15:22:23.550014+08:00"},{"id":450,"source_id":"792b8e2c16c9ff2095d83b8972313be4","target_id":"379443f450513b5492e2d9d5fca94a42","source_type":"SOURCE_FILE","target_type":"CODE_SNIPPET","relationship_type":"CONTAINS","extra":"Source file contains code snippet: 1-27","gmt_create":"2026-04-23T15:22:23.550267+08:00","gmt_modified":"2026-04-23T15:22:23.550267+08:00"},{"id":451,"source_id":"760610d4-dff6-4c6d-831f-7c9078db86a6","target_id":"4aa6ad434a73143bb7a2072124f63be0","source_type":"WIKI_ITEM","target_type":"CODE_SNIPPET","relationship_type":"CONTAINS","extra":"Wiki contains code snippet: frontend/components/ui/badge.tsx#1-37","gmt_create":"2026-04-23T15:22:23.551155+08:00","gmt_modified":"2026-04-23T15:22:23.551155+08:00"},{"id":452,"source_id":"51821ca9ec2a1c972f3c9d111e19db8a","target_id":"4aa6ad434a73143bb7a2072124f63be0","source_type":"SOURCE_FILE","target_type":"CODE_SNIPPET","relationship_type":"CONTAINS","extra":"Source file contains code snippet: 1-37","gmt_create":"2026-04-23T15:22:23.551858+08:00","gmt_modified":"2026-04-23T15:22:23.551858+08:00"},{"id":453,"source_id":"760610d4-dff6-4c6d-831f-7c9078db86a6","target_id":"c45dbdda70a8b9f02b52af4991644d0b","source_type":"WIKI_ITEM","target_type":"CODE_SNIPPET","relationship_type":"CONTAINS","extra":"Wiki contains code snippet: frontend/package.json#11-27","gmt_create":"2026-04-23T15:22:23.552353+08:00","gmt_modified":"2026-04-23T15:22:23.552353+08:00"},{"id":454,"source_id":"aaf5bce6be82d2f947bfa5c1806de452","target_id":"c45dbdda70a8b9f02b52af4991644d0b","source_type":"SOURCE_FILE","target_type":"CODE_SNIPPET","relationship_type":"CONTAINS","extra":"Source file contains code snippet: 11-27","gmt_create":"2026-04-23T15:22:23.552845+08:00","gmt_modified":"2026-04-23T15:22:23.552845+08:00"},{"id":455,"source_id":"760610d4-dff6-4c6d-831f-7c9078db86a6","target_id":"6ac6943c93570294e4fb15a862be2616","source_type":"WIKI_ITEM","target_type":"CODE_SNIPPET","relationship_type":"CONTAINS","extra":"Wiki contains code snippet: frontend/components/ui/button.tsx#36-54","gmt_create":"2026-04-23T15:22:23.553797+08:00","gmt_modified":"2026-04-23T15:22:23.553797+08:00"},{"id":456,"source_id":"ac1acbc54c49ee1de13369f6c6827568","target_id":"6ac6943c93570294e4fb15a862be2616","source_type":"SOURCE_FILE","target_type":"CODE_SNIPPET","relationship_type":"CONTAINS","extra":"Source file contains code snippet: 36-54","gmt_create":"2026-04-23T15:22:23.554077+08:00","gmt_modified":"2026-04-23T15:22:23.554077+08:00"},{"id":457,"source_id":"760610d4-dff6-4c6d-831f-7c9078db86a6","target_id":"4bfb5059c685e9878aed64cb5347ccec","source_type":"WIKI_ITEM","target_type":"CODE_SNIPPET","relationship_type":"CONTAINS","extra":"Wiki contains code snippet: frontend/components/ui/dialog.tsx#9-54","gmt_create":"2026-04-23T15:22:23.554645+08:00","gmt_modified":"2026-04-23T15:22:23.554645+08:00"},{"id":458,"source_id":"108b0c4b4dcfb6aa39a5eb138225c148","target_id":"4bfb5059c685e9878aed64cb5347ccec","source_type":"SOURCE_FILE","target_type":"CODE_SNIPPET","relationship_type":"CONTAINS","extra":"Source file contains code snippet: 9-54","gmt_create":"2026-04-23T15:22:23.554875+08:00","gmt_modified":"2026-04-23T15:22:23.554875+08:00"},{"id":459,"source_id":"760610d4-dff6-4c6d-831f-7c9078db86a6","target_id":"0af48b69fe8fb9e480fa1656f36a4330","source_type":"WIKI_ITEM","target_type":"CODE_SNIPPET","relationship_type":"CONTAINS","extra":"Wiki contains code snippet: frontend/components/ui/dropdown-menu.tsx#21-75","gmt_create":"2026-04-23T15:22:23.555418+08:00","gmt_modified":"2026-04-23T15:22:23.555418+08:00"},{"id":460,"source_id":"0186dc8a89340139a84e1e3c5571a57f","target_id":"0af48b69fe8fb9e480fa1656f36a4330","source_type":"SOURCE_FILE","target_type":"CODE_SNIPPET","relationship_type":"CONTAINS","extra":"Source file contains code snippet: 21-75","gmt_create":"2026-04-23T15:22:23.55574+08:00","gmt_modified":"2026-04-23T15:22:23.55574+08:00"},{"id":461,"source_id":"760610d4-dff6-4c6d-831f-7c9078db86a6","target_id":"09971e31ab658e119d4c0ad948282107","source_type":"WIKI_ITEM","target_type":"CODE_SNIPPET","relationship_type":"CONTAINS","extra":"Wiki contains code snippet: frontend/components/ui/select.tsx#15-100","gmt_create":"2026-04-23T15:22:23.556401+08:00","gmt_modified":"2026-04-23T15:22:23.556401+08:00"},{"id":462,"source_id":"3c56e1c079959bfcc985183805e5874f","target_id":"09971e31ab658e119d4c0ad948282107","source_type":"SOURCE_FILE","target_type":"CODE_SNIPPET","relationship_type":"CONTAINS","extra":"Source file contains code snippet: 15-100","gmt_create":"2026-04-23T15:22:23.556634+08:00","gmt_modified":"2026-04-23T15:22:23.556634+08:00"},{"id":463,"source_id":"760610d4-dff6-4c6d-831f-7c9078db86a6","target_id":"31aa8777de6043883950d2668094e388","source_type":"WIKI_ITEM","target_type":"CODE_SNIPPET","relationship_type":"CONTAINS","extra":"Wiki contains code snippet: frontend/components/ui/table.tsx#5-106","gmt_create":"2026-04-23T15:22:23.55717+08:00","gmt_modified":"2026-04-23T15:22:23.55717+08:00"},{"id":464,"source_id":"0c0b0f4e2cf44facd9d5b57de0d0bf0c","target_id":"31aa8777de6043883950d2668094e388","source_type":"SOURCE_FILE","target_type":"CODE_SNIPPET","relationship_type":"CONTAINS","extra":"Source file contains code snippet: 5-106","gmt_create":"2026-04-23T15:22:23.557428+08:00","gmt_modified":"2026-04-23T15:22:23.557429+08:00"},{"id":465,"source_id":"760610d4-dff6-4c6d-831f-7c9078db86a6","target_id":"28baf3cedb89a21c6d542b7ce2439b24","source_type":"WIKI_ITEM","target_type":"CODE_SNIPPET","relationship_type":"CONTAINS","extra":"Wiki contains code snippet: frontend/components/ui/tabs.tsx#8-53","gmt_create":"2026-04-23T15:22:23.558002+08:00","gmt_modified":"2026-04-23T15:22:23.558002+08:00"},{"id":466,"source_id":"beb87ab5aad9532647e9dbd2db7ef587","target_id":"28baf3cedb89a21c6d542b7ce2439b24","source_type":"SOURCE_FILE","target_type":"CODE_SNIPPET","relationship_type":"CONTAINS","extra":"Source file contains code snippet: 8-53","gmt_create":"2026-04-23T15:22:23.558316+08:00","gmt_modified":"2026-04-23T15:22:23.558316+08:00"},{"id":467,"source_id":"760610d4-dff6-4c6d-831f-7c9078db86a6","target_id":"28b0f4797c6084272244175a24b961cb","source_type":"WIKI_ITEM","target_type":"CODE_SNIPPET","relationship_type":"CONTAINS","extra":"Wiki contains code snippet: frontend/components/ui/card.tsx#5-77","gmt_create":"2026-04-23T15:22:23.558858+08:00","gmt_modified":"2026-04-23T15:22:23.558858+08:00"},{"id":468,"source_id":"0d5ef537f7c0b8c390f8b31d7cf47b56","target_id":"28b0f4797c6084272244175a24b961cb","source_type":"SOURCE_FILE","target_type":"CODE_SNIPPET","relationship_type":"CONTAINS","extra":"Source file contains code snippet: 5-77","gmt_create":"2026-04-23T15:22:23.559082+08:00","gmt_modified":"2026-04-23T15:22:23.559082+08:00"},{"id":469,"source_id":"760610d4-dff6-4c6d-831f-7c9078db86a6","target_id":"a6e0b3fa65906c3c3cd88707e1d40059","source_type":"WIKI_ITEM","target_type":"CODE_SNIPPET","relationship_type":"CONTAINS","extra":"Wiki contains code snippet: frontend/components/ui/label.tsx#9-23","gmt_create":"2026-04-23T15:22:23.559653+08:00","gmt_modified":"2026-04-23T15:22:23.559653+08:00"},{"id":470,"source_id":"792b8e2c16c9ff2095d83b8972313be4","target_id":"a6e0b3fa65906c3c3cd88707e1d40059","source_type":"SOURCE_FILE","target_type":"CODE_SNIPPET","relationship_type":"CONTAINS","extra":"Source file contains code snippet: 9-23","gmt_create":"2026-04-23T15:22:23.560391+08:00","gmt_modified":"2026-04-23T15:22:23.560392+08:00"},{"id":471,"source_id":"760610d4-dff6-4c6d-831f-7c9078db86a6","target_id":"9a909775022010b4686c2b00cdf1c165","source_type":"WIKI_ITEM","target_type":"CODE_SNIPPET","relationship_type":"CONTAINS","extra":"Wiki contains code snippet: frontend/components/ui/badge.tsx#6-34","gmt_create":"2026-04-23T15:22:23.562216+08:00","gmt_modified":"2026-04-23T15:22:23.562216+08:00"},{"id":472,"source_id":"51821ca9ec2a1c972f3c9d111e19db8a","target_id":"9a909775022010b4686c2b00cdf1c165","source_type":"SOURCE_FILE","target_type":"CODE_SNIPPET","relationship_type":"CONTAINS","extra":"Source file contains code snippet: 6-34","gmt_create":"2026-04-23T15:22:23.562602+08:00","gmt_modified":"2026-04-23T15:22:23.562602+08:00"},{"id":473,"source_id":"760610d4-dff6-4c6d-831f-7c9078db86a6","target_id":"ce1cd184945ae56cf63f55168afd8050","source_type":"WIKI_ITEM","target_type":"CODE_SNIPPET","relationship_type":"CONTAINS","extra":"Wiki contains code snippet: frontend/components/ui/dialog.tsx#47-50","gmt_create":"2026-04-23T15:22:23.565009+08:00","gmt_modified":"2026-04-23T15:22:23.565009+08:00"},{"id":474,"source_id":"108b0c4b4dcfb6aa39a5eb138225c148","target_id":"ce1cd184945ae56cf63f55168afd8050","source_type":"SOURCE_FILE","target_type":"CODE_SNIPPET","relationship_type":"CONTAINS","extra":"Source file contains code snippet: 47-50","gmt_create":"2026-04-23T15:22:23.565469+08:00","gmt_modified":"2026-04-23T15:22:23.565469+08:00"},{"id":475,"source_id":"760610d4-dff6-4c6d-831f-7c9078db86a6","target_id":"4a2a06e1efcbc85deaa013dca155f20c","source_type":"WIKI_ITEM","target_type":"CODE_SNIPPET","relationship_type":"CONTAINS","extra":"Wiki contains code snippet: frontend/tailwind.config.ts#10-54","gmt_create":"2026-04-23T15:22:23.57102+08:00","gmt_modified":"2026-04-23T15:22:23.57102+08:00"},{"id":476,"source_id":"01056dad8851d3e9bd532eb4cab33792","target_id":"4a2a06e1efcbc85deaa013dca155f20c","source_type":"SOURCE_FILE","target_type":"CODE_SNIPPET","relationship_type":"CONTAINS","extra":"Source file contains code snippet: 10-54","gmt_create":"2026-04-23T15:22:23.571491+08:00","gmt_modified":"2026-04-23T15:22:23.571491+08:00"},{"id":477,"source_id":"760610d4-dff6-4c6d-831f-7c9078db86a6","target_id":"8b00ea4aba57ea6ed982287fb7840805","source_type":"WIKI_ITEM","target_type":"CODE_SNIPPET","relationship_type":"CONTAINS","extra":"Wiki contains code snippet: frontend/lib/utils.ts#4-6","gmt_create":"2026-04-23T15:22:23.572188+08:00","gmt_modified":"2026-04-23T15:22:23.572188+08:00"},{"id":478,"source_id":"f93ae024fe0a2e69698037dff6df205f","target_id":"8b00ea4aba57ea6ed982287fb7840805","source_type":"SOURCE_FILE","target_type":"CODE_SNIPPET","relationship_type":"CONTAINS","extra":"Source file contains code snippet: 4-6","gmt_create":"2026-04-23T15:22:23.572722+08:00","gmt_modified":"2026-04-23T15:22:23.572722+08:00"},{"id":483,"source_id":"deb919cc-9541-4ed7-a581-ae2876ea67c2","target_id":"2fc79486-ec65-4533-860a-89c8877c2ea0","source_type":"WIKI_ITEM","target_type":"WIKI_ITEM","relationship_type":"PARENT_CHILD","extra":"Wiki parent-child relationship: deb919cc-9541-4ed7-a581-ae2876ea67c2 -\u003e 2fc79486-ec65-4533-860a-89c8877c2ea0","gmt_create":"2026-04-23T15:22:24.563092+08:00","gmt_modified":"2026-04-23T15:22:24.563092+08:00"},{"id":484,"source_id":"deb919cc-9541-4ed7-a581-ae2876ea67c2","target_id":"d8e2cef5-37e6-44e7-8a7b-9bd365b82a72","source_type":"WIKI_ITEM","target_type":"WIKI_ITEM","relationship_type":"PARENT_CHILD","extra":"Wiki parent-child relationship: deb919cc-9541-4ed7-a581-ae2876ea67c2 -\u003e d8e2cef5-37e6-44e7-8a7b-9bd365b82a72","gmt_create":"2026-04-23T15:22:24.564188+08:00","gmt_modified":"2026-04-23T15:22:24.564188+08:00"},{"id":492,"source_id":"cfc48cde-e1c3-47f6-afe2-a6d7a8f4ab69","target_id":"a16cf42e9559523c4f96ca4c79f9488d","source_type":"WIKI_ITEM","target_type":"SOURCE_FILE","relationship_type":"REFERENCED_BY","extra":"Wiki references source file: backend/app/workers/platforms/base.py","gmt_create":"2026-04-23T20:31:36.520458+08:00","gmt_modified":"2026-04-23T20:31:36.520458+08:00"},{"id":493,"source_id":"cfc48cde-e1c3-47f6-afe2-a6d7a8f4ab69","target_id":"8f973791233c698b3e64a4fb28a93d4b","source_type":"WIKI_ITEM","target_type":"SOURCE_FILE","relationship_type":"REFERENCED_BY","extra":"Wiki references source file: backend/app/workers/platforms/kimi.py","gmt_create":"2026-04-23T20:31:36.521676+08:00","gmt_modified":"2026-04-23T20:31:36.521677+08:00"},{"id":494,"source_id":"cfc48cde-e1c3-47f6-afe2-a6d7a8f4ab69","target_id":"f642fc1c2f34e15572d9d98aa6c18813","source_type":"WIKI_ITEM","target_type":"SOURCE_FILE","relationship_type":"REFERENCED_BY","extra":"Wiki references source file: backend/app/workers/platforms/wenxin.py","gmt_create":"2026-04-23T20:31:36.522472+08:00","gmt_modified":"2026-04-23T20:31:36.522472+08:00"},{"id":495,"source_id":"cfc48cde-e1c3-47f6-afe2-a6d7a8f4ab69","target_id":"e68ad5186f1e47610ab3d9f14a794393","source_type":"WIKI_ITEM","target_type":"SOURCE_FILE","relationship_type":"REFERENCED_BY","extra":"Wiki references source file: backend/app/workers/platforms/tongyi.py","gmt_create":"2026-04-23T20:31:36.522898+08:00","gmt_modified":"2026-04-23T20:31:36.522898+08:00"},{"id":496,"source_id":"cfc48cde-e1c3-47f6-afe2-a6d7a8f4ab69","target_id":"404f6d0765a8c6e77e33b7fc21b377a4","source_type":"WIKI_ITEM","target_type":"SOURCE_FILE","relationship_type":"REFERENCED_BY","extra":"Wiki references source file: backend/app/workers/platforms/doubao.py","gmt_create":"2026-04-23T20:31:36.523305+08:00","gmt_modified":"2026-04-23T20:31:36.523305+08:00"},{"id":497,"source_id":"cfc48cde-e1c3-47f6-afe2-a6d7a8f4ab69","target_id":"303e80519e946904d1cb3ac32cbb0814","source_type":"WIKI_ITEM","target_type":"SOURCE_FILE","relationship_type":"REFERENCED_BY","extra":"Wiki references source file: backend/app/workers/platforms/qingyan.py","gmt_create":"2026-04-23T20:31:36.524292+08:00","gmt_modified":"2026-04-23T20:31:36.524292+08:00"},{"id":498,"source_id":"cfc48cde-e1c3-47f6-afe2-a6d7a8f4ab69","target_id":"5af7301fe056fc3d10820d820e8ad777","source_type":"WIKI_ITEM","target_type":"SOURCE_FILE","relationship_type":"REFERENCED_BY","extra":"Wiki references source file: backend/app/workers/platforms/tiangong.py","gmt_create":"2026-04-23T20:31:36.525283+08:00","gmt_modified":"2026-04-23T20:31:36.525283+08:00"},{"id":499,"source_id":"cfc48cde-e1c3-47f6-afe2-a6d7a8f4ab69","target_id":"0e38ad5d2d3daaad08c9302df8805b15","source_type":"WIKI_ITEM","target_type":"SOURCE_FILE","relationship_type":"REFERENCED_BY","extra":"Wiki references source file: backend/app/workers/platforms/xinghuo.py","gmt_create":"2026-04-23T20:31:36.52736+08:00","gmt_modified":"2026-04-23T20:31:36.52736+08:00"},{"id":500,"source_id":"cfc48cde-e1c3-47f6-afe2-a6d7a8f4ab69","target_id":"6a63f048c16c60c5d2d57012c810ee0e","source_type":"WIKI_ITEM","target_type":"SOURCE_FILE","relationship_type":"REFERENCED_BY","extra":"Wiki references source file: backend/app/workers/platforms/search_engine.py","gmt_create":"2026-04-23T20:31:36.527985+08:00","gmt_modified":"2026-04-23T20:31:36.527985+08:00"},{"id":501,"source_id":"cfc48cde-e1c3-47f6-afe2-a6d7a8f4ab69","target_id":"74040de652d5e57f548bb5c4adc3e1a0","source_type":"WIKI_ITEM","target_type":"SOURCE_FILE","relationship_type":"REFERENCED_BY","extra":"Wiki references source file: backend/app/workers/citation_engine.py","gmt_create":"2026-04-23T20:31:36.530076+08:00","gmt_modified":"2026-04-23T20:31:36.530076+08:00"},{"id":502,"source_id":"cfc48cde-e1c3-47f6-afe2-a6d7a8f4ab69","target_id":"9ff19022ef915615911280e3c49ed44b","source_type":"WIKI_ITEM","target_type":"SOURCE_FILE","relationship_type":"REFERENCED_BY","extra":"Wiki references source file: backend/app/config.py","gmt_create":"2026-04-23T20:31:36.531496+08:00","gmt_modified":"2026-04-23T20:31:36.531496+08:00"},{"id":503,"source_id":"cfc48cde-e1c3-47f6-afe2-a6d7a8f4ab69","target_id":"b74caccb06844efcdb14d8324cff65c2","source_type":"WIKI_ITEM","target_type":"SOURCE_FILE","relationship_type":"REFERENCED_BY","extra":"Wiki references source file: backend/app/models/query.py","gmt_create":"2026-04-23T20:31:36.532308+08:00","gmt_modified":"2026-04-23T20:31:36.532308+08:00"},{"id":504,"source_id":"cfc48cde-e1c3-47f6-afe2-a6d7a8f4ab69","target_id":"b4a81ef789630d0af6a8d50859d01bf3","source_type":"WIKI_ITEM","target_type":"SOURCE_FILE","relationship_type":"REFERENCED_BY","extra":"Wiki references source file: backend/app/models/citation_record.py","gmt_create":"2026-04-23T20:31:36.533202+08:00","gmt_modified":"2026-04-23T20:31:36.533203+08:00"},{"id":505,"source_id":"cfc48cde-e1c3-47f6-afe2-a6d7a8f4ab69","target_id":"069738f21ac2da7349d22683e8c36929","source_type":"WIKI_ITEM","target_type":"SOURCE_FILE","relationship_type":"REFERENCED_BY","extra":"Wiki references source file: backend/app/models/query_task.py","gmt_create":"2026-04-23T20:31:36.533733+08:00","gmt_modified":"2026-04-23T20:31:36.533733+08:00"},{"id":506,"source_id":"cfc48cde-e1c3-47f6-afe2-a6d7a8f4ab69","target_id":"5cbb1e3f112aeba62a14b0b8999fc0f5","source_type":"WIKI_ITEM","target_type":"SOURCE_FILE","relationship_type":"REFERENCED_BY","extra":"Wiki references source file: backend/app/workers/scheduler.py","gmt_create":"2026-04-23T20:31:36.534166+08:00","gmt_modified":"2026-04-23T20:31:36.534166+08:00"},{"id":507,"source_id":"cfc48cde-e1c3-47f6-afe2-a6d7a8f4ab69","target_id":"7538ffe4902ab6041adb28b19844962a","source_type":"WIKI_ITEM","target_type":"SOURCE_FILE","relationship_type":"REFERENCED_BY","extra":"Wiki references source file: backend/app/api/citations.py","gmt_create":"2026-04-23T20:31:36.535208+08:00","gmt_modified":"2026-04-23T20:31:36.535208+08:00"},{"id":508,"source_id":"cfc48cde-e1c3-47f6-afe2-a6d7a8f4ab69","target_id":"04e3926c080e795713bff683e7dc9d3e","source_type":"WIKI_ITEM","target_type":"SOURCE_FILE","relationship_type":"REFERENCED_BY","extra":"Wiki references source file: backend/app/services/citation.py","gmt_create":"2026-04-23T20:31:36.536177+08:00","gmt_modified":"2026-04-23T20:31:36.536177+08:00"},{"id":509,"source_id":"cfc48cde-e1c3-47f6-afe2-a6d7a8f4ab69","target_id":"ef72f0c3cedb9fd9a87352fe493053dc","source_type":"WIKI_ITEM","target_type":"SOURCE_FILE","relationship_type":"REFERENCED_BY","extra":"Wiki references source file: frontend/lib/platforms.ts","gmt_create":"2026-04-23T20:31:36.536784+08:00","gmt_modified":"2026-04-23T20:31:36.536784+08:00"},{"id":510,"source_id":"cfc48cde-e1c3-47f6-afe2-a6d7a8f4ab69","target_id":"b07a4fb9cecbbd66a6910ccbc7651f19","source_type":"WIKI_ITEM","target_type":"SOURCE_FILE","relationship_type":"REFERENCED_BY","extra":"Wiki references source file: tests/test_citation_engine.py","gmt_create":"2026-04-23T20:31:36.537249+08:00","gmt_modified":"2026-04-23T20:31:36.537249+08:00"},{"id":511,"source_id":"cfc48cde-e1c3-47f6-afe2-a6d7a8f4ab69","target_id":"a26ee01cf41da3b956e1650448c156fa","source_type":"WIKI_ITEM","target_type":"SOURCE_FILE","relationship_type":"REFERENCED_BY","extra":"Wiki references source file: backend/requirements.txt","gmt_create":"2026-04-23T20:31:36.53817+08:00","gmt_modified":"2026-04-23T20:31:36.538171+08:00"},{"id":512,"source_id":"cfc48cde-e1c3-47f6-afe2-a6d7a8f4ab69","target_id":"cbd0101fa84d957bcb1baaa623c6b31c","source_type":"WIKI_ITEM","target_type":"CODE_SNIPPET","relationship_type":"CONTAINS","extra":"Wiki contains code snippet: backend/app/api/citations.py#1-78","gmt_create":"2026-04-23T20:31:36.53929+08:00","gmt_modified":"2026-04-23T20:31:36.53929+08:00"},{"id":513,"source_id":"cfc48cde-e1c3-47f6-afe2-a6d7a8f4ab69","target_id":"7c0831c17e8c65eaed9511e17ed2a2ef","source_type":"WIKI_ITEM","target_type":"CODE_SNIPPET","relationship_type":"CONTAINS","extra":"Wiki contains code snippet: backend/app/services/citation.py#1-269","gmt_create":"2026-04-23T20:31:36.540413+08:00","gmt_modified":"2026-04-23T20:31:36.540413+08:00"},{"id":514,"source_id":"04e3926c080e795713bff683e7dc9d3e","target_id":"7c0831c17e8c65eaed9511e17ed2a2ef","source_type":"SOURCE_FILE","target_type":"CODE_SNIPPET","relationship_type":"CONTAINS","extra":"Source file contains code snippet: 1-269","gmt_create":"2026-04-23T20:31:36.541301+08:00","gmt_modified":"2026-04-23T20:31:36.541301+08:00"},{"id":515,"source_id":"cfc48cde-e1c3-47f6-afe2-a6d7a8f4ab69","target_id":"71f98c8993fb42b108e34a554247869b","source_type":"WIKI_ITEM","target_type":"CODE_SNIPPET","relationship_type":"CONTAINS","extra":"Wiki contains code snippet: backend/app/workers/scheduler.py#1-95","gmt_create":"2026-04-23T20:31:36.541996+08:00","gmt_modified":"2026-04-23T20:31:36.541996+08:00"},{"id":516,"source_id":"5cbb1e3f112aeba62a14b0b8999fc0f5","target_id":"71f98c8993fb42b108e34a554247869b","source_type":"SOURCE_FILE","target_type":"CODE_SNIPPET","relationship_type":"CONTAINS","extra":"Source file contains code snippet: 1-95","gmt_create":"2026-04-23T20:31:36.542269+08:00","gmt_modified":"2026-04-23T20:31:36.542269+08:00"},{"id":517,"source_id":"cfc48cde-e1c3-47f6-afe2-a6d7a8f4ab69","target_id":"8d5aac2ae0671f05d7c0807ba9296cdf","source_type":"WIKI_ITEM","target_type":"CODE_SNIPPET","relationship_type":"CONTAINS","extra":"Wiki contains code snippet: backend/app/workers/citation_engine.py#1-330","gmt_create":"2026-04-23T20:31:36.543463+08:00","gmt_modified":"2026-04-23T20:31:36.543463+08:00"},{"id":518,"source_id":"74040de652d5e57f548bb5c4adc3e1a0","target_id":"8d5aac2ae0671f05d7c0807ba9296cdf","source_type":"SOURCE_FILE","target_type":"CODE_SNIPPET","relationship_type":"CONTAINS","extra":"Source file contains code snippet: 1-330","gmt_create":"2026-04-23T20:31:36.543912+08:00","gmt_modified":"2026-04-23T20:31:36.543912+08:00"},{"id":519,"source_id":"cfc48cde-e1c3-47f6-afe2-a6d7a8f4ab69","target_id":"debd789847d1eed2d54198772edf68a2","source_type":"WIKI_ITEM","target_type":"CODE_SNIPPET","relationship_type":"CONTAINS","extra":"Wiki contains code snippet: backend/app/workers/platforms/tongyi.py#1-38","gmt_create":"2026-04-23T20:31:36.545278+08:00","gmt_modified":"2026-04-23T20:31:36.545279+08:00"},{"id":520,"source_id":"e68ad5186f1e47610ab3d9f14a794393","target_id":"debd789847d1eed2d54198772edf68a2","source_type":"SOURCE_FILE","target_type":"CODE_SNIPPET","relationship_type":"CONTAINS","extra":"Source file contains code snippet: 1-38","gmt_create":"2026-04-23T20:31:36.545752+08:00","gmt_modified":"2026-04-23T20:31:36.545752+08:00"},{"id":521,"source_id":"cfc48cde-e1c3-47f6-afe2-a6d7a8f4ab69","target_id":"3bde521d18cc7221ae2f14637e163aac","source_type":"WIKI_ITEM","target_type":"CODE_SNIPPET","relationship_type":"CONTAINS","extra":"Wiki contains code snippet: backend/app/workers/platforms/doubao.py#1-38","gmt_create":"2026-04-23T20:31:36.546456+08:00","gmt_modified":"2026-04-23T20:31:36.546457+08:00"},{"id":522,"source_id":"404f6d0765a8c6e77e33b7fc21b377a4","target_id":"3bde521d18cc7221ae2f14637e163aac","source_type":"SOURCE_FILE","target_type":"CODE_SNIPPET","relationship_type":"CONTAINS","extra":"Source file contains code snippet: 1-38","gmt_create":"2026-04-23T20:31:36.546804+08:00","gmt_modified":"2026-04-23T20:31:36.546804+08:00"},{"id":523,"source_id":"cfc48cde-e1c3-47f6-afe2-a6d7a8f4ab69","target_id":"c26862d9e0fc878b51a2668cfd2ec827","source_type":"WIKI_ITEM","target_type":"CODE_SNIPPET","relationship_type":"CONTAINS","extra":"Wiki contains code snippet: backend/app/workers/platforms/qingyan.py#1-38","gmt_create":"2026-04-23T20:31:36.547594+08:00","gmt_modified":"2026-04-23T20:31:36.547594+08:00"},{"id":524,"source_id":"303e80519e946904d1cb3ac32cbb0814","target_id":"c26862d9e0fc878b51a2668cfd2ec827","source_type":"SOURCE_FILE","target_type":"CODE_SNIPPET","relationship_type":"CONTAINS","extra":"Source file contains code snippet: 1-38","gmt_create":"2026-04-23T20:31:36.548009+08:00","gmt_modified":"2026-04-23T20:31:36.548009+08:00"},{"id":525,"source_id":"cfc48cde-e1c3-47f6-afe2-a6d7a8f4ab69","target_id":"0fcc9c2e0d33b887c5f18a3807b64a1e","source_type":"WIKI_ITEM","target_type":"CODE_SNIPPET","relationship_type":"CONTAINS","extra":"Wiki contains code snippet: backend/app/workers/platforms/tiangong.py#1-38","gmt_create":"2026-04-23T20:31:36.548333+08:00","gmt_modified":"2026-04-23T20:31:36.548333+08:00"},{"id":526,"source_id":"5af7301fe056fc3d10820d820e8ad777","target_id":"0fcc9c2e0d33b887c5f18a3807b64a1e","source_type":"SOURCE_FILE","target_type":"CODE_SNIPPET","relationship_type":"CONTAINS","extra":"Source file contains code snippet: 1-38","gmt_create":"2026-04-23T20:31:36.548917+08:00","gmt_modified":"2026-04-23T20:31:36.548917+08:00"},{"id":527,"source_id":"cfc48cde-e1c3-47f6-afe2-a6d7a8f4ab69","target_id":"a4baa2444208b3f9a3f42bc492038207","source_type":"WIKI_ITEM","target_type":"CODE_SNIPPET","relationship_type":"CONTAINS","extra":"Wiki contains code snippet: backend/app/workers/platforms/xinghuo.py#1-38","gmt_create":"2026-04-23T20:31:36.549296+08:00","gmt_modified":"2026-04-23T20:31:36.549296+08:00"},{"id":528,"source_id":"0e38ad5d2d3daaad08c9302df8805b15","target_id":"a4baa2444208b3f9a3f42bc492038207","source_type":"SOURCE_FILE","target_type":"CODE_SNIPPET","relationship_type":"CONTAINS","extra":"Source file contains code snippet: 1-38","gmt_create":"2026-04-23T20:31:36.54956+08:00","gmt_modified":"2026-04-23T20:31:36.54956+08:00"},{"id":529,"source_id":"cfc48cde-e1c3-47f6-afe2-a6d7a8f4ab69","target_id":"9f82f6d82bf914a608d6afa3d9854abf","source_type":"WIKI_ITEM","target_type":"CODE_SNIPPET","relationship_type":"CONTAINS","extra":"Wiki contains code snippet: backend/app/workers/platforms/search_engine.py#1-174","gmt_create":"2026-04-23T20:31:36.549907+08:00","gmt_modified":"2026-04-23T20:31:36.549907+08:00"},{"id":530,"source_id":"6a63f048c16c60c5d2d57012c810ee0e","target_id":"9f82f6d82bf914a608d6afa3d9854abf","source_type":"SOURCE_FILE","target_type":"CODE_SNIPPET","relationship_type":"CONTAINS","extra":"Source file contains code snippet: 1-174","gmt_create":"2026-04-23T20:31:36.55085+08:00","gmt_modified":"2026-04-23T20:31:36.55085+08:00"},{"id":531,"source_id":"cfc48cde-e1c3-47f6-afe2-a6d7a8f4ab69","target_id":"84fbed7d35f7752e2117a74fcaf5f0e9","source_type":"WIKI_ITEM","target_type":"CODE_SNIPPET","relationship_type":"CONTAINS","extra":"Wiki contains code snippet: backend/app/config.py#1-17","gmt_create":"2026-04-23T20:31:36.551428+08:00","gmt_modified":"2026-04-23T20:31:36.551428+08:00"},{"id":532,"source_id":"cfc48cde-e1c3-47f6-afe2-a6d7a8f4ab69","target_id":"6281fff17a86ec1895c64d87c2ae7fb1","source_type":"WIKI_ITEM","target_type":"CODE_SNIPPET","relationship_type":"CONTAINS","extra":"Wiki contains code snippet: backend/app/models/query.py#1-55","gmt_create":"2026-04-23T20:31:36.552386+08:00","gmt_modified":"2026-04-23T20:31:36.552386+08:00"},{"id":533,"source_id":"b74caccb06844efcdb14d8324cff65c2","target_id":"6281fff17a86ec1895c64d87c2ae7fb1","source_type":"SOURCE_FILE","target_type":"CODE_SNIPPET","relationship_type":"CONTAINS","extra":"Source file contains code snippet: 1-55","gmt_create":"2026-04-23T20:31:36.553134+08:00","gmt_modified":"2026-04-23T20:31:36.553134+08:00"},{"id":534,"source_id":"cfc48cde-e1c3-47f6-afe2-a6d7a8f4ab69","target_id":"943c18db69a04b3137fba4cebcfea87e","source_type":"WIKI_ITEM","target_type":"CODE_SNIPPET","relationship_type":"CONTAINS","extra":"Wiki contains code snippet: backend/app/models/citation_record.py#1-42","gmt_create":"2026-04-23T20:31:36.553656+08:00","gmt_modified":"2026-04-23T20:31:36.553656+08:00"},{"id":535,"source_id":"b4a81ef789630d0af6a8d50859d01bf3","target_id":"943c18db69a04b3137fba4cebcfea87e","source_type":"SOURCE_FILE","target_type":"CODE_SNIPPET","relationship_type":"CONTAINS","extra":"Source file contains code snippet: 1-42","gmt_create":"2026-04-23T20:31:36.554174+08:00","gmt_modified":"2026-04-23T20:31:36.554174+08:00"},{"id":536,"source_id":"cfc48cde-e1c3-47f6-afe2-a6d7a8f4ab69","target_id":"6628e006b8e5ca16160743528b6b0506","source_type":"WIKI_ITEM","target_type":"CODE_SNIPPET","relationship_type":"CONTAINS","extra":"Wiki contains code snippet: backend/app/models/query_task.py#1-39","gmt_create":"2026-04-23T20:31:36.555503+08:00","gmt_modified":"2026-04-23T20:31:36.555503+08:00"},{"id":537,"source_id":"069738f21ac2da7349d22683e8c36929","target_id":"6628e006b8e5ca16160743528b6b0506","source_type":"SOURCE_FILE","target_type":"CODE_SNIPPET","relationship_type":"CONTAINS","extra":"Source file contains code snippet: 1-39","gmt_create":"2026-04-23T20:31:36.556658+08:00","gmt_modified":"2026-04-23T20:31:36.556658+08:00"},{"id":538,"source_id":"cfc48cde-e1c3-47f6-afe2-a6d7a8f4ab69","target_id":"72a110dca58d8152758e2fdab4e94761","source_type":"WIKI_ITEM","target_type":"CODE_SNIPPET","relationship_type":"CONTAINS","extra":"Wiki contains code snippet: backend/app/workers/platforms/base.py#1-18","gmt_create":"2026-04-23T20:31:36.558991+08:00","gmt_modified":"2026-04-23T20:31:36.558991+08:00"},{"id":539,"source_id":"a16cf42e9559523c4f96ca4c79f9488d","target_id":"72a110dca58d8152758e2fdab4e94761","source_type":"SOURCE_FILE","target_type":"CODE_SNIPPET","relationship_type":"CONTAINS","extra":"Source file contains code snippet: 1-18","gmt_create":"2026-04-23T20:31:36.559781+08:00","gmt_modified":"2026-04-23T20:31:36.559781+08:00"},{"id":540,"source_id":"cfc48cde-e1c3-47f6-afe2-a6d7a8f4ab69","target_id":"300e43c7a648440163f81039eaa47b5a","source_type":"WIKI_ITEM","target_type":"CODE_SNIPPET","relationship_type":"CONTAINS","extra":"Wiki contains code snippet: frontend/lib/platforms.ts#1-24","gmt_create":"2026-04-23T20:31:36.563289+08:00","gmt_modified":"2026-04-23T20:31:36.563289+08:00"},{"id":541,"source_id":"ef72f0c3cedb9fd9a87352fe493053dc","target_id":"300e43c7a648440163f81039eaa47b5a","source_type":"SOURCE_FILE","target_type":"CODE_SNIPPET","relationship_type":"CONTAINS","extra":"Source file contains code snippet: 1-24","gmt_create":"2026-04-23T20:31:36.563813+08:00","gmt_modified":"2026-04-23T20:31:36.563813+08:00"},{"id":542,"source_id":"cfc48cde-e1c3-47f6-afe2-a6d7a8f4ab69","target_id":"caf1970ded8fc5d3921005e166e2100b","source_type":"WIKI_ITEM","target_type":"CODE_SNIPPET","relationship_type":"CONTAINS","extra":"Wiki contains code snippet: backend/app/api/citations.py#59-78","gmt_create":"2026-04-23T20:31:36.567359+08:00","gmt_modified":"2026-04-23T20:31:36.567359+08:00"},{"id":543,"source_id":"7538ffe4902ab6041adb28b19844962a","target_id":"caf1970ded8fc5d3921005e166e2100b","source_type":"SOURCE_FILE","target_type":"CODE_SNIPPET","relationship_type":"CONTAINS","extra":"Source file contains code snippet: 59-78","gmt_create":"2026-04-23T20:31:36.567845+08:00","gmt_modified":"2026-04-23T20:31:36.567845+08:00"},{"id":544,"source_id":"cfc48cde-e1c3-47f6-afe2-a6d7a8f4ab69","target_id":"4ded871d02b8119cdd985de8b220b084","source_type":"WIKI_ITEM","target_type":"CODE_SNIPPET","relationship_type":"CONTAINS","extra":"Wiki contains code snippet: backend/app/services/citation.py#204-234","gmt_create":"2026-04-23T20:31:36.568622+08:00","gmt_modified":"2026-04-23T20:31:36.568622+08:00"},{"id":545,"source_id":"04e3926c080e795713bff683e7dc9d3e","target_id":"4ded871d02b8119cdd985de8b220b084","source_type":"SOURCE_FILE","target_type":"CODE_SNIPPET","relationship_type":"CONTAINS","extra":"Source file contains code snippet: 204-234","gmt_create":"2026-04-23T20:31:36.569217+08:00","gmt_modified":"2026-04-23T20:31:36.569217+08:00"},{"id":546,"source_id":"cfc48cde-e1c3-47f6-afe2-a6d7a8f4ab69","target_id":"448970b02d89d5e1576f70bdb0063363","source_type":"WIKI_ITEM","target_type":"CODE_SNIPPET","relationship_type":"CONTAINS","extra":"Wiki contains code snippet: backend/app/workers/scheduler.py#51-84","gmt_create":"2026-04-23T20:31:36.569785+08:00","gmt_modified":"2026-04-23T20:31:36.569785+08:00"},{"id":547,"source_id":"5cbb1e3f112aeba62a14b0b8999fc0f5","target_id":"448970b02d89d5e1576f70bdb0063363","source_type":"SOURCE_FILE","target_type":"CODE_SNIPPET","relationship_type":"CONTAINS","extra":"Source file contains code snippet: 51-84","gmt_create":"2026-04-23T20:31:36.570169+08:00","gmt_modified":"2026-04-23T20:31:36.570169+08:00"},{"id":548,"source_id":"cfc48cde-e1c3-47f6-afe2-a6d7a8f4ab69","target_id":"362d22f423631cda39404660b3317a2f","source_type":"WIKI_ITEM","target_type":"CODE_SNIPPET","relationship_type":"CONTAINS","extra":"Wiki contains code snippet: backend/app/workers/citation_engine.py#177-254","gmt_create":"2026-04-23T20:31:36.570576+08:00","gmt_modified":"2026-04-23T20:31:36.570576+08:00"},{"id":549,"source_id":"74040de652d5e57f548bb5c4adc3e1a0","target_id":"362d22f423631cda39404660b3317a2f","source_type":"SOURCE_FILE","target_type":"CODE_SNIPPET","relationship_type":"CONTAINS","extra":"Source file contains code snippet: 177-254","gmt_create":"2026-04-23T20:31:36.571472+08:00","gmt_modified":"2026-04-23T20:31:36.571472+08:00"},{"id":550,"source_id":"cfc48cde-e1c3-47f6-afe2-a6d7a8f4ab69","target_id":"b475ff5225ac403c7fcf3dd7e14cbac6","source_type":"WIKI_ITEM","target_type":"CODE_SNIPPET","relationship_type":"CONTAINS","extra":"Wiki contains code snippet: backend/app/workers/platforms/tongyi.py#16-33","gmt_create":"2026-04-23T20:31:36.572484+08:00","gmt_modified":"2026-04-23T20:31:36.572484+08:00"},{"id":551,"source_id":"e68ad5186f1e47610ab3d9f14a794393","target_id":"b475ff5225ac403c7fcf3dd7e14cbac6","source_type":"SOURCE_FILE","target_type":"CODE_SNIPPET","relationship_type":"CONTAINS","extra":"Source file contains code snippet: 16-33","gmt_create":"2026-04-23T20:31:36.573312+08:00","gmt_modified":"2026-04-23T20:31:36.573312+08:00"},{"id":552,"source_id":"cfc48cde-e1c3-47f6-afe2-a6d7a8f4ab69","target_id":"557ae34b57a5dd8e8fa3bb2a6ce178a7","source_type":"WIKI_ITEM","target_type":"CODE_SNIPPET","relationship_type":"CONTAINS","extra":"Wiki contains code snippet: backend/app/workers/platforms/search_engine.py#163-174","gmt_create":"2026-04-23T20:31:36.574111+08:00","gmt_modified":"2026-04-23T20:31:36.574112+08:00"},{"id":553,"source_id":"6a63f048c16c60c5d2d57012c810ee0e","target_id":"557ae34b57a5dd8e8fa3bb2a6ce178a7","source_type":"SOURCE_FILE","target_type":"CODE_SNIPPET","relationship_type":"CONTAINS","extra":"Source file contains code snippet: 163-174","gmt_create":"2026-04-23T20:31:36.574746+08:00","gmt_modified":"2026-04-23T20:31:36.574746+08:00"},{"id":554,"source_id":"cfc48cde-e1c3-47f6-afe2-a6d7a8f4ab69","target_id":"75c6ab0599d304bf36d290d4143d3d2f","source_type":"WIKI_ITEM","target_type":"CODE_SNIPPET","relationship_type":"CONTAINS","extra":"Wiki contains code snippet: backend/app/models/query.py#29-31","gmt_create":"2026-04-23T20:31:36.590144+08:00","gmt_modified":"2026-04-23T20:31:36.590144+08:00"},{"id":555,"source_id":"b74caccb06844efcdb14d8324cff65c2","target_id":"75c6ab0599d304bf36d290d4143d3d2f","source_type":"SOURCE_FILE","target_type":"CODE_SNIPPET","relationship_type":"CONTAINS","extra":"Source file contains code snippet: 29-31","gmt_create":"2026-04-23T20:31:36.591214+08:00","gmt_modified":"2026-04-23T20:31:36.591214+08:00"},{"id":556,"source_id":"cfc48cde-e1c3-47f6-afe2-a6d7a8f4ab69","target_id":"fd541971cebf8a7c167d717f5c5d1ff6","source_type":"WIKI_ITEM","target_type":"CODE_SNIPPET","relationship_type":"CONTAINS","extra":"Wiki contains code snippet: backend/app/models/citation_record.py#11-42","gmt_create":"2026-04-23T20:31:36.591664+08:00","gmt_modified":"2026-04-23T20:31:36.591664+08:00"},{"id":557,"source_id":"cfc48cde-e1c3-47f6-afe2-a6d7a8f4ab69","target_id":"b84f46f058847733347974841f613688","source_type":"WIKI_ITEM","target_type":"CODE_SNIPPET","relationship_type":"CONTAINS","extra":"Wiki contains code snippet: backend/app/models/query_task.py#11-39","gmt_create":"2026-04-23T20:31:36.592665+08:00","gmt_modified":"2026-04-23T20:31:36.592666+08:00"},{"id":558,"source_id":"cfc48cde-e1c3-47f6-afe2-a6d7a8f4ab69","target_id":"2a6780838f1415dcb7d0fa611f64cee7","source_type":"WIKI_ITEM","target_type":"CODE_SNIPPET","relationship_type":"CONTAINS","extra":"Wiki contains code snippet: backend/app/workers/platforms/base.py#4-17","gmt_create":"2026-04-23T20:31:36.593186+08:00","gmt_modified":"2026-04-23T20:31:36.593186+08:00"},{"id":559,"source_id":"a16cf42e9559523c4f96ca4c79f9488d","target_id":"2a6780838f1415dcb7d0fa611f64cee7","source_type":"SOURCE_FILE","target_type":"CODE_SNIPPET","relationship_type":"CONTAINS","extra":"Source file contains code snippet: 4-17","gmt_create":"2026-04-23T20:31:36.59372+08:00","gmt_modified":"2026-04-23T20:31:36.59372+08:00"},{"id":560,"source_id":"cfc48cde-e1c3-47f6-afe2-a6d7a8f4ab69","target_id":"c5ae7697193b2b93425ff25d2d7d54a9","source_type":"WIKI_ITEM","target_type":"CODE_SNIPPET","relationship_type":"CONTAINS","extra":"Wiki contains code snippet: backend/app/workers/platforms/tongyi.py#10-38","gmt_create":"2026-04-23T20:31:36.595227+08:00","gmt_modified":"2026-04-23T20:31:36.595227+08:00"},{"id":561,"source_id":"e68ad5186f1e47610ab3d9f14a794393","target_id":"c5ae7697193b2b93425ff25d2d7d54a9","source_type":"SOURCE_FILE","target_type":"CODE_SNIPPET","relationship_type":"CONTAINS","extra":"Source file contains code snippet: 10-38","gmt_create":"2026-04-23T20:31:36.596503+08:00","gmt_modified":"2026-04-23T20:31:36.596503+08:00"},{"id":562,"source_id":"cfc48cde-e1c3-47f6-afe2-a6d7a8f4ab69","target_id":"aa8c3fa3bc509dafe64d113bdd09eafa","source_type":"WIKI_ITEM","target_type":"CODE_SNIPPET","relationship_type":"CONTAINS","extra":"Wiki contains code snippet: backend/app/workers/platforms/doubao.py#10-38","gmt_create":"2026-04-23T20:31:36.597069+08:00","gmt_modified":"2026-04-23T20:31:36.597069+08:00"},{"id":563,"source_id":"404f6d0765a8c6e77e33b7fc21b377a4","target_id":"aa8c3fa3bc509dafe64d113bdd09eafa","source_type":"SOURCE_FILE","target_type":"CODE_SNIPPET","relationship_type":"CONTAINS","extra":"Source file contains code snippet: 10-38","gmt_create":"2026-04-23T20:31:36.597765+08:00","gmt_modified":"2026-04-23T20:31:36.597765+08:00"},{"id":564,"source_id":"cfc48cde-e1c3-47f6-afe2-a6d7a8f4ab69","target_id":"eabb031e538ea62cab69b01368740d20","source_type":"WIKI_ITEM","target_type":"CODE_SNIPPET","relationship_type":"CONTAINS","extra":"Wiki contains code snippet: backend/app/workers/platforms/qingyan.py#10-38","gmt_create":"2026-04-23T20:31:36.598445+08:00","gmt_modified":"2026-04-23T20:31:36.598445+08:00"},{"id":565,"source_id":"303e80519e946904d1cb3ac32cbb0814","target_id":"eabb031e538ea62cab69b01368740d20","source_type":"SOURCE_FILE","target_type":"CODE_SNIPPET","relationship_type":"CONTAINS","extra":"Source file contains code snippet: 10-38","gmt_create":"2026-04-23T20:31:36.599093+08:00","gmt_modified":"2026-04-23T20:31:36.599093+08:00"},{"id":566,"source_id":"cfc48cde-e1c3-47f6-afe2-a6d7a8f4ab69","target_id":"b1c09e372a63e9854886adaea1663bea","source_type":"WIKI_ITEM","target_type":"CODE_SNIPPET","relationship_type":"CONTAINS","extra":"Wiki contains code snippet: backend/app/workers/platforms/tiangong.py#10-38","gmt_create":"2026-04-23T20:31:36.599896+08:00","gmt_modified":"2026-04-23T20:31:36.599896+08:00"},{"id":567,"source_id":"5af7301fe056fc3d10820d820e8ad777","target_id":"b1c09e372a63e9854886adaea1663bea","source_type":"SOURCE_FILE","target_type":"CODE_SNIPPET","relationship_type":"CONTAINS","extra":"Source file contains code snippet: 10-38","gmt_create":"2026-04-23T20:31:36.600604+08:00","gmt_modified":"2026-04-23T20:31:36.600604+08:00"},{"id":568,"source_id":"cfc48cde-e1c3-47f6-afe2-a6d7a8f4ab69","target_id":"79793bcd507f9d287d19014b60d963d3","source_type":"WIKI_ITEM","target_type":"CODE_SNIPPET","relationship_type":"CONTAINS","extra":"Wiki contains code snippet: backend/app/workers/platforms/xinghuo.py#10-38","gmt_create":"2026-04-23T20:31:36.601204+08:00","gmt_modified":"2026-04-23T20:31:36.601204+08:00"},{"id":569,"source_id":"0e38ad5d2d3daaad08c9302df8805b15","target_id":"79793bcd507f9d287d19014b60d963d3","source_type":"SOURCE_FILE","target_type":"CODE_SNIPPET","relationship_type":"CONTAINS","extra":"Source file contains code snippet: 10-38","gmt_create":"2026-04-23T20:31:36.60148+08:00","gmt_modified":"2026-04-23T20:31:36.60148+08:00"},{"id":570,"source_id":"cfc48cde-e1c3-47f6-afe2-a6d7a8f4ab69","target_id":"102223dd13475177a1ade8b9be14fbd1","source_type":"WIKI_ITEM","target_type":"CODE_SNIPPET","relationship_type":"CONTAINS","extra":"Wiki contains code snippet: backend/app/workers/platforms/search_engine.py#79-144","gmt_create":"2026-04-23T20:31:36.603752+08:00","gmt_modified":"2026-04-23T20:31:36.603752+08:00"},{"id":571,"source_id":"6a63f048c16c60c5d2d57012c810ee0e","target_id":"102223dd13475177a1ade8b9be14fbd1","source_type":"SOURCE_FILE","target_type":"CODE_SNIPPET","relationship_type":"CONTAINS","extra":"Source file contains code snippet: 79-144","gmt_create":"2026-04-23T20:31:36.606514+08:00","gmt_modified":"2026-04-23T20:31:36.606514+08:00"},{"id":572,"source_id":"cfc48cde-e1c3-47f6-afe2-a6d7a8f4ab69","target_id":"8565f299083b4dcba5a328c947f06fee","source_type":"WIKI_ITEM","target_type":"CODE_SNIPPET","relationship_type":"CONTAINS","extra":"Wiki contains code snippet: backend/app/workers/citation_engine.py#256-287","gmt_create":"2026-04-23T20:31:36.609013+08:00","gmt_modified":"2026-04-23T20:31:36.609013+08:00"},{"id":573,"source_id":"74040de652d5e57f548bb5c4adc3e1a0","target_id":"8565f299083b4dcba5a328c947f06fee","source_type":"SOURCE_FILE","target_type":"CODE_SNIPPET","relationship_type":"CONTAINS","extra":"Source file contains code snippet: 256-287","gmt_create":"2026-04-23T20:31:36.609501+08:00","gmt_modified":"2026-04-23T20:31:36.609501+08:00"},{"id":574,"source_id":"cfc48cde-e1c3-47f6-afe2-a6d7a8f4ab69","target_id":"8af91caf063c12c8236f9675769ce4a1","source_type":"WIKI_ITEM","target_type":"CODE_SNIPPET","relationship_type":"CONTAINS","extra":"Wiki contains code snippet: tests/test_citation_engine.py#1-54","gmt_create":"2026-04-23T20:31:36.610558+08:00","gmt_modified":"2026-04-23T20:31:36.610558+08:00"},{"id":575,"source_id":"b07a4fb9cecbbd66a6910ccbc7651f19","target_id":"8af91caf063c12c8236f9675769ce4a1","source_type":"SOURCE_FILE","target_type":"CODE_SNIPPET","relationship_type":"CONTAINS","extra":"Source file contains code snippet: 1-54","gmt_create":"2026-04-23T20:31:36.610946+08:00","gmt_modified":"2026-04-23T20:31:36.610946+08:00"},{"id":576,"source_id":"cfc48cde-e1c3-47f6-afe2-a6d7a8f4ab69","target_id":"005172b71dc742cf6803c5eb0185091e","source_type":"WIKI_ITEM","target_type":"CODE_SNIPPET","relationship_type":"CONTAINS","extra":"Wiki contains code snippet: backend/requirements.txt#1-36","gmt_create":"2026-04-23T20:31:36.612653+08:00","gmt_modified":"2026-04-23T20:31:36.612653+08:00"},{"id":577,"source_id":"a26ee01cf41da3b956e1650448c156fa","target_id":"005172b71dc742cf6803c5eb0185091e","source_type":"SOURCE_FILE","target_type":"CODE_SNIPPET","relationship_type":"CONTAINS","extra":"Source file contains code snippet: 1-36","gmt_create":"2026-04-23T20:31:36.613263+08:00","gmt_modified":"2026-04-23T20:31:36.613263+08:00"},{"id":578,"source_id":"cfc48cde-e1c3-47f6-afe2-a6d7a8f4ab69","target_id":"b55cc5936c299f819b57b899858438e6","source_type":"WIKI_ITEM","target_type":"CODE_SNIPPET","relationship_type":"CONTAINS","extra":"Wiki contains code snippet: backend/app/workers/platforms/search_engine.py#139-144","gmt_create":"2026-04-23T20:31:36.614861+08:00","gmt_modified":"2026-04-23T20:31:36.614861+08:00"},{"id":579,"source_id":"6a63f048c16c60c5d2d57012c810ee0e","target_id":"b55cc5936c299f819b57b899858438e6","source_type":"SOURCE_FILE","target_type":"CODE_SNIPPET","relationship_type":"CONTAINS","extra":"Source file contains code snippet: 139-144","gmt_create":"2026-04-23T20:31:36.615692+08:00","gmt_modified":"2026-04-23T20:31:36.615692+08:00"},{"id":580,"source_id":"cfc48cde-e1c3-47f6-afe2-a6d7a8f4ab69","target_id":"384b1939e53970ce7ae75d241a49da5f","source_type":"WIKI_ITEM","target_type":"CODE_SNIPPET","relationship_type":"CONTAINS","extra":"Wiki contains code snippet: backend/app/workers/platforms/tongyi.py#22-29","gmt_create":"2026-04-23T20:31:36.615996+08:00","gmt_modified":"2026-04-23T20:31:36.615996+08:00"},{"id":581,"source_id":"e68ad5186f1e47610ab3d9f14a794393","target_id":"384b1939e53970ce7ae75d241a49da5f","source_type":"SOURCE_FILE","target_type":"CODE_SNIPPET","relationship_type":"CONTAINS","extra":"Source file contains code snippet: 22-29","gmt_create":"2026-04-23T20:31:36.61682+08:00","gmt_modified":"2026-04-23T20:31:36.61682+08:00"},{"id":582,"source_id":"cfc48cde-e1c3-47f6-afe2-a6d7a8f4ab69","target_id":"f096aa3ea82e9fa625a9acb1309b4c50","source_type":"WIKI_ITEM","target_type":"CODE_SNIPPET","relationship_type":"CONTAINS","extra":"Wiki contains code snippet: backend/app/workers/citation_engine.py#231-247","gmt_create":"2026-04-23T20:31:36.617171+08:00","gmt_modified":"2026-04-23T20:31:36.617171+08:00"},{"id":583,"source_id":"74040de652d5e57f548bb5c4adc3e1a0","target_id":"f096aa3ea82e9fa625a9acb1309b4c50","source_type":"SOURCE_FILE","target_type":"CODE_SNIPPET","relationship_type":"CONTAINS","extra":"Source file contains code snippet: 231-247","gmt_create":"2026-04-23T20:31:36.617385+08:00","gmt_modified":"2026-04-23T20:31:36.617385+08:00"},{"id":584,"source_id":"cfc48cde-e1c3-47f6-afe2-a6d7a8f4ab69","target_id":"15b8ebf74b0a5dfac58024d323ca8d0a","source_type":"WIKI_ITEM","target_type":"CODE_SNIPPET","relationship_type":"CONTAINS","extra":"Wiki contains code snippet: backend/app/workers/citation_engine.py#164-175","gmt_create":"2026-04-23T20:31:36.618327+08:00","gmt_modified":"2026-04-23T20:31:36.618327+08:00"},{"id":585,"source_id":"74040de652d5e57f548bb5c4adc3e1a0","target_id":"15b8ebf74b0a5dfac58024d323ca8d0a","source_type":"SOURCE_FILE","target_type":"CODE_SNIPPET","relationship_type":"CONTAINS","extra":"Source file contains code snippet: 164-175","gmt_create":"2026-04-23T20:31:36.618609+08:00","gmt_modified":"2026-04-23T20:31:36.618609+08:00"},{"id":586,"source_id":"fab60eaf-9652-4cb5-9f9e-0525caa62d63","target_id":"f642fc1c2f34e15572d9d98aa6c18813","source_type":"WIKI_ITEM","target_type":"SOURCE_FILE","relationship_type":"REFERENCED_BY","extra":"Wiki references source file: backend/app/workers/platforms/wenxin.py","gmt_create":"2026-04-23T20:31:50.473102+08:00","gmt_modified":"2026-04-23T20:31:50.473102+08:00"},{"id":587,"source_id":"fab60eaf-9652-4cb5-9f9e-0525caa62d63","target_id":"a16cf42e9559523c4f96ca4c79f9488d","source_type":"WIKI_ITEM","target_type":"SOURCE_FILE","relationship_type":"REFERENCED_BY","extra":"Wiki references source file: backend/app/workers/platforms/base.py","gmt_create":"2026-04-23T20:31:50.473614+08:00","gmt_modified":"2026-04-23T20:31:50.473614+08:00"},{"id":588,"source_id":"fab60eaf-9652-4cb5-9f9e-0525caa62d63","target_id":"6a63f048c16c60c5d2d57012c810ee0e","source_type":"WIKI_ITEM","target_type":"SOURCE_FILE","relationship_type":"REFERENCED_BY","extra":"Wiki references source file: backend/app/workers/platforms/search_engine.py","gmt_create":"2026-04-23T20:31:50.474171+08:00","gmt_modified":"2026-04-23T20:31:50.474171+08:00"},{"id":589,"source_id":"fab60eaf-9652-4cb5-9f9e-0525caa62d63","target_id":"74040de652d5e57f548bb5c4adc3e1a0","source_type":"WIKI_ITEM","target_type":"SOURCE_FILE","relationship_type":"REFERENCED_BY","extra":"Wiki references source file: backend/app/workers/citation_engine.py","gmt_create":"2026-04-23T20:31:50.474429+08:00","gmt_modified":"2026-04-23T20:31:50.474429+08:00"},{"id":590,"source_id":"fab60eaf-9652-4cb5-9f9e-0525caa62d63","target_id":"9ff19022ef915615911280e3c49ed44b","source_type":"WIKI_ITEM","target_type":"SOURCE_FILE","relationship_type":"REFERENCED_BY","extra":"Wiki references source file: backend/app/config.py","gmt_create":"2026-04-23T20:31:50.474658+08:00","gmt_modified":"2026-04-23T20:31:50.474658+08:00"},{"id":591,"source_id":"fab60eaf-9652-4cb5-9f9e-0525caa62d63","target_id":"b74caccb06844efcdb14d8324cff65c2","source_type":"WIKI_ITEM","target_type":"SOURCE_FILE","relationship_type":"REFERENCED_BY","extra":"Wiki references source file: backend/app/models/query.py","gmt_create":"2026-04-23T20:31:50.474883+08:00","gmt_modified":"2026-04-23T20:31:50.474883+08:00"},{"id":592,"source_id":"fab60eaf-9652-4cb5-9f9e-0525caa62d63","target_id":"6b3d903205941aa9391dd90016e1102c","source_type":"WIKI_ITEM","target_type":"SOURCE_FILE","relationship_type":"REFERENCED_BY","extra":"Wiki references source file: backend/app/api/queries.py","gmt_create":"2026-04-23T20:31:50.475158+08:00","gmt_modified":"2026-04-23T20:31:50.475158+08:00"},{"id":593,"source_id":"fab60eaf-9652-4cb5-9f9e-0525caa62d63","target_id":"e9b52adbec3c07cf021e488dd3f99ab4","source_type":"WIKI_ITEM","target_type":"SOURCE_FILE","relationship_type":"REFERENCED_BY","extra":"Wiki references source file: backend/Dockerfile","gmt_create":"2026-04-23T20:31:50.475559+08:00","gmt_modified":"2026-04-23T20:31:50.475559+08:00"},{"id":594,"source_id":"fab60eaf-9652-4cb5-9f9e-0525caa62d63","target_id":"8f973791233c698b3e64a4fb28a93d4b","source_type":"WIKI_ITEM","target_type":"SOURCE_FILE","relationship_type":"REFERENCED_BY","extra":"Wiki references source file: backend/app/workers/platforms/kimi.py","gmt_create":"2026-04-23T20:31:50.475799+08:00","gmt_modified":"2026-04-23T20:31:50.475799+08:00"},{"id":595,"source_id":"fab60eaf-9652-4cb5-9f9e-0525caa62d63","target_id":"e68ad5186f1e47610ab3d9f14a794393","source_type":"WIKI_ITEM","target_type":"SOURCE_FILE","relationship_type":"REFERENCED_BY","extra":"Wiki references source file: backend/app/workers/platforms/tongyi.py","gmt_create":"2026-04-23T20:31:50.47602+08:00","gmt_modified":"2026-04-23T20:31:50.47602+08:00"},{"id":596,"source_id":"fab60eaf-9652-4cb5-9f9e-0525caa62d63","target_id":"42ff5383133d176cec9eb88682483be3","source_type":"WIKI_ITEM","target_type":"SOURCE_FILE","relationship_type":"REFERENCED_BY","extra":"Wiki references source file: tests/test_citations.py","gmt_create":"2026-04-23T20:31:50.476237+08:00","gmt_modified":"2026-04-23T20:31:50.476237+08:00"},{"id":597,"source_id":"fab60eaf-9652-4cb5-9f9e-0525caa62d63","target_id":"72a110dca58d8152758e2fdab4e94761","source_type":"WIKI_ITEM","target_type":"CODE_SNIPPET","relationship_type":"CONTAINS","extra":"Wiki contains code snippet: backend/app/workers/platforms/base.py#1-18","gmt_create":"2026-04-23T20:31:50.476528+08:00","gmt_modified":"2026-04-23T20:31:50.476528+08:00"},{"id":598,"source_id":"fab60eaf-9652-4cb5-9f9e-0525caa62d63","target_id":"bcfade20d923c8efa713808ca9af94ca","source_type":"WIKI_ITEM","target_type":"CODE_SNIPPET","relationship_type":"CONTAINS","extra":"Wiki contains code snippet: backend/app/workers/platforms/wenxin.py#10-38","gmt_create":"2026-04-23T20:31:50.476982+08:00","gmt_modified":"2026-04-23T20:31:50.476982+08:00"},{"id":599,"source_id":"f642fc1c2f34e15572d9d98aa6c18813","target_id":"bcfade20d923c8efa713808ca9af94ca","source_type":"SOURCE_FILE","target_type":"CODE_SNIPPET","relationship_type":"CONTAINS","extra":"Source file contains code snippet: 10-38","gmt_create":"2026-04-23T20:31:50.477216+08:00","gmt_modified":"2026-04-23T20:31:50.477216+08:00"},{"id":600,"source_id":"fab60eaf-9652-4cb5-9f9e-0525caa62d63","target_id":"ca7e1232fbba5fb75e04ab8e491bfbd1","source_type":"WIKI_ITEM","target_type":"CODE_SNIPPET","relationship_type":"CONTAINS","extra":"Wiki contains code snippet: backend/app/workers/platforms/kimi.py#10-38","gmt_create":"2026-04-23T20:31:50.477565+08:00","gmt_modified":"2026-04-23T20:31:50.477565+08:00"},{"id":601,"source_id":"8f973791233c698b3e64a4fb28a93d4b","target_id":"ca7e1232fbba5fb75e04ab8e491bfbd1","source_type":"SOURCE_FILE","target_type":"CODE_SNIPPET","relationship_type":"CONTAINS","extra":"Source file contains code snippet: 10-38","gmt_create":"2026-04-23T20:31:50.477978+08:00","gmt_modified":"2026-04-23T20:31:50.477978+08:00"},{"id":602,"source_id":"fab60eaf-9652-4cb5-9f9e-0525caa62d63","target_id":"c5ae7697193b2b93425ff25d2d7d54a9","source_type":"WIKI_ITEM","target_type":"CODE_SNIPPET","relationship_type":"CONTAINS","extra":"Wiki contains code snippet: backend/app/workers/platforms/tongyi.py#10-38","gmt_create":"2026-04-23T20:31:50.478592+08:00","gmt_modified":"2026-04-23T20:31:50.478592+08:00"},{"id":603,"source_id":"fab60eaf-9652-4cb5-9f9e-0525caa62d63","target_id":"557ae34b57a5dd8e8fa3bb2a6ce178a7","source_type":"WIKI_ITEM","target_type":"CODE_SNIPPET","relationship_type":"CONTAINS","extra":"Wiki contains code snippet: backend/app/workers/platforms/search_engine.py#163-174","gmt_create":"2026-04-23T20:31:50.479311+08:00","gmt_modified":"2026-04-23T20:31:50.479311+08:00"},{"id":604,"source_id":"fab60eaf-9652-4cb5-9f9e-0525caa62d63","target_id":"9720b93ed7247efb685e2825e5f964bf","source_type":"WIKI_ITEM","target_type":"CODE_SNIPPET","relationship_type":"CONTAINS","extra":"Wiki contains code snippet: backend/app/workers/citation_engine.py#161-176","gmt_create":"2026-04-23T20:31:50.479856+08:00","gmt_modified":"2026-04-23T20:31:50.479856+08:00"},{"id":605,"source_id":"74040de652d5e57f548bb5c4adc3e1a0","target_id":"9720b93ed7247efb685e2825e5f964bf","source_type":"SOURCE_FILE","target_type":"CODE_SNIPPET","relationship_type":"CONTAINS","extra":"Source file contains code snippet: 161-176","gmt_create":"2026-04-23T20:31:50.48037+08:00","gmt_modified":"2026-04-23T20:31:50.48037+08:00"},{"id":606,"source_id":"fab60eaf-9652-4cb5-9f9e-0525caa62d63","target_id":"0d226400124ba891a46f59c36781ccd8","source_type":"WIKI_ITEM","target_type":"CODE_SNIPPET","relationship_type":"CONTAINS","extra":"Wiki contains code snippet: backend/app/config.py#9-23","gmt_create":"2026-04-23T20:31:50.481311+08:00","gmt_modified":"2026-04-23T20:31:50.481311+08:00"},{"id":607,"source_id":"9ff19022ef915615911280e3c49ed44b","target_id":"0d226400124ba891a46f59c36781ccd8","source_type":"SOURCE_FILE","target_type":"CODE_SNIPPET","relationship_type":"CONTAINS","extra":"Source file contains code snippet: 9-23","gmt_create":"2026-04-23T20:31:50.481625+08:00","gmt_modified":"2026-04-23T20:31:50.481625+08:00"},{"id":608,"source_id":"fab60eaf-9652-4cb5-9f9e-0525caa62d63","target_id":"412695e5de2014514a8f62f98c573656","source_type":"WIKI_ITEM","target_type":"CODE_SNIPPET","relationship_type":"CONTAINS","extra":"Wiki contains code snippet: backend/Dockerfile#1-41","gmt_create":"2026-04-23T20:31:50.482236+08:00","gmt_modified":"2026-04-23T20:31:50.482236+08:00"},{"id":609,"source_id":"e9b52adbec3c07cf021e488dd3f99ab4","target_id":"412695e5de2014514a8f62f98c573656","source_type":"SOURCE_FILE","target_type":"CODE_SNIPPET","relationship_type":"CONTAINS","extra":"Source file contains code snippet: 1-41","gmt_create":"2026-04-23T20:31:50.483281+08:00","gmt_modified":"2026-04-23T20:31:50.483281+08:00"},{"id":610,"source_id":"fab60eaf-9652-4cb5-9f9e-0525caa62d63","target_id":"4fb8856be3a581fe8303d11b2284ca29","source_type":"WIKI_ITEM","target_type":"CODE_SNIPPET","relationship_type":"CONTAINS","extra":"Wiki contains code snippet: backend/app/models/query.py#11-55","gmt_create":"2026-04-23T20:31:50.483853+08:00","gmt_modified":"2026-04-23T20:31:50.483854+08:00"},{"id":611,"source_id":"fab60eaf-9652-4cb5-9f9e-0525caa62d63","target_id":"485e15eb30a5b08da38a628c9dd5053e","source_type":"WIKI_ITEM","target_type":"CODE_SNIPPET","relationship_type":"CONTAINS","extra":"Wiki contains code snippet: backend/app/workers/platforms/search_engine.py#16-77","gmt_create":"2026-04-23T20:31:50.48646+08:00","gmt_modified":"2026-04-23T20:31:50.48646+08:00"},{"id":612,"source_id":"6a63f048c16c60c5d2d57012c810ee0e","target_id":"485e15eb30a5b08da38a628c9dd5053e","source_type":"SOURCE_FILE","target_type":"CODE_SNIPPET","relationship_type":"CONTAINS","extra":"Source file contains code snippet: 16-77","gmt_create":"2026-04-23T20:31:50.486841+08:00","gmt_modified":"2026-04-23T20:31:50.486841+08:00"},{"id":613,"source_id":"fab60eaf-9652-4cb5-9f9e-0525caa62d63","target_id":"ad67863041d9eea2b0fb542b5aa33aca","source_type":"WIKI_ITEM","target_type":"CODE_SNIPPET","relationship_type":"CONTAINS","extra":"Wiki contains code snippet: backend/app/workers/platforms/base.py#4-18","gmt_create":"2026-04-23T20:31:50.487399+08:00","gmt_modified":"2026-04-23T20:31:50.487399+08:00"},{"id":614,"source_id":"fab60eaf-9652-4cb5-9f9e-0525caa62d63","target_id":"8565f299083b4dcba5a328c947f06fee","source_type":"WIKI_ITEM","target_type":"CODE_SNIPPET","relationship_type":"CONTAINS","extra":"Wiki contains code snippet: backend/app/workers/citation_engine.py#256-287","gmt_create":"2026-04-23T20:31:50.488281+08:00","gmt_modified":"2026-04-23T20:31:50.488281+08:00"},{"id":615,"source_id":"fab60eaf-9652-4cb5-9f9e-0525caa62d63","target_id":"77158a6f887e224a03552893bfec7c92","source_type":"WIKI_ITEM","target_type":"CODE_SNIPPET","relationship_type":"CONTAINS","extra":"Wiki contains code snippet: backend/app/workers/platforms/wenxin.py#16-33","gmt_create":"2026-04-23T20:31:50.488807+08:00","gmt_modified":"2026-04-23T20:31:50.488807+08:00"},{"id":616,"source_id":"f642fc1c2f34e15572d9d98aa6c18813","target_id":"77158a6f887e224a03552893bfec7c92","source_type":"SOURCE_FILE","target_type":"CODE_SNIPPET","relationship_type":"CONTAINS","extra":"Source file contains code snippet: 16-33","gmt_create":"2026-04-23T20:31:50.489038+08:00","gmt_modified":"2026-04-23T20:31:50.489038+08:00"},{"id":617,"source_id":"fab60eaf-9652-4cb5-9f9e-0525caa62d63","target_id":"5c3f336b5a7b4af4cc2f2ac183539218","source_type":"WIKI_ITEM","target_type":"CODE_SNIPPET","relationship_type":"CONTAINS","extra":"Wiki contains code snippet: backend/app/workers/platforms/search_engine.py#79-145","gmt_create":"2026-04-23T20:31:50.491706+08:00","gmt_modified":"2026-04-23T20:31:50.491706+08:00"},{"id":618,"source_id":"6a63f048c16c60c5d2d57012c810ee0e","target_id":"5c3f336b5a7b4af4cc2f2ac183539218","source_type":"SOURCE_FILE","target_type":"CODE_SNIPPET","relationship_type":"CONTAINS","extra":"Source file contains code snippet: 79-145","gmt_create":"2026-04-23T20:31:50.492445+08:00","gmt_modified":"2026-04-23T20:31:50.492445+08:00"},{"id":619,"source_id":"fab60eaf-9652-4cb5-9f9e-0525caa62d63","target_id":"3894c1ed9dca2ebf2359f40ebdb1959e","source_type":"WIKI_ITEM","target_type":"CODE_SNIPPET","relationship_type":"CONTAINS","extra":"Wiki contains code snippet: backend/app/workers/platforms/search_engine.py#147-174","gmt_create":"2026-04-23T20:31:50.493129+08:00","gmt_modified":"2026-04-23T20:31:50.493129+08:00"},{"id":620,"source_id":"6a63f048c16c60c5d2d57012c810ee0e","target_id":"3894c1ed9dca2ebf2359f40ebdb1959e","source_type":"SOURCE_FILE","target_type":"CODE_SNIPPET","relationship_type":"CONTAINS","extra":"Source file contains code snippet: 147-174","gmt_create":"2026-04-23T20:31:50.493716+08:00","gmt_modified":"2026-04-23T20:31:50.493716+08:00"},{"id":621,"source_id":"fab60eaf-9652-4cb5-9f9e-0525caa62d63","target_id":"362d22f423631cda39404660b3317a2f","source_type":"WIKI_ITEM","target_type":"CODE_SNIPPET","relationship_type":"CONTAINS","extra":"Wiki contains code snippet: backend/app/workers/citation_engine.py#177-254","gmt_create":"2026-04-23T20:31:50.494347+08:00","gmt_modified":"2026-04-23T20:31:50.494348+08:00"},{"id":622,"source_id":"fab60eaf-9652-4cb5-9f9e-0525caa62d63","target_id":"e27bcba24aaadeec1922d2b4e5b8386b","source_type":"WIKI_ITEM","target_type":"CODE_SNIPPET","relationship_type":"CONTAINS","extra":"Wiki contains code snippet: backend/app/api/queries.py#1-109","gmt_create":"2026-04-23T20:31:50.496521+08:00","gmt_modified":"2026-04-23T20:31:50.496521+08:00"},{"id":623,"source_id":"6b3d903205941aa9391dd90016e1102c","target_id":"e27bcba24aaadeec1922d2b4e5b8386b","source_type":"SOURCE_FILE","target_type":"CODE_SNIPPET","relationship_type":"CONTAINS","extra":"Source file contains code snippet: 1-109","gmt_create":"2026-04-23T20:31:50.496915+08:00","gmt_modified":"2026-04-23T20:31:50.496915+08:00"},{"id":624,"source_id":"fab60eaf-9652-4cb5-9f9e-0525caa62d63","target_id":"5f893f5078aa8e549284feb057aa45da","source_type":"WIKI_ITEM","target_type":"CODE_SNIPPET","relationship_type":"CONTAINS","extra":"Wiki contains code snippet: backend/app/workers/platforms/wenxin.py#16-29","gmt_create":"2026-04-23T20:31:50.499115+08:00","gmt_modified":"2026-04-23T20:31:50.499115+08:00"},{"id":625,"source_id":"f642fc1c2f34e15572d9d98aa6c18813","target_id":"5f893f5078aa8e549284feb057aa45da","source_type":"SOURCE_FILE","target_type":"CODE_SNIPPET","relationship_type":"CONTAINS","extra":"Source file contains code snippet: 16-29","gmt_create":"2026-04-23T20:31:50.49944+08:00","gmt_modified":"2026-04-23T20:31:50.49944+08:00"},{"id":626,"source_id":"fab60eaf-9652-4cb5-9f9e-0525caa62d63","target_id":"b55cc5936c299f819b57b899858438e6","source_type":"WIKI_ITEM","target_type":"CODE_SNIPPET","relationship_type":"CONTAINS","extra":"Wiki contains code snippet: backend/app/workers/platforms/search_engine.py#139-144","gmt_create":"2026-04-23T20:31:50.50016+08:00","gmt_modified":"2026-04-23T20:31:50.50016+08:00"},{"id":627,"source_id":"fab60eaf-9652-4cb5-9f9e-0525caa62d63","target_id":"e0b68d2d24760689a0f4f00dfee5f9f2","source_type":"WIKI_ITEM","target_type":"CODE_SNIPPET","relationship_type":"CONTAINS","extra":"Wiki contains code snippet: backend/app/workers/platforms/search_engine.py#28-76","gmt_create":"2026-04-23T20:31:50.500908+08:00","gmt_modified":"2026-04-23T20:31:50.500908+08:00"},{"id":628,"source_id":"6a63f048c16c60c5d2d57012c810ee0e","target_id":"e0b68d2d24760689a0f4f00dfee5f9f2","source_type":"SOURCE_FILE","target_type":"CODE_SNIPPET","relationship_type":"CONTAINS","extra":"Source file contains code snippet: 28-76","gmt_create":"2026-04-23T20:31:50.501388+08:00","gmt_modified":"2026-04-23T20:31:50.501388+08:00"},{"id":629,"source_id":"fab60eaf-9652-4cb5-9f9e-0525caa62d63","target_id":"e9b98ae83632342d8e06cde39e9c9462","source_type":"WIKI_ITEM","target_type":"CODE_SNIPPET","relationship_type":"CONTAINS","extra":"Wiki contains code snippet: backend/app/workers/platforms/search_engine.py#105-137","gmt_create":"2026-04-23T20:31:50.502229+08:00","gmt_modified":"2026-04-23T20:31:50.502229+08:00"},{"id":630,"source_id":"6a63f048c16c60c5d2d57012c810ee0e","target_id":"e9b98ae83632342d8e06cde39e9c9462","source_type":"SOURCE_FILE","target_type":"CODE_SNIPPET","relationship_type":"CONTAINS","extra":"Source file contains code snippet: 105-137","gmt_create":"2026-04-23T20:31:50.502758+08:00","gmt_modified":"2026-04-23T20:31:50.502758+08:00"},{"id":631,"source_id":"fab60eaf-9652-4cb5-9f9e-0525caa62d63","target_id":"f096aa3ea82e9fa625a9acb1309b4c50","source_type":"WIKI_ITEM","target_type":"CODE_SNIPPET","relationship_type":"CONTAINS","extra":"Wiki contains code snippet: backend/app/workers/citation_engine.py#231-247","gmt_create":"2026-04-23T20:31:50.503532+08:00","gmt_modified":"2026-04-23T20:31:50.503532+08:00"},{"id":632,"source_id":"fab60eaf-9652-4cb5-9f9e-0525caa62d63","target_id":"2a4f741f31f62dce8ad63be2e831f520","source_type":"WIKI_ITEM","target_type":"CODE_SNIPPET","relationship_type":"CONTAINS","extra":"Wiki contains code snippet: tests/test_citations.py#23-93","gmt_create":"2026-04-23T20:31:50.504205+08:00","gmt_modified":"2026-04-23T20:31:50.504206+08:00"},{"id":633,"source_id":"fab60eaf-9652-4cb5-9f9e-0525caa62d63","target_id":"c86edb7a95fbe4b431ac65a0e2b8636e","source_type":"WIKI_ITEM","target_type":"CODE_SNIPPET","relationship_type":"CONTAINS","extra":"Wiki contains code snippet: backend/app/api/queries.py#90-109","gmt_create":"2026-04-23T20:31:50.504719+08:00","gmt_modified":"2026-04-23T20:31:50.504719+08:00"},{"id":634,"source_id":"6b3d903205941aa9391dd90016e1102c","target_id":"c86edb7a95fbe4b431ac65a0e2b8636e","source_type":"SOURCE_FILE","target_type":"CODE_SNIPPET","relationship_type":"CONTAINS","extra":"Source file contains code snippet: 90-109","gmt_create":"2026-04-23T20:31:50.505358+08:00","gmt_modified":"2026-04-23T20:31:50.505358+08:00"},{"id":635,"source_id":"a1cc822d-5382-431c-8c49-cf398fb5eb3c","target_id":"5cbb1e3f112aeba62a14b0b8999fc0f5","source_type":"WIKI_ITEM","target_type":"SOURCE_FILE","relationship_type":"REFERENCED_BY","extra":"Wiki references source file: backend/app/workers/scheduler.py","gmt_create":"2026-04-23T20:33:30.005285+08:00","gmt_modified":"2026-04-23T20:33:30.005285+08:00"},{"id":636,"source_id":"a1cc822d-5382-431c-8c49-cf398fb5eb3c","target_id":"74040de652d5e57f548bb5c4adc3e1a0","source_type":"WIKI_ITEM","target_type":"SOURCE_FILE","relationship_type":"REFERENCED_BY","extra":"Wiki references source file: backend/app/workers/citation_engine.py","gmt_create":"2026-04-23T20:33:30.006785+08:00","gmt_modified":"2026-04-23T20:33:30.006785+08:00"},{"id":637,"source_id":"a1cc822d-5382-431c-8c49-cf398fb5eb3c","target_id":"b74caccb06844efcdb14d8324cff65c2","source_type":"WIKI_ITEM","target_type":"SOURCE_FILE","relationship_type":"REFERENCED_BY","extra":"Wiki references source file: backend/app/models/query.py","gmt_create":"2026-04-23T20:33:30.008852+08:00","gmt_modified":"2026-04-23T20:33:30.008852+08:00"},{"id":638,"source_id":"a1cc822d-5382-431c-8c49-cf398fb5eb3c","target_id":"069738f21ac2da7349d22683e8c36929","source_type":"WIKI_ITEM","target_type":"SOURCE_FILE","relationship_type":"REFERENCED_BY","extra":"Wiki references source file: backend/app/models/query_task.py","gmt_create":"2026-04-23T20:33:30.010802+08:00","gmt_modified":"2026-04-23T20:33:30.010803+08:00"},{"id":639,"source_id":"a1cc822d-5382-431c-8c49-cf398fb5eb3c","target_id":"9228ff67d4c757a85d9421b71f4b29f5","source_type":"WIKI_ITEM","target_type":"SOURCE_FILE","relationship_type":"REFERENCED_BY","extra":"Wiki references source file: backend/app/main.py","gmt_create":"2026-04-23T20:33:30.011496+08:00","gmt_modified":"2026-04-23T20:33:30.011496+08:00"},{"id":640,"source_id":"a1cc822d-5382-431c-8c49-cf398fb5eb3c","target_id":"b0c428683c8a3e6922d90ca0d8c2736d","source_type":"WIKI_ITEM","target_type":"SOURCE_FILE","relationship_type":"REFERENCED_BY","extra":"Wiki references source file: backend/app/database.py","gmt_create":"2026-04-23T20:33:30.012521+08:00","gmt_modified":"2026-04-23T20:33:30.012521+08:00"},{"id":641,"source_id":"a1cc822d-5382-431c-8c49-cf398fb5eb3c","target_id":"9ff19022ef915615911280e3c49ed44b","source_type":"WIKI_ITEM","target_type":"SOURCE_FILE","relationship_type":"REFERENCED_BY","extra":"Wiki references source file: backend/app/config.py","gmt_create":"2026-04-23T20:33:30.013288+08:00","gmt_modified":"2026-04-23T20:33:30.013288+08:00"},{"id":642,"source_id":"a1cc822d-5382-431c-8c49-cf398fb5eb3c","target_id":"8f973791233c698b3e64a4fb28a93d4b","source_type":"WIKI_ITEM","target_type":"SOURCE_FILE","relationship_type":"REFERENCED_BY","extra":"Wiki references source file: backend/app/workers/platforms/kimi.py","gmt_create":"2026-04-23T20:33:30.014048+08:00","gmt_modified":"2026-04-23T20:33:30.014048+08:00"},{"id":643,"source_id":"a1cc822d-5382-431c-8c49-cf398fb5eb3c","target_id":"f642fc1c2f34e15572d9d98aa6c18813","source_type":"WIKI_ITEM","target_type":"SOURCE_FILE","relationship_type":"REFERENCED_BY","extra":"Wiki references source file: backend/app/workers/platforms/wenxin.py","gmt_create":"2026-04-23T20:33:30.014998+08:00","gmt_modified":"2026-04-23T20:33:30.014998+08:00"},{"id":644,"source_id":"a1cc822d-5382-431c-8c49-cf398fb5eb3c","target_id":"a16cf42e9559523c4f96ca4c79f9488d","source_type":"WIKI_ITEM","target_type":"SOURCE_FILE","relationship_type":"REFERENCED_BY","extra":"Wiki references source file: backend/app/workers/platforms/base.py","gmt_create":"2026-04-23T20:33:30.015593+08:00","gmt_modified":"2026-04-23T20:33:30.015593+08:00"},{"id":645,"source_id":"a1cc822d-5382-431c-8c49-cf398fb5eb3c","target_id":"7538ffe4902ab6041adb28b19844962a","source_type":"WIKI_ITEM","target_type":"SOURCE_FILE","relationship_type":"REFERENCED_BY","extra":"Wiki references source file: backend/app/api/citations.py","gmt_create":"2026-04-23T20:33:30.016186+08:00","gmt_modified":"2026-04-23T20:33:30.016187+08:00"},{"id":646,"source_id":"a1cc822d-5382-431c-8c49-cf398fb5eb3c","target_id":"88d22de3b2a7419868e8ae19130d860c","source_type":"WIKI_ITEM","target_type":"SOURCE_FILE","relationship_type":"REFERENCED_BY","extra":"Wiki references source file: backend/app/services/query.py","gmt_create":"2026-04-23T20:33:30.017118+08:00","gmt_modified":"2026-04-23T20:33:30.017118+08:00"},{"id":647,"source_id":"a1cc822d-5382-431c-8c49-cf398fb5eb3c","target_id":"b2f0d46a31a5441594f2e777365fc156","source_type":"WIKI_ITEM","target_type":"SOURCE_FILE","relationship_type":"REFERENCED_BY","extra":"Wiki references source file: tests/test_scheduler.py","gmt_create":"2026-04-23T20:33:30.017481+08:00","gmt_modified":"2026-04-23T20:33:30.017481+08:00"},{"id":648,"source_id":"a1cc822d-5382-431c-8c49-cf398fb5eb3c","target_id":"096856da621e23e78422a15e2bfce1f1","source_type":"WIKI_ITEM","target_type":"CODE_SNIPPET","relationship_type":"CONTAINS","extra":"Wiki contains code snippet: backend/app/main.py#13-22","gmt_create":"2026-04-23T20:33:30.018279+08:00","gmt_modified":"2026-04-23T20:33:30.018279+08:00"},{"id":649,"source_id":"a1cc822d-5382-431c-8c49-cf398fb5eb3c","target_id":"e230904202fcf7a861c6f49b84f9f863","source_type":"WIKI_ITEM","target_type":"CODE_SNIPPET","relationship_type":"CONTAINS","extra":"Wiki contains code snippet: backend/app/workers/scheduler.py#25-95","gmt_create":"2026-04-23T20:33:30.019076+08:00","gmt_modified":"2026-04-23T20:33:30.019076+08:00"},{"id":650,"source_id":"a1cc822d-5382-431c-8c49-cf398fb5eb3c","target_id":"309607c54b12a6340edc086ffb4737c9","source_type":"WIKI_ITEM","target_type":"CODE_SNIPPET","relationship_type":"CONTAINS","extra":"Wiki contains code snippet: backend/app/workers/citation_engine.py#148-309","gmt_create":"2026-04-23T20:33:30.020384+08:00","gmt_modified":"2026-04-23T20:33:30.020384+08:00"},{"id":651,"source_id":"a1cc822d-5382-431c-8c49-cf398fb5eb3c","target_id":"6e054d9a78c0c8c9da8dec4c4bda62ab","source_type":"WIKI_ITEM","target_type":"CODE_SNIPPET","relationship_type":"CONTAINS","extra":"Wiki contains code snippet: backend/app/database.py#6-28","gmt_create":"2026-04-23T20:33:30.021894+08:00","gmt_modified":"2026-04-23T20:33:30.021895+08:00"},{"id":652,"source_id":"b0c428683c8a3e6922d90ca0d8c2736d","target_id":"6e054d9a78c0c8c9da8dec4c4bda62ab","source_type":"SOURCE_FILE","target_type":"CODE_SNIPPET","relationship_type":"CONTAINS","extra":"Source file contains code snippet: 6-28","gmt_create":"2026-04-23T20:33:30.022319+08:00","gmt_modified":"2026-04-23T20:33:30.022319+08:00"},{"id":653,"source_id":"a1cc822d-5382-431c-8c49-cf398fb5eb3c","target_id":"4fb8856be3a581fe8303d11b2284ca29","source_type":"WIKI_ITEM","target_type":"CODE_SNIPPET","relationship_type":"CONTAINS","extra":"Wiki contains code snippet: backend/app/models/query.py#11-55","gmt_create":"2026-04-23T20:33:30.039084+08:00","gmt_modified":"2026-04-23T20:33:30.039085+08:00"},{"id":654,"source_id":"a1cc822d-5382-431c-8c49-cf398fb5eb3c","target_id":"c2747ca16b879bca0f68955534c3c4fc","source_type":"WIKI_ITEM","target_type":"CODE_SNIPPET","relationship_type":"CONTAINS","extra":"Wiki contains code snippet: backend/app/main.py#1-48","gmt_create":"2026-04-23T20:33:30.042279+08:00","gmt_modified":"2026-04-23T20:33:30.042279+08:00"},{"id":655,"source_id":"a1cc822d-5382-431c-8c49-cf398fb5eb3c","target_id":"71f98c8993fb42b108e34a554247869b","source_type":"WIKI_ITEM","target_type":"CODE_SNIPPET","relationship_type":"CONTAINS","extra":"Wiki contains code snippet: backend/app/workers/scheduler.py#1-95","gmt_create":"2026-04-23T20:33:30.043781+08:00","gmt_modified":"2026-04-23T20:33:30.043781+08:00"},{"id":656,"source_id":"a1cc822d-5382-431c-8c49-cf398fb5eb3c","target_id":"9bfc041fe426da2eb78353827e8d9163","source_type":"WIKI_ITEM","target_type":"CODE_SNIPPET","relationship_type":"CONTAINS","extra":"Wiki contains code snippet: backend/app/database.py#1-29","gmt_create":"2026-04-23T20:33:30.048591+08:00","gmt_modified":"2026-04-23T20:33:30.048591+08:00"},{"id":657,"source_id":"a1cc822d-5382-431c-8c49-cf398fb5eb3c","target_id":"6281fff17a86ec1895c64d87c2ae7fb1","source_type":"WIKI_ITEM","target_type":"CODE_SNIPPET","relationship_type":"CONTAINS","extra":"Wiki contains code snippet: backend/app/models/query.py#1-55","gmt_create":"2026-04-23T20:33:30.049875+08:00","gmt_modified":"2026-04-23T20:33:30.049875+08:00"},{"id":658,"source_id":"a1cc822d-5382-431c-8c49-cf398fb5eb3c","target_id":"eecf9581dbaa0a515cf11514175e7ef9","source_type":"WIKI_ITEM","target_type":"CODE_SNIPPET","relationship_type":"CONTAINS","extra":"Wiki contains code snippet: backend/app/workers/platforms/kimi.py#11-206","gmt_create":"2026-04-23T20:33:30.052505+08:00","gmt_modified":"2026-04-23T20:33:30.052505+08:00"},{"id":659,"source_id":"a1cc822d-5382-431c-8c49-cf398fb5eb3c","target_id":"5563c29185326a59be61ee0a6eec4463","source_type":"WIKI_ITEM","target_type":"CODE_SNIPPET","relationship_type":"CONTAINS","extra":"Wiki contains code snippet: backend/app/workers/platforms/wenxin.py#11-205","gmt_create":"2026-04-23T20:33:30.054452+08:00","gmt_modified":"2026-04-23T20:33:30.054452+08:00"},{"id":660,"source_id":"a1cc822d-5382-431c-8c49-cf398fb5eb3c","target_id":"9c16a069e5154660bfdfa48f3518fc6a","source_type":"WIKI_ITEM","target_type":"CODE_SNIPPET","relationship_type":"CONTAINS","extra":"Wiki contains code snippet: backend/app/models/query_task.py#11-38","gmt_create":"2026-04-23T20:33:30.056033+08:00","gmt_modified":"2026-04-23T20:33:30.056033+08:00"},{"id":661,"source_id":"069738f21ac2da7349d22683e8c36929","target_id":"9c16a069e5154660bfdfa48f3518fc6a","source_type":"SOURCE_FILE","target_type":"CODE_SNIPPET","relationship_type":"CONTAINS","extra":"Source file contains code snippet: 11-38","gmt_create":"2026-04-23T20:33:30.056759+08:00","gmt_modified":"2026-04-23T20:33:30.056759+08:00"},{"id":662,"source_id":"a1cc822d-5382-431c-8c49-cf398fb5eb3c","target_id":"2d35e1345d25020f8e7ac1318db06f7b","source_type":"WIKI_ITEM","target_type":"CODE_SNIPPET","relationship_type":"CONTAINS","extra":"Wiki contains code snippet: backend/app/workers/scheduler.py#30-90","gmt_create":"2026-04-23T20:33:30.060127+08:00","gmt_modified":"2026-04-23T20:33:30.060127+08:00"},{"id":663,"source_id":"a1cc822d-5382-431c-8c49-cf398fb5eb3c","target_id":"160b5326537d25444c40a459a01e79c6","source_type":"WIKI_ITEM","target_type":"CODE_SNIPPET","relationship_type":"CONTAINS","extra":"Wiki contains code snippet: backend/app/workers/citation_engine.py#159-234","gmt_create":"2026-04-23T20:33:30.06165+08:00","gmt_modified":"2026-04-23T20:33:30.06165+08:00"},{"id":664,"source_id":"a1cc822d-5382-431c-8c49-cf398fb5eb3c","target_id":"a4918fcbd21492ad996d7f5496f03a4b","source_type":"WIKI_ITEM","target_type":"CODE_SNIPPET","relationship_type":"CONTAINS","extra":"Wiki contains code snippet: backend/app/workers/platforms/kimi.py#33-48","gmt_create":"2026-04-23T20:33:30.063084+08:00","gmt_modified":"2026-04-23T20:33:30.063084+08:00"},{"id":665,"source_id":"8f973791233c698b3e64a4fb28a93d4b","target_id":"a4918fcbd21492ad996d7f5496f03a4b","source_type":"SOURCE_FILE","target_type":"CODE_SNIPPET","relationship_type":"CONTAINS","extra":"Source file contains code snippet: 33-48","gmt_create":"2026-04-23T20:33:30.063941+08:00","gmt_modified":"2026-04-23T20:33:30.063941+08:00"},{"id":666,"source_id":"a1cc822d-5382-431c-8c49-cf398fb5eb3c","target_id":"bc38d046b4b1410ae2165cee2272839e","source_type":"WIKI_ITEM","target_type":"CODE_SNIPPET","relationship_type":"CONTAINS","extra":"Wiki contains code snippet: backend/app/workers/platforms/wenxin.py#33-48","gmt_create":"2026-04-23T20:33:30.065013+08:00","gmt_modified":"2026-04-23T20:33:30.065013+08:00"},{"id":667,"source_id":"f642fc1c2f34e15572d9d98aa6c18813","target_id":"bc38d046b4b1410ae2165cee2272839e","source_type":"SOURCE_FILE","target_type":"CODE_SNIPPET","relationship_type":"CONTAINS","extra":"Source file contains code snippet: 33-48","gmt_create":"2026-04-23T20:33:30.066091+08:00","gmt_modified":"2026-04-23T20:33:30.066091+08:00"},{"id":668,"source_id":"a1cc822d-5382-431c-8c49-cf398fb5eb3c","target_id":"72f6d334026866e8a61d2ffb1d83370a","source_type":"WIKI_ITEM","target_type":"CODE_SNIPPET","relationship_type":"CONTAINS","extra":"Wiki contains code snippet: backend/app/workers/citation_engine.py#19-100","gmt_create":"2026-04-23T20:33:30.06977+08:00","gmt_modified":"2026-04-23T20:33:30.06977+08:00"},{"id":669,"source_id":"74040de652d5e57f548bb5c4adc3e1a0","target_id":"72f6d334026866e8a61d2ffb1d83370a","source_type":"SOURCE_FILE","target_type":"CODE_SNIPPET","relationship_type":"CONTAINS","extra":"Source file contains code snippet: 19-100","gmt_create":"2026-04-23T20:33:30.070839+08:00","gmt_modified":"2026-04-23T20:33:30.070839+08:00"},{"id":670,"source_id":"a1cc822d-5382-431c-8c49-cf398fb5eb3c","target_id":"5c67e2f70283956b2d29a3c1443eb514","source_type":"WIKI_ITEM","target_type":"CODE_SNIPPET","relationship_type":"CONTAINS","extra":"Wiki contains code snippet: backend/app/workers/citation_engine.py#122-146","gmt_create":"2026-04-23T20:33:30.07226+08:00","gmt_modified":"2026-04-23T20:33:30.07226+08:00"},{"id":671,"source_id":"a1cc822d-5382-431c-8c49-cf398fb5eb3c","target_id":"ad67863041d9eea2b0fb542b5aa33aca","source_type":"WIKI_ITEM","target_type":"CODE_SNIPPET","relationship_type":"CONTAINS","extra":"Wiki contains code snippet: backend/app/workers/platforms/base.py#4-18","gmt_create":"2026-04-23T20:33:30.076075+08:00","gmt_modified":"2026-04-23T20:33:30.076076+08:00"},{"id":672,"source_id":"a1cc822d-5382-431c-8c49-cf398fb5eb3c","target_id":"1e85186eded8743ff5f231df4aa6df3f","source_type":"WIKI_ITEM","target_type":"CODE_SNIPPET","relationship_type":"CONTAINS","extra":"Wiki contains code snippet: backend/app/workers/platforms/kimi.py#21-48","gmt_create":"2026-04-23T20:33:30.080882+08:00","gmt_modified":"2026-04-23T20:33:30.080882+08:00"},{"id":673,"source_id":"a1cc822d-5382-431c-8c49-cf398fb5eb3c","target_id":"1d84b9a7eb013882953a2d1d948299e4","source_type":"WIKI_ITEM","target_type":"CODE_SNIPPET","relationship_type":"CONTAINS","extra":"Wiki contains code snippet: backend/app/workers/platforms/kimi.py#126-197","gmt_create":"2026-04-23T20:33:30.082996+08:00","gmt_modified":"2026-04-23T20:33:30.082997+08:00"},{"id":674,"source_id":"8f973791233c698b3e64a4fb28a93d4b","target_id":"1d84b9a7eb013882953a2d1d948299e4","source_type":"SOURCE_FILE","target_type":"CODE_SNIPPET","relationship_type":"CONTAINS","extra":"Source file contains code snippet: 126-197","gmt_create":"2026-04-23T20:33:30.084021+08:00","gmt_modified":"2026-04-23T20:33:30.084021+08:00"},{"id":675,"source_id":"a1cc822d-5382-431c-8c49-cf398fb5eb3c","target_id":"e2b1718570fb714b2f4342221898ab30","source_type":"WIKI_ITEM","target_type":"CODE_SNIPPET","relationship_type":"CONTAINS","extra":"Wiki contains code snippet: backend/app/workers/platforms/wenxin.py#21-48","gmt_create":"2026-04-23T20:33:30.08518+08:00","gmt_modified":"2026-04-23T20:33:30.085181+08:00"},{"id":676,"source_id":"a1cc822d-5382-431c-8c49-cf398fb5eb3c","target_id":"ba687f2c64aff92b3906658359ed953a","source_type":"WIKI_ITEM","target_type":"CODE_SNIPPET","relationship_type":"CONTAINS","extra":"Wiki contains code snippet: backend/app/workers/platforms/wenxin.py#124-195","gmt_create":"2026-04-23T20:33:30.086912+08:00","gmt_modified":"2026-04-23T20:33:30.086913+08:00"},{"id":677,"source_id":"f642fc1c2f34e15572d9d98aa6c18813","target_id":"ba687f2c64aff92b3906658359ed953a","source_type":"SOURCE_FILE","target_type":"CODE_SNIPPET","relationship_type":"CONTAINS","extra":"Source file contains code snippet: 124-195","gmt_create":"2026-04-23T20:33:30.087917+08:00","gmt_modified":"2026-04-23T20:33:30.087917+08:00"},{"id":678,"source_id":"a1cc822d-5382-431c-8c49-cf398fb5eb3c","target_id":"52ee729b02c992c689522c7956c14128","source_type":"WIKI_ITEM","target_type":"CODE_SNIPPET","relationship_type":"CONTAINS","extra":"Wiki contains code snippet: backend/app/workers/scheduler.py#57-62","gmt_create":"2026-04-23T20:33:30.090606+08:00","gmt_modified":"2026-04-23T20:33:30.090606+08:00"},{"id":679,"source_id":"5cbb1e3f112aeba62a14b0b8999fc0f5","target_id":"52ee729b02c992c689522c7956c14128","source_type":"SOURCE_FILE","target_type":"CODE_SNIPPET","relationship_type":"CONTAINS","extra":"Source file contains code snippet: 57-62","gmt_create":"2026-04-23T20:33:30.092747+08:00","gmt_modified":"2026-04-23T20:33:30.092747+08:00"},{"id":680,"source_id":"a1cc822d-5382-431c-8c49-cf398fb5eb3c","target_id":"c9e32b7324cce60c8887deb8404ee759","source_type":"WIKI_ITEM","target_type":"CODE_SNIPPET","relationship_type":"CONTAINS","extra":"Wiki contains code snippet: backend/app/workers/scheduler.py#107-112","gmt_create":"2026-04-23T20:33:30.094246+08:00","gmt_modified":"2026-04-23T20:33:30.094246+08:00"},{"id":681,"source_id":"5cbb1e3f112aeba62a14b0b8999fc0f5","target_id":"c9e32b7324cce60c8887deb8404ee759","source_type":"SOURCE_FILE","target_type":"CODE_SNIPPET","relationship_type":"CONTAINS","extra":"Source file contains code snippet: 107-112","gmt_create":"2026-04-23T20:33:30.095189+08:00","gmt_modified":"2026-04-23T20:33:30.095189+08:00"},{"id":682,"source_id":"a1cc822d-5382-431c-8c49-cf398fb5eb3c","target_id":"212d822d207a4c0bd7825bbf20e188e9","source_type":"WIKI_ITEM","target_type":"CODE_SNIPPET","relationship_type":"CONTAINS","extra":"Wiki contains code snippet: backend/app/api/citations.py#59-77","gmt_create":"2026-04-23T20:33:30.096673+08:00","gmt_modified":"2026-04-23T20:33:30.096673+08:00"},{"id":683,"source_id":"a1cc822d-5382-431c-8c49-cf398fb5eb3c","target_id":"8355d3821337334caee57a75dc8c8865","source_type":"WIKI_ITEM","target_type":"CODE_SNIPPET","relationship_type":"CONTAINS","extra":"Wiki contains code snippet: backend/app/services/query.py#116-130","gmt_create":"2026-04-23T20:33:30.098422+08:00","gmt_modified":"2026-04-23T20:33:30.098422+08:00"},{"id":684,"source_id":"88d22de3b2a7419868e8ae19130d860c","target_id":"8355d3821337334caee57a75dc8c8865","source_type":"SOURCE_FILE","target_type":"CODE_SNIPPET","relationship_type":"CONTAINS","extra":"Source file contains code snippet: 116-130","gmt_create":"2026-04-23T20:33:30.099427+08:00","gmt_modified":"2026-04-23T20:33:30.099427+08:00"},{"id":685,"source_id":"a1cc822d-5382-431c-8c49-cf398fb5eb3c","target_id":"4fe27d4d1323b500e72d870aa6212a1a","source_type":"WIKI_ITEM","target_type":"CODE_SNIPPET","relationship_type":"CONTAINS","extra":"Wiki contains code snippet: backend/app/workers/scheduler.py#13-20","gmt_create":"2026-04-23T20:33:30.101771+08:00","gmt_modified":"2026-04-23T20:33:30.101771+08:00"},{"id":686,"source_id":"5cbb1e3f112aeba62a14b0b8999fc0f5","target_id":"4fe27d4d1323b500e72d870aa6212a1a","source_type":"SOURCE_FILE","target_type":"CODE_SNIPPET","relationship_type":"CONTAINS","extra":"Source file contains code snippet: 13-20","gmt_create":"2026-04-23T20:33:30.102515+08:00","gmt_modified":"2026-04-23T20:33:30.102515+08:00"},{"id":687,"source_id":"a1cc822d-5382-431c-8c49-cf398fb5eb3c","target_id":"3729543092bccad8926c5ea852db1e69","source_type":"WIKI_ITEM","target_type":"CODE_SNIPPET","relationship_type":"CONTAINS","extra":"Wiki contains code snippet: backend/app/workers/citation_engine.py#148-157","gmt_create":"2026-04-23T20:33:30.103598+08:00","gmt_modified":"2026-04-23T20:33:30.103599+08:00"},{"id":688,"source_id":"74040de652d5e57f548bb5c4adc3e1a0","target_id":"3729543092bccad8926c5ea852db1e69","source_type":"SOURCE_FILE","target_type":"CODE_SNIPPET","relationship_type":"CONTAINS","extra":"Source file contains code snippet: 148-157","gmt_create":"2026-04-23T20:33:30.104105+08:00","gmt_modified":"2026-04-23T20:33:30.104105+08:00"},{"id":689,"source_id":"a1cc822d-5382-431c-8c49-cf398fb5eb3c","target_id":"1ee5153c867fc6e9d277a3067963a1fc","source_type":"WIKI_ITEM","target_type":"CODE_SNIPPET","relationship_type":"CONTAINS","extra":"Wiki contains code snippet: backend/app/workers/scheduler.py#32-38","gmt_create":"2026-04-23T20:33:30.105113+08:00","gmt_modified":"2026-04-23T20:33:30.105113+08:00"},{"id":690,"source_id":"5cbb1e3f112aeba62a14b0b8999fc0f5","target_id":"1ee5153c867fc6e9d277a3067963a1fc","source_type":"SOURCE_FILE","target_type":"CODE_SNIPPET","relationship_type":"CONTAINS","extra":"Source file contains code snippet: 32-38","gmt_create":"2026-04-23T20:33:30.105627+08:00","gmt_modified":"2026-04-23T20:33:30.105627+08:00"},{"id":691,"source_id":"a1cc822d-5382-431c-8c49-cf398fb5eb3c","target_id":"ed527c7a549ec333c2b30b59614343df","source_type":"WIKI_ITEM","target_type":"CODE_SNIPPET","relationship_type":"CONTAINS","extra":"Wiki contains code snippet: backend/app/models/query.py#50-54","gmt_create":"2026-04-23T20:33:30.106672+08:00","gmt_modified":"2026-04-23T20:33:30.106672+08:00"},{"id":692,"source_id":"b74caccb06844efcdb14d8324cff65c2","target_id":"ed527c7a549ec333c2b30b59614343df","source_type":"SOURCE_FILE","target_type":"CODE_SNIPPET","relationship_type":"CONTAINS","extra":"Source file contains code snippet: 50-54","gmt_create":"2026-04-23T20:33:30.107651+08:00","gmt_modified":"2026-04-23T20:33:30.107651+08:00"},{"id":693,"source_id":"a1cc822d-5382-431c-8c49-cf398fb5eb3c","target_id":"f6c9f1b4e8646c366a31426a4537675d","source_type":"WIKI_ITEM","target_type":"CODE_SNIPPET","relationship_type":"CONTAINS","extra":"Wiki contains code snippet: backend/app/models/query_task.py#36-38","gmt_create":"2026-04-23T20:33:30.109238+08:00","gmt_modified":"2026-04-23T20:33:30.109238+08:00"},{"id":694,"source_id":"a1cc822d-5382-431c-8c49-cf398fb5eb3c","target_id":"1a3351698ecc7cd4e508b7a792804fc4","source_type":"WIKI_ITEM","target_type":"CODE_SNIPPET","relationship_type":"CONTAINS","extra":"Wiki contains code snippet: backend/app/workers/citation_engine.py#302-309","gmt_create":"2026-04-23T20:33:30.111966+08:00","gmt_modified":"2026-04-23T20:33:30.111966+08:00"},{"id":695,"source_id":"74040de652d5e57f548bb5c4adc3e1a0","target_id":"1a3351698ecc7cd4e508b7a792804fc4","source_type":"SOURCE_FILE","target_type":"CODE_SNIPPET","relationship_type":"CONTAINS","extra":"Source file contains code snippet: 302-309","gmt_create":"2026-04-23T20:33:30.112959+08:00","gmt_modified":"2026-04-23T20:33:30.11296+08:00"},{"id":696,"source_id":"a1cc822d-5382-431c-8c49-cf398fb5eb3c","target_id":"e3e9710c7eead933c936519395f792e0","source_type":"WIKI_ITEM","target_type":"CODE_SNIPPET","relationship_type":"CONTAINS","extra":"Wiki contains code snippet: backend/app/workers/scheduler.py#44-49","gmt_create":"2026-04-23T20:33:30.114604+08:00","gmt_modified":"2026-04-23T20:33:30.114605+08:00"},{"id":697,"source_id":"5cbb1e3f112aeba62a14b0b8999fc0f5","target_id":"e3e9710c7eead933c936519395f792e0","source_type":"SOURCE_FILE","target_type":"CODE_SNIPPET","relationship_type":"CONTAINS","extra":"Source file contains code snippet: 44-49","gmt_create":"2026-04-23T20:33:30.115247+08:00","gmt_modified":"2026-04-23T20:33:30.115247+08:00"},{"id":698,"source_id":"a1cc822d-5382-431c-8c49-cf398fb5eb3c","target_id":"d20fc729a5d3986b1c077f9e07ece9c4","source_type":"WIKI_ITEM","target_type":"CODE_SNIPPET","relationship_type":"CONTAINS","extra":"Wiki contains code snippet: backend/app/config.py#7","gmt_create":"2026-04-23T20:33:30.116587+08:00","gmt_modified":"2026-04-23T20:33:30.116587+08:00"},{"id":699,"source_id":"a1cc822d-5382-431c-8c49-cf398fb5eb3c","target_id":"a4143cc29b14f1f5bc75a5e021690666","source_type":"WIKI_ITEM","target_type":"CODE_SNIPPET","relationship_type":"CONTAINS","extra":"Wiki contains code snippet: backend/app/workers/platforms/kimi.py#23-31","gmt_create":"2026-04-23T20:33:30.117646+08:00","gmt_modified":"2026-04-23T20:33:30.117646+08:00"},{"id":700,"source_id":"8f973791233c698b3e64a4fb28a93d4b","target_id":"a4143cc29b14f1f5bc75a5e021690666","source_type":"SOURCE_FILE","target_type":"CODE_SNIPPET","relationship_type":"CONTAINS","extra":"Source file contains code snippet: 23-31","gmt_create":"2026-04-23T20:33:30.118764+08:00","gmt_modified":"2026-04-23T20:33:30.118764+08:00"},{"id":701,"source_id":"a1cc822d-5382-431c-8c49-cf398fb5eb3c","target_id":"7192cfda5508e7587efd91d26cf1f018","source_type":"WIKI_ITEM","target_type":"CODE_SNIPPET","relationship_type":"CONTAINS","extra":"Wiki contains code snippet: backend/app/workers/platforms/wenxin.py#23-31","gmt_create":"2026-04-23T20:33:30.120253+08:00","gmt_modified":"2026-04-23T20:33:30.120253+08:00"},{"id":702,"source_id":"f642fc1c2f34e15572d9d98aa6c18813","target_id":"7192cfda5508e7587efd91d26cf1f018","source_type":"SOURCE_FILE","target_type":"CODE_SNIPPET","relationship_type":"CONTAINS","extra":"Source file contains code snippet: 23-31","gmt_create":"2026-04-23T20:33:30.121853+08:00","gmt_modified":"2026-04-23T20:33:30.121853+08:00"},{"id":703,"source_id":"a1cc822d-5382-431c-8c49-cf398fb5eb3c","target_id":"38142b7d7016c5590e638fafcdcb1a19","source_type":"WIKI_ITEM","target_type":"CODE_SNIPPET","relationship_type":"CONTAINS","extra":"Wiki contains code snippet: backend/app/workers/citation_engine.py#211-227","gmt_create":"2026-04-23T20:33:30.1234+08:00","gmt_modified":"2026-04-23T20:33:30.1234+08:00"},{"id":704,"source_id":"74040de652d5e57f548bb5c4adc3e1a0","target_id":"38142b7d7016c5590e638fafcdcb1a19","source_type":"SOURCE_FILE","target_type":"CODE_SNIPPET","relationship_type":"CONTAINS","extra":"Source file contains code snippet: 211-227","gmt_create":"2026-04-23T20:33:30.125433+08:00","gmt_modified":"2026-04-23T20:33:30.125433+08:00"},{"id":705,"source_id":"a1cc822d-5382-431c-8c49-cf398fb5eb3c","target_id":"fb5276346dcc4e7044d8765a8572e7a8","source_type":"WIKI_ITEM","target_type":"CODE_SNIPPET","relationship_type":"CONTAINS","extra":"Wiki contains code snippet: backend/app/config.py#4-16","gmt_create":"2026-04-23T20:33:30.128657+08:00","gmt_modified":"2026-04-23T20:33:30.128657+08:00"},{"id":706,"source_id":"9ff19022ef915615911280e3c49ed44b","target_id":"fb5276346dcc4e7044d8765a8572e7a8","source_type":"SOURCE_FILE","target_type":"CODE_SNIPPET","relationship_type":"CONTAINS","extra":"Source file contains code snippet: 4-16","gmt_create":"2026-04-23T20:33:30.129814+08:00","gmt_modified":"2026-04-23T20:33:30.129814+08:00"},{"id":707,"source_id":"19e75845-5147-4aeb-90be-16f3aa270465","target_id":"74040de652d5e57f548bb5c4adc3e1a0","source_type":"WIKI_ITEM","target_type":"SOURCE_FILE","relationship_type":"REFERENCED_BY","extra":"Wiki references source file: backend/app/workers/citation_engine.py","gmt_create":"2026-04-23T20:33:37.259749+08:00","gmt_modified":"2026-04-23T20:33:37.259749+08:00"},{"id":708,"source_id":"19e75845-5147-4aeb-90be-16f3aa270465","target_id":"a16cf42e9559523c4f96ca4c79f9488d","source_type":"WIKI_ITEM","target_type":"SOURCE_FILE","relationship_type":"REFERENCED_BY","extra":"Wiki references source file: backend/app/workers/platforms/base.py","gmt_create":"2026-04-23T20:33:37.26107+08:00","gmt_modified":"2026-04-23T20:33:37.26107+08:00"},{"id":709,"source_id":"19e75845-5147-4aeb-90be-16f3aa270465","target_id":"8f973791233c698b3e64a4fb28a93d4b","source_type":"WIKI_ITEM","target_type":"SOURCE_FILE","relationship_type":"REFERENCED_BY","extra":"Wiki references source file: backend/app/workers/platforms/kimi.py","gmt_create":"2026-04-23T20:33:37.261714+08:00","gmt_modified":"2026-04-23T20:33:37.261714+08:00"},{"id":710,"source_id":"19e75845-5147-4aeb-90be-16f3aa270465","target_id":"f642fc1c2f34e15572d9d98aa6c18813","source_type":"WIKI_ITEM","target_type":"SOURCE_FILE","relationship_type":"REFERENCED_BY","extra":"Wiki references source file: backend/app/workers/platforms/wenxin.py","gmt_create":"2026-04-23T20:33:37.262532+08:00","gmt_modified":"2026-04-23T20:33:37.262532+08:00"},{"id":711,"source_id":"19e75845-5147-4aeb-90be-16f3aa270465","target_id":"e68ad5186f1e47610ab3d9f14a794393","source_type":"WIKI_ITEM","target_type":"SOURCE_FILE","relationship_type":"REFERENCED_BY","extra":"Wiki references source file: backend/app/workers/platforms/tongyi.py","gmt_create":"2026-04-23T20:33:37.263665+08:00","gmt_modified":"2026-04-23T20:33:37.263665+08:00"},{"id":712,"source_id":"19e75845-5147-4aeb-90be-16f3aa270465","target_id":"404f6d0765a8c6e77e33b7fc21b377a4","source_type":"WIKI_ITEM","target_type":"SOURCE_FILE","relationship_type":"REFERENCED_BY","extra":"Wiki references source file: backend/app/workers/platforms/doubao.py","gmt_create":"2026-04-23T20:33:37.26425+08:00","gmt_modified":"2026-04-23T20:33:37.26425+08:00"},{"id":713,"source_id":"19e75845-5147-4aeb-90be-16f3aa270465","target_id":"303e80519e946904d1cb3ac32cbb0814","source_type":"WIKI_ITEM","target_type":"SOURCE_FILE","relationship_type":"REFERENCED_BY","extra":"Wiki references source file: backend/app/workers/platforms/qingyan.py","gmt_create":"2026-04-23T20:33:37.265278+08:00","gmt_modified":"2026-04-23T20:33:37.265278+08:00"},{"id":714,"source_id":"19e75845-5147-4aeb-90be-16f3aa270465","target_id":"5af7301fe056fc3d10820d820e8ad777","source_type":"WIKI_ITEM","target_type":"SOURCE_FILE","relationship_type":"REFERENCED_BY","extra":"Wiki references source file: backend/app/workers/platforms/tiangong.py","gmt_create":"2026-04-23T20:33:37.265809+08:00","gmt_modified":"2026-04-23T20:33:37.265809+08:00"},{"id":715,"source_id":"19e75845-5147-4aeb-90be-16f3aa270465","target_id":"0e38ad5d2d3daaad08c9302df8805b15","source_type":"WIKI_ITEM","target_type":"SOURCE_FILE","relationship_type":"REFERENCED_BY","extra":"Wiki references source file: backend/app/workers/platforms/xinghuo.py","gmt_create":"2026-04-23T20:33:37.266496+08:00","gmt_modified":"2026-04-23T20:33:37.266496+08:00"},{"id":716,"source_id":"19e75845-5147-4aeb-90be-16f3aa270465","target_id":"6a63f048c16c60c5d2d57012c810ee0e","source_type":"WIKI_ITEM","target_type":"SOURCE_FILE","relationship_type":"REFERENCED_BY","extra":"Wiki references source file: backend/app/workers/platforms/search_engine.py","gmt_create":"2026-04-23T20:33:37.267203+08:00","gmt_modified":"2026-04-23T20:33:37.267203+08:00"},{"id":717,"source_id":"19e75845-5147-4aeb-90be-16f3aa270465","target_id":"5cbb1e3f112aeba62a14b0b8999fc0f5","source_type":"WIKI_ITEM","target_type":"SOURCE_FILE","relationship_type":"REFERENCED_BY","extra":"Wiki references source file: backend/app/workers/scheduler.py","gmt_create":"2026-04-23T20:33:37.268722+08:00","gmt_modified":"2026-04-23T20:33:37.268722+08:00"},{"id":718,"source_id":"19e75845-5147-4aeb-90be-16f3aa270465","target_id":"04e3926c080e795713bff683e7dc9d3e","source_type":"WIKI_ITEM","target_type":"SOURCE_FILE","relationship_type":"REFERENCED_BY","extra":"Wiki references source file: backend/app/services/citation.py","gmt_create":"2026-04-23T20:33:37.269288+08:00","gmt_modified":"2026-04-23T20:33:37.269288+08:00"},{"id":719,"source_id":"19e75845-5147-4aeb-90be-16f3aa270465","target_id":"7538ffe4902ab6041adb28b19844962a","source_type":"WIKI_ITEM","target_type":"SOURCE_FILE","relationship_type":"REFERENCED_BY","extra":"Wiki references source file: backend/app/api/citations.py","gmt_create":"2026-04-23T20:33:37.270139+08:00","gmt_modified":"2026-04-23T20:33:37.270139+08:00"},{"id":720,"source_id":"19e75845-5147-4aeb-90be-16f3aa270465","target_id":"b4a81ef789630d0af6a8d50859d01bf3","source_type":"WIKI_ITEM","target_type":"SOURCE_FILE","relationship_type":"REFERENCED_BY","extra":"Wiki references source file: backend/app/models/citation_record.py","gmt_create":"2026-04-23T20:33:37.273632+08:00","gmt_modified":"2026-04-23T20:33:37.273632+08:00"},{"id":721,"source_id":"19e75845-5147-4aeb-90be-16f3aa270465","target_id":"b74caccb06844efcdb14d8324cff65c2","source_type":"WIKI_ITEM","target_type":"SOURCE_FILE","relationship_type":"REFERENCED_BY","extra":"Wiki references source file: backend/app/models/query.py","gmt_create":"2026-04-23T20:33:37.275218+08:00","gmt_modified":"2026-04-23T20:33:37.275218+08:00"},{"id":722,"source_id":"19e75845-5147-4aeb-90be-16f3aa270465","target_id":"069738f21ac2da7349d22683e8c36929","source_type":"WIKI_ITEM","target_type":"SOURCE_FILE","relationship_type":"REFERENCED_BY","extra":"Wiki references source file: backend/app/models/query_task.py","gmt_create":"2026-04-23T20:33:37.276269+08:00","gmt_modified":"2026-04-23T20:33:37.27627+08:00"},{"id":723,"source_id":"19e75845-5147-4aeb-90be-16f3aa270465","target_id":"9ff19022ef915615911280e3c49ed44b","source_type":"WIKI_ITEM","target_type":"SOURCE_FILE","relationship_type":"REFERENCED_BY","extra":"Wiki references source file: backend/app/config.py","gmt_create":"2026-04-23T20:33:37.277294+08:00","gmt_modified":"2026-04-23T20:33:37.277294+08:00"},{"id":724,"source_id":"19e75845-5147-4aeb-90be-16f3aa270465","target_id":"9228ff67d4c757a85d9421b71f4b29f5","source_type":"WIKI_ITEM","target_type":"SOURCE_FILE","relationship_type":"REFERENCED_BY","extra":"Wiki references source file: backend/app/main.py","gmt_create":"2026-04-23T20:33:37.278423+08:00","gmt_modified":"2026-04-23T20:33:37.278423+08:00"},{"id":725,"source_id":"19e75845-5147-4aeb-90be-16f3aa270465","target_id":"b07a4fb9cecbbd66a6910ccbc7651f19","source_type":"WIKI_ITEM","target_type":"SOURCE_FILE","relationship_type":"REFERENCED_BY","extra":"Wiki references source file: tests/test_citation_engine.py","gmt_create":"2026-04-23T20:33:37.279079+08:00","gmt_modified":"2026-04-23T20:33:37.279079+08:00"},{"id":726,"source_id":"19e75845-5147-4aeb-90be-16f3aa270465","target_id":"a26ee01cf41da3b956e1650448c156fa","source_type":"WIKI_ITEM","target_type":"SOURCE_FILE","relationship_type":"REFERENCED_BY","extra":"Wiki references source file: backend/requirements.txt","gmt_create":"2026-04-23T20:33:37.279629+08:00","gmt_modified":"2026-04-23T20:33:37.27963+08:00"},{"id":727,"source_id":"19e75845-5147-4aeb-90be-16f3aa270465","target_id":"cbd0101fa84d957bcb1baaa623c6b31c","source_type":"WIKI_ITEM","target_type":"CODE_SNIPPET","relationship_type":"CONTAINS","extra":"Wiki contains code snippet: backend/app/api/citations.py#1-78","gmt_create":"2026-04-23T20:33:37.280454+08:00","gmt_modified":"2026-04-23T20:33:37.280454+08:00"},{"id":728,"source_id":"19e75845-5147-4aeb-90be-16f3aa270465","target_id":"6b3d903205941aa9391dd90016e1102c","source_type":"WIKI_ITEM","target_type":"SOURCE_FILE","relationship_type":"REFERENCED_BY","extra":"Wiki references source file: backend/app/api/queries.py","gmt_create":"2026-04-23T20:33:37.281512+08:00","gmt_modified":"2026-04-23T20:33:37.281513+08:00"},{"id":729,"source_id":"19e75845-5147-4aeb-90be-16f3aa270465","target_id":"482d573f97b482b99bcde1c399eceb73","source_type":"WIKI_ITEM","target_type":"CODE_SNIPPET","relationship_type":"CONTAINS","extra":"Wiki contains code snippet: backend/app/api/queries.py#90-108","gmt_create":"2026-04-23T20:33:37.281875+08:00","gmt_modified":"2026-04-23T20:33:37.281876+08:00"},{"id":730,"source_id":"6b3d903205941aa9391dd90016e1102c","target_id":"482d573f97b482b99bcde1c399eceb73","source_type":"SOURCE_FILE","target_type":"CODE_SNIPPET","relationship_type":"CONTAINS","extra":"Source file contains code snippet: 90-108","gmt_create":"2026-04-23T20:33:37.28285+08:00","gmt_modified":"2026-04-23T20:33:37.28285+08:00"},{"id":731,"source_id":"19e75845-5147-4aeb-90be-16f3aa270465","target_id":"7c0831c17e8c65eaed9511e17ed2a2ef","source_type":"WIKI_ITEM","target_type":"CODE_SNIPPET","relationship_type":"CONTAINS","extra":"Wiki contains code snippet: backend/app/services/citation.py#1-269","gmt_create":"2026-04-23T20:33:37.283208+08:00","gmt_modified":"2026-04-23T20:33:37.283208+08:00"},{"id":732,"source_id":"19e75845-5147-4aeb-90be-16f3aa270465","target_id":"88d22de3b2a7419868e8ae19130d860c","source_type":"WIKI_ITEM","target_type":"SOURCE_FILE","relationship_type":"REFERENCED_BY","extra":"Wiki references source file: backend/app/services/query.py","gmt_create":"2026-04-23T20:33:37.283598+08:00","gmt_modified":"2026-04-23T20:33:37.283598+08:00"},{"id":733,"source_id":"19e75845-5147-4aeb-90be-16f3aa270465","target_id":"4cef9e740b6feb68c6bd22b660c47320","source_type":"WIKI_ITEM","target_type":"CODE_SNIPPET","relationship_type":"CONTAINS","extra":"Wiki contains code snippet: backend/app/services/query.py#1-123","gmt_create":"2026-04-23T20:33:37.284031+08:00","gmt_modified":"2026-04-23T20:33:37.284031+08:00"},{"id":734,"source_id":"19e75845-5147-4aeb-90be-16f3aa270465","target_id":"8d5aac2ae0671f05d7c0807ba9296cdf","source_type":"WIKI_ITEM","target_type":"CODE_SNIPPET","relationship_type":"CONTAINS","extra":"Wiki contains code snippet: backend/app/workers/citation_engine.py#1-330","gmt_create":"2026-04-23T20:33:37.284881+08:00","gmt_modified":"2026-04-23T20:33:37.284881+08:00"},{"id":735,"source_id":"19e75845-5147-4aeb-90be-16f3aa270465","target_id":"72a110dca58d8152758e2fdab4e94761","source_type":"WIKI_ITEM","target_type":"CODE_SNIPPET","relationship_type":"CONTAINS","extra":"Wiki contains code snippet: backend/app/workers/platforms/base.py#1-18","gmt_create":"2026-04-23T20:33:37.285439+08:00","gmt_modified":"2026-04-23T20:33:37.285439+08:00"},{"id":736,"source_id":"19e75845-5147-4aeb-90be-16f3aa270465","target_id":"56f44cc97867cee3e5663424134d6072","source_type":"WIKI_ITEM","target_type":"CODE_SNIPPET","relationship_type":"CONTAINS","extra":"Wiki contains code snippet: backend/app/workers/platforms/kimi.py#1-37","gmt_create":"2026-04-23T20:33:37.285889+08:00","gmt_modified":"2026-04-23T20:33:37.285889+08:00"},{"id":737,"source_id":"8f973791233c698b3e64a4fb28a93d4b","target_id":"56f44cc97867cee3e5663424134d6072","source_type":"SOURCE_FILE","target_type":"CODE_SNIPPET","relationship_type":"CONTAINS","extra":"Source file contains code snippet: 1-37","gmt_create":"2026-04-23T20:33:37.286195+08:00","gmt_modified":"2026-04-23T20:33:37.286195+08:00"},{"id":738,"source_id":"19e75845-5147-4aeb-90be-16f3aa270465","target_id":"2e326ef8322619f1e8b3873022cb0437","source_type":"WIKI_ITEM","target_type":"CODE_SNIPPET","relationship_type":"CONTAINS","extra":"Wiki contains code snippet: backend/app/workers/platforms/wenxin.py#1-37","gmt_create":"2026-04-23T20:33:37.286846+08:00","gmt_modified":"2026-04-23T20:33:37.286846+08:00"},{"id":739,"source_id":"f642fc1c2f34e15572d9d98aa6c18813","target_id":"2e326ef8322619f1e8b3873022cb0437","source_type":"SOURCE_FILE","target_type":"CODE_SNIPPET","relationship_type":"CONTAINS","extra":"Source file contains code snippet: 1-37","gmt_create":"2026-04-23T20:33:37.287299+08:00","gmt_modified":"2026-04-23T20:33:37.287299+08:00"},{"id":740,"source_id":"19e75845-5147-4aeb-90be-16f3aa270465","target_id":"debd789847d1eed2d54198772edf68a2","source_type":"WIKI_ITEM","target_type":"CODE_SNIPPET","relationship_type":"CONTAINS","extra":"Wiki contains code snippet: backend/app/workers/platforms/tongyi.py#1-38","gmt_create":"2026-04-23T20:33:37.28771+08:00","gmt_modified":"2026-04-23T20:33:37.287711+08:00"},{"id":741,"source_id":"19e75845-5147-4aeb-90be-16f3aa270465","target_id":"3bde521d18cc7221ae2f14637e163aac","source_type":"WIKI_ITEM","target_type":"CODE_SNIPPET","relationship_type":"CONTAINS","extra":"Wiki contains code snippet: backend/app/workers/platforms/doubao.py#1-38","gmt_create":"2026-04-23T20:33:37.288659+08:00","gmt_modified":"2026-04-23T20:33:37.288659+08:00"},{"id":742,"source_id":"19e75845-5147-4aeb-90be-16f3aa270465","target_id":"c26862d9e0fc878b51a2668cfd2ec827","source_type":"WIKI_ITEM","target_type":"CODE_SNIPPET","relationship_type":"CONTAINS","extra":"Wiki contains code snippet: backend/app/workers/platforms/qingyan.py#1-38","gmt_create":"2026-04-23T20:33:37.290497+08:00","gmt_modified":"2026-04-23T20:33:37.290498+08:00"},{"id":743,"source_id":"19e75845-5147-4aeb-90be-16f3aa270465","target_id":"0fcc9c2e0d33b887c5f18a3807b64a1e","source_type":"WIKI_ITEM","target_type":"CODE_SNIPPET","relationship_type":"CONTAINS","extra":"Wiki contains code snippet: backend/app/workers/platforms/tiangong.py#1-38","gmt_create":"2026-04-23T20:33:37.292345+08:00","gmt_modified":"2026-04-23T20:33:37.292345+08:00"},{"id":744,"source_id":"19e75845-5147-4aeb-90be-16f3aa270465","target_id":"a4baa2444208b3f9a3f42bc492038207","source_type":"WIKI_ITEM","target_type":"CODE_SNIPPET","relationship_type":"CONTAINS","extra":"Wiki contains code snippet: backend/app/workers/platforms/xinghuo.py#1-38","gmt_create":"2026-04-23T20:33:37.293708+08:00","gmt_modified":"2026-04-23T20:33:37.293708+08:00"},{"id":745,"source_id":"19e75845-5147-4aeb-90be-16f3aa270465","target_id":"9f82f6d82bf914a608d6afa3d9854abf","source_type":"WIKI_ITEM","target_type":"CODE_SNIPPET","relationship_type":"CONTAINS","extra":"Wiki contains code snippet: backend/app/workers/platforms/search_engine.py#1-174","gmt_create":"2026-04-23T20:33:37.2944+08:00","gmt_modified":"2026-04-23T20:33:37.2944+08:00"},{"id":746,"source_id":"19e75845-5147-4aeb-90be-16f3aa270465","target_id":"4cac57dbc530f0335c913ec5725dfa4f","source_type":"WIKI_ITEM","target_type":"CODE_SNIPPET","relationship_type":"CONTAINS","extra":"Wiki contains code snippet: backend/app/workers/scheduler.py#1-121","gmt_create":"2026-04-23T20:33:37.295331+08:00","gmt_modified":"2026-04-23T20:33:37.295331+08:00"},{"id":747,"source_id":"5cbb1e3f112aeba62a14b0b8999fc0f5","target_id":"4cac57dbc530f0335c913ec5725dfa4f","source_type":"SOURCE_FILE","target_type":"CODE_SNIPPET","relationship_type":"CONTAINS","extra":"Source file contains code snippet: 1-121","gmt_create":"2026-04-23T20:33:37.296239+08:00","gmt_modified":"2026-04-23T20:33:37.296239+08:00"},{"id":748,"source_id":"19e75845-5147-4aeb-90be-16f3aa270465","target_id":"6281fff17a86ec1895c64d87c2ae7fb1","source_type":"WIKI_ITEM","target_type":"CODE_SNIPPET","relationship_type":"CONTAINS","extra":"Wiki contains code snippet: backend/app/models/query.py#1-55","gmt_create":"2026-04-23T20:33:37.296858+08:00","gmt_modified":"2026-04-23T20:33:37.296858+08:00"},{"id":749,"source_id":"19e75845-5147-4aeb-90be-16f3aa270465","target_id":"6628e006b8e5ca16160743528b6b0506","source_type":"WIKI_ITEM","target_type":"CODE_SNIPPET","relationship_type":"CONTAINS","extra":"Wiki contains code snippet: backend/app/models/query_task.py#1-39","gmt_create":"2026-04-23T20:33:37.297624+08:00","gmt_modified":"2026-04-23T20:33:37.297624+08:00"},{"id":750,"source_id":"19e75845-5147-4aeb-90be-16f3aa270465","target_id":"943c18db69a04b3137fba4cebcfea87e","source_type":"WIKI_ITEM","target_type":"CODE_SNIPPET","relationship_type":"CONTAINS","extra":"Wiki contains code snippet: backend/app/models/citation_record.py#1-42","gmt_create":"2026-04-23T20:33:37.298765+08:00","gmt_modified":"2026-04-23T20:33:37.298765+08:00"},{"id":751,"source_id":"19e75845-5147-4aeb-90be-16f3aa270465","target_id":"84fbed7d35f7752e2117a74fcaf5f0e9","source_type":"WIKI_ITEM","target_type":"CODE_SNIPPET","relationship_type":"CONTAINS","extra":"Wiki contains code snippet: backend/app/config.py#1-17","gmt_create":"2026-04-23T20:33:37.299752+08:00","gmt_modified":"2026-04-23T20:33:37.299752+08:00"},{"id":752,"source_id":"19e75845-5147-4aeb-90be-16f3aa270465","target_id":"c2747ca16b879bca0f68955534c3c4fc","source_type":"WIKI_ITEM","target_type":"CODE_SNIPPET","relationship_type":"CONTAINS","extra":"Wiki contains code snippet: backend/app/main.py#1-48","gmt_create":"2026-04-23T20:33:37.30067+08:00","gmt_modified":"2026-04-23T20:33:37.30067+08:00"},{"id":753,"source_id":"19e75845-5147-4aeb-90be-16f3aa270465","target_id":"db174cfe219fc84d0dd26529f047b1d0","source_type":"WIKI_ITEM","target_type":"CODE_SNIPPET","relationship_type":"CONTAINS","extra":"Wiki contains code snippet: backend/app/workers/citation_engine.py#161-330","gmt_create":"2026-04-23T20:33:37.304109+08:00","gmt_modified":"2026-04-23T20:33:37.304109+08:00"},{"id":754,"source_id":"74040de652d5e57f548bb5c4adc3e1a0","target_id":"db174cfe219fc84d0dd26529f047b1d0","source_type":"SOURCE_FILE","target_type":"CODE_SNIPPET","relationship_type":"CONTAINS","extra":"Source file contains code snippet: 161-330","gmt_create":"2026-04-23T20:33:37.304836+08:00","gmt_modified":"2026-04-23T20:33:37.304836+08:00"},{"id":755,"source_id":"19e75845-5147-4aeb-90be-16f3aa270465","target_id":"f36452f78aabfb0c46da03bbe25dff06","source_type":"WIKI_ITEM","target_type":"CODE_SNIPPET","relationship_type":"CONTAINS","extra":"Wiki contains code snippet: backend/app/services/citation.py#219-295","gmt_create":"2026-04-23T20:33:37.307629+08:00","gmt_modified":"2026-04-23T20:33:37.307629+08:00"},{"id":756,"source_id":"04e3926c080e795713bff683e7dc9d3e","target_id":"f36452f78aabfb0c46da03bbe25dff06","source_type":"SOURCE_FILE","target_type":"CODE_SNIPPET","relationship_type":"CONTAINS","extra":"Source file contains code snippet: 219-295","gmt_create":"2026-04-23T20:33:37.308258+08:00","gmt_modified":"2026-04-23T20:33:37.308258+08:00"},{"id":757,"source_id":"19e75845-5147-4aeb-90be-16f3aa270465","target_id":"362d22f423631cda39404660b3317a2f","source_type":"WIKI_ITEM","target_type":"CODE_SNIPPET","relationship_type":"CONTAINS","extra":"Wiki contains code snippet: backend/app/workers/citation_engine.py#177-254","gmt_create":"2026-04-23T20:33:37.310127+08:00","gmt_modified":"2026-04-23T20:33:37.310127+08:00"},{"id":758,"source_id":"19e75845-5147-4aeb-90be-16f3aa270465","target_id":"b475ff5225ac403c7fcf3dd7e14cbac6","source_type":"WIKI_ITEM","target_type":"CODE_SNIPPET","relationship_type":"CONTAINS","extra":"Wiki contains code snippet: backend/app/workers/platforms/tongyi.py#16-33","gmt_create":"2026-04-23T20:33:37.31061+08:00","gmt_modified":"2026-04-23T20:33:37.31061+08:00"},{"id":759,"source_id":"19e75845-5147-4aeb-90be-16f3aa270465","target_id":"557ae34b57a5dd8e8fa3bb2a6ce178a7","source_type":"WIKI_ITEM","target_type":"CODE_SNIPPET","relationship_type":"CONTAINS","extra":"Wiki contains code snippet: backend/app/workers/platforms/search_engine.py#163-174","gmt_create":"2026-04-23T20:33:37.311106+08:00","gmt_modified":"2026-04-23T20:33:37.311106+08:00"},{"id":760,"source_id":"19e75845-5147-4aeb-90be-16f3aa270465","target_id":"52c01d7b9c17aa16944cbfcf8885be61","source_type":"WIKI_ITEM","target_type":"CODE_SNIPPET","relationship_type":"CONTAINS","extra":"Wiki contains code snippet: backend/app/workers/platforms/kimi.py#16-33","gmt_create":"2026-04-23T20:33:37.311558+08:00","gmt_modified":"2026-04-23T20:33:37.311558+08:00"},{"id":761,"source_id":"8f973791233c698b3e64a4fb28a93d4b","target_id":"52c01d7b9c17aa16944cbfcf8885be61","source_type":"SOURCE_FILE","target_type":"CODE_SNIPPET","relationship_type":"CONTAINS","extra":"Source file contains code snippet: 16-33","gmt_create":"2026-04-23T20:33:37.319146+08:00","gmt_modified":"2026-04-23T20:33:37.319146+08:00"},{"id":762,"source_id":"19e75845-5147-4aeb-90be-16f3aa270465","target_id":"77158a6f887e224a03552893bfec7c92","source_type":"WIKI_ITEM","target_type":"CODE_SNIPPET","relationship_type":"CONTAINS","extra":"Wiki contains code snippet: backend/app/workers/platforms/wenxin.py#16-33","gmt_create":"2026-04-23T20:33:37.320166+08:00","gmt_modified":"2026-04-23T20:33:37.320166+08:00"},{"id":763,"source_id":"19e75845-5147-4aeb-90be-16f3aa270465","target_id":"9d352899554ab41b65b2e9f32558d811","source_type":"WIKI_ITEM","target_type":"CODE_SNIPPET","relationship_type":"CONTAINS","extra":"Wiki contains code snippet: backend/app/workers/citation_engine.py#39-113","gmt_create":"2026-04-23T20:33:37.321322+08:00","gmt_modified":"2026-04-23T20:33:37.321322+08:00"},{"id":764,"source_id":"74040de652d5e57f548bb5c4adc3e1a0","target_id":"9d352899554ab41b65b2e9f32558d811","source_type":"SOURCE_FILE","target_type":"CODE_SNIPPET","relationship_type":"CONTAINS","extra":"Source file contains code snippet: 39-113","gmt_create":"2026-04-23T20:33:37.322276+08:00","gmt_modified":"2026-04-23T20:33:37.322276+08:00"},{"id":765,"source_id":"19e75845-5147-4aeb-90be-16f3aa270465","target_id":"b1ee5a992230844ba898765be63f7b27","source_type":"WIKI_ITEM","target_type":"CODE_SNIPPET","relationship_type":"CONTAINS","extra":"Wiki contains code snippet: backend/app/workers/citation_engine.py#32-133","gmt_create":"2026-04-23T20:33:37.323119+08:00","gmt_modified":"2026-04-23T20:33:37.323119+08:00"},{"id":766,"source_id":"74040de652d5e57f548bb5c4adc3e1a0","target_id":"b1ee5a992230844ba898765be63f7b27","source_type":"SOURCE_FILE","target_type":"CODE_SNIPPET","relationship_type":"CONTAINS","extra":"Source file contains code snippet: 32-133","gmt_create":"2026-04-23T20:33:37.323615+08:00","gmt_modified":"2026-04-23T20:33:37.323615+08:00"},{"id":767,"source_id":"19e75845-5147-4aeb-90be-16f3aa270465","target_id":"cb098a3cd32339e99f755dfd0fc35b5c","source_type":"WIKI_ITEM","target_type":"CODE_SNIPPET","relationship_type":"CONTAINS","extra":"Wiki contains code snippet: tests/test_citation_engine.py#6-127","gmt_create":"2026-04-23T20:33:37.324259+08:00","gmt_modified":"2026-04-23T20:33:37.324259+08:00"},{"id":768,"source_id":"b07a4fb9cecbbd66a6910ccbc7651f19","target_id":"cb098a3cd32339e99f755dfd0fc35b5c","source_type":"SOURCE_FILE","target_type":"CODE_SNIPPET","relationship_type":"CONTAINS","extra":"Source file contains code snippet: 6-127","gmt_create":"2026-04-23T20:33:37.32508+08:00","gmt_modified":"2026-04-23T20:33:37.32508+08:00"},{"id":769,"source_id":"19e75845-5147-4aeb-90be-16f3aa270465","target_id":"3d2dab79f7a3fedf24f0212cc9ef7aa1","source_type":"WIKI_ITEM","target_type":"CODE_SNIPPET","relationship_type":"CONTAINS","extra":"Wiki contains code snippet: backend/app/workers/citation_engine.py#145-158","gmt_create":"2026-04-23T20:33:37.325915+08:00","gmt_modified":"2026-04-23T20:33:37.325915+08:00"},{"id":770,"source_id":"74040de652d5e57f548bb5c4adc3e1a0","target_id":"3d2dab79f7a3fedf24f0212cc9ef7aa1","source_type":"SOURCE_FILE","target_type":"CODE_SNIPPET","relationship_type":"CONTAINS","extra":"Source file contains code snippet: 145-158","gmt_create":"2026-04-23T20:33:37.327012+08:00","gmt_modified":"2026-04-23T20:33:37.327012+08:00"},{"id":771,"source_id":"19e75845-5147-4aeb-90be-16f3aa270465","target_id":"4e9b3d0e94282f4bc6fa500f4eed61a1","source_type":"WIKI_ITEM","target_type":"CODE_SNIPPET","relationship_type":"CONTAINS","extra":"Wiki contains code snippet: backend/app/workers/citation_engine.py#135-159","gmt_create":"2026-04-23T20:33:37.327853+08:00","gmt_modified":"2026-04-23T20:33:37.327853+08:00"},{"id":772,"source_id":"74040de652d5e57f548bb5c4adc3e1a0","target_id":"4e9b3d0e94282f4bc6fa500f4eed61a1","source_type":"SOURCE_FILE","target_type":"CODE_SNIPPET","relationship_type":"CONTAINS","extra":"Source file contains code snippet: 135-159","gmt_create":"2026-04-23T20:33:37.328872+08:00","gmt_modified":"2026-04-23T20:33:37.328872+08:00"},{"id":773,"source_id":"19e75845-5147-4aeb-90be-16f3aa270465","target_id":"8e3201561a9dd9a06ee3bf68ffdb3f99","source_type":"WIKI_ITEM","target_type":"CODE_SNIPPET","relationship_type":"CONTAINS","extra":"Wiki contains code snippet: tests/test_citation_engine.py#39-109","gmt_create":"2026-04-23T20:33:37.32989+08:00","gmt_modified":"2026-04-23T20:33:37.32989+08:00"},{"id":774,"source_id":"b07a4fb9cecbbd66a6910ccbc7651f19","target_id":"8e3201561a9dd9a06ee3bf68ffdb3f99","source_type":"SOURCE_FILE","target_type":"CODE_SNIPPET","relationship_type":"CONTAINS","extra":"Source file contains code snippet: 39-109","gmt_create":"2026-04-23T20:33:37.33132+08:00","gmt_modified":"2026-04-23T20:33:37.33132+08:00"},{"id":775,"source_id":"19e75845-5147-4aeb-90be-16f3aa270465","target_id":"c3a417be3d61f5bcd3fbf976e0c4f15a","source_type":"WIKI_ITEM","target_type":"CODE_SNIPPET","relationship_type":"CONTAINS","extra":"Wiki contains code snippet: backend/app/workers/scheduler.py#33-121","gmt_create":"2026-04-23T20:33:37.336944+08:00","gmt_modified":"2026-04-23T20:33:37.336944+08:00"},{"id":776,"source_id":"5cbb1e3f112aeba62a14b0b8999fc0f5","target_id":"c3a417be3d61f5bcd3fbf976e0c4f15a","source_type":"SOURCE_FILE","target_type":"CODE_SNIPPET","relationship_type":"CONTAINS","extra":"Source file contains code snippet: 33-121","gmt_create":"2026-04-23T20:33:37.337655+08:00","gmt_modified":"2026-04-23T20:33:37.337655+08:00"},{"id":777,"source_id":"19e75845-5147-4aeb-90be-16f3aa270465","target_id":"096856da621e23e78422a15e2bfce1f1","source_type":"WIKI_ITEM","target_type":"CODE_SNIPPET","relationship_type":"CONTAINS","extra":"Wiki contains code snippet: backend/app/main.py#13-22","gmt_create":"2026-04-23T20:33:37.339169+08:00","gmt_modified":"2026-04-23T20:33:37.339169+08:00"},{"id":778,"source_id":"19e75845-5147-4aeb-90be-16f3aa270465","target_id":"7ce954ed7d3bc4dcf78630124cc0dd88","source_type":"WIKI_ITEM","target_type":"CODE_SNIPPET","relationship_type":"CONTAINS","extra":"Wiki contains code snippet: backend/app/services/citation.py#264-295","gmt_create":"2026-04-23T20:33:37.34124+08:00","gmt_modified":"2026-04-23T20:33:37.34124+08:00"},{"id":779,"source_id":"04e3926c080e795713bff683e7dc9d3e","target_id":"7ce954ed7d3bc4dcf78630124cc0dd88","source_type":"SOURCE_FILE","target_type":"CODE_SNIPPET","relationship_type":"CONTAINS","extra":"Source file contains code snippet: 264-295","gmt_create":"2026-04-23T20:33:37.342433+08:00","gmt_modified":"2026-04-23T20:33:37.342433+08:00"},{"id":780,"source_id":"19e75845-5147-4aeb-90be-16f3aa270465","target_id":"7289a3568c137c8a671fc8c963bb8d28","source_type":"WIKI_ITEM","target_type":"CODE_SNIPPET","relationship_type":"CONTAINS","extra":"Wiki contains code snippet: backend/requirements.txt#1-35","gmt_create":"2026-04-23T20:33:37.346038+08:00","gmt_modified":"2026-04-23T20:33:37.346038+08:00"},{"id":781,"source_id":"a26ee01cf41da3b956e1650448c156fa","target_id":"7289a3568c137c8a671fc8c963bb8d28","source_type":"SOURCE_FILE","target_type":"CODE_SNIPPET","relationship_type":"CONTAINS","extra":"Source file contains code snippet: 1-35","gmt_create":"2026-04-23T20:33:37.346577+08:00","gmt_modified":"2026-04-23T20:33:37.346577+08:00"},{"id":782,"source_id":"19e75845-5147-4aeb-90be-16f3aa270465","target_id":"ef82ce4377c549013c200e19701a6805","source_type":"WIKI_ITEM","target_type":"CODE_SNIPPET","relationship_type":"CONTAINS","extra":"Wiki contains code snippet: backend/app/workers/platforms/kimi.py#21-32","gmt_create":"2026-04-23T20:33:37.352671+08:00","gmt_modified":"2026-04-23T20:33:37.352671+08:00"},{"id":783,"source_id":"8f973791233c698b3e64a4fb28a93d4b","target_id":"ef82ce4377c549013c200e19701a6805","source_type":"SOURCE_FILE","target_type":"CODE_SNIPPET","relationship_type":"CONTAINS","extra":"Source file contains code snippet: 21-32","gmt_create":"2026-04-23T20:33:37.354355+08:00","gmt_modified":"2026-04-23T20:33:37.354355+08:00"},{"id":784,"source_id":"19e75845-5147-4aeb-90be-16f3aa270465","target_id":"c7986eb1be0ffdd9ec4e243be4270119","source_type":"WIKI_ITEM","target_type":"CODE_SNIPPET","relationship_type":"CONTAINS","extra":"Wiki contains code snippet: backend/app/workers/platforms/wenxin.py#21-32","gmt_create":"2026-04-23T20:33:37.355472+08:00","gmt_modified":"2026-04-23T20:33:37.355472+08:00"},{"id":785,"source_id":"f642fc1c2f34e15572d9d98aa6c18813","target_id":"c7986eb1be0ffdd9ec4e243be4270119","source_type":"SOURCE_FILE","target_type":"CODE_SNIPPET","relationship_type":"CONTAINS","extra":"Source file contains code snippet: 21-32","gmt_create":"2026-04-23T20:33:37.357613+08:00","gmt_modified":"2026-04-23T20:33:37.357613+08:00"},{"id":786,"source_id":"19e75845-5147-4aeb-90be-16f3aa270465","target_id":"b55cc5936c299f819b57b899858438e6","source_type":"WIKI_ITEM","target_type":"CODE_SNIPPET","relationship_type":"CONTAINS","extra":"Wiki contains code snippet: backend/app/workers/platforms/search_engine.py#139-144","gmt_create":"2026-04-23T20:33:37.358273+08:00","gmt_modified":"2026-04-23T20:33:37.358273+08:00"},{"id":787,"source_id":"19e75845-5147-4aeb-90be-16f3aa270465","target_id":"5563b3bd56550648dc70302c1762ce5a","source_type":"WIKI_ITEM","target_type":"CODE_SNIPPET","relationship_type":"CONTAINS","extra":"Wiki contains code snippet: backend/app/workers/platforms/tongyi.py#18-29","gmt_create":"2026-04-23T20:33:37.360657+08:00","gmt_modified":"2026-04-23T20:33:37.360657+08:00"},{"id":788,"source_id":"e68ad5186f1e47610ab3d9f14a794393","target_id":"5563b3bd56550648dc70302c1762ce5a","source_type":"SOURCE_FILE","target_type":"CODE_SNIPPET","relationship_type":"CONTAINS","extra":"Source file contains code snippet: 18-29","gmt_create":"2026-04-23T20:33:37.361776+08:00","gmt_modified":"2026-04-23T20:33:37.361776+08:00"},{"id":789,"source_id":"19e75845-5147-4aeb-90be-16f3aa270465","target_id":"91852ef8dcc844a2f85e9fce0227ab74","source_type":"WIKI_ITEM","target_type":"CODE_SNIPPET","relationship_type":"CONTAINS","extra":"Wiki contains code snippet: backend/app/workers/platforms/doubao.py#18-29","gmt_create":"2026-04-23T20:33:37.363109+08:00","gmt_modified":"2026-04-23T20:33:37.363109+08:00"},{"id":790,"source_id":"404f6d0765a8c6e77e33b7fc21b377a4","target_id":"91852ef8dcc844a2f85e9fce0227ab74","source_type":"SOURCE_FILE","target_type":"CODE_SNIPPET","relationship_type":"CONTAINS","extra":"Source file contains code snippet: 18-29","gmt_create":"2026-04-23T20:33:37.363811+08:00","gmt_modified":"2026-04-23T20:33:37.363811+08:00"},{"id":791,"source_id":"19e75845-5147-4aeb-90be-16f3aa270465","target_id":"1b46fab9e22f53db30ead5677d03e3e2","source_type":"WIKI_ITEM","target_type":"CODE_SNIPPET","relationship_type":"CONTAINS","extra":"Wiki contains code snippet: backend/app/workers/citation_engine.py#11-16","gmt_create":"2026-04-23T20:33:37.364819+08:00","gmt_modified":"2026-04-23T20:33:37.364819+08:00"},{"id":792,"source_id":"74040de652d5e57f548bb5c4adc3e1a0","target_id":"1b46fab9e22f53db30ead5677d03e3e2","source_type":"SOURCE_FILE","target_type":"CODE_SNIPPET","relationship_type":"CONTAINS","extra":"Source file contains code snippet: 11-16","gmt_create":"2026-04-23T20:33:37.365554+08:00","gmt_modified":"2026-04-23T20:33:37.365554+08:00"},{"id":793,"source_id":"19e75845-5147-4aeb-90be-16f3aa270465","target_id":"f096aa3ea82e9fa625a9acb1309b4c50","source_type":"WIKI_ITEM","target_type":"CODE_SNIPPET","relationship_type":"CONTAINS","extra":"Wiki contains code snippet: backend/app/workers/citation_engine.py#231-247","gmt_create":"2026-04-23T20:33:37.36634+08:00","gmt_modified":"2026-04-23T20:33:37.366341+08:00"},{"id":794,"source_id":"19e75845-5147-4aeb-90be-16f3aa270465","target_id":"4a2fa09aa3a948dec5ef8ba873b0e716","source_type":"WIKI_ITEM","target_type":"CODE_SNIPPET","relationship_type":"CONTAINS","extra":"Wiki contains code snippet: backend/app/services/citation.py#14-42","gmt_create":"2026-04-23T20:33:37.367379+08:00","gmt_modified":"2026-04-23T20:33:37.367379+08:00"},{"id":795,"source_id":"04e3926c080e795713bff683e7dc9d3e","target_id":"4a2fa09aa3a948dec5ef8ba873b0e716","source_type":"SOURCE_FILE","target_type":"CODE_SNIPPET","relationship_type":"CONTAINS","extra":"Source file contains code snippet: 14-42","gmt_create":"2026-04-23T20:33:37.368233+08:00","gmt_modified":"2026-04-23T20:33:37.368233+08:00"},{"id":796,"source_id":"74d3018f-4e23-4687-8bf4-7fb403f479f7","target_id":"6b3d903205941aa9391dd90016e1102c","source_type":"WIKI_ITEM","target_type":"SOURCE_FILE","relationship_type":"REFERENCED_BY","extra":"Wiki references source file: backend/app/api/queries.py","gmt_create":"2026-04-23T20:33:57.518077+08:00","gmt_modified":"2026-04-23T20:33:57.518077+08:00"},{"id":797,"source_id":"74d3018f-4e23-4687-8bf4-7fb403f479f7","target_id":"f301b79d833233ce39d350e82a71c938","source_type":"WIKI_ITEM","target_type":"SOURCE_FILE","relationship_type":"REFERENCED_BY","extra":"Wiki references source file: backend/app/schemas/query.py","gmt_create":"2026-04-23T20:33:57.518453+08:00","gmt_modified":"2026-04-23T20:33:57.518454+08:00"},{"id":798,"source_id":"74d3018f-4e23-4687-8bf4-7fb403f479f7","target_id":"1a3336b4af8a39a055e912724338580c","source_type":"WIKI_ITEM","target_type":"SOURCE_FILE","relationship_type":"REFERENCED_BY","extra":"Wiki references source file: backend/app/schemas/citation.py","gmt_create":"2026-04-23T20:33:57.519644+08:00","gmt_modified":"2026-04-23T20:33:57.519644+08:00"},{"id":799,"source_id":"74d3018f-4e23-4687-8bf4-7fb403f479f7","target_id":"b74caccb06844efcdb14d8324cff65c2","source_type":"WIKI_ITEM","target_type":"SOURCE_FILE","relationship_type":"REFERENCED_BY","extra":"Wiki references source file: backend/app/models/query.py","gmt_create":"2026-04-23T20:33:57.521079+08:00","gmt_modified":"2026-04-23T20:33:57.521079+08:00"},{"id":800,"source_id":"74d3018f-4e23-4687-8bf4-7fb403f479f7","target_id":"069738f21ac2da7349d22683e8c36929","source_type":"WIKI_ITEM","target_type":"SOURCE_FILE","relationship_type":"REFERENCED_BY","extra":"Wiki references source file: backend/app/models/query_task.py","gmt_create":"2026-04-23T20:33:57.522061+08:00","gmt_modified":"2026-04-23T20:33:57.522061+08:00"},{"id":801,"source_id":"74d3018f-4e23-4687-8bf4-7fb403f479f7","target_id":"b4a81ef789630d0af6a8d50859d01bf3","source_type":"WIKI_ITEM","target_type":"SOURCE_FILE","relationship_type":"REFERENCED_BY","extra":"Wiki references source file: backend/app/models/citation_record.py","gmt_create":"2026-04-23T20:33:57.523189+08:00","gmt_modified":"2026-04-23T20:33:57.523189+08:00"},{"id":802,"source_id":"74d3018f-4e23-4687-8bf4-7fb403f479f7","target_id":"c59f8c276697a070dffc581fe94d809c","source_type":"WIKI_ITEM","target_type":"SOURCE_FILE","relationship_type":"REFERENCED_BY","extra":"Wiki references source file: backend/app/models/user.py","gmt_create":"2026-04-23T20:33:57.52383+08:00","gmt_modified":"2026-04-23T20:33:57.52383+08:00"},{"id":803,"source_id":"74d3018f-4e23-4687-8bf4-7fb403f479f7","target_id":"88d22de3b2a7419868e8ae19130d860c","source_type":"WIKI_ITEM","target_type":"SOURCE_FILE","relationship_type":"REFERENCED_BY","extra":"Wiki references source file: backend/app/services/query.py","gmt_create":"2026-04-23T20:33:57.524563+08:00","gmt_modified":"2026-04-23T20:33:57.524563+08:00"},{"id":804,"source_id":"74d3018f-4e23-4687-8bf4-7fb403f479f7","target_id":"04e3926c080e795713bff683e7dc9d3e","source_type":"WIKI_ITEM","target_type":"SOURCE_FILE","relationship_type":"REFERENCED_BY","extra":"Wiki references source file: backend/app/services/citation.py","gmt_create":"2026-04-23T20:33:57.525774+08:00","gmt_modified":"2026-04-23T20:33:57.525774+08:00"},{"id":805,"source_id":"74d3018f-4e23-4687-8bf4-7fb403f479f7","target_id":"5cbb1e3f112aeba62a14b0b8999fc0f5","source_type":"WIKI_ITEM","target_type":"SOURCE_FILE","relationship_type":"REFERENCED_BY","extra":"Wiki references source file: backend/app/workers/scheduler.py","gmt_create":"2026-04-23T20:33:57.526492+08:00","gmt_modified":"2026-04-23T20:33:57.526492+08:00"},{"id":806,"source_id":"74d3018f-4e23-4687-8bf4-7fb403f479f7","target_id":"74040de652d5e57f548bb5c4adc3e1a0","source_type":"WIKI_ITEM","target_type":"SOURCE_FILE","relationship_type":"REFERENCED_BY","extra":"Wiki references source file: backend/app/workers/citation_engine.py","gmt_create":"2026-04-23T20:33:57.527326+08:00","gmt_modified":"2026-04-23T20:33:57.527326+08:00"},{"id":807,"source_id":"74d3018f-4e23-4687-8bf4-7fb403f479f7","target_id":"a16cf42e9559523c4f96ca4c79f9488d","source_type":"WIKI_ITEM","target_type":"SOURCE_FILE","relationship_type":"REFERENCED_BY","extra":"Wiki references source file: backend/app/workers/platforms/base.py","gmt_create":"2026-04-23T20:33:57.527983+08:00","gmt_modified":"2026-04-23T20:33:57.527983+08:00"},{"id":808,"source_id":"74d3018f-4e23-4687-8bf4-7fb403f479f7","target_id":"8f973791233c698b3e64a4fb28a93d4b","source_type":"WIKI_ITEM","target_type":"SOURCE_FILE","relationship_type":"REFERENCED_BY","extra":"Wiki references source file: backend/app/workers/platforms/kimi.py","gmt_create":"2026-04-23T20:33:57.529144+08:00","gmt_modified":"2026-04-23T20:33:57.529144+08:00"},{"id":809,"source_id":"74d3018f-4e23-4687-8bf4-7fb403f479f7","target_id":"f642fc1c2f34e15572d9d98aa6c18813","source_type":"WIKI_ITEM","target_type":"SOURCE_FILE","relationship_type":"REFERENCED_BY","extra":"Wiki references source file: backend/app/workers/platforms/wenxin.py","gmt_create":"2026-04-23T20:33:57.529998+08:00","gmt_modified":"2026-04-23T20:33:57.529998+08:00"},{"id":810,"source_id":"74d3018f-4e23-4687-8bf4-7fb403f479f7","target_id":"7538ffe4902ab6041adb28b19844962a","source_type":"WIKI_ITEM","target_type":"SOURCE_FILE","relationship_type":"REFERENCED_BY","extra":"Wiki references source file: backend/app/api/citations.py","gmt_create":"2026-04-23T20:33:57.530659+08:00","gmt_modified":"2026-04-23T20:33:57.530659+08:00"},{"id":811,"source_id":"74d3018f-4e23-4687-8bf4-7fb403f479f7","target_id":"9228ff67d4c757a85d9421b71f4b29f5","source_type":"WIKI_ITEM","target_type":"SOURCE_FILE","relationship_type":"REFERENCED_BY","extra":"Wiki references source file: backend/app/main.py","gmt_create":"2026-04-23T20:33:57.531953+08:00","gmt_modified":"2026-04-23T20:33:57.531953+08:00"},{"id":812,"source_id":"74d3018f-4e23-4687-8bf4-7fb403f479f7","target_id":"0613e76b9679be7f998fb8fd8056e686","source_type":"WIKI_ITEM","target_type":"SOURCE_FILE","relationship_type":"REFERENCED_BY","extra":"Wiki references source file: tests/test_queries.py","gmt_create":"2026-04-23T20:33:57.532681+08:00","gmt_modified":"2026-04-23T20:33:57.532681+08:00"},{"id":813,"source_id":"74d3018f-4e23-4687-8bf4-7fb403f479f7","target_id":"80a0429cc47931de27ddb17a62b8dd9c","source_type":"WIKI_ITEM","target_type":"SOURCE_FILE","relationship_type":"REFERENCED_BY","extra":"Wiki references source file: tests/test_business_flow.py","gmt_create":"2026-04-23T20:33:57.533708+08:00","gmt_modified":"2026-04-23T20:33:57.533708+08:00"},{"id":814,"source_id":"74d3018f-4e23-4687-8bf4-7fb403f479f7","target_id":"e27bcba24aaadeec1922d2b4e5b8386b","source_type":"WIKI_ITEM","target_type":"CODE_SNIPPET","relationship_type":"CONTAINS","extra":"Wiki contains code snippet: backend/app/api/queries.py#1-109","gmt_create":"2026-04-23T20:33:57.534482+08:00","gmt_modified":"2026-04-23T20:33:57.534482+08:00"},{"id":815,"source_id":"74d3018f-4e23-4687-8bf4-7fb403f479f7","target_id":"e7afbab5932c93c3469f1a225e6c7156","source_type":"WIKI_ITEM","target_type":"CODE_SNIPPET","relationship_type":"CONTAINS","extra":"Wiki contains code snippet: backend/app/api/citations.py#1-55","gmt_create":"2026-04-23T20:33:57.535515+08:00","gmt_modified":"2026-04-23T20:33:57.535515+08:00"},{"id":816,"source_id":"7538ffe4902ab6041adb28b19844962a","target_id":"e7afbab5932c93c3469f1a225e6c7156","source_type":"SOURCE_FILE","target_type":"CODE_SNIPPET","relationship_type":"CONTAINS","extra":"Source file contains code snippet: 1-55","gmt_create":"2026-04-23T20:33:57.536318+08:00","gmt_modified":"2026-04-23T20:33:57.536318+08:00"},{"id":817,"source_id":"74d3018f-4e23-4687-8bf4-7fb403f479f7","target_id":"a0eac56d622a2fff529bc2b796064bcd","source_type":"WIKI_ITEM","target_type":"CODE_SNIPPET","relationship_type":"CONTAINS","extra":"Wiki contains code snippet: backend/app/schemas/query.py#1-94","gmt_create":"2026-04-23T20:33:57.537094+08:00","gmt_modified":"2026-04-23T20:33:57.537094+08:00"},{"id":818,"source_id":"f301b79d833233ce39d350e82a71c938","target_id":"a0eac56d622a2fff529bc2b796064bcd","source_type":"SOURCE_FILE","target_type":"CODE_SNIPPET","relationship_type":"CONTAINS","extra":"Source file contains code snippet: 1-94","gmt_create":"2026-04-23T20:33:57.537769+08:00","gmt_modified":"2026-04-23T20:33:57.53777+08:00"},{"id":819,"source_id":"74d3018f-4e23-4687-8bf4-7fb403f479f7","target_id":"174be58163b6f72b4cd4a493f3463ce4","source_type":"WIKI_ITEM","target_type":"CODE_SNIPPET","relationship_type":"CONTAINS","extra":"Wiki contains code snippet: backend/app/schemas/citation.py#1-52","gmt_create":"2026-04-23T20:33:57.53855+08:00","gmt_modified":"2026-04-23T20:33:57.53855+08:00"},{"id":820,"source_id":"1a3336b4af8a39a055e912724338580c","target_id":"174be58163b6f72b4cd4a493f3463ce4","source_type":"SOURCE_FILE","target_type":"CODE_SNIPPET","relationship_type":"CONTAINS","extra":"Source file contains code snippet: 1-52","gmt_create":"2026-04-23T20:33:57.53965+08:00","gmt_modified":"2026-04-23T20:33:57.53965+08:00"},{"id":821,"source_id":"74d3018f-4e23-4687-8bf4-7fb403f479f7","target_id":"6281fff17a86ec1895c64d87c2ae7fb1","source_type":"WIKI_ITEM","target_type":"CODE_SNIPPET","relationship_type":"CONTAINS","extra":"Wiki contains code snippet: backend/app/models/query.py#1-55","gmt_create":"2026-04-23T20:33:57.54057+08:00","gmt_modified":"2026-04-23T20:33:57.54057+08:00"},{"id":822,"source_id":"74d3018f-4e23-4687-8bf4-7fb403f479f7","target_id":"6628e006b8e5ca16160743528b6b0506","source_type":"WIKI_ITEM","target_type":"CODE_SNIPPET","relationship_type":"CONTAINS","extra":"Wiki contains code snippet: backend/app/models/query_task.py#1-39","gmt_create":"2026-04-23T20:33:57.541654+08:00","gmt_modified":"2026-04-23T20:33:57.541654+08:00"},{"id":823,"source_id":"74d3018f-4e23-4687-8bf4-7fb403f479f7","target_id":"943c18db69a04b3137fba4cebcfea87e","source_type":"WIKI_ITEM","target_type":"CODE_SNIPPET","relationship_type":"CONTAINS","extra":"Wiki contains code snippet: backend/app/models/citation_record.py#1-42","gmt_create":"2026-04-23T20:33:57.543056+08:00","gmt_modified":"2026-04-23T20:33:57.543056+08:00"},{"id":824,"source_id":"74d3018f-4e23-4687-8bf4-7fb403f479f7","target_id":"136f172c732d0cc130532a4f0df475a4","source_type":"WIKI_ITEM","target_type":"CODE_SNIPPET","relationship_type":"CONTAINS","extra":"Wiki contains code snippet: backend/app/models/user.py#1-41","gmt_create":"2026-04-23T20:33:57.543958+08:00","gmt_modified":"2026-04-23T20:33:57.543958+08:00"},{"id":825,"source_id":"c59f8c276697a070dffc581fe94d809c","target_id":"136f172c732d0cc130532a4f0df475a4","source_type":"SOURCE_FILE","target_type":"CODE_SNIPPET","relationship_type":"CONTAINS","extra":"Source file contains code snippet: 1-41","gmt_create":"2026-04-23T20:33:57.544974+08:00","gmt_modified":"2026-04-23T20:33:57.544974+08:00"},{"id":826,"source_id":"74d3018f-4e23-4687-8bf4-7fb403f479f7","target_id":"916551131bd9ac8c9f9c8bb762af1fa4","source_type":"WIKI_ITEM","target_type":"CODE_SNIPPET","relationship_type":"CONTAINS","extra":"Wiki contains code snippet: backend/app/services/query.py#1-130","gmt_create":"2026-04-23T20:33:57.545482+08:00","gmt_modified":"2026-04-23T20:33:57.545482+08:00"},{"id":827,"source_id":"88d22de3b2a7419868e8ae19130d860c","target_id":"916551131bd9ac8c9f9c8bb762af1fa4","source_type":"SOURCE_FILE","target_type":"CODE_SNIPPET","relationship_type":"CONTAINS","extra":"Source file contains code snippet: 1-130","gmt_create":"2026-04-23T20:33:57.545785+08:00","gmt_modified":"2026-04-23T20:33:57.545785+08:00"},{"id":828,"source_id":"74d3018f-4e23-4687-8bf4-7fb403f479f7","target_id":"5d2836286eb7d4eb6039b004a9744d26","source_type":"WIKI_ITEM","target_type":"CODE_SNIPPET","relationship_type":"CONTAINS","extra":"Wiki contains code snippet: backend/app/services/citation.py#1-429","gmt_create":"2026-04-23T20:33:57.546196+08:00","gmt_modified":"2026-04-23T20:33:57.546196+08:00"},{"id":829,"source_id":"04e3926c080e795713bff683e7dc9d3e","target_id":"5d2836286eb7d4eb6039b004a9744d26","source_type":"SOURCE_FILE","target_type":"CODE_SNIPPET","relationship_type":"CONTAINS","extra":"Source file contains code snippet: 1-429","gmt_create":"2026-04-23T20:33:57.546517+08:00","gmt_modified":"2026-04-23T20:33:57.546517+08:00"},{"id":830,"source_id":"74d3018f-4e23-4687-8bf4-7fb403f479f7","target_id":"71f98c8993fb42b108e34a554247869b","source_type":"WIKI_ITEM","target_type":"CODE_SNIPPET","relationship_type":"CONTAINS","extra":"Wiki contains code snippet: backend/app/workers/scheduler.py#1-95","gmt_create":"2026-04-23T20:33:57.547004+08:00","gmt_modified":"2026-04-23T20:33:57.547005+08:00"},{"id":831,"source_id":"74d3018f-4e23-4687-8bf4-7fb403f479f7","target_id":"116584ea9162c1bc05911f39f9ef82b6","source_type":"WIKI_ITEM","target_type":"CODE_SNIPPET","relationship_type":"CONTAINS","extra":"Wiki contains code snippet: backend/app/workers/citation_engine.py#1-309","gmt_create":"2026-04-23T20:33:57.5475+08:00","gmt_modified":"2026-04-23T20:33:57.5475+08:00"},{"id":832,"source_id":"74d3018f-4e23-4687-8bf4-7fb403f479f7","target_id":"72a110dca58d8152758e2fdab4e94761","source_type":"WIKI_ITEM","target_type":"CODE_SNIPPET","relationship_type":"CONTAINS","extra":"Wiki contains code snippet: backend/app/workers/platforms/base.py#1-18","gmt_create":"2026-04-23T20:33:57.548046+08:00","gmt_modified":"2026-04-23T20:33:57.548046+08:00"},{"id":833,"source_id":"74d3018f-4e23-4687-8bf4-7fb403f479f7","target_id":"39a3b2d9301fa4eff7bef0fda3352790","source_type":"WIKI_ITEM","target_type":"CODE_SNIPPET","relationship_type":"CONTAINS","extra":"Wiki contains code snippet: backend/app/workers/platforms/kimi.py#1-206","gmt_create":"2026-04-23T20:33:57.548538+08:00","gmt_modified":"2026-04-23T20:33:57.548538+08:00"},{"id":834,"source_id":"8f973791233c698b3e64a4fb28a93d4b","target_id":"39a3b2d9301fa4eff7bef0fda3352790","source_type":"SOURCE_FILE","target_type":"CODE_SNIPPET","relationship_type":"CONTAINS","extra":"Source file contains code snippet: 1-206","gmt_create":"2026-04-23T20:33:57.548868+08:00","gmt_modified":"2026-04-23T20:33:57.548868+08:00"},{"id":835,"source_id":"74d3018f-4e23-4687-8bf4-7fb403f479f7","target_id":"fbcfae3b1238b3da5329ebafe4294861","source_type":"WIKI_ITEM","target_type":"CODE_SNIPPET","relationship_type":"CONTAINS","extra":"Wiki contains code snippet: backend/app/workers/platforms/wenxin.py#1-205","gmt_create":"2026-04-23T20:33:57.549268+08:00","gmt_modified":"2026-04-23T20:33:57.549268+08:00"},{"id":836,"source_id":"f642fc1c2f34e15572d9d98aa6c18813","target_id":"fbcfae3b1238b3da5329ebafe4294861","source_type":"SOURCE_FILE","target_type":"CODE_SNIPPET","relationship_type":"CONTAINS","extra":"Source file contains code snippet: 1-205","gmt_create":"2026-04-23T20:33:57.549553+08:00","gmt_modified":"2026-04-23T20:33:57.549553+08:00"},{"id":837,"source_id":"74d3018f-4e23-4687-8bf4-7fb403f479f7","target_id":"c2747ca16b879bca0f68955534c3c4fc","source_type":"WIKI_ITEM","target_type":"CODE_SNIPPET","relationship_type":"CONTAINS","extra":"Wiki contains code snippet: backend/app/main.py#1-48","gmt_create":"2026-04-23T20:33:57.550006+08:00","gmt_modified":"2026-04-23T20:33:57.550006+08:00"},{"id":838,"source_id":"74d3018f-4e23-4687-8bf4-7fb403f479f7","target_id":"c4273407c88f470df7daf6a8ad5ce969","source_type":"WIKI_ITEM","target_type":"CODE_SNIPPET","relationship_type":"CONTAINS","extra":"Wiki contains code snippet: backend/app/api/queries.py#15-109","gmt_create":"2026-04-23T20:33:57.550496+08:00","gmt_modified":"2026-04-23T20:33:57.550496+08:00"},{"id":839,"source_id":"6b3d903205941aa9391dd90016e1102c","target_id":"c4273407c88f470df7daf6a8ad5ce969","source_type":"SOURCE_FILE","target_type":"CODE_SNIPPET","relationship_type":"CONTAINS","extra":"Source file contains code snippet: 15-109","gmt_create":"2026-04-23T20:33:57.551777+08:00","gmt_modified":"2026-04-23T20:33:57.551777+08:00"},{"id":840,"source_id":"74d3018f-4e23-4687-8bf4-7fb403f479f7","target_id":"35774e0a09ac5459c868914d7182ca95","source_type":"WIKI_ITEM","target_type":"CODE_SNIPPET","relationship_type":"CONTAINS","extra":"Wiki contains code snippet: backend/app/api/citations.py#19-55","gmt_create":"2026-04-23T20:33:57.552775+08:00","gmt_modified":"2026-04-23T20:33:57.552775+08:00"},{"id":841,"source_id":"7538ffe4902ab6041adb28b19844962a","target_id":"35774e0a09ac5459c868914d7182ca95","source_type":"SOURCE_FILE","target_type":"CODE_SNIPPET","relationship_type":"CONTAINS","extra":"Source file contains code snippet: 19-55","gmt_create":"2026-04-23T20:33:57.553082+08:00","gmt_modified":"2026-04-23T20:33:57.553082+08:00"},{"id":842,"source_id":"74d3018f-4e23-4687-8bf4-7fb403f479f7","target_id":"69118807690ef351a9de910414d5e676","source_type":"WIKI_ITEM","target_type":"CODE_SNIPPET","relationship_type":"CONTAINS","extra":"Wiki contains code snippet: backend/app/schemas/query.py#11-94","gmt_create":"2026-04-23T20:33:57.553571+08:00","gmt_modified":"2026-04-23T20:33:57.553571+08:00"},{"id":843,"source_id":"74d3018f-4e23-4687-8bf4-7fb403f479f7","target_id":"f639b566c26dfd18b24e3dfd2e9853ac","source_type":"WIKI_ITEM","target_type":"CODE_SNIPPET","relationship_type":"CONTAINS","extra":"Wiki contains code snippet: backend/app/schemas/citation.py#7-52","gmt_create":"2026-04-23T20:33:57.554164+08:00","gmt_modified":"2026-04-23T20:33:57.554164+08:00"},{"id":844,"source_id":"1a3336b4af8a39a055e912724338580c","target_id":"f639b566c26dfd18b24e3dfd2e9853ac","source_type":"SOURCE_FILE","target_type":"CODE_SNIPPET","relationship_type":"CONTAINS","extra":"Source file contains code snippet: 7-52","gmt_create":"2026-04-23T20:33:57.554458+08:00","gmt_modified":"2026-04-23T20:33:57.554458+08:00"},{"id":845,"source_id":"74d3018f-4e23-4687-8bf4-7fb403f479f7","target_id":"4fb8856be3a581fe8303d11b2284ca29","source_type":"WIKI_ITEM","target_type":"CODE_SNIPPET","relationship_type":"CONTAINS","extra":"Wiki contains code snippet: backend/app/models/query.py#11-55","gmt_create":"2026-04-23T20:33:57.55511+08:00","gmt_modified":"2026-04-23T20:33:57.55511+08:00"},{"id":846,"source_id":"74d3018f-4e23-4687-8bf4-7fb403f479f7","target_id":"b84f46f058847733347974841f613688","source_type":"WIKI_ITEM","target_type":"CODE_SNIPPET","relationship_type":"CONTAINS","extra":"Wiki contains code snippet: backend/app/models/query_task.py#11-39","gmt_create":"2026-04-23T20:33:57.557064+08:00","gmt_modified":"2026-04-23T20:33:57.557064+08:00"},{"id":847,"source_id":"74d3018f-4e23-4687-8bf4-7fb403f479f7","target_id":"fd541971cebf8a7c167d717f5c5d1ff6","source_type":"WIKI_ITEM","target_type":"CODE_SNIPPET","relationship_type":"CONTAINS","extra":"Wiki contains code snippet: backend/app/models/citation_record.py#11-42","gmt_create":"2026-04-23T20:33:57.558255+08:00","gmt_modified":"2026-04-23T20:33:57.558255+08:00"},{"id":848,"source_id":"74d3018f-4e23-4687-8bf4-7fb403f479f7","target_id":"56e46969bdb790a5e8f333184b878d6d","source_type":"WIKI_ITEM","target_type":"CODE_SNIPPET","relationship_type":"CONTAINS","extra":"Wiki contains code snippet: backend/app/models/user.py#11-41","gmt_create":"2026-04-23T20:33:57.558894+08:00","gmt_modified":"2026-04-23T20:33:57.558894+08:00"},{"id":849,"source_id":"74d3018f-4e23-4687-8bf4-7fb403f479f7","target_id":"d7c319a04abbc6704da53107e07dd8e7","source_type":"WIKI_ITEM","target_type":"CODE_SNIPPET","relationship_type":"CONTAINS","extra":"Wiki contains code snippet: backend/app/services/query.py#12-130","gmt_create":"2026-04-23T20:33:57.560321+08:00","gmt_modified":"2026-04-23T20:33:57.560321+08:00"},{"id":850,"source_id":"74d3018f-4e23-4687-8bf4-7fb403f479f7","target_id":"b46654006178160f12897e2c5baac8fa","source_type":"WIKI_ITEM","target_type":"CODE_SNIPPET","relationship_type":"CONTAINS","extra":"Wiki contains code snippet: backend/app/services/citation.py#219-429","gmt_create":"2026-04-23T20:33:57.561417+08:00","gmt_modified":"2026-04-23T20:33:57.561417+08:00"},{"id":851,"source_id":"04e3926c080e795713bff683e7dc9d3e","target_id":"b46654006178160f12897e2c5baac8fa","source_type":"SOURCE_FILE","target_type":"CODE_SNIPPET","relationship_type":"CONTAINS","extra":"Source file contains code snippet: 219-429","gmt_create":"2026-04-23T20:33:57.561724+08:00","gmt_modified":"2026-04-23T20:33:57.561724+08:00"},{"id":852,"source_id":"74d3018f-4e23-4687-8bf4-7fb403f479f7","target_id":"e230904202fcf7a861c6f49b84f9f863","source_type":"WIKI_ITEM","target_type":"CODE_SNIPPET","relationship_type":"CONTAINS","extra":"Wiki contains code snippet: backend/app/workers/scheduler.py#25-95","gmt_create":"2026-04-23T20:33:57.562679+08:00","gmt_modified":"2026-04-23T20:33:57.562679+08:00"},{"id":853,"source_id":"74d3018f-4e23-4687-8bf4-7fb403f479f7","target_id":"309607c54b12a6340edc086ffb4737c9","source_type":"WIKI_ITEM","target_type":"CODE_SNIPPET","relationship_type":"CONTAINS","extra":"Wiki contains code snippet: backend/app/workers/citation_engine.py#148-309","gmt_create":"2026-04-23T20:33:57.563303+08:00","gmt_modified":"2026-04-23T20:33:57.563303+08:00"},{"id":854,"source_id":"74d3018f-4e23-4687-8bf4-7fb403f479f7","target_id":"ad67863041d9eea2b0fb542b5aa33aca","source_type":"WIKI_ITEM","target_type":"CODE_SNIPPET","relationship_type":"CONTAINS","extra":"Wiki contains code snippet: backend/app/workers/platforms/base.py#4-18","gmt_create":"2026-04-23T20:33:57.563842+08:00","gmt_modified":"2026-04-23T20:33:57.563842+08:00"},{"id":855,"source_id":"74d3018f-4e23-4687-8bf4-7fb403f479f7","target_id":"82265d393c20d0af96beec6b9c657c27","source_type":"WIKI_ITEM","target_type":"CODE_SNIPPET","relationship_type":"CONTAINS","extra":"Wiki contains code snippet: backend/app/api/queries.py#28-41","gmt_create":"2026-04-23T20:33:57.564486+08:00","gmt_modified":"2026-04-23T20:33:57.564486+08:00"},{"id":856,"source_id":"6b3d903205941aa9391dd90016e1102c","target_id":"82265d393c20d0af96beec6b9c657c27","source_type":"SOURCE_FILE","target_type":"CODE_SNIPPET","relationship_type":"CONTAINS","extra":"Source file contains code snippet: 28-41","gmt_create":"2026-04-23T20:33:57.564788+08:00","gmt_modified":"2026-04-23T20:33:57.564788+08:00"},{"id":857,"source_id":"74d3018f-4e23-4687-8bf4-7fb403f479f7","target_id":"c86edb7a95fbe4b431ac65a0e2b8636e","source_type":"WIKI_ITEM","target_type":"CODE_SNIPPET","relationship_type":"CONTAINS","extra":"Wiki contains code snippet: backend/app/api/queries.py#90-109","gmt_create":"2026-04-23T20:33:57.565285+08:00","gmt_modified":"2026-04-23T20:33:57.565285+08:00"},{"id":858,"source_id":"74d3018f-4e23-4687-8bf4-7fb403f479f7","target_id":"9b10dac7dbbb1327afc8a525bf4bd0c3","source_type":"WIKI_ITEM","target_type":"CODE_SNIPPET","relationship_type":"CONTAINS","extra":"Wiki contains code snippet: backend/app/services/query.py#45-81","gmt_create":"2026-04-23T20:33:57.565809+08:00","gmt_modified":"2026-04-23T20:33:57.565809+08:00"},{"id":859,"source_id":"74d3018f-4e23-4687-8bf4-7fb403f479f7","target_id":"93e5c95b1691bb81a36bf9a0ac889030","source_type":"WIKI_ITEM","target_type":"CODE_SNIPPET","relationship_type":"CONTAINS","extra":"Wiki contains code snippet: backend/app/services/citation.py#219-261","gmt_create":"2026-04-23T20:33:57.566399+08:00","gmt_modified":"2026-04-23T20:33:57.566399+08:00"},{"id":860,"source_id":"04e3926c080e795713bff683e7dc9d3e","target_id":"93e5c95b1691bb81a36bf9a0ac889030","source_type":"SOURCE_FILE","target_type":"CODE_SNIPPET","relationship_type":"CONTAINS","extra":"Source file contains code snippet: 219-261","gmt_create":"2026-04-23T20:33:57.578474+08:00","gmt_modified":"2026-04-23T20:33:57.578474+08:00"},{"id":861,"source_id":"74d3018f-4e23-4687-8bf4-7fb403f479f7","target_id":"448970b02d89d5e1576f70bdb0063363","source_type":"WIKI_ITEM","target_type":"CODE_SNIPPET","relationship_type":"CONTAINS","extra":"Wiki contains code snippet: backend/app/workers/scheduler.py#51-84","gmt_create":"2026-04-23T20:33:57.580464+08:00","gmt_modified":"2026-04-23T20:33:57.580464+08:00"},{"id":862,"source_id":"74d3018f-4e23-4687-8bf4-7fb403f479f7","target_id":"160b5326537d25444c40a459a01e79c6","source_type":"WIKI_ITEM","target_type":"CODE_SNIPPET","relationship_type":"CONTAINS","extra":"Wiki contains code snippet: backend/app/workers/citation_engine.py#159-234","gmt_create":"2026-04-23T20:33:57.581421+08:00","gmt_modified":"2026-04-23T20:33:57.581422+08:00"},{"id":863,"source_id":"74d3018f-4e23-4687-8bf4-7fb403f479f7","target_id":"a4918fcbd21492ad996d7f5496f03a4b","source_type":"WIKI_ITEM","target_type":"CODE_SNIPPET","relationship_type":"CONTAINS","extra":"Wiki contains code snippet: backend/app/workers/platforms/kimi.py#33-48","gmt_create":"2026-04-23T20:33:57.58279+08:00","gmt_modified":"2026-04-23T20:33:57.58279+08:00"},{"id":864,"source_id":"74d3018f-4e23-4687-8bf4-7fb403f479f7","target_id":"bc38d046b4b1410ae2165cee2272839e","source_type":"WIKI_ITEM","target_type":"CODE_SNIPPET","relationship_type":"CONTAINS","extra":"Wiki contains code snippet: backend/app/workers/platforms/wenxin.py#33-48","gmt_create":"2026-04-23T20:33:57.583676+08:00","gmt_modified":"2026-04-23T20:33:57.583676+08:00"},{"id":865,"source_id":"74d3018f-4e23-4687-8bf4-7fb403f479f7","target_id":"374200f0bf946f0399351756977d0495","source_type":"WIKI_ITEM","target_type":"CODE_SNIPPET","relationship_type":"CONTAINS","extra":"Wiki contains code snippet: backend/app/workers/citation_engine.py#176-234","gmt_create":"2026-04-23T20:33:57.588601+08:00","gmt_modified":"2026-04-23T20:33:57.588601+08:00"},{"id":866,"source_id":"74040de652d5e57f548bb5c4adc3e1a0","target_id":"374200f0bf946f0399351756977d0495","source_type":"SOURCE_FILE","target_type":"CODE_SNIPPET","relationship_type":"CONTAINS","extra":"Source file contains code snippet: 176-234","gmt_create":"2026-04-23T20:33:57.589609+08:00","gmt_modified":"2026-04-23T20:33:57.589609+08:00"},{"id":867,"source_id":"74d3018f-4e23-4687-8bf4-7fb403f479f7","target_id":"ac5982063da5f04315f3e82a0d653902","source_type":"WIKI_ITEM","target_type":"CODE_SNIPPET","relationship_type":"CONTAINS","extra":"Wiki contains code snippet: backend/app/models/query_task.py#24-32","gmt_create":"2026-04-23T20:33:57.590732+08:00","gmt_modified":"2026-04-23T20:33:57.590732+08:00"},{"id":868,"source_id":"74d3018f-4e23-4687-8bf4-7fb403f479f7","target_id":"601b981b00d93b941843f046a163d5a3","source_type":"WIKI_ITEM","target_type":"CODE_SNIPPET","relationship_type":"CONTAINS","extra":"Wiki contains code snippet: backend/app/schemas/query.py#18-33","gmt_create":"2026-04-23T20:33:57.592508+08:00","gmt_modified":"2026-04-23T20:33:57.592508+08:00"},{"id":869,"source_id":"74d3018f-4e23-4687-8bf4-7fb403f479f7","target_id":"9a8d9100a6bc34ebae9ee065def7e88a","source_type":"WIKI_ITEM","target_type":"CODE_SNIPPET","relationship_type":"CONTAINS","extra":"Wiki contains code snippet: backend/app/schemas/query.py#44-72","gmt_create":"2026-04-23T20:33:57.593647+08:00","gmt_modified":"2026-04-23T20:33:57.593647+08:00"},{"id":870,"source_id":"f301b79d833233ce39d350e82a71c938","target_id":"9a8d9100a6bc34ebae9ee065def7e88a","source_type":"SOURCE_FILE","target_type":"CODE_SNIPPET","relationship_type":"CONTAINS","extra":"Source file contains code snippet: 44-72","gmt_create":"2026-04-23T20:33:57.594757+08:00","gmt_modified":"2026-04-23T20:33:57.594757+08:00"},{"id":871,"source_id":"74d3018f-4e23-4687-8bf4-7fb403f479f7","target_id":"93c23bcc3456826af17e26a6d4c32116","source_type":"WIKI_ITEM","target_type":"CODE_SNIPPET","relationship_type":"CONTAINS","extra":"Wiki contains code snippet: backend/app/schemas/query.py#6-9","gmt_create":"2026-04-23T20:33:57.595474+08:00","gmt_modified":"2026-04-23T20:33:57.595474+08:00"},{"id":872,"source_id":"f301b79d833233ce39d350e82a71c938","target_id":"93c23bcc3456826af17e26a6d4c32116","source_type":"SOURCE_FILE","target_type":"CODE_SNIPPET","relationship_type":"CONTAINS","extra":"Source file contains code snippet: 6-9","gmt_create":"2026-04-23T20:33:57.596276+08:00","gmt_modified":"2026-04-23T20:33:57.596276+08:00"},{"id":873,"source_id":"74d3018f-4e23-4687-8bf4-7fb403f479f7","target_id":"c17eeb8726297096cd5542283f11494f","source_type":"WIKI_ITEM","target_type":"CODE_SNIPPET","relationship_type":"CONTAINS","extra":"Wiki contains code snippet: backend/app/api/queries.py#17-109","gmt_create":"2026-04-23T20:33:57.597516+08:00","gmt_modified":"2026-04-23T20:33:57.597516+08:00"},{"id":874,"source_id":"6b3d903205941aa9391dd90016e1102c","target_id":"c17eeb8726297096cd5542283f11494f","source_type":"SOURCE_FILE","target_type":"CODE_SNIPPET","relationship_type":"CONTAINS","extra":"Source file contains code snippet: 17-109","gmt_create":"2026-04-23T20:33:57.598386+08:00","gmt_modified":"2026-04-23T20:33:57.598386+08:00"},{"id":875,"source_id":"74d3018f-4e23-4687-8bf4-7fb403f479f7","target_id":"08fec4718be6991260c00ca532f9173a","source_type":"WIKI_ITEM","target_type":"CODE_SNIPPET","relationship_type":"CONTAINS","extra":"Wiki contains code snippet: backend/app/api/citations.py#22-55","gmt_create":"2026-04-23T20:33:57.599188+08:00","gmt_modified":"2026-04-23T20:33:57.599188+08:00"},{"id":876,"source_id":"7538ffe4902ab6041adb28b19844962a","target_id":"08fec4718be6991260c00ca532f9173a","source_type":"SOURCE_FILE","target_type":"CODE_SNIPPET","relationship_type":"CONTAINS","extra":"Source file contains code snippet: 22-55","gmt_create":"2026-04-23T20:33:57.600043+08:00","gmt_modified":"2026-04-23T20:33:57.600043+08:00"},{"id":877,"source_id":"74d3018f-4e23-4687-8bf4-7fb403f479f7","target_id":"08007199eea846dd14f15f7dc70419e2","source_type":"WIKI_ITEM","target_type":"CODE_SNIPPET","relationship_type":"CONTAINS","extra":"Wiki contains code snippet: backend/app/schemas/citation.py#48-52","gmt_create":"2026-04-23T20:33:57.600852+08:00","gmt_modified":"2026-04-23T20:33:57.600852+08:00"},{"id":878,"source_id":"1a3336b4af8a39a055e912724338580c","target_id":"08007199eea846dd14f15f7dc70419e2","source_type":"SOURCE_FILE","target_type":"CODE_SNIPPET","relationship_type":"CONTAINS","extra":"Source file contains code snippet: 48-52","gmt_create":"2026-04-23T20:33:57.601489+08:00","gmt_modified":"2026-04-23T20:33:57.601489+08:00"},{"id":879,"source_id":"74d3018f-4e23-4687-8bf4-7fb403f479f7","target_id":"4caff756fd4da029bd64cd16e7ef5960","source_type":"WIKI_ITEM","target_type":"CODE_SNIPPET","relationship_type":"CONTAINS","extra":"Wiki contains code snippet: backend/app/api/queries.py#32-39","gmt_create":"2026-04-23T20:33:57.602322+08:00","gmt_modified":"2026-04-23T20:33:57.602323+08:00"},{"id":880,"source_id":"6b3d903205941aa9391dd90016e1102c","target_id":"4caff756fd4da029bd64cd16e7ef5960","source_type":"SOURCE_FILE","target_type":"CODE_SNIPPET","relationship_type":"CONTAINS","extra":"Source file contains code snippet: 32-39","gmt_create":"2026-04-23T20:33:57.602918+08:00","gmt_modified":"2026-04-23T20:33:57.602918+08:00"},{"id":881,"source_id":"74d3018f-4e23-4687-8bf4-7fb403f479f7","target_id":"b0220895f66f1273966ad5b2c3266952","source_type":"WIKI_ITEM","target_type":"CODE_SNIPPET","relationship_type":"CONTAINS","extra":"Wiki contains code snippet: backend/app/api/queries.py#49-53","gmt_create":"2026-04-23T20:33:57.603881+08:00","gmt_modified":"2026-04-23T20:33:57.603881+08:00"},{"id":882,"source_id":"6b3d903205941aa9391dd90016e1102c","target_id":"b0220895f66f1273966ad5b2c3266952","source_type":"SOURCE_FILE","target_type":"CODE_SNIPPET","relationship_type":"CONTAINS","extra":"Source file contains code snippet: 49-53","gmt_create":"2026-04-23T20:33:57.604555+08:00","gmt_modified":"2026-04-23T20:33:57.604555+08:00"},{"id":883,"source_id":"74d3018f-4e23-4687-8bf4-7fb403f479f7","target_id":"44f88f9664fdf6e84ffb7e0675a86a28","source_type":"WIKI_ITEM","target_type":"CODE_SNIPPET","relationship_type":"CONTAINS","extra":"Wiki contains code snippet: backend/app/api/queries.py#64-69","gmt_create":"2026-04-23T20:33:57.605262+08:00","gmt_modified":"2026-04-23T20:33:57.605262+08:00"},{"id":884,"source_id":"6b3d903205941aa9391dd90016e1102c","target_id":"44f88f9664fdf6e84ffb7e0675a86a28","source_type":"SOURCE_FILE","target_type":"CODE_SNIPPET","relationship_type":"CONTAINS","extra":"Source file contains code snippet: 64-69","gmt_create":"2026-04-23T20:33:57.606324+08:00","gmt_modified":"2026-04-23T20:33:57.606324+08:00"},{"id":885,"source_id":"74d3018f-4e23-4687-8bf4-7fb403f479f7","target_id":"91f280f51389bd1cf711dcf33a4da681","source_type":"WIKI_ITEM","target_type":"CODE_SNIPPET","relationship_type":"CONTAINS","extra":"Wiki contains code snippet: backend/app/api/queries.py#79-84","gmt_create":"2026-04-23T20:33:57.607055+08:00","gmt_modified":"2026-04-23T20:33:57.607055+08:00"},{"id":886,"source_id":"6b3d903205941aa9391dd90016e1102c","target_id":"91f280f51389bd1cf711dcf33a4da681","source_type":"SOURCE_FILE","target_type":"CODE_SNIPPET","relationship_type":"CONTAINS","extra":"Source file contains code snippet: 79-84","gmt_create":"2026-04-23T20:33:57.608388+08:00","gmt_modified":"2026-04-23T20:33:57.608388+08:00"},{"id":887,"source_id":"74d3018f-4e23-4687-8bf4-7fb403f479f7","target_id":"ab50466a57c77659d7b469d3a8a04ddb","source_type":"WIKI_ITEM","target_type":"CODE_SNIPPET","relationship_type":"CONTAINS","extra":"Wiki contains code snippet: backend/app/api/queries.py#96-103","gmt_create":"2026-04-23T20:33:57.609206+08:00","gmt_modified":"2026-04-23T20:33:57.609206+08:00"},{"id":888,"source_id":"6b3d903205941aa9391dd90016e1102c","target_id":"ab50466a57c77659d7b469d3a8a04ddb","source_type":"SOURCE_FILE","target_type":"CODE_SNIPPET","relationship_type":"CONTAINS","extra":"Source file contains code snippet: 96-103","gmt_create":"2026-04-23T20:33:57.609975+08:00","gmt_modified":"2026-04-23T20:33:57.609975+08:00"},{"id":889,"source_id":"74d3018f-4e23-4687-8bf4-7fb403f479f7","target_id":"572c2dece1fbc13aa2bb7d6b61b0fd5c","source_type":"WIKI_ITEM","target_type":"CODE_SNIPPET","relationship_type":"CONTAINS","extra":"Wiki contains code snippet: backend/app/api/citations.py#65-71","gmt_create":"2026-04-23T20:33:57.61104+08:00","gmt_modified":"2026-04-23T20:33:57.611041+08:00"},{"id":890,"source_id":"7538ffe4902ab6041adb28b19844962a","target_id":"572c2dece1fbc13aa2bb7d6b61b0fd5c","source_type":"SOURCE_FILE","target_type":"CODE_SNIPPET","relationship_type":"CONTAINS","extra":"Source file contains code snippet: 65-71","gmt_create":"2026-04-23T20:33:57.611833+08:00","gmt_modified":"2026-04-23T20:33:57.611833+08:00"},{"id":891,"source_id":"74d3018f-4e23-4687-8bf4-7fb403f479f7","target_id":"82386bc7ca57d9ccc94b656e52bc89f6","source_type":"WIKI_ITEM","target_type":"CODE_SNIPPET","relationship_type":"CONTAINS","extra":"Wiki contains code snippet: backend/app/api/queries.py#1-14","gmt_create":"2026-04-23T20:33:57.612865+08:00","gmt_modified":"2026-04-23T20:33:57.612865+08:00"},{"id":892,"source_id":"6b3d903205941aa9391dd90016e1102c","target_id":"82386bc7ca57d9ccc94b656e52bc89f6","source_type":"SOURCE_FILE","target_type":"CODE_SNIPPET","relationship_type":"CONTAINS","extra":"Source file contains code snippet: 1-14","gmt_create":"2026-04-23T20:33:57.613537+08:00","gmt_modified":"2026-04-23T20:33:57.613537+08:00"},{"id":893,"source_id":"74d3018f-4e23-4687-8bf4-7fb403f479f7","target_id":"7ab79ab21d7d6e4dbcb224572516f6f6","source_type":"WIKI_ITEM","target_type":"CODE_SNIPPET","relationship_type":"CONTAINS","extra":"Wiki contains code snippet: backend/app/api/citations.py#1-19","gmt_create":"2026-04-23T20:33:57.613967+08:00","gmt_modified":"2026-04-23T20:33:57.613968+08:00"},{"id":894,"source_id":"7538ffe4902ab6041adb28b19844962a","target_id":"7ab79ab21d7d6e4dbcb224572516f6f6","source_type":"SOURCE_FILE","target_type":"CODE_SNIPPET","relationship_type":"CONTAINS","extra":"Source file contains code snippet: 1-19","gmt_create":"2026-04-23T20:33:57.61426+08:00","gmt_modified":"2026-04-23T20:33:57.61426+08:00"},{"id":895,"source_id":"74d3018f-4e23-4687-8bf4-7fb403f479f7","target_id":"8433204d7a82a1f480e57df9ceee5581","source_type":"WIKI_ITEM","target_type":"CODE_SNIPPET","relationship_type":"CONTAINS","extra":"Wiki contains code snippet: backend/app/services/query.py#1-10","gmt_create":"2026-04-23T20:33:57.614658+08:00","gmt_modified":"2026-04-23T20:33:57.614658+08:00"},{"id":896,"source_id":"88d22de3b2a7419868e8ae19130d860c","target_id":"8433204d7a82a1f480e57df9ceee5581","source_type":"SOURCE_FILE","target_type":"CODE_SNIPPET","relationship_type":"CONTAINS","extra":"Source file contains code snippet: 1-10","gmt_create":"2026-04-23T20:33:57.614988+08:00","gmt_modified":"2026-04-23T20:33:57.614988+08:00"},{"id":897,"source_id":"74d3018f-4e23-4687-8bf4-7fb403f479f7","target_id":"3957ee6f15a01b7b541490438ef18684","source_type":"WIKI_ITEM","target_type":"CODE_SNIPPET","relationship_type":"CONTAINS","extra":"Wiki contains code snippet: backend/app/services/citation.py#1-17","gmt_create":"2026-04-23T20:33:57.615388+08:00","gmt_modified":"2026-04-23T20:33:57.615388+08:00"},{"id":898,"source_id":"04e3926c080e795713bff683e7dc9d3e","target_id":"3957ee6f15a01b7b541490438ef18684","source_type":"SOURCE_FILE","target_type":"CODE_SNIPPET","relationship_type":"CONTAINS","extra":"Source file contains code snippet: 1-17","gmt_create":"2026-04-23T20:33:57.615908+08:00","gmt_modified":"2026-04-23T20:33:57.615908+08:00"},{"id":899,"source_id":"74d3018f-4e23-4687-8bf4-7fb403f479f7","target_id":"3729543092bccad8926c5ea852db1e69","source_type":"WIKI_ITEM","target_type":"CODE_SNIPPET","relationship_type":"CONTAINS","extra":"Wiki contains code snippet: backend/app/workers/citation_engine.py#148-157","gmt_create":"2026-04-23T20:33:57.61673+08:00","gmt_modified":"2026-04-23T20:33:57.61673+08:00"},{"id":900,"source_id":"74d3018f-4e23-4687-8bf4-7fb403f479f7","target_id":"fcae8d1d281ad7186999cc4ca8e43db7","source_type":"WIKI_ITEM","target_type":"CODE_SNIPPET","relationship_type":"CONTAINS","extra":"Wiki contains code snippet: backend/app/workers/scheduler.py#25-39","gmt_create":"2026-04-23T20:33:57.617716+08:00","gmt_modified":"2026-04-23T20:33:57.617716+08:00"},{"id":901,"source_id":"5cbb1e3f112aeba62a14b0b8999fc0f5","target_id":"fcae8d1d281ad7186999cc4ca8e43db7","source_type":"SOURCE_FILE","target_type":"CODE_SNIPPET","relationship_type":"CONTAINS","extra":"Source file contains code snippet: 25-39","gmt_create":"2026-04-23T20:33:57.618148+08:00","gmt_modified":"2026-04-23T20:33:57.618148+08:00"},{"id":902,"source_id":"74d3018f-4e23-4687-8bf4-7fb403f479f7","target_id":"ee12a84ac6334b13e20132181454488b","source_type":"WIKI_ITEM","target_type":"CODE_SNIPPET","relationship_type":"CONTAINS","extra":"Wiki contains code snippet: backend/app/workers/scheduler.py#13-19","gmt_create":"2026-04-23T20:33:57.6192+08:00","gmt_modified":"2026-04-23T20:33:57.6192+08:00"},{"id":903,"source_id":"5cbb1e3f112aeba62a14b0b8999fc0f5","target_id":"ee12a84ac6334b13e20132181454488b","source_type":"SOURCE_FILE","target_type":"CODE_SNIPPET","relationship_type":"CONTAINS","extra":"Source file contains code snippet: 13-19","gmt_create":"2026-04-23T20:33:57.619587+08:00","gmt_modified":"2026-04-23T20:33:57.619587+08:00"},{"id":904,"source_id":"74d3018f-4e23-4687-8bf4-7fb403f479f7","target_id":"897e047b94772e5a0ff57cf773a7f965","source_type":"WIKI_ITEM","target_type":"CODE_SNIPPET","relationship_type":"CONTAINS","extra":"Wiki contains code snippet: backend/app/workers/platforms/kimi.py#17-32","gmt_create":"2026-04-23T20:33:57.620024+08:00","gmt_modified":"2026-04-23T20:33:57.620024+08:00"},{"id":905,"source_id":"8f973791233c698b3e64a4fb28a93d4b","target_id":"897e047b94772e5a0ff57cf773a7f965","source_type":"SOURCE_FILE","target_type":"CODE_SNIPPET","relationship_type":"CONTAINS","extra":"Source file contains code snippet: 17-32","gmt_create":"2026-04-23T20:33:57.620315+08:00","gmt_modified":"2026-04-23T20:33:57.620315+08:00"},{"id":906,"source_id":"74d3018f-4e23-4687-8bf4-7fb403f479f7","target_id":"53e8ec81b4d2dbb13c831048e5897036","source_type":"WIKI_ITEM","target_type":"CODE_SNIPPET","relationship_type":"CONTAINS","extra":"Wiki contains code snippet: backend/app/workers/platforms/wenxin.py#17-32","gmt_create":"2026-04-23T20:33:57.620909+08:00","gmt_modified":"2026-04-23T20:33:57.620909+08:00"},{"id":907,"source_id":"f642fc1c2f34e15572d9d98aa6c18813","target_id":"53e8ec81b4d2dbb13c831048e5897036","source_type":"SOURCE_FILE","target_type":"CODE_SNIPPET","relationship_type":"CONTAINS","extra":"Source file contains code snippet: 17-32","gmt_create":"2026-04-23T20:33:57.621267+08:00","gmt_modified":"2026-04-23T20:33:57.621267+08:00"},{"id":908,"source_id":"74d3018f-4e23-4687-8bf4-7fb403f479f7","target_id":"096856da621e23e78422a15e2bfce1f1","source_type":"WIKI_ITEM","target_type":"CODE_SNIPPET","relationship_type":"CONTAINS","extra":"Wiki contains code snippet: backend/app/main.py#13-22","gmt_create":"2026-04-23T20:33:57.621687+08:00","gmt_modified":"2026-04-23T20:33:57.621687+08:00"},{"id":909,"source_id":"74d3018f-4e23-4687-8bf4-7fb403f479f7","target_id":"ef82ce4377c549013c200e19701a6805","source_type":"WIKI_ITEM","target_type":"CODE_SNIPPET","relationship_type":"CONTAINS","extra":"Wiki contains code snippet: backend/app/workers/platforms/kimi.py#21-32","gmt_create":"2026-04-23T20:33:57.62216+08:00","gmt_modified":"2026-04-23T20:33:57.62216+08:00"},{"id":910,"source_id":"74d3018f-4e23-4687-8bf4-7fb403f479f7","target_id":"c7986eb1be0ffdd9ec4e243be4270119","source_type":"WIKI_ITEM","target_type":"CODE_SNIPPET","relationship_type":"CONTAINS","extra":"Wiki contains code snippet: backend/app/workers/platforms/wenxin.py#21-32","gmt_create":"2026-04-23T20:33:57.623241+08:00","gmt_modified":"2026-04-23T20:33:57.623241+08:00"},{"id":911,"source_id":"74d3018f-4e23-4687-8bf4-7fb403f479f7","target_id":"eecf9581dbaa0a515cf11514175e7ef9","source_type":"WIKI_ITEM","target_type":"CODE_SNIPPET","relationship_type":"CONTAINS","extra":"Wiki contains code snippet: backend/app/workers/platforms/kimi.py#11-206","gmt_create":"2026-04-23T20:33:57.627555+08:00","gmt_modified":"2026-04-23T20:33:57.627555+08:00"},{"id":912,"source_id":"74d3018f-4e23-4687-8bf4-7fb403f479f7","target_id":"5563c29185326a59be61ee0a6eec4463","source_type":"WIKI_ITEM","target_type":"CODE_SNIPPET","relationship_type":"CONTAINS","extra":"Wiki contains code snippet: backend/app/workers/platforms/wenxin.py#11-205","gmt_create":"2026-04-23T20:33:57.62809+08:00","gmt_modified":"2026-04-23T20:33:57.62809+08:00"},{"id":913,"source_id":"74d3018f-4e23-4687-8bf4-7fb403f479f7","target_id":"fd3145047b9c813cc8e64b9322e531f9","source_type":"WIKI_ITEM","target_type":"CODE_SNIPPET","relationship_type":"CONTAINS","extra":"Wiki contains code snippet: backend/app/services/citation.py#219-327","gmt_create":"2026-04-23T20:33:57.62931+08:00","gmt_modified":"2026-04-23T20:33:57.62931+08:00"},{"id":914,"source_id":"04e3926c080e795713bff683e7dc9d3e","target_id":"fd3145047b9c813cc8e64b9322e531f9","source_type":"SOURCE_FILE","target_type":"CODE_SNIPPET","relationship_type":"CONTAINS","extra":"Source file contains code snippet: 219-327","gmt_create":"2026-04-23T20:33:57.629745+08:00","gmt_modified":"2026-04-23T20:33:57.629745+08:00"},{"id":915,"source_id":"74d3018f-4e23-4687-8bf4-7fb403f479f7","target_id":"b09a0f415030d91b25e6cabd8a0a93fc","source_type":"WIKI_ITEM","target_type":"CODE_SNIPPET","relationship_type":"CONTAINS","extra":"Wiki contains code snippet: backend/app/models/query_task.py#176-289","gmt_create":"2026-04-23T20:33:57.630458+08:00","gmt_modified":"2026-04-23T20:33:57.630458+08:00"},{"id":916,"source_id":"069738f21ac2da7349d22683e8c36929","target_id":"b09a0f415030d91b25e6cabd8a0a93fc","source_type":"SOURCE_FILE","target_type":"CODE_SNIPPET","relationship_type":"CONTAINS","extra":"Source file contains code snippet: 176-289","gmt_create":"2026-04-23T20:33:57.630748+08:00","gmt_modified":"2026-04-23T20:33:57.630748+08:00"},{"id":917,"source_id":"74d3018f-4e23-4687-8bf4-7fb403f479f7","target_id":"e2168959b26c386940370b5f1bf48d7d","source_type":"WIKI_ITEM","target_type":"CODE_SNIPPET","relationship_type":"CONTAINS","extra":"Wiki contains code snippet: backend/app/models/citation_record.py#194-204","gmt_create":"2026-04-23T20:33:57.631184+08:00","gmt_modified":"2026-04-23T20:33:57.631184+08:00"},{"id":918,"source_id":"b4a81ef789630d0af6a8d50859d01bf3","target_id":"e2168959b26c386940370b5f1bf48d7d","source_type":"SOURCE_FILE","target_type":"CODE_SNIPPET","relationship_type":"CONTAINS","extra":"Source file contains code snippet: 194-204","gmt_create":"2026-04-23T20:33:57.63147+08:00","gmt_modified":"2026-04-23T20:33:57.63147+08:00"},{"id":919,"source_id":"2126339b-b0f5-4152-924b-cbe028cd0c39","target_id":"8f973791233c698b3e64a4fb28a93d4b","source_type":"WIKI_ITEM","target_type":"SOURCE_FILE","relationship_type":"REFERENCED_BY","extra":"Wiki references source file: backend/app/workers/platforms/kimi.py","gmt_create":"2026-04-23T20:35:18.634061+08:00","gmt_modified":"2026-04-23T20:35:18.634062+08:00"},{"id":920,"source_id":"2126339b-b0f5-4152-924b-cbe028cd0c39","target_id":"a16cf42e9559523c4f96ca4c79f9488d","source_type":"WIKI_ITEM","target_type":"SOURCE_FILE","relationship_type":"REFERENCED_BY","extra":"Wiki references source file: backend/app/workers/platforms/base.py","gmt_create":"2026-04-23T20:35:18.634886+08:00","gmt_modified":"2026-04-23T20:35:18.634886+08:00"},{"id":921,"source_id":"2126339b-b0f5-4152-924b-cbe028cd0c39","target_id":"6a63f048c16c60c5d2d57012c810ee0e","source_type":"WIKI_ITEM","target_type":"SOURCE_FILE","relationship_type":"REFERENCED_BY","extra":"Wiki references source file: backend/app/workers/platforms/search_engine.py","gmt_create":"2026-04-23T20:35:18.635377+08:00","gmt_modified":"2026-04-23T20:35:18.635377+08:00"},{"id":922,"source_id":"2126339b-b0f5-4152-924b-cbe028cd0c39","target_id":"4a56ef5fca60bc63480b457cab3832f0","source_type":"WIKI_ITEM","target_type":"SOURCE_FILE","relationship_type":"REFERENCED_BY","extra":"Wiki references source file: backend/app/workers/platforms/__init__.py","gmt_create":"2026-04-23T20:35:18.63595+08:00","gmt_modified":"2026-04-23T20:35:18.63595+08:00"},{"id":923,"source_id":"2126339b-b0f5-4152-924b-cbe028cd0c39","target_id":"74040de652d5e57f548bb5c4adc3e1a0","source_type":"WIKI_ITEM","target_type":"SOURCE_FILE","relationship_type":"REFERENCED_BY","extra":"Wiki references source file: backend/app/workers/citation_engine.py","gmt_create":"2026-04-23T20:35:18.636363+08:00","gmt_modified":"2026-04-23T20:35:18.636363+08:00"},{"id":924,"source_id":"2126339b-b0f5-4152-924b-cbe028cd0c39","target_id":"5cbb1e3f112aeba62a14b0b8999fc0f5","source_type":"WIKI_ITEM","target_type":"SOURCE_FILE","relationship_type":"REFERENCED_BY","extra":"Wiki references source file: backend/app/workers/scheduler.py","gmt_create":"2026-04-23T20:35:18.636753+08:00","gmt_modified":"2026-04-23T20:35:18.636753+08:00"},{"id":925,"source_id":"2126339b-b0f5-4152-924b-cbe028cd0c39","target_id":"36dd0ad3ee6bc75a480ad8a62268e80e","source_type":"WIKI_ITEM","target_type":"SOURCE_FILE","relationship_type":"REFERENCED_BY","extra":"Wiki references source file: backend/app/workers/models/query.py","gmt_create":"2026-04-23T20:35:18.6372+08:00","gmt_modified":"2026-04-23T20:35:18.6372+08:00"},{"id":926,"source_id":"2126339b-b0f5-4152-924b-cbe028cd0c39","target_id":"b4a81ef789630d0af6a8d50859d01bf3","source_type":"WIKI_ITEM","target_type":"SOURCE_FILE","relationship_type":"REFERENCED_BY","extra":"Wiki references source file: backend/app/models/citation_record.py","gmt_create":"2026-04-23T20:35:18.637558+08:00","gmt_modified":"2026-04-23T20:35:18.637558+08:00"},{"id":927,"source_id":"2126339b-b0f5-4152-924b-cbe028cd0c39","target_id":"069738f21ac2da7349d22683e8c36929","source_type":"WIKI_ITEM","target_type":"SOURCE_FILE","relationship_type":"REFERENCED_BY","extra":"Wiki references source file: backend/app/models/query_task.py","gmt_create":"2026-04-23T20:35:18.637924+08:00","gmt_modified":"2026-04-23T20:35:18.637924+08:00"},{"id":928,"source_id":"2126339b-b0f5-4152-924b-cbe028cd0c39","target_id":"88d22de3b2a7419868e8ae19130d860c","source_type":"WIKI_ITEM","target_type":"SOURCE_FILE","relationship_type":"REFERENCED_BY","extra":"Wiki references source file: backend/app/services/query.py","gmt_create":"2026-04-23T20:35:18.638407+08:00","gmt_modified":"2026-04-23T20:35:18.638407+08:00"},{"id":929,"source_id":"2126339b-b0f5-4152-924b-cbe028cd0c39","target_id":"04e3926c080e795713bff683e7dc9d3e","source_type":"WIKI_ITEM","target_type":"SOURCE_FILE","relationship_type":"REFERENCED_BY","extra":"Wiki references source file: backend/app/services/citation.py","gmt_create":"2026-04-23T20:35:18.638942+08:00","gmt_modified":"2026-04-23T20:35:18.638942+08:00"},{"id":930,"source_id":"2126339b-b0f5-4152-924b-cbe028cd0c39","target_id":"6b3d903205941aa9391dd90016e1102c","source_type":"WIKI_ITEM","target_type":"SOURCE_FILE","relationship_type":"REFERENCED_BY","extra":"Wiki references source file: backend/app/api/queries.py","gmt_create":"2026-04-23T20:35:18.641162+08:00","gmt_modified":"2026-04-23T20:35:18.641162+08:00"},{"id":931,"source_id":"2126339b-b0f5-4152-924b-cbe028cd0c39","target_id":"7538ffe4902ab6041adb28b19844962a","source_type":"WIKI_ITEM","target_type":"SOURCE_FILE","relationship_type":"REFERENCED_BY","extra":"Wiki references source file: backend/app/api/citations.py","gmt_create":"2026-04-23T20:35:18.642251+08:00","gmt_modified":"2026-04-23T20:35:18.642251+08:00"},{"id":932,"source_id":"2126339b-b0f5-4152-924b-cbe028cd0c39","target_id":"9228ff67d4c757a85d9421b71f4b29f5","source_type":"WIKI_ITEM","target_type":"SOURCE_FILE","relationship_type":"REFERENCED_BY","extra":"Wiki references source file: backend/app/main.py","gmt_create":"2026-04-23T20:35:18.642925+08:00","gmt_modified":"2026-04-23T20:35:18.642925+08:00"},{"id":933,"source_id":"2126339b-b0f5-4152-924b-cbe028cd0c39","target_id":"ef72f0c3cedb9fd9a87352fe493053dc","source_type":"WIKI_ITEM","target_type":"SOURCE_FILE","relationship_type":"REFERENCED_BY","extra":"Wiki references source file: frontend/lib/platforms.ts","gmt_create":"2026-04-23T20:35:18.643414+08:00","gmt_modified":"2026-04-23T20:35:18.643415+08:00"},{"id":934,"source_id":"2126339b-b0f5-4152-924b-cbe028cd0c39","target_id":"096856da621e23e78422a15e2bfce1f1","source_type":"WIKI_ITEM","target_type":"CODE_SNIPPET","relationship_type":"CONTAINS","extra":"Wiki contains code snippet: backend/app/main.py#13-22","gmt_create":"2026-04-23T20:35:18.643912+08:00","gmt_modified":"2026-04-23T20:35:18.643912+08:00"},{"id":935,"source_id":"2126339b-b0f5-4152-924b-cbe028cd0c39","target_id":"129573d2bbcde48697ed0e75dea12396","source_type":"WIKI_ITEM","target_type":"CODE_SNIPPET","relationship_type":"CONTAINS","extra":"Wiki contains code snippet: backend/app/workers/scheduler.py#25-40","gmt_create":"2026-04-23T20:35:18.645078+08:00","gmt_modified":"2026-04-23T20:35:18.645078+08:00"},{"id":936,"source_id":"5cbb1e3f112aeba62a14b0b8999fc0f5","target_id":"129573d2bbcde48697ed0e75dea12396","source_type":"SOURCE_FILE","target_type":"CODE_SNIPPET","relationship_type":"CONTAINS","extra":"Source file contains code snippet: 25-40","gmt_create":"2026-04-23T20:35:18.646964+08:00","gmt_modified":"2026-04-23T20:35:18.646965+08:00"},{"id":937,"source_id":"2126339b-b0f5-4152-924b-cbe028cd0c39","target_id":"cf18c97a9be6c78aa43cc229ed3dad20","source_type":"WIKI_ITEM","target_type":"CODE_SNIPPET","relationship_type":"CONTAINS","extra":"Wiki contains code snippet: backend/app/workers/citation_engine.py#164-173","gmt_create":"2026-04-23T20:35:18.647598+08:00","gmt_modified":"2026-04-23T20:35:18.647598+08:00"},{"id":938,"source_id":"74040de652d5e57f548bb5c4adc3e1a0","target_id":"cf18c97a9be6c78aa43cc229ed3dad20","source_type":"SOURCE_FILE","target_type":"CODE_SNIPPET","relationship_type":"CONTAINS","extra":"Source file contains code snippet: 164-173","gmt_create":"2026-04-23T20:35:18.647972+08:00","gmt_modified":"2026-04-23T20:35:18.647972+08:00"},{"id":939,"source_id":"2126339b-b0f5-4152-924b-cbe028cd0c39","target_id":"3c7ca5d582dca31c2530b1ce9c058e95","source_type":"WIKI_ITEM","target_type":"CODE_SNIPPET","relationship_type":"CONTAINS","extra":"Wiki contains code snippet: backend/app/workers/platforms/kimi.py#10-37","gmt_create":"2026-04-23T20:35:18.648459+08:00","gmt_modified":"2026-04-23T20:35:18.64846+08:00"},{"id":940,"source_id":"8f973791233c698b3e64a4fb28a93d4b","target_id":"3c7ca5d582dca31c2530b1ce9c058e95","source_type":"SOURCE_FILE","target_type":"CODE_SNIPPET","relationship_type":"CONTAINS","extra":"Source file contains code snippet: 10-37","gmt_create":"2026-04-23T20:35:18.648785+08:00","gmt_modified":"2026-04-23T20:35:18.648785+08:00"},{"id":941,"source_id":"2126339b-b0f5-4152-924b-cbe028cd0c39","target_id":"9f82f6d82bf914a608d6afa3d9854abf","source_type":"WIKI_ITEM","target_type":"CODE_SNIPPET","relationship_type":"CONTAINS","extra":"Wiki contains code snippet: backend/app/workers/platforms/search_engine.py#1-174","gmt_create":"2026-04-23T20:35:18.649264+08:00","gmt_modified":"2026-04-23T20:35:18.649264+08:00"},{"id":942,"source_id":"2126339b-b0f5-4152-924b-cbe028cd0c39","target_id":"b74caccb06844efcdb14d8324cff65c2","source_type":"WIKI_ITEM","target_type":"SOURCE_FILE","relationship_type":"REFERENCED_BY","extra":"Wiki references source file: backend/app/models/query.py","gmt_create":"2026-04-23T20:35:18.650358+08:00","gmt_modified":"2026-04-23T20:35:18.650358+08:00"},{"id":943,"source_id":"2126339b-b0f5-4152-924b-cbe028cd0c39","target_id":"4fb8856be3a581fe8303d11b2284ca29","source_type":"WIKI_ITEM","target_type":"CODE_SNIPPET","relationship_type":"CONTAINS","extra":"Wiki contains code snippet: backend/app/models/query.py#11-55","gmt_create":"2026-04-23T20:35:18.650954+08:00","gmt_modified":"2026-04-23T20:35:18.650954+08:00"},{"id":944,"source_id":"2126339b-b0f5-4152-924b-cbe028cd0c39","target_id":"fd541971cebf8a7c167d717f5c5d1ff6","source_type":"WIKI_ITEM","target_type":"CODE_SNIPPET","relationship_type":"CONTAINS","extra":"Wiki contains code snippet: backend/app/models/citation_record.py#11-42","gmt_create":"2026-04-23T20:35:18.652232+08:00","gmt_modified":"2026-04-23T20:35:18.652232+08:00"},{"id":945,"source_id":"2126339b-b0f5-4152-924b-cbe028cd0c39","target_id":"b84f46f058847733347974841f613688","source_type":"WIKI_ITEM","target_type":"CODE_SNIPPET","relationship_type":"CONTAINS","extra":"Wiki contains code snippet: backend/app/models/query_task.py#11-39","gmt_create":"2026-04-23T20:35:18.653511+08:00","gmt_modified":"2026-04-23T20:35:18.653511+08:00"},{"id":946,"source_id":"2126339b-b0f5-4152-924b-cbe028cd0c39","target_id":"27047f868643e5457d4f242b4298a9f6","source_type":"WIKI_ITEM","target_type":"CODE_SNIPPET","relationship_type":"CONTAINS","extra":"Wiki contains code snippet: frontend/lib/platforms.ts#1-23","gmt_create":"2026-04-23T20:35:18.654994+08:00","gmt_modified":"2026-04-23T20:35:18.654994+08:00"},{"id":947,"source_id":"ef72f0c3cedb9fd9a87352fe493053dc","target_id":"27047f868643e5457d4f242b4298a9f6","source_type":"SOURCE_FILE","target_type":"CODE_SNIPPET","relationship_type":"CONTAINS","extra":"Source file contains code snippet: 1-23","gmt_create":"2026-04-23T20:35:18.6556+08:00","gmt_modified":"2026-04-23T20:35:18.6556+08:00"},{"id":948,"source_id":"2126339b-b0f5-4152-924b-cbe028cd0c39","target_id":"557ae34b57a5dd8e8fa3bb2a6ce178a7","source_type":"WIKI_ITEM","target_type":"CODE_SNIPPET","relationship_type":"CONTAINS","extra":"Wiki contains code snippet: backend/app/workers/platforms/search_engine.py#163-174","gmt_create":"2026-04-23T20:35:18.657485+08:00","gmt_modified":"2026-04-23T20:35:18.657486+08:00"},{"id":949,"source_id":"2126339b-b0f5-4152-924b-cbe028cd0c39","target_id":"1526e4e02133a48eac04befb74ec5bd1","source_type":"WIKI_ITEM","target_type":"CODE_SNIPPET","relationship_type":"CONTAINS","extra":"Wiki contains code snippet: backend/app/workers/citation_engine.py#161-173","gmt_create":"2026-04-23T20:35:18.65887+08:00","gmt_modified":"2026-04-23T20:35:18.65887+08:00"},{"id":950,"source_id":"74040de652d5e57f548bb5c4adc3e1a0","target_id":"1526e4e02133a48eac04befb74ec5bd1","source_type":"SOURCE_FILE","target_type":"CODE_SNIPPET","relationship_type":"CONTAINS","extra":"Source file contains code snippet: 161-173","gmt_create":"2026-04-23T20:35:18.659265+08:00","gmt_modified":"2026-04-23T20:35:18.659265+08:00"},{"id":951,"source_id":"2126339b-b0f5-4152-924b-cbe028cd0c39","target_id":"98c02d9bb7aa6e2b6be5f7381e64fd99","source_type":"WIKI_ITEM","target_type":"CODE_SNIPPET","relationship_type":"CONTAINS","extra":"Wiki contains code snippet: backend/app/api/queries.py#26-39","gmt_create":"2026-04-23T20:35:18.661103+08:00","gmt_modified":"2026-04-23T20:35:18.661103+08:00"},{"id":952,"source_id":"6b3d903205941aa9391dd90016e1102c","target_id":"98c02d9bb7aa6e2b6be5f7381e64fd99","source_type":"SOURCE_FILE","target_type":"CODE_SNIPPET","relationship_type":"CONTAINS","extra":"Source file contains code snippet: 26-39","gmt_create":"2026-04-23T20:35:18.661433+08:00","gmt_modified":"2026-04-23T20:35:18.661433+08:00"},{"id":953,"source_id":"2126339b-b0f5-4152-924b-cbe028cd0c39","target_id":"212d822d207a4c0bd7825bbf20e188e9","source_type":"WIKI_ITEM","target_type":"CODE_SNIPPET","relationship_type":"CONTAINS","extra":"Wiki contains code snippet: backend/app/api/citations.py#59-77","gmt_create":"2026-04-23T20:35:18.661922+08:00","gmt_modified":"2026-04-23T20:35:18.661922+08:00"},{"id":954,"source_id":"2126339b-b0f5-4152-924b-cbe028cd0c39","target_id":"9b10dac7dbbb1327afc8a525bf4bd0c3","source_type":"WIKI_ITEM","target_type":"CODE_SNIPPET","relationship_type":"CONTAINS","extra":"Wiki contains code snippet: backend/app/services/query.py#45-81","gmt_create":"2026-04-23T20:35:18.662781+08:00","gmt_modified":"2026-04-23T20:35:18.662781+08:00"},{"id":955,"source_id":"2126339b-b0f5-4152-924b-cbe028cd0c39","target_id":"4ded871d02b8119cdd985de8b220b084","source_type":"WIKI_ITEM","target_type":"CODE_SNIPPET","relationship_type":"CONTAINS","extra":"Wiki contains code snippet: backend/app/services/citation.py#204-234","gmt_create":"2026-04-23T20:35:18.680675+08:00","gmt_modified":"2026-04-23T20:35:18.680675+08:00"},{"id":956,"source_id":"2126339b-b0f5-4152-924b-cbe028cd0c39","target_id":"448970b02d89d5e1576f70bdb0063363","source_type":"WIKI_ITEM","target_type":"CODE_SNIPPET","relationship_type":"CONTAINS","extra":"Wiki contains code snippet: backend/app/workers/scheduler.py#51-84","gmt_create":"2026-04-23T20:35:18.68314+08:00","gmt_modified":"2026-04-23T20:35:18.68314+08:00"},{"id":957,"source_id":"2126339b-b0f5-4152-924b-cbe028cd0c39","target_id":"8565f299083b4dcba5a328c947f06fee","source_type":"WIKI_ITEM","target_type":"CODE_SNIPPET","relationship_type":"CONTAINS","extra":"Wiki contains code snippet: backend/app/workers/citation_engine.py#256-287","gmt_create":"2026-04-23T20:35:18.685341+08:00","gmt_modified":"2026-04-23T20:35:18.685341+08:00"},{"id":958,"source_id":"2126339b-b0f5-4152-924b-cbe028cd0c39","target_id":"52c01d7b9c17aa16944cbfcf8885be61","source_type":"WIKI_ITEM","target_type":"CODE_SNIPPET","relationship_type":"CONTAINS","extra":"Wiki contains code snippet: backend/app/workers/platforms/kimi.py#16-33","gmt_create":"2026-04-23T20:35:18.686894+08:00","gmt_modified":"2026-04-23T20:35:18.686894+08:00"},{"id":959,"source_id":"2126339b-b0f5-4152-924b-cbe028cd0c39","target_id":"2a971cb83924013902324eceeab22559","source_type":"WIKI_ITEM","target_type":"CODE_SNIPPET","relationship_type":"CONTAINS","extra":"Wiki contains code snippet: backend/app/workers/platforms/kimi.py#16-29","gmt_create":"2026-04-23T20:35:18.689849+08:00","gmt_modified":"2026-04-23T20:35:18.689849+08:00"},{"id":960,"source_id":"8f973791233c698b3e64a4fb28a93d4b","target_id":"2a971cb83924013902324eceeab22559","source_type":"SOURCE_FILE","target_type":"CODE_SNIPPET","relationship_type":"CONTAINS","extra":"Source file contains code snippet: 16-29","gmt_create":"2026-04-23T20:35:18.69154+08:00","gmt_modified":"2026-04-23T20:35:18.69154+08:00"},{"id":961,"source_id":"2126339b-b0f5-4152-924b-cbe028cd0c39","target_id":"99326fedad9275392719105b5b6782d6","source_type":"WIKI_ITEM","target_type":"CODE_SNIPPET","relationship_type":"CONTAINS","extra":"Wiki contains code snippet: backend/app/workers/platforms/kimi.py#31-33","gmt_create":"2026-04-23T20:35:18.692776+08:00","gmt_modified":"2026-04-23T20:35:18.692776+08:00"},{"id":962,"source_id":"8f973791233c698b3e64a4fb28a93d4b","target_id":"99326fedad9275392719105b5b6782d6","source_type":"SOURCE_FILE","target_type":"CODE_SNIPPET","relationship_type":"CONTAINS","extra":"Source file contains code snippet: 31-33","gmt_create":"2026-04-23T20:35:18.693945+08:00","gmt_modified":"2026-04-23T20:35:18.693945+08:00"},{"id":963,"source_id":"2126339b-b0f5-4152-924b-cbe028cd0c39","target_id":"102223dd13475177a1ade8b9be14fbd1","source_type":"WIKI_ITEM","target_type":"CODE_SNIPPET","relationship_type":"CONTAINS","extra":"Wiki contains code snippet: backend/app/workers/platforms/search_engine.py#79-144","gmt_create":"2026-04-23T20:35:18.695323+08:00","gmt_modified":"2026-04-23T20:35:18.695324+08:00"},{"id":964,"source_id":"2126339b-b0f5-4152-924b-cbe028cd0c39","target_id":"5e5dacc623918c0f1eba234154c99291","source_type":"WIKI_ITEM","target_type":"CODE_SNIPPET","relationship_type":"CONTAINS","extra":"Wiki contains code snippet: backend/app/workers/platforms/search_engine.py#16-76","gmt_create":"2026-04-23T20:35:18.696341+08:00","gmt_modified":"2026-04-23T20:35:18.696341+08:00"},{"id":965,"source_id":"6a63f048c16c60c5d2d57012c810ee0e","target_id":"5e5dacc623918c0f1eba234154c99291","source_type":"SOURCE_FILE","target_type":"CODE_SNIPPET","relationship_type":"CONTAINS","extra":"Source file contains code snippet: 16-76","gmt_create":"2026-04-23T20:35:18.697266+08:00","gmt_modified":"2026-04-23T20:35:18.697267+08:00"},{"id":966,"source_id":"2126339b-b0f5-4152-924b-cbe028cd0c39","target_id":"5be7e6cf82d6359efddaf131aaf92615","source_type":"WIKI_ITEM","target_type":"CODE_SNIPPET","relationship_type":"CONTAINS","extra":"Wiki contains code snippet: backend/app/workers/citation_engine.py#323-330","gmt_create":"2026-04-23T20:35:18.701473+08:00","gmt_modified":"2026-04-23T20:35:18.701473+08:00"},{"id":967,"source_id":"74040de652d5e57f548bb5c4adc3e1a0","target_id":"5be7e6cf82d6359efddaf131aaf92615","source_type":"SOURCE_FILE","target_type":"CODE_SNIPPET","relationship_type":"CONTAINS","extra":"Source file contains code snippet: 323-330","gmt_create":"2026-04-23T20:35:18.7021+08:00","gmt_modified":"2026-04-23T20:35:18.7021+08:00"},{"id":968,"source_id":"2126339b-b0f5-4152-924b-cbe028cd0c39","target_id":"129b746e71a9013ceb1b0fcc59942b39","source_type":"WIKI_ITEM","target_type":"CODE_SNIPPET","relationship_type":"CONTAINS","extra":"Wiki contains code snippet: backend/app/workers/scheduler.py#86-90","gmt_create":"2026-04-23T20:35:18.703871+08:00","gmt_modified":"2026-04-23T20:35:18.703871+08:00"},{"id":969,"source_id":"5cbb1e3f112aeba62a14b0b8999fc0f5","target_id":"129b746e71a9013ceb1b0fcc59942b39","source_type":"SOURCE_FILE","target_type":"CODE_SNIPPET","relationship_type":"CONTAINS","extra":"Source file contains code snippet: 86-90","gmt_create":"2026-04-23T20:35:18.709231+08:00","gmt_modified":"2026-04-23T20:35:18.709231+08:00"},{"id":970,"source_id":"2126339b-b0f5-4152-924b-cbe028cd0c39","target_id":"fe70b1fef9f36e73d26d84987e927c7a","source_type":"WIKI_ITEM","target_type":"CODE_SNIPPET","relationship_type":"CONTAINS","extra":"Wiki contains code snippet: backend/app/api/queries.py#15-86","gmt_create":"2026-04-23T20:35:18.712574+08:00","gmt_modified":"2026-04-23T20:35:18.712574+08:00"},{"id":971,"source_id":"2126339b-b0f5-4152-924b-cbe028cd0c39","target_id":"c066a8d4bffabed87a2e38ccad81c107","source_type":"WIKI_ITEM","target_type":"CODE_SNIPPET","relationship_type":"CONTAINS","extra":"Wiki contains code snippet: backend/app/api/citations.py#25-77","gmt_create":"2026-04-23T20:35:18.713529+08:00","gmt_modified":"2026-04-23T20:35:18.713529+08:00"},{"id":972,"source_id":"2126339b-b0f5-4152-924b-cbe028cd0c39","target_id":"d7c319a04abbc6704da53107e07dd8e7","source_type":"WIKI_ITEM","target_type":"CODE_SNIPPET","relationship_type":"CONTAINS","extra":"Wiki contains code snippet: backend/app/services/query.py#12-130","gmt_create":"2026-04-23T20:35:18.714412+08:00","gmt_modified":"2026-04-23T20:35:18.714412+08:00"},{"id":973,"source_id":"2126339b-b0f5-4152-924b-cbe028cd0c39","target_id":"d780e807ee751f39f331a658b47c4ed3","source_type":"WIKI_ITEM","target_type":"CODE_SNIPPET","relationship_type":"CONTAINS","extra":"Wiki contains code snippet: backend/app/services/citation.py#24-269","gmt_create":"2026-04-23T20:35:18.715261+08:00","gmt_modified":"2026-04-23T20:35:18.715261+08:00"},{"id":974,"source_id":"04e3926c080e795713bff683e7dc9d3e","target_id":"d780e807ee751f39f331a658b47c4ed3","source_type":"SOURCE_FILE","target_type":"CODE_SNIPPET","relationship_type":"CONTAINS","extra":"Source file contains code snippet: 24-269","gmt_create":"2026-04-23T20:35:18.716135+08:00","gmt_modified":"2026-04-23T20:35:18.716135+08:00"},{"id":975,"source_id":"2126339b-b0f5-4152-924b-cbe028cd0c39","target_id":"8eea43550951387ac740b5e3e64c7691","source_type":"WIKI_ITEM","target_type":"CODE_SNIPPET","relationship_type":"CONTAINS","extra":"Wiki contains code snippet: backend/app/workers/platforms/search_engine.py#94-96","gmt_create":"2026-04-23T20:35:18.720519+08:00","gmt_modified":"2026-04-23T20:35:18.720519+08:00"},{"id":976,"source_id":"6a63f048c16c60c5d2d57012c810ee0e","target_id":"8eea43550951387ac740b5e3e64c7691","source_type":"SOURCE_FILE","target_type":"CODE_SNIPPET","relationship_type":"CONTAINS","extra":"Source file contains code snippet: 94-96","gmt_create":"2026-04-23T20:35:18.72132+08:00","gmt_modified":"2026-04-23T20:35:18.72132+08:00"},{"id":977,"source_id":"2126339b-b0f5-4152-924b-cbe028cd0c39","target_id":"ed527c7a549ec333c2b30b59614343df","source_type":"WIKI_ITEM","target_type":"CODE_SNIPPET","relationship_type":"CONTAINS","extra":"Wiki contains code snippet: backend/app/models/query.py#50-54","gmt_create":"2026-04-23T20:35:18.72244+08:00","gmt_modified":"2026-04-23T20:35:18.72244+08:00"},{"id":978,"source_id":"2126339b-b0f5-4152-924b-cbe028cd0c39","target_id":"a2adbf02c71e4eb2cf1f120e1a2ff517","source_type":"WIKI_ITEM","target_type":"CODE_SNIPPET","relationship_type":"CONTAINS","extra":"Wiki contains code snippet: backend/app/models/citation_record.py#37-41","gmt_create":"2026-04-23T20:35:18.725156+08:00","gmt_modified":"2026-04-23T20:35:18.725157+08:00"},{"id":979,"source_id":"2126339b-b0f5-4152-924b-cbe028cd0c39","target_id":"b55cc5936c299f819b57b899858438e6","source_type":"WIKI_ITEM","target_type":"CODE_SNIPPET","relationship_type":"CONTAINS","extra":"Wiki contains code snippet: backend/app/workers/platforms/search_engine.py#139-144","gmt_create":"2026-04-23T20:35:18.727146+08:00","gmt_modified":"2026-04-23T20:35:18.727146+08:00"},{"id":980,"source_id":"2126339b-b0f5-4152-924b-cbe028cd0c39","target_id":"37769b7e6b5588be0065681dedf514ed","source_type":"WIKI_ITEM","target_type":"CODE_SNIPPET","relationship_type":"CONTAINS","extra":"Wiki contains code snippet: backend/app/workers/platforms/search_engine.py#140-144","gmt_create":"2026-04-23T20:35:18.728033+08:00","gmt_modified":"2026-04-23T20:35:18.728033+08:00"},{"id":981,"source_id":"6a63f048c16c60c5d2d57012c810ee0e","target_id":"37769b7e6b5588be0065681dedf514ed","source_type":"SOURCE_FILE","target_type":"CODE_SNIPPET","relationship_type":"CONTAINS","extra":"Source file contains code snippet: 140-144","gmt_create":"2026-04-23T20:35:18.728855+08:00","gmt_modified":"2026-04-23T20:35:18.728855+08:00"},{"id":982,"source_id":"2126339b-b0f5-4152-924b-cbe028cd0c39","target_id":"518d184988b97ebc7ef0c0bf5c10f42c","source_type":"WIKI_ITEM","target_type":"CODE_SNIPPET","relationship_type":"CONTAINS","extra":"Wiki contains code snippet: backend/app/workers/platforms/kimi.py#24-29","gmt_create":"2026-04-23T20:35:18.72968+08:00","gmt_modified":"2026-04-23T20:35:18.72968+08:00"},{"id":983,"source_id":"8f973791233c698b3e64a4fb28a93d4b","target_id":"518d184988b97ebc7ef0c0bf5c10f42c","source_type":"SOURCE_FILE","target_type":"CODE_SNIPPET","relationship_type":"CONTAINS","extra":"Source file contains code snippet: 24-29","gmt_create":"2026-04-23T20:35:18.730545+08:00","gmt_modified":"2026-04-23T20:35:18.730546+08:00"},{"id":984,"source_id":"2126339b-b0f5-4152-924b-cbe028cd0c39","target_id":"818504ee2e17d2f9cc8fe115ca321138","source_type":"WIKI_ITEM","target_type":"CODE_SNIPPET","relationship_type":"CONTAINS","extra":"Wiki contains code snippet: backend/app/api/queries.py#34-38","gmt_create":"2026-04-23T20:35:18.73162+08:00","gmt_modified":"2026-04-23T20:35:18.73162+08:00"},{"id":985,"source_id":"6b3d903205941aa9391dd90016e1102c","target_id":"818504ee2e17d2f9cc8fe115ca321138","source_type":"SOURCE_FILE","target_type":"CODE_SNIPPET","relationship_type":"CONTAINS","extra":"Source file contains code snippet: 34-38","gmt_create":"2026-04-23T20:35:18.732614+08:00","gmt_modified":"2026-04-23T20:35:18.732614+08:00"},{"id":986,"source_id":"2126339b-b0f5-4152-924b-cbe028cd0c39","target_id":"55f1628f1ab6f323710e367e12146b1a","source_type":"WIKI_ITEM","target_type":"CODE_SNIPPET","relationship_type":"CONTAINS","extra":"Wiki contains code snippet: backend/app/api/citations.py#67-71","gmt_create":"2026-04-23T20:35:18.733467+08:00","gmt_modified":"2026-04-23T20:35:18.733467+08:00"},{"id":987,"source_id":"2126339b-b0f5-4152-924b-cbe028cd0c39","target_id":"8a1a0ffd82ac6ff54d3410e4ce59a6b8","source_type":"WIKI_ITEM","target_type":"CODE_SNIPPET","relationship_type":"CONTAINS","extra":"Wiki contains code snippet: backend/app/api/citations.py#25-56","gmt_create":"2026-04-23T20:35:18.735579+08:00","gmt_modified":"2026-04-23T20:35:18.735579+08:00"},{"id":988,"source_id":"7538ffe4902ab6041adb28b19844962a","target_id":"8a1a0ffd82ac6ff54d3410e4ce59a6b8","source_type":"SOURCE_FILE","target_type":"CODE_SNIPPET","relationship_type":"CONTAINS","extra":"Source file contains code snippet: 25-56","gmt_create":"2026-04-23T20:35:18.73663+08:00","gmt_modified":"2026-04-23T20:35:18.73663+08:00"},{"id":1012,"source_id":"b4a81ef789630d0af6a8d50859d01bf3","target_id":"d4f99d3dd9fe489c354edf5fe2f8803d","source_type":"SOURCE_FILE","target_type":"CODE_SNIPPET","relationship_type":"CONTAINS","extra":"Source file contains code snippet: 1-44","gmt_create":"2026-04-23T20:35:45.713712+08:00","gmt_modified":"2026-04-23T20:35:45.713713+08:00"},{"id":1015,"source_id":"bceca00463fe55d3bcafda728f97f723","target_id":"86e37040be1aeb400fab9b529f5404c8","source_type":"SOURCE_FILE","target_type":"CODE_SNIPPET","relationship_type":"CONTAINS","extra":"Source file contains code snippet: 1-37","gmt_create":"2026-04-23T20:35:45.722046+08:00","gmt_modified":"2026-04-23T20:35:45.722047+08:00"},{"id":1017,"source_id":"a680d4819f5da57fe9fa0e6bc708f380","target_id":"211463f5b49610f09594c40c0a235943","source_type":"SOURCE_FILE","target_type":"CODE_SNIPPET","relationship_type":"CONTAINS","extra":"Source file contains code snippet: 1-89","gmt_create":"2026-04-23T20:35:45.736063+08:00","gmt_modified":"2026-04-23T20:35:45.736064+08:00"},{"id":1019,"source_id":"fc6242433ae9506bcc0bf4cb0dce1413","target_id":"48d22eaee09e364a293ad6c4750f5c5a","source_type":"SOURCE_FILE","target_type":"CODE_SNIPPET","relationship_type":"CONTAINS","extra":"Source file contains code snippet: 1-71","gmt_create":"2026-04-23T20:35:45.743112+08:00","gmt_modified":"2026-04-23T20:35:45.743112+08:00"},{"id":1022,"source_id":"d4f95fcf50683b5bf6167c7d2a6b126d","target_id":"98cc82f62b83678f06a33cf9231ecdf8","source_type":"SOURCE_FILE","target_type":"CODE_SNIPPET","relationship_type":"CONTAINS","extra":"Source file contains code snippet: 1-128","gmt_create":"2026-04-23T20:35:45.771158+08:00","gmt_modified":"2026-04-23T20:35:45.771158+08:00"},{"id":1024,"source_id":"f6e6948dd0cdd3894bd9928b21feb979","target_id":"e1aabd52989e47806fb997157381e1cf","source_type":"SOURCE_FILE","target_type":"CODE_SNIPPET","relationship_type":"CONTAINS","extra":"Source file contains code snippet: 1-37","gmt_create":"2026-04-23T20:35:45.782446+08:00","gmt_modified":"2026-04-23T20:35:45.782446+08:00"},{"id":1028,"source_id":"d4f95fcf50683b5bf6167c7d2a6b126d","target_id":"ac77e4875817616194b7b5997d4fb1ae","source_type":"SOURCE_FILE","target_type":"CODE_SNIPPET","relationship_type":"CONTAINS","extra":"Source file contains code snippet: 57-94","gmt_create":"2026-04-23T20:35:45.808076+08:00","gmt_modified":"2026-04-23T20:35:45.808076+08:00"},{"id":1030,"source_id":"f6e6948dd0cdd3894bd9928b21feb979","target_id":"0e57efd98dacc85da21f995980371ee4","source_type":"SOURCE_FILE","target_type":"CODE_SNIPPET","relationship_type":"CONTAINS","extra":"Source file contains code snippet: 21-37","gmt_create":"2026-04-23T20:35:45.81891+08:00","gmt_modified":"2026-04-23T20:35:45.81891+08:00"},{"id":1033,"source_id":"b4a81ef789630d0af6a8d50859d01bf3","target_id":"717eb27184726e4f78d694984d29420c","source_type":"SOURCE_FILE","target_type":"CODE_SNIPPET","relationship_type":"CONTAINS","extra":"Source file contains code snippet: 37-44","gmt_create":"2026-04-23T20:35:45.831123+08:00","gmt_modified":"2026-04-23T20:35:45.831123+08:00"},{"id":1037,"source_id":"b74caccb06844efcdb14d8324cff65c2","target_id":"bfdf3479f244dc6794628d9df10ab6d0","source_type":"SOURCE_FILE","target_type":"CODE_SNIPPET","relationship_type":"CONTAINS","extra":"Source file contains code snippet: 11-48","gmt_create":"2026-04-23T20:35:45.842187+08:00","gmt_modified":"2026-04-23T20:35:45.842187+08:00"},{"id":1039,"source_id":"b4a81ef789630d0af6a8d50859d01bf3","target_id":"f5f9f0d96263ae84631c7a8d7e9b3648","source_type":"SOURCE_FILE","target_type":"CODE_SNIPPET","relationship_type":"CONTAINS","extra":"Source file contains code snippet: 11-44","gmt_create":"2026-04-23T20:35:45.84404+08:00","gmt_modified":"2026-04-23T20:35:45.84404+08:00"},{"id":1041,"source_id":"069738f21ac2da7349d22683e8c36929","target_id":"818d1354dc0665798f3d91a2ca5153d6","source_type":"SOURCE_FILE","target_type":"CODE_SNIPPET","relationship_type":"CONTAINS","extra":"Source file contains code snippet: 11-34","gmt_create":"2026-04-23T20:35:45.845935+08:00","gmt_modified":"2026-04-23T20:35:45.845935+08:00"},{"id":1043,"source_id":"bceca00463fe55d3bcafda728f97f723","target_id":"24aade4c34609a8ab28e4643a3692201","source_type":"SOURCE_FILE","target_type":"CODE_SNIPPET","relationship_type":"CONTAINS","extra":"Source file contains code snippet: 11-36","gmt_create":"2026-04-23T20:35:45.853262+08:00","gmt_modified":"2026-04-23T20:35:45.853263+08:00"},{"id":1045,"source_id":"a680d4819f5da57fe9fa0e6bc708f380","target_id":"d34337b9ff77246979252d2fd8fb8018","source_type":"SOURCE_FILE","target_type":"CODE_SNIPPET","relationship_type":"CONTAINS","extra":"Source file contains code snippet: 33-88","gmt_create":"2026-04-23T20:35:45.866334+08:00","gmt_modified":"2026-04-23T20:35:45.866335+08:00"},{"id":1048,"source_id":"d4f95fcf50683b5bf6167c7d2a6b126d","target_id":"eb63042f04a22f9a67bd498df1684d20","source_type":"SOURCE_FILE","target_type":"CODE_SNIPPET","relationship_type":"CONTAINS","extra":"Source file contains code snippet: 36-111","gmt_create":"2026-04-23T20:35:45.883763+08:00","gmt_modified":"2026-04-23T20:35:45.883763+08:00"},{"id":1051,"source_id":"b0c428683c8a3e6922d90ca0d8c2736d","target_id":"c651c7ad6747a92ee96eabb2eb82afdd","source_type":"SOURCE_FILE","target_type":"CODE_SNIPPET","relationship_type":"CONTAINS","extra":"Source file contains code snippet: 12-18","gmt_create":"2026-04-23T20:35:45.891674+08:00","gmt_modified":"2026-04-23T20:35:45.891674+08:00"},{"id":1053,"source_id":"04e3926c080e795713bff683e7dc9d3e","target_id":"dd01eee487298a28e950f6345196f1d4","source_type":"SOURCE_FILE","target_type":"CODE_SNIPPET","relationship_type":"CONTAINS","extra":"Source file contains code snippet: 30-79","gmt_create":"2026-04-23T20:35:45.895814+08:00","gmt_modified":"2026-04-23T20:35:45.895814+08:00"},{"id":1055,"source_id":"88d22de3b2a7419868e8ae19130d860c","target_id":"7dae7237f11c5100bf7889c105193cf6","source_type":"SOURCE_FILE","target_type":"CODE_SNIPPET","relationship_type":"CONTAINS","extra":"Source file contains code snippet: 12-32","gmt_create":"2026-04-23T20:35:45.901349+08:00","gmt_modified":"2026-04-23T20:35:45.901349+08:00"},{"id":1057,"source_id":"04e3926c080e795713bff683e7dc9d3e","target_id":"cc64cf609f5ff218f618e0664ffa7cc7","source_type":"SOURCE_FILE","target_type":"CODE_SNIPPET","relationship_type":"CONTAINS","extra":"Source file contains code snippet: 298-308","gmt_create":"2026-04-23T20:35:45.904411+08:00","gmt_modified":"2026-04-23T20:35:45.904411+08:00"},{"id":1059,"source_id":"04e3926c080e795713bff683e7dc9d3e","target_id":"ce7e334595a4ce912e0d116314db9a35","source_type":"SOURCE_FILE","target_type":"CODE_SNIPPET","relationship_type":"CONTAINS","extra":"Source file contains code snippet: 342-429","gmt_create":"2026-04-23T20:35:45.906963+08:00","gmt_modified":"2026-04-23T20:35:45.906964+08:00"},{"id":1061,"source_id":"1a3336b4af8a39a055e912724338580c","target_id":"2f46f212597e3c245b9e5dcc5dbc863d","source_type":"SOURCE_FILE","target_type":"CODE_SNIPPET","relationship_type":"CONTAINS","extra":"Source file contains code snippet: 7-18","gmt_create":"2026-04-23T20:35:45.909475+08:00","gmt_modified":"2026-04-23T20:35:45.909476+08:00"},{"id":1063,"source_id":"04e3926c080e795713bff683e7dc9d3e","target_id":"dc40f1dd3e59ee7f046019201068bea1","source_type":"SOURCE_FILE","target_type":"CODE_SNIPPET","relationship_type":"CONTAINS","extra":"Source file contains code snippet: 14-22","gmt_create":"2026-04-23T20:35:45.920772+08:00","gmt_modified":"2026-04-23T20:35:45.920772+08:00"},{"id":1069,"source_id":"deb919cc-9541-4ed7-a581-ae2876ea67c2","target_id":"a1cc822d-5382-431c-8c49-cf398fb5eb3c","source_type":"WIKI_ITEM","target_type":"WIKI_ITEM","relationship_type":"PARENT_CHILD","extra":"Wiki parent-child relationship: deb919cc-9541-4ed7-a581-ae2876ea67c2 -\u003e a1cc822d-5382-431c-8c49-cf398fb5eb3c","gmt_create":"2026-04-23T20:35:46.950364+08:00","gmt_modified":"2026-04-23T20:35:46.950364+08:00"},{"id":1070,"source_id":"cfc48cde-e1c3-47f6-afe2-a6d7a8f4ab69","target_id":"37003fc0-1cf5-4264-996b-40807001875f","source_type":"WIKI_ITEM","target_type":"WIKI_ITEM","relationship_type":"PARENT_CHILD","extra":"Wiki parent-child relationship: cfc48cde-e1c3-47f6-afe2-a6d7a8f4ab69 -\u003e 37003fc0-1cf5-4264-996b-40807001875f","gmt_create":"2026-04-23T20:35:46.957122+08:00","gmt_modified":"2026-04-23T20:35:46.957122+08:00"},{"id":1071,"source_id":"cfc48cde-e1c3-47f6-afe2-a6d7a8f4ab69","target_id":"2126339b-b0f5-4152-924b-cbe028cd0c39","source_type":"WIKI_ITEM","target_type":"WIKI_ITEM","relationship_type":"PARENT_CHILD","extra":"Wiki parent-child relationship: cfc48cde-e1c3-47f6-afe2-a6d7a8f4ab69 -\u003e 2126339b-b0f5-4152-924b-cbe028cd0c39","gmt_create":"2026-04-23T20:35:46.959782+08:00","gmt_modified":"2026-04-23T20:35:46.959782+08:00"},{"id":1072,"source_id":"cfc48cde-e1c3-47f6-afe2-a6d7a8f4ab69","target_id":"fab60eaf-9652-4cb5-9f9e-0525caa62d63","source_type":"WIKI_ITEM","target_type":"WIKI_ITEM","relationship_type":"PARENT_CHILD","extra":"Wiki parent-child relationship: cfc48cde-e1c3-47f6-afe2-a6d7a8f4ab69 -\u003e fab60eaf-9652-4cb5-9f9e-0525caa62d63","gmt_create":"2026-04-23T20:35:46.965729+08:00","gmt_modified":"2026-04-23T20:35:46.965729+08:00"},{"id":1073,"source_id":"cfc48cde-e1c3-47f6-afe2-a6d7a8f4ab69","target_id":"00359e45-209d-4be3-8795-50dea52bdba1","source_type":"WIKI_ITEM","target_type":"WIKI_ITEM","relationship_type":"PARENT_CHILD","extra":"Wiki parent-child relationship: cfc48cde-e1c3-47f6-afe2-a6d7a8f4ab69 -\u003e 00359e45-209d-4be3-8795-50dea52bdba1","gmt_create":"2026-04-23T20:35:46.970985+08:00","gmt_modified":"2026-04-23T20:35:46.970985+08:00"},{"id":1074,"source_id":"cfc48cde-e1c3-47f6-afe2-a6d7a8f4ab69","target_id":"2632a6f9-774e-4a91-94da-a984bdb20758","source_type":"WIKI_ITEM","target_type":"WIKI_ITEM","relationship_type":"PARENT_CHILD","extra":"Wiki parent-child relationship: cfc48cde-e1c3-47f6-afe2-a6d7a8f4ab69 -\u003e 2632a6f9-774e-4a91-94da-a984bdb20758","gmt_create":"2026-04-23T20:35:46.974435+08:00","gmt_modified":"2026-04-23T20:35:46.974435+08:00"},{"id":1076,"source_id":"643984fc-5a57-498b-8f25-68cc318d9d82","target_id":"a26ee01cf41da3b956e1650448c156fa","source_type":"WIKI_ITEM","target_type":"SOURCE_FILE","relationship_type":"REFERENCED_BY","extra":"Wiki references source file: backend/requirements.txt","gmt_create":"2026-04-23T21:00:59.656249+08:00","gmt_modified":"2026-04-23T21:00:59.656249+08:00"},{"id":1077,"source_id":"643984fc-5a57-498b-8f25-68cc318d9d82","target_id":"aaf5bce6be82d2f947bfa5c1806de452","source_type":"WIKI_ITEM","target_type":"SOURCE_FILE","relationship_type":"REFERENCED_BY","extra":"Wiki references source file: frontend/package.json","gmt_create":"2026-04-23T21:00:59.656613+08:00","gmt_modified":"2026-04-23T21:00:59.656613+08:00"},{"id":1078,"source_id":"643984fc-5a57-498b-8f25-68cc318d9d82","target_id":"9228ff67d4c757a85d9421b71f4b29f5","source_type":"WIKI_ITEM","target_type":"SOURCE_FILE","relationship_type":"REFERENCED_BY","extra":"Wiki references source file: backend/app/main.py","gmt_create":"2026-04-23T21:00:59.656928+08:00","gmt_modified":"2026-04-23T21:00:59.656928+08:00"},{"id":1079,"source_id":"643984fc-5a57-498b-8f25-68cc318d9d82","target_id":"e9b52adbec3c07cf021e488dd3f99ab4","source_type":"WIKI_ITEM","target_type":"SOURCE_FILE","relationship_type":"REFERENCED_BY","extra":"Wiki references source file: backend/Dockerfile","gmt_create":"2026-04-23T21:00:59.657229+08:00","gmt_modified":"2026-04-23T21:00:59.657229+08:00"},{"id":1080,"source_id":"643984fc-5a57-498b-8f25-68cc318d9d82","target_id":"5e414f2ef9b69e55e00ab15f85b9291a","source_type":"WIKI_ITEM","target_type":"SOURCE_FILE","relationship_type":"REFERENCED_BY","extra":"Wiki references source file: frontend/Dockerfile","gmt_create":"2026-04-23T21:00:59.657778+08:00","gmt_modified":"2026-04-23T21:00:59.657779+08:00"},{"id":1081,"source_id":"643984fc-5a57-498b-8f25-68cc318d9d82","target_id":"fc6242433ae9506bcc0bf4cb0dce1413","source_type":"WIKI_ITEM","target_type":"SOURCE_FILE","relationship_type":"REFERENCED_BY","extra":"Wiki references source file: docker-compose.yml","gmt_create":"2026-04-23T21:00:59.658783+08:00","gmt_modified":"2026-04-23T21:00:59.658783+08:00"},{"id":1082,"source_id":"643984fc-5a57-498b-8f25-68cc318d9d82","target_id":"50f2e6bdc4a79e69bd43ea8d6fec67fe","source_type":"WIKI_ITEM","target_type":"SOURCE_FILE","relationship_type":"REFERENCED_BY","extra":"Wiki references source file: backend/alembic.ini","gmt_create":"2026-04-23T21:00:59.659121+08:00","gmt_modified":"2026-04-23T21:00:59.659121+08:00"},{"id":1083,"source_id":"643984fc-5a57-498b-8f25-68cc318d9d82","target_id":"9ff19022ef915615911280e3c49ed44b","source_type":"WIKI_ITEM","target_type":"SOURCE_FILE","relationship_type":"REFERENCED_BY","extra":"Wiki references source file: backend/app/config.py","gmt_create":"2026-04-23T21:00:59.659433+08:00","gmt_modified":"2026-04-23T21:00:59.659433+08:00"},{"id":1084,"source_id":"643984fc-5a57-498b-8f25-68cc318d9d82","target_id":"fb8af100a06778e1fbdac4790a3ed0a9","source_type":"WIKI_ITEM","target_type":"SOURCE_FILE","relationship_type":"REFERENCED_BY","extra":"Wiki references source file: frontend/tsconfig.json","gmt_create":"2026-04-23T21:00:59.659973+08:00","gmt_modified":"2026-04-23T21:00:59.659973+08:00"},{"id":1085,"source_id":"643984fc-5a57-498b-8f25-68cc318d9d82","target_id":"01056dad8851d3e9bd532eb4cab33792","source_type":"WIKI_ITEM","target_type":"SOURCE_FILE","relationship_type":"REFERENCED_BY","extra":"Wiki references source file: frontend/tailwind.config.ts","gmt_create":"2026-04-23T21:00:59.660739+08:00","gmt_modified":"2026-04-23T21:00:59.660739+08:00"},{"id":1086,"source_id":"643984fc-5a57-498b-8f25-68cc318d9d82","target_id":"4d9b59c294a0aac5e300b3de715eb226","source_type":"WIKI_ITEM","target_type":"SOURCE_FILE","relationship_type":"REFERENCED_BY","extra":"Wiki references source file: frontend/.eslintrc.json","gmt_create":"2026-04-23T21:00:59.661096+08:00","gmt_modified":"2026-04-23T21:00:59.661097+08:00"},{"id":1087,"source_id":"643984fc-5a57-498b-8f25-68cc318d9d82","target_id":"0ef1efea889dba3e1f299626df479571","source_type":"WIKI_ITEM","target_type":"SOURCE_FILE","relationship_type":"REFERENCED_BY","extra":"Wiki references source file: tests/conftest.py","gmt_create":"2026-04-23T21:00:59.661386+08:00","gmt_modified":"2026-04-23T21:00:59.661386+08:00"},{"id":1088,"source_id":"643984fc-5a57-498b-8f25-68cc318d9d82","target_id":"93022c8938ce318f167277cfa65c29a7","source_type":"WIKI_ITEM","target_type":"SOURCE_FILE","relationship_type":"REFERENCED_BY","extra":"Wiki references source file: backend/app/api/auth.py","gmt_create":"2026-04-23T21:00:59.661691+08:00","gmt_modified":"2026-04-23T21:00:59.661691+08:00"},{"id":1089,"source_id":"643984fc-5a57-498b-8f25-68cc318d9d82","target_id":"e0c0ca66b8b81cf66e078a7ab162c07f","source_type":"WIKI_ITEM","target_type":"SOURCE_FILE","relationship_type":"REFERENCED_BY","extra":"Wiki references source file: backend/app/schemas/auth.py","gmt_create":"2026-04-23T21:00:59.661989+08:00","gmt_modified":"2026-04-23T21:00:59.661989+08:00"},{"id":1090,"source_id":"643984fc-5a57-498b-8f25-68cc318d9d82","target_id":"c59f8c276697a070dffc581fe94d809c","source_type":"WIKI_ITEM","target_type":"SOURCE_FILE","relationship_type":"REFERENCED_BY","extra":"Wiki references source file: backend/app/models/user.py","gmt_create":"2026-04-23T21:00:59.662317+08:00","gmt_modified":"2026-04-23T21:00:59.662317+08:00"},{"id":1091,"source_id":"643984fc-5a57-498b-8f25-68cc318d9d82","target_id":"48a560c49d2b21da327c036ec2934b96","source_type":"WIKI_ITEM","target_type":"SOURCE_FILE","relationship_type":"REFERENCED_BY","extra":"Wiki references source file: README.md","gmt_create":"2026-04-23T21:00:59.662608+08:00","gmt_modified":"2026-04-23T21:00:59.662608+08:00"},{"id":1092,"source_id":"643984fc-5a57-498b-8f25-68cc318d9d82","target_id":"48d22eaee09e364a293ad6c4750f5c5a","source_type":"WIKI_ITEM","target_type":"CODE_SNIPPET","relationship_type":"CONTAINS","extra":"Wiki contains code snippet: docker-compose.yml#1-71","gmt_create":"2026-04-23T21:00:59.663719+08:00","gmt_modified":"2026-04-23T21:00:59.663719+08:00"},{"id":1093,"source_id":"643984fc-5a57-498b-8f25-68cc318d9d82","target_id":"01a0c4b40819965823b56e9da858c024","source_type":"WIKI_ITEM","target_type":"CODE_SNIPPET","relationship_type":"CONTAINS","extra":"Wiki contains code snippet: frontend/Dockerfile#1-15","gmt_create":"2026-04-23T21:00:59.66424+08:00","gmt_modified":"2026-04-23T21:00:59.66424+08:00"},{"id":1094,"source_id":"5e414f2ef9b69e55e00ab15f85b9291a","target_id":"01a0c4b40819965823b56e9da858c024","source_type":"SOURCE_FILE","target_type":"CODE_SNIPPET","relationship_type":"CONTAINS","extra":"Source file contains code snippet: 1-15","gmt_create":"2026-04-23T21:00:59.664546+08:00","gmt_modified":"2026-04-23T21:00:59.664546+08:00"},{"id":1095,"source_id":"643984fc-5a57-498b-8f25-68cc318d9d82","target_id":"412695e5de2014514a8f62f98c573656","source_type":"WIKI_ITEM","target_type":"CODE_SNIPPET","relationship_type":"CONTAINS","extra":"Wiki contains code snippet: backend/Dockerfile#1-41","gmt_create":"2026-04-23T21:00:59.66492+08:00","gmt_modified":"2026-04-23T21:00:59.66492+08:00"},{"id":1096,"source_id":"643984fc-5a57-498b-8f25-68cc318d9d82","target_id":"71a37a516437e94fd82a87efc70a3f16","source_type":"WIKI_ITEM","target_type":"CODE_SNIPPET","relationship_type":"CONTAINS","extra":"Wiki contains code snippet: frontend/package.json#1-40","gmt_create":"2026-04-23T21:00:59.665702+08:00","gmt_modified":"2026-04-23T21:00:59.665702+08:00"},{"id":1097,"source_id":"643984fc-5a57-498b-8f25-68cc318d9d82","target_id":"7289a3568c137c8a671fc8c963bb8d28","source_type":"WIKI_ITEM","target_type":"CODE_SNIPPET","relationship_type":"CONTAINS","extra":"Wiki contains code snippet: backend/requirements.txt#1-35","gmt_create":"2026-04-23T21:00:59.688277+08:00","gmt_modified":"2026-04-23T21:00:59.688278+08:00"},{"id":1098,"source_id":"643984fc-5a57-498b-8f25-68cc318d9d82","target_id":"c2747ca16b879bca0f68955534c3c4fc","source_type":"WIKI_ITEM","target_type":"CODE_SNIPPET","relationship_type":"CONTAINS","extra":"Wiki contains code snippet: backend/app/main.py#1-48","gmt_create":"2026-04-23T21:00:59.689553+08:00","gmt_modified":"2026-04-23T21:00:59.689553+08:00"},{"id":1099,"source_id":"643984fc-5a57-498b-8f25-68cc318d9d82","target_id":"84fbed7d35f7752e2117a74fcaf5f0e9","source_type":"WIKI_ITEM","target_type":"CODE_SNIPPET","relationship_type":"CONTAINS","extra":"Wiki contains code snippet: backend/app/config.py#1-17","gmt_create":"2026-04-23T21:00:59.690337+08:00","gmt_modified":"2026-04-23T21:00:59.690337+08:00"},{"id":1100,"source_id":"643984fc-5a57-498b-8f25-68cc318d9d82","target_id":"13f6ca76349ef86ae756bb519f122bc5","source_type":"WIKI_ITEM","target_type":"CODE_SNIPPET","relationship_type":"CONTAINS","extra":"Wiki contains code snippet: backend/alembic.ini#1-150","gmt_create":"2026-04-23T21:00:59.691229+08:00","gmt_modified":"2026-04-23T21:00:59.691229+08:00"},{"id":1101,"source_id":"50f2e6bdc4a79e69bd43ea8d6fec67fe","target_id":"13f6ca76349ef86ae756bb519f122bc5","source_type":"SOURCE_FILE","target_type":"CODE_SNIPPET","relationship_type":"CONTAINS","extra":"Source file contains code snippet: 1-150","gmt_create":"2026-04-23T21:00:59.691641+08:00","gmt_modified":"2026-04-23T21:00:59.691641+08:00"},{"id":1102,"source_id":"643984fc-5a57-498b-8f25-68cc318d9d82","target_id":"74abd6612105c29b67178fa9dbd04b61","source_type":"WIKI_ITEM","target_type":"CODE_SNIPPET","relationship_type":"CONTAINS","extra":"Wiki contains code snippet: frontend/tsconfig.json#1-27","gmt_create":"2026-04-23T21:00:59.696048+08:00","gmt_modified":"2026-04-23T21:00:59.696048+08:00"},{"id":1103,"source_id":"fb8af100a06778e1fbdac4790a3ed0a9","target_id":"74abd6612105c29b67178fa9dbd04b61","source_type":"SOURCE_FILE","target_type":"CODE_SNIPPET","relationship_type":"CONTAINS","extra":"Source file contains code snippet: 1-27","gmt_create":"2026-04-23T21:00:59.696535+08:00","gmt_modified":"2026-04-23T21:00:59.696535+08:00"},{"id":1104,"source_id":"643984fc-5a57-498b-8f25-68cc318d9d82","target_id":"5bdaabf085a7c3eb6e87c5ad7479e25d","source_type":"WIKI_ITEM","target_type":"CODE_SNIPPET","relationship_type":"CONTAINS","extra":"Wiki contains code snippet: frontend/.eslintrc.json#1-4","gmt_create":"2026-04-23T21:00:59.697248+08:00","gmt_modified":"2026-04-23T21:00:59.697248+08:00"},{"id":1105,"source_id":"4d9b59c294a0aac5e300b3de715eb226","target_id":"5bdaabf085a7c3eb6e87c5ad7479e25d","source_type":"SOURCE_FILE","target_type":"CODE_SNIPPET","relationship_type":"CONTAINS","extra":"Source file contains code snippet: 1-4","gmt_create":"2026-04-23T21:00:59.697778+08:00","gmt_modified":"2026-04-23T21:00:59.697778+08:00"},{"id":1106,"source_id":"643984fc-5a57-498b-8f25-68cc318d9d82","target_id":"89d70e5f89be23a229e3ee59982b8e6e","source_type":"WIKI_ITEM","target_type":"CODE_SNIPPET","relationship_type":"CONTAINS","extra":"Wiki contains code snippet: frontend/tailwind.config.ts#1-57","gmt_create":"2026-04-23T21:00:59.69854+08:00","gmt_modified":"2026-04-23T21:00:59.69854+08:00"},{"id":1107,"source_id":"643984fc-5a57-498b-8f25-68cc318d9d82","target_id":"9482f4f6279a4f636b77e69b8273b996","source_type":"WIKI_ITEM","target_type":"CODE_SNIPPET","relationship_type":"CONTAINS","extra":"Wiki contains code snippet: backend/alembic.ini#86-114","gmt_create":"2026-04-23T21:00:59.700127+08:00","gmt_modified":"2026-04-23T21:00:59.700127+08:00"},{"id":1108,"source_id":"50f2e6bdc4a79e69bd43ea8d6fec67fe","target_id":"9482f4f6279a4f636b77e69b8273b996","source_type":"SOURCE_FILE","target_type":"CODE_SNIPPET","relationship_type":"CONTAINS","extra":"Source file contains code snippet: 86-114","gmt_create":"2026-04-23T21:00:59.700939+08:00","gmt_modified":"2026-04-23T21:00:59.70094+08:00"},{"id":1109,"source_id":"643984fc-5a57-498b-8f25-68cc318d9d82","target_id":"397b266f19a1addebdf6c32db71ae77f","source_type":"WIKI_ITEM","target_type":"CODE_SNIPPET","relationship_type":"CONTAINS","extra":"Wiki contains code snippet: tests/conftest.py#1-71","gmt_create":"2026-04-23T21:00:59.70244+08:00","gmt_modified":"2026-04-23T21:00:59.70244+08:00"},{"id":1110,"source_id":"0ef1efea889dba3e1f299626df479571","target_id":"397b266f19a1addebdf6c32db71ae77f","source_type":"SOURCE_FILE","target_type":"CODE_SNIPPET","relationship_type":"CONTAINS","extra":"Source file contains code snippet: 1-71","gmt_create":"2026-04-23T21:00:59.703412+08:00","gmt_modified":"2026-04-23T21:00:59.703413+08:00"},{"id":1111,"source_id":"643984fc-5a57-498b-8f25-68cc318d9d82","target_id":"b55a164add5a8fec2ef0e489f7234829","source_type":"WIKI_ITEM","target_type":"CODE_SNIPPET","relationship_type":"CONTAINS","extra":"Wiki contains code snippet: backend/app/main.py#24-47","gmt_create":"2026-04-23T21:00:59.707909+08:00","gmt_modified":"2026-04-23T21:00:59.707909+08:00"},{"id":1112,"source_id":"643984fc-5a57-498b-8f25-68cc318d9d82","target_id":"eb603ec2611957de67af00756f4b1efa","source_type":"WIKI_ITEM","target_type":"CODE_SNIPPET","relationship_type":"CONTAINS","extra":"Wiki contains code snippet: backend/app/config.py#7-13","gmt_create":"2026-04-23T21:00:59.708942+08:00","gmt_modified":"2026-04-23T21:00:59.708942+08:00"},{"id":1113,"source_id":"9ff19022ef915615911280e3c49ed44b","target_id":"eb603ec2611957de67af00756f4b1efa","source_type":"SOURCE_FILE","target_type":"CODE_SNIPPET","relationship_type":"CONTAINS","extra":"Source file contains code snippet: 7-13","gmt_create":"2026-04-23T21:00:59.713128+08:00","gmt_modified":"2026-04-23T21:00:59.713128+08:00"},{"id":1114,"source_id":"643984fc-5a57-498b-8f25-68cc318d9d82","target_id":"c25b39830f3b7734da975acc7f214666","source_type":"WIKI_ITEM","target_type":"CODE_SNIPPET","relationship_type":"CONTAINS","extra":"Wiki contains code snippet: backend/Dockerfile#31-33","gmt_create":"2026-04-23T21:00:59.714181+08:00","gmt_modified":"2026-04-23T21:00:59.714181+08:00"},{"id":1115,"source_id":"e9b52adbec3c07cf021e488dd3f99ab4","target_id":"c25b39830f3b7734da975acc7f214666","source_type":"SOURCE_FILE","target_type":"CODE_SNIPPET","relationship_type":"CONTAINS","extra":"Source file contains code snippet: 31-33","gmt_create":"2026-04-23T21:00:59.71645+08:00","gmt_modified":"2026-04-23T21:00:59.71645+08:00"},{"id":1116,"source_id":"643984fc-5a57-498b-8f25-68cc318d9d82","target_id":"4c9d362ecce8e796e6f14850def049b0","source_type":"WIKI_ITEM","target_type":"CODE_SNIPPET","relationship_type":"CONTAINS","extra":"Wiki contains code snippet: docker-compose.yml#4-20","gmt_create":"2026-04-23T21:00:59.717301+08:00","gmt_modified":"2026-04-23T21:00:59.717301+08:00"},{"id":1117,"source_id":"fc6242433ae9506bcc0bf4cb0dce1413","target_id":"4c9d362ecce8e796e6f14850def049b0","source_type":"SOURCE_FILE","target_type":"CODE_SNIPPET","relationship_type":"CONTAINS","extra":"Source file contains code snippet: 4-20","gmt_create":"2026-04-23T21:00:59.718148+08:00","gmt_modified":"2026-04-23T21:00:59.718148+08:00"},{"id":1118,"source_id":"643984fc-5a57-498b-8f25-68cc318d9d82","target_id":"d5827be2cfbe41c8177660ae877e93a4","source_type":"WIKI_ITEM","target_type":"CODE_SNIPPET","relationship_type":"CONTAINS","extra":"Wiki contains code snippet: docker-compose.yml#22-34","gmt_create":"2026-04-23T21:00:59.719092+08:00","gmt_modified":"2026-04-23T21:00:59.719092+08:00"},{"id":1119,"source_id":"fc6242433ae9506bcc0bf4cb0dce1413","target_id":"d5827be2cfbe41c8177660ae877e93a4","source_type":"SOURCE_FILE","target_type":"CODE_SNIPPET","relationship_type":"CONTAINS","extra":"Source file contains code snippet: 22-34","gmt_create":"2026-04-23T21:00:59.719965+08:00","gmt_modified":"2026-04-23T21:00:59.719965+08:00"},{"id":1120,"source_id":"643984fc-5a57-498b-8f25-68cc318d9d82","target_id":"03a65cdcfc173217d12ad8a417f8f033","source_type":"WIKI_ITEM","target_type":"CODE_SNIPPET","relationship_type":"CONTAINS","extra":"Wiki contains code snippet: backend/app/main.py#13-21","gmt_create":"2026-04-23T21:00:59.720372+08:00","gmt_modified":"2026-04-23T21:00:59.720372+08:00"},{"id":1121,"source_id":"9228ff67d4c757a85d9421b71f4b29f5","target_id":"03a65cdcfc173217d12ad8a417f8f033","source_type":"SOURCE_FILE","target_type":"CODE_SNIPPET","relationship_type":"CONTAINS","extra":"Source file contains code snippet: 13-21","gmt_create":"2026-04-23T21:00:59.721352+08:00","gmt_modified":"2026-04-23T21:00:59.721353+08:00"},{"id":1122,"source_id":"643984fc-5a57-498b-8f25-68cc318d9d82","target_id":"6286d4be455dc058c8be2ee4e0d1175a","source_type":"WIKI_ITEM","target_type":"CODE_SNIPPET","relationship_type":"CONTAINS","extra":"Wiki contains code snippet: backend/app/main.py#38-42","gmt_create":"2026-04-23T21:00:59.722016+08:00","gmt_modified":"2026-04-23T21:00:59.722016+08:00"},{"id":1123,"source_id":"643984fc-5a57-498b-8f25-68cc318d9d82","target_id":"3365fa8db33d43bab1d0a614e8af3a70","source_type":"WIKI_ITEM","target_type":"CODE_SNIPPET","relationship_type":"CONTAINS","extra":"Wiki contains code snippet: backend/app/main.py#45-47","gmt_create":"2026-04-23T21:00:59.722511+08:00","gmt_modified":"2026-04-23T21:00:59.722511+08:00"},{"id":1124,"source_id":"9228ff67d4c757a85d9421b71f4b29f5","target_id":"3365fa8db33d43bab1d0a614e8af3a70","source_type":"SOURCE_FILE","target_type":"CODE_SNIPPET","relationship_type":"CONTAINS","extra":"Source file contains code snippet: 45-47","gmt_create":"2026-04-23T21:00:59.724292+08:00","gmt_modified":"2026-04-23T21:00:59.724292+08:00"},{"id":1125,"source_id":"643984fc-5a57-498b-8f25-68cc318d9d82","target_id":"4aad38dfc00a0877bd965c3d0b3c280c","source_type":"WIKI_ITEM","target_type":"CODE_SNIPPET","relationship_type":"CONTAINS","extra":"Wiki contains code snippet: backend/app/schemas/auth.py#7-34","gmt_create":"2026-04-23T21:00:59.725223+08:00","gmt_modified":"2026-04-23T21:00:59.725223+08:00"},{"id":1126,"source_id":"643984fc-5a57-498b-8f25-68cc318d9d82","target_id":"56e46969bdb790a5e8f333184b878d6d","source_type":"WIKI_ITEM","target_type":"CODE_SNIPPET","relationship_type":"CONTAINS","extra":"Wiki contains code snippet: backend/app/models/user.py#11-41","gmt_create":"2026-04-23T21:00:59.725972+08:00","gmt_modified":"2026-04-23T21:00:59.725972+08:00"},{"id":1127,"source_id":"643984fc-5a57-498b-8f25-68cc318d9d82","target_id":"f66d9907b467b110c638bd527efd95c5","source_type":"WIKI_ITEM","target_type":"CODE_SNIPPET","relationship_type":"CONTAINS","extra":"Wiki contains code snippet: backend/app/api/auth.py#1-43","gmt_create":"2026-04-23T21:00:59.727037+08:00","gmt_modified":"2026-04-23T21:00:59.727038+08:00"},{"id":1128,"source_id":"643984fc-5a57-498b-8f25-68cc318d9d82","target_id":"6f637c2b0796ec533aafb3b865c11cf0","source_type":"WIKI_ITEM","target_type":"CODE_SNIPPET","relationship_type":"CONTAINS","extra":"Wiki contains code snippet: backend/app/schemas/auth.py#1-34","gmt_create":"2026-04-23T21:00:59.728108+08:00","gmt_modified":"2026-04-23T21:00:59.728108+08:00"},{"id":1129,"source_id":"e0c0ca66b8b81cf66e078a7ab162c07f","target_id":"6f637c2b0796ec533aafb3b865c11cf0","source_type":"SOURCE_FILE","target_type":"CODE_SNIPPET","relationship_type":"CONTAINS","extra":"Source file contains code snippet: 1-34","gmt_create":"2026-04-23T21:00:59.728891+08:00","gmt_modified":"2026-04-23T21:00:59.728891+08:00"},{"id":1130,"source_id":"643984fc-5a57-498b-8f25-68cc318d9d82","target_id":"136f172c732d0cc130532a4f0df475a4","source_type":"WIKI_ITEM","target_type":"CODE_SNIPPET","relationship_type":"CONTAINS","extra":"Wiki contains code snippet: backend/app/models/user.py#1-41","gmt_create":"2026-04-23T21:00:59.729618+08:00","gmt_modified":"2026-04-23T21:00:59.729618+08:00"},{"id":1131,"source_id":"643984fc-5a57-498b-8f25-68cc318d9d82","target_id":"a698e13bfada239280fc9354ff9e2331","source_type":"WIKI_ITEM","target_type":"CODE_SNIPPET","relationship_type":"CONTAINS","extra":"Wiki contains code snippet: backend/app/config.py#7-8","gmt_create":"2026-04-23T21:00:59.731437+08:00","gmt_modified":"2026-04-23T21:00:59.731438+08:00"},{"id":1132,"source_id":"9ff19022ef915615911280e3c49ed44b","target_id":"a698e13bfada239280fc9354ff9e2331","source_type":"SOURCE_FILE","target_type":"CODE_SNIPPET","relationship_type":"CONTAINS","extra":"Source file contains code snippet: 7-8","gmt_create":"2026-04-23T21:00:59.731927+08:00","gmt_modified":"2026-04-23T21:00:59.731927+08:00"},{"id":1133,"source_id":"643984fc-5a57-498b-8f25-68cc318d9d82","target_id":"37bbab6e4f16db7eac6eee9d05e80e46","source_type":"WIKI_ITEM","target_type":"CODE_SNIPPET","relationship_type":"CONTAINS","extra":"Wiki contains code snippet: README.md#1-3","gmt_create":"2026-04-23T21:00:59.737212+08:00","gmt_modified":"2026-04-23T21:00:59.737212+08:00"},{"id":1134,"source_id":"48a560c49d2b21da327c036ec2934b96","target_id":"37bbab6e4f16db7eac6eee9d05e80e46","source_type":"SOURCE_FILE","target_type":"CODE_SNIPPET","relationship_type":"CONTAINS","extra":"Source file contains code snippet: 1-3","gmt_create":"2026-04-23T21:00:59.737807+08:00","gmt_modified":"2026-04-23T21:00:59.737807+08:00"},{"id":1135,"source_id":"643984fc-5a57-498b-8f25-68cc318d9d82","target_id":"63ecbf5e72a0354028b84eb531a58977","source_type":"WIKI_ITEM","target_type":"CODE_SNIPPET","relationship_type":"CONTAINS","extra":"Wiki contains code snippet: frontend/package.json#11-38","gmt_create":"2026-04-23T21:00:59.738706+08:00","gmt_modified":"2026-04-23T21:00:59.738706+08:00"},{"id":1136,"source_id":"aaf5bce6be82d2f947bfa5c1806de452","target_id":"63ecbf5e72a0354028b84eb531a58977","source_type":"SOURCE_FILE","target_type":"CODE_SNIPPET","relationship_type":"CONTAINS","extra":"Source file contains code snippet: 11-38","gmt_create":"2026-04-23T21:00:59.738981+08:00","gmt_modified":"2026-04-23T21:00:59.738981+08:00"},{"id":1137,"source_id":"643984fc-5a57-498b-8f25-68cc318d9d82","target_id":"bf363deac5ef38c8dc80c73b862e730b","source_type":"WIKI_ITEM","target_type":"CODE_SNIPPET","relationship_type":"CONTAINS","extra":"Wiki contains code snippet: docker-compose.yml#4-34","gmt_create":"2026-04-23T21:00:59.740313+08:00","gmt_modified":"2026-04-23T21:00:59.740313+08:00"},{"id":1138,"source_id":"fc6242433ae9506bcc0bf4cb0dce1413","target_id":"bf363deac5ef38c8dc80c73b862e730b","source_type":"SOURCE_FILE","target_type":"CODE_SNIPPET","relationship_type":"CONTAINS","extra":"Source file contains code snippet: 4-34","gmt_create":"2026-04-23T21:00:59.740555+08:00","gmt_modified":"2026-04-23T21:00:59.740555+08:00"},{"id":1139,"source_id":"643984fc-5a57-498b-8f25-68cc318d9d82","target_id":"c6e94075e5f689bfa2fe16f8cf965203","source_type":"WIKI_ITEM","target_type":"CODE_SNIPPET","relationship_type":"CONTAINS","extra":"Wiki contains code snippet: tests/conftest.py#19-50","gmt_create":"2026-04-23T21:00:59.741293+08:00","gmt_modified":"2026-04-23T21:00:59.741294+08:00"},{"id":1140,"source_id":"0ef1efea889dba3e1f299626df479571","target_id":"c6e94075e5f689bfa2fe16f8cf965203","source_type":"SOURCE_FILE","target_type":"CODE_SNIPPET","relationship_type":"CONTAINS","extra":"Source file contains code snippet: 19-50","gmt_create":"2026-04-23T21:00:59.742478+08:00","gmt_modified":"2026-04-23T21:00:59.742478+08:00"},{"id":1141,"source_id":"643984fc-5a57-498b-8f25-68cc318d9d82","target_id":"1a78f5574add6d07a1d7c947dba3f23d","source_type":"WIKI_ITEM","target_type":"CODE_SNIPPET","relationship_type":"CONTAINS","extra":"Wiki contains code snippet: backend/alembic.ini#115-150","gmt_create":"2026-04-23T21:00:59.743043+08:00","gmt_modified":"2026-04-23T21:00:59.743043+08:00"},{"id":1142,"source_id":"50f2e6bdc4a79e69bd43ea8d6fec67fe","target_id":"1a78f5574add6d07a1d7c947dba3f23d","source_type":"SOURCE_FILE","target_type":"CODE_SNIPPET","relationship_type":"CONTAINS","extra":"Source file contains code snippet: 115-150","gmt_create":"2026-04-23T21:00:59.743435+08:00","gmt_modified":"2026-04-23T21:00:59.743435+08:00"},{"id":1143,"source_id":"643984fc-5a57-498b-8f25-68cc318d9d82","target_id":"f6810849c947471a4b45d7ca01ec8c5f","source_type":"WIKI_ITEM","target_type":"CODE_SNIPPET","relationship_type":"CONTAINS","extra":"Wiki contains code snippet: frontend/tailwind.config.ts#5-9","gmt_create":"2026-04-23T21:00:59.744058+08:00","gmt_modified":"2026-04-23T21:00:59.744059+08:00"},{"id":1144,"source_id":"01056dad8851d3e9bd532eb4cab33792","target_id":"f6810849c947471a4b45d7ca01ec8c5f","source_type":"SOURCE_FILE","target_type":"CODE_SNIPPET","relationship_type":"CONTAINS","extra":"Source file contains code snippet: 5-9","gmt_create":"2026-04-23T21:00:59.744873+08:00","gmt_modified":"2026-04-23T21:00:59.744873+08:00"},{"id":1145,"source_id":"643984fc-5a57-498b-8f25-68cc318d9d82","target_id":"9f6d9941f3b93e29d714bfec7e83434c","source_type":"WIKI_ITEM","target_type":"CODE_SNIPPET","relationship_type":"CONTAINS","extra":"Wiki contains code snippet: backend/app/main.py#30-36","gmt_create":"2026-04-23T21:00:59.745431+08:00","gmt_modified":"2026-04-23T21:00:59.745431+08:00"},{"id":1146,"source_id":"9228ff67d4c757a85d9421b71f4b29f5","target_id":"9f6d9941f3b93e29d714bfec7e83434c","source_type":"SOURCE_FILE","target_type":"CODE_SNIPPET","relationship_type":"CONTAINS","extra":"Source file contains code snippet: 30-36","gmt_create":"2026-04-23T21:00:59.745747+08:00","gmt_modified":"2026-04-23T21:00:59.745747+08:00"},{"id":1147,"source_id":"643984fc-5a57-498b-8f25-68cc318d9d82","target_id":"669d67125dcddb0756f4ff50a43512c6","source_type":"WIKI_ITEM","target_type":"CODE_SNIPPET","relationship_type":"CONTAINS","extra":"Wiki contains code snippet: backend/app/config.py#9-13","gmt_create":"2026-04-23T21:00:59.746227+08:00","gmt_modified":"2026-04-23T21:00:59.746227+08:00"},{"id":1148,"source_id":"9ff19022ef915615911280e3c49ed44b","target_id":"669d67125dcddb0756f4ff50a43512c6","source_type":"SOURCE_FILE","target_type":"CODE_SNIPPET","relationship_type":"CONTAINS","extra":"Source file contains code snippet: 9-13","gmt_create":"2026-04-23T21:00:59.746456+08:00","gmt_modified":"2026-04-23T21:00:59.746456+08:00"},{"id":1149,"source_id":"b0c36b2b-bb03-4624-933d-c1f6a320b7ca","target_id":"0ef1efea889dba3e1f299626df479571","source_type":"WIKI_ITEM","target_type":"SOURCE_FILE","relationship_type":"REFERENCED_BY","extra":"Wiki references source file: tests/conftest.py","gmt_create":"2026-04-23T21:02:44.176751+08:00","gmt_modified":"2026-04-23T21:02:44.176752+08:00"},{"id":1150,"source_id":"b0c36b2b-bb03-4624-933d-c1f6a320b7ca","target_id":"389d631bc6c7111ba411b0b79fca455e","source_type":"WIKI_ITEM","target_type":"SOURCE_FILE","relationship_type":"REFERENCED_BY","extra":"Wiki references source file: tests/test_auth.py","gmt_create":"2026-04-23T21:02:44.178412+08:00","gmt_modified":"2026-04-23T21:02:44.178412+08:00"},{"id":1151,"source_id":"b0c36b2b-bb03-4624-933d-c1f6a320b7ca","target_id":"80a0429cc47931de27ddb17a62b8dd9c","source_type":"WIKI_ITEM","target_type":"SOURCE_FILE","relationship_type":"REFERENCED_BY","extra":"Wiki references source file: tests/test_business_flow.py","gmt_create":"2026-04-23T21:02:44.178822+08:00","gmt_modified":"2026-04-23T21:02:44.178822+08:00"},{"id":1152,"source_id":"b0c36b2b-bb03-4624-933d-c1f6a320b7ca","target_id":"b07a4fb9cecbbd66a6910ccbc7651f19","source_type":"WIKI_ITEM","target_type":"SOURCE_FILE","relationship_type":"REFERENCED_BY","extra":"Wiki references source file: tests/test_citation_engine.py","gmt_create":"2026-04-23T21:02:44.179239+08:00","gmt_modified":"2026-04-23T21:02:44.179239+08:00"},{"id":1153,"source_id":"b0c36b2b-bb03-4624-933d-c1f6a320b7ca","target_id":"42ff5383133d176cec9eb88682483be3","source_type":"WIKI_ITEM","target_type":"SOURCE_FILE","relationship_type":"REFERENCED_BY","extra":"Wiki references source file: tests/test_citations.py","gmt_create":"2026-04-23T21:02:44.180317+08:00","gmt_modified":"2026-04-23T21:02:44.180317+08:00"},{"id":1154,"source_id":"b0c36b2b-bb03-4624-933d-c1f6a320b7ca","target_id":"0613e76b9679be7f998fb8fd8056e686","source_type":"WIKI_ITEM","target_type":"SOURCE_FILE","relationship_type":"REFERENCED_BY","extra":"Wiki references source file: tests/test_queries.py","gmt_create":"2026-04-23T21:02:44.181814+08:00","gmt_modified":"2026-04-23T21:02:44.181814+08:00"},{"id":1155,"source_id":"b0c36b2b-bb03-4624-933d-c1f6a320b7ca","target_id":"b2f0d46a31a5441594f2e777365fc156","source_type":"WIKI_ITEM","target_type":"SOURCE_FILE","relationship_type":"REFERENCED_BY","extra":"Wiki references source file: tests/test_scheduler.py","gmt_create":"2026-04-23T21:02:44.182497+08:00","gmt_modified":"2026-04-23T21:02:44.182497+08:00"},{"id":1156,"source_id":"b0c36b2b-bb03-4624-933d-c1f6a320b7ca","target_id":"9228ff67d4c757a85d9421b71f4b29f5","source_type":"WIKI_ITEM","target_type":"SOURCE_FILE","relationship_type":"REFERENCED_BY","extra":"Wiki references source file: backend/app/main.py","gmt_create":"2026-04-23T21:02:44.183181+08:00","gmt_modified":"2026-04-23T21:02:44.183181+08:00"},{"id":1157,"source_id":"b0c36b2b-bb03-4624-933d-c1f6a320b7ca","target_id":"9d08667997a868fc07c9b4e328e44224","source_type":"WIKI_ITEM","target_type":"SOURCE_FILE","relationship_type":"REFERENCED_BY","extra":"Wiki references source file: backend/app/api/deps.py","gmt_create":"2026-04-23T21:02:44.18439+08:00","gmt_modified":"2026-04-23T21:02:44.184391+08:00"},{"id":1158,"source_id":"b0c36b2b-bb03-4624-933d-c1f6a320b7ca","target_id":"4d2f3847b7c10634733118b70a1aea0b","source_type":"WIKI_ITEM","target_type":"SOURCE_FILE","relationship_type":"REFERENCED_BY","extra":"Wiki references source file: backend/app/services/auth.py","gmt_create":"2026-04-23T21:02:44.185381+08:00","gmt_modified":"2026-04-23T21:02:44.185381+08:00"},{"id":1159,"source_id":"b0c36b2b-bb03-4624-933d-c1f6a320b7ca","target_id":"74040de652d5e57f548bb5c4adc3e1a0","source_type":"WIKI_ITEM","target_type":"SOURCE_FILE","relationship_type":"REFERENCED_BY","extra":"Wiki references source file: backend/app/workers/citation_engine.py","gmt_create":"2026-04-23T21:02:44.186205+08:00","gmt_modified":"2026-04-23T21:02:44.186205+08:00"},{"id":1160,"source_id":"b0c36b2b-bb03-4624-933d-c1f6a320b7ca","target_id":"5cbb1e3f112aeba62a14b0b8999fc0f5","source_type":"WIKI_ITEM","target_type":"SOURCE_FILE","relationship_type":"REFERENCED_BY","extra":"Wiki references source file: backend/app/workers/scheduler.py","gmt_create":"2026-04-23T21:02:44.186821+08:00","gmt_modified":"2026-04-23T21:02:44.186821+08:00"},{"id":1161,"source_id":"b0c36b2b-bb03-4624-933d-c1f6a320b7ca","target_id":"93022c8938ce318f167277cfa65c29a7","source_type":"WIKI_ITEM","target_type":"SOURCE_FILE","relationship_type":"REFERENCED_BY","extra":"Wiki references source file: backend/app/api/auth.py","gmt_create":"2026-04-23T21:02:44.187337+08:00","gmt_modified":"2026-04-23T21:02:44.187337+08:00"},{"id":1162,"source_id":"b0c36b2b-bb03-4624-933d-c1f6a320b7ca","target_id":"7538ffe4902ab6041adb28b19844962a","source_type":"WIKI_ITEM","target_type":"SOURCE_FILE","relationship_type":"REFERENCED_BY","extra":"Wiki references source file: backend/app/api/citations.py","gmt_create":"2026-04-23T21:02:44.187931+08:00","gmt_modified":"2026-04-23T21:02:44.187931+08:00"},{"id":1163,"source_id":"b0c36b2b-bb03-4624-933d-c1f6a320b7ca","target_id":"6b3d903205941aa9391dd90016e1102c","source_type":"WIKI_ITEM","target_type":"SOURCE_FILE","relationship_type":"REFERENCED_BY","extra":"Wiki references source file: backend/app/api/queries.py","gmt_create":"2026-04-23T21:02:44.189534+08:00","gmt_modified":"2026-04-23T21:02:44.189534+08:00"},{"id":1164,"source_id":"b0c36b2b-bb03-4624-933d-c1f6a320b7ca","target_id":"b0c428683c8a3e6922d90ca0d8c2736d","source_type":"WIKI_ITEM","target_type":"SOURCE_FILE","relationship_type":"REFERENCED_BY","extra":"Wiki references source file: backend/app/database.py","gmt_create":"2026-04-23T21:02:44.190082+08:00","gmt_modified":"2026-04-23T21:02:44.190082+08:00"},{"id":1165,"source_id":"b0c36b2b-bb03-4624-933d-c1f6a320b7ca","target_id":"9ff19022ef915615911280e3c49ed44b","source_type":"WIKI_ITEM","target_type":"SOURCE_FILE","relationship_type":"REFERENCED_BY","extra":"Wiki references source file: backend/app/config.py","gmt_create":"2026-04-23T21:02:44.191061+08:00","gmt_modified":"2026-04-23T21:02:44.191061+08:00"},{"id":1166,"source_id":"b0c36b2b-bb03-4624-933d-c1f6a320b7ca","target_id":"290df8332b3d104e5ea8d71dc39315b5","source_type":"WIKI_ITEM","target_type":"CODE_SNIPPET","relationship_type":"CONTAINS","extra":"Wiki contains code snippet: tests/conftest.py#1-123","gmt_create":"2026-04-23T21:02:44.191818+08:00","gmt_modified":"2026-04-23T21:02:44.191818+08:00"},{"id":1167,"source_id":"b0c36b2b-bb03-4624-933d-c1f6a320b7ca","target_id":"85792f0b1e34b5b48b0300aa606ed6e6","source_type":"WIKI_ITEM","target_type":"CODE_SNIPPET","relationship_type":"CONTAINS","extra":"Wiki contains code snippet: backend/app/main.py#1-56","gmt_create":"2026-04-23T21:02:44.193519+08:00","gmt_modified":"2026-04-23T21:02:44.193519+08:00"},{"id":1168,"source_id":"9228ff67d4c757a85d9421b71f4b29f5","target_id":"85792f0b1e34b5b48b0300aa606ed6e6","source_type":"SOURCE_FILE","target_type":"CODE_SNIPPET","relationship_type":"CONTAINS","extra":"Source file contains code snippet: 1-56","gmt_create":"2026-04-23T21:02:44.193893+08:00","gmt_modified":"2026-04-23T21:02:44.193893+08:00"},{"id":1169,"source_id":"b0c36b2b-bb03-4624-933d-c1f6a320b7ca","target_id":"76e6c0abb49fec57cac4892837a143c9","source_type":"WIKI_ITEM","target_type":"CODE_SNIPPET","relationship_type":"CONTAINS","extra":"Wiki contains code snippet: backend/app/api/deps.py#1-43","gmt_create":"2026-04-23T21:02:44.19465+08:00","gmt_modified":"2026-04-23T21:02:44.19465+08:00"},{"id":1170,"source_id":"b0c36b2b-bb03-4624-933d-c1f6a320b7ca","target_id":"f66d9907b467b110c638bd527efd95c5","source_type":"WIKI_ITEM","target_type":"CODE_SNIPPET","relationship_type":"CONTAINS","extra":"Wiki contains code snippet: backend/app/api/auth.py#1-43","gmt_create":"2026-04-23T21:02:44.196035+08:00","gmt_modified":"2026-04-23T21:02:44.196035+08:00"},{"id":1171,"source_id":"b0c36b2b-bb03-4624-933d-c1f6a320b7ca","target_id":"10d1e37bdc9f353c189b7a2fe79dc85e","source_type":"WIKI_ITEM","target_type":"CODE_SNIPPET","relationship_type":"CONTAINS","extra":"Wiki contains code snippet: backend/app/api/queries.py#1-86","gmt_create":"2026-04-23T21:02:44.196664+08:00","gmt_modified":"2026-04-23T21:02:44.196664+08:00"},{"id":1172,"source_id":"b0c36b2b-bb03-4624-933d-c1f6a320b7ca","target_id":"cbd0101fa84d957bcb1baaa623c6b31c","source_type":"WIKI_ITEM","target_type":"CODE_SNIPPET","relationship_type":"CONTAINS","extra":"Wiki contains code snippet: backend/app/api/citations.py#1-78","gmt_create":"2026-04-23T21:02:44.197331+08:00","gmt_modified":"2026-04-23T21:02:44.197331+08:00"},{"id":1173,"source_id":"b0c36b2b-bb03-4624-933d-c1f6a320b7ca","target_id":"116584ea9162c1bc05911f39f9ef82b6","source_type":"WIKI_ITEM","target_type":"CODE_SNIPPET","relationship_type":"CONTAINS","extra":"Wiki contains code snippet: backend/app/workers/citation_engine.py#1-309","gmt_create":"2026-04-23T21:02:44.198546+08:00","gmt_modified":"2026-04-23T21:02:44.198546+08:00"},{"id":1174,"source_id":"b0c36b2b-bb03-4624-933d-c1f6a320b7ca","target_id":"9630036e63fc15cb81b202cf79671aab","source_type":"WIKI_ITEM","target_type":"CODE_SNIPPET","relationship_type":"CONTAINS","extra":"Wiki contains code snippet: backend/app/workers/scheduler.py#1-182","gmt_create":"2026-04-23T21:02:44.201418+08:00","gmt_modified":"2026-04-23T21:02:44.201418+08:00"},{"id":1175,"source_id":"b0c36b2b-bb03-4624-933d-c1f6a320b7ca","target_id":"9bfc041fe426da2eb78353827e8d9163","source_type":"WIKI_ITEM","target_type":"CODE_SNIPPET","relationship_type":"CONTAINS","extra":"Wiki contains code snippet: backend/app/database.py#1-29","gmt_create":"2026-04-23T21:02:44.204845+08:00","gmt_modified":"2026-04-23T21:02:44.204845+08:00"},{"id":1176,"source_id":"b0c36b2b-bb03-4624-933d-c1f6a320b7ca","target_id":"ea655c6d147bc98beb42955d437260cc","source_type":"WIKI_ITEM","target_type":"CODE_SNIPPET","relationship_type":"CONTAINS","extra":"Wiki contains code snippet: backend/app/config.py#1-23","gmt_create":"2026-04-23T21:02:44.206431+08:00","gmt_modified":"2026-04-23T21:02:44.206431+08:00"},{"id":1177,"source_id":"b0c36b2b-bb03-4624-933d-c1f6a320b7ca","target_id":"5ddf0c8d7b38e4f6126a5d85da1dfeda","source_type":"WIKI_ITEM","target_type":"CODE_SNIPPET","relationship_type":"CONTAINS","extra":"Wiki contains code snippet: tests/conftest.py#19-123","gmt_create":"2026-04-23T21:02:44.209024+08:00","gmt_modified":"2026-04-23T21:02:44.209024+08:00"},{"id":1178,"source_id":"b0c36b2b-bb03-4624-933d-c1f6a320b7ca","target_id":"9df233ef1be4b95068ed91bf01083ae7","source_type":"WIKI_ITEM","target_type":"CODE_SNIPPET","relationship_type":"CONTAINS","extra":"Wiki contains code snippet: tests/conftest.py#117-123","gmt_create":"2026-04-23T21:02:44.210394+08:00","gmt_modified":"2026-04-23T21:02:44.210394+08:00"},{"id":1179,"source_id":"b0c36b2b-bb03-4624-933d-c1f6a320b7ca","target_id":"6286d4be455dc058c8be2ee4e0d1175a","source_type":"WIKI_ITEM","target_type":"CODE_SNIPPET","relationship_type":"CONTAINS","extra":"Wiki contains code snippet: backend/app/main.py#38-42","gmt_create":"2026-04-23T21:02:44.211434+08:00","gmt_modified":"2026-04-23T21:02:44.211434+08:00"},{"id":1180,"source_id":"b0c36b2b-bb03-4624-933d-c1f6a320b7ca","target_id":"069243fafe60a85cf16a0ca40fa07180","source_type":"WIKI_ITEM","target_type":"CODE_SNIPPET","relationship_type":"CONTAINS","extra":"Wiki contains code snippet: backend/app/api/deps.py#16-43","gmt_create":"2026-04-23T21:02:44.21293+08:00","gmt_modified":"2026-04-23T21:02:44.21293+08:00"},{"id":1181,"source_id":"b0c36b2b-bb03-4624-933d-c1f6a320b7ca","target_id":"d5a1fb0bd23ce9240fbf79529ef94a45","source_type":"WIKI_ITEM","target_type":"CODE_SNIPPET","relationship_type":"CONTAINS","extra":"Wiki contains code snippet: backend/app/api/auth.py#13-43","gmt_create":"2026-04-23T21:02:44.214312+08:00","gmt_modified":"2026-04-23T21:02:44.214312+08:00"},{"id":1182,"source_id":"b0c36b2b-bb03-4624-933d-c1f6a320b7ca","target_id":"fe70b1fef9f36e73d26d84987e927c7a","source_type":"WIKI_ITEM","target_type":"CODE_SNIPPET","relationship_type":"CONTAINS","extra":"Wiki contains code snippet: backend/app/api/queries.py#15-86","gmt_create":"2026-04-23T21:02:44.214737+08:00","gmt_modified":"2026-04-23T21:02:44.214737+08:00"},{"id":1183,"source_id":"b0c36b2b-bb03-4624-933d-c1f6a320b7ca","target_id":"735aef72b4fe6ca4f407e69b7dda8b43","source_type":"WIKI_ITEM","target_type":"CODE_SNIPPET","relationship_type":"CONTAINS","extra":"Wiki contains code snippet: backend/app/api/citations.py#25-78","gmt_create":"2026-04-23T21:02:44.215146+08:00","gmt_modified":"2026-04-23T21:02:44.215146+08:00"},{"id":1184,"source_id":"b0c36b2b-bb03-4624-933d-c1f6a320b7ca","target_id":"8128dd67cf376d2cadf7c2d3831c380a","source_type":"WIKI_ITEM","target_type":"CODE_SNIPPET","relationship_type":"CONTAINS","extra":"Wiki contains code snippet: backend/app/database.py#23-29","gmt_create":"2026-04-23T21:02:44.215569+08:00","gmt_modified":"2026-04-23T21:02:44.215569+08:00"},{"id":1185,"source_id":"b0c36b2b-bb03-4624-933d-c1f6a320b7ca","target_id":"1721defc3d6206478d3c0692cc821761","source_type":"WIKI_ITEM","target_type":"CODE_SNIPPET","relationship_type":"CONTAINS","extra":"Wiki contains code snippet: tests/test_auth.py#25-104","gmt_create":"2026-04-23T21:02:44.216343+08:00","gmt_modified":"2026-04-23T21:02:44.216343+08:00"},{"id":1186,"source_id":"b0c36b2b-bb03-4624-933d-c1f6a320b7ca","target_id":"753a437d837246ead62b0e16c6331284","source_type":"WIKI_ITEM","target_type":"CODE_SNIPPET","relationship_type":"CONTAINS","extra":"Wiki contains code snippet: backend/app/services/auth.py#37-69","gmt_create":"2026-04-23T21:02:44.217942+08:00","gmt_modified":"2026-04-23T21:02:44.217942+08:00"},{"id":1187,"source_id":"b0c36b2b-bb03-4624-933d-c1f6a320b7ca","target_id":"d820e2daf2ea133a7aa17cdc475e44a4","source_type":"WIKI_ITEM","target_type":"CODE_SNIPPET","relationship_type":"CONTAINS","extra":"Wiki contains code snippet: tests/test_auth.py#1-104","gmt_create":"2026-04-23T21:02:44.218781+08:00","gmt_modified":"2026-04-23T21:02:44.218781+08:00"},{"id":1188,"source_id":"b0c36b2b-bb03-4624-933d-c1f6a320b7ca","target_id":"1a439c5fed6cfd188c646e1614d56371","source_type":"WIKI_ITEM","target_type":"CODE_SNIPPET","relationship_type":"CONTAINS","extra":"Wiki contains code snippet: backend/app/services/auth.py#1-69","gmt_create":"2026-04-23T21:02:44.219529+08:00","gmt_modified":"2026-04-23T21:02:44.219529+08:00"},{"id":1189,"source_id":"b0c36b2b-bb03-4624-933d-c1f6a320b7ca","target_id":"b624be78e3bffd876e403cff2557b088","source_type":"WIKI_ITEM","target_type":"CODE_SNIPPET","relationship_type":"CONTAINS","extra":"Wiki contains code snippet: backend/app/workers/citation_engine.py#19-120","gmt_create":"2026-04-23T21:02:44.220324+08:00","gmt_modified":"2026-04-23T21:02:44.220324+08:00"},{"id":1190,"source_id":"b0c36b2b-bb03-4624-933d-c1f6a320b7ca","target_id":"5c67e2f70283956b2d29a3c1443eb514","source_type":"WIKI_ITEM","target_type":"CODE_SNIPPET","relationship_type":"CONTAINS","extra":"Wiki contains code snippet: backend/app/workers/citation_engine.py#122-146","gmt_create":"2026-04-23T21:02:44.220747+08:00","gmt_modified":"2026-04-23T21:02:44.220748+08:00"},{"id":1191,"source_id":"b0c36b2b-bb03-4624-933d-c1f6a320b7ca","target_id":"309607c54b12a6340edc086ffb4737c9","source_type":"WIKI_ITEM","target_type":"CODE_SNIPPET","relationship_type":"CONTAINS","extra":"Wiki contains code snippet: backend/app/workers/citation_engine.py#148-309","gmt_create":"2026-04-23T21:02:44.221252+08:00","gmt_modified":"2026-04-23T21:02:44.221252+08:00"},{"id":1192,"source_id":"b0c36b2b-bb03-4624-933d-c1f6a320b7ca","target_id":"a57acd9da5287c915ac823784a409292","source_type":"WIKI_ITEM","target_type":"CODE_SNIPPET","relationship_type":"CONTAINS","extra":"Wiki contains code snippet: tests/test_citation_engine.py#1-127","gmt_create":"2026-04-23T21:02:44.221767+08:00","gmt_modified":"2026-04-23T21:02:44.221767+08:00"},{"id":1193,"source_id":"b0c36b2b-bb03-4624-933d-c1f6a320b7ca","target_id":"2a4f741f31f62dce8ad63be2e831f520","source_type":"WIKI_ITEM","target_type":"CODE_SNIPPET","relationship_type":"CONTAINS","extra":"Wiki contains code snippet: tests/test_citations.py#23-93","gmt_create":"2026-04-23T21:02:44.222579+08:00","gmt_modified":"2026-04-23T21:02:44.222579+08:00"},{"id":1194,"source_id":"b0c36b2b-bb03-4624-933d-c1f6a320b7ca","target_id":"692ac240965eff7e66945aa3c4c270f7","source_type":"WIKI_ITEM","target_type":"CODE_SNIPPET","relationship_type":"CONTAINS","extra":"Wiki contains code snippet: tests/test_citations.py#1-93","gmt_create":"2026-04-23T21:02:44.22325+08:00","gmt_modified":"2026-04-23T21:02:44.22325+08:00"},{"id":1195,"source_id":"b0c36b2b-bb03-4624-933d-c1f6a320b7ca","target_id":"32a0a52faca2d8d488e49c63c86075b1","source_type":"WIKI_ITEM","target_type":"CODE_SNIPPET","relationship_type":"CONTAINS","extra":"Wiki contains code snippet: tests/test_queries.py#29-154","gmt_create":"2026-04-23T21:02:44.224171+08:00","gmt_modified":"2026-04-23T21:02:44.224171+08:00"},{"id":1196,"source_id":"b0c36b2b-bb03-4624-933d-c1f6a320b7ca","target_id":"7804331f5f8c1ba5a3b6d9c1ae1c78c1","source_type":"WIKI_ITEM","target_type":"CODE_SNIPPET","relationship_type":"CONTAINS","extra":"Wiki contains code snippet: tests/test_queries.py#1-154","gmt_create":"2026-04-23T21:02:44.224941+08:00","gmt_modified":"2026-04-23T21:02:44.224941+08:00"},{"id":1197,"source_id":"b0c36b2b-bb03-4624-933d-c1f6a320b7ca","target_id":"3a6e1b738967bf8cc651e57f48e2e126","source_type":"WIKI_ITEM","target_type":"CODE_SNIPPET","relationship_type":"CONTAINS","extra":"Wiki contains code snippet: tests/test_business_flow.py#83-126","gmt_create":"2026-04-23T21:02:44.225635+08:00","gmt_modified":"2026-04-23T21:02:44.225635+08:00"},{"id":1198,"source_id":"b0c36b2b-bb03-4624-933d-c1f6a320b7ca","target_id":"b1afd377757f1d0e9bdf87edfff3ad88","source_type":"WIKI_ITEM","target_type":"CODE_SNIPPET","relationship_type":"CONTAINS","extra":"Wiki contains code snippet: tests/test_business_flow.py#131-186","gmt_create":"2026-04-23T21:02:44.226111+08:00","gmt_modified":"2026-04-23T21:02:44.226111+08:00"},{"id":1199,"source_id":"b0c36b2b-bb03-4624-933d-c1f6a320b7ca","target_id":"de05ec7eed033e432991e5a88e1b5a06","source_type":"WIKI_ITEM","target_type":"CODE_SNIPPET","relationship_type":"CONTAINS","extra":"Wiki contains code snippet: tests/test_business_flow.py#192-222","gmt_create":"2026-04-23T21:02:44.22649+08:00","gmt_modified":"2026-04-23T21:02:44.22649+08:00"},{"id":1200,"source_id":"b0c36b2b-bb03-4624-933d-c1f6a320b7ca","target_id":"7fd61a451248b6b129299d6246f711c7","source_type":"WIKI_ITEM","target_type":"CODE_SNIPPET","relationship_type":"CONTAINS","extra":"Wiki contains code snippet: tests/test_business_flow.py#228-296","gmt_create":"2026-04-23T21:02:44.226892+08:00","gmt_modified":"2026-04-23T21:02:44.226892+08:00"},{"id":1201,"source_id":"b0c36b2b-bb03-4624-933d-c1f6a320b7ca","target_id":"53eedffff456a566fa7b0cecc7169f56","source_type":"WIKI_ITEM","target_type":"CODE_SNIPPET","relationship_type":"CONTAINS","extra":"Wiki contains code snippet: tests/test_business_flow.py#1-441","gmt_create":"2026-04-23T21:02:44.227356+08:00","gmt_modified":"2026-04-23T21:02:44.227356+08:00"},{"id":1202,"source_id":"b0c36b2b-bb03-4624-933d-c1f6a320b7ca","target_id":"906f7a8288e38d4244211f3f538fe7b6","source_type":"WIKI_ITEM","target_type":"CODE_SNIPPET","relationship_type":"CONTAINS","extra":"Wiki contains code snippet: backend/app/workers/scheduler.py#27-182","gmt_create":"2026-04-23T21:02:44.227899+08:00","gmt_modified":"2026-04-23T21:02:44.227899+08:00"},{"id":1203,"source_id":"b0c36b2b-bb03-4624-933d-c1f6a320b7ca","target_id":"1647ee2066de2ae59ba8cf88e33c5e02","source_type":"WIKI_ITEM","target_type":"CODE_SNIPPET","relationship_type":"CONTAINS","extra":"Wiki contains code snippet: tests/test_scheduler.py#1-123","gmt_create":"2026-04-23T21:02:44.228365+08:00","gmt_modified":"2026-04-23T21:02:44.228365+08:00"},{"id":1204,"source_id":"643984fc-5a57-498b-8f25-68cc318d9d82","target_id":"13c568d2-dfa7-4d1b-81c0-dfef247cbb67","source_type":"WIKI_ITEM","target_type":"WIKI_ITEM","relationship_type":"PARENT_CHILD","extra":"Wiki parent-child relationship: 643984fc-5a57-498b-8f25-68cc318d9d82 -\u003e 13c568d2-dfa7-4d1b-81c0-dfef247cbb67","gmt_create":"2026-04-23T21:02:45.18694+08:00","gmt_modified":"2026-04-23T21:02:45.18694+08:00"},{"id":1205,"source_id":"643984fc-5a57-498b-8f25-68cc318d9d82","target_id":"222a9371-45c1-4e0d-b1da-e8ada1c501c2","source_type":"WIKI_ITEM","target_type":"WIKI_ITEM","relationship_type":"PARENT_CHILD","extra":"Wiki parent-child relationship: 643984fc-5a57-498b-8f25-68cc318d9d82 -\u003e 222a9371-45c1-4e0d-b1da-e8ada1c501c2","gmt_create":"2026-04-23T21:02:45.187426+08:00","gmt_modified":"2026-04-23T21:02:45.187426+08:00"},{"id":1206,"source_id":"643984fc-5a57-498b-8f25-68cc318d9d82","target_id":"979be617-a83d-4db9-b73e-38581348f8c1","source_type":"WIKI_ITEM","target_type":"WIKI_ITEM","relationship_type":"PARENT_CHILD","extra":"Wiki parent-child relationship: 643984fc-5a57-498b-8f25-68cc318d9d82 -\u003e 979be617-a83d-4db9-b73e-38581348f8c1","gmt_create":"2026-04-23T21:02:45.187832+08:00","gmt_modified":"2026-04-23T21:02:45.187832+08:00"},{"id":1207,"source_id":"643984fc-5a57-498b-8f25-68cc318d9d82","target_id":"422c46b3-e69c-4023-a878-411a48ae182f","source_type":"WIKI_ITEM","target_type":"WIKI_ITEM","relationship_type":"PARENT_CHILD","extra":"Wiki parent-child relationship: 643984fc-5a57-498b-8f25-68cc318d9d82 -\u003e 422c46b3-e69c-4023-a878-411a48ae182f","gmt_create":"2026-04-23T21:02:45.188275+08:00","gmt_modified":"2026-04-23T21:02:45.188275+08:00"},{"id":1208,"source_id":"b0c36b2b-bb03-4624-933d-c1f6a320b7ca","target_id":"8150ddbb-7aa9-48d0-9953-2ef55e4bcfd5","source_type":"WIKI_ITEM","target_type":"WIKI_ITEM","relationship_type":"PARENT_CHILD","extra":"Wiki parent-child relationship: b0c36b2b-bb03-4624-933d-c1f6a320b7ca -\u003e 8150ddbb-7aa9-48d0-9953-2ef55e4bcfd5","gmt_create":"2026-04-23T21:02:45.190159+08:00","gmt_modified":"2026-04-23T21:02:45.190159+08:00"},{"id":1209,"source_id":"b0c36b2b-bb03-4624-933d-c1f6a320b7ca","target_id":"8c17b44f-1586-459b-a83d-c9b961cd2142","source_type":"WIKI_ITEM","target_type":"WIKI_ITEM","relationship_type":"PARENT_CHILD","extra":"Wiki parent-child relationship: b0c36b2b-bb03-4624-933d-c1f6a320b7ca -\u003e 8c17b44f-1586-459b-a83d-c9b961cd2142","gmt_create":"2026-04-23T21:02:45.191275+08:00","gmt_modified":"2026-04-23T21:02:45.191275+08:00"},{"id":1210,"source_id":"b0c36b2b-bb03-4624-933d-c1f6a320b7ca","target_id":"05e59a75-d52f-42e1-a924-f6a32f06f2fe","source_type":"WIKI_ITEM","target_type":"WIKI_ITEM","relationship_type":"PARENT_CHILD","extra":"Wiki parent-child relationship: b0c36b2b-bb03-4624-933d-c1f6a320b7ca -\u003e 05e59a75-d52f-42e1-a924-f6a32f06f2fe","gmt_create":"2026-04-23T21:02:45.191685+08:00","gmt_modified":"2026-04-23T21:02:45.191685+08:00"},{"id":1211,"source_id":"34e572eb-6fc8-4de7-8061-63783ef8be24","target_id":"ed630a36e81abafd12787d4095dfe8c2","source_type":"WIKI_ITEM","target_type":"SOURCE_FILE","relationship_type":"REFERENCED_BY","extra":"Wiki references source file: backend/README.md","gmt_create":"2026-04-24T10:58:35.359267+08:00","gmt_modified":"2026-04-24T10:58:35.359267+08:00"},{"id":1212,"source_id":"34e572eb-6fc8-4de7-8061-63783ef8be24","target_id":"1cafc02d1d722feb4692dab6ae85c09f","source_type":"WIKI_ITEM","target_type":"SOURCE_FILE","relationship_type":"REFERENCED_BY","extra":"Wiki references source file: frontend/README.md","gmt_create":"2026-04-24T10:58:35.360113+08:00","gmt_modified":"2026-04-24T10:58:35.360113+08:00"},{"id":1213,"source_id":"34e572eb-6fc8-4de7-8061-63783ef8be24","target_id":"9228ff67d4c757a85d9421b71f4b29f5","source_type":"WIKI_ITEM","target_type":"SOURCE_FILE","relationship_type":"REFERENCED_BY","extra":"Wiki references source file: backend/app/main.py","gmt_create":"2026-04-24T10:58:35.36047+08:00","gmt_modified":"2026-04-24T10:58:35.36047+08:00"},{"id":1214,"source_id":"34e572eb-6fc8-4de7-8061-63783ef8be24","target_id":"9ff19022ef915615911280e3c49ed44b","source_type":"WIKI_ITEM","target_type":"SOURCE_FILE","relationship_type":"REFERENCED_BY","extra":"Wiki references source file: backend/app/config.py","gmt_create":"2026-04-24T10:58:35.360788+08:00","gmt_modified":"2026-04-24T10:58:35.360788+08:00"},{"id":1215,"source_id":"34e572eb-6fc8-4de7-8061-63783ef8be24","target_id":"5cbb1e3f112aeba62a14b0b8999fc0f5","source_type":"WIKI_ITEM","target_type":"SOURCE_FILE","relationship_type":"REFERENCED_BY","extra":"Wiki references source file: backend/app/workers/scheduler.py","gmt_create":"2026-04-24T10:58:35.361116+08:00","gmt_modified":"2026-04-24T10:58:35.361116+08:00"},{"id":1216,"source_id":"34e572eb-6fc8-4de7-8061-63783ef8be24","target_id":"74040de652d5e57f548bb5c4adc3e1a0","source_type":"WIKI_ITEM","target_type":"SOURCE_FILE","relationship_type":"REFERENCED_BY","extra":"Wiki references source file: backend/app/workers/citation_engine.py","gmt_create":"2026-04-24T10:58:35.385327+08:00","gmt_modified":"2026-04-24T10:58:35.385328+08:00"},{"id":1217,"source_id":"34e572eb-6fc8-4de7-8061-63783ef8be24","target_id":"a16cf42e9559523c4f96ca4c79f9488d","source_type":"WIKI_ITEM","target_type":"SOURCE_FILE","relationship_type":"REFERENCED_BY","extra":"Wiki references source file: backend/app/workers/platforms/base.py","gmt_create":"2026-04-24T10:58:35.386483+08:00","gmt_modified":"2026-04-24T10:58:35.386484+08:00"},{"id":1218,"source_id":"34e572eb-6fc8-4de7-8061-63783ef8be24","target_id":"6b3d903205941aa9391dd90016e1102c","source_type":"WIKI_ITEM","target_type":"SOURCE_FILE","relationship_type":"REFERENCED_BY","extra":"Wiki references source file: backend/app/api/queries.py","gmt_create":"2026-04-24T10:58:35.386836+08:00","gmt_modified":"2026-04-24T10:58:35.386836+08:00"},{"id":1219,"source_id":"34e572eb-6fc8-4de7-8061-63783ef8be24","target_id":"b74caccb06844efcdb14d8324cff65c2","source_type":"WIKI_ITEM","target_type":"SOURCE_FILE","relationship_type":"REFERENCED_BY","extra":"Wiki references source file: backend/app/models/query.py","gmt_create":"2026-04-24T10:58:35.387135+08:00","gmt_modified":"2026-04-24T10:58:35.387135+08:00"},{"id":1220,"source_id":"34e572eb-6fc8-4de7-8061-63783ef8be24","target_id":"b4a81ef789630d0af6a8d50859d01bf3","source_type":"WIKI_ITEM","target_type":"SOURCE_FILE","relationship_type":"REFERENCED_BY","extra":"Wiki references source file: backend/app/models/citation_record.py","gmt_create":"2026-04-24T10:58:35.387467+08:00","gmt_modified":"2026-04-24T10:58:35.387467+08:00"},{"id":1221,"source_id":"34e572eb-6fc8-4de7-8061-63783ef8be24","target_id":"12e2c3d7b9a92dc44a6ee29b85e10df6","source_type":"WIKI_ITEM","target_type":"SOURCE_FILE","relationship_type":"REFERENCED_BY","extra":"Wiki references source file: frontend/app/layout.tsx","gmt_create":"2026-04-24T10:58:35.38776+08:00","gmt_modified":"2026-04-24T10:58:35.38776+08:00"},{"id":1222,"source_id":"34e572eb-6fc8-4de7-8061-63783ef8be24","target_id":"aaf5bce6be82d2f947bfa5c1806de452","source_type":"WIKI_ITEM","target_type":"SOURCE_FILE","relationship_type":"REFERENCED_BY","extra":"Wiki references source file: frontend/package.json","gmt_create":"2026-04-24T10:58:35.388086+08:00","gmt_modified":"2026-04-24T10:58:35.388086+08:00"},{"id":1223,"source_id":"34e572eb-6fc8-4de7-8061-63783ef8be24","target_id":"f1a7d61831cc0a45ac6220294f15c21d","source_type":"WIKI_ITEM","target_type":"SOURCE_FILE","relationship_type":"REFERENCED_BY","extra":"Wiki references source file: frontend/components/charts/platform-chart.tsx","gmt_create":"2026-04-24T10:58:35.388419+08:00","gmt_modified":"2026-04-24T10:58:35.388419+08:00"},{"id":1224,"source_id":"34e572eb-6fc8-4de7-8061-63783ef8be24","target_id":"ef72f0c3cedb9fd9a87352fe493053dc","source_type":"WIKI_ITEM","target_type":"SOURCE_FILE","relationship_type":"REFERENCED_BY","extra":"Wiki references source file: frontend/lib/platforms.ts","gmt_create":"2026-04-24T10:58:35.3887+08:00","gmt_modified":"2026-04-24T10:58:35.3887+08:00"},{"id":1225,"source_id":"34e572eb-6fc8-4de7-8061-63783ef8be24","target_id":"fc6242433ae9506bcc0bf4cb0dce1413","source_type":"WIKI_ITEM","target_type":"SOURCE_FILE","relationship_type":"REFERENCED_BY","extra":"Wiki references source file: docker-compose.yml","gmt_create":"2026-04-24T10:58:35.388982+08:00","gmt_modified":"2026-04-24T10:58:35.388982+08:00"},{"id":1226,"source_id":"34e572eb-6fc8-4de7-8061-63783ef8be24","target_id":"a26ee01cf41da3b956e1650448c156fa","source_type":"WIKI_ITEM","target_type":"SOURCE_FILE","relationship_type":"REFERENCED_BY","extra":"Wiki references source file: backend/requirements.txt","gmt_create":"2026-04-24T10:58:35.389271+08:00","gmt_modified":"2026-04-24T10:58:35.389271+08:00"},{"id":1227,"source_id":"34e572eb-6fc8-4de7-8061-63783ef8be24","target_id":"5d7886d0dc99f81073a578b8aefdd375","source_type":"WIKI_ITEM","target_type":"SOURCE_FILE","relationship_type":"REFERENCED_BY","extra":"Wiki references source file: frontend/lib/api.ts","gmt_create":"2026-04-24T10:58:35.389707+08:00","gmt_modified":"2026-04-24T10:58:35.389707+08:00"},{"id":1228,"source_id":"34e572eb-6fc8-4de7-8061-63783ef8be24","target_id":"d2c1984414de6856ed5b3873c661b712","source_type":"WIKI_ITEM","target_type":"SOURCE_FILE","relationship_type":"REFERENCED_BY","extra":"Wiki references source file: frontend/lib/auth.ts","gmt_create":"2026-04-24T10:58:35.390068+08:00","gmt_modified":"2026-04-24T10:58:35.390068+08:00"},{"id":1229,"source_id":"34e572eb-6fc8-4de7-8061-63783ef8be24","target_id":"0ef1efea889dba3e1f299626df479571","source_type":"WIKI_ITEM","target_type":"SOURCE_FILE","relationship_type":"REFERENCED_BY","extra":"Wiki references source file: tests/conftest.py","gmt_create":"2026-04-24T10:58:35.390413+08:00","gmt_modified":"2026-04-24T10:58:35.390413+08:00"},{"id":1230,"source_id":"34e572eb-6fc8-4de7-8061-63783ef8be24","target_id":"389d631bc6c7111ba411b0b79fca455e","source_type":"WIKI_ITEM","target_type":"SOURCE_FILE","relationship_type":"REFERENCED_BY","extra":"Wiki references source file: tests/test_auth.py","gmt_create":"2026-04-24T10:58:35.390888+08:00","gmt_modified":"2026-04-24T10:58:35.390888+08:00"},{"id":1231,"source_id":"34e572eb-6fc8-4de7-8061-63783ef8be24","target_id":"f240c1067c223a019ba05b0fbd718aa4","source_type":"WIKI_ITEM","target_type":"CODE_SNIPPET","relationship_type":"CONTAINS","extra":"Wiki contains code snippet: backend/app/main.py#1-84","gmt_create":"2026-04-24T10:58:35.39137+08:00","gmt_modified":"2026-04-24T10:58:35.39137+08:00"},{"id":1232,"source_id":"9228ff67d4c757a85d9421b71f4b29f5","target_id":"f240c1067c223a019ba05b0fbd718aa4","source_type":"SOURCE_FILE","target_type":"CODE_SNIPPET","relationship_type":"CONTAINS","extra":"Source file contains code snippet: 1-84","gmt_create":"2026-04-24T10:58:35.391735+08:00","gmt_modified":"2026-04-24T10:58:35.391735+08:00"},{"id":1233,"source_id":"34e572eb-6fc8-4de7-8061-63783ef8be24","target_id":"71f98c8993fb42b108e34a554247869b","source_type":"WIKI_ITEM","target_type":"CODE_SNIPPET","relationship_type":"CONTAINS","extra":"Wiki contains code snippet: backend/app/workers/scheduler.py#1-95","gmt_create":"2026-04-24T10:58:35.393449+08:00","gmt_modified":"2026-04-24T10:58:35.393449+08:00"},{"id":1234,"source_id":"34e572eb-6fc8-4de7-8061-63783ef8be24","target_id":"116584ea9162c1bc05911f39f9ef82b6","source_type":"WIKI_ITEM","target_type":"CODE_SNIPPET","relationship_type":"CONTAINS","extra":"Wiki contains code snippet: backend/app/workers/citation_engine.py#1-309","gmt_create":"2026-04-24T10:58:35.394311+08:00","gmt_modified":"2026-04-24T10:58:35.394312+08:00"},{"id":1235,"source_id":"34e572eb-6fc8-4de7-8061-63783ef8be24","target_id":"48d22eaee09e364a293ad6c4750f5c5a","source_type":"WIKI_ITEM","target_type":"CODE_SNIPPET","relationship_type":"CONTAINS","extra":"Wiki contains code snippet: docker-compose.yml#1-71","gmt_create":"2026-04-24T10:58:35.395171+08:00","gmt_modified":"2026-04-24T10:58:35.395171+08:00"},{"id":1236,"source_id":"34e572eb-6fc8-4de7-8061-63783ef8be24","target_id":"72a110dca58d8152758e2fdab4e94761","source_type":"WIKI_ITEM","target_type":"CODE_SNIPPET","relationship_type":"CONTAINS","extra":"Wiki contains code snippet: backend/app/workers/platforms/base.py#1-18","gmt_create":"2026-04-24T10:58:35.397907+08:00","gmt_modified":"2026-04-24T10:58:35.397907+08:00"},{"id":1237,"source_id":"34e572eb-6fc8-4de7-8061-63783ef8be24","target_id":"10d1e37bdc9f353c189b7a2fe79dc85e","source_type":"WIKI_ITEM","target_type":"CODE_SNIPPET","relationship_type":"CONTAINS","extra":"Wiki contains code snippet: backend/app/api/queries.py#1-86","gmt_create":"2026-04-24T10:58:35.399232+08:00","gmt_modified":"2026-04-24T10:58:35.399232+08:00"},{"id":1238,"source_id":"34e572eb-6fc8-4de7-8061-63783ef8be24","target_id":"6281fff17a86ec1895c64d87c2ae7fb1","source_type":"WIKI_ITEM","target_type":"CODE_SNIPPET","relationship_type":"CONTAINS","extra":"Wiki contains code snippet: backend/app/models/query.py#1-55","gmt_create":"2026-04-24T10:58:35.400157+08:00","gmt_modified":"2026-04-24T10:58:35.400157+08:00"},{"id":1239,"source_id":"34e572eb-6fc8-4de7-8061-63783ef8be24","target_id":"943c18db69a04b3137fba4cebcfea87e","source_type":"WIKI_ITEM","target_type":"CODE_SNIPPET","relationship_type":"CONTAINS","extra":"Wiki contains code snippet: backend/app/models/citation_record.py#1-42","gmt_create":"2026-04-24T10:58:35.400997+08:00","gmt_modified":"2026-04-24T10:58:35.400997+08:00"},{"id":1240,"source_id":"34e572eb-6fc8-4de7-8061-63783ef8be24","target_id":"8a466b0c6eac2ccb54c5da7e13854646","source_type":"WIKI_ITEM","target_type":"CODE_SNIPPET","relationship_type":"CONTAINS","extra":"Wiki contains code snippet: frontend/app/layout.tsx#1-37","gmt_create":"2026-04-24T10:58:35.401612+08:00","gmt_modified":"2026-04-24T10:58:35.401612+08:00"},{"id":1241,"source_id":"34e572eb-6fc8-4de7-8061-63783ef8be24","target_id":"6b9f52af0b6d78c17ff9bbc42d760ea2","source_type":"WIKI_ITEM","target_type":"CODE_SNIPPET","relationship_type":"CONTAINS","extra":"Wiki contains code snippet: frontend/components/charts/platform-chart.tsx#1-68","gmt_create":"2026-04-24T10:58:35.402427+08:00","gmt_modified":"2026-04-24T10:58:35.402427+08:00"},{"id":1242,"source_id":"34e572eb-6fc8-4de7-8061-63783ef8be24","target_id":"a829403082cc3460c01e0110229c53c4","source_type":"WIKI_ITEM","target_type":"CODE_SNIPPET","relationship_type":"CONTAINS","extra":"Wiki contains code snippet: frontend/lib/platforms.ts#1-18","gmt_create":"2026-04-24T10:58:35.409328+08:00","gmt_modified":"2026-04-24T10:58:35.409329+08:00"},{"id":1243,"source_id":"34e572eb-6fc8-4de7-8061-63783ef8be24","target_id":"a9fb75d1fdb833a11b36bc7b298f19be","source_type":"WIKI_ITEM","target_type":"CODE_SNIPPET","relationship_type":"CONTAINS","extra":"Wiki contains code snippet: frontend/lib/api.ts#1-154","gmt_create":"2026-04-24T10:58:35.410752+08:00","gmt_modified":"2026-04-24T10:58:35.410752+08:00"},{"id":1244,"source_id":"5d7886d0dc99f81073a578b8aefdd375","target_id":"a9fb75d1fdb833a11b36bc7b298f19be","source_type":"SOURCE_FILE","target_type":"CODE_SNIPPET","relationship_type":"CONTAINS","extra":"Source file contains code snippet: 1-154","gmt_create":"2026-04-24T10:58:35.411143+08:00","gmt_modified":"2026-04-24T10:58:35.411143+08:00"},{"id":1245,"source_id":"34e572eb-6fc8-4de7-8061-63783ef8be24","target_id":"40325db1cb621a9af027150a8c5cf8e9","source_type":"WIKI_ITEM","target_type":"CODE_SNIPPET","relationship_type":"CONTAINS","extra":"Wiki contains code snippet: frontend/lib/auth.ts#1-73","gmt_create":"2026-04-24T10:58:35.41196+08:00","gmt_modified":"2026-04-24T10:58:35.41196+08:00"},{"id":1246,"source_id":"d2c1984414de6856ed5b3873c661b712","target_id":"40325db1cb621a9af027150a8c5cf8e9","source_type":"SOURCE_FILE","target_type":"CODE_SNIPPET","relationship_type":"CONTAINS","extra":"Source file contains code snippet: 1-73","gmt_create":"2026-04-24T10:58:35.412876+08:00","gmt_modified":"2026-04-24T10:58:35.412876+08:00"},{"id":1247,"source_id":"34e572eb-6fc8-4de7-8061-63783ef8be24","target_id":"ea655c6d147bc98beb42955d437260cc","source_type":"WIKI_ITEM","target_type":"CODE_SNIPPET","relationship_type":"CONTAINS","extra":"Wiki contains code snippet: backend/app/config.py#1-23","gmt_create":"2026-04-24T10:58:35.414212+08:00","gmt_modified":"2026-04-24T10:58:35.414212+08:00"},{"id":1248,"source_id":"34e572eb-6fc8-4de7-8061-63783ef8be24","target_id":"93d8c6a312849c344b6a9713b671840f","source_type":"WIKI_ITEM","target_type":"CODE_SNIPPET","relationship_type":"CONTAINS","extra":"Wiki contains code snippet: backend/requirements.txt#1-39","gmt_create":"2026-04-24T10:58:35.4148+08:00","gmt_modified":"2026-04-24T10:58:35.4148+08:00"},{"id":1249,"source_id":"a26ee01cf41da3b956e1650448c156fa","target_id":"93d8c6a312849c344b6a9713b671840f","source_type":"SOURCE_FILE","target_type":"CODE_SNIPPET","relationship_type":"CONTAINS","extra":"Source file contains code snippet: 1-39","gmt_create":"2026-04-24T10:58:35.415254+08:00","gmt_modified":"2026-04-24T10:58:35.415254+08:00"},{"id":1250,"source_id":"34e572eb-6fc8-4de7-8061-63783ef8be24","target_id":"71a37a516437e94fd82a87efc70a3f16","source_type":"WIKI_ITEM","target_type":"CODE_SNIPPET","relationship_type":"CONTAINS","extra":"Wiki contains code snippet: frontend/package.json#1-40","gmt_create":"2026-04-24T10:58:35.416275+08:00","gmt_modified":"2026-04-24T10:58:35.416275+08:00"},{"id":1251,"source_id":"34e572eb-6fc8-4de7-8061-63783ef8be24","target_id":"844b21a35ae39ead76ff8831eb974e5a","source_type":"WIKI_ITEM","target_type":"CODE_SNIPPET","relationship_type":"CONTAINS","extra":"Wiki contains code snippet: backend/app/main.py#81-84","gmt_create":"2026-04-24T10:58:35.417932+08:00","gmt_modified":"2026-04-24T10:58:35.417932+08:00"},{"id":1252,"source_id":"9228ff67d4c757a85d9421b71f4b29f5","target_id":"844b21a35ae39ead76ff8831eb974e5a","source_type":"SOURCE_FILE","target_type":"CODE_SNIPPET","relationship_type":"CONTAINS","extra":"Source file contains code snippet: 81-84","gmt_create":"2026-04-24T10:58:35.418732+08:00","gmt_modified":"2026-04-24T10:58:35.418732+08:00"},{"id":1253,"source_id":"34e572eb-6fc8-4de7-8061-63783ef8be24","target_id":"3af33bd686ce3d418e31843cac66f58b","source_type":"WIKI_ITEM","target_type":"CODE_SNIPPET","relationship_type":"CONTAINS","extra":"Wiki contains code snippet: backend/README.md#12-67","gmt_create":"2026-04-24T10:58:35.422407+08:00","gmt_modified":"2026-04-24T10:58:35.422407+08:00"},{"id":1254,"source_id":"ed630a36e81abafd12787d4095dfe8c2","target_id":"3af33bd686ce3d418e31843cac66f58b","source_type":"SOURCE_FILE","target_type":"CODE_SNIPPET","relationship_type":"CONTAINS","extra":"Source file contains code snippet: 12-67","gmt_create":"2026-04-24T10:58:35.423436+08:00","gmt_modified":"2026-04-24T10:58:35.423436+08:00"},{"id":1255,"source_id":"34e572eb-6fc8-4de7-8061-63783ef8be24","target_id":"06c6dfcd66159d42fa9b9eafd1e36a04","source_type":"WIKI_ITEM","target_type":"CODE_SNIPPET","relationship_type":"CONTAINS","extra":"Wiki contains code snippet: frontend/README.md#11-34","gmt_create":"2026-04-24T10:58:35.424232+08:00","gmt_modified":"2026-04-24T10:58:35.424232+08:00"},{"id":1256,"source_id":"1cafc02d1d722feb4692dab6ae85c09f","target_id":"06c6dfcd66159d42fa9b9eafd1e36a04","source_type":"SOURCE_FILE","target_type":"CODE_SNIPPET","relationship_type":"CONTAINS","extra":"Source file contains code snippet: 11-34","gmt_create":"2026-04-24T10:58:35.424616+08:00","gmt_modified":"2026-04-24T10:58:35.424616+08:00"},{"id":1257,"source_id":"34e572eb-6fc8-4de7-8061-63783ef8be24","target_id":"903da86dc3fb26783f45f247d60e9534","source_type":"WIKI_ITEM","target_type":"CODE_SNIPPET","relationship_type":"CONTAINS","extra":"Wiki contains code snippet: backend/README.md#69-126","gmt_create":"2026-04-24T10:58:35.426243+08:00","gmt_modified":"2026-04-24T10:58:35.426243+08:00"},{"id":1258,"source_id":"ed630a36e81abafd12787d4095dfe8c2","target_id":"903da86dc3fb26783f45f247d60e9534","source_type":"SOURCE_FILE","target_type":"CODE_SNIPPET","relationship_type":"CONTAINS","extra":"Source file contains code snippet: 69-126","gmt_create":"2026-04-24T10:58:35.426634+08:00","gmt_modified":"2026-04-24T10:58:35.426634+08:00"},{"id":1259,"source_id":"34e572eb-6fc8-4de7-8061-63783ef8be24","target_id":"0ffe337a73c8fb7254f3e48932a8ae7f","source_type":"WIKI_ITEM","target_type":"CODE_SNIPPET","relationship_type":"CONTAINS","extra":"Wiki contains code snippet: backend/README.md#209-234","gmt_create":"2026-04-24T10:58:35.427155+08:00","gmt_modified":"2026-04-24T10:58:35.427155+08:00"},{"id":1260,"source_id":"ed630a36e81abafd12787d4095dfe8c2","target_id":"0ffe337a73c8fb7254f3e48932a8ae7f","source_type":"SOURCE_FILE","target_type":"CODE_SNIPPET","relationship_type":"CONTAINS","extra":"Source file contains code snippet: 209-234","gmt_create":"2026-04-24T10:58:35.427796+08:00","gmt_modified":"2026-04-24T10:58:35.427797+08:00"},{"id":1261,"source_id":"34e572eb-6fc8-4de7-8061-63783ef8be24","target_id":"290df8332b3d104e5ea8d71dc39315b5","source_type":"WIKI_ITEM","target_type":"CODE_SNIPPET","relationship_type":"CONTAINS","extra":"Wiki contains code snippet: tests/conftest.py#1-123","gmt_create":"2026-04-24T10:58:35.428393+08:00","gmt_modified":"2026-04-24T10:58:35.428393+08:00"},{"id":1262,"source_id":"34e572eb-6fc8-4de7-8061-63783ef8be24","target_id":"d820e2daf2ea133a7aa17cdc475e44a4","source_type":"WIKI_ITEM","target_type":"CODE_SNIPPET","relationship_type":"CONTAINS","extra":"Wiki contains code snippet: tests/test_auth.py#1-104","gmt_create":"2026-04-24T10:58:35.429142+08:00","gmt_modified":"2026-04-24T10:58:35.429142+08:00"},{"id":1263,"source_id":"34e572eb-6fc8-4de7-8061-63783ef8be24","target_id":"55369db351eb916a3210b22f3d672162","source_type":"WIKI_ITEM","target_type":"CODE_SNIPPET","relationship_type":"CONTAINS","extra":"Wiki contains code snippet: frontend/README.md#161-170","gmt_create":"2026-04-24T10:58:35.429799+08:00","gmt_modified":"2026-04-24T10:58:35.429799+08:00"},{"id":1264,"source_id":"1cafc02d1d722feb4692dab6ae85c09f","target_id":"55369db351eb916a3210b22f3d672162","source_type":"SOURCE_FILE","target_type":"CODE_SNIPPET","relationship_type":"CONTAINS","extra":"Source file contains code snippet: 161-170","gmt_create":"2026-04-24T10:58:35.430152+08:00","gmt_modified":"2026-04-24T10:58:35.430152+08:00"},{"id":1265,"source_id":"c7eb113b-b503-4d83-be7f-9ccf3350c9d9","target_id":"9228ff67d4c757a85d9421b71f4b29f5","source_type":"WIKI_ITEM","target_type":"SOURCE_FILE","relationship_type":"REFERENCED_BY","extra":"Wiki references source file: backend/app/main.py","gmt_create":"2026-04-24T10:58:51.090576+08:00","gmt_modified":"2026-04-24T10:58:51.090576+08:00"},{"id":1266,"source_id":"c7eb113b-b503-4d83-be7f-9ccf3350c9d9","target_id":"9ff19022ef915615911280e3c49ed44b","source_type":"WIKI_ITEM","target_type":"SOURCE_FILE","relationship_type":"REFERENCED_BY","extra":"Wiki references source file: backend/app/config.py","gmt_create":"2026-04-24T10:58:51.091365+08:00","gmt_modified":"2026-04-24T10:58:51.091365+08:00"},{"id":1267,"source_id":"c7eb113b-b503-4d83-be7f-9ccf3350c9d9","target_id":"b0c428683c8a3e6922d90ca0d8c2736d","source_type":"WIKI_ITEM","target_type":"SOURCE_FILE","relationship_type":"REFERENCED_BY","extra":"Wiki references source file: backend/app/database.py","gmt_create":"2026-04-24T10:58:51.091737+08:00","gmt_modified":"2026-04-24T10:58:51.091737+08:00"},{"id":1268,"source_id":"c7eb113b-b503-4d83-be7f-9ccf3350c9d9","target_id":"93022c8938ce318f167277cfa65c29a7","source_type":"WIKI_ITEM","target_type":"SOURCE_FILE","relationship_type":"REFERENCED_BY","extra":"Wiki references source file: backend/app/api/auth.py","gmt_create":"2026-04-24T10:58:51.092081+08:00","gmt_modified":"2026-04-24T10:58:51.092082+08:00"},{"id":1269,"source_id":"c7eb113b-b503-4d83-be7f-9ccf3350c9d9","target_id":"6b3d903205941aa9391dd90016e1102c","source_type":"WIKI_ITEM","target_type":"SOURCE_FILE","relationship_type":"REFERENCED_BY","extra":"Wiki references source file: backend/app/api/queries.py","gmt_create":"2026-04-24T10:58:51.09262+08:00","gmt_modified":"2026-04-24T10:58:51.092621+08:00"},{"id":1270,"source_id":"c7eb113b-b503-4d83-be7f-9ccf3350c9d9","target_id":"7538ffe4902ab6041adb28b19844962a","source_type":"WIKI_ITEM","target_type":"SOURCE_FILE","relationship_type":"REFERENCED_BY","extra":"Wiki references source file: backend/app/api/citations.py","gmt_create":"2026-04-24T10:58:51.093031+08:00","gmt_modified":"2026-04-24T10:58:51.093032+08:00"},{"id":1271,"source_id":"c7eb113b-b503-4d83-be7f-9ccf3350c9d9","target_id":"9d08667997a868fc07c9b4e328e44224","source_type":"WIKI_ITEM","target_type":"SOURCE_FILE","relationship_type":"REFERENCED_BY","extra":"Wiki references source file: backend/app/api/deps.py","gmt_create":"2026-04-24T10:58:51.093465+08:00","gmt_modified":"2026-04-24T10:58:51.093465+08:00"},{"id":1272,"source_id":"c7eb113b-b503-4d83-be7f-9ccf3350c9d9","target_id":"f26740f2a1532b38c816663a4f665dbf","source_type":"WIKI_ITEM","target_type":"SOURCE_FILE","relationship_type":"REFERENCED_BY","extra":"Wiki references source file: backend/app/api/admin.py","gmt_create":"2026-04-24T10:58:51.094698+08:00","gmt_modified":"2026-04-24T10:58:51.094698+08:00"},{"id":1273,"source_id":"c7eb113b-b503-4d83-be7f-9ccf3350c9d9","target_id":"58901c94d975d87e652a4dc6c8dda656","source_type":"WIKI_ITEM","target_type":"SOURCE_FILE","relationship_type":"REFERENCED_BY","extra":"Wiki references source file: backend/app/api/reports.py","gmt_create":"2026-04-24T10:58:51.095352+08:00","gmt_modified":"2026-04-24T10:58:51.095352+08:00"},{"id":1274,"source_id":"c7eb113b-b503-4d83-be7f-9ccf3350c9d9","target_id":"5386144bf3c668c6fa14481c0d85a214","source_type":"WIKI_ITEM","target_type":"SOURCE_FILE","relationship_type":"REFERENCED_BY","extra":"Wiki references source file: backend/app/api/subscriptions.py","gmt_create":"2026-04-24T10:58:51.09625+08:00","gmt_modified":"2026-04-24T10:58:51.09625+08:00"},{"id":1275,"source_id":"c7eb113b-b503-4d83-be7f-9ccf3350c9d9","target_id":"b44632a0f399b2fe2b4daf295a120ec7","source_type":"WIKI_ITEM","target_type":"SOURCE_FILE","relationship_type":"REFERENCED_BY","extra":"Wiki references source file: backend/app/middleware/logging_middleware.py","gmt_create":"2026-04-24T10:58:51.096695+08:00","gmt_modified":"2026-04-24T10:58:51.096695+08:00"},{"id":1276,"source_id":"c7eb113b-b503-4d83-be7f-9ccf3350c9d9","target_id":"5883a8ef4fc156d76b71ffdb5ecdf232","source_type":"WIKI_ITEM","target_type":"SOURCE_FILE","relationship_type":"REFERENCED_BY","extra":"Wiki references source file: backend/app/middleware/rate_limit.py","gmt_create":"2026-04-24T10:58:51.097182+08:00","gmt_modified":"2026-04-24T10:58:51.097182+08:00"},{"id":1277,"source_id":"c7eb113b-b503-4d83-be7f-9ccf3350c9d9","target_id":"e0c0ca66b8b81cf66e078a7ab162c07f","source_type":"WIKI_ITEM","target_type":"SOURCE_FILE","relationship_type":"REFERENCED_BY","extra":"Wiki references source file: backend/app/schemas/auth.py","gmt_create":"2026-04-24T10:58:51.097544+08:00","gmt_modified":"2026-04-24T10:58:51.097544+08:00"},{"id":1278,"source_id":"c7eb113b-b503-4d83-be7f-9ccf3350c9d9","target_id":"5013cbe89f1c6f03533eb218400cedb0","source_type":"WIKI_ITEM","target_type":"SOURCE_FILE","relationship_type":"REFERENCED_BY","extra":"Wiki references source file: backend/app/schemas/subscription.py","gmt_create":"2026-04-24T10:58:51.097989+08:00","gmt_modified":"2026-04-24T10:58:51.097989+08:00"},{"id":1279,"source_id":"c7eb113b-b503-4d83-be7f-9ccf3350c9d9","target_id":"c59f8c276697a070dffc581fe94d809c","source_type":"WIKI_ITEM","target_type":"SOURCE_FILE","relationship_type":"REFERENCED_BY","extra":"Wiki references source file: backend/app/models/user.py","gmt_create":"2026-04-24T10:58:51.098376+08:00","gmt_modified":"2026-04-24T10:58:51.098376+08:00"},{"id":1280,"source_id":"c7eb113b-b503-4d83-be7f-9ccf3350c9d9","target_id":"b74caccb06844efcdb14d8324cff65c2","source_type":"WIKI_ITEM","target_type":"SOURCE_FILE","relationship_type":"REFERENCED_BY","extra":"Wiki references source file: backend/app/models/query.py","gmt_create":"2026-04-24T10:58:51.098703+08:00","gmt_modified":"2026-04-24T10:58:51.098703+08:00"},{"id":1281,"source_id":"c7eb113b-b503-4d83-be7f-9ccf3350c9d9","target_id":"b4a81ef789630d0af6a8d50859d01bf3","source_type":"WIKI_ITEM","target_type":"SOURCE_FILE","relationship_type":"REFERENCED_BY","extra":"Wiki references source file: backend/app/models/citation_record.py","gmt_create":"2026-04-24T10:58:51.099068+08:00","gmt_modified":"2026-04-24T10:58:51.099068+08:00"},{"id":1282,"source_id":"c7eb113b-b503-4d83-be7f-9ccf3350c9d9","target_id":"bceca00463fe55d3bcafda728f97f723","source_type":"WIKI_ITEM","target_type":"SOURCE_FILE","relationship_type":"REFERENCED_BY","extra":"Wiki references source file: backend/app/models/subscription.py","gmt_create":"2026-04-24T10:58:51.09939+08:00","gmt_modified":"2026-04-24T10:58:51.09939+08:00"},{"id":1283,"source_id":"c7eb113b-b503-4d83-be7f-9ccf3350c9d9","target_id":"069738f21ac2da7349d22683e8c36929","source_type":"WIKI_ITEM","target_type":"SOURCE_FILE","relationship_type":"REFERENCED_BY","extra":"Wiki references source file: backend/app/models/query_task.py","gmt_create":"2026-04-24T10:58:51.099701+08:00","gmt_modified":"2026-04-24T10:58:51.099701+08:00"},{"id":1284,"source_id":"c7eb113b-b503-4d83-be7f-9ccf3350c9d9","target_id":"4d2f3847b7c10634733118b70a1aea0b","source_type":"WIKI_ITEM","target_type":"SOURCE_FILE","relationship_type":"REFERENCED_BY","extra":"Wiki references source file: backend/app/services/auth.py","gmt_create":"2026-04-24T10:58:51.100081+08:00","gmt_modified":"2026-04-24T10:58:51.100081+08:00"},{"id":1285,"source_id":"c7eb113b-b503-4d83-be7f-9ccf3350c9d9","target_id":"3809c5ab912511e0e093ba02a4fc918f","source_type":"WIKI_ITEM","target_type":"SOURCE_FILE","relationship_type":"REFERENCED_BY","extra":"Wiki references source file: backend/app/services/admin.py","gmt_create":"2026-04-24T10:58:51.100379+08:00","gmt_modified":"2026-04-24T10:58:51.100379+08:00"},{"id":1286,"source_id":"c7eb113b-b503-4d83-be7f-9ccf3350c9d9","target_id":"b250fc6c32106a7f3e0c3ad152dfc097","source_type":"WIKI_ITEM","target_type":"SOURCE_FILE","relationship_type":"REFERENCED_BY","extra":"Wiki references source file: backend/app/services/subscription.py","gmt_create":"2026-04-24T10:58:51.100715+08:00","gmt_modified":"2026-04-24T10:58:51.100715+08:00"},{"id":1287,"source_id":"c7eb113b-b503-4d83-be7f-9ccf3350c9d9","target_id":"5cbb1e3f112aeba62a14b0b8999fc0f5","source_type":"WIKI_ITEM","target_type":"SOURCE_FILE","relationship_type":"REFERENCED_BY","extra":"Wiki references source file: backend/app/workers/scheduler.py","gmt_create":"2026-04-24T10:58:51.101009+08:00","gmt_modified":"2026-04-24T10:58:51.101009+08:00"},{"id":1288,"source_id":"c7eb113b-b503-4d83-be7f-9ccf3350c9d9","target_id":"74040de652d5e57f548bb5c4adc3e1a0","source_type":"WIKI_ITEM","target_type":"SOURCE_FILE","relationship_type":"REFERENCED_BY","extra":"Wiki references source file: backend/app/workers/citation_engine.py","gmt_create":"2026-04-24T10:58:51.101343+08:00","gmt_modified":"2026-04-24T10:58:51.101343+08:00"},{"id":1289,"source_id":"c7eb113b-b503-4d83-be7f-9ccf3350c9d9","target_id":"c2747ca16b879bca0f68955534c3c4fc","source_type":"WIKI_ITEM","target_type":"CODE_SNIPPET","relationship_type":"CONTAINS","extra":"Wiki contains code snippet: backend/app/main.py#1-48","gmt_create":"2026-04-24T10:58:51.10249+08:00","gmt_modified":"2026-04-24T10:58:51.10249+08:00"},{"id":1290,"source_id":"c7eb113b-b503-4d83-be7f-9ccf3350c9d9","target_id":"84fbed7d35f7752e2117a74fcaf5f0e9","source_type":"WIKI_ITEM","target_type":"CODE_SNIPPET","relationship_type":"CONTAINS","extra":"Wiki contains code snippet: backend/app/config.py#1-17","gmt_create":"2026-04-24T10:58:51.103065+08:00","gmt_modified":"2026-04-24T10:58:51.103065+08:00"},{"id":1291,"source_id":"c7eb113b-b503-4d83-be7f-9ccf3350c9d9","target_id":"9bfc041fe426da2eb78353827e8d9163","source_type":"WIKI_ITEM","target_type":"CODE_SNIPPET","relationship_type":"CONTAINS","extra":"Wiki contains code snippet: backend/app/database.py#1-29","gmt_create":"2026-04-24T10:58:51.103573+08:00","gmt_modified":"2026-04-24T10:58:51.103573+08:00"},{"id":1292,"source_id":"c7eb113b-b503-4d83-be7f-9ccf3350c9d9","target_id":"6c080aba7d0e611bd4e7f268835b630f","source_type":"WIKI_ITEM","target_type":"CODE_SNIPPET","relationship_type":"CONTAINS","extra":"Wiki contains code snippet: backend/app/middleware/logging_middleware.py#1-24","gmt_create":"2026-04-24T10:58:51.104208+08:00","gmt_modified":"2026-04-24T10:58:51.104208+08:00"},{"id":1293,"source_id":"b44632a0f399b2fe2b4daf295a120ec7","target_id":"6c080aba7d0e611bd4e7f268835b630f","source_type":"SOURCE_FILE","target_type":"CODE_SNIPPET","relationship_type":"CONTAINS","extra":"Source file contains code snippet: 1-24","gmt_create":"2026-04-24T10:58:51.104849+08:00","gmt_modified":"2026-04-24T10:58:51.104849+08:00"},{"id":1294,"source_id":"c7eb113b-b503-4d83-be7f-9ccf3350c9d9","target_id":"a7bba55ddc4dd5d215e881e8432d83ea","source_type":"WIKI_ITEM","target_type":"CODE_SNIPPET","relationship_type":"CONTAINS","extra":"Wiki contains code snippet: backend/app/middleware/rate_limit.py#1-83","gmt_create":"2026-04-24T10:58:51.105316+08:00","gmt_modified":"2026-04-24T10:58:51.105316+08:00"},{"id":1295,"source_id":"5883a8ef4fc156d76b71ffdb5ecdf232","target_id":"a7bba55ddc4dd5d215e881e8432d83ea","source_type":"SOURCE_FILE","target_type":"CODE_SNIPPET","relationship_type":"CONTAINS","extra":"Source file contains code snippet: 1-83","gmt_create":"2026-04-24T10:58:51.105611+08:00","gmt_modified":"2026-04-24T10:58:51.105612+08:00"},{"id":1296,"source_id":"c7eb113b-b503-4d83-be7f-9ccf3350c9d9","target_id":"7c7425c51cc43b8840cefd9764b47204","source_type":"WIKI_ITEM","target_type":"CODE_SNIPPET","relationship_type":"CONTAINS","extra":"Wiki contains code snippet: backend/app/api/admin.py#1-108","gmt_create":"2026-04-24T10:58:51.106015+08:00","gmt_modified":"2026-04-24T10:58:51.106015+08:00"},{"id":1297,"source_id":"f26740f2a1532b38c816663a4f665dbf","target_id":"7c7425c51cc43b8840cefd9764b47204","source_type":"SOURCE_FILE","target_type":"CODE_SNIPPET","relationship_type":"CONTAINS","extra":"Source file contains code snippet: 1-108","gmt_create":"2026-04-24T10:58:51.106317+08:00","gmt_modified":"2026-04-24T10:58:51.106317+08:00"},{"id":1298,"source_id":"c7eb113b-b503-4d83-be7f-9ccf3350c9d9","target_id":"6e4a52820e780e4b42651a8214ad4493","source_type":"WIKI_ITEM","target_type":"CODE_SNIPPET","relationship_type":"CONTAINS","extra":"Wiki contains code snippet: backend/app/api/reports.py#1-75","gmt_create":"2026-04-24T10:58:51.106864+08:00","gmt_modified":"2026-04-24T10:58:51.106864+08:00"},{"id":1299,"source_id":"58901c94d975d87e652a4dc6c8dda656","target_id":"6e4a52820e780e4b42651a8214ad4493","source_type":"SOURCE_FILE","target_type":"CODE_SNIPPET","relationship_type":"CONTAINS","extra":"Source file contains code snippet: 1-75","gmt_create":"2026-04-24T10:58:51.10724+08:00","gmt_modified":"2026-04-24T10:58:51.10724+08:00"},{"id":1300,"source_id":"c7eb113b-b503-4d83-be7f-9ccf3350c9d9","target_id":"4247da3fc00a7e5f8b73775321eccf8e","source_type":"WIKI_ITEM","target_type":"CODE_SNIPPET","relationship_type":"CONTAINS","extra":"Wiki contains code snippet: backend/app/api/subscriptions.py#1-77","gmt_create":"2026-04-24T10:58:51.107736+08:00","gmt_modified":"2026-04-24T10:58:51.107736+08:00"},{"id":1301,"source_id":"5386144bf3c668c6fa14481c0d85a214","target_id":"4247da3fc00a7e5f8b73775321eccf8e","source_type":"SOURCE_FILE","target_type":"CODE_SNIPPET","relationship_type":"CONTAINS","extra":"Source file contains code snippet: 1-77","gmt_create":"2026-04-24T10:58:51.108036+08:00","gmt_modified":"2026-04-24T10:58:51.108036+08:00"},{"id":1302,"source_id":"c7eb113b-b503-4d83-be7f-9ccf3350c9d9","target_id":"9bdd2f6103cf3cc8b3914b9d6d8812fb","source_type":"WIKI_ITEM","target_type":"CODE_SNIPPET","relationship_type":"CONTAINS","extra":"Wiki contains code snippet: backend/app/services/admin.py#1-188","gmt_create":"2026-04-24T10:58:51.10901+08:00","gmt_modified":"2026-04-24T10:58:51.10901+08:00"},{"id":1303,"source_id":"3809c5ab912511e0e093ba02a4fc918f","target_id":"9bdd2f6103cf3cc8b3914b9d6d8812fb","source_type":"SOURCE_FILE","target_type":"CODE_SNIPPET","relationship_type":"CONTAINS","extra":"Source file contains code snippet: 1-188","gmt_create":"2026-04-24T10:58:51.109999+08:00","gmt_modified":"2026-04-24T10:58:51.109999+08:00"},{"id":1304,"source_id":"c7eb113b-b503-4d83-be7f-9ccf3350c9d9","target_id":"557281ca025f76d0dc2db67e56b44053","source_type":"WIKI_ITEM","target_type":"CODE_SNIPPET","relationship_type":"CONTAINS","extra":"Wiki contains code snippet: backend/app/services/subscription.py#1-155","gmt_create":"2026-04-24T10:58:51.110901+08:00","gmt_modified":"2026-04-24T10:58:51.110901+08:00"},{"id":1305,"source_id":"b250fc6c32106a7f3e0c3ad152dfc097","target_id":"557281ca025f76d0dc2db67e56b44053","source_type":"SOURCE_FILE","target_type":"CODE_SNIPPET","relationship_type":"CONTAINS","extra":"Source file contains code snippet: 1-155","gmt_create":"2026-04-24T10:58:51.111471+08:00","gmt_modified":"2026-04-24T10:58:51.111472+08:00"},{"id":1306,"source_id":"c7eb113b-b503-4d83-be7f-9ccf3350c9d9","target_id":"e2d4838e58acc0eee236ef586abab64e","source_type":"WIKI_ITEM","target_type":"CODE_SNIPPET","relationship_type":"CONTAINS","extra":"Wiki contains code snippet: backend/app/main.py#13-48","gmt_create":"2026-04-24T10:58:51.112975+08:00","gmt_modified":"2026-04-24T10:58:51.112975+08:00"},{"id":1307,"source_id":"9228ff67d4c757a85d9421b71f4b29f5","target_id":"e2d4838e58acc0eee236ef586abab64e","source_type":"SOURCE_FILE","target_type":"CODE_SNIPPET","relationship_type":"CONTAINS","extra":"Source file contains code snippet: 13-48","gmt_create":"2026-04-24T10:58:51.113574+08:00","gmt_modified":"2026-04-24T10:58:51.113574+08:00"},{"id":1308,"source_id":"c7eb113b-b503-4d83-be7f-9ccf3350c9d9","target_id":"8aee7654d1f435ab53d8ddaabd269fed","source_type":"WIKI_ITEM","target_type":"CODE_SNIPPET","relationship_type":"CONTAINS","extra":"Wiki contains code snippet: backend/app/database.py#6-29","gmt_create":"2026-04-24T10:58:51.114316+08:00","gmt_modified":"2026-04-24T10:58:51.114317+08:00"},{"id":1309,"source_id":"b0c428683c8a3e6922d90ca0d8c2736d","target_id":"8aee7654d1f435ab53d8ddaabd269fed","source_type":"SOURCE_FILE","target_type":"CODE_SNIPPET","relationship_type":"CONTAINS","extra":"Source file contains code snippet: 6-29","gmt_create":"2026-04-24T10:58:51.114869+08:00","gmt_modified":"2026-04-24T10:58:51.114869+08:00"},{"id":1310,"source_id":"c7eb113b-b503-4d83-be7f-9ccf3350c9d9","target_id":"acd9e6c32084e589d5aeb1665d918dfd","source_type":"WIKI_ITEM","target_type":"CODE_SNIPPET","relationship_type":"CONTAINS","extra":"Wiki contains code snippet: backend/app/api/deps.py#13-43","gmt_create":"2026-04-24T10:58:51.115422+08:00","gmt_modified":"2026-04-24T10:58:51.115422+08:00"},{"id":1311,"source_id":"9d08667997a868fc07c9b4e328e44224","target_id":"acd9e6c32084e589d5aeb1665d918dfd","source_type":"SOURCE_FILE","target_type":"CODE_SNIPPET","relationship_type":"CONTAINS","extra":"Source file contains code snippet: 13-43","gmt_create":"2026-04-24T10:58:51.115783+08:00","gmt_modified":"2026-04-24T10:58:51.115783+08:00"},{"id":1312,"source_id":"c7eb113b-b503-4d83-be7f-9ccf3350c9d9","target_id":"33ec8bca51cb9f667bf91088dd6b6a70","source_type":"WIKI_ITEM","target_type":"CODE_SNIPPET","relationship_type":"CONTAINS","extra":"Wiki contains code snippet: backend/app/main.py#24-48","gmt_create":"2026-04-24T10:58:51.116194+08:00","gmt_modified":"2026-04-24T10:58:51.116194+08:00"},{"id":1313,"source_id":"9228ff67d4c757a85d9421b71f4b29f5","target_id":"33ec8bca51cb9f667bf91088dd6b6a70","source_type":"SOURCE_FILE","target_type":"CODE_SNIPPET","relationship_type":"CONTAINS","extra":"Source file contains code snippet: 24-48","gmt_create":"2026-04-24T10:58:51.116484+08:00","gmt_modified":"2026-04-24T10:58:51.116484+08:00"},{"id":1314,"source_id":"c7eb113b-b503-4d83-be7f-9ccf3350c9d9","target_id":"712424bd3bd3d5f39b1a0a72acc9952a","source_type":"WIKI_ITEM","target_type":"CODE_SNIPPET","relationship_type":"CONTAINS","extra":"Wiki contains code snippet: backend/app/middleware/rate_limit.py#10-83","gmt_create":"2026-04-24T10:58:51.117175+08:00","gmt_modified":"2026-04-24T10:58:51.117175+08:00"},{"id":1315,"source_id":"5883a8ef4fc156d76b71ffdb5ecdf232","target_id":"712424bd3bd3d5f39b1a0a72acc9952a","source_type":"SOURCE_FILE","target_type":"CODE_SNIPPET","relationship_type":"CONTAINS","extra":"Source file contains code snippet: 10-83","gmt_create":"2026-04-24T10:58:51.117511+08:00","gmt_modified":"2026-04-24T10:58:51.117511+08:00"},{"id":1316,"source_id":"c7eb113b-b503-4d83-be7f-9ccf3350c9d9","target_id":"9357a0fcca02068d428f4a191d08fdcd","source_type":"WIKI_ITEM","target_type":"CODE_SNIPPET","relationship_type":"CONTAINS","extra":"Wiki contains code snippet: backend/app/middleware/logging_middleware.py#8-24","gmt_create":"2026-04-24T10:58:51.117972+08:00","gmt_modified":"2026-04-24T10:58:51.117972+08:00"},{"id":1317,"source_id":"b44632a0f399b2fe2b4daf295a120ec7","target_id":"9357a0fcca02068d428f4a191d08fdcd","source_type":"SOURCE_FILE","target_type":"CODE_SNIPPET","relationship_type":"CONTAINS","extra":"Source file contains code snippet: 8-24","gmt_create":"2026-04-24T10:58:51.118728+08:00","gmt_modified":"2026-04-24T10:58:51.118728+08:00"},{"id":1318,"source_id":"c7eb113b-b503-4d83-be7f-9ccf3350c9d9","target_id":"069243fafe60a85cf16a0ca40fa07180","source_type":"WIKI_ITEM","target_type":"CODE_SNIPPET","relationship_type":"CONTAINS","extra":"Wiki contains code snippet: backend/app/api/deps.py#16-43","gmt_create":"2026-04-24T10:58:51.119241+08:00","gmt_modified":"2026-04-24T10:58:51.119241+08:00"},{"id":1319,"source_id":"c7eb113b-b503-4d83-be7f-9ccf3350c9d9","target_id":"8efcce12915471fe5b88fe058bcf238e","source_type":"WIKI_ITEM","target_type":"CODE_SNIPPET","relationship_type":"CONTAINS","extra":"Wiki contains code snippet: backend/app/services/auth.py#16-69","gmt_create":"2026-04-24T10:58:51.119743+08:00","gmt_modified":"2026-04-24T10:58:51.119743+08:00"},{"id":1320,"source_id":"4d2f3847b7c10634733118b70a1aea0b","target_id":"8efcce12915471fe5b88fe058bcf238e","source_type":"SOURCE_FILE","target_type":"CODE_SNIPPET","relationship_type":"CONTAINS","extra":"Source file contains code snippet: 16-69","gmt_create":"2026-04-24T10:58:51.120028+08:00","gmt_modified":"2026-04-24T10:58:51.120028+08:00"},{"id":1321,"source_id":"c7eb113b-b503-4d83-be7f-9ccf3350c9d9","target_id":"7f81ebbdde3496054e6f43f5eef366dc","source_type":"WIKI_ITEM","target_type":"CODE_SNIPPET","relationship_type":"CONTAINS","extra":"Wiki contains code snippet: backend/app/services/admin.py#14-188","gmt_create":"2026-04-24T10:58:51.120577+08:00","gmt_modified":"2026-04-24T10:58:51.120577+08:00"},{"id":1322,"source_id":"3809c5ab912511e0e093ba02a4fc918f","target_id":"7f81ebbdde3496054e6f43f5eef366dc","source_type":"SOURCE_FILE","target_type":"CODE_SNIPPET","relationship_type":"CONTAINS","extra":"Source file contains code snippet: 14-188","gmt_create":"2026-04-24T10:58:51.124562+08:00","gmt_modified":"2026-04-24T10:58:51.124562+08:00"},{"id":1323,"source_id":"c7eb113b-b503-4d83-be7f-9ccf3350c9d9","target_id":"f4d57f9a78585969a006b7451ea8ce84","source_type":"WIKI_ITEM","target_type":"CODE_SNIPPET","relationship_type":"CONTAINS","extra":"Wiki contains code snippet: backend/app/services/subscription.py#69-155","gmt_create":"2026-04-24T10:58:51.125327+08:00","gmt_modified":"2026-04-24T10:58:51.125327+08:00"},{"id":1324,"source_id":"b250fc6c32106a7f3e0c3ad152dfc097","target_id":"f4d57f9a78585969a006b7451ea8ce84","source_type":"SOURCE_FILE","target_type":"CODE_SNIPPET","relationship_type":"CONTAINS","extra":"Source file contains code snippet: 69-155","gmt_create":"2026-04-24T10:58:51.125712+08:00","gmt_modified":"2026-04-24T10:58:51.125712+08:00"},{"id":1325,"source_id":"c7eb113b-b503-4d83-be7f-9ccf3350c9d9","target_id":"e230904202fcf7a861c6f49b84f9f863","source_type":"WIKI_ITEM","target_type":"CODE_SNIPPET","relationship_type":"CONTAINS","extra":"Wiki contains code snippet: backend/app/workers/scheduler.py#25-95","gmt_create":"2026-04-24T10:58:51.126301+08:00","gmt_modified":"2026-04-24T10:58:51.126301+08:00"},{"id":1326,"source_id":"c7eb113b-b503-4d83-be7f-9ccf3350c9d9","target_id":"309607c54b12a6340edc086ffb4737c9","source_type":"WIKI_ITEM","target_type":"CODE_SNIPPET","relationship_type":"CONTAINS","extra":"Wiki contains code snippet: backend/app/workers/citation_engine.py#148-309","gmt_create":"2026-04-24T10:58:51.126941+08:00","gmt_modified":"2026-04-24T10:58:51.126941+08:00"},{"id":1327,"source_id":"c7eb113b-b503-4d83-be7f-9ccf3350c9d9","target_id":"096856da621e23e78422a15e2bfce1f1","source_type":"WIKI_ITEM","target_type":"CODE_SNIPPET","relationship_type":"CONTAINS","extra":"Wiki contains code snippet: backend/app/main.py#13-22","gmt_create":"2026-04-24T10:58:51.127508+08:00","gmt_modified":"2026-04-24T10:58:51.127508+08:00"},{"id":1328,"source_id":"c7eb113b-b503-4d83-be7f-9ccf3350c9d9","target_id":"129b746e71a9013ceb1b0fcc59942b39","source_type":"WIKI_ITEM","target_type":"CODE_SNIPPET","relationship_type":"CONTAINS","extra":"Wiki contains code snippet: backend/app/workers/scheduler.py#86-90","gmt_create":"2026-04-24T10:58:51.128006+08:00","gmt_modified":"2026-04-24T10:58:51.128006+08:00"},{"id":1329,"source_id":"c7eb113b-b503-4d83-be7f-9ccf3350c9d9","target_id":"608c00e1835ad72363ef08796961faca","source_type":"WIKI_ITEM","target_type":"CODE_SNIPPET","relationship_type":"CONTAINS","extra":"Wiki contains code snippet: backend/app/config.py#4-17","gmt_create":"2026-04-24T10:58:51.128784+08:00","gmt_modified":"2026-04-24T10:58:51.128784+08:00"},{"id":1330,"source_id":"9ff19022ef915615911280e3c49ed44b","target_id":"608c00e1835ad72363ef08796961faca","source_type":"SOURCE_FILE","target_type":"CODE_SNIPPET","relationship_type":"CONTAINS","extra":"Source file contains code snippet: 4-17","gmt_create":"2026-04-24T10:58:51.129154+08:00","gmt_modified":"2026-04-24T10:58:51.129154+08:00"},{"id":1331,"source_id":"c7eb113b-b503-4d83-be7f-9ccf3350c9d9","target_id":"d5a1fb0bd23ce9240fbf79529ef94a45","source_type":"WIKI_ITEM","target_type":"CODE_SNIPPET","relationship_type":"CONTAINS","extra":"Wiki contains code snippet: backend/app/api/auth.py#13-43","gmt_create":"2026-04-24T10:58:51.130528+08:00","gmt_modified":"2026-04-24T10:58:51.130528+08:00"},{"id":1332,"source_id":"c7eb113b-b503-4d83-be7f-9ccf3350c9d9","target_id":"753a437d837246ead62b0e16c6331284","source_type":"WIKI_ITEM","target_type":"CODE_SNIPPET","relationship_type":"CONTAINS","extra":"Wiki contains code snippet: backend/app/services/auth.py#37-69","gmt_create":"2026-04-24T10:58:51.131058+08:00","gmt_modified":"2026-04-24T10:58:51.131059+08:00"},{"id":1333,"source_id":"c7eb113b-b503-4d83-be7f-9ccf3350c9d9","target_id":"f66d9907b467b110c638bd527efd95c5","source_type":"WIKI_ITEM","target_type":"CODE_SNIPPET","relationship_type":"CONTAINS","extra":"Wiki contains code snippet: backend/app/api/auth.py#1-43","gmt_create":"2026-04-24T10:58:51.131916+08:00","gmt_modified":"2026-04-24T10:58:51.131916+08:00"},{"id":1334,"source_id":"c7eb113b-b503-4d83-be7f-9ccf3350c9d9","target_id":"6f637c2b0796ec533aafb3b865c11cf0","source_type":"WIKI_ITEM","target_type":"CODE_SNIPPET","relationship_type":"CONTAINS","extra":"Wiki contains code snippet: backend/app/schemas/auth.py#1-34","gmt_create":"2026-04-24T10:58:51.132407+08:00","gmt_modified":"2026-04-24T10:58:51.132407+08:00"},{"id":1335,"source_id":"c7eb113b-b503-4d83-be7f-9ccf3350c9d9","target_id":"56e46969bdb790a5e8f333184b878d6d","source_type":"WIKI_ITEM","target_type":"CODE_SNIPPET","relationship_type":"CONTAINS","extra":"Wiki contains code snippet: backend/app/models/user.py#11-41","gmt_create":"2026-04-24T10:58:51.132958+08:00","gmt_modified":"2026-04-24T10:58:51.132958+08:00"},{"id":1336,"source_id":"c7eb113b-b503-4d83-be7f-9ccf3350c9d9","target_id":"1a439c5fed6cfd188c646e1614d56371","source_type":"WIKI_ITEM","target_type":"CODE_SNIPPET","relationship_type":"CONTAINS","extra":"Wiki contains code snippet: backend/app/services/auth.py#1-69","gmt_create":"2026-04-24T10:58:51.133552+08:00","gmt_modified":"2026-04-24T10:58:51.133552+08:00"},{"id":1337,"source_id":"c7eb113b-b503-4d83-be7f-9ccf3350c9d9","target_id":"76e6c0abb49fec57cac4892837a143c9","source_type":"WIKI_ITEM","target_type":"CODE_SNIPPET","relationship_type":"CONTAINS","extra":"Wiki contains code snippet: backend/app/api/deps.py#1-43","gmt_create":"2026-04-24T10:58:51.134042+08:00","gmt_modified":"2026-04-24T10:58:51.134042+08:00"},{"id":1338,"source_id":"c7eb113b-b503-4d83-be7f-9ccf3350c9d9","target_id":"98c02d9bb7aa6e2b6be5f7381e64fd99","source_type":"WIKI_ITEM","target_type":"CODE_SNIPPET","relationship_type":"CONTAINS","extra":"Wiki contains code snippet: backend/app/api/queries.py#26-39","gmt_create":"2026-04-24T10:58:51.134529+08:00","gmt_modified":"2026-04-24T10:58:51.134529+08:00"},{"id":1339,"source_id":"c7eb113b-b503-4d83-be7f-9ccf3350c9d9","target_id":"10d1e37bdc9f353c189b7a2fe79dc85e","source_type":"WIKI_ITEM","target_type":"CODE_SNIPPET","relationship_type":"CONTAINS","extra":"Wiki contains code snippet: backend/app/api/queries.py#1-86","gmt_create":"2026-04-24T10:58:51.136504+08:00","gmt_modified":"2026-04-24T10:58:51.136504+08:00"},{"id":1340,"source_id":"c7eb113b-b503-4d83-be7f-9ccf3350c9d9","target_id":"cbd0101fa84d957bcb1baaa623c6b31c","source_type":"WIKI_ITEM","target_type":"CODE_SNIPPET","relationship_type":"CONTAINS","extra":"Wiki contains code snippet: backend/app/api/citations.py#1-78","gmt_create":"2026-04-24T10:58:51.13738+08:00","gmt_modified":"2026-04-24T10:58:51.137381+08:00"},{"id":1341,"source_id":"c7eb113b-b503-4d83-be7f-9ccf3350c9d9","target_id":"ec4bf600a513dc2b014c85e141d7582d","source_type":"WIKI_ITEM","target_type":"CODE_SNIPPET","relationship_type":"CONTAINS","extra":"Wiki contains code snippet: backend/app/workers/scheduler.py#51-85","gmt_create":"2026-04-24T10:58:51.138525+08:00","gmt_modified":"2026-04-24T10:58:51.138525+08:00"},{"id":1342,"source_id":"5cbb1e3f112aeba62a14b0b8999fc0f5","target_id":"ec4bf600a513dc2b014c85e141d7582d","source_type":"SOURCE_FILE","target_type":"CODE_SNIPPET","relationship_type":"CONTAINS","extra":"Source file contains code snippet: 51-85","gmt_create":"2026-04-24T10:58:51.139025+08:00","gmt_modified":"2026-04-24T10:58:51.139026+08:00"},{"id":1343,"source_id":"c7eb113b-b503-4d83-be7f-9ccf3350c9d9","target_id":"160b5326537d25444c40a459a01e79c6","source_type":"WIKI_ITEM","target_type":"CODE_SNIPPET","relationship_type":"CONTAINS","extra":"Wiki contains code snippet: backend/app/workers/citation_engine.py#159-234","gmt_create":"2026-04-24T10:58:51.139644+08:00","gmt_modified":"2026-04-24T10:58:51.139644+08:00"},{"id":1344,"source_id":"c7eb113b-b503-4d83-be7f-9ccf3350c9d9","target_id":"71f98c8993fb42b108e34a554247869b","source_type":"WIKI_ITEM","target_type":"CODE_SNIPPET","relationship_type":"CONTAINS","extra":"Wiki contains code snippet: backend/app/workers/scheduler.py#1-95","gmt_create":"2026-04-24T10:58:51.147556+08:00","gmt_modified":"2026-04-24T10:58:51.147556+08:00"},{"id":1345,"source_id":"c7eb113b-b503-4d83-be7f-9ccf3350c9d9","target_id":"116584ea9162c1bc05911f39f9ef82b6","source_type":"WIKI_ITEM","target_type":"CODE_SNIPPET","relationship_type":"CONTAINS","extra":"Wiki contains code snippet: backend/app/workers/citation_engine.py#1-309","gmt_create":"2026-04-24T10:58:51.148531+08:00","gmt_modified":"2026-04-24T10:58:51.148532+08:00"},{"id":1346,"source_id":"c7eb113b-b503-4d83-be7f-9ccf3350c9d9","target_id":"4fb8856be3a581fe8303d11b2284ca29","source_type":"WIKI_ITEM","target_type":"CODE_SNIPPET","relationship_type":"CONTAINS","extra":"Wiki contains code snippet: backend/app/models/query.py#11-55","gmt_create":"2026-04-24T10:58:51.149856+08:00","gmt_modified":"2026-04-24T10:58:51.149856+08:00"},{"id":1347,"source_id":"c7eb113b-b503-4d83-be7f-9ccf3350c9d9","target_id":"fd541971cebf8a7c167d717f5c5d1ff6","source_type":"WIKI_ITEM","target_type":"CODE_SNIPPET","relationship_type":"CONTAINS","extra":"Wiki contains code snippet: backend/app/models/citation_record.py#11-42","gmt_create":"2026-04-24T10:58:51.151182+08:00","gmt_modified":"2026-04-24T10:58:51.151182+08:00"},{"id":1348,"source_id":"c7eb113b-b503-4d83-be7f-9ccf3350c9d9","target_id":"4d323bf0aaf4078f09726dc0890e5955","source_type":"WIKI_ITEM","target_type":"CODE_SNIPPET","relationship_type":"CONTAINS","extra":"Wiki contains code snippet: backend/app/models/subscription.py#11-37","gmt_create":"2026-04-24T10:58:51.152306+08:00","gmt_modified":"2026-04-24T10:58:51.152306+08:00"},{"id":1349,"source_id":"c7eb113b-b503-4d83-be7f-9ccf3350c9d9","target_id":"b84f46f058847733347974841f613688","source_type":"WIKI_ITEM","target_type":"CODE_SNIPPET","relationship_type":"CONTAINS","extra":"Wiki contains code snippet: backend/app/models/query_task.py#11-39","gmt_create":"2026-04-24T10:58:51.153882+08:00","gmt_modified":"2026-04-24T10:58:51.153882+08:00"},{"id":1350,"source_id":"c7eb113b-b503-4d83-be7f-9ccf3350c9d9","target_id":"136f172c732d0cc130532a4f0df475a4","source_type":"WIKI_ITEM","target_type":"CODE_SNIPPET","relationship_type":"CONTAINS","extra":"Wiki contains code snippet: backend/app/models/user.py#1-41","gmt_create":"2026-04-24T10:58:51.154802+08:00","gmt_modified":"2026-04-24T10:58:51.154802+08:00"},{"id":1351,"source_id":"c7eb113b-b503-4d83-be7f-9ccf3350c9d9","target_id":"6281fff17a86ec1895c64d87c2ae7fb1","source_type":"WIKI_ITEM","target_type":"CODE_SNIPPET","relationship_type":"CONTAINS","extra":"Wiki contains code snippet: backend/app/models/query.py#1-55","gmt_create":"2026-04-24T10:58:51.155416+08:00","gmt_modified":"2026-04-24T10:58:51.155416+08:00"},{"id":1352,"source_id":"c7eb113b-b503-4d83-be7f-9ccf3350c9d9","target_id":"943c18db69a04b3137fba4cebcfea87e","source_type":"WIKI_ITEM","target_type":"CODE_SNIPPET","relationship_type":"CONTAINS","extra":"Wiki contains code snippet: backend/app/models/citation_record.py#1-42","gmt_create":"2026-04-24T10:58:51.155991+08:00","gmt_modified":"2026-04-24T10:58:51.155991+08:00"},{"id":1353,"source_id":"c7eb113b-b503-4d83-be7f-9ccf3350c9d9","target_id":"86e37040be1aeb400fab9b529f5404c8","source_type":"WIKI_ITEM","target_type":"CODE_SNIPPET","relationship_type":"CONTAINS","extra":"Wiki contains code snippet: backend/app/models/subscription.py#1-37","gmt_create":"2026-04-24T10:58:51.15701+08:00","gmt_modified":"2026-04-24T10:58:51.15701+08:00"},{"id":1354,"source_id":"c7eb113b-b503-4d83-be7f-9ccf3350c9d9","target_id":"6628e006b8e5ca16160743528b6b0506","source_type":"WIKI_ITEM","target_type":"CODE_SNIPPET","relationship_type":"CONTAINS","extra":"Wiki contains code snippet: backend/app/models/query_task.py#1-39","gmt_create":"2026-04-24T10:58:51.157758+08:00","gmt_modified":"2026-04-24T10:58:51.157758+08:00"},{"id":1355,"source_id":"c7eb113b-b503-4d83-be7f-9ccf3350c9d9","target_id":"9606b8243736b4a6f5ecfe152b2ab6dd","source_type":"WIKI_ITEM","target_type":"CODE_SNIPPET","relationship_type":"CONTAINS","extra":"Wiki contains code snippet: backend/app/middleware/rate_limit.py#34-83","gmt_create":"2026-04-24T10:58:51.158329+08:00","gmt_modified":"2026-04-24T10:58:51.158329+08:00"},{"id":1356,"source_id":"5883a8ef4fc156d76b71ffdb5ecdf232","target_id":"9606b8243736b4a6f5ecfe152b2ab6dd","source_type":"SOURCE_FILE","target_type":"CODE_SNIPPET","relationship_type":"CONTAINS","extra":"Source file contains code snippet: 34-83","gmt_create":"2026-04-24T10:58:51.158662+08:00","gmt_modified":"2026-04-24T10:58:51.158662+08:00"},{"id":1357,"source_id":"c7eb113b-b503-4d83-be7f-9ccf3350c9d9","target_id":"05664cbd35007caa5290760cc1ef1b99","source_type":"WIKI_ITEM","target_type":"CODE_SNIPPET","relationship_type":"CONTAINS","extra":"Wiki contains code snippet: backend/app/api/admin.py#29-108","gmt_create":"2026-04-24T10:58:51.159846+08:00","gmt_modified":"2026-04-24T10:58:51.159846+08:00"},{"id":1358,"source_id":"f26740f2a1532b38c816663a4f665dbf","target_id":"05664cbd35007caa5290760cc1ef1b99","source_type":"SOURCE_FILE","target_type":"CODE_SNIPPET","relationship_type":"CONTAINS","extra":"Source file contains code snippet: 29-108","gmt_create":"2026-04-24T10:58:51.160297+08:00","gmt_modified":"2026-04-24T10:58:51.160297+08:00"},{"id":1359,"source_id":"c7eb113b-b503-4d83-be7f-9ccf3350c9d9","target_id":"3d85cad939ce858f9c6d153d425c19fb","source_type":"WIKI_ITEM","target_type":"CODE_SNIPPET","relationship_type":"CONTAINS","extra":"Wiki contains code snippet: backend/app/services/subscription.py#25-155","gmt_create":"2026-04-24T10:58:51.162467+08:00","gmt_modified":"2026-04-24T10:58:51.162467+08:00"},{"id":1360,"source_id":"b250fc6c32106a7f3e0c3ad152dfc097","target_id":"3d85cad939ce858f9c6d153d425c19fb","source_type":"SOURCE_FILE","target_type":"CODE_SNIPPET","relationship_type":"CONTAINS","extra":"Source file contains code snippet: 25-155","gmt_create":"2026-04-24T10:58:51.163075+08:00","gmt_modified":"2026-04-24T10:58:51.163075+08:00"},{"id":1361,"source_id":"c7eb113b-b503-4d83-be7f-9ccf3350c9d9","target_id":"36769bd305cd5f664fa6e28f82e4b3e7","source_type":"WIKI_ITEM","target_type":"CODE_SNIPPET","relationship_type":"CONTAINS","extra":"Wiki contains code snippet: backend/app/schemas/subscription.py#1-41","gmt_create":"2026-04-24T10:58:51.164182+08:00","gmt_modified":"2026-04-24T10:58:51.164182+08:00"},{"id":1362,"source_id":"5013cbe89f1c6f03533eb218400cedb0","target_id":"36769bd305cd5f664fa6e28f82e4b3e7","source_type":"SOURCE_FILE","target_type":"CODE_SNIPPET","relationship_type":"CONTAINS","extra":"Source file contains code snippet: 1-41","gmt_create":"2026-04-24T10:58:51.164477+08:00","gmt_modified":"2026-04-24T10:58:51.164477+08:00"},{"id":1363,"source_id":"c7eb113b-b503-4d83-be7f-9ccf3350c9d9","target_id":"14c2d098319eeab16c64ff7d1447df6b","source_type":"WIKI_ITEM","target_type":"CODE_SNIPPET","relationship_type":"CONTAINS","extra":"Wiki contains code snippet: backend/app/api/reports.py#18-75","gmt_create":"2026-04-24T10:58:51.165828+08:00","gmt_modified":"2026-04-24T10:58:51.165828+08:00"},{"id":1364,"source_id":"58901c94d975d87e652a4dc6c8dda656","target_id":"14c2d098319eeab16c64ff7d1447df6b","source_type":"SOURCE_FILE","target_type":"CODE_SNIPPET","relationship_type":"CONTAINS","extra":"Source file contains code snippet: 18-75","gmt_create":"2026-04-24T10:58:51.166362+08:00","gmt_modified":"2026-04-24T10:58:51.166363+08:00"},{"id":1365,"source_id":"c7eb113b-b503-4d83-be7f-9ccf3350c9d9","target_id":"eb603ec2611957de67af00756f4b1efa","source_type":"WIKI_ITEM","target_type":"CODE_SNIPPET","relationship_type":"CONTAINS","extra":"Wiki contains code snippet: backend/app/config.py#7-13","gmt_create":"2026-04-24T10:58:51.173515+08:00","gmt_modified":"2026-04-24T10:58:51.173515+08:00"},{"id":1366,"source_id":"c7eb113b-b503-4d83-be7f-9ccf3350c9d9","target_id":"e1d2b027678118df4d0a50ce9269271d","source_type":"WIKI_ITEM","target_type":"CODE_SNIPPET","relationship_type":"CONTAINS","extra":"Wiki contains code snippet: backend/app/workers/scheduler.py#42-90","gmt_create":"2026-04-24T10:58:51.174668+08:00","gmt_modified":"2026-04-24T10:58:51.174668+08:00"},{"id":1367,"source_id":"c7eb113b-b503-4d83-be7f-9ccf3350c9d9","target_id":"38142b7d7016c5590e638fafcdcb1a19","source_type":"WIKI_ITEM","target_type":"CODE_SNIPPET","relationship_type":"CONTAINS","extra":"Wiki contains code snippet: backend/app/workers/citation_engine.py#211-227","gmt_create":"2026-04-24T10:58:51.175216+08:00","gmt_modified":"2026-04-24T10:58:51.175216+08:00"},{"id":1368,"source_id":"ffbb970e-56e0-40ad-bd88-1a1e55482d96","target_id":"b0c428683c8a3e6922d90ca0d8c2736d","source_type":"WIKI_ITEM","target_type":"SOURCE_FILE","relationship_type":"REFERENCED_BY","extra":"Wiki references source file: backend/app/database.py","gmt_create":"2026-04-24T10:59:38.925103+08:00","gmt_modified":"2026-04-24T10:59:38.925103+08:00"},{"id":1369,"source_id":"ffbb970e-56e0-40ad-bd88-1a1e55482d96","target_id":"c59f8c276697a070dffc581fe94d809c","source_type":"WIKI_ITEM","target_type":"SOURCE_FILE","relationship_type":"REFERENCED_BY","extra":"Wiki references source file: backend/app/models/user.py","gmt_create":"2026-04-24T10:59:38.925495+08:00","gmt_modified":"2026-04-24T10:59:38.925495+08:00"},{"id":1370,"source_id":"ffbb970e-56e0-40ad-bd88-1a1e55482d96","target_id":"b74caccb06844efcdb14d8324cff65c2","source_type":"WIKI_ITEM","target_type":"SOURCE_FILE","relationship_type":"REFERENCED_BY","extra":"Wiki references source file: backend/app/models/query.py","gmt_create":"2026-04-24T10:59:38.925816+08:00","gmt_modified":"2026-04-24T10:59:38.925816+08:00"},{"id":1371,"source_id":"ffbb970e-56e0-40ad-bd88-1a1e55482d96","target_id":"b4a81ef789630d0af6a8d50859d01bf3","source_type":"WIKI_ITEM","target_type":"SOURCE_FILE","relationship_type":"REFERENCED_BY","extra":"Wiki references source file: backend/app/models/citation_record.py","gmt_create":"2026-04-24T10:59:38.926111+08:00","gmt_modified":"2026-04-24T10:59:38.926111+08:00"},{"id":1372,"source_id":"ffbb970e-56e0-40ad-bd88-1a1e55482d96","target_id":"069738f21ac2da7349d22683e8c36929","source_type":"WIKI_ITEM","target_type":"SOURCE_FILE","relationship_type":"REFERENCED_BY","extra":"Wiki references source file: backend/app/models/query_task.py","gmt_create":"2026-04-24T10:59:38.926454+08:00","gmt_modified":"2026-04-24T10:59:38.926454+08:00"},{"id":1373,"source_id":"ffbb970e-56e0-40ad-bd88-1a1e55482d96","target_id":"bceca00463fe55d3bcafda728f97f723","source_type":"WIKI_ITEM","target_type":"SOURCE_FILE","relationship_type":"REFERENCED_BY","extra":"Wiki references source file: backend/app/models/subscription.py","gmt_create":"2026-04-24T10:59:38.926763+08:00","gmt_modified":"2026-04-24T10:59:38.926763+08:00"},{"id":1374,"source_id":"ffbb970e-56e0-40ad-bd88-1a1e55482d96","target_id":"99fe1b288fd41daa86c2dfbab819abf0","source_type":"WIKI_ITEM","target_type":"SOURCE_FILE","relationship_type":"REFERENCED_BY","extra":"Wiki references source file: backend/app/models/__init__.py","gmt_create":"2026-04-24T10:59:38.927067+08:00","gmt_modified":"2026-04-24T10:59:38.927067+08:00"},{"id":1375,"source_id":"ffbb970e-56e0-40ad-bd88-1a1e55482d96","target_id":"a680d4819f5da57fe9fa0e6bc708f380","source_type":"WIKI_ITEM","target_type":"SOURCE_FILE","relationship_type":"REFERENCED_BY","extra":"Wiki references source file: backend/alembic/env.py","gmt_create":"2026-04-24T10:59:38.927719+08:00","gmt_modified":"2026-04-24T10:59:38.927719+08:00"},{"id":1376,"source_id":"ffbb970e-56e0-40ad-bd88-1a1e55482d96","target_id":"d4f95fcf50683b5bf6167c7d2a6b126d","source_type":"WIKI_ITEM","target_type":"SOURCE_FILE","relationship_type":"REFERENCED_BY","extra":"Wiki references source file: backend/alembic/versions/488d0bd5ab01_initial_migration.py","gmt_create":"2026-04-24T10:59:38.928116+08:00","gmt_modified":"2026-04-24T10:59:38.928116+08:00"},{"id":1377,"source_id":"ffbb970e-56e0-40ad-bd88-1a1e55482d96","target_id":"f6e6948dd0cdd3894bd9928b21feb979","source_type":"WIKI_ITEM","target_type":"SOURCE_FILE","relationship_type":"REFERENCED_BY","extra":"Wiki references source file: backend/alembic/versions/b2c4d6e8fa10_add_confidence_match_type_to_citation_records.py","gmt_create":"2026-04-24T10:59:38.928438+08:00","gmt_modified":"2026-04-24T10:59:38.928438+08:00"},{"id":1378,"source_id":"ffbb970e-56e0-40ad-bd88-1a1e55482d96","target_id":"b0cb6810919f64006be7aa66b2b76a61","source_type":"WIKI_ITEM","target_type":"SOURCE_FILE","relationship_type":"REFERENCED_BY","extra":"Wiki references source file: backend/alembic/versions/c3d5e7f9ab12_add_user_management_fields.py","gmt_create":"2026-04-24T10:59:38.928749+08:00","gmt_modified":"2026-04-24T10:59:38.928749+08:00"},{"id":1379,"source_id":"ffbb970e-56e0-40ad-bd88-1a1e55482d96","target_id":"50f2e6bdc4a79e69bd43ea8d6fec67fe","source_type":"WIKI_ITEM","target_type":"SOURCE_FILE","relationship_type":"REFERENCED_BY","extra":"Wiki references source file: backend/alembic.ini","gmt_create":"2026-04-24T10:59:38.929055+08:00","gmt_modified":"2026-04-24T10:59:38.929055+08:00"},{"id":1380,"source_id":"ffbb970e-56e0-40ad-bd88-1a1e55482d96","target_id":"9ff19022ef915615911280e3c49ed44b","source_type":"WIKI_ITEM","target_type":"SOURCE_FILE","relationship_type":"REFERENCED_BY","extra":"Wiki references source file: backend/app/config.py","gmt_create":"2026-04-24T10:59:38.929804+08:00","gmt_modified":"2026-04-24T10:59:38.929804+08:00"},{"id":1381,"source_id":"ffbb970e-56e0-40ad-bd88-1a1e55482d96","target_id":"fc6242433ae9506bcc0bf4cb0dce1413","source_type":"WIKI_ITEM","target_type":"SOURCE_FILE","relationship_type":"REFERENCED_BY","extra":"Wiki references source file: docker-compose.yml","gmt_create":"2026-04-24T10:59:38.930168+08:00","gmt_modified":"2026-04-24T10:59:38.930168+08:00"},{"id":1382,"source_id":"ffbb970e-56e0-40ad-bd88-1a1e55482d96","target_id":"88d22de3b2a7419868e8ae19130d860c","source_type":"WIKI_ITEM","target_type":"SOURCE_FILE","relationship_type":"REFERENCED_BY","extra":"Wiki references source file: backend/app/services/query.py","gmt_create":"2026-04-24T10:59:38.930497+08:00","gmt_modified":"2026-04-24T10:59:38.930497+08:00"},{"id":1383,"source_id":"ffbb970e-56e0-40ad-bd88-1a1e55482d96","target_id":"04e3926c080e795713bff683e7dc9d3e","source_type":"WIKI_ITEM","target_type":"SOURCE_FILE","relationship_type":"REFERENCED_BY","extra":"Wiki references source file: backend/app/services/citation.py","gmt_create":"2026-04-24T10:59:38.9308+08:00","gmt_modified":"2026-04-24T10:59:38.9308+08:00"},{"id":1384,"source_id":"ffbb970e-56e0-40ad-bd88-1a1e55482d96","target_id":"4d2f3847b7c10634733118b70a1aea0b","source_type":"WIKI_ITEM","target_type":"SOURCE_FILE","relationship_type":"REFERENCED_BY","extra":"Wiki references source file: backend/app/services/auth.py","gmt_create":"2026-04-24T10:59:38.93116+08:00","gmt_modified":"2026-04-24T10:59:38.93116+08:00"},{"id":1385,"source_id":"ffbb970e-56e0-40ad-bd88-1a1e55482d96","target_id":"e0c0ca66b8b81cf66e078a7ab162c07f","source_type":"WIKI_ITEM","target_type":"SOURCE_FILE","relationship_type":"REFERENCED_BY","extra":"Wiki references source file: backend/app/schemas/auth.py","gmt_create":"2026-04-24T10:59:38.931453+08:00","gmt_modified":"2026-04-24T10:59:38.931453+08:00"},{"id":1386,"source_id":"ffbb970e-56e0-40ad-bd88-1a1e55482d96","target_id":"93022c8938ce318f167277cfa65c29a7","source_type":"WIKI_ITEM","target_type":"SOURCE_FILE","relationship_type":"REFERENCED_BY","extra":"Wiki references source file: backend/app/api/auth.py","gmt_create":"2026-04-24T10:59:38.931762+08:00","gmt_modified":"2026-04-24T10:59:38.931762+08:00"},{"id":1387,"source_id":"ffbb970e-56e0-40ad-bd88-1a1e55482d96","target_id":"7538ffe4902ab6041adb28b19844962a","source_type":"WIKI_ITEM","target_type":"SOURCE_FILE","relationship_type":"REFERENCED_BY","extra":"Wiki references source file: backend/app/api/citations.py","gmt_create":"2026-04-24T10:59:38.932057+08:00","gmt_modified":"2026-04-24T10:59:38.932057+08:00"},{"id":1388,"source_id":"ffbb970e-56e0-40ad-bd88-1a1e55482d96","target_id":"58901c94d975d87e652a4dc6c8dda656","source_type":"WIKI_ITEM","target_type":"SOURCE_FILE","relationship_type":"REFERENCED_BY","extra":"Wiki references source file: backend/app/api/reports.py","gmt_create":"2026-04-24T10:59:38.932387+08:00","gmt_modified":"2026-04-24T10:59:38.932387+08:00"},{"id":1389,"source_id":"ffbb970e-56e0-40ad-bd88-1a1e55482d96","target_id":"ea655c6d147bc98beb42955d437260cc","source_type":"WIKI_ITEM","target_type":"CODE_SNIPPET","relationship_type":"CONTAINS","extra":"Wiki contains code snippet: backend/app/config.py#1-23","gmt_create":"2026-04-24T10:59:38.932782+08:00","gmt_modified":"2026-04-24T10:59:38.932782+08:00"},{"id":1390,"source_id":"ffbb970e-56e0-40ad-bd88-1a1e55482d96","target_id":"9bfc041fe426da2eb78353827e8d9163","source_type":"WIKI_ITEM","target_type":"CODE_SNIPPET","relationship_type":"CONTAINS","extra":"Wiki contains code snippet: backend/app/database.py#1-29","gmt_create":"2026-04-24T10:59:38.933359+08:00","gmt_modified":"2026-04-24T10:59:38.933359+08:00"},{"id":1391,"source_id":"ffbb970e-56e0-40ad-bd88-1a1e55482d96","target_id":"1f8d26b6a5da49d89d95bb13c7ace2c6","source_type":"WIKI_ITEM","target_type":"CODE_SNIPPET","relationship_type":"CONTAINS","extra":"Wiki contains code snippet: backend/app/models/user.py#1-48","gmt_create":"2026-04-24T10:59:38.93393+08:00","gmt_modified":"2026-04-24T10:59:38.93393+08:00"},{"id":1392,"source_id":"c59f8c276697a070dffc581fe94d809c","target_id":"1f8d26b6a5da49d89d95bb13c7ace2c6","source_type":"SOURCE_FILE","target_type":"CODE_SNIPPET","relationship_type":"CONTAINS","extra":"Source file contains code snippet: 1-48","gmt_create":"2026-04-24T10:59:38.934235+08:00","gmt_modified":"2026-04-24T10:59:38.934235+08:00"},{"id":1393,"source_id":"ffbb970e-56e0-40ad-bd88-1a1e55482d96","target_id":"6281fff17a86ec1895c64d87c2ae7fb1","source_type":"WIKI_ITEM","target_type":"CODE_SNIPPET","relationship_type":"CONTAINS","extra":"Wiki contains code snippet: backend/app/models/query.py#1-55","gmt_create":"2026-04-24T10:59:38.934687+08:00","gmt_modified":"2026-04-24T10:59:38.934687+08:00"},{"id":1394,"source_id":"ffbb970e-56e0-40ad-bd88-1a1e55482d96","target_id":"d4f99d3dd9fe489c354edf5fe2f8803d","source_type":"WIKI_ITEM","target_type":"CODE_SNIPPET","relationship_type":"CONTAINS","extra":"Wiki contains code snippet: backend/app/models/citation_record.py#1-44","gmt_create":"2026-04-24T10:59:38.93518+08:00","gmt_modified":"2026-04-24T10:59:38.93518+08:00"},{"id":1395,"source_id":"ffbb970e-56e0-40ad-bd88-1a1e55482d96","target_id":"6628e006b8e5ca16160743528b6b0506","source_type":"WIKI_ITEM","target_type":"CODE_SNIPPET","relationship_type":"CONTAINS","extra":"Wiki contains code snippet: backend/app/models/query_task.py#1-39","gmt_create":"2026-04-24T10:59:38.935665+08:00","gmt_modified":"2026-04-24T10:59:38.935666+08:00"},{"id":1396,"source_id":"ffbb970e-56e0-40ad-bd88-1a1e55482d96","target_id":"86e37040be1aeb400fab9b529f5404c8","source_type":"WIKI_ITEM","target_type":"CODE_SNIPPET","relationship_type":"CONTAINS","extra":"Wiki contains code snippet: backend/app/models/subscription.py#1-37","gmt_create":"2026-04-24T10:59:38.936197+08:00","gmt_modified":"2026-04-24T10:59:38.936197+08:00"},{"id":1397,"source_id":"ffbb970e-56e0-40ad-bd88-1a1e55482d96","target_id":"211463f5b49610f09594c40c0a235943","source_type":"WIKI_ITEM","target_type":"CODE_SNIPPET","relationship_type":"CONTAINS","extra":"Wiki contains code snippet: backend/alembic/env.py#1-89","gmt_create":"2026-04-24T10:59:38.936699+08:00","gmt_modified":"2026-04-24T10:59:38.936699+08:00"},{"id":1398,"source_id":"ffbb970e-56e0-40ad-bd88-1a1e55482d96","target_id":"48d22eaee09e364a293ad6c4750f5c5a","source_type":"WIKI_ITEM","target_type":"CODE_SNIPPET","relationship_type":"CONTAINS","extra":"Wiki contains code snippet: docker-compose.yml#1-71","gmt_create":"2026-04-24T10:59:38.937893+08:00","gmt_modified":"2026-04-24T10:59:38.937893+08:00"},{"id":1399,"source_id":"ffbb970e-56e0-40ad-bd88-1a1e55482d96","target_id":"afe4138895492c26aac5c0120ef46cd8","source_type":"WIKI_ITEM","target_type":"CODE_SNIPPET","relationship_type":"CONTAINS","extra":"Wiki contains code snippet: backend/app/models/__init__.py#1-14","gmt_create":"2026-04-24T10:59:38.93994+08:00","gmt_modified":"2026-04-24T10:59:38.93994+08:00"},{"id":1400,"source_id":"ffbb970e-56e0-40ad-bd88-1a1e55482d96","target_id":"98cc82f62b83678f06a33cf9231ecdf8","source_type":"WIKI_ITEM","target_type":"CODE_SNIPPET","relationship_type":"CONTAINS","extra":"Wiki contains code snippet: backend/alembic/versions/488d0bd5ab01_initial_migration.py#1-128","gmt_create":"2026-04-24T10:59:38.940473+08:00","gmt_modified":"2026-04-24T10:59:38.940474+08:00"},{"id":1401,"source_id":"ffbb970e-56e0-40ad-bd88-1a1e55482d96","target_id":"e1aabd52989e47806fb997157381e1cf","source_type":"WIKI_ITEM","target_type":"CODE_SNIPPET","relationship_type":"CONTAINS","extra":"Wiki contains code snippet: backend/alembic/versions/b2c4d6e8fa10_add_confidence_match_type_to_citation_records.py#1-37","gmt_create":"2026-04-24T10:59:38.941718+08:00","gmt_modified":"2026-04-24T10:59:38.941719+08:00"},{"id":1402,"source_id":"ffbb970e-56e0-40ad-bd88-1a1e55482d96","target_id":"c8f2dbcb7475bd189a34c7061ea46c6d","source_type":"WIKI_ITEM","target_type":"CODE_SNIPPET","relationship_type":"CONTAINS","extra":"Wiki contains code snippet: backend/alembic/versions/c3d5e7f9ab12_add_user_management_fields.py#1-41","gmt_create":"2026-04-24T10:59:38.943509+08:00","gmt_modified":"2026-04-24T10:59:38.943509+08:00"},{"id":1403,"source_id":"b0cb6810919f64006be7aa66b2b76a61","target_id":"c8f2dbcb7475bd189a34c7061ea46c6d","source_type":"SOURCE_FILE","target_type":"CODE_SNIPPET","relationship_type":"CONTAINS","extra":"Source file contains code snippet: 1-41","gmt_create":"2026-04-24T10:59:38.943933+08:00","gmt_modified":"2026-04-24T10:59:38.943933+08:00"},{"id":1404,"source_id":"ffbb970e-56e0-40ad-bd88-1a1e55482d96","target_id":"916551131bd9ac8c9f9c8bb762af1fa4","source_type":"WIKI_ITEM","target_type":"CODE_SNIPPET","relationship_type":"CONTAINS","extra":"Wiki contains code snippet: backend/app/services/query.py#1-130","gmt_create":"2026-04-24T10:59:38.944411+08:00","gmt_modified":"2026-04-24T10:59:38.944411+08:00"},{"id":1405,"source_id":"ffbb970e-56e0-40ad-bd88-1a1e55482d96","target_id":"5d2836286eb7d4eb6039b004a9744d26","source_type":"WIKI_ITEM","target_type":"CODE_SNIPPET","relationship_type":"CONTAINS","extra":"Wiki contains code snippet: backend/app/services/citation.py#1-429","gmt_create":"2026-04-24T10:59:38.945012+08:00","gmt_modified":"2026-04-24T10:59:38.945012+08:00"},{"id":1406,"source_id":"ffbb970e-56e0-40ad-bd88-1a1e55482d96","target_id":"08c1475254a5bc8877ff29a895de3b6a","source_type":"WIKI_ITEM","target_type":"CODE_SNIPPET","relationship_type":"CONTAINS","extra":"Wiki contains code snippet: backend/app/services/auth.py#1-175","gmt_create":"2026-04-24T10:59:38.945794+08:00","gmt_modified":"2026-04-24T10:59:38.945794+08:00"},{"id":1407,"source_id":"4d2f3847b7c10634733118b70a1aea0b","target_id":"08c1475254a5bc8877ff29a895de3b6a","source_type":"SOURCE_FILE","target_type":"CODE_SNIPPET","relationship_type":"CONTAINS","extra":"Source file contains code snippet: 1-175","gmt_create":"2026-04-24T10:59:38.9463+08:00","gmt_modified":"2026-04-24T10:59:38.9463+08:00"},{"id":1408,"source_id":"ffbb970e-56e0-40ad-bd88-1a1e55482d96","target_id":"f5978358d04c3c917d9ca5044c7f36fa","source_type":"WIKI_ITEM","target_type":"CODE_SNIPPET","relationship_type":"CONTAINS","extra":"Wiki contains code snippet: backend/app/models/user.py#11-48","gmt_create":"2026-04-24T10:59:38.947657+08:00","gmt_modified":"2026-04-24T10:59:38.947657+08:00"},{"id":1409,"source_id":"c59f8c276697a070dffc581fe94d809c","target_id":"f5978358d04c3c917d9ca5044c7f36fa","source_type":"SOURCE_FILE","target_type":"CODE_SNIPPET","relationship_type":"CONTAINS","extra":"Source file contains code snippet: 11-48","gmt_create":"2026-04-24T10:59:38.947981+08:00","gmt_modified":"2026-04-24T10:59:38.947981+08:00"},{"id":1410,"source_id":"ffbb970e-56e0-40ad-bd88-1a1e55482d96","target_id":"bfdf3479f244dc6794628d9df10ab6d0","source_type":"WIKI_ITEM","target_type":"CODE_SNIPPET","relationship_type":"CONTAINS","extra":"Wiki contains code snippet: backend/app/models/query.py#11-48","gmt_create":"2026-04-24T10:59:38.948384+08:00","gmt_modified":"2026-04-24T10:59:38.948384+08:00"},{"id":1411,"source_id":"ffbb970e-56e0-40ad-bd88-1a1e55482d96","target_id":"f5f9f0d96263ae84631c7a8d7e9b3648","source_type":"WIKI_ITEM","target_type":"CODE_SNIPPET","relationship_type":"CONTAINS","extra":"Wiki contains code snippet: backend/app/models/citation_record.py#11-44","gmt_create":"2026-04-24T10:59:38.948988+08:00","gmt_modified":"2026-04-24T10:59:38.948988+08:00"},{"id":1412,"source_id":"ffbb970e-56e0-40ad-bd88-1a1e55482d96","target_id":"818d1354dc0665798f3d91a2ca5153d6","source_type":"WIKI_ITEM","target_type":"CODE_SNIPPET","relationship_type":"CONTAINS","extra":"Wiki contains code snippet: backend/app/models/query_task.py#11-34","gmt_create":"2026-04-24T10:59:38.949513+08:00","gmt_modified":"2026-04-24T10:59:38.949513+08:00"},{"id":1413,"source_id":"ffbb970e-56e0-40ad-bd88-1a1e55482d96","target_id":"24aade4c34609a8ab28e4643a3692201","source_type":"WIKI_ITEM","target_type":"CODE_SNIPPET","relationship_type":"CONTAINS","extra":"Wiki contains code snippet: backend/app/models/subscription.py#11-36","gmt_create":"2026-04-24T10:59:38.950006+08:00","gmt_modified":"2026-04-24T10:59:38.950006+08:00"},{"id":1414,"source_id":"ffbb970e-56e0-40ad-bd88-1a1e55482d96","target_id":"ac77e4875817616194b7b5997d4fb1ae","source_type":"WIKI_ITEM","target_type":"CODE_SNIPPET","relationship_type":"CONTAINS","extra":"Wiki contains code snippet: backend/alembic/versions/488d0bd5ab01_initial_migration.py#57-94","gmt_create":"2026-04-24T10:59:38.951919+08:00","gmt_modified":"2026-04-24T10:59:38.951919+08:00"},{"id":1415,"source_id":"ffbb970e-56e0-40ad-bd88-1a1e55482d96","target_id":"0e57efd98dacc85da21f995980371ee4","source_type":"WIKI_ITEM","target_type":"CODE_SNIPPET","relationship_type":"CONTAINS","extra":"Wiki contains code snippet: backend/alembic/versions/b2c4d6e8fa10_add_confidence_match_type_to_citation_records.py#21-37","gmt_create":"2026-04-24T10:59:38.952471+08:00","gmt_modified":"2026-04-24T10:59:38.952471+08:00"},{"id":1416,"source_id":"ffbb970e-56e0-40ad-bd88-1a1e55482d96","target_id":"675ab6c1ae510ca753b5e966b7b6a10c","source_type":"WIKI_ITEM","target_type":"CODE_SNIPPET","relationship_type":"CONTAINS","extra":"Wiki contains code snippet: backend/alembic/versions/c3d5e7f9ab12_add_user_management_fields.py#21-41","gmt_create":"2026-04-24T10:59:38.953364+08:00","gmt_modified":"2026-04-24T10:59:38.953364+08:00"},{"id":1417,"source_id":"b0cb6810919f64006be7aa66b2b76a61","target_id":"675ab6c1ae510ca753b5e966b7b6a10c","source_type":"SOURCE_FILE","target_type":"CODE_SNIPPET","relationship_type":"CONTAINS","extra":"Source file contains code snippet: 21-41","gmt_create":"2026-04-24T10:59:38.954222+08:00","gmt_modified":"2026-04-24T10:59:38.954223+08:00"},{"id":1418,"source_id":"ffbb970e-56e0-40ad-bd88-1a1e55482d96","target_id":"ed527c7a549ec333c2b30b59614343df","source_type":"WIKI_ITEM","target_type":"CODE_SNIPPET","relationship_type":"CONTAINS","extra":"Wiki contains code snippet: backend/app/models/query.py#50-54","gmt_create":"2026-04-24T10:59:38.954734+08:00","gmt_modified":"2026-04-24T10:59:38.954734+08:00"},{"id":1419,"source_id":"ffbb970e-56e0-40ad-bd88-1a1e55482d96","target_id":"717eb27184726e4f78d694984d29420c","source_type":"WIKI_ITEM","target_type":"CODE_SNIPPET","relationship_type":"CONTAINS","extra":"Wiki contains code snippet: backend/app/models/citation_record.py#37-44","gmt_create":"2026-04-24T10:59:38.955244+08:00","gmt_modified":"2026-04-24T10:59:38.955244+08:00"},{"id":1420,"source_id":"ffbb970e-56e0-40ad-bd88-1a1e55482d96","target_id":"f6c9f1b4e8646c366a31426a4537675d","source_type":"WIKI_ITEM","target_type":"CODE_SNIPPET","relationship_type":"CONTAINS","extra":"Wiki contains code snippet: backend/app/models/query_task.py#36-38","gmt_create":"2026-04-24T10:59:38.95576+08:00","gmt_modified":"2026-04-24T10:59:38.95576+08:00"},{"id":1421,"source_id":"ffbb970e-56e0-40ad-bd88-1a1e55482d96","target_id":"d34337b9ff77246979252d2fd8fb8018","source_type":"WIKI_ITEM","target_type":"CODE_SNIPPET","relationship_type":"CONTAINS","extra":"Wiki contains code snippet: backend/alembic/env.py#33-88","gmt_create":"2026-04-24T10:59:38.959262+08:00","gmt_modified":"2026-04-24T10:59:38.959262+08:00"},{"id":1422,"source_id":"ffbb970e-56e0-40ad-bd88-1a1e55482d96","target_id":"4d11ddf7abb8076d81b30c4315786f9a","source_type":"WIKI_ITEM","target_type":"CODE_SNIPPET","relationship_type":"CONTAINS","extra":"Wiki contains code snippet: backend/alembic/versions/488d0bd5ab01_initial_migration.py#21-128","gmt_create":"2026-04-24T10:59:38.959807+08:00","gmt_modified":"2026-04-24T10:59:38.959807+08:00"},{"id":1423,"source_id":"ffbb970e-56e0-40ad-bd88-1a1e55482d96","target_id":"eb63042f04a22f9a67bd498df1684d20","source_type":"WIKI_ITEM","target_type":"CODE_SNIPPET","relationship_type":"CONTAINS","extra":"Wiki contains code snippet: backend/alembic/versions/488d0bd5ab01_initial_migration.py#36-111","gmt_create":"2026-04-24T10:59:38.962943+08:00","gmt_modified":"2026-04-24T10:59:38.962944+08:00"},{"id":1424,"source_id":"ffbb970e-56e0-40ad-bd88-1a1e55482d96","target_id":"9b10dac7dbbb1327afc8a525bf4bd0c3","source_type":"WIKI_ITEM","target_type":"CODE_SNIPPET","relationship_type":"CONTAINS","extra":"Wiki contains code snippet: backend/app/services/query.py#45-81","gmt_create":"2026-04-24T10:59:38.964073+08:00","gmt_modified":"2026-04-24T10:59:38.964073+08:00"},{"id":1425,"source_id":"ffbb970e-56e0-40ad-bd88-1a1e55482d96","target_id":"c651c7ad6747a92ee96eabb2eb82afdd","source_type":"WIKI_ITEM","target_type":"CODE_SNIPPET","relationship_type":"CONTAINS","extra":"Wiki contains code snippet: backend/app/database.py#12-18","gmt_create":"2026-04-24T10:59:38.964595+08:00","gmt_modified":"2026-04-24T10:59:38.964595+08:00"},{"id":1426,"source_id":"ffbb970e-56e0-40ad-bd88-1a1e55482d96","target_id":"fe351bf59a46bec7f77ffe40a68a5993","source_type":"WIKI_ITEM","target_type":"CODE_SNIPPET","relationship_type":"CONTAINS","extra":"Wiki contains code snippet: backend/app/services/auth.py#40-56","gmt_create":"2026-04-24T10:59:38.96518+08:00","gmt_modified":"2026-04-24T10:59:38.96518+08:00"},{"id":1427,"source_id":"4d2f3847b7c10634733118b70a1aea0b","target_id":"fe351bf59a46bec7f77ffe40a68a5993","source_type":"SOURCE_FILE","target_type":"CODE_SNIPPET","relationship_type":"CONTAINS","extra":"Source file contains code snippet: 40-56","gmt_create":"2026-04-24T10:59:38.965521+08:00","gmt_modified":"2026-04-24T10:59:38.965521+08:00"},{"id":1428,"source_id":"ffbb970e-56e0-40ad-bd88-1a1e55482d96","target_id":"7dae7237f11c5100bf7889c105193cf6","source_type":"WIKI_ITEM","target_type":"CODE_SNIPPET","relationship_type":"CONTAINS","extra":"Wiki contains code snippet: backend/app/services/query.py#12-32","gmt_create":"2026-04-24T10:59:38.966015+08:00","gmt_modified":"2026-04-24T10:59:38.966015+08:00"},{"id":1429,"source_id":"ffbb970e-56e0-40ad-bd88-1a1e55482d96","target_id":"dd01eee487298a28e950f6345196f1d4","source_type":"WIKI_ITEM","target_type":"CODE_SNIPPET","relationship_type":"CONTAINS","extra":"Wiki contains code snippet: backend/app/services/citation.py#30-79","gmt_create":"2026-04-24T10:59:38.96654+08:00","gmt_modified":"2026-04-24T10:59:38.96654+08:00"},{"id":1430,"source_id":"ffbb970e-56e0-40ad-bd88-1a1e55482d96","target_id":"cc64cf609f5ff218f618e0664ffa7cc7","source_type":"WIKI_ITEM","target_type":"CODE_SNIPPET","relationship_type":"CONTAINS","extra":"Wiki contains code snippet: backend/app/services/citation.py#298-308","gmt_create":"2026-04-24T10:59:38.967326+08:00","gmt_modified":"2026-04-24T10:59:38.967326+08:00"},{"id":1431,"source_id":"ffbb970e-56e0-40ad-bd88-1a1e55482d96","target_id":"ce7e334595a4ce912e0d116314db9a35","source_type":"WIKI_ITEM","target_type":"CODE_SNIPPET","relationship_type":"CONTAINS","extra":"Wiki contains code snippet: backend/app/services/citation.py#342-429","gmt_create":"2026-04-24T10:59:38.96818+08:00","gmt_modified":"2026-04-24T10:59:38.96818+08:00"},{"id":1432,"source_id":"ffbb970e-56e0-40ad-bd88-1a1e55482d96","target_id":"1a3336b4af8a39a055e912724338580c","source_type":"WIKI_ITEM","target_type":"SOURCE_FILE","relationship_type":"REFERENCED_BY","extra":"Wiki references source file: backend/app/schemas/citation.py","gmt_create":"2026-04-24T10:59:38.968611+08:00","gmt_modified":"2026-04-24T10:59:38.968611+08:00"},{"id":1433,"source_id":"ffbb970e-56e0-40ad-bd88-1a1e55482d96","target_id":"2f46f212597e3c245b9e5dcc5dbc863d","source_type":"WIKI_ITEM","target_type":"CODE_SNIPPET","relationship_type":"CONTAINS","extra":"Wiki contains code snippet: backend/app/schemas/citation.py#7-18","gmt_create":"2026-04-24T10:59:38.969663+08:00","gmt_modified":"2026-04-24T10:59:38.969663+08:00"},{"id":1434,"source_id":"ffbb970e-56e0-40ad-bd88-1a1e55482d96","target_id":"46e69841e5c5dc62faa55c9f066586d6","source_type":"WIKI_ITEM","target_type":"CODE_SNIPPET","relationship_type":"CONTAINS","extra":"Wiki contains code snippet: backend/app/services/auth.py#74-107","gmt_create":"2026-04-24T10:59:38.970327+08:00","gmt_modified":"2026-04-24T10:59:38.970327+08:00"},{"id":1435,"source_id":"4d2f3847b7c10634733118b70a1aea0b","target_id":"46e69841e5c5dc62faa55c9f066586d6","source_type":"SOURCE_FILE","target_type":"CODE_SNIPPET","relationship_type":"CONTAINS","extra":"Source file contains code snippet: 74-107","gmt_create":"2026-04-24T10:59:38.971032+08:00","gmt_modified":"2026-04-24T10:59:38.971032+08:00"},{"id":1436,"source_id":"ffbb970e-56e0-40ad-bd88-1a1e55482d96","target_id":"cecc8857775f7928d465b68e429493d2","source_type":"WIKI_ITEM","target_type":"CODE_SNIPPET","relationship_type":"CONTAINS","extra":"Wiki contains code snippet: backend/app/services/auth.py#110-140","gmt_create":"2026-04-24T10:59:38.971655+08:00","gmt_modified":"2026-04-24T10:59:38.971655+08:00"},{"id":1437,"source_id":"4d2f3847b7c10634733118b70a1aea0b","target_id":"cecc8857775f7928d465b68e429493d2","source_type":"SOURCE_FILE","target_type":"CODE_SNIPPET","relationship_type":"CONTAINS","extra":"Source file contains code snippet: 110-140","gmt_create":"2026-04-24T10:59:38.97203+08:00","gmt_modified":"2026-04-24T10:59:38.97203+08:00"},{"id":1438,"source_id":"ffbb970e-56e0-40ad-bd88-1a1e55482d96","target_id":"1153d8a149a70bc79ca59a9dcba5945c","source_type":"WIKI_ITEM","target_type":"CODE_SNIPPET","relationship_type":"CONTAINS","extra":"Wiki contains code snippet: backend/app/schemas/auth.py#8-55","gmt_create":"2026-04-24T10:59:38.972462+08:00","gmt_modified":"2026-04-24T10:59:38.972462+08:00"},{"id":1439,"source_id":"e0c0ca66b8b81cf66e078a7ab162c07f","target_id":"1153d8a149a70bc79ca59a9dcba5945c","source_type":"SOURCE_FILE","target_type":"CODE_SNIPPET","relationship_type":"CONTAINS","extra":"Source file contains code snippet: 8-55","gmt_create":"2026-04-24T10:59:38.972843+08:00","gmt_modified":"2026-04-24T10:59:38.972843+08:00"},{"id":1440,"source_id":"ffbb970e-56e0-40ad-bd88-1a1e55482d96","target_id":"35dd08df9c7a562d9c7b8edf740eaf3c","source_type":"WIKI_ITEM","target_type":"CODE_SNIPPET","relationship_type":"CONTAINS","extra":"Wiki contains code snippet: backend/app/api/auth.py#33-115","gmt_create":"2026-04-24T10:59:38.973327+08:00","gmt_modified":"2026-04-24T10:59:38.973327+08:00"},{"id":1441,"source_id":"93022c8938ce318f167277cfa65c29a7","target_id":"35dd08df9c7a562d9c7b8edf740eaf3c","source_type":"SOURCE_FILE","target_type":"CODE_SNIPPET","relationship_type":"CONTAINS","extra":"Source file contains code snippet: 33-115","gmt_create":"2026-04-24T10:59:38.973675+08:00","gmt_modified":"2026-04-24T10:59:38.973675+08:00"},{"id":1442,"source_id":"ffbb970e-56e0-40ad-bd88-1a1e55482d96","target_id":"dc40f1dd3e59ee7f046019201068bea1","source_type":"WIKI_ITEM","target_type":"CODE_SNIPPET","relationship_type":"CONTAINS","extra":"Wiki contains code snippet: backend/app/services/citation.py#14-22","gmt_create":"2026-04-24T10:59:38.978124+08:00","gmt_modified":"2026-04-24T10:59:38.978124+08:00"},{"id":1443,"source_id":"3af3bb9e-4d99-4dc3-b1ed-2686db385c26","target_id":"aaf5bce6be82d2f947bfa5c1806de452","source_type":"WIKI_ITEM","target_type":"SOURCE_FILE","relationship_type":"REFERENCED_BY","extra":"Wiki references source file: frontend/package.json","gmt_create":"2026-04-24T11:01:58.083117+08:00","gmt_modified":"2026-04-24T11:01:58.083117+08:00"},{"id":1444,"source_id":"3af3bb9e-4d99-4dc3-b1ed-2686db385c26","target_id":"955e1dfe57f0a9a8e900383eb7641ba1","source_type":"WIKI_ITEM","target_type":"SOURCE_FILE","relationship_type":"REFERENCED_BY","extra":"Wiki references source file: frontend/next.config.mjs","gmt_create":"2026-04-24T11:01:58.083525+08:00","gmt_modified":"2026-04-24T11:01:58.083525+08:00"},{"id":1445,"source_id":"3af3bb9e-4d99-4dc3-b1ed-2686db385c26","target_id":"01056dad8851d3e9bd532eb4cab33792","source_type":"WIKI_ITEM","target_type":"SOURCE_FILE","relationship_type":"REFERENCED_BY","extra":"Wiki references source file: frontend/tailwind.config.ts","gmt_create":"2026-04-24T11:01:58.08385+08:00","gmt_modified":"2026-04-24T11:01:58.083851+08:00"},{"id":1446,"source_id":"3af3bb9e-4d99-4dc3-b1ed-2686db385c26","target_id":"12e2c3d7b9a92dc44a6ee29b85e10df6","source_type":"WIKI_ITEM","target_type":"SOURCE_FILE","relationship_type":"REFERENCED_BY","extra":"Wiki references source file: frontend/app/layout.tsx","gmt_create":"2026-04-24T11:01:58.084156+08:00","gmt_modified":"2026-04-24T11:01:58.084156+08:00"},{"id":1447,"source_id":"3af3bb9e-4d99-4dc3-b1ed-2686db385c26","target_id":"546e01c5f73aaf5140eee922f4b9a441","source_type":"WIKI_ITEM","target_type":"SOURCE_FILE","relationship_type":"REFERENCED_BY","extra":"Wiki references source file: frontend/components/providers.tsx","gmt_create":"2026-04-24T11:01:58.084498+08:00","gmt_modified":"2026-04-24T11:01:58.084498+08:00"},{"id":1448,"source_id":"3af3bb9e-4d99-4dc3-b1ed-2686db385c26","target_id":"5800a08224424ebced854d06365f6d44","source_type":"WIKI_ITEM","target_type":"SOURCE_FILE","relationship_type":"REFERENCED_BY","extra":"Wiki references source file: frontend/app/(auth","gmt_create":"2026-04-24T11:01:58.084794+08:00","gmt_modified":"2026-04-24T11:01:58.084794+08:00"},{"id":1449,"source_id":"3af3bb9e-4d99-4dc3-b1ed-2686db385c26","target_id":"2a1c745c7b3fb7f600596be3d979bba1","source_type":"WIKI_ITEM","target_type":"SOURCE_FILE","relationship_type":"REFERENCED_BY","extra":"Wiki references source file: frontend/app/(dashboard","gmt_create":"2026-04-24T11:01:58.08511+08:00","gmt_modified":"2026-04-24T11:01:58.08511+08:00"},{"id":1450,"source_id":"3af3bb9e-4d99-4dc3-b1ed-2686db385c26","target_id":"d2c1984414de6856ed5b3873c661b712","source_type":"WIKI_ITEM","target_type":"SOURCE_FILE","relationship_type":"REFERENCED_BY","extra":"Wiki references source file: frontend/lib/auth.ts","gmt_create":"2026-04-24T11:01:58.085472+08:00","gmt_modified":"2026-04-24T11:01:58.085472+08:00"},{"id":1451,"source_id":"3af3bb9e-4d99-4dc3-b1ed-2686db385c26","target_id":"b1d80d63eae8fd5e1bdfeee3c6bc9594","source_type":"WIKI_ITEM","target_type":"SOURCE_FILE","relationship_type":"REFERENCED_BY","extra":"Wiki references source file: frontend/types/next-auth.d.ts","gmt_create":"2026-04-24T11:01:58.085769+08:00","gmt_modified":"2026-04-24T11:01:58.085769+08:00"},{"id":1452,"source_id":"3af3bb9e-4d99-4dc3-b1ed-2686db385c26","target_id":"5d7886d0dc99f81073a578b8aefdd375","source_type":"WIKI_ITEM","target_type":"SOURCE_FILE","relationship_type":"REFERENCED_BY","extra":"Wiki references source file: frontend/lib/api.ts","gmt_create":"2026-04-24T11:01:58.08607+08:00","gmt_modified":"2026-04-24T11:01:58.086071+08:00"},{"id":1453,"source_id":"3af3bb9e-4d99-4dc3-b1ed-2686db385c26","target_id":"ac1acbc54c49ee1de13369f6c6827568","source_type":"WIKI_ITEM","target_type":"SOURCE_FILE","relationship_type":"REFERENCED_BY","extra":"Wiki references source file: frontend/components/ui/button.tsx","gmt_create":"2026-04-24T11:01:58.087299+08:00","gmt_modified":"2026-04-24T11:01:58.087299+08:00"},{"id":1454,"source_id":"3af3bb9e-4d99-4dc3-b1ed-2686db385c26","target_id":"eca13a610badfc5ffc6210827fb96991","source_type":"WIKI_ITEM","target_type":"SOURCE_FILE","relationship_type":"REFERENCED_BY","extra":"Wiki references source file: frontend/components/layout/header.tsx","gmt_create":"2026-04-24T11:01:58.087674+08:00","gmt_modified":"2026-04-24T11:01:58.087674+08:00"},{"id":1455,"source_id":"3af3bb9e-4d99-4dc3-b1ed-2686db385c26","target_id":"18a0651d895fba9bb4e0c0229459efdc","source_type":"WIKI_ITEM","target_type":"SOURCE_FILE","relationship_type":"REFERENCED_BY","extra":"Wiki references source file: frontend/components/layout/sidebar.tsx","gmt_create":"2026-04-24T11:01:58.087981+08:00","gmt_modified":"2026-04-24T11:01:58.087981+08:00"},{"id":1456,"source_id":"3af3bb9e-4d99-4dc3-b1ed-2686db385c26","target_id":"beb87ab5aad9532647e9dbd2db7ef587","source_type":"WIKI_ITEM","target_type":"SOURCE_FILE","relationship_type":"REFERENCED_BY","extra":"Wiki references source file: frontend/components/ui/tabs.tsx","gmt_create":"2026-04-24T11:01:58.088269+08:00","gmt_modified":"2026-04-24T11:01:58.088269+08:00"},{"id":1457,"source_id":"3af3bb9e-4d99-4dc3-b1ed-2686db385c26","target_id":"facea1f00ec72e00f774d0839fee7131","source_type":"WIKI_ITEM","target_type":"SOURCE_FILE","relationship_type":"REFERENCED_BY","extra":"Wiki references source file: /Users/Chiguyong/Code/GEO#wiki#main#wiki#zh/[app/api/auth/[...nextauth]/route.ts](file:/frontend/app/api/auth/[...nextauth]/route.ts)","gmt_create":"2026-04-24T11:01:58.088559+08:00","gmt_modified":"2026-04-24T11:01:58.088559+08:00"},{"id":1458,"source_id":"3af3bb9e-4d99-4dc3-b1ed-2686db385c26","target_id":"8a466b0c6eac2ccb54c5da7e13854646","source_type":"WIKI_ITEM","target_type":"CODE_SNIPPET","relationship_type":"CONTAINS","extra":"Wiki contains code snippet: frontend/app/layout.tsx#1-37","gmt_create":"2026-04-24T11:01:58.088994+08:00","gmt_modified":"2026-04-24T11:01:58.088994+08:00"},{"id":1459,"source_id":"3af3bb9e-4d99-4dc3-b1ed-2686db385c26","target_id":"fd18328b6582e68c30b130b912891992","source_type":"WIKI_ITEM","target_type":"CODE_SNIPPET","relationship_type":"CONTAINS","extra":"Wiki contains code snippet: frontend/components/providers.tsx#1-9","gmt_create":"2026-04-24T11:01:58.089491+08:00","gmt_modified":"2026-04-24T11:01:58.089491+08:00"},{"id":1460,"source_id":"3af3bb9e-4d99-4dc3-b1ed-2686db385c26","target_id":"dc735ee4a0f12140bcee122a67f4a13b","source_type":"WIKI_ITEM","target_type":"CODE_SNIPPET","relationship_type":"CONTAINS","extra":"Wiki contains code snippet: frontend/components/layout/sidebar.tsx#1-63","gmt_create":"2026-04-24T11:01:58.089973+08:00","gmt_modified":"2026-04-24T11:01:58.089973+08:00"},{"id":1461,"source_id":"18a0651d895fba9bb4e0c0229459efdc","target_id":"dc735ee4a0f12140bcee122a67f4a13b","source_type":"SOURCE_FILE","target_type":"CODE_SNIPPET","relationship_type":"CONTAINS","extra":"Source file contains code snippet: 1-63","gmt_create":"2026-04-24T11:01:58.090246+08:00","gmt_modified":"2026-04-24T11:01:58.090246+08:00"},{"id":1462,"source_id":"3af3bb9e-4d99-4dc3-b1ed-2686db385c26","target_id":"bd3042a8d9b602334720b0d7b4e8ab3d","source_type":"WIKI_ITEM","target_type":"CODE_SNIPPET","relationship_type":"CONTAINS","extra":"Wiki contains code snippet: frontend/components/ui/tabs.tsx#1-56","gmt_create":"2026-04-24T11:01:58.090695+08:00","gmt_modified":"2026-04-24T11:01:58.090695+08:00"},{"id":1463,"source_id":"3af3bb9e-4d99-4dc3-b1ed-2686db385c26","target_id":"89d70e5f89be23a229e3ee59982b8e6e","source_type":"WIKI_ITEM","target_type":"CODE_SNIPPET","relationship_type":"CONTAINS","extra":"Wiki contains code snippet: frontend/tailwind.config.ts#1-57","gmt_create":"2026-04-24T11:01:58.091173+08:00","gmt_modified":"2026-04-24T11:01:58.091173+08:00"},{"id":1464,"source_id":"3af3bb9e-4d99-4dc3-b1ed-2686db385c26","target_id":"f990ecd63842b3ab82f5b8c8dcde2a6b","source_type":"WIKI_ITEM","target_type":"CODE_SNIPPET","relationship_type":"CONTAINS","extra":"Wiki contains code snippet: frontend/next.config.mjs#1-5","gmt_create":"2026-04-24T11:01:58.091728+08:00","gmt_modified":"2026-04-24T11:01:58.091729+08:00"},{"id":1465,"source_id":"955e1dfe57f0a9a8e900383eb7641ba1","target_id":"f990ecd63842b3ab82f5b8c8dcde2a6b","source_type":"SOURCE_FILE","target_type":"CODE_SNIPPET","relationship_type":"CONTAINS","extra":"Source file contains code snippet: 1-5","gmt_create":"2026-04-24T11:01:58.092029+08:00","gmt_modified":"2026-04-24T11:01:58.092029+08:00"},{"id":1466,"source_id":"3af3bb9e-4d99-4dc3-b1ed-2686db385c26","target_id":"40325db1cb621a9af027150a8c5cf8e9","source_type":"WIKI_ITEM","target_type":"CODE_SNIPPET","relationship_type":"CONTAINS","extra":"Wiki contains code snippet: frontend/lib/auth.ts#1-73","gmt_create":"2026-04-24T11:01:58.094426+08:00","gmt_modified":"2026-04-24T11:01:58.094426+08:00"},{"id":1467,"source_id":"3af3bb9e-4d99-4dc3-b1ed-2686db385c26","target_id":"d5efa0fbc545b778dd913854d860c502","source_type":"WIKI_ITEM","target_type":"CODE_SNIPPET","relationship_type":"CONTAINS","extra":"Wiki contains code snippet: frontend/types/next-auth.d.ts#1-29","gmt_create":"2026-04-24T11:01:58.094992+08:00","gmt_modified":"2026-04-24T11:01:58.094992+08:00"},{"id":1468,"source_id":"b1d80d63eae8fd5e1bdfeee3c6bc9594","target_id":"d5efa0fbc545b778dd913854d860c502","source_type":"SOURCE_FILE","target_type":"CODE_SNIPPET","relationship_type":"CONTAINS","extra":"Source file contains code snippet: 1-29","gmt_create":"2026-04-24T11:01:58.095303+08:00","gmt_modified":"2026-04-24T11:01:58.095304+08:00"},{"id":1469,"source_id":"3af3bb9e-4d99-4dc3-b1ed-2686db385c26","target_id":"a9fb75d1fdb833a11b36bc7b298f19be","source_type":"WIKI_ITEM","target_type":"CODE_SNIPPET","relationship_type":"CONTAINS","extra":"Wiki contains code snippet: frontend/lib/api.ts#1-154","gmt_create":"2026-04-24T11:01:58.095866+08:00","gmt_modified":"2026-04-24T11:01:58.095867+08:00"},{"id":1470,"source_id":"3af3bb9e-4d99-4dc3-b1ed-2686db385c26","target_id":"95be577a89fbeb02578e4c3718c6ec86","source_type":"WIKI_ITEM","target_type":"CODE_SNIPPET","relationship_type":"CONTAINS","extra":"Wiki contains code snippet: frontend/components/ui/button.tsx#1-57","gmt_create":"2026-04-24T11:01:58.096403+08:00","gmt_modified":"2026-04-24T11:01:58.096403+08:00"},{"id":1471,"source_id":"3af3bb9e-4d99-4dc3-b1ed-2686db385c26","target_id":"0d903468b55bdc63cc7e25a87a89c522","source_type":"WIKI_ITEM","target_type":"CODE_SNIPPET","relationship_type":"CONTAINS","extra":"Wiki contains code snippet: frontend/components/layout/header.tsx#1-30","gmt_create":"2026-04-24T11:01:58.096919+08:00","gmt_modified":"2026-04-24T11:01:58.096919+08:00"},{"id":1472,"source_id":"3af3bb9e-4d99-4dc3-b1ed-2686db385c26","target_id":"71a37a516437e94fd82a87efc70a3f16","source_type":"WIKI_ITEM","target_type":"CODE_SNIPPET","relationship_type":"CONTAINS","extra":"Wiki contains code snippet: frontend/package.json#1-40","gmt_create":"2026-04-24T11:01:58.105424+08:00","gmt_modified":"2026-04-24T11:01:58.105424+08:00"},{"id":1473,"source_id":"df661133-efbf-43fe-97c3-f581c81f47a7","target_id":"c59f8c276697a070dffc581fe94d809c","source_type":"WIKI_ITEM","target_type":"SOURCE_FILE","relationship_type":"REFERENCED_BY","extra":"Wiki references source file: backend/app/models/user.py","gmt_create":"2026-04-24T11:02:17.577219+08:00","gmt_modified":"2026-04-24T11:02:17.577219+08:00"},{"id":1474,"source_id":"df661133-efbf-43fe-97c3-f581c81f47a7","target_id":"e0c0ca66b8b81cf66e078a7ab162c07f","source_type":"WIKI_ITEM","target_type":"SOURCE_FILE","relationship_type":"REFERENCED_BY","extra":"Wiki references source file: backend/app/schemas/auth.py","gmt_create":"2026-04-24T11:02:17.578316+08:00","gmt_modified":"2026-04-24T11:02:17.578316+08:00"},{"id":1475,"source_id":"df661133-efbf-43fe-97c3-f581c81f47a7","target_id":"4d2f3847b7c10634733118b70a1aea0b","source_type":"WIKI_ITEM","target_type":"SOURCE_FILE","relationship_type":"REFERENCED_BY","extra":"Wiki references source file: backend/app/services/auth.py","gmt_create":"2026-04-24T11:02:17.579016+08:00","gmt_modified":"2026-04-24T11:02:17.579016+08:00"},{"id":1476,"source_id":"df661133-efbf-43fe-97c3-f581c81f47a7","target_id":"93022c8938ce318f167277cfa65c29a7","source_type":"WIKI_ITEM","target_type":"SOURCE_FILE","relationship_type":"REFERENCED_BY","extra":"Wiki references source file: backend/app/api/auth.py","gmt_create":"2026-04-24T11:02:17.579604+08:00","gmt_modified":"2026-04-24T11:02:17.579604+08:00"},{"id":1477,"source_id":"df661133-efbf-43fe-97c3-f581c81f47a7","target_id":"9d08667997a868fc07c9b4e328e44224","source_type":"WIKI_ITEM","target_type":"SOURCE_FILE","relationship_type":"REFERENCED_BY","extra":"Wiki references source file: backend/app/api/deps.py","gmt_create":"2026-04-24T11:02:17.580669+08:00","gmt_modified":"2026-04-24T11:02:17.580669+08:00"},{"id":1478,"source_id":"df661133-efbf-43fe-97c3-f581c81f47a7","target_id":"9ff19022ef915615911280e3c49ed44b","source_type":"WIKI_ITEM","target_type":"SOURCE_FILE","relationship_type":"REFERENCED_BY","extra":"Wiki references source file: backend/app/config.py","gmt_create":"2026-04-24T11:02:17.581765+08:00","gmt_modified":"2026-04-24T11:02:17.581765+08:00"},{"id":1479,"source_id":"df661133-efbf-43fe-97c3-f581c81f47a7","target_id":"b0c428683c8a3e6922d90ca0d8c2736d","source_type":"WIKI_ITEM","target_type":"SOURCE_FILE","relationship_type":"REFERENCED_BY","extra":"Wiki references source file: backend/app/database.py","gmt_create":"2026-04-24T11:02:17.582245+08:00","gmt_modified":"2026-04-24T11:02:17.582245+08:00"},{"id":1480,"source_id":"df661133-efbf-43fe-97c3-f581c81f47a7","target_id":"9228ff67d4c757a85d9421b71f4b29f5","source_type":"WIKI_ITEM","target_type":"SOURCE_FILE","relationship_type":"REFERENCED_BY","extra":"Wiki references source file: backend/app/main.py","gmt_create":"2026-04-24T11:02:17.582573+08:00","gmt_modified":"2026-04-24T11:02:17.582573+08:00"},{"id":1481,"source_id":"df661133-efbf-43fe-97c3-f581c81f47a7","target_id":"d4f95fcf50683b5bf6167c7d2a6b126d","source_type":"WIKI_ITEM","target_type":"SOURCE_FILE","relationship_type":"REFERENCED_BY","extra":"Wiki references source file: backend/alembic/versions/488d0bd5ab01_initial_migration.py","gmt_create":"2026-04-24T11:02:17.582943+08:00","gmt_modified":"2026-04-24T11:02:17.582943+08:00"},{"id":1482,"source_id":"df661133-efbf-43fe-97c3-f581c81f47a7","target_id":"b0cb6810919f64006be7aa66b2b76a61","source_type":"WIKI_ITEM","target_type":"SOURCE_FILE","relationship_type":"REFERENCED_BY","extra":"Wiki references source file: backend/alembic/versions/c3d5e7f9ab12_add_user_management_fields.py","gmt_create":"2026-04-24T11:02:17.58335+08:00","gmt_modified":"2026-04-24T11:02:17.58335+08:00"},{"id":1483,"source_id":"df661133-efbf-43fe-97c3-f581c81f47a7","target_id":"d2c1984414de6856ed5b3873c661b712","source_type":"WIKI_ITEM","target_type":"SOURCE_FILE","relationship_type":"REFERENCED_BY","extra":"Wiki references source file: frontend/lib/auth.ts","gmt_create":"2026-04-24T11:02:17.583672+08:00","gmt_modified":"2026-04-24T11:02:17.583673+08:00"},{"id":1484,"source_id":"df661133-efbf-43fe-97c3-f581c81f47a7","target_id":"5d7886d0dc99f81073a578b8aefdd375","source_type":"WIKI_ITEM","target_type":"SOURCE_FILE","relationship_type":"REFERENCED_BY","extra":"Wiki references source file: frontend/lib/api.ts","gmt_create":"2026-04-24T11:02:17.583973+08:00","gmt_modified":"2026-04-24T11:02:17.583973+08:00"},{"id":1485,"source_id":"df661133-efbf-43fe-97c3-f581c81f47a7","target_id":"5800a08224424ebced854d06365f6d44","source_type":"WIKI_ITEM","target_type":"SOURCE_FILE","relationship_type":"REFERENCED_BY","extra":"Wiki references source file: frontend/app/(auth","gmt_create":"2026-04-24T11:02:17.584307+08:00","gmt_modified":"2026-04-24T11:02:17.584307+08:00"},{"id":1486,"source_id":"df661133-efbf-43fe-97c3-f581c81f47a7","target_id":"37d7291b1373216dcf08f081a94ab1c8","source_type":"WIKI_ITEM","target_type":"SOURCE_FILE","relationship_type":"REFERENCED_BY","extra":"Wiki references source file: /Users/Chiguyong/Code/GEO#wiki#main#wiki#zh/[frontend/app/api/auth/[...nextauth]/route.ts](file:/frontend/app/api/auth/[...nextauth]/route.ts)","gmt_create":"2026-04-24T11:02:17.585037+08:00","gmt_modified":"2026-04-24T11:02:17.585037+08:00"},{"id":1487,"source_id":"df661133-efbf-43fe-97c3-f581c81f47a7","target_id":"389d631bc6c7111ba411b0b79fca455e","source_type":"WIKI_ITEM","target_type":"SOURCE_FILE","relationship_type":"REFERENCED_BY","extra":"Wiki references source file: tests/test_auth.py","gmt_create":"2026-04-24T11:02:17.585369+08:00","gmt_modified":"2026-04-24T11:02:17.585369+08:00"},{"id":1488,"source_id":"df661133-efbf-43fe-97c3-f581c81f47a7","target_id":"f5978358d04c3c917d9ca5044c7f36fa","source_type":"WIKI_ITEM","target_type":"CODE_SNIPPET","relationship_type":"CONTAINS","extra":"Wiki contains code snippet: backend/app/models/user.py#11-48","gmt_create":"2026-04-24T11:02:17.585874+08:00","gmt_modified":"2026-04-24T11:02:17.585874+08:00"},{"id":1489,"source_id":"df661133-efbf-43fe-97c3-f581c81f47a7","target_id":"46434c04e402674d97a6e2017a3a13c0","source_type":"WIKI_ITEM","target_type":"CODE_SNIPPET","relationship_type":"CONTAINS","extra":"Wiki contains code snippet: backend/app/schemas/auth.py#8-62","gmt_create":"2026-04-24T11:02:17.58637+08:00","gmt_modified":"2026-04-24T11:02:17.58637+08:00"},{"id":1490,"source_id":"e0c0ca66b8b81cf66e078a7ab162c07f","target_id":"46434c04e402674d97a6e2017a3a13c0","source_type":"SOURCE_FILE","target_type":"CODE_SNIPPET","relationship_type":"CONTAINS","extra":"Source file contains code snippet: 8-62","gmt_create":"2026-04-24T11:02:17.586722+08:00","gmt_modified":"2026-04-24T11:02:17.586723+08:00"},{"id":1491,"source_id":"df661133-efbf-43fe-97c3-f581c81f47a7","target_id":"3a0fd619768c80d413f8b02b3daec229","source_type":"WIKI_ITEM","target_type":"CODE_SNIPPET","relationship_type":"CONTAINS","extra":"Wiki contains code snippet: backend/app/services/auth.py#74-175","gmt_create":"2026-04-24T11:02:17.587241+08:00","gmt_modified":"2026-04-24T11:02:17.587241+08:00"},{"id":1492,"source_id":"4d2f3847b7c10634733118b70a1aea0b","target_id":"3a0fd619768c80d413f8b02b3daec229","source_type":"SOURCE_FILE","target_type":"CODE_SNIPPET","relationship_type":"CONTAINS","extra":"Source file contains code snippet: 74-175","gmt_create":"2026-04-24T11:02:17.587532+08:00","gmt_modified":"2026-04-24T11:02:17.587532+08:00"},{"id":1493,"source_id":"df661133-efbf-43fe-97c3-f581c81f47a7","target_id":"86af0295eebcd62f33207e158db86c81","source_type":"WIKI_ITEM","target_type":"CODE_SNIPPET","relationship_type":"CONTAINS","extra":"Wiki contains code snippet: backend/app/api/auth.py#65-115","gmt_create":"2026-04-24T11:02:17.58823+08:00","gmt_modified":"2026-04-24T11:02:17.58823+08:00"},{"id":1494,"source_id":"93022c8938ce318f167277cfa65c29a7","target_id":"86af0295eebcd62f33207e158db86c81","source_type":"SOURCE_FILE","target_type":"CODE_SNIPPET","relationship_type":"CONTAINS","extra":"Source file contains code snippet: 65-115","gmt_create":"2026-04-24T11:02:17.588592+08:00","gmt_modified":"2026-04-24T11:02:17.588592+08:00"},{"id":1495,"source_id":"df661133-efbf-43fe-97c3-f581c81f47a7","target_id":"675ab6c1ae510ca753b5e966b7b6a10c","source_type":"WIKI_ITEM","target_type":"CODE_SNIPPET","relationship_type":"CONTAINS","extra":"Wiki contains code snippet: backend/alembic/versions/c3d5e7f9ab12_add_user_management_fields.py#21-41","gmt_create":"2026-04-24T11:02:17.589011+08:00","gmt_modified":"2026-04-24T11:02:17.589011+08:00"},{"id":1496,"source_id":"df661133-efbf-43fe-97c3-f581c81f47a7","target_id":"809fc86e3ce390a1af1db1e0cd5ad787","source_type":"WIKI_ITEM","target_type":"CODE_SNIPPET","relationship_type":"CONTAINS","extra":"Wiki contains code snippet: frontend/lib/api.ts#55-84","gmt_create":"2026-04-24T11:02:17.589558+08:00","gmt_modified":"2026-04-24T11:02:17.589558+08:00"},{"id":1497,"source_id":"5d7886d0dc99f81073a578b8aefdd375","target_id":"809fc86e3ce390a1af1db1e0cd5ad787","source_type":"SOURCE_FILE","target_type":"CODE_SNIPPET","relationship_type":"CONTAINS","extra":"Source file contains code snippet: 55-84","gmt_create":"2026-04-24T11:02:17.589968+08:00","gmt_modified":"2026-04-24T11:02:17.589968+08:00"},{"id":1498,"source_id":"df661133-efbf-43fe-97c3-f581c81f47a7","target_id":"33ec8bca51cb9f667bf91088dd6b6a70","source_type":"WIKI_ITEM","target_type":"CODE_SNIPPET","relationship_type":"CONTAINS","extra":"Wiki contains code snippet: backend/app/main.py#24-48","gmt_create":"2026-04-24T11:02:17.590369+08:00","gmt_modified":"2026-04-24T11:02:17.590369+08:00"},{"id":1499,"source_id":"df661133-efbf-43fe-97c3-f581c81f47a7","target_id":"069243fafe60a85cf16a0ca40fa07180","source_type":"WIKI_ITEM","target_type":"CODE_SNIPPET","relationship_type":"CONTAINS","extra":"Wiki contains code snippet: backend/app/api/deps.py#16-43","gmt_create":"2026-04-24T11:02:17.591152+08:00","gmt_modified":"2026-04-24T11:02:17.591152+08:00"},{"id":1500,"source_id":"df661133-efbf-43fe-97c3-f581c81f47a7","target_id":"608c00e1835ad72363ef08796961faca","source_type":"WIKI_ITEM","target_type":"CODE_SNIPPET","relationship_type":"CONTAINS","extra":"Wiki contains code snippet: backend/app/config.py#4-17","gmt_create":"2026-04-24T11:02:17.59504+08:00","gmt_modified":"2026-04-24T11:02:17.59504+08:00"},{"id":1501,"source_id":"df661133-efbf-43fe-97c3-f581c81f47a7","target_id":"8aee7654d1f435ab53d8ddaabd269fed","source_type":"WIKI_ITEM","target_type":"CODE_SNIPPET","relationship_type":"CONTAINS","extra":"Wiki contains code snippet: backend/app/database.py#6-29","gmt_create":"2026-04-24T11:02:17.595846+08:00","gmt_modified":"2026-04-24T11:02:17.595846+08:00"},{"id":1502,"source_id":"df661133-efbf-43fe-97c3-f581c81f47a7","target_id":"29ee02d164db08d7b9bd4591195e191b","source_type":"WIKI_ITEM","target_type":"CODE_SNIPPET","relationship_type":"CONTAINS","extra":"Wiki contains code snippet: frontend/lib/auth.ts#5-56","gmt_create":"2026-04-24T11:02:17.596584+08:00","gmt_modified":"2026-04-24T11:02:17.596584+08:00"},{"id":1503,"source_id":"d2c1984414de6856ed5b3873c661b712","target_id":"29ee02d164db08d7b9bd4591195e191b","source_type":"SOURCE_FILE","target_type":"CODE_SNIPPET","relationship_type":"CONTAINS","extra":"Source file contains code snippet: 5-56","gmt_create":"2026-04-24T11:02:17.596923+08:00","gmt_modified":"2026-04-24T11:02:17.596923+08:00"},{"id":1504,"source_id":"df661133-efbf-43fe-97c3-f581c81f47a7","target_id":"73c4889fcacaea737921a568bf20383d","source_type":"WIKI_ITEM","target_type":"CODE_SNIPPET","relationship_type":"CONTAINS","extra":"Wiki contains code snippet: frontend/lib/auth.ts#13-32","gmt_create":"2026-04-24T11:02:17.598958+08:00","gmt_modified":"2026-04-24T11:02:17.598958+08:00"},{"id":1505,"source_id":"d2c1984414de6856ed5b3873c661b712","target_id":"73c4889fcacaea737921a568bf20383d","source_type":"SOURCE_FILE","target_type":"CODE_SNIPPET","relationship_type":"CONTAINS","extra":"Source file contains code snippet: 13-32","gmt_create":"2026-04-24T11:02:17.599388+08:00","gmt_modified":"2026-04-24T11:02:17.599389+08:00"},{"id":1506,"source_id":"df661133-efbf-43fe-97c3-f581c81f47a7","target_id":"11c2505e56ba9a48c50be4c915f22c9d","source_type":"WIKI_ITEM","target_type":"CODE_SNIPPET","relationship_type":"CONTAINS","extra":"Wiki contains code snippet: backend/app/services/auth.py#27-37","gmt_create":"2026-04-24T11:02:17.601161+08:00","gmt_modified":"2026-04-24T11:02:17.601161+08:00"},{"id":1507,"source_id":"4d2f3847b7c10634733118b70a1aea0b","target_id":"11c2505e56ba9a48c50be4c915f22c9d","source_type":"SOURCE_FILE","target_type":"CODE_SNIPPET","relationship_type":"CONTAINS","extra":"Source file contains code snippet: 27-37","gmt_create":"2026-04-24T11:02:17.601545+08:00","gmt_modified":"2026-04-24T11:02:17.601545+08:00"},{"id":1508,"source_id":"df661133-efbf-43fe-97c3-f581c81f47a7","target_id":"5f32b18b18cea3b2bdc9150366c24e5e","source_type":"WIKI_ITEM","target_type":"CODE_SNIPPET","relationship_type":"CONTAINS","extra":"Wiki contains code snippet: backend/app/api/deps.py#26-37","gmt_create":"2026-04-24T11:02:17.601968+08:00","gmt_modified":"2026-04-24T11:02:17.601968+08:00"},{"id":1509,"source_id":"9d08667997a868fc07c9b4e328e44224","target_id":"5f32b18b18cea3b2bdc9150366c24e5e","source_type":"SOURCE_FILE","target_type":"CODE_SNIPPET","relationship_type":"CONTAINS","extra":"Source file contains code snippet: 26-37","gmt_create":"2026-04-24T11:02:17.602636+08:00","gmt_modified":"2026-04-24T11:02:17.602636+08:00"},{"id":1510,"source_id":"df661133-efbf-43fe-97c3-f581c81f47a7","target_id":"c4abaa8a82ad75d09ee66f97fbad4b96","source_type":"WIKI_ITEM","target_type":"CODE_SNIPPET","relationship_type":"CONTAINS","extra":"Wiki contains code snippet: backend/app/config.py#9-10","gmt_create":"2026-04-24T11:02:17.603102+08:00","gmt_modified":"2026-04-24T11:02:17.603102+08:00"},{"id":1511,"source_id":"9ff19022ef915615911280e3c49ed44b","target_id":"c4abaa8a82ad75d09ee66f97fbad4b96","source_type":"SOURCE_FILE","target_type":"CODE_SNIPPET","relationship_type":"CONTAINS","extra":"Source file contains code snippet: 9-10","gmt_create":"2026-04-24T11:02:17.603401+08:00","gmt_modified":"2026-04-24T11:02:17.603402+08:00"},{"id":1512,"source_id":"df661133-efbf-43fe-97c3-f581c81f47a7","target_id":"08ac91fb508b386f0e6c66e53b03a471","source_type":"WIKI_ITEM","target_type":"CODE_SNIPPET","relationship_type":"CONTAINS","extra":"Wiki contains code snippet: backend/app/schemas/auth.py#8-11","gmt_create":"2026-04-24T11:02:17.604811+08:00","gmt_modified":"2026-04-24T11:02:17.604811+08:00"},{"id":1513,"source_id":"e0c0ca66b8b81cf66e078a7ab162c07f","target_id":"08ac91fb508b386f0e6c66e53b03a471","source_type":"SOURCE_FILE","target_type":"CODE_SNIPPET","relationship_type":"CONTAINS","extra":"Source file contains code snippet: 8-11","gmt_create":"2026-04-24T11:02:17.60518+08:00","gmt_modified":"2026-04-24T11:02:17.60518+08:00"},{"id":1514,"source_id":"df661133-efbf-43fe-97c3-f581c81f47a7","target_id":"d4ea500c0acb4ebf267a44908e23f787","source_type":"WIKI_ITEM","target_type":"CODE_SNIPPET","relationship_type":"CONTAINS","extra":"Wiki contains code snippet: backend/app/services/auth.py#40-55","gmt_create":"2026-04-24T11:02:17.605584+08:00","gmt_modified":"2026-04-24T11:02:17.605584+08:00"},{"id":1515,"source_id":"4d2f3847b7c10634733118b70a1aea0b","target_id":"d4ea500c0acb4ebf267a44908e23f787","source_type":"SOURCE_FILE","target_type":"CODE_SNIPPET","relationship_type":"CONTAINS","extra":"Source file contains code snippet: 40-55","gmt_create":"2026-04-24T11:02:17.605874+08:00","gmt_modified":"2026-04-24T11:02:17.605874+08:00"},{"id":1516,"source_id":"df661133-efbf-43fe-97c3-f581c81f47a7","target_id":"b4f0bea37f71296167571d8831ebe6d5","source_type":"WIKI_ITEM","target_type":"CODE_SNIPPET","relationship_type":"CONTAINS","extra":"Wiki contains code snippet: tests/test_auth.py#25-58","gmt_create":"2026-04-24T11:02:17.60772+08:00","gmt_modified":"2026-04-24T11:02:17.607721+08:00"},{"id":1517,"source_id":"389d631bc6c7111ba411b0b79fca455e","target_id":"b4f0bea37f71296167571d8831ebe6d5","source_type":"SOURCE_FILE","target_type":"CODE_SNIPPET","relationship_type":"CONTAINS","extra":"Source file contains code snippet: 25-58","gmt_create":"2026-04-24T11:02:17.608058+08:00","gmt_modified":"2026-04-24T11:02:17.608058+08:00"},{"id":1518,"source_id":"df661133-efbf-43fe-97c3-f581c81f47a7","target_id":"46f7431da5eb82bbd7686a71abaddf78","source_type":"WIKI_ITEM","target_type":"CODE_SNIPPET","relationship_type":"CONTAINS","extra":"Wiki contains code snippet: backend/app/api/auth.py#42-57","gmt_create":"2026-04-24T11:02:17.608532+08:00","gmt_modified":"2026-04-24T11:02:17.608532+08:00"},{"id":1519,"source_id":"93022c8938ce318f167277cfa65c29a7","target_id":"46f7431da5eb82bbd7686a71abaddf78","source_type":"SOURCE_FILE","target_type":"CODE_SNIPPET","relationship_type":"CONTAINS","extra":"Source file contains code snippet: 42-57","gmt_create":"2026-04-24T11:02:17.608872+08:00","gmt_modified":"2026-04-24T11:02:17.608872+08:00"},{"id":1520,"source_id":"df661133-efbf-43fe-97c3-f581c81f47a7","target_id":"0ba2ea54873608360c48c8b5aaeea20f","source_type":"WIKI_ITEM","target_type":"CODE_SNIPPET","relationship_type":"CONTAINS","extra":"Wiki contains code snippet: backend/app/services/auth.py#58-71","gmt_create":"2026-04-24T11:02:17.609376+08:00","gmt_modified":"2026-04-24T11:02:17.609376+08:00"},{"id":1521,"source_id":"4d2f3847b7c10634733118b70a1aea0b","target_id":"0ba2ea54873608360c48c8b5aaeea20f","source_type":"SOURCE_FILE","target_type":"CODE_SNIPPET","relationship_type":"CONTAINS","extra":"Source file contains code snippet: 58-71","gmt_create":"2026-04-24T11:02:17.609794+08:00","gmt_modified":"2026-04-24T11:02:17.609794+08:00"},{"id":1522,"source_id":"df661133-efbf-43fe-97c3-f581c81f47a7","target_id":"2d170933ae8c838199f6d68a2b9165c0","source_type":"WIKI_ITEM","target_type":"CODE_SNIPPET","relationship_type":"CONTAINS","extra":"Wiki contains code snippet: tests/test_auth.py#61-84","gmt_create":"2026-04-24T11:02:17.610895+08:00","gmt_modified":"2026-04-24T11:02:17.610895+08:00"},{"id":1523,"source_id":"389d631bc6c7111ba411b0b79fca455e","target_id":"2d170933ae8c838199f6d68a2b9165c0","source_type":"SOURCE_FILE","target_type":"CODE_SNIPPET","relationship_type":"CONTAINS","extra":"Source file contains code snippet: 61-84","gmt_create":"2026-04-24T11:02:17.6112+08:00","gmt_modified":"2026-04-24T11:02:17.6112+08:00"},{"id":1524,"source_id":"df661133-efbf-43fe-97c3-f581c81f47a7","target_id":"0ea85b56099b9087bd22eec96b7bb752","source_type":"WIKI_ITEM","target_type":"CODE_SNIPPET","relationship_type":"CONTAINS","extra":"Wiki contains code snippet: backend/app/services/auth.py#74-140","gmt_create":"2026-04-24T11:02:17.611696+08:00","gmt_modified":"2026-04-24T11:02:17.611696+08:00"},{"id":1525,"source_id":"4d2f3847b7c10634733118b70a1aea0b","target_id":"0ea85b56099b9087bd22eec96b7bb752","source_type":"SOURCE_FILE","target_type":"CODE_SNIPPET","relationship_type":"CONTAINS","extra":"Source file contains code snippet: 74-140","gmt_create":"2026-04-24T11:02:17.612307+08:00","gmt_modified":"2026-04-24T11:02:17.612307+08:00"},{"id":1526,"source_id":"df661133-efbf-43fe-97c3-f581c81f47a7","target_id":"2a4087b6941ca17dd651147f2f23451c","source_type":"WIKI_ITEM","target_type":"CODE_SNIPPET","relationship_type":"CONTAINS","extra":"Wiki contains code snippet: backend/app/api/auth.py#65-90","gmt_create":"2026-04-24T11:02:17.613704+08:00","gmt_modified":"2026-04-24T11:02:17.613704+08:00"},{"id":1527,"source_id":"93022c8938ce318f167277cfa65c29a7","target_id":"2a4087b6941ca17dd651147f2f23451c","source_type":"SOURCE_FILE","target_type":"CODE_SNIPPET","relationship_type":"CONTAINS","extra":"Source file contains code snippet: 65-90","gmt_create":"2026-04-24T11:02:17.614071+08:00","gmt_modified":"2026-04-24T11:02:17.614071+08:00"},{"id":1528,"source_id":"df661133-efbf-43fe-97c3-f581c81f47a7","target_id":"88c12e200d5c3ea53c695aa4209cecd9","source_type":"WIKI_ITEM","target_type":"CODE_SNIPPET","relationship_type":"CONTAINS","extra":"Wiki contains code snippet: backend/app/api/auth.py#65-76","gmt_create":"2026-04-24T11:02:17.614574+08:00","gmt_modified":"2026-04-24T11:02:17.614574+08:00"},{"id":1529,"source_id":"93022c8938ce318f167277cfa65c29a7","target_id":"88c12e200d5c3ea53c695aa4209cecd9","source_type":"SOURCE_FILE","target_type":"CODE_SNIPPET","relationship_type":"CONTAINS","extra":"Source file contains code snippet: 65-76","gmt_create":"2026-04-24T11:02:17.615017+08:00","gmt_modified":"2026-04-24T11:02:17.615017+08:00"},{"id":1530,"source_id":"df661133-efbf-43fe-97c3-f581c81f47a7","target_id":"cecc8857775f7928d465b68e429493d2","source_type":"WIKI_ITEM","target_type":"CODE_SNIPPET","relationship_type":"CONTAINS","extra":"Wiki contains code snippet: backend/app/services/auth.py#110-140","gmt_create":"2026-04-24T11:02:17.615713+08:00","gmt_modified":"2026-04-24T11:02:17.615713+08:00"},{"id":1531,"source_id":"df661133-efbf-43fe-97c3-f581c81f47a7","target_id":"42b92d878423a23067e9a6da104e3a5e","source_type":"WIKI_ITEM","target_type":"CODE_SNIPPET","relationship_type":"CONTAINS","extra":"Wiki contains code snippet: backend/app/api/auth.py#79-90","gmt_create":"2026-04-24T11:02:17.616887+08:00","gmt_modified":"2026-04-24T11:02:17.616888+08:00"},{"id":1532,"source_id":"93022c8938ce318f167277cfa65c29a7","target_id":"42b92d878423a23067e9a6da104e3a5e","source_type":"SOURCE_FILE","target_type":"CODE_SNIPPET","relationship_type":"CONTAINS","extra":"Source file contains code snippet: 79-90","gmt_create":"2026-04-24T11:02:17.617309+08:00","gmt_modified":"2026-04-24T11:02:17.617309+08:00"},{"id":1533,"source_id":"df661133-efbf-43fe-97c3-f581c81f47a7","target_id":"46e69841e5c5dc62faa55c9f066586d6","source_type":"WIKI_ITEM","target_type":"CODE_SNIPPET","relationship_type":"CONTAINS","extra":"Wiki contains code snippet: backend/app/services/auth.py#74-107","gmt_create":"2026-04-24T11:02:17.617785+08:00","gmt_modified":"2026-04-24T11:02:17.617785+08:00"},{"id":1534,"source_id":"df661133-efbf-43fe-97c3-f581c81f47a7","target_id":"abadc99952ad6e00ab4bfb66b84732bb","source_type":"WIKI_ITEM","target_type":"CODE_SNIPPET","relationship_type":"CONTAINS","extra":"Wiki contains code snippet: backend/app/schemas/auth.py#33-41","gmt_create":"2026-04-24T11:02:17.618924+08:00","gmt_modified":"2026-04-24T11:02:17.618925+08:00"},{"id":1535,"source_id":"e0c0ca66b8b81cf66e078a7ab162c07f","target_id":"abadc99952ad6e00ab4bfb66b84732bb","source_type":"SOURCE_FILE","target_type":"CODE_SNIPPET","relationship_type":"CONTAINS","extra":"Source file contains code snippet: 33-41","gmt_create":"2026-04-24T11:02:17.619333+08:00","gmt_modified":"2026-04-24T11:02:17.619333+08:00"},{"id":1536,"source_id":"df661133-efbf-43fe-97c3-f581c81f47a7","target_id":"f784a33e47128515d518555d99103f62","source_type":"WIKI_ITEM","target_type":"CODE_SNIPPET","relationship_type":"CONTAINS","extra":"Wiki contains code snippet: backend/app/services/auth.py#143-175","gmt_create":"2026-04-24T11:02:17.619742+08:00","gmt_modified":"2026-04-24T11:02:17.619742+08:00"},{"id":1537,"source_id":"4d2f3847b7c10634733118b70a1aea0b","target_id":"f784a33e47128515d518555d99103f62","source_type":"SOURCE_FILE","target_type":"CODE_SNIPPET","relationship_type":"CONTAINS","extra":"Source file contains code snippet: 143-175","gmt_create":"2026-04-24T11:02:17.620025+08:00","gmt_modified":"2026-04-24T11:02:17.620025+08:00"},{"id":1538,"source_id":"df661133-efbf-43fe-97c3-f581c81f47a7","target_id":"173f8de5896e18fc81cdd5d72e2a8c07","source_type":"WIKI_ITEM","target_type":"CODE_SNIPPET","relationship_type":"CONTAINS","extra":"Wiki contains code snippet: backend/app/api/auth.py#93-115","gmt_create":"2026-04-24T11:02:17.621068+08:00","gmt_modified":"2026-04-24T11:02:17.621068+08:00"},{"id":1539,"source_id":"93022c8938ce318f167277cfa65c29a7","target_id":"173f8de5896e18fc81cdd5d72e2a8c07","source_type":"SOURCE_FILE","target_type":"CODE_SNIPPET","relationship_type":"CONTAINS","extra":"Source file contains code snippet: 93-115","gmt_create":"2026-04-24T11:02:17.62207+08:00","gmt_modified":"2026-04-24T11:02:17.62207+08:00"},{"id":1540,"source_id":"df661133-efbf-43fe-97c3-f581c81f47a7","target_id":"3ab144009e705151f69698d2d8a81cea","source_type":"WIKI_ITEM","target_type":"CODE_SNIPPET","relationship_type":"CONTAINS","extra":"Wiki contains code snippet: backend/app/services/auth.py#35-37","gmt_create":"2026-04-24T11:02:17.622971+08:00","gmt_modified":"2026-04-24T11:02:17.622972+08:00"},{"id":1541,"source_id":"4d2f3847b7c10634733118b70a1aea0b","target_id":"3ab144009e705151f69698d2d8a81cea","source_type":"SOURCE_FILE","target_type":"CODE_SNIPPET","relationship_type":"CONTAINS","extra":"Source file contains code snippet: 35-37","gmt_create":"2026-04-24T11:02:17.623434+08:00","gmt_modified":"2026-04-24T11:02:17.623434+08:00"},{"id":1542,"source_id":"df661133-efbf-43fe-97c3-f581c81f47a7","target_id":"570a917d85850ab1208fce5823b110a3","source_type":"WIKI_ITEM","target_type":"CODE_SNIPPET","relationship_type":"CONTAINS","extra":"Wiki contains code snippet: backend/app/api/auth.py#60-62","gmt_create":"2026-04-24T11:02:17.62436+08:00","gmt_modified":"2026-04-24T11:02:17.62436+08:00"},{"id":1543,"source_id":"93022c8938ce318f167277cfa65c29a7","target_id":"570a917d85850ab1208fce5823b110a3","source_type":"SOURCE_FILE","target_type":"CODE_SNIPPET","relationship_type":"CONTAINS","extra":"Source file contains code snippet: 60-62","gmt_create":"2026-04-24T11:02:17.624694+08:00","gmt_modified":"2026-04-24T11:02:17.624694+08:00"},{"id":1544,"source_id":"df661133-efbf-43fe-97c3-f581c81f47a7","target_id":"f92c0c41197c488f04f994bf0f7ea465","source_type":"WIKI_ITEM","target_type":"CODE_SNIPPET","relationship_type":"CONTAINS","extra":"Wiki contains code snippet: tests/test_auth.py#87-104","gmt_create":"2026-04-24T11:02:17.625099+08:00","gmt_modified":"2026-04-24T11:02:17.625099+08:00"},{"id":1545,"source_id":"389d631bc6c7111ba411b0b79fca455e","target_id":"f92c0c41197c488f04f994bf0f7ea465","source_type":"SOURCE_FILE","target_type":"CODE_SNIPPET","relationship_type":"CONTAINS","extra":"Source file contains code snippet: 87-104","gmt_create":"2026-04-24T11:02:17.625385+08:00","gmt_modified":"2026-04-24T11:02:17.625385+08:00"},{"id":1546,"source_id":"df661133-efbf-43fe-97c3-f581c81f47a7","target_id":"5688471e2418628ac2a6409451708d06","source_type":"WIKI_ITEM","target_type":"CODE_SNIPPET","relationship_type":"CONTAINS","extra":"Wiki contains code snippet: backend/app/api/auth.py#1-115","gmt_create":"2026-04-24T11:02:17.626962+08:00","gmt_modified":"2026-04-24T11:02:17.626962+08:00"},{"id":1547,"source_id":"93022c8938ce318f167277cfa65c29a7","target_id":"5688471e2418628ac2a6409451708d06","source_type":"SOURCE_FILE","target_type":"CODE_SNIPPET","relationship_type":"CONTAINS","extra":"Source file contains code snippet: 1-115","gmt_create":"2026-04-24T11:02:17.627296+08:00","gmt_modified":"2026-04-24T11:02:17.627296+08:00"},{"id":1548,"source_id":"df661133-efbf-43fe-97c3-f581c81f47a7","target_id":"76e6c0abb49fec57cac4892837a143c9","source_type":"WIKI_ITEM","target_type":"CODE_SNIPPET","relationship_type":"CONTAINS","extra":"Wiki contains code snippet: backend/app/api/deps.py#1-43","gmt_create":"2026-04-24T11:02:17.62778+08:00","gmt_modified":"2026-04-24T11:02:17.62778+08:00"},{"id":1549,"source_id":"df661133-efbf-43fe-97c3-f581c81f47a7","target_id":"08c1475254a5bc8877ff29a895de3b6a","source_type":"WIKI_ITEM","target_type":"CODE_SNIPPET","relationship_type":"CONTAINS","extra":"Wiki contains code snippet: backend/app/services/auth.py#1-175","gmt_create":"2026-04-24T11:02:17.628417+08:00","gmt_modified":"2026-04-24T11:02:17.628417+08:00"},{"id":1550,"source_id":"df661133-efbf-43fe-97c3-f581c81f47a7","target_id":"9bfc041fe426da2eb78353827e8d9163","source_type":"WIKI_ITEM","target_type":"CODE_SNIPPET","relationship_type":"CONTAINS","extra":"Wiki contains code snippet: backend/app/database.py#1-29","gmt_create":"2026-04-24T11:02:17.629023+08:00","gmt_modified":"2026-04-24T11:02:17.629023+08:00"},{"id":1551,"source_id":"df661133-efbf-43fe-97c3-f581c81f47a7","target_id":"84fbed7d35f7752e2117a74fcaf5f0e9","source_type":"WIKI_ITEM","target_type":"CODE_SNIPPET","relationship_type":"CONTAINS","extra":"Wiki contains code snippet: backend/app/config.py#1-17","gmt_create":"2026-04-24T11:02:17.629535+08:00","gmt_modified":"2026-04-24T11:02:17.629535+08:00"},{"id":1552,"source_id":"df661133-efbf-43fe-97c3-f581c81f47a7","target_id":"c2747ca16b879bca0f68955534c3c4fc","source_type":"WIKI_ITEM","target_type":"CODE_SNIPPET","relationship_type":"CONTAINS","extra":"Wiki contains code snippet: backend/app/main.py#1-48","gmt_create":"2026-04-24T11:02:17.630073+08:00","gmt_modified":"2026-04-24T11:02:17.630073+08:00"},{"id":1553,"source_id":"df661133-efbf-43fe-97c3-f581c81f47a7","target_id":"1721defc3d6206478d3c0692cc821761","source_type":"WIKI_ITEM","target_type":"CODE_SNIPPET","relationship_type":"CONTAINS","extra":"Wiki contains code snippet: tests/test_auth.py#25-104","gmt_create":"2026-04-24T11:02:17.632419+08:00","gmt_modified":"2026-04-24T11:02:17.632419+08:00"},{"id":1554,"source_id":"df661133-efbf-43fe-97c3-f581c81f47a7","target_id":"7075cde1c771c46dbbd37b3c09dac53d","source_type":"WIKI_ITEM","target_type":"CODE_SNIPPET","relationship_type":"CONTAINS","extra":"Wiki contains code snippet: backend/app/api/deps.py#20-41","gmt_create":"2026-04-24T11:02:17.633252+08:00","gmt_modified":"2026-04-24T11:02:17.633252+08:00"},{"id":1555,"source_id":"9d08667997a868fc07c9b4e328e44224","target_id":"7075cde1c771c46dbbd37b3c09dac53d","source_type":"SOURCE_FILE","target_type":"CODE_SNIPPET","relationship_type":"CONTAINS","extra":"Source file contains code snippet: 20-41","gmt_create":"2026-04-24T11:02:17.636427+08:00","gmt_modified":"2026-04-24T11:02:17.636427+08:00"},{"id":1556,"source_id":"df661133-efbf-43fe-97c3-f581c81f47a7","target_id":"607e99e751640281d26516c772548b93","source_type":"WIKI_ITEM","target_type":"CODE_SNIPPET","relationship_type":"CONTAINS","extra":"Wiki contains code snippet: frontend/lib/api.ts#17-39","gmt_create":"2026-04-24T11:02:17.637267+08:00","gmt_modified":"2026-04-24T11:02:17.637267+08:00"},{"id":1557,"source_id":"5d7886d0dc99f81073a578b8aefdd375","target_id":"607e99e751640281d26516c772548b93","source_type":"SOURCE_FILE","target_type":"CODE_SNIPPET","relationship_type":"CONTAINS","extra":"Source file contains code snippet: 17-39","gmt_create":"2026-04-24T11:02:17.637632+08:00","gmt_modified":"2026-04-24T11:02:17.637632+08:00"},{"id":1558,"source_id":"49915365-e38e-43b5-beac-6aa7d5a74cbb","target_id":"9228ff67d4c757a85d9421b71f4b29f5","source_type":"WIKI_ITEM","target_type":"SOURCE_FILE","relationship_type":"REFERENCED_BY","extra":"Wiki references source file: backend/app/main.py","gmt_create":"2026-04-24T11:02:30.039416+08:00","gmt_modified":"2026-04-24T11:02:30.039416+08:00"},{"id":1559,"source_id":"49915365-e38e-43b5-beac-6aa7d5a74cbb","target_id":"93022c8938ce318f167277cfa65c29a7","source_type":"WIKI_ITEM","target_type":"SOURCE_FILE","relationship_type":"REFERENCED_BY","extra":"Wiki references source file: backend/app/api/auth.py","gmt_create":"2026-04-24T11:02:30.039811+08:00","gmt_modified":"2026-04-24T11:02:30.039811+08:00"},{"id":1560,"source_id":"49915365-e38e-43b5-beac-6aa7d5a74cbb","target_id":"6b3d903205941aa9391dd90016e1102c","source_type":"WIKI_ITEM","target_type":"SOURCE_FILE","relationship_type":"REFERENCED_BY","extra":"Wiki references source file: backend/app/api/queries.py","gmt_create":"2026-04-24T11:02:30.040216+08:00","gmt_modified":"2026-04-24T11:02:30.040216+08:00"},{"id":1561,"source_id":"49915365-e38e-43b5-beac-6aa7d5a74cbb","target_id":"7538ffe4902ab6041adb28b19844962a","source_type":"WIKI_ITEM","target_type":"SOURCE_FILE","relationship_type":"REFERENCED_BY","extra":"Wiki references source file: backend/app/api/citations.py","gmt_create":"2026-04-24T11:02:30.040578+08:00","gmt_modified":"2026-04-24T11:02:30.040578+08:00"},{"id":1562,"source_id":"49915365-e38e-43b5-beac-6aa7d5a74cbb","target_id":"58901c94d975d87e652a4dc6c8dda656","source_type":"WIKI_ITEM","target_type":"SOURCE_FILE","relationship_type":"REFERENCED_BY","extra":"Wiki references source file: backend/app/api/reports.py","gmt_create":"2026-04-24T11:02:30.040879+08:00","gmt_modified":"2026-04-24T11:02:30.040879+08:00"},{"id":1563,"source_id":"49915365-e38e-43b5-beac-6aa7d5a74cbb","target_id":"5386144bf3c668c6fa14481c0d85a214","source_type":"WIKI_ITEM","target_type":"SOURCE_FILE","relationship_type":"REFERENCED_BY","extra":"Wiki references source file: backend/app/api/subscriptions.py","gmt_create":"2026-04-24T11:02:30.041164+08:00","gmt_modified":"2026-04-24T11:02:30.041164+08:00"},{"id":1564,"source_id":"49915365-e38e-43b5-beac-6aa7d5a74cbb","target_id":"f26740f2a1532b38c816663a4f665dbf","source_type":"WIKI_ITEM","target_type":"SOURCE_FILE","relationship_type":"REFERENCED_BY","extra":"Wiki references source file: backend/app/api/admin.py","gmt_create":"2026-04-24T11:02:30.04145+08:00","gmt_modified":"2026-04-24T11:02:30.04145+08:00"},{"id":1565,"source_id":"49915365-e38e-43b5-beac-6aa7d5a74cbb","target_id":"9d08667997a868fc07c9b4e328e44224","source_type":"WIKI_ITEM","target_type":"SOURCE_FILE","relationship_type":"REFERENCED_BY","extra":"Wiki references source file: backend/app/api/deps.py","gmt_create":"2026-04-24T11:02:30.041739+08:00","gmt_modified":"2026-04-24T11:02:30.041739+08:00"},{"id":1566,"source_id":"49915365-e38e-43b5-beac-6aa7d5a74cbb","target_id":"5883a8ef4fc156d76b71ffdb5ecdf232","source_type":"WIKI_ITEM","target_type":"SOURCE_FILE","relationship_type":"REFERENCED_BY","extra":"Wiki references source file: backend/app/middleware/rate_limit.py","gmt_create":"2026-04-24T11:02:30.042071+08:00","gmt_modified":"2026-04-24T11:02:30.042071+08:00"},{"id":1567,"source_id":"49915365-e38e-43b5-beac-6aa7d5a74cbb","target_id":"e0c0ca66b8b81cf66e078a7ab162c07f","source_type":"WIKI_ITEM","target_type":"SOURCE_FILE","relationship_type":"REFERENCED_BY","extra":"Wiki references source file: backend/app/schemas/auth.py","gmt_create":"2026-04-24T11:02:30.042401+08:00","gmt_modified":"2026-04-24T11:02:30.042401+08:00"},{"id":1568,"source_id":"49915365-e38e-43b5-beac-6aa7d5a74cbb","target_id":"f301b79d833233ce39d350e82a71c938","source_type":"WIKI_ITEM","target_type":"SOURCE_FILE","relationship_type":"REFERENCED_BY","extra":"Wiki references source file: backend/app/schemas/query.py","gmt_create":"2026-04-24T11:02:30.042688+08:00","gmt_modified":"2026-04-24T11:02:30.042688+08:00"},{"id":1569,"source_id":"49915365-e38e-43b5-beac-6aa7d5a74cbb","target_id":"1a3336b4af8a39a055e912724338580c","source_type":"WIKI_ITEM","target_type":"SOURCE_FILE","relationship_type":"REFERENCED_BY","extra":"Wiki references source file: backend/app/schemas/citation.py","gmt_create":"2026-04-24T11:02:30.042971+08:00","gmt_modified":"2026-04-24T11:02:30.042971+08:00"},{"id":1570,"source_id":"49915365-e38e-43b5-beac-6aa7d5a74cbb","target_id":"5013cbe89f1c6f03533eb218400cedb0","source_type":"WIKI_ITEM","target_type":"SOURCE_FILE","relationship_type":"REFERENCED_BY","extra":"Wiki references source file: backend/app/schemas/subscription.py","gmt_create":"2026-04-24T11:02:30.043264+08:00","gmt_modified":"2026-04-24T11:02:30.043264+08:00"},{"id":1571,"source_id":"49915365-e38e-43b5-beac-6aa7d5a74cbb","target_id":"4d2f3847b7c10634733118b70a1aea0b","source_type":"WIKI_ITEM","target_type":"SOURCE_FILE","relationship_type":"REFERENCED_BY","extra":"Wiki references source file: backend/app/services/auth.py","gmt_create":"2026-04-24T11:02:30.043594+08:00","gmt_modified":"2026-04-24T11:02:30.043594+08:00"},{"id":1572,"source_id":"49915365-e38e-43b5-beac-6aa7d5a74cbb","target_id":"88d22de3b2a7419868e8ae19130d860c","source_type":"WIKI_ITEM","target_type":"SOURCE_FILE","relationship_type":"REFERENCED_BY","extra":"Wiki references source file: backend/app/services/query.py","gmt_create":"2026-04-24T11:02:30.043956+08:00","gmt_modified":"2026-04-24T11:02:30.043956+08:00"},{"id":1573,"source_id":"49915365-e38e-43b5-beac-6aa7d5a74cbb","target_id":"04e3926c080e795713bff683e7dc9d3e","source_type":"WIKI_ITEM","target_type":"SOURCE_FILE","relationship_type":"REFERENCED_BY","extra":"Wiki references source file: backend/app/services/citation.py","gmt_create":"2026-04-24T11:02:30.044289+08:00","gmt_modified":"2026-04-24T11:02:30.044289+08:00"},{"id":1574,"source_id":"49915365-e38e-43b5-beac-6aa7d5a74cbb","target_id":"b250fc6c32106a7f3e0c3ad152dfc097","source_type":"WIKI_ITEM","target_type":"SOURCE_FILE","relationship_type":"REFERENCED_BY","extra":"Wiki references source file: backend/app/services/subscription.py","gmt_create":"2026-04-24T11:02:30.044599+08:00","gmt_modified":"2026-04-24T11:02:30.044599+08:00"},{"id":1575,"source_id":"49915365-e38e-43b5-beac-6aa7d5a74cbb","target_id":"3809c5ab912511e0e093ba02a4fc918f","source_type":"WIKI_ITEM","target_type":"SOURCE_FILE","relationship_type":"REFERENCED_BY","extra":"Wiki references source file: backend/app/services/admin.py","gmt_create":"2026-04-24T11:02:30.045053+08:00","gmt_modified":"2026-04-24T11:02:30.045053+08:00"},{"id":1576,"source_id":"49915365-e38e-43b5-beac-6aa7d5a74cbb","target_id":"9ff19022ef915615911280e3c49ed44b","source_type":"WIKI_ITEM","target_type":"SOURCE_FILE","relationship_type":"REFERENCED_BY","extra":"Wiki references source file: backend/app/config.py","gmt_create":"2026-04-24T11:02:30.045401+08:00","gmt_modified":"2026-04-24T11:02:30.045401+08:00"},{"id":1577,"source_id":"49915365-e38e-43b5-beac-6aa7d5a74cbb","target_id":"c59f8c276697a070dffc581fe94d809c","source_type":"WIKI_ITEM","target_type":"SOURCE_FILE","relationship_type":"REFERENCED_BY","extra":"Wiki references source file: backend/app/models/user.py","gmt_create":"2026-04-24T11:02:30.045812+08:00","gmt_modified":"2026-04-24T11:02:30.045813+08:00"},{"id":1578,"source_id":"49915365-e38e-43b5-beac-6aa7d5a74cbb","target_id":"b74caccb06844efcdb14d8324cff65c2","source_type":"WIKI_ITEM","target_type":"SOURCE_FILE","relationship_type":"REFERENCED_BY","extra":"Wiki references source file: backend/app/models/query.py","gmt_create":"2026-04-24T11:02:30.046255+08:00","gmt_modified":"2026-04-24T11:02:30.046255+08:00"},{"id":1579,"source_id":"49915365-e38e-43b5-beac-6aa7d5a74cbb","target_id":"b4a81ef789630d0af6a8d50859d01bf3","source_type":"WIKI_ITEM","target_type":"SOURCE_FILE","relationship_type":"REFERENCED_BY","extra":"Wiki references source file: backend/app/models/citation_record.py","gmt_create":"2026-04-24T11:02:30.046821+08:00","gmt_modified":"2026-04-24T11:02:30.046821+08:00"},{"id":1580,"source_id":"49915365-e38e-43b5-beac-6aa7d5a74cbb","target_id":"069738f21ac2da7349d22683e8c36929","source_type":"WIKI_ITEM","target_type":"SOURCE_FILE","relationship_type":"REFERENCED_BY","extra":"Wiki references source file: backend/app/models/query_task.py","gmt_create":"2026-04-24T11:02:30.047179+08:00","gmt_modified":"2026-04-24T11:02:30.047179+08:00"},{"id":1581,"source_id":"49915365-e38e-43b5-beac-6aa7d5a74cbb","target_id":"bceca00463fe55d3bcafda728f97f723","source_type":"WIKI_ITEM","target_type":"SOURCE_FILE","relationship_type":"REFERENCED_BY","extra":"Wiki references source file: backend/app/models/subscription.py","gmt_create":"2026-04-24T11:02:30.04757+08:00","gmt_modified":"2026-04-24T11:02:30.04757+08:00"},{"id":1582,"source_id":"49915365-e38e-43b5-beac-6aa7d5a74cbb","target_id":"0fcc0fe680a7ca8b8c7f4d579b77aeec","source_type":"WIKI_ITEM","target_type":"CODE_SNIPPET","relationship_type":"CONTAINS","extra":"Wiki contains code snippet: backend/app/main.py#12-78","gmt_create":"2026-04-24T11:02:30.048059+08:00","gmt_modified":"2026-04-24T11:02:30.048059+08:00"},{"id":1583,"source_id":"9228ff67d4c757a85d9421b71f4b29f5","target_id":"0fcc0fe680a7ca8b8c7f4d579b77aeec","source_type":"SOURCE_FILE","target_type":"CODE_SNIPPET","relationship_type":"CONTAINS","extra":"Source file contains code snippet: 12-78","gmt_create":"2026-04-24T11:02:30.048441+08:00","gmt_modified":"2026-04-24T11:02:30.048441+08:00"},{"id":1584,"source_id":"49915365-e38e-43b5-beac-6aa7d5a74cbb","target_id":"10d3948b1394ffa0110796edfa0bfc25","source_type":"WIKI_ITEM","target_type":"CODE_SNIPPET","relationship_type":"CONTAINS","extra":"Wiki contains code snippet: backend/app/api/auth.py#30","gmt_create":"2026-04-24T11:02:30.049701+08:00","gmt_modified":"2026-04-24T11:02:30.049701+08:00"},{"id":1585,"source_id":"93022c8938ce318f167277cfa65c29a7","target_id":"10d3948b1394ffa0110796edfa0bfc25","source_type":"SOURCE_FILE","target_type":"CODE_SNIPPET","relationship_type":"CONTAINS","extra":"Source file contains code snippet: 30","gmt_create":"2026-04-24T11:02:30.050019+08:00","gmt_modified":"2026-04-24T11:02:30.050019+08:00"},{"id":1586,"source_id":"49915365-e38e-43b5-beac-6aa7d5a74cbb","target_id":"fa1ee5e3822128a37e9d03af74083392","source_type":"WIKI_ITEM","target_type":"CODE_SNIPPET","relationship_type":"CONTAINS","extra":"Wiki contains code snippet: backend/app/api/queries.py#12","gmt_create":"2026-04-24T11:02:30.050437+08:00","gmt_modified":"2026-04-24T11:02:30.050437+08:00"},{"id":1587,"source_id":"49915365-e38e-43b5-beac-6aa7d5a74cbb","target_id":"7e908f05baccdfcf7f4a3ef3c9cd5c38","source_type":"WIKI_ITEM","target_type":"CODE_SNIPPET","relationship_type":"CONTAINS","extra":"Wiki contains code snippet: backend/app/api/citations.py#21","gmt_create":"2026-04-24T11:02:30.050938+08:00","gmt_modified":"2026-04-24T11:02:30.050938+08:00"},{"id":1588,"source_id":"49915365-e38e-43b5-beac-6aa7d5a74cbb","target_id":"3c41910bad9855635d1362efc314463a","source_type":"WIKI_ITEM","target_type":"CODE_SNIPPET","relationship_type":"CONTAINS","extra":"Wiki contains code snippet: backend/app/api/reports.py#15","gmt_create":"2026-04-24T11:02:30.051502+08:00","gmt_modified":"2026-04-24T11:02:30.051502+08:00"},{"id":1589,"source_id":"58901c94d975d87e652a4dc6c8dda656","target_id":"3c41910bad9855635d1362efc314463a","source_type":"SOURCE_FILE","target_type":"CODE_SNIPPET","relationship_type":"CONTAINS","extra":"Source file contains code snippet: 15","gmt_create":"2026-04-24T11:02:30.051832+08:00","gmt_modified":"2026-04-24T11:02:30.051832+08:00"},{"id":1590,"source_id":"49915365-e38e-43b5-beac-6aa7d5a74cbb","target_id":"f32e078c985967af30d2c526290d9acb","source_type":"WIKI_ITEM","target_type":"CODE_SNIPPET","relationship_type":"CONTAINS","extra":"Wiki contains code snippet: backend/app/api/subscriptions.py#23","gmt_create":"2026-04-24T11:02:30.052221+08:00","gmt_modified":"2026-04-24T11:02:30.052221+08:00"},{"id":1591,"source_id":"5386144bf3c668c6fa14481c0d85a214","target_id":"f32e078c985967af30d2c526290d9acb","source_type":"SOURCE_FILE","target_type":"CODE_SNIPPET","relationship_type":"CONTAINS","extra":"Source file contains code snippet: 23","gmt_create":"2026-04-24T11:02:30.052506+08:00","gmt_modified":"2026-04-24T11:02:30.052506+08:00"},{"id":1592,"source_id":"49915365-e38e-43b5-beac-6aa7d5a74cbb","target_id":"c10a89cdd47474f51664a239b82cc2e2","source_type":"WIKI_ITEM","target_type":"CODE_SNIPPET","relationship_type":"CONTAINS","extra":"Wiki contains code snippet: backend/app/api/admin.py#17","gmt_create":"2026-04-24T11:02:30.052951+08:00","gmt_modified":"2026-04-24T11:02:30.052951+08:00"},{"id":1593,"source_id":"f26740f2a1532b38c816663a4f665dbf","target_id":"c10a89cdd47474f51664a239b82cc2e2","source_type":"SOURCE_FILE","target_type":"CODE_SNIPPET","relationship_type":"CONTAINS","extra":"Source file contains code snippet: 17","gmt_create":"2026-04-24T11:02:30.05328+08:00","gmt_modified":"2026-04-24T11:02:30.05328+08:00"},{"id":1594,"source_id":"49915365-e38e-43b5-beac-6aa7d5a74cbb","target_id":"f240c1067c223a019ba05b0fbd718aa4","source_type":"WIKI_ITEM","target_type":"CODE_SNIPPET","relationship_type":"CONTAINS","extra":"Wiki contains code snippet: backend/app/main.py#1-84","gmt_create":"2026-04-24T11:02:30.053738+08:00","gmt_modified":"2026-04-24T11:02:30.053738+08:00"},{"id":1595,"source_id":"49915365-e38e-43b5-beac-6aa7d5a74cbb","target_id":"d6ebce8c7d9e9de127486400670ebed0","source_type":"WIKI_ITEM","target_type":"CODE_SNIPPET","relationship_type":"CONTAINS","extra":"Wiki contains code snippet: backend/app/main.py#39-84","gmt_create":"2026-04-24T11:02:30.054219+08:00","gmt_modified":"2026-04-24T11:02:30.054219+08:00"},{"id":1596,"source_id":"9228ff67d4c757a85d9421b71f4b29f5","target_id":"d6ebce8c7d9e9de127486400670ebed0","source_type":"SOURCE_FILE","target_type":"CODE_SNIPPET","relationship_type":"CONTAINS","extra":"Source file contains code snippet: 39-84","gmt_create":"2026-04-24T11:02:30.054595+08:00","gmt_modified":"2026-04-24T11:02:30.054595+08:00"},{"id":1597,"source_id":"49915365-e38e-43b5-beac-6aa7d5a74cbb","target_id":"35dd08df9c7a562d9c7b8edf740eaf3c","source_type":"WIKI_ITEM","target_type":"CODE_SNIPPET","relationship_type":"CONTAINS","extra":"Wiki contains code snippet: backend/app/api/auth.py#33-115","gmt_create":"2026-04-24T11:02:30.055201+08:00","gmt_modified":"2026-04-24T11:02:30.055201+08:00"},{"id":1598,"source_id":"49915365-e38e-43b5-beac-6aa7d5a74cbb","target_id":"ec3ed02cad3cd8af4bacb5c978273092","source_type":"WIKI_ITEM","target_type":"CODE_SNIPPET","relationship_type":"CONTAINS","extra":"Wiki contains code snippet: backend/app/api/subscriptions.py#26-77","gmt_create":"2026-04-24T11:02:30.055878+08:00","gmt_modified":"2026-04-24T11:02:30.055878+08:00"},{"id":1599,"source_id":"5386144bf3c668c6fa14481c0d85a214","target_id":"ec3ed02cad3cd8af4bacb5c978273092","source_type":"SOURCE_FILE","target_type":"CODE_SNIPPET","relationship_type":"CONTAINS","extra":"Source file contains code snippet: 26-77","gmt_create":"2026-04-24T11:02:30.056273+08:00","gmt_modified":"2026-04-24T11:02:30.056273+08:00"},{"id":1600,"source_id":"49915365-e38e-43b5-beac-6aa7d5a74cbb","target_id":"05664cbd35007caa5290760cc1ef1b99","source_type":"WIKI_ITEM","target_type":"CODE_SNIPPET","relationship_type":"CONTAINS","extra":"Wiki contains code snippet: backend/app/api/admin.py#29-108","gmt_create":"2026-04-24T11:02:30.056757+08:00","gmt_modified":"2026-04-24T11:02:30.056757+08:00"},{"id":1601,"source_id":"49915365-e38e-43b5-beac-6aa7d5a74cbb","target_id":"712424bd3bd3d5f39b1a0a72acc9952a","source_type":"WIKI_ITEM","target_type":"CODE_SNIPPET","relationship_type":"CONTAINS","extra":"Wiki contains code snippet: backend/app/middleware/rate_limit.py#10-83","gmt_create":"2026-04-24T11:02:30.057383+08:00","gmt_modified":"2026-04-24T11:02:30.057383+08:00"},{"id":1602,"source_id":"49915365-e38e-43b5-beac-6aa7d5a74cbb","target_id":"2db9940a42c91fc92f23595491ea93d1","source_type":"WIKI_ITEM","target_type":"CODE_SNIPPET","relationship_type":"CONTAINS","extra":"Wiki contains code snippet: backend/app/main.py#67-78","gmt_create":"2026-04-24T11:02:30.057883+08:00","gmt_modified":"2026-04-24T11:02:30.057883+08:00"},{"id":1603,"source_id":"9228ff67d4c757a85d9421b71f4b29f5","target_id":"2db9940a42c91fc92f23595491ea93d1","source_type":"SOURCE_FILE","target_type":"CODE_SNIPPET","relationship_type":"CONTAINS","extra":"Source file contains code snippet: 67-78","gmt_create":"2026-04-24T11:02:30.058168+08:00","gmt_modified":"2026-04-24T11:02:30.058168+08:00"},{"id":1604,"source_id":"49915365-e38e-43b5-beac-6aa7d5a74cbb","target_id":"bcdf50f6234651cb9863ab210e6473e5","source_type":"WIKI_ITEM","target_type":"CODE_SNIPPET","relationship_type":"CONTAINS","extra":"Wiki contains code snippet: backend/app/api/deps.py#16-42","gmt_create":"2026-04-24T11:02:30.058557+08:00","gmt_modified":"2026-04-24T11:02:30.058557+08:00"},{"id":1605,"source_id":"49915365-e38e-43b5-beac-6aa7d5a74cbb","target_id":"6df0277c2486b148fa26c2682dbdaa4c","source_type":"WIKI_ITEM","target_type":"CODE_SNIPPET","relationship_type":"CONTAINS","extra":"Wiki contains code snippet: backend/app/services/auth.py#37-68","gmt_create":"2026-04-24T11:02:30.05912+08:00","gmt_modified":"2026-04-24T11:02:30.05912+08:00"},{"id":1606,"source_id":"49915365-e38e-43b5-beac-6aa7d5a74cbb","target_id":"5ea5f192d580031ffe57e1582b70c67e","source_type":"WIKI_ITEM","target_type":"CODE_SNIPPET","relationship_type":"CONTAINS","extra":"Wiki contains code snippet: backend/app/services/query.py#12-123","gmt_create":"2026-04-24T11:02:30.05967+08:00","gmt_modified":"2026-04-24T11:02:30.059671+08:00"},{"id":1607,"source_id":"49915365-e38e-43b5-beac-6aa7d5a74cbb","target_id":"fe4a793f16cd4e12b56253c0a6d53ae0","source_type":"WIKI_ITEM","target_type":"CODE_SNIPPET","relationship_type":"CONTAINS","extra":"Wiki contains code snippet: backend/app/services/citation.py#24-359","gmt_create":"2026-04-24T11:02:30.060346+08:00","gmt_modified":"2026-04-24T11:02:30.060346+08:00"},{"id":1608,"source_id":"49915365-e38e-43b5-beac-6aa7d5a74cbb","target_id":"68fbb2bd365f96a98ea187a9738c4460","source_type":"WIKI_ITEM","target_type":"CODE_SNIPPET","relationship_type":"CONTAINS","extra":"Wiki contains code snippet: backend/app/api/auth.py#33-57","gmt_create":"2026-04-24T11:02:30.060876+08:00","gmt_modified":"2026-04-24T11:02:30.060876+08:00"},{"id":1609,"source_id":"93022c8938ce318f167277cfa65c29a7","target_id":"68fbb2bd365f96a98ea187a9738c4460","source_type":"SOURCE_FILE","target_type":"CODE_SNIPPET","relationship_type":"CONTAINS","extra":"Source file contains code snippet: 33-57","gmt_create":"2026-04-24T11:02:30.061204+08:00","gmt_modified":"2026-04-24T11:02:30.061204+08:00"},{"id":1610,"source_id":"49915365-e38e-43b5-beac-6aa7d5a74cbb","target_id":"4aad38dfc00a0877bd965c3d0b3c280c","source_type":"WIKI_ITEM","target_type":"CODE_SNIPPET","relationship_type":"CONTAINS","extra":"Wiki contains code snippet: backend/app/schemas/auth.py#7-34","gmt_create":"2026-04-24T11:02:30.063434+08:00","gmt_modified":"2026-04-24T11:02:30.063434+08:00"},{"id":1611,"source_id":"49915365-e38e-43b5-beac-6aa7d5a74cbb","target_id":"9b10dac7dbbb1327afc8a525bf4bd0c3","source_type":"WIKI_ITEM","target_type":"CODE_SNIPPET","relationship_type":"CONTAINS","extra":"Wiki contains code snippet: backend/app/services/query.py#45-81","gmt_create":"2026-04-24T11:02:30.064469+08:00","gmt_modified":"2026-04-24T11:02:30.064469+08:00"},{"id":1612,"source_id":"49915365-e38e-43b5-beac-6aa7d5a74cbb","target_id":"ae9de874df4a46f4197b6c157c25ec6e","source_type":"WIKI_ITEM","target_type":"CODE_SNIPPET","relationship_type":"CONTAINS","extra":"Wiki contains code snippet: backend/app/api/queries.py#15-85","gmt_create":"2026-04-24T11:02:30.065051+08:00","gmt_modified":"2026-04-24T11:02:30.065052+08:00"},{"id":1613,"source_id":"49915365-e38e-43b5-beac-6aa7d5a74cbb","target_id":"69118807690ef351a9de910414d5e676","source_type":"WIKI_ITEM","target_type":"CODE_SNIPPET","relationship_type":"CONTAINS","extra":"Wiki contains code snippet: backend/app/schemas/query.py#11-94","gmt_create":"2026-04-24T11:02:30.065708+08:00","gmt_modified":"2026-04-24T11:02:30.065708+08:00"},{"id":1614,"source_id":"49915365-e38e-43b5-beac-6aa7d5a74cbb","target_id":"212d822d207a4c0bd7825bbf20e188e9","source_type":"WIKI_ITEM","target_type":"CODE_SNIPPET","relationship_type":"CONTAINS","extra":"Wiki contains code snippet: backend/app/api/citations.py#59-77","gmt_create":"2026-04-24T11:02:30.066709+08:00","gmt_modified":"2026-04-24T11:02:30.066709+08:00"},{"id":1615,"source_id":"49915365-e38e-43b5-beac-6aa7d5a74cbb","target_id":"b0777c7da17be89abb333c81c0dcf349","source_type":"WIKI_ITEM","target_type":"CODE_SNIPPET","relationship_type":"CONTAINS","extra":"Wiki contains code snippet: backend/app/services/citation.py#204-261","gmt_create":"2026-04-24T11:02:30.067247+08:00","gmt_modified":"2026-04-24T11:02:30.067247+08:00"},{"id":1616,"source_id":"49915365-e38e-43b5-beac-6aa7d5a74cbb","target_id":"c066a8d4bffabed87a2e38ccad81c107","source_type":"WIKI_ITEM","target_type":"CODE_SNIPPET","relationship_type":"CONTAINS","extra":"Wiki contains code snippet: backend/app/api/citations.py#25-77","gmt_create":"2026-04-24T11:02:30.067743+08:00","gmt_modified":"2026-04-24T11:02:30.067743+08:00"},{"id":1617,"source_id":"49915365-e38e-43b5-beac-6aa7d5a74cbb","target_id":"26288877e8e1f6c4ff5aca12610b0218","source_type":"WIKI_ITEM","target_type":"CODE_SNIPPET","relationship_type":"CONTAINS","extra":"Wiki contains code snippet: backend/app/schemas/citation.py#7-50","gmt_create":"2026-04-24T11:02:30.06828+08:00","gmt_modified":"2026-04-24T11:02:30.06828+08:00"},{"id":1618,"source_id":"49915365-e38e-43b5-beac-6aa7d5a74cbb","target_id":"44f9c9f195e096efbd6c6a6f97880944","source_type":"WIKI_ITEM","target_type":"CODE_SNIPPET","relationship_type":"CONTAINS","extra":"Wiki contains code snippet: backend/app/api/reports.py#51-75","gmt_create":"2026-04-24T11:02:30.069039+08:00","gmt_modified":"2026-04-24T11:02:30.069039+08:00"},{"id":1619,"source_id":"58901c94d975d87e652a4dc6c8dda656","target_id":"44f9c9f195e096efbd6c6a6f97880944","source_type":"SOURCE_FILE","target_type":"CODE_SNIPPET","relationship_type":"CONTAINS","extra":"Source file contains code snippet: 51-75","gmt_create":"2026-04-24T11:02:30.069323+08:00","gmt_modified":"2026-04-24T11:02:30.069323+08:00"},{"id":1620,"source_id":"49915365-e38e-43b5-beac-6aa7d5a74cbb","target_id":"cbe8ffc1cfb98ac79c7659e968191837","source_type":"WIKI_ITEM","target_type":"CODE_SNIPPET","relationship_type":"CONTAINS","extra":"Wiki contains code snippet: backend/app/services/citation.py#343-466","gmt_create":"2026-04-24T11:02:30.069788+08:00","gmt_modified":"2026-04-24T11:02:30.069788+08:00"},{"id":1621,"source_id":"04e3926c080e795713bff683e7dc9d3e","target_id":"cbe8ffc1cfb98ac79c7659e968191837","source_type":"SOURCE_FILE","target_type":"CODE_SNIPPET","relationship_type":"CONTAINS","extra":"Source file contains code snippet: 343-466","gmt_create":"2026-04-24T11:02:30.070073+08:00","gmt_modified":"2026-04-24T11:02:30.070073+08:00"},{"id":1622,"source_id":"49915365-e38e-43b5-beac-6aa7d5a74cbb","target_id":"14c2d098319eeab16c64ff7d1447df6b","source_type":"WIKI_ITEM","target_type":"CODE_SNIPPET","relationship_type":"CONTAINS","extra":"Wiki contains code snippet: backend/app/api/reports.py#18-75","gmt_create":"2026-04-24T11:02:30.070531+08:00","gmt_modified":"2026-04-24T11:02:30.070531+08:00"},{"id":1623,"source_id":"49915365-e38e-43b5-beac-6aa7d5a74cbb","target_id":"97f9b6149bd43feb0f69cf2582ab6305","source_type":"WIKI_ITEM","target_type":"CODE_SNIPPET","relationship_type":"CONTAINS","extra":"Wiki contains code snippet: backend/app/services/subscription.py#85-117","gmt_create":"2026-04-24T11:02:30.071432+08:00","gmt_modified":"2026-04-24T11:02:30.071432+08:00"},{"id":1624,"source_id":"b250fc6c32106a7f3e0c3ad152dfc097","target_id":"97f9b6149bd43feb0f69cf2582ab6305","source_type":"SOURCE_FILE","target_type":"CODE_SNIPPET","relationship_type":"CONTAINS","extra":"Source file contains code snippet: 85-117","gmt_create":"2026-04-24T11:02:30.071724+08:00","gmt_modified":"2026-04-24T11:02:30.071724+08:00"},{"id":1625,"source_id":"49915365-e38e-43b5-beac-6aa7d5a74cbb","target_id":"ce4de96353f8f81ca825173ddbec1150","source_type":"WIKI_ITEM","target_type":"CODE_SNIPPET","relationship_type":"CONTAINS","extra":"Wiki contains code snippet: backend/app/schemas/subscription.py#12-41","gmt_create":"2026-04-24T11:02:30.072433+08:00","gmt_modified":"2026-04-24T11:02:30.072433+08:00"},{"id":1626,"source_id":"5013cbe89f1c6f03533eb218400cedb0","target_id":"ce4de96353f8f81ca825173ddbec1150","source_type":"SOURCE_FILE","target_type":"CODE_SNIPPET","relationship_type":"CONTAINS","extra":"Source file contains code snippet: 12-41","gmt_create":"2026-04-24T11:02:30.072769+08:00","gmt_modified":"2026-04-24T11:02:30.072769+08:00"},{"id":1627,"source_id":"49915365-e38e-43b5-beac-6aa7d5a74cbb","target_id":"a87a1a7c1723518159d5818c197996cc","source_type":"WIKI_ITEM","target_type":"CODE_SNIPPET","relationship_type":"CONTAINS","extra":"Wiki contains code snippet: backend/app/services/subscription.py#56-155","gmt_create":"2026-04-24T11:02:30.073186+08:00","gmt_modified":"2026-04-24T11:02:30.073186+08:00"},{"id":1628,"source_id":"b250fc6c32106a7f3e0c3ad152dfc097","target_id":"a87a1a7c1723518159d5818c197996cc","source_type":"SOURCE_FILE","target_type":"CODE_SNIPPET","relationship_type":"CONTAINS","extra":"Source file contains code snippet: 56-155","gmt_create":"2026-04-24T11:02:30.073474+08:00","gmt_modified":"2026-04-24T11:02:30.073474+08:00"},{"id":1629,"source_id":"49915365-e38e-43b5-beac-6aa7d5a74cbb","target_id":"0e4bc0a539e0ccc6832031bdaf1eb1ca","source_type":"WIKI_ITEM","target_type":"CODE_SNIPPET","relationship_type":"CONTAINS","extra":"Wiki contains code snippet: backend/app/api/admin.py#29-45","gmt_create":"2026-04-24T11:02:30.073878+08:00","gmt_modified":"2026-04-24T11:02:30.073878+08:00"},{"id":1630,"source_id":"f26740f2a1532b38c816663a4f665dbf","target_id":"0e4bc0a539e0ccc6832031bdaf1eb1ca","source_type":"SOURCE_FILE","target_type":"CODE_SNIPPET","relationship_type":"CONTAINS","extra":"Source file contains code snippet: 29-45","gmt_create":"2026-04-24T11:02:30.074211+08:00","gmt_modified":"2026-04-24T11:02:30.074211+08:00"},{"id":1631,"source_id":"49915365-e38e-43b5-beac-6aa7d5a74cbb","target_id":"f7314a4515e822cba6f37d7a8f1970f3","source_type":"WIKI_ITEM","target_type":"CODE_SNIPPET","relationship_type":"CONTAINS","extra":"Wiki contains code snippet: backend/app/services/admin.py#14-46","gmt_create":"2026-04-24T11:02:30.074677+08:00","gmt_modified":"2026-04-24T11:02:30.074677+08:00"},{"id":1632,"source_id":"3809c5ab912511e0e093ba02a4fc918f","target_id":"f7314a4515e822cba6f37d7a8f1970f3","source_type":"SOURCE_FILE","target_type":"CODE_SNIPPET","relationship_type":"CONTAINS","extra":"Source file contains code snippet: 14-46","gmt_create":"2026-04-24T11:02:30.074964+08:00","gmt_modified":"2026-04-24T11:02:30.074964+08:00"},{"id":1633,"source_id":"49915365-e38e-43b5-beac-6aa7d5a74cbb","target_id":"7f81ebbdde3496054e6f43f5eef366dc","source_type":"WIKI_ITEM","target_type":"CODE_SNIPPET","relationship_type":"CONTAINS","extra":"Wiki contains code snippet: backend/app/services/admin.py#14-188","gmt_create":"2026-04-24T11:02:30.075667+08:00","gmt_modified":"2026-04-24T11:02:30.075667+08:00"},{"id":1634,"source_id":"49915365-e38e-43b5-beac-6aa7d5a74cbb","target_id":"ef31f4aa4fbd1b6ff76eba467b757a04","source_type":"WIKI_ITEM","target_type":"CODE_SNIPPET","relationship_type":"CONTAINS","extra":"Wiki contains code snippet: backend/app/middleware/rate_limit.py#34-69","gmt_create":"2026-04-24T11:02:30.076225+08:00","gmt_modified":"2026-04-24T11:02:30.076225+08:00"},{"id":1635,"source_id":"5883a8ef4fc156d76b71ffdb5ecdf232","target_id":"ef31f4aa4fbd1b6ff76eba467b757a04","source_type":"SOURCE_FILE","target_type":"CODE_SNIPPET","relationship_type":"CONTAINS","extra":"Source file contains code snippet: 34-69","gmt_create":"2026-04-24T11:02:30.076612+08:00","gmt_modified":"2026-04-24T11:02:30.076612+08:00"},{"id":1636,"source_id":"49915365-e38e-43b5-beac-6aa7d5a74cbb","target_id":"f5978358d04c3c917d9ca5044c7f36fa","source_type":"WIKI_ITEM","target_type":"CODE_SNIPPET","relationship_type":"CONTAINS","extra":"Wiki contains code snippet: backend/app/models/user.py#11-48","gmt_create":"2026-04-24T11:02:30.077351+08:00","gmt_modified":"2026-04-24T11:02:30.077351+08:00"},{"id":1637,"source_id":"49915365-e38e-43b5-beac-6aa7d5a74cbb","target_id":"4fb8856be3a581fe8303d11b2284ca29","source_type":"WIKI_ITEM","target_type":"CODE_SNIPPET","relationship_type":"CONTAINS","extra":"Wiki contains code snippet: backend/app/models/query.py#11-55","gmt_create":"2026-04-24T11:02:30.077878+08:00","gmt_modified":"2026-04-24T11:02:30.077878+08:00"},{"id":1638,"source_id":"49915365-e38e-43b5-beac-6aa7d5a74cbb","target_id":"fd541971cebf8a7c167d717f5c5d1ff6","source_type":"WIKI_ITEM","target_type":"CODE_SNIPPET","relationship_type":"CONTAINS","extra":"Wiki contains code snippet: backend/app/models/citation_record.py#11-42","gmt_create":"2026-04-24T11:02:30.078464+08:00","gmt_modified":"2026-04-24T11:02:30.078464+08:00"},{"id":1639,"source_id":"49915365-e38e-43b5-beac-6aa7d5a74cbb","target_id":"b84f46f058847733347974841f613688","source_type":"WIKI_ITEM","target_type":"CODE_SNIPPET","relationship_type":"CONTAINS","extra":"Wiki contains code snippet: backend/app/models/query_task.py#11-39","gmt_create":"2026-04-24T11:02:30.079686+08:00","gmt_modified":"2026-04-24T11:02:30.079686+08:00"},{"id":1640,"source_id":"49915365-e38e-43b5-beac-6aa7d5a74cbb","target_id":"4d323bf0aaf4078f09726dc0890e5955","source_type":"WIKI_ITEM","target_type":"CODE_SNIPPET","relationship_type":"CONTAINS","extra":"Wiki contains code snippet: backend/app/models/subscription.py#11-37","gmt_create":"2026-04-24T11:02:30.080405+08:00","gmt_modified":"2026-04-24T11:02:30.080405+08:00"},{"id":1641,"source_id":"49915365-e38e-43b5-beac-6aa7d5a74cbb","target_id":"1a2657244414b5681afded9565a86422","source_type":"WIKI_ITEM","target_type":"CODE_SNIPPET","relationship_type":"CONTAINS","extra":"Wiki contains code snippet: backend/app/models/user.py#35-40","gmt_create":"2026-04-24T11:02:30.081664+08:00","gmt_modified":"2026-04-24T11:02:30.081664+08:00"},{"id":1642,"source_id":"49915365-e38e-43b5-beac-6aa7d5a74cbb","target_id":"acd5a29be2bdd4ae251e10ca266ffe13","source_type":"WIKI_ITEM","target_type":"CODE_SNIPPET","relationship_type":"CONTAINS","extra":"Wiki contains code snippet: backend/app/models/query.py#43-48","gmt_create":"2026-04-24T11:02:30.082422+08:00","gmt_modified":"2026-04-24T11:02:30.082422+08:00"},{"id":1643,"source_id":"49915365-e38e-43b5-beac-6aa7d5a74cbb","target_id":"27a5e2dd1d197b2e3a45be41c57a6183","source_type":"WIKI_ITEM","target_type":"CODE_SNIPPET","relationship_type":"CONTAINS","extra":"Wiki contains code snippet: backend/app/models/citation_record.py#35","gmt_create":"2026-04-24T11:02:30.083022+08:00","gmt_modified":"2026-04-24T11:02:30.083022+08:00"},{"id":1644,"source_id":"49915365-e38e-43b5-beac-6aa7d5a74cbb","target_id":"c43e8fc0c04c5ed2db7798d99c8c77b8","source_type":"WIKI_ITEM","target_type":"CODE_SNIPPET","relationship_type":"CONTAINS","extra":"Wiki contains code snippet: backend/app/models/query_task.py#34","gmt_create":"2026-04-24T11:02:30.083614+08:00","gmt_modified":"2026-04-24T11:02:30.083614+08:00"},{"id":1645,"source_id":"49915365-e38e-43b5-beac-6aa7d5a74cbb","target_id":"3a7201f4564dbcf35c5771f1b5d58cb6","source_type":"WIKI_ITEM","target_type":"CODE_SNIPPET","relationship_type":"CONTAINS","extra":"Wiki contains code snippet: backend/app/api/auth.py#46-50","gmt_create":"2026-04-24T11:02:30.084198+08:00","gmt_modified":"2026-04-24T11:02:30.084198+08:00"},{"id":1646,"source_id":"93022c8938ce318f167277cfa65c29a7","target_id":"3a7201f4564dbcf35c5771f1b5d58cb6","source_type":"SOURCE_FILE","target_type":"CODE_SNIPPET","relationship_type":"CONTAINS","extra":"Source file contains code snippet: 46-50","gmt_create":"2026-04-24T11:02:30.084522+08:00","gmt_modified":"2026-04-24T11:02:30.084522+08:00"},{"id":1647,"source_id":"49915365-e38e-43b5-beac-6aa7d5a74cbb","target_id":"a50f983ec39bac67dff5df80f6dad837","source_type":"WIKI_ITEM","target_type":"CODE_SNIPPET","relationship_type":"CONTAINS","extra":"Wiki contains code snippet: backend/app/services/query.py#59-60","gmt_create":"2026-04-24T11:02:30.084964+08:00","gmt_modified":"2026-04-24T11:02:30.084964+08:00"},{"id":1648,"source_id":"49915365-e38e-43b5-beac-6aa7d5a74cbb","target_id":"55f1628f1ab6f323710e367e12146b1a","source_type":"WIKI_ITEM","target_type":"CODE_SNIPPET","relationship_type":"CONTAINS","extra":"Wiki contains code snippet: backend/app/api/citations.py#67-71","gmt_create":"2026-04-24T11:02:30.085559+08:00","gmt_modified":"2026-04-24T11:02:30.085559+08:00"},{"id":1649,"source_id":"49915365-e38e-43b5-beac-6aa7d5a74cbb","target_id":"39c3dbe67ab2ae74446fe6a118bd8738","source_type":"WIKI_ITEM","target_type":"CODE_SNIPPET","relationship_type":"CONTAINS","extra":"Wiki contains code snippet: backend/app/api/reports.py#25-29","gmt_create":"2026-04-24T11:02:30.086053+08:00","gmt_modified":"2026-04-24T11:02:30.086053+08:00"},{"id":1650,"source_id":"58901c94d975d87e652a4dc6c8dda656","target_id":"39c3dbe67ab2ae74446fe6a118bd8738","source_type":"SOURCE_FILE","target_type":"CODE_SNIPPET","relationship_type":"CONTAINS","extra":"Source file contains code snippet: 25-29","gmt_create":"2026-04-24T11:02:30.086409+08:00","gmt_modified":"2026-04-24T11:02:30.08641+08:00"},{"id":1651,"source_id":"49915365-e38e-43b5-beac-6aa7d5a74cbb","target_id":"68d937267aab2509edc0c7b67e1b5ef6","source_type":"WIKI_ITEM","target_type":"CODE_SNIPPET","relationship_type":"CONTAINS","extra":"Wiki contains code snippet: backend/app/api/subscriptions.py#53-57","gmt_create":"2026-04-24T11:02:30.086938+08:00","gmt_modified":"2026-04-24T11:02:30.086938+08:00"},{"id":1652,"source_id":"5386144bf3c668c6fa14481c0d85a214","target_id":"68d937267aab2509edc0c7b67e1b5ef6","source_type":"SOURCE_FILE","target_type":"CODE_SNIPPET","relationship_type":"CONTAINS","extra":"Source file contains code snippet: 53-57","gmt_create":"2026-04-24T11:02:30.087245+08:00","gmt_modified":"2026-04-24T11:02:30.087245+08:00"},{"id":1653,"source_id":"49915365-e38e-43b5-beac-6aa7d5a74cbb","target_id":"3d0bf5a05f6a7d2b8b12bb91e8f93642","source_type":"WIKI_ITEM","target_type":"CODE_SNIPPET","relationship_type":"CONTAINS","extra":"Wiki contains code snippet: backend/app/api/admin.py#22-25","gmt_create":"2026-04-24T11:02:30.087665+08:00","gmt_modified":"2026-04-24T11:02:30.087665+08:00"},{"id":1654,"source_id":"f26740f2a1532b38c816663a4f665dbf","target_id":"3d0bf5a05f6a7d2b8b12bb91e8f93642","source_type":"SOURCE_FILE","target_type":"CODE_SNIPPET","relationship_type":"CONTAINS","extra":"Source file contains code snippet: 22-25","gmt_create":"2026-04-24T11:02:30.08803+08:00","gmt_modified":"2026-04-24T11:02:30.08803+08:00"},{"id":1655,"source_id":"49915365-e38e-43b5-beac-6aa7d5a74cbb","target_id":"a9c1b0716ae36af22fce6148c2e40ce5","source_type":"WIKI_ITEM","target_type":"CODE_SNIPPET","relationship_type":"CONTAINS","extra":"Wiki contains code snippet: backend/app/middleware/rate_limit.py#47-49","gmt_create":"2026-04-24T11:02:30.088435+08:00","gmt_modified":"2026-04-24T11:02:30.088435+08:00"},{"id":1656,"source_id":"5883a8ef4fc156d76b71ffdb5ecdf232","target_id":"a9c1b0716ae36af22fce6148c2e40ce5","source_type":"SOURCE_FILE","target_type":"CODE_SNIPPET","relationship_type":"CONTAINS","extra":"Source file contains code snippet: 47-49","gmt_create":"2026-04-24T11:02:30.088761+08:00","gmt_modified":"2026-04-24T11:02:30.088762+08:00"},{"id":1657,"source_id":"34e572eb-6fc8-4de7-8061-63783ef8be24","target_id":"2793782c-91c8-4052-b9db-39513426c736","source_type":"WIKI_ITEM","target_type":"WIKI_ITEM","relationship_type":"PARENT_CHILD","extra":"Wiki parent-child relationship: 34e572eb-6fc8-4de7-8061-63783ef8be24 -\u003e 2793782c-91c8-4052-b9db-39513426c736","gmt_create":"2026-04-24T11:08:43.063241+08:00","gmt_modified":"2026-04-24T11:08:43.063241+08:00"},{"id":1658,"source_id":"34e572eb-6fc8-4de7-8061-63783ef8be24","target_id":"e23bd86e-b4ac-40eb-b1c1-38d929fd5419","source_type":"WIKI_ITEM","target_type":"WIKI_ITEM","relationship_type":"PARENT_CHILD","extra":"Wiki parent-child relationship: 34e572eb-6fc8-4de7-8061-63783ef8be24 -\u003e e23bd86e-b4ac-40eb-b1c1-38d929fd5419","gmt_create":"2026-04-24T11:08:43.063978+08:00","gmt_modified":"2026-04-24T11:08:43.063978+08:00"},{"id":1659,"source_id":"34e572eb-6fc8-4de7-8061-63783ef8be24","target_id":"70b3948e-f456-42d2-b7ad-a0097ad5ee5f","source_type":"WIKI_ITEM","target_type":"WIKI_ITEM","relationship_type":"PARENT_CHILD","extra":"Wiki parent-child relationship: 34e572eb-6fc8-4de7-8061-63783ef8be24 -\u003e 70b3948e-f456-42d2-b7ad-a0097ad5ee5f","gmt_create":"2026-04-24T11:08:43.064613+08:00","gmt_modified":"2026-04-24T11:08:43.064613+08:00"},{"id":1660,"source_id":"34e572eb-6fc8-4de7-8061-63783ef8be24","target_id":"1c4316a1-f1d7-46da-bcfc-ea2fa0c56110","source_type":"WIKI_ITEM","target_type":"WIKI_ITEM","relationship_type":"PARENT_CHILD","extra":"Wiki parent-child relationship: 34e572eb-6fc8-4de7-8061-63783ef8be24 -\u003e 1c4316a1-f1d7-46da-bcfc-ea2fa0c56110","gmt_create":"2026-04-24T11:08:43.065266+08:00","gmt_modified":"2026-04-24T11:08:43.065266+08:00"},{"id":1661,"source_id":"34e572eb-6fc8-4de7-8061-63783ef8be24","target_id":"7e679d62-c415-4d6a-a7e5-d41d00e0ed69","source_type":"WIKI_ITEM","target_type":"WIKI_ITEM","relationship_type":"PARENT_CHILD","extra":"Wiki parent-child relationship: 34e572eb-6fc8-4de7-8061-63783ef8be24 -\u003e 7e679d62-c415-4d6a-a7e5-d41d00e0ed69","gmt_create":"2026-04-24T11:08:43.065797+08:00","gmt_modified":"2026-04-24T11:08:43.065797+08:00"},{"id":1662,"source_id":"c7eb113b-b503-4d83-be7f-9ccf3350c9d9","target_id":"f94da0b4-8a07-4de1-b0b3-d3b32a12c3c1","source_type":"WIKI_ITEM","target_type":"WIKI_ITEM","relationship_type":"PARENT_CHILD","extra":"Wiki parent-child relationship: c7eb113b-b503-4d83-be7f-9ccf3350c9d9 -\u003e f94da0b4-8a07-4de1-b0b3-d3b32a12c3c1","gmt_create":"2026-04-24T11:08:43.066252+08:00","gmt_modified":"2026-04-24T11:08:43.066252+08:00"},{"id":1663,"source_id":"c7eb113b-b503-4d83-be7f-9ccf3350c9d9","target_id":"df661133-efbf-43fe-97c3-f581c81f47a7","source_type":"WIKI_ITEM","target_type":"WIKI_ITEM","relationship_type":"PARENT_CHILD","extra":"Wiki parent-child relationship: c7eb113b-b503-4d83-be7f-9ccf3350c9d9 -\u003e df661133-efbf-43fe-97c3-f581c81f47a7","gmt_create":"2026-04-24T11:08:43.066859+08:00","gmt_modified":"2026-04-24T11:08:43.06686+08:00"},{"id":1664,"source_id":"c7eb113b-b503-4d83-be7f-9ccf3350c9d9","target_id":"11936bb5-374f-40f4-bb53-b75264fc4b9d","source_type":"WIKI_ITEM","target_type":"WIKI_ITEM","relationship_type":"PARENT_CHILD","extra":"Wiki parent-child relationship: c7eb113b-b503-4d83-be7f-9ccf3350c9d9 -\u003e 11936bb5-374f-40f4-bb53-b75264fc4b9d","gmt_create":"2026-04-24T11:08:43.06741+08:00","gmt_modified":"2026-04-24T11:08:43.06741+08:00"},{"id":1665,"source_id":"c7eb113b-b503-4d83-be7f-9ccf3350c9d9","target_id":"23ad3419-5473-4e2c-ac87-d9715090279d","source_type":"WIKI_ITEM","target_type":"WIKI_ITEM","relationship_type":"PARENT_CHILD","extra":"Wiki parent-child relationship: c7eb113b-b503-4d83-be7f-9ccf3350c9d9 -\u003e 23ad3419-5473-4e2c-ac87-d9715090279d","gmt_create":"2026-04-24T11:08:43.067912+08:00","gmt_modified":"2026-04-24T11:08:43.067912+08:00"},{"id":1666,"source_id":"c7eb113b-b503-4d83-be7f-9ccf3350c9d9","target_id":"19e75845-5147-4aeb-90be-16f3aa270465","source_type":"WIKI_ITEM","target_type":"WIKI_ITEM","relationship_type":"PARENT_CHILD","extra":"Wiki parent-child relationship: c7eb113b-b503-4d83-be7f-9ccf3350c9d9 -\u003e 19e75845-5147-4aeb-90be-16f3aa270465","gmt_create":"2026-04-24T11:08:43.068381+08:00","gmt_modified":"2026-04-24T11:08:43.068382+08:00"},{"id":1667,"source_id":"c7eb113b-b503-4d83-be7f-9ccf3350c9d9","target_id":"83fe6837-7874-4467-8114-103062f15f58","source_type":"WIKI_ITEM","target_type":"WIKI_ITEM","relationship_type":"PARENT_CHILD","extra":"Wiki parent-child relationship: c7eb113b-b503-4d83-be7f-9ccf3350c9d9 -\u003e 83fe6837-7874-4467-8114-103062f15f58","gmt_create":"2026-04-24T11:08:43.068809+08:00","gmt_modified":"2026-04-24T11:08:43.068809+08:00"},{"id":1668,"source_id":"3af3bb9e-4d99-4dc3-b1ed-2686db385c26","target_id":"c112a3f4-b0a1-4c4a-a325-e3ede8c90be6","source_type":"WIKI_ITEM","target_type":"WIKI_ITEM","relationship_type":"PARENT_CHILD","extra":"Wiki parent-child relationship: 3af3bb9e-4d99-4dc3-b1ed-2686db385c26 -\u003e c112a3f4-b0a1-4c4a-a325-e3ede8c90be6","gmt_create":"2026-04-24T11:08:43.069423+08:00","gmt_modified":"2026-04-24T11:08:43.069423+08:00"},{"id":1669,"source_id":"3af3bb9e-4d99-4dc3-b1ed-2686db385c26","target_id":"2b32ec11-d228-42c0-9232-103ba7e44f71","source_type":"WIKI_ITEM","target_type":"WIKI_ITEM","relationship_type":"PARENT_CHILD","extra":"Wiki parent-child relationship: 3af3bb9e-4d99-4dc3-b1ed-2686db385c26 -\u003e 2b32ec11-d228-42c0-9232-103ba7e44f71","gmt_create":"2026-04-24T11:08:43.070039+08:00","gmt_modified":"2026-04-24T11:08:43.07004+08:00"},{"id":1670,"source_id":"3af3bb9e-4d99-4dc3-b1ed-2686db385c26","target_id":"ba0390b3-c249-4e92-a3c8-6820343aeda9","source_type":"WIKI_ITEM","target_type":"WIKI_ITEM","relationship_type":"PARENT_CHILD","extra":"Wiki parent-child relationship: 3af3bb9e-4d99-4dc3-b1ed-2686db385c26 -\u003e ba0390b3-c249-4e92-a3c8-6820343aeda9","gmt_create":"2026-04-24T11:08:43.070549+08:00","gmt_modified":"2026-04-24T11:08:43.070549+08:00"},{"id":1671,"source_id":"3af3bb9e-4d99-4dc3-b1ed-2686db385c26","target_id":"760610d4-dff6-4c6d-831f-7c9078db86a6","source_type":"WIKI_ITEM","target_type":"WIKI_ITEM","relationship_type":"PARENT_CHILD","extra":"Wiki parent-child relationship: 3af3bb9e-4d99-4dc3-b1ed-2686db385c26 -\u003e 760610d4-dff6-4c6d-831f-7c9078db86a6","gmt_create":"2026-04-24T11:08:43.071132+08:00","gmt_modified":"2026-04-24T11:08:43.071132+08:00"},{"id":1672,"source_id":"3af3bb9e-4d99-4dc3-b1ed-2686db385c26","target_id":"a40267bc-925a-4364-a01f-b96d3df60aea","source_type":"WIKI_ITEM","target_type":"WIKI_ITEM","relationship_type":"PARENT_CHILD","extra":"Wiki parent-child relationship: 3af3bb9e-4d99-4dc3-b1ed-2686db385c26 -\u003e a40267bc-925a-4364-a01f-b96d3df60aea","gmt_create":"2026-04-24T11:08:43.07161+08:00","gmt_modified":"2026-04-24T11:08:43.07161+08:00"},{"id":1673,"source_id":"3af3bb9e-4d99-4dc3-b1ed-2686db385c26","target_id":"7bd2c461-81b0-48e8-8cb3-b4b14305806d","source_type":"WIKI_ITEM","target_type":"WIKI_ITEM","relationship_type":"PARENT_CHILD","extra":"Wiki parent-child relationship: 3af3bb9e-4d99-4dc3-b1ed-2686db385c26 -\u003e 7bd2c461-81b0-48e8-8cb3-b4b14305806d","gmt_create":"2026-04-24T11:08:43.072138+08:00","gmt_modified":"2026-04-24T11:08:43.072138+08:00"},{"id":1674,"source_id":"ffbb970e-56e0-40ad-bd88-1a1e55482d96","target_id":"d5c75004-b01b-416f-850a-4791c5489a32","source_type":"WIKI_ITEM","target_type":"WIKI_ITEM","relationship_type":"PARENT_CHILD","extra":"Wiki parent-child relationship: ffbb970e-56e0-40ad-bd88-1a1e55482d96 -\u003e d5c75004-b01b-416f-850a-4791c5489a32","gmt_create":"2026-04-24T11:08:43.072666+08:00","gmt_modified":"2026-04-24T11:08:43.072666+08:00"},{"id":1675,"source_id":"ffbb970e-56e0-40ad-bd88-1a1e55482d96","target_id":"c3fa653f-8dd7-41fe-8c2e-8b60adbf70f4","source_type":"WIKI_ITEM","target_type":"WIKI_ITEM","relationship_type":"PARENT_CHILD","extra":"Wiki parent-child relationship: ffbb970e-56e0-40ad-bd88-1a1e55482d96 -\u003e c3fa653f-8dd7-41fe-8c2e-8b60adbf70f4","gmt_create":"2026-04-24T11:08:43.073112+08:00","gmt_modified":"2026-04-24T11:08:43.073112+08:00"},{"id":1676,"source_id":"ffbb970e-56e0-40ad-bd88-1a1e55482d96","target_id":"262a3941-fdc6-46b0-b767-be40aa9d5761","source_type":"WIKI_ITEM","target_type":"WIKI_ITEM","relationship_type":"PARENT_CHILD","extra":"Wiki parent-child relationship: ffbb970e-56e0-40ad-bd88-1a1e55482d96 -\u003e 262a3941-fdc6-46b0-b767-be40aa9d5761","gmt_create":"2026-04-24T11:08:43.073598+08:00","gmt_modified":"2026-04-24T11:08:43.073599+08:00"},{"id":1677,"source_id":"ffbb970e-56e0-40ad-bd88-1a1e55482d96","target_id":"7c0201f7-9e02-4cba-9ee1-81c3477f049a","source_type":"WIKI_ITEM","target_type":"WIKI_ITEM","relationship_type":"PARENT_CHILD","extra":"Wiki parent-child relationship: ffbb970e-56e0-40ad-bd88-1a1e55482d96 -\u003e 7c0201f7-9e02-4cba-9ee1-81c3477f049a","gmt_create":"2026-04-24T11:08:43.074022+08:00","gmt_modified":"2026-04-24T11:08:43.074022+08:00"},{"id":1678,"source_id":"49915365-e38e-43b5-beac-6aa7d5a74cbb","target_id":"7c7564ee-7fe2-4555-8ff0-4ec1b757997a","source_type":"WIKI_ITEM","target_type":"WIKI_ITEM","relationship_type":"PARENT_CHILD","extra":"Wiki parent-child relationship: 49915365-e38e-43b5-beac-6aa7d5a74cbb -\u003e 7c7564ee-7fe2-4555-8ff0-4ec1b757997a","gmt_create":"2026-04-24T11:08:43.076175+08:00","gmt_modified":"2026-04-24T11:08:43.076176+08:00"},{"id":1679,"source_id":"49915365-e38e-43b5-beac-6aa7d5a74cbb","target_id":"74d3018f-4e23-4687-8bf4-7fb403f479f7","source_type":"WIKI_ITEM","target_type":"WIKI_ITEM","relationship_type":"PARENT_CHILD","extra":"Wiki parent-child relationship: 49915365-e38e-43b5-beac-6aa7d5a74cbb -\u003e 74d3018f-4e23-4687-8bf4-7fb403f479f7","gmt_create":"2026-04-24T11:08:43.07673+08:00","gmt_modified":"2026-04-24T11:08:43.07673+08:00"},{"id":1680,"source_id":"49915365-e38e-43b5-beac-6aa7d5a74cbb","target_id":"737f8d6c-bd8f-4c11-b142-71a400423323","source_type":"WIKI_ITEM","target_type":"WIKI_ITEM","relationship_type":"PARENT_CHILD","extra":"Wiki parent-child relationship: 49915365-e38e-43b5-beac-6aa7d5a74cbb -\u003e 737f8d6c-bd8f-4c11-b142-71a400423323","gmt_create":"2026-04-24T11:08:43.077384+08:00","gmt_modified":"2026-04-24T11:08:43.077384+08:00"},{"id":1681,"source_id":"49915365-e38e-43b5-beac-6aa7d5a74cbb","target_id":"ae62f4a8-8840-4c8e-9a42-3373370299ff","source_type":"WIKI_ITEM","target_type":"WIKI_ITEM","relationship_type":"PARENT_CHILD","extra":"Wiki parent-child relationship: 49915365-e38e-43b5-beac-6aa7d5a74cbb -\u003e ae62f4a8-8840-4c8e-9a42-3373370299ff","gmt_create":"2026-04-24T11:08:43.078078+08:00","gmt_modified":"2026-04-24T11:08:43.078078+08:00"},{"id":1682,"source_id":"1c4316a1-f1d7-46da-bcfc-ea2fa0c56110","target_id":"ec2f1708-d31e-42bb-8959-fa405db7d6da","source_type":"WIKI_ITEM","target_type":"WIKI_ITEM","relationship_type":"PARENT_CHILD","extra":"Wiki parent-child relationship: 1c4316a1-f1d7-46da-bcfc-ea2fa0c56110 -\u003e ec2f1708-d31e-42bb-8959-fa405db7d6da","gmt_create":"2026-04-24T11:08:43.086144+08:00","gmt_modified":"2026-04-24T11:08:43.086144+08:00"},{"id":1683,"source_id":"1c4316a1-f1d7-46da-bcfc-ea2fa0c56110","target_id":"2059d1cd-98a3-4b7f-b29b-69acf8a0d751","source_type":"WIKI_ITEM","target_type":"WIKI_ITEM","relationship_type":"PARENT_CHILD","extra":"Wiki parent-child relationship: 1c4316a1-f1d7-46da-bcfc-ea2fa0c56110 -\u003e 2059d1cd-98a3-4b7f-b29b-69acf8a0d751","gmt_create":"2026-04-24T11:08:43.0867+08:00","gmt_modified":"2026-04-24T11:08:43.0867+08:00"},{"id":1684,"source_id":"1c4316a1-f1d7-46da-bcfc-ea2fa0c56110","target_id":"d474a7a6-e056-4456-ba79-4aedbb7add58","source_type":"WIKI_ITEM","target_type":"WIKI_ITEM","relationship_type":"PARENT_CHILD","extra":"Wiki parent-child relationship: 1c4316a1-f1d7-46da-bcfc-ea2fa0c56110 -\u003e d474a7a6-e056-4456-ba79-4aedbb7add58","gmt_create":"2026-04-24T11:08:43.087214+08:00","gmt_modified":"2026-04-24T11:08:43.087214+08:00"},{"id":1685,"source_id":"1c4316a1-f1d7-46da-bcfc-ea2fa0c56110","target_id":"2d7c030d-7b82-418c-9a16-67b067cac93c","source_type":"WIKI_ITEM","target_type":"WIKI_ITEM","relationship_type":"PARENT_CHILD","extra":"Wiki parent-child relationship: 1c4316a1-f1d7-46da-bcfc-ea2fa0c56110 -\u003e 2d7c030d-7b82-418c-9a16-67b067cac93c","gmt_create":"2026-04-24T11:08:43.087792+08:00","gmt_modified":"2026-04-24T11:08:43.087792+08:00"}],"source_files":[{"id":"12e2c3d7b9a92dc44a6ee29b85e10df6","path":"frontend/app/layout.tsx","filename":"layout.tsx","gmt_create":"2026-04-23T15:19:43.754128+08:00","gmt_modified":"2026-04-23T15:19:43.754129+08:00"},{"id":"2a1c745c7b3fb7f600596be3d979bba1","path":"frontend/app/(dashboard","filename":"(dashboard","gmt_create":"2026-04-23T15:19:43.756075+08:00","gmt_modified":"2026-04-23T15:19:43.756075+08:00"},{"id":"eca13a610badfc5ffc6210827fb96991","path":"frontend/components/layout/header.tsx","filename":"header.tsx","gmt_create":"2026-04-23T15:19:43.756308+08:00","gmt_modified":"2026-04-23T15:19:43.756308+08:00"},{"id":"18a0651d895fba9bb4e0c0229459efdc","path":"frontend/components/layout/sidebar.tsx","filename":"sidebar.tsx","gmt_create":"2026-04-23T15:19:43.756496+08:00","gmt_modified":"2026-04-23T15:19:43.756496+08:00"},{"id":"5d7886d0dc99f81073a578b8aefdd375","path":"frontend/lib/api.ts","filename":"api.ts","gmt_create":"2026-04-23T15:19:43.756648+08:00","gmt_modified":"2026-04-23T15:19:43.756648+08:00"},{"id":"0c0b0f4e2cf44facd9d5b57de0d0bf0c","path":"frontend/components/ui/table.tsx","filename":"table.tsx","gmt_create":"2026-04-23T15:19:43.758184+08:00","gmt_modified":"2026-04-23T15:19:43.758184+08:00"},{"id":"108b0c4b4dcfb6aa39a5eb138225c148","path":"frontend/components/ui/dialog.tsx","filename":"dialog.tsx","gmt_create":"2026-04-23T15:19:43.75905+08:00","gmt_modified":"2026-04-23T15:19:43.75905+08:00"},{"id":"ef72f0c3cedb9fd9a87352fe493053dc","path":"frontend/lib/platforms.ts","filename":"platforms.ts","gmt_create":"2026-04-23T15:19:43.759223+08:00","gmt_modified":"2026-04-23T15:19:43.759223+08:00"},{"id":"f93ae024fe0a2e69698037dff6df205f","path":"frontend/lib/utils.ts","filename":"utils.ts","gmt_create":"2026-04-23T15:19:43.759351+08:00","gmt_modified":"2026-04-23T15:19:43.759351+08:00"},{"id":"d5f2266643d2011c66e86af088ec637f","path":"frontend/components/charts/trend-chart.tsx","filename":"trend-chart.tsx","gmt_create":"2026-04-23T15:19:43.759489+08:00","gmt_modified":"2026-04-23T15:19:43.759489+08:00"},{"id":"f1a7d61831cc0a45ac6220294f15c21d","path":"frontend/components/charts/platform-chart.tsx","filename":"platform-chart.tsx","gmt_create":"2026-04-23T15:19:43.759606+08:00","gmt_modified":"2026-04-23T15:19:43.759606+08:00"},{"id":"9228ff67d4c757a85d9421b71f4b29f5","path":"backend/app/main.py","filename":"main.py","gmt_create":"2026-04-23T15:19:45.5873+08:00","gmt_modified":"2026-04-23T15:19:45.5873+08:00"},{"id":"93022c8938ce318f167277cfa65c29a7","path":"backend/app/api/auth.py","filename":"auth.py","gmt_create":"2026-04-23T15:19:45.587785+08:00","gmt_modified":"2026-04-23T15:19:45.587786+08:00"},{"id":"6b3d903205941aa9391dd90016e1102c","path":"backend/app/api/queries.py","filename":"queries.py","gmt_create":"2026-04-23T15:19:45.588167+08:00","gmt_modified":"2026-04-23T15:19:45.588167+08:00"},{"id":"7538ffe4902ab6041adb28b19844962a","path":"backend/app/api/citations.py","filename":"citations.py","gmt_create":"2026-04-23T15:19:45.588473+08:00","gmt_modified":"2026-04-23T15:19:45.588473+08:00"},{"id":"58901c94d975d87e652a4dc6c8dda656","path":"backend/app/api/reports.py","filename":"reports.py","gmt_create":"2026-04-23T15:19:45.588695+08:00","gmt_modified":"2026-04-23T15:19:45.588695+08:00"},{"id":"9d08667997a868fc07c9b4e328e44224","path":"backend/app/api/deps.py","filename":"deps.py","gmt_create":"2026-04-23T15:19:45.588857+08:00","gmt_modified":"2026-04-23T15:19:45.588857+08:00"},{"id":"e0c0ca66b8b81cf66e078a7ab162c07f","path":"backend/app/schemas/auth.py","filename":"auth.py","gmt_create":"2026-04-23T15:19:45.589011+08:00","gmt_modified":"2026-04-23T15:19:45.589011+08:00"},{"id":"f301b79d833233ce39d350e82a71c938","path":"backend/app/schemas/query.py","filename":"query.py","gmt_create":"2026-04-23T15:19:45.589202+08:00","gmt_modified":"2026-04-23T15:19:45.589202+08:00"},{"id":"1a3336b4af8a39a055e912724338580c","path":"backend/app/schemas/citation.py","filename":"citation.py","gmt_create":"2026-04-23T15:19:45.589399+08:00","gmt_modified":"2026-04-23T15:19:45.589399+08:00"},{"id":"4d2f3847b7c10634733118b70a1aea0b","path":"backend/app/services/auth.py","filename":"auth.py","gmt_create":"2026-04-23T15:19:45.589591+08:00","gmt_modified":"2026-04-23T15:19:45.589591+08:00"},{"id":"88d22de3b2a7419868e8ae19130d860c","path":"backend/app/services/query.py","filename":"query.py","gmt_create":"2026-04-23T15:19:45.589732+08:00","gmt_modified":"2026-04-23T15:19:45.589732+08:00"},{"id":"04e3926c080e795713bff683e7dc9d3e","path":"backend/app/services/citation.py","filename":"citation.py","gmt_create":"2026-04-23T15:19:45.589852+08:00","gmt_modified":"2026-04-23T15:19:45.589852+08:00"},{"id":"9ff19022ef915615911280e3c49ed44b","path":"backend/app/config.py","filename":"config.py","gmt_create":"2026-04-23T15:19:45.589987+08:00","gmt_modified":"2026-04-23T15:19:45.589987+08:00"},{"id":"c59f8c276697a070dffc581fe94d809c","path":"backend/app/models/user.py","filename":"user.py","gmt_create":"2026-04-23T15:19:45.590197+08:00","gmt_modified":"2026-04-23T15:19:45.590198+08:00"},{"id":"b74caccb06844efcdb14d8324cff65c2","path":"backend/app/models/query.py","filename":"query.py","gmt_create":"2026-04-23T15:19:45.590343+08:00","gmt_modified":"2026-04-23T15:19:45.590344+08:00"},{"id":"b4a81ef789630d0af6a8d50859d01bf3","path":"backend/app/models/citation_record.py","filename":"citation_record.py","gmt_create":"2026-04-23T15:19:45.590489+08:00","gmt_modified":"2026-04-23T15:19:45.590489+08:00"},{"id":"069738f21ac2da7349d22683e8c36929","path":"backend/app/models/query_task.py","filename":"query_task.py","gmt_create":"2026-04-23T15:19:45.59062+08:00","gmt_modified":"2026-04-23T15:19:45.59062+08:00"},{"id":"5cbb1e3f112aeba62a14b0b8999fc0f5","path":"backend/app/workers/scheduler.py","filename":"scheduler.py","gmt_create":"2026-04-23T15:20:08.953491+08:00","gmt_modified":"2026-04-23T15:20:08.953491+08:00"},{"id":"74040de652d5e57f548bb5c4adc3e1a0","path":"backend/app/workers/citation_engine.py","filename":"citation_engine.py","gmt_create":"2026-04-23T15:20:08.953836+08:00","gmt_modified":"2026-04-23T15:20:08.953837+08:00"},{"id":"8f973791233c698b3e64a4fb28a93d4b","path":"backend/app/workers/platforms/kimi.py","filename":"kimi.py","gmt_create":"2026-04-23T15:20:08.954103+08:00","gmt_modified":"2026-04-23T15:20:08.954103+08:00"},{"id":"f642fc1c2f34e15572d9d98aa6c18813","path":"backend/app/workers/platforms/wenxin.py","filename":"wenxin.py","gmt_create":"2026-04-23T15:20:08.954273+08:00","gmt_modified":"2026-04-23T15:20:08.954273+08:00"},{"id":"a16cf42e9559523c4f96ca4c79f9488d","path":"backend/app/workers/platforms/base.py","filename":"base.py","gmt_create":"2026-04-23T15:20:08.954406+08:00","gmt_modified":"2026-04-23T15:20:08.954406+08:00"},{"id":"b0c428683c8a3e6922d90ca0d8c2736d","path":"backend/app/database.py","filename":"database.py","gmt_create":"2026-04-23T15:20:08.955702+08:00","gmt_modified":"2026-04-23T15:20:08.955702+08:00"},{"id":"b2f0d46a31a5441594f2e777365fc156","path":"tests/test_scheduler.py","filename":"test_scheduler.py","gmt_create":"2026-04-23T15:20:08.95621+08:00","gmt_modified":"2026-04-23T15:20:08.95621+08:00"},{"id":"0613e76b9679be7f998fb8fd8056e686","path":"tests/test_queries.py","filename":"test_queries.py","gmt_create":"2026-04-23T15:20:08.956336+08:00","gmt_modified":"2026-04-23T15:20:08.956336+08:00"},{"id":"99fe1b288fd41daa86c2dfbab819abf0","path":"backend/app/models/__init__.py","filename":"__init__.py","gmt_create":"2026-04-23T15:21:46.682639+08:00","gmt_modified":"2026-04-23T15:21:46.682639+08:00"},{"id":"bceca00463fe55d3bcafda728f97f723","path":"backend/app/models/subscription.py","filename":"subscription.py","gmt_create":"2026-04-23T15:21:46.684259+08:00","gmt_modified":"2026-04-23T15:21:46.684259+08:00"},{"id":"d4f95fcf50683b5bf6167c7d2a6b126d","path":"backend/alembic/versions/488d0bd5ab01_initial_migration.py","filename":"488d0bd5ab01_initial_migration.py","gmt_create":"2026-04-23T15:21:46.684619+08:00","gmt_modified":"2026-04-23T15:21:46.684619+08:00"},{"id":"0ef1efea889dba3e1f299626df479571","path":"tests/conftest.py","filename":"conftest.py","gmt_create":"2026-04-23T15:22:15.981194+08:00","gmt_modified":"2026-04-23T15:22:15.981194+08:00"},{"id":"389d631bc6c7111ba411b0b79fca455e","path":"tests/test_auth.py","filename":"test_auth.py","gmt_create":"2026-04-23T15:22:15.98141+08:00","gmt_modified":"2026-04-23T15:22:15.98141+08:00"},{"id":"80a0429cc47931de27ddb17a62b8dd9c","path":"tests/test_business_flow.py","filename":"test_business_flow.py","gmt_create":"2026-04-23T15:22:15.981566+08:00","gmt_modified":"2026-04-23T15:22:15.981567+08:00"},{"id":"b07a4fb9cecbbd66a6910ccbc7651f19","path":"tests/test_citation_engine.py","filename":"test_citation_engine.py","gmt_create":"2026-04-23T15:22:15.981715+08:00","gmt_modified":"2026-04-23T15:22:15.981715+08:00"},{"id":"42ff5383133d176cec9eb88682483be3","path":"tests/test_citations.py","filename":"test_citations.py","gmt_create":"2026-04-23T15:22:15.981831+08:00","gmt_modified":"2026-04-23T15:22:15.981831+08:00"},{"id":"aaf5bce6be82d2f947bfa5c1806de452","path":"frontend/package.json","filename":"package.json","gmt_create":"2026-04-23T15:22:23.492837+08:00","gmt_modified":"2026-04-23T15:22:23.492837+08:00"},{"id":"01056dad8851d3e9bd532eb4cab33792","path":"frontend/tailwind.config.ts","filename":"tailwind.config.ts","gmt_create":"2026-04-23T15:22:23.495792+08:00","gmt_modified":"2026-04-23T15:22:23.495792+08:00"},{"id":"ac1acbc54c49ee1de13369f6c6827568","path":"frontend/components/ui/button.tsx","filename":"button.tsx","gmt_create":"2026-04-23T15:22:23.496353+08:00","gmt_modified":"2026-04-23T15:22:23.496353+08:00"},{"id":"0186dc8a89340139a84e1e3c5571a57f","path":"frontend/components/ui/dropdown-menu.tsx","filename":"dropdown-menu.tsx","gmt_create":"2026-04-23T15:22:23.496869+08:00","gmt_modified":"2026-04-23T15:22:23.496869+08:00"},{"id":"3cf787fa77a15b2b1783560c6d83ed21","path":"frontend/components/ui/input.tsx","filename":"input.tsx","gmt_create":"2026-04-23T15:22:23.497127+08:00","gmt_modified":"2026-04-23T15:22:23.497128+08:00"},{"id":"3c56e1c079959bfcc985183805e5874f","path":"frontend/components/ui/select.tsx","filename":"select.tsx","gmt_create":"2026-04-23T15:22:23.497457+08:00","gmt_modified":"2026-04-23T15:22:23.497457+08:00"},{"id":"0d5ef537f7c0b8c390f8b31d7cf47b56","path":"frontend/components/ui/card.tsx","filename":"card.tsx","gmt_create":"2026-04-23T15:22:23.497745+08:00","gmt_modified":"2026-04-23T15:22:23.497745+08:00"},{"id":"51821ca9ec2a1c972f3c9d111e19db8a","path":"frontend/components/ui/badge.tsx","filename":"badge.tsx","gmt_create":"2026-04-23T15:22:23.498034+08:00","gmt_modified":"2026-04-23T15:22:23.498034+08:00"},{"id":"beb87ab5aad9532647e9dbd2db7ef587","path":"frontend/components/ui/tabs.tsx","filename":"tabs.tsx","gmt_create":"2026-04-23T15:22:23.498711+08:00","gmt_modified":"2026-04-23T15:22:23.498711+08:00"},{"id":"792b8e2c16c9ff2095d83b8972313be4","path":"frontend/components/ui/label.tsx","filename":"label.tsx","gmt_create":"2026-04-23T15:22:23.499031+08:00","gmt_modified":"2026-04-23T15:22:23.499031+08:00"},{"id":"546e01c5f73aaf5140eee922f4b9a441","path":"frontend/components/providers.tsx","filename":"providers.tsx","gmt_create":"2026-04-23T15:22:23.499298+08:00","gmt_modified":"2026-04-23T15:22:23.499298+08:00"},{"id":"e68ad5186f1e47610ab3d9f14a794393","path":"backend/app/workers/platforms/tongyi.py","filename":"tongyi.py","gmt_create":"2026-04-23T20:31:36.476814+08:00","gmt_modified":"2026-04-23T20:31:36.476814+08:00"},{"id":"404f6d0765a8c6e77e33b7fc21b377a4","path":"backend/app/workers/platforms/doubao.py","filename":"doubao.py","gmt_create":"2026-04-23T20:31:36.477414+08:00","gmt_modified":"2026-04-23T20:31:36.477414+08:00"},{"id":"303e80519e946904d1cb3ac32cbb0814","path":"backend/app/workers/platforms/qingyan.py","filename":"qingyan.py","gmt_create":"2026-04-23T20:31:36.477731+08:00","gmt_modified":"2026-04-23T20:31:36.477731+08:00"},{"id":"5af7301fe056fc3d10820d820e8ad777","path":"backend/app/workers/platforms/tiangong.py","filename":"tiangong.py","gmt_create":"2026-04-23T20:31:36.477969+08:00","gmt_modified":"2026-04-23T20:31:36.477969+08:00"},{"id":"0e38ad5d2d3daaad08c9302df8805b15","path":"backend/app/workers/platforms/xinghuo.py","filename":"xinghuo.py","gmt_create":"2026-04-23T20:31:36.47825+08:00","gmt_modified":"2026-04-23T20:31:36.47825+08:00"},{"id":"6a63f048c16c60c5d2d57012c810ee0e","path":"backend/app/workers/platforms/search_engine.py","filename":"search_engine.py","gmt_create":"2026-04-23T20:31:36.478564+08:00","gmt_modified":"2026-04-23T20:31:36.478564+08:00"},{"id":"a26ee01cf41da3b956e1650448c156fa","path":"backend/requirements.txt","filename":"requirements.txt","gmt_create":"2026-04-23T20:31:36.48051+08:00","gmt_modified":"2026-04-23T20:31:36.48051+08:00"},{"id":"e9b52adbec3c07cf021e488dd3f99ab4","path":"backend/Dockerfile","filename":"Dockerfile","gmt_create":"2026-04-23T20:31:50.452043+08:00","gmt_modified":"2026-04-23T20:31:50.452043+08:00"},{"id":"4a56ef5fca60bc63480b457cab3832f0","path":"backend/app/workers/platforms/__init__.py","filename":"__init__.py","gmt_create":"2026-04-23T20:35:18.583102+08:00","gmt_modified":"2026-04-23T20:35:18.583102+08:00"},{"id":"36dd0ad3ee6bc75a480ad8a62268e80e","path":"backend/app/workers/models/query.py","filename":"query.py","gmt_create":"2026-04-23T20:35:18.58383+08:00","gmt_modified":"2026-04-23T20:35:18.58383+08:00"},{"id":"a680d4819f5da57fe9fa0e6bc708f380","path":"backend/alembic/env.py","filename":"env.py","gmt_create":"2026-04-23T20:35:45.568869+08:00","gmt_modified":"2026-04-23T20:35:45.56887+08:00"},{"id":"f6e6948dd0cdd3894bd9928b21feb979","path":"backend/alembic/versions/b2c4d6e8fa10_add_confidence_match_type_to_citation_records.py","filename":"b2c4d6e8fa10_add_confidence_match_type_to_citation_records.py","gmt_create":"2026-04-23T20:35:45.569946+08:00","gmt_modified":"2026-04-23T20:35:45.569946+08:00"},{"id":"50f2e6bdc4a79e69bd43ea8d6fec67fe","path":"backend/alembic.ini","filename":"alembic.ini","gmt_create":"2026-04-23T20:35:45.570621+08:00","gmt_modified":"2026-04-23T20:35:45.570621+08:00"},{"id":"fc6242433ae9506bcc0bf4cb0dce1413","path":"docker-compose.yml","filename":"docker-compose.yml","gmt_create":"2026-04-23T20:35:45.574312+08:00","gmt_modified":"2026-04-23T20:35:45.574314+08:00"},{"id":"5e414f2ef9b69e55e00ab15f85b9291a","path":"frontend/Dockerfile","filename":"Dockerfile","gmt_create":"2026-04-23T21:00:59.630269+08:00","gmt_modified":"2026-04-23T21:00:59.630269+08:00"},{"id":"fb8af100a06778e1fbdac4790a3ed0a9","path":"frontend/tsconfig.json","filename":"tsconfig.json","gmt_create":"2026-04-23T21:00:59.630887+08:00","gmt_modified":"2026-04-23T21:00:59.630888+08:00"},{"id":"4d9b59c294a0aac5e300b3de715eb226","path":"frontend/.eslintrc.json","filename":".eslintrc.json","gmt_create":"2026-04-23T21:00:59.631396+08:00","gmt_modified":"2026-04-23T21:00:59.631396+08:00"},{"id":"48a560c49d2b21da327c036ec2934b96","path":"README.md","filename":"README.md","gmt_create":"2026-04-23T21:00:59.633061+08:00","gmt_modified":"2026-04-23T21:00:59.633061+08:00"},{"id":"ed630a36e81abafd12787d4095dfe8c2","path":"backend/README.md","filename":"README.md","gmt_create":"2026-04-24T10:58:35.330288+08:00","gmt_modified":"2026-04-24T10:58:35.330289+08:00"},{"id":"1cafc02d1d722feb4692dab6ae85c09f","path":"frontend/README.md","filename":"README.md","gmt_create":"2026-04-24T10:58:35.331593+08:00","gmt_modified":"2026-04-24T10:58:35.331593+08:00"},{"id":"d2c1984414de6856ed5b3873c661b712","path":"frontend/lib/auth.ts","filename":"auth.ts","gmt_create":"2026-04-24T10:58:35.334476+08:00","gmt_modified":"2026-04-24T10:58:35.334477+08:00"},{"id":"f26740f2a1532b38c816663a4f665dbf","path":"backend/app/api/admin.py","filename":"admin.py","gmt_create":"2026-04-24T10:58:51.055493+08:00","gmt_modified":"2026-04-24T10:58:51.055493+08:00"},{"id":"5386144bf3c668c6fa14481c0d85a214","path":"backend/app/api/subscriptions.py","filename":"subscriptions.py","gmt_create":"2026-04-24T10:58:51.055792+08:00","gmt_modified":"2026-04-24T10:58:51.055792+08:00"},{"id":"b44632a0f399b2fe2b4daf295a120ec7","path":"backend/app/middleware/logging_middleware.py","filename":"logging_middleware.py","gmt_create":"2026-04-24T10:58:51.05617+08:00","gmt_modified":"2026-04-24T10:58:51.056171+08:00"},{"id":"5883a8ef4fc156d76b71ffdb5ecdf232","path":"backend/app/middleware/rate_limit.py","filename":"rate_limit.py","gmt_create":"2026-04-24T10:58:51.056416+08:00","gmt_modified":"2026-04-24T10:58:51.056416+08:00"},{"id":"5013cbe89f1c6f03533eb218400cedb0","path":"backend/app/schemas/subscription.py","filename":"subscription.py","gmt_create":"2026-04-24T10:58:51.056765+08:00","gmt_modified":"2026-04-24T10:58:51.056765+08:00"},{"id":"3809c5ab912511e0e093ba02a4fc918f","path":"backend/app/services/admin.py","filename":"admin.py","gmt_create":"2026-04-24T10:58:51.058083+08:00","gmt_modified":"2026-04-24T10:58:51.058083+08:00"},{"id":"b250fc6c32106a7f3e0c3ad152dfc097","path":"backend/app/services/subscription.py","filename":"subscription.py","gmt_create":"2026-04-24T10:58:51.058233+08:00","gmt_modified":"2026-04-24T10:58:51.058233+08:00"},{"id":"b0cb6810919f64006be7aa66b2b76a61","path":"backend/alembic/versions/c3d5e7f9ab12_add_user_management_fields.py","filename":"c3d5e7f9ab12_add_user_management_fields.py","gmt_create":"2026-04-24T10:59:38.893705+08:00","gmt_modified":"2026-04-24T10:59:38.893705+08:00"},{"id":"955e1dfe57f0a9a8e900383eb7641ba1","path":"frontend/next.config.mjs","filename":"next.config.mjs","gmt_create":"2026-04-24T11:01:58.061252+08:00","gmt_modified":"2026-04-24T11:01:58.061252+08:00"},{"id":"5800a08224424ebced854d06365f6d44","path":"frontend/app/(auth","filename":"(auth","gmt_create":"2026-04-24T11:01:58.062019+08:00","gmt_modified":"2026-04-24T11:01:58.062019+08:00"},{"id":"b1d80d63eae8fd5e1bdfeee3c6bc9594","path":"frontend/types/next-auth.d.ts","filename":"next-auth.d.ts","gmt_create":"2026-04-24T11:01:58.062472+08:00","gmt_modified":"2026-04-24T11:01:58.062472+08:00"},{"id":"facea1f00ec72e00f774d0839fee7131","path":"#wiki#main#wiki#zh/[app/api/auth/[...nextauth]/route.ts](file:/frontend/app/api/auth/[...nextauth]/route.ts)","filename":"route.ts)","gmt_create":"2026-04-24T11:01:58.064844+08:00","gmt_modified":"2026-04-24T11:01:58.064845+08:00"},{"id":"37d7291b1373216dcf08f081a94ab1c8","path":"#wiki#main#wiki#zh/[frontend/app/api/auth/[...nextauth]/route.ts](file:/frontend/app/api/auth/[...nextauth]/route.ts)","filename":"route.ts)","gmt_create":"2026-04-24T11:02:17.54199+08:00","gmt_modified":"2026-04-24T11:02:17.54199+08:00"}],"wiki_catalogs":[{"id":"1bb55e12-24c4-42cb-8f59-ddc303460d45","repo_id":"1095f823-f6f5-4e66-9aad-9f0b5b6b99d1","name":"项目概述","description":"project-overview","prompt":"为GEO项目创建全面的项目概述内容。详细介绍GEO平台的核心目标、主要功能特性和技术架构。解释项目作为智能学术查询与引用管理系统的设计理念,包括多AI平台集成、定时查询任务调度、数据可视化展示等核心功能。说明前后端技术栈的选择原因和整体架构设计思路。提供项目背景、应用场景和价值主张。包含系统边界、核心组件关系图和数据流向说明。面向初学者提供概念性理解,同时为经验丰富的开发者提供技术决策的背景信息。","progress_status":"completed","dependent_files":"backend/README.md,frontend/README.md,backend/app/main.py,backend/app/config.py,docker-compose.yml,README.md","gmt_create":"2026-04-22T18:56:47.080895+08:00","gmt_modified":"2026-04-24T10:58:35.431076+08:00","raw_data":"WikiEncrypted:nzQO5jvliy8ncyK0FT40s3j/+jLrEduTcrc/mlxpgSLdYjBwtNztvkbMoPPMFNEMDes7QSOWotr7g4sRG3hN1QC5esoYS3BvN6Y/T/6GOvnwo5Ww+L13yRESwkAhTxZ0bDtqMqBMDJjp0MKl68qbq7B2U5OjVB5vyO1G7qlX+bY4a+E+zpn1E17PQvN9P7VlQgVDqa1nwz8U0c4YkUjlvSLoRXqMUPWbTTo8enr8varFiB9kZhlIveqWyQg70c2so+mmgK5tu58aGpglpVdjphh9cbkx8+rqqdDcytUZT7S8pKc4MGkZe3rCbq6nyT0QAyu8WwZ0h9/zER3M3mecpY0QwlpWFcQiEekYeGeusO+eNSbtIN9Tohtik8zfV/pV0TaGc/LbnkcMtj8m0T83c8wKIfYs/liR225bzfnhLIqsoF6rOnXNLIoTpE8Z6Ks8+5swWOqw0Oa1WUgNMnH79HbG7z2uBctEg3Kb/3wmXweL49APkVOhhX9rJu18yc8nR26giaoFIlCpKme7nOHGBbxVcV8/JH1uRvSJLspnk9+gwQcK6n07+/KN5SIq/dFPZUVljWill5+4lQiNxtX+bZcGsWdNjyiate8dGLZoiydoxbt8zaaOQ/sE/vzpNhUqORGkQ8zSh8rLkJEdzSYUCb95gUWs+6vCBogO7GSPqHQcoYZi5WnndLvZiktMpSEJFxGL8OBQQmyD6Z6bOiznhTf01DdqjQOJBP1sIfkt1trL9OQOr20Ak7fnYetRoaFaSlNhpQQ/hgidyWqYv/uEjDqbh6r8sMdfkOJfWVQwoTFcSfwD2/Ezujp/A0M27lE6NNRroam4tql49iIRkSJ8j5Mqpc4aSg/1LGSCtGFO7lgwS9gOqERvjimyvLJqWq3dZ0cOYXDKpKLA0X7nDR9XyX2YWJS4KaXUr5+S2sxJzO7sAlTKSz6PH6BQ/b2JlcDCx+56VN8QMP+RCcbydnghzXKe6RgzxbAnDpW0JuxjjZ4MX8K34hI8qs2i0yxuU9+Mf/FjPgDApnz61m6zpE7ytZaS5gDZPTG3wIPktdrLMdemyyufsG9Lw++TxZ0idt/BkMk5EUrehRV+xT+AOX78k10N+lSt8JqDE3IeHtwqfFd0is91jzyBsgYPlipjXY6xSsJlNTYZ8aU/1mQMFLZvcMTTF703Kx6yRYTe1s9QIB3LdfeaNqDov7ouvZRgU5fNwWTcIt9sUTJn5/2mwjZpBmntggvmpmp5wC7dpNB6kBNb8jJrmRLMepO0ocqPbXE6JhTb8/yOhegEy3fJ1RNTeTZIEpBt4+sCZtc5TA3aJSYPZ51wEGmqMbiVCl1DnxLKmBc0O0JH97VCXcyhIKj4aOGsfQbqM3cyeIWuRNds3/do3Z8vOc9AQfcOnwFZU1H3df4iLKZ9pDyMVGCNqEeKew=="},{"id":"7c3e3c0b-5d1f-4d64-99be-668041c6cd9d","repo_id":"1095f823-f6f5-4e66-9aad-9f0b5b6b99d1","name":"核心框架配置","description":"core-framework","prompt":"为GEO后端核心框架创建详细的配置文档。深入解释FastAPI应用实例的初始化过程,包括应用名称、版本管理和生命周期管理。详细说明CORS中间件配置、路由注册机制和健康检查端点。文档化配置管理系统的实现,包括环境变量读取、配置验证和默认值设置。解释数据库连接池配置、异步会话管理和连接超时设置。包含应用启动和关闭流程的详细说明,以及资源清理机制。提供配置最佳实践和常见问题解决方案。","parent_id":"7c2ac186-ec90-400a-ac1d-b3b7ca2f01d5","progress_status":"completed","dependent_files":"backend/app/main.py,backend/app/config.py,backend/app/database.py","gmt_create":"2026-04-22T18:57:02.316945+08:00","gmt_modified":"2026-04-22T19:03:21.69307+08:00","raw_data":"WikiEncrypted:luoNp8LvFa7zGThvIT9T4rhp6COPRJpm3tT/kftARqFq4dg1cG/8M10NcCrCelp/LC8SV6McSk0Sx9xEgJV/YmEmjfMmlukALh9v7ZKLxT8XDDYkBCrff2Ia9KfGFRdlfVmmQUGfhQARTeykGZh6O8/4GECBHUYLS0F6NXI7fSS3R+/I5c/HIjI7F17mVNpZDQZcc2HmM4zhdyIinOGyErSf3vIPcfVVobPB4D/wCUvMWxl+jpvktykHTIgH9ze7f4fTCC02xK5vRnt1RlMdAQ3d1Km7OOGjAga30OGvRdp9UtT48gdhzPQH5FEbfzn7K6TnuPzqQRf4GuS2kVTRSUFbSnmj5d5HqHmgx7D9iQYR/XxRRVbv+GeFwINvVa+UX9cnanYU19zazOGWG2rcdDk8jqu5MwAhVZsT28hykyuLfKeTf7xuM6Li86T1mZ18SROCJHe4LXYEaH94K6CHjZLCyEl10xBk02/CkW4aTW29TIgrponrmnrvV6bShQ+ZitR1TcivPsNN5t6TCaHMnlaLlOpznSGNpMyf4S51cRPxl2cwZrqJbrdFxehIoPrUyOvtRvtEsLhpo30456ihrInvbVXgJMwZIcDaKHSu0Bf7ma8y+UCWH61+VBIqW44KzA9zmKcXU9hiiwL+gjwiNcV7JDcgg43Un4qvjEzeJiBRBMGGzc8Oc05dWgRs1K6QUdS1kZTjI/JKiGS8zFYKz0mvQqLwc6/xe1/MDhMyU1QUXSqpcNNU6aFmY7te5kENN2aSPZqigqID+RwvIV8k8JETdmHaxJUzCSrNEpbpUukFuVQKz419athf4kMeQH2fKsLMZABn10WnnmY9HGGqBx+gpNOTU9AiSz1l4b0Ej8XoQcwIn1lqw49qdJ6+PRuuFBv6OcjxgJSMNSQzm4c/eyl7yv6J4vXceT7Ul+ySMAGRnSpDUehmOuw1DT4dV0n05Rcrx5gBjuztOAexxUhLwMUK/v+8qdn/0OcciISCZ/U1GhzhWFYiVKRBfNuNkuRjwmc4zg5Zc97TPRBXYs2q2e0/3cT+Dr7lqeGnXWL3X4iTjTygXMekhDQBjc0NbF6cdDOJcPAUnOg6jDkreBiEkTJ7hZg3J9ho2RYDaHuPvyMlkW4YWTpGRODtXIs4aLG0KFbNr6uOG31hOPZsgnHmoNwcPwRUO4G89Nkl2M6ZTMiNHWtsSwES+gLmCLPunm7R2zQNtdei+K3lzSg0bQgUvg==","layer_level":1},{"id":"bcaa04da-04e3-427f-ba01-847ad657e78a","repo_id":"1095f823-f6f5-4e66-9aad-9f0b5b6b99d1","name":"Next.js应用配置","description":"nextjs-app-config","prompt":"创建Next.js 14应用配置的详细文档。说明App Router的页面组织结构,包括路由规则、嵌套路由和页面布局设计。文档化全局样式配置、字体系统和主题定制。解释Tailwind CSS的配置选项、自定义样式和响应式设计原则。说明TypeScript配置、类型定义和开发工具设置。包含性能优化配置、构建优化和生产环境部署设置。提供配置最佳实践和常见问题解决方案。","parent_id":"d907a8eb-795c-4060-9cdd-50d31cf39be3","progress_status":"completed","dependent_files":"frontend/app/layout.tsx,frontend/app/globals.css,frontend/next.config.mjs,frontend/tailwind.config.ts,frontend/tsconfig.json","gmt_create":"2026-04-22T18:57:04.216045+08:00","gmt_modified":"2026-04-22T19:04:47.361369+08:00","raw_data":"WikiEncrypted:MoQ9U2rERvJfHcC2U9f5yo5PrhAUeAY0OH9kgPk99cOGQSyTenUDM+krr5XcMxqj+FSA7CYnuq8hz8eS8Pvzc8yZuRRHbRPExvPpdrOEr8fRtUXkjnECv8NVvFPloo2fonxY9Q2vmL0x2O1UsV1O6L6tkraG28x1o504hsBitow5XMWkk8uSk+sDbyHo/y9/SBDWpcEOXVqeU4nwD/UU+7N90n5i5T89nz6b4M+31tkvffIuZRigZ+1+IJqlsqFgRt9PNrxL9ZUsD2D/Yvh8EJ0sCr9z7AI+D3z+JYM2kgFT/3ugS/EnEzwByGZk/e2EsOY4D+NkRBas836JX++o61ZH5GPQBXTHnVa8h5B1LAVlbA5zBuJHHY3V2XS4X1cTo9Hj76mg9Ha+jWvX2A9fv4vnscE6cVxnM+WjWnSfN8N7Vtla2YRDrNXZRAL50+PNfhUKpb48d0hKFyzf1Av1T4WBKgaYEo2znphEy99ViuG+oOFS6D5pVQ/w5yoPe5MpZCDk4aNsO/owrJkILcGc3+qHfld4Yd4HtYM6madWmmOvHIIuCy5CPGojBzKDcTTSPP6ZjuY1EC/RG3lBkYCQtQj889+80GZpaSbrqWjTmMI1DX1KLNXJkoI3dFk5Tx+w4TqiKICJ8q9KJhOX+mEVk+ECXqrc2Qz787D34zY5UlwsaA44ziBvWDZuwfPWmtelAq4KjqfWTFWYqdY6D0fUvetLh3/VEqH/o5Nh4HrlGvy/faZbU9FKOBZPkAy8c0J24rW5p2pKmRq6+2IicNTgufRROtiY87GKfbfmqpDYBEn3Dogv/Q3i5beVavuD1tJWhRsewhAZAUi1jWdiK3LyS0QI7dMFXVJw3cm2FnegeXA8CNlWnjUVSOY/OfLFqJJqYrfcj57f3nAU4a88w4h10+iFBLh0yZkX50llRxgUjV0fnjyEFUDoinC1xDA9ip9IOosTI+avZPhLTC0Yn4ZGnJi4NCD5cD88+KIdRUnVZJ5Sqf4ZcCCQamtYBT8NJ+PlByYxpqJpGtLyV9BuexYC86YnD3PJau0oXazcytuXMYh/TTaEo89ZzW4jpsqDM1G/gBUq7R+QDzLElNZfw3Ov0E0+Pvfm89W+v2iSsJ2JI2Yq7wrml7FiTN0KoP5KVEBCEzDLwebnJFqa7GBaghwADYcgoZ2VX2Xtin82a3oqlX2WNfur2DIr4YURiSmE8g8O","layer_level":1},{"id":"9e3d703f-f424-47f4-84df-b99873b93e5a","repo_id":"1095f823-f6f5-4e66-9aad-9f0b5b6b99d1","name":"项目介绍","description":"project-introduction","prompt":"为GEO项目创建详细的项目介绍内容。解释GEO平台作为智能学术查询与引用管理系统的核心使命和价值主张。详细描述项目解决的实际问题,包括传统学术研究中品牌引用检测的痛点、多平台数据整合的需求等。说明项目的目标用户群体和应用场景,如研究人员、市场分析师、品牌监测团队等。介绍项目的发展历程、设计理念和创新点。提供系统的功能概览,包括智能引用检测、多AI平台集成、定时查询调度等核心能力。面向初学者解释项目的基本概念和使用价值,为后续技术文档奠定基础。","parent_id":"1bb55e12-24c4-42cb-8f59-ddc303460d45","progress_status":"completed","dependent_files":"backend/app/main.py,backend/app/config.py,README.md","gmt_create":"2026-04-22T18:57:13.329466+08:00","gmt_modified":"2026-04-22T19:05:00.376007+08:00","raw_data":"WikiEncrypted:0MI1/XkBoMl0lTbK6t0CnyIiRc/FeBluVaO5vMjpi7GJDj6RYPJBK8z3pvJGG/q2Umz028dfdXdKirGdHRY2lrn0erk9nv1ZHCzuughhzuFHwcxdCPIpZdrZtQpPh6bsxkWiwYzSScq7WGo0sBeTvyoiisiPXNkFNbSjUGQOu0M9zOwZAcknYWqtf16nUcOV3lRfAFHfNSt77Nc0IUQGl1zM4BWFjitEsa6cq/jjGIh7XC2gcTvm2eWRaWDDr5n6IcJZtD0ODJYzhH9IJVk4uIXlKksbQcuIrmEWEkZBxeh+DAIp0tmgXr52zuL9uRxapFuSlOq3BlU5N3I+Iu8Fg/rBAnNcvKEwSk/71gIbFlwaxLvik5gposBrfcD4U1+MJLRTPhgg/HJwljnpTC13NERk70aJg2/SCvFZcO+86xWuLwvNjWRxc2K8yOeJggfWG6S/Dt0dGaFl5F44u6XDbQV0GKiDfNOzo5CtzO7CrkSRJ+zErGQOEEoF6UhVmmpA6ONf2YDr/z3Z5bIP5z605qNZZWUDPVLjU5elINOMi4fsEw3OYaerNp6aoSHA1eXnOJoJIMsU0KM3eGAO9QNhHE2PlkwXulCEX5l1tkohbwthcv94cBVsn64CtaMMgjrgUkflNYnfEM1djmP2iJFEG/MjNMntZCrVRGXdjjqR4Q+lRe3ELhXuHjqeU5RS+KdYLASsYBDzti2T8foSfBxxXcpMIz/lS8+Qx3pTLW3ktH5AaEtSdclWCF2HLc1/03O/gdv070KOck/8TXbyZsJ6g3fzThY7xASttVsW1IITTaX9XE52YkNOe7KOrjJwkSbUgOU1Rv3Aa7x3VJ/ac9nDL4AgS+TlYNxfYBlGkbesL+sqDgWrL268y38MyK0DRqEQVjCxV9+7aAkxLvaUXVMYIwxqAM9Id66zRb0pJB3uwgpOAIRzOCskNEghjp17p4BK3lgehkRcM9RAGb7WqgeNfl/+ox2b25Pj+nvbWN3XghNZwNzoTW+kBZxXhOTRvIyAne7IPRpmtD1XD6ZBx/C6ucQ7kTUL/7LqFXE66g3Zey3hiaiQihueSMCFVer6F+BIMSBpV+9cmAczdqYvXRnKIjQg15zwVGz7mKE4D7caiDjkAQeMUSqziw+i/S26Ont/JBHIsLpYISQJErTAl2rGwC+7ADw+H6jg0rn+nE5s5u9fxUPMsWodcWi5oGIFRRTyGeIZYSTNveEwN8h0LGwXhUlHR6RxBAIpbiwKVUcOFOKc7mojhJEN36mXsQdRyCUjV3YdNzj2Tw5tG4exPzStsjDxSn98XK42QisGde126iI=","layer_level":1},{"id":"a06436ee-1678-4a51-bbf8-b0d0ac3456b9","repo_id":"1095f823-f6f5-4e66-9aad-9f0b5b6b99d1","name":"数据库架构","description":"database-architecture","prompt":"创建GEO项目数据库架构文档。详细说明基于PostgreSQL的异步数据库连接配置,包括SQLAlchemy异步引擎设置、连接池管理和会话生命周期。文档化数据库连接字符串配置、环境变量管理和安全考虑。解释异步数据库操作的优势、性能特点和最佳实践。包含数据库连接监控、错误处理和故障恢复机制。提供生产环境配置建议和性能调优指南。","parent_id":"243a1a45-d31f-405e-a3b9-694d2fe617d5","progress_status":"completed","dependent_files":"backend/app/database.py,backend/app/config.py,backend/alembic.ini","gmt_create":"2026-04-22T18:57:14.160162+08:00","gmt_modified":"2026-04-22T19:05:13.623934+08:00","raw_data":"WikiEncrypted:veTYwq2y4io5qXerCTrkkJxdCaPVm76qYvPs0DmFrBYr++cWSoBpsZCop64XjnmZv6vHv8URIJAqohtlaw1HFotKc3mK0aD3tk5jmFWmTjGEd9iSTEcB45Yccg7p5eggZzqexWRLP1afxRQPau2t5uy1dZIlExyu+lyiNQI9/hXf1UppgfCjo4u6akBIZtYhzgcUSoYY4jCjv0naBAT/PyevZQctOpKPIBwMdeB86h71UT0hKB1hXxbyQoljBYZmATJaRjmlQzZf/Ka1gnDj1s1WVsGMpSoA7jyNRPH+Ra6hR+5N8Ba5vkjxM/HcRFq282Jnr/TnidF4MF5HpD5Piye73QZ3zAvIbu8+iOSvpQee/FTzkrUQBy0xOA5lsfFOy5OFOKtQh0mHybuNqe6H5squ2Tge+K4+RKXbDCt0wptrSV+BVQ+OkAJJEtLNRpJElsQ5bw1UU6CuzbgnnEYrMXB5TMBI5N2/J6hmlqt978t04N3zVI9JnnFKK0H2og6TVu1Hrxq/xEB8RFWTf/WNN1p4Akee5r1uOuUry6hsO2yQUTlmHq74QnJz4o4YJodWkhwAmcyzPIlMeSFg/Kr/EvsQJN4UprhudCTvNitnPaBesVkucYDYQiVAhxyNSAqCzZUYXbyuLD4r5DKxKzvHjkhRugm73yBM7wzbxB2lABMiGM9p90FASIxS0SfzIl4qrFbO/oQGRIFaYfUCnQF8h0YDi40UX4/LVmnlT/L8y/d+hU00P5j5PI0qOyoRDqsfQZFaze+qtibkMnJ//iy0Awl0wqQ47SxaB0jhTc07lPFBLSHFSoVUaKDs1DPGiwKjpWZRzAw7rbv9NFuV+irKc0l8qDNCaK6Rk0rRd0ukFuszcaE9n92URbvv0Fk8XTHLr8sFAh/xMm63r5hUAuqEYN6z/Si5Isq52UmJ1/TvnLYIUK58JHTuDsVn3MKJ2fTgUw/U3g+N61WpDIgGvaHO75crgWZbS9qQyDoSSj4wNdxWR+wtmKjwZdRK44kWRBS1QebMTLNYDBgHD5hPnmOa5W/Rx4Y0QBw6UFjCy/GOmDI=","layer_level":1},{"id":"7fea5a24-e6de-4003-bc70-9dae6d8fdb25","repo_id":"1095f823-f6f5-4e66-9aad-9f0b5b6b99d1","name":"适配器架构设计","description":"adapter-architecture","prompt":"创建适配器架构设计的详细文档。详细解释BasePlatformAdapter抽象基类的设计理念和实现细节,包括平台名称、平台URL等核心属性的定义。说明抽象方法query()的设计目的和参数规范,以及close()方法的资源清理机制。文档化适配器模式在AI平台集成中的应用价值,包括如何通过统一接口实现不同平台的无缝切换。提供适配器扩展的最佳实践和代码示例,帮助开发者理解如何为新平台创建适配器。","parent_id":"7e66719b-4a8a-484d-889d-10fdc76788bb","progress_status":"completed","dependent_files":"backend/app/workers/platforms/base.py","gmt_create":"2026-04-22T18:57:14.592407+08:00","gmt_modified":"2026-04-22T19:06:14.01609+08:00","raw_data":"WikiEncrypted:mEeeU1uNqYKn4jkG2zPtuGBVTFJMKL8+aALSFPkyoEYifQL2Z+klmgmPGyzF3YlP0xw/C/hG8jzgXcVjqaWbA8lOQYPPvd4qFK8fszqAYs/fYEHXvWBVaOTbFhjNiT5k+li1MqVRx7SiaRze/N6NV4j39o5dfNAouxnCXgLyBZdG5QXj6JAfhJ1mTHsYQFDmrIU+nOtrQvRh3bruUOURVd64c13kwbBISJKHVwByRrfqWLRTsCLXPYfsgZF4rkL+Iz9x27Nl0VXvNcIIoMXj9B7hg2PPcQlmup4U8y2LhUHmKrdiKpW1t+XZ8rpO2aPKpzr47rn+3n2axWoQIDjWKlHAwi5AhxgPysB/i5EGv0pvgo/mNNIfsZlmSYgXASM6bgCzH5W4O4oJVqOi+gaLuI5+i7N8/+s+FKb63H9ZNvwClw5jXJe2Xm1YUwVGLG8KX5beKRTmBgnyDPmOW17/OXwsWMWQSQKrgpiv+2C7VQqI8X/agBVWawLJAc8VloY281S3ZH5LTa/6ajeGUVXiwpWSD/YWzo9sxLdws1ZXCInzLYy5vX7YflgBOlw+pn6Z901TBktq5jxrG3CFTbRLGxaeG1aJ06sLEFoPzLSXIIiEIuAROC6lPr6XpYAKESgWGOG0GdM3BinxdkriGn21ZZjENIJ436aZjsOiE5M20/kJAnjWIBPEJ/sv3nsi7u5iLfYFvkus4GfnKXJyto9LWiTgqrwHoEUQy4+pnVW+ce//iLlM/t0ZknimuBfzgYSWx/jPc8o9ZU5OIserDAYGaE4sDZIDQas1jOq8HGN/q4wJR7sW7Fw1jKyl4suQZE6QSfYx6molnJ1cSVKcsGrf7AHDKM5x+uGRmLWXqMMUZXXtbbCw0mwqfxAUPiRLUdVyzot8dh/NIWX6B1KABd/kKs+L+vVuCmMen1XVfP72Uy91fYOkBj/xPkA6GYrempnrB6zh6INdvGw5dEKlvNARMnZZLCA64Xw4h2TBjbkIjsBawvJtT+wEGkfkPk5z99jbaaGS65e/JDF/g5WNnKSX0B1Xo+frM1AFwnKR4dIJXZ8=","layer_level":1},{"id":"78288302-33bd-44f7-8b29-24f516c8b6bb","repo_id":"1095f823-f6f5-4e66-9aad-9f0b5b6b99d1","name":"调度器设计","description":"scheduler-design","prompt":"创建调度器设计的详细文档。解释基于APScheduler的AsyncIOScheduler架构选择和配置,包括调度器初始化、触发器设置和任务注册机制。详细说明调度器的核心组件,包括QueryScheduler类的设计模式、事件循环管理和异步任务包装。文档化调度器的启动和关闭流程,包括资源清理和优雅停机机制。提供调度器配置参数、性能调优选项和扩展方法。包含实际代码示例展示调度器的使用模式和最佳实践。","parent_id":"7416db23-312f-478d-8883-2fc3c41ac2e8","progress_status":"completed","dependent_files":"backend/app/workers/scheduler.py","gmt_create":"2026-04-22T18:57:25.383156+08:00","gmt_modified":"2026-04-23T20:33:30.132403+08:00","raw_data":"WikiEncrypted:z5m818jdZZHs9QqQTrTafQ5BuN3hUq8ojqzL8SUBUvazzYVUu4EVEqQ8I56QCaxYSTvxoxfSrvjJk5zRU5X7dcnw4Xa3OBhn3OLehoT3E+tyMxhlJSbJpOfp1afGCLyH7k587Ud4I355IvboUvSoBViL1WL1yQq+6Tus1CsKPq1yHjNiWT35OfV9g7bRu5xE+1nSxjPu58jZpFKuN1x9oqF5OJmckHxf5sVFqKlGPU2yyeGdpzKRagbQGUkBdw72yxzSyevTXJ4y+UPCQLh2FLZ8RgYP0OD705z2xIGb7KSeQocLcW5FoxR79ySiibc+AmzE0OBKZqbcm/aw8K5lAK1GP31LdhjrndMTmXrsf9CYBNRIir1QOJsuCh6zPtpsvQVmrX7DpqXiWsaqnK2GVOkKPtnYAJnGsEQhaoX24/64eSYeSnJ7KIsQxP0MHUrRG85VVGF2ADUGh6L8qzexe7uE+lnaqgC8HBQ7CnQ3Ugnj5hcO7vnwQl67NHMOQ5yaL1SpfURVWAx3jjUBU4xjHfmUNcBC2VM6ie9C6Ulelai8Pg0+gFL0A+pfN/Mkzzh05wcgnmFbWfjabZ4Ofv/w+UlG5qhMsEJQAgag4tXHgP/86pheTsfyefYhWEkow983vJf6mYl4lgRaFHeOZ/JBTmM0sxmg1PMZ8wgClMSC0a9SKcsAyWOh0yMuBn/Ckhx4HqGoPAP1rx/k9TkBiHFEoEAXeTNoeg/Wn7tVimdgZvAjW79z7lbcRV1cvlKMSjhRyO2s6n6N3Z6xTlKtLrqHBbXZcrjNQqJVgW91Xk78+a1haDNngswufhJkTJcH8hp3hSUCJeU/Cpx3RYRRf7E3bGmj4sV/+yXAybUvCOhs1s89mYVFThdpDifMbvN5C8a9xrjKJNfjzijlVZwx+cGy5aj+ZQFSDCRCBHvCCIBd76w8uxi+VR8VhbsIryP2KUNpudqIY4V56Jx3DB+dznNJMasPFZZ2ZttlKIAV7oqWrreoweIqeEIugrIM4TdE4EWmokDP5wr0tBdyerPnkaCgJLQj3X2K/xjY6ony3F4svfG1pk2jd5JwTLnudwS4dnGY/1b//vEDGI668cQtR5fW7+APXXb8qjOLlzM4Enze4mw=","layer_level":1},{"id":"b027f234-4ac5-4d6d-9b38-afc8054325f5","repo_id":"1095f823-f6f5-4e66-9aad-9f0b5b6b99d1","name":"单元测试","description":"unit-testing","prompt":"创建GEO项目单元测试的详细文档。说明各个模块的单元测试实现,包括认证模块测试、引用引擎测试、查询处理测试和引用数据测试的具体用例设计。文档化测试夹具的使用方法,包括mock_user、auth_token、auth_headers等测试辅助对象的创建和配置。详细说明测试断言的编写方法和测试覆盖率要求。提供具体的测试代码示例,展示如何测试异步函数、依赖注入和错误处理。包含测试数据准备和清理的最佳实践。","parent_id":"fc6f24c3-594e-4153-854f-19250834eeb1","progress_status":"completed","dependent_files":"tests/test_auth.py,tests/test_citation_engine.py,tests/test_citations.py,tests/test_queries.py","gmt_create":"2026-04-22T18:57:25.616384+08:00","gmt_modified":"2026-04-22T19:06:55.090058+08:00","raw_data":"WikiEncrypted:oQ7VNoYBl3ApU4O5/TGa/YEO9ObmRNw6knddpSF6M+qfBokxpt9FAn5Oh9wXkjVweu6TpLk0XawcRFRcQ09Zi+YnQyN8+4Ep9fANKzHyAxzcnhkI4VZF35j3DwTbhekUFTKQ+71fms4SP6LGrVw+8IP/eqJC2TH96LJR1oxckQk//yfvKqFHsMLgziXy6zrXuQO8PIu5U/WbkKUkJHWSkLkoTtPteU+WKljSMapCS60e0RUDWZEPuFD2uupr2PJxT8AoOXx358C9XEj8tQ+OwHpsBiR7NdmO0D3GmcgVUcuU7WWxnToWu1UM1d/t4u+x7bIQvHQIDjLWR40nTrvBZJBSSiui0he3T03jLkIB7r9kxCpm9mFUx0fkmUSWp7FRfs7MfJkuoQYVU0YHf6/FF6g/PoQ8ieyqr4YaNjM3kk8GirHkmKjfdQt9YmQtuzMWnzUQ6COtN+BG3STyOvO+12YQAYi5LWe7u7oP4D7TJRReg7FeLDQ60Y8KEoKBJKM051F7pgHlorthWz42brF5tF7oa0tjB4AtWaEwXdCvH278kzwHNEW9E5zeERzX3hlHYL+mKpTbemJlfuHuRugCRy4EKFRP0RYiIUecBK82Pi4Vi9MGjB7cQxIEutHQ/3D0JNLGwEo5TCsk4W3isoF+mJDFy6/IDwgW/+5FIo7V/G18dTg9YbFRwMecdvBfJU5QZV4R993bdx+kH6qB5IoJrA0AzBOCn99YQ/xgAd3w/82Z5vR8syeNZjHYmcx8P/XrYDk4UZTwaacEHfn7tcq+tL5qJDbxdY95wjaWRo9giFE8woDfoLWstvKA1/q+YOyDsIHC/uHjNP1L0ELPZ9ssFuHcwLVrqDwlcblya4+oXlPEOH2ar22uXNRmFyd8Mf8MmEWVZklodBHSKiGUlj8eSWqtR+Cw5Am1gmeUcOxqan5YwzpyXet6g5ll12dnu6ItLby6qm+kjET3rsjaJag7UBlMXWV9xn9Vj4QDK8USPTTWkRUEAj4WH9QqECQzUtYJ6+GsIE7LGx/5tzApMdX3BThIiG8C2k5ry3z310nAMX/pTSrGFGjy8tWFf+KH95sJ6aG4CDyxSPHT/3ivhXAnKDesNYTVgSIKNmAUcj5hRjTfJeGyljB7NEs6Gxz0tf5k+GQLwvRX6PxSnMGkm+q0yx0MNDRBYJNlPCFKUR74ZAU=","layer_level":1},{"id":"940e5918-1689-4001-a284-44f2de75b8ee","repo_id":"1095f823-f6f5-4e66-9aad-9f0b5b6b99d1","name":"认证接口","description":"authentication-api","prompt":"创建认证系统的完整API文档。详细记录用户注册接口(/api/v1/auth/register)的请求参数、响应格式和错误处理。说明用户登录接口(/api/v1/auth/login)的JWT令牌生成机制、认证流程和安全考虑。文档化用户信息接口(/api/v1/auth/me)的权限验证和当前用户获取功能。包含完整的请求示例、响应示例、状态码说明和常见错误处理。提供认证中间件的使用指南和最佳实践。","parent_id":"dd12cc44-0c95-45d5-a726-e7b8bcf2531b","progress_status":"completed","dependent_files":"backend/app/api/auth.py,backend/app/schemas/auth.py,backend/app/services/auth.py","gmt_create":"2026-04-22T18:57:37.836287+08:00","gmt_modified":"2026-04-22T19:07:12.356456+08:00","raw_data":"WikiEncrypted:uxAckj1IXK2TQH//kEdeBPmScopsydAsQUjZb8Fs6jI7ezX3WnM5wMv74LMiw55tL2+YKxETbMgwkBQYqIg1VTja5IjBYqljlAzD5l6SrkKU835vZQoOKlYgIFEEXj5PMURu9+2Om7SDVgjbSQ05vLa2aVIBV6PiVswRGc5EGTGtYnV+DJs4BxHzYpH0Ac7KkyHUCGgH6w5QDaOxWt6c5gftFmsRwr8WVKANmqlNU9uhDjmWzjTtSqZ39EVbLd++OjVbpLbTtijQ6gOF0KBBS4B0N5k+Xm2/gDv+HNK9kZ0BphZE1Si3NfV0+cu27HLJ2XV9w357rte4pplU0wYG5oC6cuO7eBFxQdCR6e+ejXIvKGahQOce8d/jWexjfdWnUzvQ18PU4+bUZmiP+YD1dJVBFgxggbCIHG8VFTQBqMaYwc3NLWogjXnczII+Z3sLLneLkVAQEdQ381GeRKdaD4PrtAWp1Ss2QpGHWUKDdaNSLcfm5NXEe6GeECxXH96p6BvyegD3twPfZmY9WKG8YOhXqbpzae/+DXnUTfldYKnMfbonSav0nUBYt8JA0L3oceaNs03211fvlSgE8L9vtUDtNF5lHkhOLMLbu000pe/VWc8WVQRbCKd8KPd4TUxMkB61vQNIcvlRKLMJLNSnE1VftRTpdEpWKhm5qkLfOfikgsp2qp1iSw5Idpu/TLQPIGN/sYpTJ1eACeXt/A3qrlITHFV8by4utTXDT1gRQQ7j7n51fQHHEIbpU+6CRhSBBQfa5IlWAqkarenBmr5RY74jeX7tlhDhvFojQGHYyMaDsZO8G/H93/20YG/li4iihHLIYmsN+2YRP/KWCNaopBGp7tRyZi//RKVXdHGteWxP7vse7URwPhfmHDUB6dMExCT5PwgsYoDwD32k19Eauv4c6OogAMMUN3I9rhSo3V0cde7/xSOhJ34SUY3w9VpPAu1I4zTqhY649YmBnNEjtGLZGTnEJWSdneSPsudvl1HJKg6faq1dMy0dVkMqbHaqMCooFDhiYVS1AM1cG07y9rQisvQP8Ic3NTPAA7BhH0nrPnLc615Jg+XEAjs3brkNXEVZlxNvX5ZqMCoMqsiZrA==","layer_level":1},{"id":"6406f42a-e10b-4a2b-84a5-0a21c1c759ea","repo_id":"1095f823-f6f5-4e66-9aad-9f0b5b6b99d1","name":"代码规范","description":"code-standards","prompt":"创建GEO项目的代码规范文档。详细说明Python代码风格指南,包括PEP8标准、命名约定、导入顺序和注释规范。文档化TypeScript/JavaScript代码规范,包括类型定义、接口设计、模块组织和错误处理模式。说明前后端代码风格差异和一致性要求。提供具体的代码示例展示正确和错误的编码方式。包含自动化代码检查工具的配置和使用方法。","parent_id":"2148d7d6-25c4-497f-8894-c4eb7a0d2bd7","progress_status":"completed","dependent_files":"backend/requirements.txt,frontend/tsconfig.json,frontend/.eslintrc.json,backend/app/__init__.py","gmt_create":"2026-04-22T18:57:39.373374+08:00","gmt_modified":"2026-04-22T19:07:51.274139+08:00","raw_data":"WikiEncrypted:Gw00+yNdsAXvNpUHE0sZ2+QbHW33I6XBnIRt1QjI/FW/5OIgpgiMvU/f+bhXrxoZK5Mgo6YrGuAKhtZ2BPutU1EdQeDFUnQQxxqSupe1WUkFgEECvCkbZOAHimRWBeUutq2qKCfVhu1+US1y8n87OZXUUvVSAksZOa8lbb2AHyiKTMdzzPThS0D+8uOalkBg1mvJCS9fqVoZzY5BYYpuH5eZJBglHbA4uMbdFVTSKVFfHaJ8nlm6uYjaY0sJCSg+dhEAIiMfOTXP5Bh59kxWfLSdZU6b8oPvLV0btsiS22/oEJZI4rWjJ0YTxfQ4jRv348P+GQ6oi1pvwveiJyOxLq8QcVKSiDxO55Ovd76PhOgpOp2WJcUsKoKBoxs817utm+Ld0htpPBS3V90Rw+suMSPCU0mCa80FTrBNn6PnXemH7lH1ozQIu3Y/AGNYBN93acBxtiZ09sGFh2sO9mbbCU0iRuNe9nwWa4MsA5rJMLGdRbyv6jk03+sAvuKwZHXyTWxqeXvMatOUKXzTNfmhXsE+Bexe1vaukG22SWhsXu7FhIaH4Rt7CdpMW0jjbZOf4CwKY36ucVBRwft6ymuED4ihzikPz7pJ5IEuxLGtCyt5QDqT7kbv5ITx4NM/Q2IMMTRZf9bAZyN64PV2TJVCNK11yU+cE7y8HFBNFSzPfDBGFmxijKjTL9MvlElogPp0+qckxGclnip/IOFc6/WAbPNK0qXq98Jq5DsZwLsx4//8yOyRyaQGmOVaOWxb3Aum4RIf933X/hzoTFpV2uSLSznRyCwLpKqjp2zMS7lCj9aDhWLcx5J9NxXfdxFVxBsapMeDDl5xR5nfTFJcOFylsdPxEdxf5J8ULB77F3OmE8Hff/40adNMxJHMyBmju99HNnMZkGLjC68HEPNMZ/6T0+m/Sq1yHOrakYMiw6vnQvmLW4cBIhsTFbhbgpkazGFTk8xsKH3pGySrLXL4xmadfs/g2X/lRrLbSonWaQehTqHYrhz4HIxrTUDn4kdxaPPDhH4fHdEu/69Dri0DSzmSF2m8W3hh1gbAbUO/mbHob1eJg0yKGzyh8AmvUlwXIRGrOwQA5dUZNPSo+oCcv1qlrQ==","layer_level":1},{"id":"e8ec6ac6-ad1a-4332-a7be-727b47d71233","repo_id":"1095f823-f6f5-4e66-9aad-9f0b5b6b99d1","name":"Docker容器化部署","description":"docker-containerization","prompt":"创建GEO项目Docker容器化部署的详细文档。说明Docker Compose配置文件的结构和各个服务的配置参数,包括数据库(PostgreSQL)、Redis缓存、后端(FastAPI)和前端(Next.js)服务的容器设置。详细解释容器间的依赖关系、网络配置和数据卷挂载。文档化Dockerfile的构建过程,包括多阶段构建策略、依赖安装和运行时配置。提供完整的容器编排流程,从镜像构建到服务启动的完整步骤。包含环境变量配置、健康检查设置和故障排查方法。","parent_id":"803bfef4-3985-477e-a61c-915a246d0061","progress_status":"completed","dependent_files":"docker-compose.yml,backend/Dockerfile,frontend/Dockerfile,.env","gmt_create":"2026-04-22T18:57:40.354835+08:00","gmt_modified":"2026-04-22T19:08:34.084609+08:00","raw_data":"WikiEncrypted:h7ADvj4WLJHyulzCl+z7kNgZWY+r5P000yRKX1NQnlv1Xv3Dqgu5Ve8V72HxPVQrbKK8WU/ipQ1PAqV6SDrNgrc1Neea6KoTKr95imYAh3dYgIt/lZ1sndBbQCFqOF87dQsUIEKQgwrsicAeQ0zdudUWh6EW2nyIF0NGa50xffbgEr1mm/MThBZjOua+YnCRogCbgtirEO/6HGlC+I33w/bfFI+rREYKdumqUEia0kUP0pWSpwWjOQp06I7cUoSrx/LuJJ4in5YsZetdjzxdbA3ZvGMjeyI/VVF6UC/QUOgE2csP9z42v6XdOOngM/coBHI3DiUrroBGTPa6BVxJdngItCJ9XcNvXPbo0xMAkAoUKnNPA72B2pRuk4F1sTiOaSCQ1jaMiCTFvbj7+VleaodRFLDFsYa8f1w2FkiW7cEBhFpFgB7Qfru+Yi11rpkjnM2def+Sqq2PSHQ+Ji83jPoQXFl935rDQbNUy28wOIE3BdWN5jjM3nyoXcqKjPVjLf3cxGvg/sbdWk1FYPMIsbK/DUWayyTHt6L/fYkDQYjY5h0H6Q0jBxlhNQ34GG8kEcvrZ6Dy/jtCtE149pi/ToeMbpPq21c5KUhs9OHcEHgMjxWMaEVjQXMjFCpKyJIPfC984tfoZhAHi9WupzyEi37/igcgVJnvIdtadpX7uRxW2JCdfoHn1H87nGQj4eAeI3kMhtJ3EIPd/D6STxUcgtyLdTIZu9kgvnBIN4OyZeI1ygNZfawwQMmbDxHZ1pPcyZDHFlz1HZ0NFX+7VnN2b25TJP2hxMCZ/5OdYeSLozIbM/azA8QMHofESSdxDX9ZDdhvENDlngxUBmxM8+yCAWHENGYqWDL0gZMMDwe89n48Xy9qnKNLX0ROfG4FAtoXsEgLlPQM3AWFETnzr7Kvuma+8sY1iaMVIXJ/MWoy1zLwuY/oOZhVqGLX+DOEupKhk1oQmiqzciCeV8my5Q6LQeriSBww4jA3r6VQMPzBVzKJYz+TLizB6Esf//9+ilsgUVUc6GjD41Ml4fb1GZO3PzxGWrcX1RUE6RKllUBVNffxzE2WCirEX4e4YprntsHu6SAb9TLIInCx7aZnlVnaDQE5BCiHLjIQJnsHHJzlBm+8jtzE4zi7ljHLfbJwhtZ9W6S9KGUqjjNryjTVnVyYQlumOT8HCAkz3fSM6MpXwQr1qz/gHyDrQanmM1O9B/0ox5O2NWcOm5qtsteiyxwKACdyxrsUx0X9BaU8xygDL75XcTfcaOTcICRwaRZF3/UQW+zhbJo9LnHxq30JzTbxU7wEdjpWZQHZ+tu5BMrIqi4=","layer_level":1},{"id":"a91fff3d-ec5e-43df-8176-22f0084109ef","repo_id":"1095f823-f6f5-4e66-9aad-9f0b5b6b99d1","name":"功能扩展","description":"feature-extension","prompt":"创建GEO项目功能扩展的详细文档。说明如何新增API接口,包括后端路由添加、数据模型扩展和业务逻辑实现的具体步骤。详细介绍前端页面扩展方法,包括Next.js页面路由添加、组件开发和状态管理集成。文档化引用检测引擎的扩展机制,包括新品牌匹配策略添加和竞争品牌识别算法的实现。提供UI组件库的扩展指南,包括新组件开发、样式定制和响应式设计。包含完整的代码示例和最佳实践建议。","parent_id":"b2bb2e3c-5661-497c-97dd-15bf6ee8b7d4","progress_status":"completed","dependent_files":"backend/app/api/,frontend/app/(dashboard)/,backend/app/workers/citation_engine.py,frontend/components/ui/","gmt_create":"2026-04-22T18:57:48.684421+08:00","gmt_modified":"2026-04-22T19:08:25.140739+08:00","raw_data":"WikiEncrypted:5RlNBsIi2/3o8ATlHuzaYD9/6k0SjLB2nW/cTN9Sp7ydYLe7mauzXPQFm5pYVoY1D1K/aULghB4g32vyxSUIsHV6NsxwYA/5+FQ8w/4xsQc3urcx9OEKeSC0hGU52WXucdAGjiEq/f4wJ2c9FdJEeALD6eX7MltcooFsxAVRWIKzHsMdBiy0RQN6s7vv4sb8vpV3b1ET27D9QlTUiTPU7RgtJLMui8iYiwJIirfL1TgdGRSx0Rr3tY/JvS3/6/L6VU/69BKglW8DnLwDkWKuthI/2sfWQa+lb+uTuixXL/VbltWQnzwjMVYghhTizEEC0xTpFGcDY/ajvLcjy5+wSleNEr9AFy/ytJKkpqEO8Zt5qyVJ4eANJMSXYcoKrZEskjVpnrPEHGdOzaEaCqcl2sQYkXde8LWM29fWmwlMjwJzucGwhudoQLXgkIwJnD+jb1r2SdjjafTI76MM53AnSfD4aj8K26yrOkVtoD6nWG1A1fG6F22pPBhJdezNJCYuKBaSDxJDES5486L5Gm5RvjYDq4r6RZ5CheGPgxl29XjCimgWuxXKVX0jPLUawteo/Vo5D7AHzucx2dX4mKr4rSSSHpD4HGdbwnxZ717DkRG01vTOnue6gSQ7pceMjSZ6TnB7dvtwwarHBKQMKwJXrpqxc83aZQjW4sRTAJs2Gc9+11c7qT9fQnGK54JJjEARaQZVaDmTpKmme4SKKxCB7V8yUqR+D+swVuSjIpYdL1m7THJtbWSSLaKkWmYiom1C6qb4GIgO4CT/IiFSyQ0Sz8MUIJi/dK0l/vVmpp5p3IF5K1m6NHDX94yEPWEHsWIS8eC2B74AyX6PG1fWSt7HpiBAzq8nu8n+IrXPqDege5sXbjfNrbvkRot94AvLF2aqMbteOUGOZxMLASQYyfRQBlaEEFMiKEVNTRSaHqiS8mS3pG6XLcV7TkWJIyMzhcT93hKXrSB2+jLa/rrxxrZwfp6lddgEcV+XZzQU3KsJf8blNUd+UkA4TcwFugu0um1Kr6Hro8EHAR34+FGMbPskEPPX2yd42YXx6qfmcFrI1xvHIQfnc7QuxZwO6GHR0G5LiPtuV4ZSxklXCwgnGWy1lpC13xANNvM1UKqAuhpuV2qU+xayK5IQv7kQaDOJpnMzFj/dSxtRgL2Xm20nH4BA2lhBCQMqeM5OxJ5vzwVlgVMZxDbhwrRaDU6cudgNfRJDFh2lGQqE2flEkvSF7g87Hc5H3qDQxUv56qpdOPJcgugKJtT3Jz4dNt3+eojvEwrTUc7d2Kq4KDTFUa5jDr5uo9PZhNR2TDJazpNIdl1x/64=","layer_level":1},{"id":"e3ae8925-4862-4280-b85a-0b376841b15e","repo_id":"1095f823-f6f5-4e66-9aad-9f0b5b6b99d1","name":"快速开始","description":"getting-started","prompt":"创建GEO项目的快速开始指南。提供详细的环境要求、依赖安装步骤和本地开发环境配置说明。包含Docker容器化部署的完整流程,从环境准备到应用启动的每一步操作。提供基本的使用示例,包括用户注册登录、创建查询任务、查看引用数据等核心功能演示。说明开发环境的调试方法和常见问题解决方案。确保新开发者能够在最短时间内成功运行项目并理解基本使用流程。","order":1,"progress_status":"completed","dependent_files":"docker-compose.yml,backend/requirements.txt,frontend/package.json,.env.example","gmt_create":"2026-04-22T18:56:47.081987+08:00","gmt_modified":"2026-04-22T18:58:54.237875+08:00","raw_data":"WikiEncrypted:qfgbutC7oyxR6nMxrwk1ODnNMBEQ3/sG78fQT1yXWju83LC7H/jAM8CEAvWT8huE5OClmQiIfNYNxHQ9s7RRS/GGSwI5DTgXTPiPdxvdU9tU52Y4wj4FfVrOtqmH0nMPa+EBKH1Wo4HibSewimTkeCuJVAAjyygiPePcftR4ud09LKmopy1NSgZrtHMoDFDwUOcNJQad4OVgxMnOi6B6z6s2Oh2aPWNJX5EvE5xGkLAc6XvhE2T7MU40VJ4lUOoKlCNZNdI06grEqwyizBqt13Hg20wonqeQ1uPs49UbF84IJecH3DmE6KW3oqmqvQY6tztk79eE1bKZmBtQKXz8WhEMWZwALTsVk+hkk4dH/fcDoLteR1iuO4FaxDwAOaD71KF79AaYxDZiM/8RER9YsajjGSI+sfpJALuiQbqqfKbYFSgliiUcf4gTM20Ey5rtfBkcvBY6yOBPpqdKg7/ls7jdggNEWDJfN+DPVzV4SGAYRD4g/kDzPa5vaNZ6USRa7hVIR0SJufX0DGSdzX5BMh5DQEEyd9svxV+bs4KPZphBIeqAOzvo6zyF9l9LjPPdEook/uTIBHjGgx+8Ck1NQEeNOs61Zqr5EfISope1Au8dYCrzwpr02s4XAb/6bYsMSkfVqETlSSUkipDodGoLJU8QiYr5Pjv63Bb9Qb7SZ+i7NrGp6UJNVT0etywEMKSQn+73I8e9AYrAxlN5ST6K5b3W7cOPzFQMCVRfzvdd/FbuN30u7JXlFCnm6Ee8LDHW6nteOxBP1D6JxbrQirCQE0cSuk+d8OR5tR/DJiRDcjbsG38KVBEqWnIek8KlMGxEt6N3oq2ceUCCLe4jVURPc/2G/6gNiyVq0dPPAVwjaNKNwtiyaDhhBu4T21k9NUfhdQNz9DJWD0wXuaZc89RoqLNlCHJ6TtxEHJ/Sv4cgvm3QUierIBIqUawkCMEDn3ZEo7L2fUS4fMlzfpHSgTvxB43ta+H1m6syFUmAyh1yqfXVxKZY0f4JtmBbQpNzpT+aRHMKKQ9UVvtjvNcpupzO5aNkyclJVWis66DMtfA1H4am2gseXSfgHHtXiLfOnGoELSM1fLS+T9oPt48v+RPafJQpahtNeKtZc4dbTcsc4qlS1krenNSBbkKac4Zsosjv8xHuD1aqYvAS476XT3gjLfV7YUCF/+i3PiovD9NGzhA="},{"id":"c19260e2-5163-43d4-b35a-b48aae995f4a","repo_id":"1095f823-f6f5-4e66-9aad-9f0b5b6b99d1","name":"认证系统","description":"authentication-system","prompt":"为GEO认证系统创建全面的实现文档。详细解释用户模型设计,包括字段定义、数据类型和约束条件。文档化JWT令牌生成和验证机制,包括令牌签名算法、过期时间和刷新策略。说明用户注册流程,包括密码加密、邮箱验证和用户激活。解释登录认证过程,包括凭据验证、会话管理和权限分配。详细描述依赖注入系统在认证中的应用,包括当前用户获取和权限检查。包含安全最佳实践、令牌存储策略和会话管理。提供认证错误处理和调试指南。","parent_id":"7c2ac186-ec90-400a-ac1d-b3b7ca2f01d5","order":1,"progress_status":"completed","dependent_files":"backend/app/schemas/auth.py,backend/app/services/auth.py,backend/app/api/auth.py,frontend/app/(auth)/forgot-password/page.tsx,frontend/app/(auth)/reset-password/page.tsx,frontend/app/(auth)/verify-email/page.tsx,frontend/app/(dashboard)/dashboard/settings/page.tsx,backend/app/api/deps.py,backend/app/models/user.py","gmt_create":"2026-04-22T18:57:02.317252+08:00","gmt_modified":"2026-04-24T11:02:17.638164+08:00","raw_data":"WikiEncrypted:1O68LCvyq1zgacF3KZk5YThbR7ok3g75/gwtsJvdh2o83INCVjstQiF01tda6hFb+2JTqgZSefMRniabd6NWxIcxLGQkPzKVW/Hd8nBmAPUj7rQun7N62bOjGs7Vdy4RhltwZryBPaspbuAyl910fhwCIzZMGRfD+PXCWNv/v434hWViOvWnjpYaMrt2sX9Ljy71CYMLz0NLL55ClE3+kRm2WBxbzfWvpabmDbKCJIjHUouLtLTqa8nO2ZD/mpn8P/USYy3J+ucCQEsu8jbkFecDJgSCRkNzfeLi54eh7hIPt3cwY3k1GwBPcK28HnOkNGaLuFV5qSbDgUwDBoJ1ZTehKeXMMxAuPFJ+1q+Cushre7O1bOmgO+I80GEecYAmWGgpx7U8Xu3tI2XaqjSkfRQHdUEezEWtGlEdBOV5pTVVkz/k7SvMCf0IQSaeAV4CB0uPNlyH37JexzmbUl6SbJQzlmX5BcDo56/DmhFUZ+iz591eZevVGaIdCDU9scQfmskMZZfkf9d+T9heLb3IonhkwGtoofl1NWkyMZ4LRfpoWpOQVz5rwZczDy6DzPtcmJMGgjGoJF5qad8II9wEjnSfCikdIKBXQM/KBIZKZDvEsRH7Kf28A8nCpNpf9eKymJ9xUlUDXB7chWBw+J9WK5EQplTeI52vg2TWVsMNSe/gBLV0GDzzFNuAIAOAh+BEGM65LlZrL89p9j3rI7YORJ+qtC/f7HdtqWPMDToAOV2WH9ykII3qnNarPzMf6QbGtA9+XEJw1P3fie457QflUMrUyuW1QAW9RXj3CdpyA0XWl7v69GhCW+ABebIpbYBRusC1DkAL1U16hWKVHHgqUV4gf8Fe9Chq1RalQUnIusIyrILaH9a4GAwAAclwJrHhLdDwcGeZYBVyM2BngvsRb/O3ChVyFYnpcM8mdwPauc5jvaBBKrdeyK61TlB6N6oOmNMsnvd+MbQGK9PFBrRFUzkC0+NgBC/hMn84JKFb9bM9QByG7MpRGn3SXDA8p06GgAXdN4la5zg9hm5Zf0B4pryWfgd4FuhV3KvyBM2w4YHORaKYN9xZtxAbX+IOODdualJ0330kxPW6dvHj7fPGxFcUQQb+/tR7E2nO8orJBmwWZh0YchjYeDSg1cD1y+YJUGjn6kBo2UeP1OKt09nDiSlHMp8EuHnvFBQpBxP6HevfwlW1Fg5bwtkTOlgAmJBltJgnn2qJpcbfTminqL9HbR7qWWabkMULUXBRWUSvixoKdphNXY++/I84oDc81EJBNgQz8ZglrU2lOzuPY1D/NDPfzU2MAwNrhMKGcVz2fQj6T4Ritr4wQmQEVRTdma8ST30CO5COXFne2c+0Jtnl/ASeYQcC8/87vsgSXxLQApyJARvqN14s+M1RDKVFG095u2ZXOboEbwN9cTPaDY72E387diTUEL8SKiX2kjnHME/eldUwbnuXM0raDbPpoUSzIunVEWrB21l/8hx823tGkHNjc20MuSe7gaDnYWxj9CZI07jHTk7KM+fVncOW8XC39kS/z+F7PcJbV+22DtWJkoi4U40aX/PuLYs8oyTC6NjvAaj0mgd0QVWF2vvW2R4XGpEIyIZ4Tx+CRzKGE8X9v7ysizR/XX5nLdr42F25yZM=","layer_level":1},{"id":"9b71fe02-5927-4a19-8db8-66eb129ecd9a","repo_id":"1095f823-f6f5-4e66-9aad-9f0b5b6b99d1","name":"认证系统前端实现","description":"auth-system-frontend","prompt":"创建前端认证系统的详细实现文档。说明NextAuth.js的集成配置、会话管理和用户状态同步机制。文档化认证提供者配置、OAuth流程和JWT令牌处理。解释路由保护机制、权限验证和用户状态持久化。说明API客户端的认证头设置、请求拦截和错误处理。包含用户登录状态管理、会话过期处理和安全最佳实践。提供认证流程的调试方法和常见问题排查指南。","parent_id":"d907a8eb-795c-4060-9cdd-50d31cf39be3","order":1,"progress_status":"completed","dependent_files":"frontend/components/providers.tsx,frontend/lib/auth.ts,frontend/lib/api.ts,frontend/types/next-auth.d.ts","gmt_create":"2026-04-22T18:57:04.21635+08:00","gmt_modified":"2026-04-22T19:09:48.747579+08:00","raw_data":"WikiEncrypted:BenkIlLPgjbiADCpekIm2LnLFWkzmPKE+C+tunEqC7EVMaC4hkq7YX8EJXa9qt893SobX5KrGOKV9QEeDplCQkFx4neCRj4kZkvt/lObxAfDgMBruR7HQAasniGfUhUjW5KYXC16w7brsqCWR8CWKDQGEZiduwEsaDjAZy9TEu7PlK6Cp8RhkPZ9jhN/YjqaxTAq5i4xHmQz4VuuV2SO1LedFcTlV12iJH/vTW0vFyXgJqY/Ql6+bTZO2yMaEWan9rB7e+IsErvp40JaC2xqL7fRnfroIwQssGEvaqckwf2qyNjjNCcewd62C6FVDnxJOLjQbizlBKmbb8XVzuRLkECZVB1edGJKnDV6FkOkP9y2Al2Qtpbx/1Uhx1Lo92eRd57kA0Icc/KGcHKRjNsW0HfYWAtLctTH3fNIwtmND/J/6zKK4UdDJ8sXiTnjiU4JhX/fqW8bl4FVo8F+kJYUIhbJCQkl+qlYh/MkTCmyG8XukvSZGbvWMPUxyU1gMjDxUnyVdcJmFFt15oXI+X1CL6ukGEn1cRRDiB4yRAq2GR4/iUPUFC0d3aqeRj+ryjr6Cp8YqrHfONdwZyWd4hS8RPEP7NeRuD64yNRSDFTju1oPvBfROcmunn1GaAmw8dV6KtXSJnM9SaiqnYutX51ah9psTgX+UxTu7EU/ijnQYUnDLg26m2/bX4Rhm4MRyE/fAwzxOKEI3uIaqyun0W3lgdaF4bWTwTblet2a9rBOwbVP1xtJ5M095JzboruOAhl29fAT9iO2jeqpZBoO7zBim2s8cpkCt/Zf2Edu2CeUkS180PzKCBtnq0FpPLD9hjXPsn0GjtTEbwO6lSl9JdJ1+J03tiLVJjRTZffLUlA2gM3tucbJOfyGdAom4yffwP8hjrhTBeEyLwKmLISNARiKuE2Cm671yMn1pmt85Vu1rajq9L/GeJdoPPL+4pw0dk8/Oydx0+kOg8/Jyb/8D+XobOK98UfLB6gCaeqZV/2EBEumn1xdhcDpP8cx/kijjzPmOg+tlXa5VzG6SpcY1zw1kYgyEbLZMts5EHUFYp+UCNixZleiG2HvEN5v2iuXOdcZiguCFkQLt9TkzO1v99jj08p64LxUkxY7ovJoeanwleMMBEAI0vWrt1+8nf065/WLA+s6zQWMP7nlMloMXAfMybSF/he7s2xGsrnFXqR0XBU9qRnrLY/9IcroEnKTvicyEUylh+wG8KUQcIJj+fOEVqPGITla0i+36wx46XgzdRw=","layer_level":1},{"id":"b80dc237-1a6a-401f-9f4d-14190edebcdd","repo_id":"1095f823-f6f5-4e66-9aad-9f0b5b6b99d1","name":"技术栈","description":"technology-stack","prompt":"为GEO项目创建全面的技术栈文档。详细介绍前后端采用的核心技术和框架选择,包括后端的FastAPI + Python 3.9+、前端的Next.js 14 + TypeScript、数据库的PostgreSQL、Redis缓存等。解释每个技术选型的原因和优势,如FastAPI的高性能异步特性、Next.js的App Router架构、SQLAlchemy的异步ORM支持等。说明容器化部署方案,包括Docker镜像构建和多阶段部署策略。介绍开发工具链,如TypeScript配置、Tailwind CSS样式框架、ESLint代码规范等。提供技术兼容性信息和版本要求,帮助开发者快速了解项目的技术基础。","parent_id":"1bb55e12-24c4-42cb-8f59-ddc303460d45","order":1,"progress_status":"completed","dependent_files":"backend/requirements.txt,frontend/package.json,backend/Dockerfile,frontend/Dockerfile","gmt_create":"2026-04-22T18:57:13.329718+08:00","gmt_modified":"2026-04-22T19:09:54.216074+08:00","raw_data":"WikiEncrypted:w0CkdCdnXCcvlN5xOpiEhEX3U68GI0Ngj6azFMJo9xRSxuOblJXg8Gncvj5vankATp2aJeXH/Zz4LVKH2Ep+cABEA0J7OIJMnt/ZJc7uvMtWJKS6+i5aGsUhX9BZcr1SC4TqdgwXb2je+DFK+fLZJVkri1Ne9BkEqmtSaV5CijFytJ/VSKFHzj8+7gC5Jd3CbEASojclHovCufD4dAVhlK2qcIuY3RBxMsvfRAlLyMLZEWg/gD7LEj0JaChWWR8vRaEtX0LtMoYIgSfbY/nUjR+3xHFig+m0qclK8Q01S5GJH99paLVqVkmt12iwMMiqNZypY1W2gRvZNsT8eanIKu0tq5HqvmbN0y9+nnuwnz/Tg6nUBlKIIS40jp2oYca9ak9bIwBm0TqkMe+M3Ara03+x9PgGRUuYwCt9d0PwpPG5/vOAkZtP8talqqwhn7Qom1nVkhmExMfsXTYsM+Fn2bQFXKIT/rAyT5rY6hwokrvghKwOb9pH7V8+4XckeKWV6L1rNcccOb6Inp4WcVBTcTvGbdy4Wj5Z1VETFwMnDdpOGFWc0jZRJpjrRSGgDuEW8IXpMvVYk3FV5ZyUXZcNyEWZ0Fp/s84guMC21/RYF67/9jD7eJYMeCsU92nWm6QkdVB13XQBOvYGFSu1QejQCgDMWpPz4kkt4yz9mgOtH7HsH8ZUDIml7Vci6pCcEIzS2Sy+BoXxSxcOzrqxD+PbGcH8A/BafN1771WuNzprCCTqbZd5MVXBKiY+qrlRCD1ug+pKS075xfWh/Y2Sjz4p1aJuyVplvOfNUKTlbZVBzQu5DBO+yhXj4b8Amf7OLydq0Avaf0gJhYhX3HpFNqi6aqT9OzPBIPohOUi9RWffBwHMJii2/NZj4GbgeXsWU5+EKE6sGFRGtUiBZGzf8FnB6rW16EA6in7Vd7Ls3pJrra3z6b/k9gqlh8eAVDoZhCPuxtA6yNlXm+RYWLDYeWiRDZoavKVj13rXtaqtX3j1/e1zFPMBZlDPVHyBqCZRiZjlKnty9cj2ASgpu7idyh8jDQSALGu814Wb55H1q08bvFxJf6pxn0JfbRJZMHqCEgInivdDUTcCCPOteDT0O2pwMmyHuq3mI3VzFPnYLM3aYzgJQsNIVztV/dIEJu2UGF/cyjIeROHaxvWYLNXRJZ05iMp8oelEwNe58eAvWt2KOuahqQl6xKUctm90QLv8QR9hr7PjiNAMVH3WsMxkqLcIUPuboMElVq3ErUqd4qE7W5l5Uxi2I9bVcnq4qiRtbCnRY32uC43wILTgq6KrBaO6dehB3eW4drPWqtmcU8rP1DJEatUWEvhpDNrI7T7wG6F+","layer_level":1},{"id":"7e5c3b8e-5aa3-448d-ae52-d5a96a413b0b","repo_id":"1095f823-f6f5-4e66-9aad-9f0b5b6b99d1","name":"表结构设计","description":"table-schema-design","prompt":"创建GEO项目表结构设计文档。详细描述所有数据库表的设计,包括users、queries、citation_records、query_tasks和subscriptions表的字段定义、数据类型和约束条件。说明主键、外键关系和索引策略。文档化表之间的关联关系,包括一对一、一对多和多对多关系。解释业务规则在数据库层面的实现,如数据完整性约束和业务逻辑验证。提供表结构图和ER关系图,帮助理解数据模型的整体架构。","parent_id":"243a1a45-d31f-405e-a3b9-694d2fe617d5","order":1,"progress_status":"completed","dependent_files":"backend/app/models/user.py,backend/app/models/query.py,backend/app/models/citation_record.py,backend/app/models/query_task.py,backend/app/models/subscription.py","gmt_create":"2026-04-22T18:57:14.160671+08:00","gmt_modified":"2026-04-22T19:10:23.576798+08:00","raw_data":"WikiEncrypted:TWtD9cYU/QQHU+vD+ojNNl24L1Ao0zI5Y2mk07u9ZlXGce4CUXsGNCSRaLrvDZHw4OUpuZEJrmJBXEQX8GmxRc1IXLTgRlqUGmpzfcUAx8VrQijBe+unqg1mWTkYnMlYOqKWSJdISHyD5K3kBL2cL5pXF+f+lPHzSbWtqMnNnMKbqnSl/TkKh6cr7PM1YBR4IYmE21gHSR5XoQjbtYmg5qNyKF1kMdcAd0LHw6p7zHBaF9cNt++5GyFKLK0zjN2L8YiFsuFBSrn/M48QW3WyTrvDvqdOuR/Slfv+gUsKgbkt6+NEpuY9HPcRdvVJHvG9FZedomH4DrKuI0fUXgICXotXbrcEe5dOkLKgfn+gXmS6sPSZ1XgrSNO5gy2QNJaW+oKBuEPzfuKsNr3X19FZTz+x620YmL1Ccv/5uvf0Zxl6fyQb3qP+lsh2kaMdhWVKyoBv37oNKF7MO+fy+TWHFEwlVnxgmQREyQva5qxLyYzu1GtDpGp79IemnumltTAAzQ7LRs/RsaNcU3BZdYfQspjnhukylPJpNZtmKNN//XWvj023bGiaLyy805c71DcyqZNUs+EdlXmRTABeq9QkVU5wq/gkO4RFSgsWao/8f2i9FLeEZolKQXzoLnX7GxaY3BMcynG+DlwKFEolVOw07cpddYEWzmVKgJUokX/eiMbrokbcv9bLXJpHl2aP27B2FXy5Q2Ot11b2WbuT532RndBI+S9HQpfMmZ2z2Fc3VrWAbk03DwChHEbNHpmQvJpjKtLweVEpClahV8iTSwCkwd43jJdW+tR00iSdjt5vbl1cU7Dciah/B/9B7CDr9sUyZMjly7kzyWZqTkdXde3tO6tu6tWhTigIMXmZVqhW/pgVifH0R72VuM+sdMw57m7Z89ibQ7o2LewlMzJ4GsV90DdDhHQtUr++aRhcZp/669o8mijOQKj8MPHY+xjhZ2oiS6RHiCYxpibVfauiaXA3swWKIQrVCVE1x+jB07pieI3wHrmZf875mdp9rhfrz96+y4zJ464iINUdTQinm/zI4CnhXE3inFBgr8bD3pop0oYr2X5f8Gn2iKyvByc+w5r8HKV/7dd4GrdAosqVWpQweVEYR+MHRZ3AxiW+TCpRWz/PsHgunD4m+AQv5lxwoHVqF0Tqw7fmmxTqA/zC+dxlIJVD/R2WF4sFpA6femHOwqniwaowQerg8bGe7mz3BCSqiobqGSZQ5jQdh34TRP7qUg6PGkJx2NJ6AVIZVYBg9JNOQI67+2PN5AKq6WiT7Rojgo1r8lEx8SORaVptbL4YEEeD8Ec4g2l7Aqkhdxd43uw=","layer_level":1},{"id":"9fe32b83-3697-4939-8b10-524f5ed3e65e","repo_id":"1095f823-f6f5-4e66-9aad-9f0b5b6b99d1","name":"Kimi平台集成","description":"kimi-platform-integration","prompt":"创建Kimi平台集成的详细文档。详细说明Kimi平台适配器的实现,包括Playwright浏览器自动化配置和初始化过程。文档化页面交互逻辑,包括搜索框定位、输入处理、搜索按钮点击和结果页面解析。解释错误重试机制的实现,包括网络异常处理、页面加载超时和重试策略。说明浏览器会话管理和资源清理机制。提供Kimi平台API调用的具体示例和常见问题解决方案。包含性能优化建议和调试技巧。","parent_id":"7e66719b-4a8a-484d-889d-10fdc76788bb","order":1,"progress_status":"completed","dependent_files":"backend/app/workers/platforms/kimi.py","gmt_create":"2026-04-22T18:57:14.59267+08:00","gmt_modified":"2026-04-23T20:35:18.737652+08:00","raw_data":"WikiEncrypted:0zvMywNpoUVtx5LPNkwYYfwlM/Ie9jv+tKyKKcv1AxRC9mVBYjtaMmDbjB4bi6R3DoFVGOgv6ErdxCywJprEc4/FOXSuinoLipOBEjS1SoLvIuIvglY6l/IjgeQW61Rm7d1YcswwpmQZIzWMvqp6xJswdQOA6I4OCWZyyoaPa/2lETrzZcBW9ssD16KyXFVp96WbqY4mZhPFxSQEDiT4cUJ/clUzKx+oT4S+pSOYSGl6/5YsuAOA3Rc1HhY9Ow5FK9FlKsVMaFmxyJU/KLHcwZslXi8yzFzIWcnJQnRmMQlz6Zzz6mhJvkfg/s1TIOTiz3ZX906YG6DBXgZ66UywONJCeYpSAmTL6PJmP5z+lNRhuD0CzfmDGhErgZhLtvoyUfFoVruQmx/x9Rgy1lFnhKmvH60xIEg1eXiVjrQ/yktlr5ioCPigx1TWbcHspNlPAbDuKqqBhQtNOIgnlpoGgyEogad7Il1hkawUxt/TaiS3Lh0SN+zWs028ewgjO9gdWMB7xsAiB1+L5jMFCCJP/mhbPEfqnGC/VyxfevmgulrRD5A2EPR0QF4D/XNbc/vqSGqnIgkBngdxV4ibQlp1HO+Av79lh88FpVteFuEf6bsCL5SSHLDhJ8seJm0aoD1e6f+DtutdT3mVHaMcrEbMYz3AaNJhbNq0bEuElJ/ANz3eN0m5PPDjjnZto+CQ9o7K0C3DeRqKx2P0uRlrzhuBWIwJMzcC944SPjxYEUXHfT4C4vryztUifweDRw3eil4eFCrCBpGf/6gsdtqLoTPs1uBBVkxVh2UFoypvq5jwW2g9IkwMSHN/sAbNIITH2bRVDR7Z/pJay1eQSTjF1pz3NWcM6kQpB22XVAiOhiWPjJRQuWDtpRh+kOxWUSLaNkXSsf98tkydtHAPkMfUhalyLYFO/66PWyHJDWdFPECqtsOy5mpoJdYD0O/20+xc08z7liVDDgIlSocFXHWG35upSCjW6JWCIiphXqsI3He/dWHuwvTBamA9XB7Q44hTbQY3lKiTRjkbjuNfX8cmxcX7Hq21kTW6OBbxTVR55HSW1znrOe12b0sUz6V4Sk1zI5OB","layer_level":1},{"id":"cc7a1f1b-c70e-4c61-bfbc-6dc408a12ff2","repo_id":"1095f823-f6f5-4e66-9aad-9f0b5b6b99d1","name":"查询执行流程","description":"query-execution-flow","prompt":"创建查询执行流程的详细文档。解释从任务检查到执行完成的完整生命周期,包括查询状态检查、数据库事务处理和异常处理机制。详细说明check_and_execute_queries方法的工作原理,包括查询条件筛选、批量执行策略和错误隔离机制。文档化单个查询执行过程,包括CitationEngine的集成、异步调用模式和状态更新流程。提供执行流程的时序图、状态转换图和错误处理策略。包含性能监控指标和调试技巧。","parent_id":"7416db23-312f-478d-8883-2fc3c41ac2e8","order":1,"progress_status":"completed","dependent_files":"backend/app/workers/scheduler.py,backend/app/workers/citation_engine.py","gmt_create":"2026-04-22T18:57:25.383473+08:00","gmt_modified":"2026-04-22T19:11:29.353795+08:00","raw_data":"WikiEncrypted:l9Ho0Yh0r5bYH9QEePEhka2UMFH582eHsB+P+EaGE/r7Zj5gVUJmL6923rRlAt7h2uvHOVtef4s71D/S/eYpYYgI+wRFyPq+fQZYOCmVnMBRyypO5m8WqfyrsSGvviugw2fw2oH6ruNX2ul1LjPKkntbj4o015R9XwHG0oDdyJlipxqNUbh66IV2c2DO1besCA/q2yTeLh6EiHD+vYeG3HO5H+y8kykMbBuh9eydnmoXBTCsTlNBHH8gzmZWEBBSL7DETM0lYCiNr6WpRCoeZEo9ewLagGq1ammmMjcMg+7fO/xo+ZkkACRTnG2vnKh3if5fBjzo9tY4tGmtF7Fevx+yjLRfhpPsg8vSRZeaggRPgub5zBIulo/4qZhAvIVsyYuAQCqrwq6mBxAEjgWWrWjOThUEQOntbugUY0DitRui7XGp7tDjAIWw570xWzTTUWe0CMoHIPghfvhItcnYfjKK+fapnQTnz159jVJarLbBdjZT5JJfw9a+jlkVyF5RIKu3J03cjGFJeBf74DiMxFIMQkKzgL8jg5YiLQTisI4X0BBQrKHQvHzsD5+VzHGwCsz7IIfcdZuhkg3PIA4z4V7eZP9tOBUJdh7iE4fjhOk6fVDG5iZME72OxpBtFkmfrhwM52swaToCosj1eQ5m6V2GjsYY/+ZvaNf2aWn8vBJHI4IEO+Ua1mLHkPRT9bhDGS+Td2r1R2fmSEEvNQ+PTuhnRAyzRASTsjfWljzNWGNmcbCtClwcIuTSwPWLAoL+ANl303UlvxObHa9udiJcH3pZ86+A7iBLoCg6JxZQuCSqD0W6bPR/vozpiCvGs1TvMR5tx6AtfZGWw4JYl9wN5iPPaP8sPsz40D4PWkYIb4fIYY/X3r2iAnbjpV+/8+h3DQCWEdqRNnkZ4Do+XZGOi1yH7QaPOf/RN00+bcNtR36PnzENY47tg8VfPkbt47YTWHf+qvWfMFPwco2hLzXvNFmYN4dVMld5V+9mzCPJSIb+JOcDoVkoGuNq7aXnOVFdERnypgzvjryBt3W2LgPNlD3k6jR7pJAE1gKKrl00VSdDN9npu4QXyT49p+YMv9m8Jbf9xo1Jn2dqM/cJiKZi1FLR0clZHZ7nh7/7WxoEqbKnLWbboi/qyuTABO07nyQfmyXR/24bRp3AIRiM+7Bq8KL9ZFZs05JmFBtaRCAzWdBdM3TElVkfFOyZRZeKaBlk","layer_level":1},{"id":"fec685a0-c9bb-4048-baf4-40b56b2aa29c","repo_id":"1095f823-f6f5-4e66-9aad-9f0b5b6b99d1","name":"集成测试","description":"integration-testing","prompt":"创建GEO项目集成测试的综合文档。详细说明API端到端测试的实现方法,包括FastAPI应用测试、数据库连接测试和外部服务集成测试。文档化测试环境的配置,包括测试数据库设置、异步客户端配置和依赖注入覆盖。说明如何测试完整的用户工作流,从认证到查询执行再到结果返回的端到端流程。提供数据库事务管理和测试数据隔离的策略。包含性能测试和负载测试的方法。","parent_id":"fc6f24c3-594e-4153-854f-19250834eeb1","order":1,"progress_status":"completed","dependent_files":"tests/conftest.py,backend/app/main.py,backend/app/database.py","gmt_create":"2026-04-22T18:57:25.616681+08:00","gmt_modified":"2026-04-22T19:12:37.820526+08:00","raw_data":"WikiEncrypted:0j4RRfWJQdenLQLpT+DwLTyjMVG5sQffpuJQoSG8tbOVCukW9eq2bqobYYACR3zRn/N/FP6n0t+ZzbrLBFIDPbiPv5CjhNbth11wsRap1Da2YyKifcvwg7uyuWtSILKRIkP8wIVHX2/TkxRFQi9/m+9Qz3xVjYcNeOD0G8UWxzsSDqYGS90xX9MVwW3N24hbwwcJUE/TAMETdbhwrekpr33ej8R6IT6aBvn7m0Y93BRItueF5HJcUtKCizqJqcsG+BIQ1fodLPAsUiqvYW5dwymM89ASYiZXVbCOJq19yL9K4p1ZW1LsAc2J+6D8SR9RJ//D4gGwBmMTqxyP9bgn5eNt3ILeVMXWLXI9oxaDrdVs2Y4dXNC4AK1j0pegZkiNREUo54kWHFqCuQ6dG8dZB7BmnFEIYjwEeU29KdF6i0dyUH3/h5QjdLfc0OV75zuHQPaMs1p5fn3vo6ubXz/uWtxEF/IoVhph+AyY0Gci8TxdouTw4RZOm9I6mo5m4Y+TBsxUb9RO0WCrD/U7tRgIZcrxFfkORsKadNWm60Q4SRJeImUzxIVCUGBjr4km9AMwVsl94KSXmkBCNOFppeijE4N4Dl0n+RekVA2NBOau2woOIr/GwJ7b2h0jV/5/3x5hihxUSqZJ/q4RJmV/8aP30XRdYwZ6qiLcaF6Ic8kwpaS+9cvzGsPMcUF4GCS6ZSZoq4tuGj1ZY/iFI0w6Wj7rJHWbeBhsF/fHqFm2ijbrvn2nz+lH8Gxb3FM+re81hKNVU3BaZ3fxOAldPPvUxDw9tttWR+oH3F/gRkqefOIsw95LNYf2vIq/HXfNygn6mUw4aYidP1SY8flPcCMl0mDm7y7W6l+DKUJuok11v6h2AM09f0VV9JnGBMgwCic1FjQmfF2FWdqlsEaB0X4+aPne0DgPyIivgCLEq1dyneDm4TxA3CEVODVKHIu4fxPjmDtwbXUvPQe5sWkG7AEkp1Vuul8T/GLjJc/DHgUFe51MPFk3+8i0FCKo0x0fS8Mqm3spHB5W1tKYAIyexOgSkHzqgRdgERCTqUW461c4lKbFO2WIJqWgt/seMgxHr02Yk/pvMU08AaMRC974SfB7kP0lEQ==","layer_level":1},{"id":"b10c2334-a850-471a-9851-a1c698e3a485","repo_id":"1095f823-f6f5-4e66-9aad-9f0b5b6b99d1","name":"查询管理接口","description":"queries-api","prompt":"创建查询管理系统的详细API文档。记录查询任务的创建、读取、更新、删除和执行操作的完整流程。详细说明查询任务的数据模型、字段定义和验证规则。文档化查询任务的状态管理、调度机制和执行监控功能。包含查询参数配置、定时任务设置和批量操作接口。提供查询任务生命周期管理的最佳实践和错误处理策略。","parent_id":"dd12cc44-0c95-45d5-a726-e7b8bcf2531b","order":1,"progress_status":"completed","dependent_files":"backend/app/api/queries.py,backend/app/schemas/query.py,backend/app/models/query.py","gmt_create":"2026-04-22T18:57:37.836674+08:00","gmt_modified":"2026-04-23T20:33:57.631967+08:00","raw_data":"WikiEncrypted:pNRlLcrWPaMbqj3wxGubppFNc0/AzaZuAQDxEKkb9fgIpRlV367n+a2PWiIY8g+kSLtBeyylocxMvW4jGcb79BLGGixlb4O6TPBIJc7v8GgK1UB+nLdmTHx/nT1JfKtrcPOkDjQ/yPHvw+ykuXomGaA2hiHzzBxAe+PbZILYbxYpQjnTqh7v4SGaGQ9U1E2EOXJ0RFpwna+s0NYfvBk+YvwkzRYPMiKcr+F4pcD5xTUWKMHZO3NuijnbDIE02fzYXvZ/xDBLubLxQ9Byx2dgdWxmi+xwo+gspb4v/DcrNll6qDWKwDnHGuyOQzDJJ1vXg3AaxwF5c2JyyQLNPUM7YV2kwxweQA08sFkJHAJ2yA0z4XM/DvAPZRdQf54LPlDB1zuFh8c3Ih5WaEO7+aTJM4YSmIYUbqjIjbqsMea3+cY2bIHXq2kdRT7uLikCktC9Lakrz0fFKLoJLovY3S1UBP3i7tCt6cmtMlN5g5hyHGqIVTT/fqAVUAc7wSZumMs4rr4uyEizs6t12KohwD2SqiCePMC+kbUpHV0fEBuzGlnYqPbW0yjiiVQlmIe8wTDNiNNa88JmcXkQB1pYhkAYrBUvBUN4Nrdf7lGBTIbQkQwvVoHuFah0MmoLuRQtoBqISkKJ9PMN0EOofu4pUNKyxmmcY87ZVbUNrwkgbvahp01NhzlsOLdxEa7d/74gFI+6MOrPY/6TcJqttksCQEkme4HWeJgRl5S2bCy3hlU9qcZyk6WAGPjVZg4JXdq2UbvBokHzB7KA7421mWkKGQALuZcUApNvwsvF1ZHjVau13wxP02WvaOzt+udwhgw2PXdNi26RDqwLhRL+GIjkpNfVngOcLfk1ULiMS87NXS9kHRTdXxu5W6PqAzyrgByrL3G+nPHL+XmMw6ntgsJdmtYmNWV0VijOOQGxSJGQHtaif6ZhBP+ckr+OXJ4GlkTF3jvGcfRkfx/eox+BaoxWI06xuXbFfImPuNqqa6odgzQzWv4CkvAnjcFq7umhE9Iri8xw/PDlUzBnr4HGnUPnAVvdomeMasz/oiPVTaI0O6tO3+I=","layer_level":1},{"id":"0c1d3542-92cf-4796-8dba-82caf2f7b361","repo_id":"1095f823-f6f5-4e66-9aad-9f0b5b6b99d1","name":"开发流程","description":"development-workflow","prompt":"创建GEO项目的开发流程文档。详细说明Git分支策略和工作流,包括feature分支、develop分支和release分支的管理。文档化代码审查流程,包括Pull Request模板、审查标准和合并要求。说明版本发布管理,包括语义化版本控制、变更日志维护和发布标签。提供持续集成/持续部署(CI/CD)配置说明。包含开发环境搭建和团队协作的最佳实践。","parent_id":"2148d7d6-25c4-497f-8894-c4eb7a0d2bd7","order":1,"progress_status":"completed","dependent_files":"docker-compose.yml,backend/Dockerfile,frontend/Dockerfile,backend/requirements.txt,frontend/package.json","gmt_create":"2026-04-22T18:57:39.374243+08:00","gmt_modified":"2026-04-22T19:13:23.08237+08:00","raw_data":"WikiEncrypted:F3QgleoEfoy16cQggYe9Czfqaqo1gAmvHQcnSrNK3eg3bg6SLp6Qtm0Hd5JwzGY3jDj+dSShAoxbjZ6YvxA0ahjJ7+4npTrro/p0OlyQfTnVZ5PYAZZMMXhJM063eUYiuQW88+rNBbc3mKbsAdZboYndBnd6/wybElFnP7TORa5qWxWMveWf6U7O01ocA+ZnrQqoPWB5xrRfSzD1p3yGFA3fzKobYoxAAA3xE1ALEY0vjLN7vajgFVllC2Z6uKZOE4Q6v+W+r18Pr7pLXGDJM7b6pEfFCqcEMw2fWzUAFYSUOjSyg7j9TjP6Lae0AWOmmxIDmJIIiaY0BCv/iOXgg4F6QSChC8bZFyWJATWTNhfmHAMU6tYpDXqDsfLmRpczznZ5nzTtcX+87Ndpqchh+NWU4y5OYvzEeMRCh3HcCUDs5KrOoCJgRneV8BzAxfk4gCwSo2t2D/FYg1XWGfb6hPdmWzePBCYhhIGeDQRyAdApe2Js8UhXUOD3TM7yzFPMX9q5U9ZBfejCp8TyW2thbRzOL4s5Fto9PpXg38HbnE59l0BmptA7z5bTKTp4DHA8d4NhgCeDbfNLfSJXbyYaD3RqsQt8szzbxB2Q8mvEi8iUZUARZR0lyq0oEw3cYkZRo7Dcb1n5az2OJRZwHmvRYAm7KceVqa92aKeBUlVrfA7nOuwsVH+cEXyzE8ApglbJiQfTJshljzVBvYPkz0BxhBcYrnRIjy9TlqfTs67adZyWc0wqEVZeZhuYHwwN5yID2imZ/nq7cqiZCbV1dtBUUM6ayhVX2h/cBSLpHKAwVHAg9bb9V+RxXgtSYWYKCHsAD0ymmu/Fzk3/QBvrrFiVqL4b/5CKqk6Qi2dh4pN4tZg3zJZDuyx6xzWSrsHeYGnLunZQWtHn2lr2vR6+RqzRTDiOC8SizuAjeZP72IbQf5Xyyf65hS6yls8xztLA9oDCNnSDgJ/RiNDOspfgUyj2xemyoNqf2eJ/kCDdo4/VXxMiKVfg3MHY+Vi4dVlRcSEJYLU4AYuGqtqVhTIi2ESpnPXgDPAIT+ZZPqg0hLIIPx+HNqo5qz0qqxvliLlcAhizNT4MG3p3dBRI2IkylW4gHg==","layer_level":1},{"id":"109a8fb1-6619-4bc7-8481-e28cc2127d24","repo_id":"1095f823-f6f5-4e66-9aad-9f0b5b6b99d1","name":"生产环境部署","description":"production-deployment","prompt":"创建GEO项目生产环境部署的综合指南。详细说明生产环境的部署架构,包括Nginx反向代理配置、SSL证书管理和负载均衡设置。文档化环境变量的安全配置,包括数据库连接、Redis配置和API密钥管理。说明生产环境的性能优化策略,包括静态资源缓存、Gzip压缩和CDN集成。提供安全加固措施,包括防火墙配置、访问控制和数据加密。包含域名配置、DNS设置和HTTPS证书申请流程。提供部署后的验证步骤和性能基准测试方法。","parent_id":"803bfef4-3985-477e-a61c-915a246d0061","order":1,"progress_status":"completed","dependent_files":"docker-compose.yml,backend/Dockerfile,frontend/Dockerfile,backend/requirements.txt,frontend/package.json","gmt_create":"2026-04-22T18:57:40.355193+08:00","gmt_modified":"2026-04-22T19:13:58.697418+08:00","raw_data":"WikiEncrypted:1PcQ+NupkgQiLQ506NXlaizhNZeqS8C1INCZPnjb6ozpR9JAOMhzbAgtECu8k4VbH9zFlJ7iHctHtUva/hpzUaHUxVuG/rnK2RrcCUGVfbG0WKRpjG+EsQheC10ihbe51Rb+uXm+ciY+/SOxWBmrtK9m9jwSBQZQx2vXLOPvachfZTksEB+Ak0/Y5DF+vjL4WN+ym2SAYi7dW98iM9YCG0AepSeRm5DxENKRvtPR7m+w+vL7F2oISKi67pFiAATpFXSSgbkKjENZIgPfqc+pJfUREOrnHANiCx/oVaX2aOb68pluM8RGtAgyOfMp097D2Nt4PR/HN691JphbIyyeHPc82yGTjeuFPfg5XqFkhM4gvd9EdBLE3/6bh/MJhYjEwmN2RRhz7EYgLjSss8gEdDu+YLIEbHIaIC5fFS7gss/cJULC0/i3v4nnobE2Iqh3WdeIMAmynsin0sjO60LhvRmXlecODQ7+1EeQpMWju5LwTuVyX3dnr4CO4rJJxEBNYA4gaJuef2xo/ZXoun6cEIHjUq7qVNVOBZw2QtqBD2CyY3NULBP+nDD/NwjH/Gh98gl2Q0am/gLAHHoKcZfkSub1o1m1ZWTFgYn6MqyYv95NuqxR5+MSPb9C6/rwkYduPmovFsS2Alznry8TjsLdD5iSNz9MdRTR9iNV/A/TIIovgVogXlgCwnIz6EXZUgDnTeBTfTHxC+gwTrSKXUigRlIxEGksBJkzktpQA8y9mwnIfHgRDI4c8WEQRGEcKm2N3/ZPVOyBHSOHNpXK/BX8MCQqGoj0x6jusO9pJehw7KRprktlMbB0LmAuc5i0RYf9SnhsGs23W7ktzhS+uTjRB4kviSWZdHs+hgh1Pu0HsyBZxX7pemalNElQsWbvLwFNsJY1L1yjHNbBDYyXC7gZZqdb2l9GqKVgozQuK+qUUA0Vj2o6Cr4CxL01vBYMFpHALv8KnmAI2CuprX0c6PmsXV20FAFF8tIxoGfh7qcvquq/d4ONxZ5FZ1hJPYzi2xeCU0p8gFYEYYlbGMXdLCk0L5Tu0aDmTVkkrZlOHSIneYJDGZ1W/q+U6W18i48iBLvFBHD19jGHBgdzRuX551rbt4axStOcEGuyFrivbWK9R2zdcffHbiRtxe9wSFXxthLGe23JR42EF5PmZmMtlUhpV6alxUZNxguf+q/ouSz7Xn8+o6amnO60N57RyJjJO7O6+TgfHeroxL7CpABxkru/vXEJ5XTLqZBiECMMi4keQOqUbNZX8Ioct03e1YG7OgHtDSayZFtZf3kwN2ToVkxIRpLHTUHxSWLZu0YiAI2MONU=","layer_level":1},{"id":"4d5ac6d7-8812-414b-b8df-68574cc36d7d","repo_id":"1095f823-f6f5-4e66-9aad-9f0b5b6b99d1","name":"配置定制","description":"configuration-customization","prompt":"创建GEO项目配置定制的综合文档。详细说明环境变量配置管理,包括数据库连接配置、AI平台API密钥管理和Redis缓存配置。文档化功能开关的实现机制,包括动态配置加载、运行时功能启用/禁用和配置热更新。说明性能调优参数的配置方法,包括数据库连接池大小、异步任务并发数和缓存策略参数。提供前端主题定制指南,包括Tailwind CSS配置、颜色方案定制和响应式断点调整。包含生产环境配置最佳实践和安全配置建议。","parent_id":"b2bb2e3c-5661-497c-97dd-15bf6ee8b7d4","order":1,"progress_status":"completed","dependent_files":"backend/app/config.py,backend/alembic.ini,frontend/tailwind.config.ts,frontend/next.config.mjs","gmt_create":"2026-04-22T18:57:48.684725+08:00","gmt_modified":"2026-04-22T19:14:17.843426+08:00","raw_data":"WikiEncrypted:aC5ZtUyEKPSxjzg//aVllKOp167MIMMk/Juev/hVoGY4+Uz0exYT+x+CbyScHHV/Mh1WUG25XsdoZThZQEtO0sLOn9+hGddmRIK1DWfKa/hxxPvnViNvXvltvNYiLNOIbKgkBxtXovEsADGNyhZh4ndOp+a/upcB9NJ4f0miwJacx2Kc2MyCkDCgUM/gJEjyoB9tRPRJVPFRvprzmaiPXJ1K8jd+KuXwrM12ogUA9iPZOtJJQTeEXQVIItOZYzY5bzAZ/mnRyVIB11vegQ+E6Lzm7D1Nza2QOZ2893Bzu61StECZsNlfecc+xEh82aNHrbFip7Fg2I3E3fqBs5EgoNXO5Wnvkcd9fHCw9vI9kMJucTIPcthOyWAFiP56zu6Hzknqy5N0o2gSAJQdhzzEvIUUKeeGDZKSY2EjFsH531gWa+Q9m0FsYWFcErqBlQXG8K06rnNNeMwR71GloOifAK0ySuik/7BjJ7xIR7HF8FOfSaOhI011z3GaEBxZsMfPc13v0joKHld4p4PRBXAfExWLlfuM6cmB/77U4xdBrHVyMcS8NPKuT+TQCTzjr2uUKzxUcjbz+yGbjVFGKMaVzKH0UQfLKeSDUnb1JNBrQWR0PFAuZsPZt730dAHdElNx9MenV8/GY+XPklTXdGMUtflT6CKf3fLy6ppMVbMDph2Ov+1Xh3z35Y5Mz3rufJasyOE0rZQMNsUu3wHtnjYprxfzvmpP9En5z4KoGEa/282c8xoLp+n3+etuGCN2aor1BSrro/ZpPTduyQtqj2WdfXDnZo1In/RRAh0TwqPze8Cd244OFfKDDAEICSSoZl0S/2l15QyTbqDNVnRzLndJswfAi2yfaVOEkBHvZuDQZXmmlf4VGsJYihVUwG8Y8bvegjLxgcD3LFGNKjzuKP1eAYLcotF84HRaFwNG3hz8Mv8puFMKyrHVKIC3UxzBVaialQqdO3oFRcrLdcSIx1JlY2qhK3BsrUtj0OLURUs0dBnCQS4ndq4NTLSQECFIifA9l7GSPXyOkGkp0+H5QCfjOl7L/3EJ2o+lTisAZggIZSZ57Ig3WxOGp4tgBh18ubr0TRNi0u/VccTbFyT97irQVq+9KNBKwPZZazaWvJEuqNSsdX3WGjh17VTbbZgmTkAwLyuCf+nyKkGUkq6MtRYwX17XkQuhceFpBmYkoxlfSWr4odGaspQ3c/AJ5zFNMigymGGpxOynWRWD5Abo/3R67eqZ9rZbmCqQbF0fkFPxdi1prJr87dubXtG1Zkj8AE/ZGXYjwas/l8NeDYxLFeir/ic+yR2tcU34lFAY/B86IHf+EBSbBYigErIEadb9gw81","layer_level":1},{"id":"a232faa5-28b0-4235-8ad4-b082fd226e69","repo_id":"1095f823-f6f5-4e66-9aad-9f0b5b6b99d1","name":"订阅管理系统","description":"subscription-management-system","parent_id":"178b681f-d013-44b7-aef8-dee7ca8c22a9","order":1,"progress_status":"completed","dependent_files":"backend/app/api/subscriptions.py,backend/app/services/subscription.py,backend/app/schemas/subscription.py,backend/app/models/subscription.py,frontend/app/(dashboard)/dashboard/settings/page.tsx","gmt_create":"2026-04-24T11:02:30.91857+08:00","gmt_modified":"2026-04-24T11:04:05.339576+08:00","raw_data":"WikiEncrypted:esVoUJ7ZE3JHzIVFBls2kBN3sRNq72F+2dVFRiBKd+IrKVrEmIv5onipM8erIVXb1pP69wHz5wuM2zNLXG0Ok25RXMybvVHkFqWAEJZpvoheUZoKQmWosbt/UANV5ZMnjhjv0ugRLP8tCwG6HlqUXa4nXCgq5eT+9CKzBTZAc4gf0pl58FewLHZ717UOV2vGW8V5Sc2aVmo/U4kxF9AoGPen+UMUBOILg3LRfP1EM8uA0NcfMu0/dTEUhVAoYdg3egrk6V0LTUamV5NV1SNEVaJfKvMAbt0cYc8sTySSeM8Snn/OvSpnZV2OyrhySqbTxicufzGyCTg/r00/80Kp/vQ96wbKsGjdmbm1F12CjGpKngHQMvn6jGX1n4TtKe4WXqhzWD8nSBjxmMuHQfT8IIpn7seKyIYsAno3TuGU8reVJsl4T9zxMpyipiCssZHp","layer_level":2},{"id":"9ac86c99-3b7e-4745-bc95-9586153d616e","repo_id":"1095f823-f6f5-4e66-9aad-9f0b5b6b99d1","name":"管理员仪表板系统","description":"admin-dashboard-system","parent_id":"178b681f-d013-44b7-aef8-dee7ca8c22a9","order":1,"progress_status":"completed","dependent_files":"backend/app/api/admin.py,backend/app/services/admin.py,frontend/app/(dashboard)/dashboard/admin/page.tsx","gmt_create":"2026-04-24T11:04:06.082629+08:00","gmt_modified":"2026-04-24T11:06:01.089787+08:00","raw_data":"WikiEncrypted:VQqnnGxIj1CWE0rWwHbIomxfew9b7C1uZnUxTSvoHNsF7jhPgOFZS93QZowJJe0Bae/WW9gTFISgZqZ6JAIQlKjp5+H4hYIxP4IyhsAvFP0LcPKdx9gdtkqMwGuidWR2jaXij4fO24hbtjQmmqGXzUUbNnTur6SoiIIKMQ50UFibNp6+YGkvBNWvYJucvpgox24f7/W4o623WN3fB7olfkunOV4HVtCrMdz7LTroAFTZrFhDQtadQmH2JKYCypsT6SHcUyxNUvEZKgLDm1LnOAV0ZyfEx3DuALwEmdt1djL4f0HygoGjNMpqhiA4vnlg4puNMiDyY1yoIUNQDPK+RQ==","layer_level":2},{"id":"d54446b1-5984-4fe6-8fc1-ad0322ab7914","repo_id":"1095f823-f6f5-4e66-9aad-9f0b5b6b99d1","name":"安全增强功能","description":"security-enhancements","parent_id":"178b681f-d013-44b7-aef8-dee7ca8c22a9","order":1,"progress_status":"completed","dependent_files":"backend/app/middleware/rate_limit.py,backend/app/middleware/logging_middleware.py,backend/app/main.py","gmt_create":"2026-04-24T11:06:01.807432+08:00","gmt_modified":"2026-04-24T11:07:19.927506+08:00","raw_data":"WikiEncrypted:6g8iffgXzed698CsRven+bBahvPZ7dIWZ8oYo2ql8SUqS81oHqMdt4/8dBPkLJmUIV4rpltw/NKHLMVVnedRfw/FNgssHH7lJc6ouSeYuFX3t4LMNLJCZkqOnMgC+EkvVhhY7xeMZKjKAR0WN5yHtQ8nh+sWXX5BRoIgiZVs+G4ejsoPo06ZZ7dCm3NkqT1esGxyyfRka2pRlAtMZopE67FJNPBax6aDb7t3Tp40D3FqwBrnPkLvNpEpjadhQJLLGbUZ1ZVau7pWleXvys3qtdfdlpt3SRU3GxhleT5RyWyb6H7xliffBBWs6e2+EPrg","layer_level":2},{"id":"d645182f-1eaa-4439-854c-0437806ceebb","repo_id":"1095f823-f6f5-4e66-9aad-9f0b5b6b99d1","name":"PDF报告系统","description":"pdf-reporting-system","parent_id":"178b681f-d013-44b7-aef8-dee7ca8c22a9","order":1,"progress_status":"completed","dependent_files":"backend/app/services/citation.py,frontend/app/(dashboard)/dashboard/reports/page.tsx","gmt_create":"2026-04-24T11:07:20.621291+08:00","gmt_modified":"2026-04-24T11:08:42.188151+08:00","raw_data":"WikiEncrypted:JtXUgB2EREv7ncJ+MegCx6wn6P3rv/DbcpMX2oD3DhY8Q8TNEnThfOLhKKIJTZNfzlKgubFFqtmmSTVW7QSMR71tLjgZgSLACwoE6wo1/FhEifj/8lOp77v9Aa5u7WO+EgtLVWSz4kKO750z4owTufvhVR+uZ2ahVoHSKD9mXo4KuqrWwFr60hm65igoFdhy/Y+hyNsaJejQJMCUwntWiPiJoBxyTIgf/GpbNj3Ed3Rz67bKvr4/rnGpjDMYKrLKqH5QhLo8wpIaf7MZcfqc6GYtYhyLXCLk61wnw7Xgs08=","layer_level":2},{"id":"7c2ac186-ec90-400a-ac1d-b3b7ca2f01d5","repo_id":"1095f823-f6f5-4e66-9aad-9f0b5b6b99d1","name":"后端系统架构","description":"backend-architecture","prompt":"为GEO后端系统创建全面的架构文档。详细描述基于FastAPI的后端架构设计,包括应用配置、中间件设置、路由组织和生命周期管理。解释数据库连接、ORM配置和异步处理机制。文档化认证系统的实现,包括JWT令牌管理、权限控制和用户会话处理。说明API接口设计原则、错误处理机制和响应格式规范。包含系统监控、日志记录和性能优化策略。提供架构决策的技术背景和权衡考虑。","order":2,"progress_status":"completed","dependent_files":"backend/app/middleware/rate_limit.py,backend/app/middleware/logging_middleware.py,backend/app/services/auth.py,backend/app/services/subscription.py,backend/app/services/admin.py,backend/app/services/citation.py,backend/app/main.py,backend/app/database.py,backend/app/config.py,backend/app/api/,backend/app/models/,backend/app/workers/","gmt_create":"2026-04-22T18:56:47.08233+08:00","gmt_modified":"2026-04-24T10:58:51.176465+08:00","raw_data":"WikiEncrypted:7Nn1MUEMCjrO9aPSED6FHT454wxodEJExHk1Z3tdkRG7psPg9iIsEKvTk2vItDaJAXIG4d4xq8Laz0GUpWi7tvVyLa03YCfOyluItzeFyggOAAnOECGGCu8+eZnrHGjCrLMORlQ+1wEw9nkOpcZHrAs9OhT91iKgU5h0B74rt6WjaJ6MNzH84B64xYyEqmHM0niEHypbMjA8WO+d7J7BmhjgtxWBkUJMprVu/3XnDqSwD4nrvstGxDp6a2Me/1xldqPAIH33Bh7jHl8jwBH57j5llwy6peK7Pcn56nd6/IUHuPpwTrnoc5YduJIMKWGYxu1xF9PNaWMAkurHhHCoMemJuTlpc4HVN6jdvDHV1XLd1WD+tWrKhA2iqcmzuvaGu9XkVGmdF9XSUr3QcpLHFeBkTanbvFYTANI7G07mjpGtPOIvGgmHilbbqh883xvi0eQEyrXDdoAqA5jU+paPRtXoLxib8JBQEqB+fcKcniH+C74h9BHKdauZgcLRT46tYmeFNQiyrNO1vcm7emWe5DFtjbfwrxYUv0K5IY6AUMUzoATIs+eb7f/Y0X4T56LR9E2aUyeViaWeVtnLMiXVSgRMz1/fAG0OfZ1BYXRB08PvPctEfVdY3C2FC9+10XmkN/9fasMBvjcmO9WvIqX6eguoLy23soTupv+OrVuoZ6hiCfInpOcYV2r/ApKBP60ayqitCwvs+ndNATQGz2v3VVvoolt8ZIZvqhvzyOE4JAltTznL18weTTPLWlFYhCPnG3qPm4/bDu07klIkZYx7sKLgTJk+q9nrNphi7sFpmzfC6wnhOtCPR6moX9vrKxydsmZt9cgBuSBia2j8lOQuW4fB5z4WqWJ77Tt1H5EjT5vr3XU4FH20+0eYQYPZNXm52VxrLvB9embAi+nRLiJ1efhYYT/43T4PaUpLTjNMd+g9dYZAgDJ0SVX05PLYNgf0hrDicYjtZkb1/nYUORVOB1zsV5Vlxd64mw1OyQeTokBZYMIKVwfz5UppkEO0an24PaWXjGBnGwjQuDU+aQcm41Tzj+RpNOs5Jgj4MNTv/O+qBC2nvJ+HzTDKmL3LiAV7NfixyGTkrgW8UwAIlDIoPw9OhoM0cQUt7ngzx0vqevePxkh+zyEVs5vjLNwy/sC/UnJpsSsSAlFZ2knnjVE7Og7MI9qWikoCxEYO0qe0Rs33TTI4BlWyFvy4ts/7qO5lG7mkLjHXKv9351kbCuJfG0L4w/Pe7iuve16Nb4unvEKDxYCa+6CzFAjLIsZa4BdOQRsVxyUXf9P4rokWxV5I9sV4jt+WMARYpD5jvN8S2SOqqH6mgcz6Avyd7Ae/46d8Fwo1fLqt+vaQ8zAN+1W6NxUD3NRJqtbcG74m4zp77sPb+jKwNzpnAEewLzpcefAjyBDM9G0IQkgIucrvTCPUr0dK6NCS1H5VIGRNHT936f5C7AFiKxngxFR+EPtBbl3+5AB6y/yxA6jOwcyP22+d/rGsqnkMfxru4kZXc+SJWu6y5nLjRGUBJDZuECrt9WAGscutosi+ugvzvbZwXU8Ws3Ld2j11PJ2MFiPdItEBwKaK1uaEtnFGebbA+g4v2w79ingJODsBC/sZU9N9nFi37WgPpulaDGOkX/9hIyA61F1KNe0Qj5ACKj+VZUN9BdhIk6DNHWMVTRqAvdbP6aXn5Xe9uIJ2hmLtxltTcZMh/YQxM+FUEN02HPI9R2mkP5qg"},{"id":"159f2ccf-71b7-4d1b-a4c4-c15b23a4126e","repo_id":"1095f823-f6f5-4e66-9aad-9f0b5b6b99d1","name":"API接口设计","description":"api-design","prompt":"为GEO API接口设计创建详细的规范文档。解释RESTful API设计原则和路由组织结构,包括URL命名规范、HTTP方法使用和状态码标准。详细说明API版本控制策略和路由前缀管理。文档化请求和响应数据模型,包括Pydantic模型定义、字段验证和序列化规则。解释错误处理机制,包括异常类型分类、错误响应格式和HTTP状态码映射。说明API文档生成和测试策略。包含认证和授权在API层的实现,包括权限检查和访问控制。提供API使用示例和最佳实践指南。","parent_id":"7c2ac186-ec90-400a-ac1d-b3b7ca2f01d5","order":2,"progress_status":"completed","dependent_files":"backend/app/api/auth.py,backend/app/api/queries.py,backend/app/api/citations.py,backend/app/api/reports.py","gmt_create":"2026-04-22T18:57:02.317509+08:00","gmt_modified":"2026-04-22T19:15:14.078939+08:00","raw_data":"WikiEncrypted:xKp6XrvgQ6yDy/qZb6DBAyzRhY9oY9wND++XWs8abaIu3G2LITgI+Z0UQBWYGKhuTqBsuTOr5OLyKixlekyR1Xfq7usrLYQyUqykz50fvTC/eHiVp24qJjGIE/yM/QXCeZCQ0Io9avqxwyMLsy7oz+0kRVW2WjLzRO6OrvbiUY+8yPMkSPi3UCtyM0GVLTpD/1yhEPFlJimDIuMsn1U/6MxjS0vcd+yEDjCBtrAoR40VIxrMz5v+dKD/pjfzoR1p6GEjf7b6zpzZGPhEtFmhzIahThZIdAaGShFz2YepbNwjns9s+2XJPvMdDYb5mBTcQCjoCHeUfqpQ5eRpjJ47qGFAfFw7lpv7GfOixRgEasUkVhJaX2fS+R0bGg3mmJFfg8tK9XXCm0OvNdgj+aJ6EUKT7GWXDkWLJd4NWEHKvqO9jfXu7YBJxM5tfR1i4e7CPz16fSaCPJtKsI+HgIoTf1JQ+3TrBqGncHko/5j2BznPg08EvIvKnECTrZEH1ATf3+Dpz7cY5x5f+D+oBDxG88V899fkfZSrXbY4YZJnhO691mRZPnKUgr3TsGO4kK0/eZw19HvuCyKxuqWlpHvV2nWGiFCyQpLul9lskV53bxNE6LCdF4LpQgsnxp3NRkXRo9kqVcTFEVZX1D65nknWMQHMOr91wEbFu5y7eHBY/M1mlvT+FpX/uzM6NvEAUkyKHsIpLihbh/obM0dUOwFr/y/hUOLfs5gw3aMosXT7+uwJRXkzxJlNzCyzWUQoMQbw19Mq53uhogOLGeVQNV9+lYZlsF9DEbUg7pWX1HOTZw0qj0G50JKHtiM0mGIwmRxZy7HDNhqrMGXboadds7LRAL8up6y1uZya4V4Y43X61XVoJJrERnU6caJROOJ+2I5yEbNYOvo/g+dDZf6DLrj/5IPInHUF/rwxMPX3V17obui48Yk9OOgLp3s7TEAU+t97lkEPo58h2oDARfsbxrnrVd0I9z2/IJSBouFoAA5+wGUVU3BH0Wdc9bwTyjJg6t+iiz5Z14RRB6hnBI45qD3U9a5fIJ1mWWGl2mBaOfvJck5hTbq7v+Au4iOMprm6m9SIq8C9D5w/PtHslYGeBDUYeIOWciDfxj90/WlNjcdIpE8qX8PqRFKdnwDCBOD0xewCH5Cw+MxNEuc6RRDsFu6vhFjjYe/vtb6bNc674kCJn5eQOGFAo6+v5wfkkZhG1S1q5EY8GJf+H3HgtucPikTjpKAbpBkkiorIBJ4n6Gdi9Jof2lYe1Ina6yJPsnNyd1MyQgdpEg7sStrvevt6IaMoeIe0vQ+WPecPhqsIm9X4wS4nI7Knd7q8WUsBQfphwlTzUb0igehWxKagmMc8N3x64Q==","layer_level":1},{"id":"9cc59a5a-f597-4707-b994-b6c49514d553","repo_id":"1095f823-f6f5-4e66-9aad-9f0b5b6b99d1","name":"页面组件设计","description":"page-components","prompt":"创建页面组件设计的综合文档。详细说明仪表板、查询管理、引用数据、报告导出和设置页面的组件结构和实现。文档化页面布局设计、导航结构和用户体验流程。解释页面级数据获取策略、状态管理和错误边界处理。说明页面间的导航逻辑、路由参数传递和页面生命周期管理。包含页面性能优化、懒加载策略和SEO配置。提供页面组件的开发规范和最佳实践。","parent_id":"d907a8eb-795c-4060-9cdd-50d31cf39be3","order":2,"progress_status":"completed","dependent_files":"frontend/app/(dashboard)/dashboard/page.tsx,frontend/app/(dashboard)/dashboard/queries/page.tsx,frontend/app/(dashboard)/dashboard/citations/page.tsx,frontend/app/(dashboard)/dashboard/reports/page.tsx,frontend/app/(dashboard)/queries/page.tsx,frontend/app/(dashboard)/citations/page.tsx,frontend/app/(dashboard)/reports/page.tsx,frontend/app/(dashboard)/settings/page.tsx,frontend/app/(auth)/login/page.tsx,frontend/app/(auth)/register/page.tsx","gmt_create":"2026-04-22T18:57:04.216604+08:00","gmt_modified":"2026-04-23T15:19:43.818179+08:00","raw_data":"WikiEncrypted:5oI5y1yTFbg14yVSXHYDGFeITEbIkjmdES7qr/P4na8TrPHqKZDCV0OwvONxgczey0MsZEE95T/q1IqTn1MDXDe+zweBCSZSlefgNsHwrtPEnyqFrV2NhO5nKlcD6tYwGnW5Ag8vX/svtjfAjl//gRYZD89hOQGnlYrcSU5a6FC1LQaaD4KqNgrn7yYxshfLveO4k610B0mb5BrOdyTpLLBcuNmEgY9/GKvdoyt0cfpZPwN5J+wPoYjAnGjm9LDIkL9L02r9Lvvq1mhN88A7yKU49c6lU6S75IzcT+OFjTd7OXXastuPBLJRb1A0sFMKjZVshweginUNg6fhc3vFQ08Hthoizv1Pjm4qNnloa7P3w/rnuQrvCJk3Nt1PWn+ouHeenTb9bsV/KwF6BGJ4HGDSDyFcd0YmY4CDfW5aSBFP1QYneJUBxux4dxgw1GbBsa6R2o+cDCB4DqSA14RqNvsI4r16PlAraoYSaQRYj8NQzY5dRbzpEnhmyPsBmgzcW1gLo067XcLiF0DJvlouezCyJW+Y9YA0fmJslQSYvcMhcI8mYdAfGDi1EoXoUiQYMnvlYq8J8ktBwLbIskG3FgeWvmoAFZE08E9APByPtLjDcHHan03Nwy7CPZqb6FtXLeHH6H4TK+WRnxyWWUCCGwQxVYXq0SDxaUvHuhZ4XUr7+Q1U42rlW6cND/0kiOhqZxe5qp/7PBom2IrcPdORh4lVv3RCQrIDCkHcBzCV+1WIwFeaxUaSDNJMmZ500JhDl+ECx+6dgbMAMTRPh+SxHxLd/OJMI9dD9eWQZMj4RwDxTbqlVp8cpoAEGPNvmweo2JApNndlNo1gDMJ++de+I8cKsyCdEsPfQ8ikJHY3R/UaPh/mPp8pQaKIBBP/nvMsT8jYMtdv59ejwQy6+/9dplr/mqdQCkRA4B/maZQ57aFmnsw8HZM9ukvo0Ni9KpUFM7iFAVdZy3NGVf8DX4J0jwAjd643HXH9I6+6dP2Jfs7ezsKz1T5yAHvocFPqxtbC3b6WrwrjPWf32N1a/qM1RiZdPyUNGE5ij+CTm9PUzcQxUcatfkjdDGnwRIAJMmmrtYVTBvCP+xUKuAp2UmXU9xfTYxlU6rdp5LyGQS9dHP0x7KBg+yOWNzECNEzMiCgE7gOqv+X75WA7D/sSBMaO52H6f4qtJovvnkwq4r67A/ByroGz4ctZ/wSVqTHti+gzlXIxgHKWr8VVq1HUFUCSRdZH3Q8PaR08vmQcapIQHpDRW13nUf7saKZh3N6R63lREJu04Ie+fQ8i7VUsNE4QclcrUsdj7eUxv5xtz7xrCEBDZooPT3RW8OM08MJ2Qe9sU6bdCvHTPE21OkEYFD1tWzWH7149QZPhOzkXIQ7qGdKQlmRvyOnd4uL20k58I3p/q9ktqLxBCy5s9Ac6PYODpXPLAelkYzhV3TcJAzxphaGjCmR8goNGJJWsqw3FOOCjGqWliL0JmW23Xo4emXDMUU50N9Ru8dM6NBIs6o8Hy3YcM2dj4t5RwlVejQhCn9gwtm742VYEdCEYKq+8FJtp49Xm01KPOtgTyFN0lF+HOQG6LCrIBY8cXRQtkck1aTvxD+KmKoVxp09guujaDutV+eyhyb5dYSytjq2ptL1FsYHLS14Xa+GW6DEvniGGnCzP2LTzntbqIVzx3J6F7gquTfsiDTTPkIijyYxWvkSseJc=","layer_level":1},{"id":"f70f5d9b-d7c7-4dc6-b36a-5f4508e6acaa","repo_id":"1095f823-f6f5-4e66-9aad-9f0b5b6b99d1","name":"系统架构","description":"system-architecture","prompt":"为GEO项目创建系统架构文档。描述整体的分层架构设计,包括表现层(Next.js前端)、业务逻辑层(FastAPI后端)、数据访问层(SQLAlchemy ORM)和基础设施层(Docker容器)。详细说明核心组件之间的交互关系,如前端通过API与后端通信、后端通过工作器调用AI平台、数据库存储业务数据等。解释数据流向和处理流程,从用户请求到AI平台查询再到结果返回的完整链路。介绍关键的设计模式,如适配器模式用于AI平台集成、依赖注入用于服务管理等。提供系统拓扑图和组件关系图,帮助开发者理解系统的整体结构和各部分职责。","parent_id":"1bb55e12-24c4-42cb-8f59-ddc303460d45","order":2,"progress_status":"completed","dependent_files":"backend/app/main.py,backend/app/database.py,docker-compose.yml,backend/app/workers/scheduler.py","gmt_create":"2026-04-22T18:57:13.329904+08:00","gmt_modified":"2026-04-22T19:15:17.452724+08:00","raw_data":"WikiEncrypted:gWB8HBj+8+/15rQhXgtMjCy7qJxJBEw3w9EAqc5Otte14+SfcEK3DSbmZRhW2TgD6BlsxDXHpLcSijck/Nymh09xxwlFe9hXY5fsIsj1IZW9egIbof/vmRQ/HkxJSvNy7WDeHEuuU7TDae+7kls5UELL0/oUUiCC4fjizzoaOlqMuOvW/DImO8fA0xbQ2wAt6L3bqB1pcGWvnB10d6EKKhQYmUj8xv/2M3cUBtDMkUdyKbAuduBIInt+jZnOGnXKcr1w3W66u8elz0iqgWhMCsMFd54QokMhn1Uyguz3NcIfEVH6IlKil0ufINdb2d/QV+9aukLvJ4Mq4YDlUjQ2iJ8oxAYYUb8eIjBnsLHPfBnMUyXVAo0tbyNB7wUmRb/L1VR7ipOMMKd9mEohzKGpsTxHpM8my7x8Ryc9N1guO/H766qiiNij1HNCu4rWVW12oeTTjAoEKdLzLyn59Fc4QjYVkS/I+r/lwRtMNN0OGjWXGXea+HUaIHwW1088PW3eZj3FlyGEsTiYb6ysJAWanY2qoIhASm31o8s9DekhdxTRbWeBCNzGN2ufTYGM9ygKNDHF5dCbVW0/Vtc6FC/TDiflhIaDY44Gvuu84O4l7SRBl0jKM8uCFHOgx/NzDlnUdNFaSOdjUBxQ7vVyi0Q5X6P4H/ERPzJQvOa0gmXW7S1ry0P4/CRjOCzq0Afw+mAf2j4PHM/4MWFkvrFkycbEkHWoWnPY+DWYI00TVSdTWjj4n4l9wbj1XDhXavLdg00qHVjv0dTq1ghcZKv3C04T5MfvVQjMXCKPQaK0KzwZDfXydWnlyLPgM8t95lTETMkjjEpIMtiv2w1gJda4ChFrJq27oPmVlEoVzGPuuk2B4YN3z6A5y3ehJpejis1/EuBjd0vXHhwghZeUv8mMD4smRPUMA8GcEeKVs9TQgBHqVuuVDdEAQfE7w1ILarmq3trYAuc+LH1KMUyPD0aZEbhKZdMRkFYWLhfyYeuazm9SfO1BqtEuTVoAXdLD86TCQNmxxTZPgU9OB9JluopAMt1oszBwKK/88UqwBqgUZle95RTKVR6QPn7zAGZaDbfsbYvsGUfNBSH08o6nnraxB0Vpj+r6WaoZLCcxhqSWoTp60YlMt7BDsla0Lt8r6D+a89AtCqZOHLJbrEx6T4wsmiykEi1uC/9XhtcsTHuytq/rHeDWR/bTToB+mGjBipoGscvIFMgUJonYCOjLDyBPGpeWispYZV21bIJQtFIYv06NKYU/IV9ZISLel9AttowTEXv/Y/U1xRtmaTp3BgGI4iRdwXYMJICv7Jyr5kYd2CrLJQPzEBdkJi7+q3WNdTCWBPd3B3hL/tTL2lFNDOc1sqMga78PcdWWHQfheORW9OfH3cDRiq85LJziojysfwkQVqHY7niPkDyphAwn9F2xZZl9ZfahAaU07CgK26wyavgkYOAU0dlWI6WrAKE2gQOzOxBL","layer_level":1},{"id":"816a2805-76c9-4f32-a3cf-96428208081e","repo_id":"1095f823-f6f5-4e66-9aad-9f0b5b6b99d1","name":"数据模型","description":"data-models","prompt":"创建GEO项目数据模型文档。详细说明SQLAlchemy ORM模型的实现,包括模型类定义、字段映射和关系配置。文档化每个模型的属性、方法和业务逻辑。解释模型之间的关系映射,包括级联操作和外键约束。说明模型的序列化、反序列化和数据验证机制。包含模型的生命周期管理、事件钩子和自定义行为。提供模型使用示例和最佳实践指南。","parent_id":"243a1a45-d31f-405e-a3b9-694d2fe617d5","order":2,"progress_status":"completed","dependent_files":"backend/app/models/user.py,backend/app/models/query.py,backend/app/models/citation_record.py,backend/app/models/query_task.py,backend/app/models/subscription.py,backend/app/models/__init__.py","gmt_create":"2026-04-22T18:57:14.161024+08:00","gmt_modified":"2026-04-23T15:21:46.785144+08:00","raw_data":"WikiEncrypted:Zb5TNaG1u/mRrgPr+sDyCr47uD+4y/GruMCqF9C9nxStxKZi2OWvk4ViC2NJmWUO/Jxugi7iel+AeINiHAz9c7erlmOh78DEPvZI5zcQaIYzm9l0e6yLGbMS64gON4GYqx4TUizeLGAIntFG405vTATENZMylmwR0jTbWx2uP/KlAPch72o8TGREvPTy7FGikY773VIwNZq0MXKYxjbwvld1ADWYjtxMoKmZ7pixx5LeZM3O+bfisD7UTqLobS2VvR5Ic2ynsAkEEzef+Rh5O85TXra/uluSuAOST9W65TENzfEzwHe+CNAQmUp47/vG6d7I14WPEipc0/aKbh43AhJkclnRjpR0bYFPJrW/HuN6chk1uhxzBK9sKpOUOLZ5MffdIttkTAOz4Ny5MxnUwt0zj4hDsVOevpasy4FZ/3pVx07fb7SlIDC18p+OUYQIk9JqBxZmgeMslhOBSkmRTAwqir6PN/GuLEeeC0mPlAMNhsvDrklfLlJmLY8MuSQHqteqYJryoZ1cp1yeqxATnDfeigUr8eSSaFqZc5S/AlgSIrvr+7XJWk/Oz0wKPLRXNUcG9yDweys2pdDb/hV5hiTmLYjgvYvnDLMMjrFgR6Fogz3U5ItD0xLC3lt09GJfm8jhS9E4AJd36iPN2WMeHsM0ctdvzYB/MKtWIIrBkWuRD7CZeGJepiGO/GJprp9HK9m+APjZQ4oc5d43tgDModdepglAEgNklY7IzUAPW0Qls3DhfUUHq/Zuf5AxAfUAAg1JOW2qEQWV+btkeoRPEiHjZXFDLGsC226d9yUlnYcTkFOeVbL2gomt13MPt6c4EQ3y4BSoG1CYqO0q6IgkX6a4g9QE7OKjdE3RX8rNGixxNJzfx3oeGtcne/lDvhO9/U5SlpNgbkkemAIPu+eZw1zMpknFdRwUdwOwgyVNxR/tt9AEktJ2gcaxRGfG3xTSa0JHoniO9otA8VI+Paw/il8qAI4Z1kf2w+L8LavGt05hchhlzWcrGbBjXF/VkCoYxFvM6JX9FafcLjoT3FtVTSorVysHodJyR1nHB1TL6/SH9v5IZMlZeQ6/Gm87g4SquVaVgvEBMuFPA6c7BBhWUqGw48UIBxfB3Ri4l8HYfRBiqrPSIuldaD+xTVL8F5XsVhczS4JXDnX3RLtvjOuBZRcejVO0ubg+syCfBhf+6CtYOyDTTQDGgwdiNg0MjJnmjy5TMmMdynOGSm2oF6wS+tUuWG8lMMBtredaLHdyVb455+OY2oQ5hJZGo7eyzchNabr+Xous+Ve/4cM2FOoHdQ==","layer_level":1},{"id":"64cbb894-755f-47b5-854e-c26c7821e9b2","repo_id":"1095f823-f6f5-4e66-9aad-9f0b5b6b99d1","name":"文心平台集成","description":"wenxin-platform-integration","prompt":"创建文心平台集成的详细文档。详细说明文心平台适配器的实现,包括API调用封装和HTTP请求处理。文档化请求参数构建,包括关键词处理、请求头设置和认证机制。解释响应解析逻辑,包括JSON数据提取、错误码处理和异常情况处理。说明配置管理机制,包括API密钥管理、请求超时设置和重试配置。提供文心平台API调用的具体示例和错误处理方案。包含安全注意事项和最佳实践建议。","parent_id":"7e66719b-4a8a-484d-889d-10fdc76788bb","order":2,"progress_status":"completed","dependent_files":"backend/app/workers/platforms/wenxin.py","gmt_create":"2026-04-22T18:57:14.59287+08:00","gmt_modified":"2026-04-23T20:31:50.506814+08:00","raw_data":"WikiEncrypted:2Sm2Oxxfu6PsmMr2pZflRJ0uQ9gYQuPnIUHmJotOVM3YPmWq0HSDTQGvIE8WdDGtHlaemWXQzS6Ra6mdo6lkRL4Slh8EfpKUg4wigWPN0r3GaSXHkkAIs0wgET5OjWqYvTL1QooFFzxPhX1ZTdHcTpcp7CVvRNSVGiTu93qzZloeLF1EwOxsLvQ8hFf9SuWGjeOUYDGh7ktNwrMbeUIV32VkQlqsqQ1HqoKoqjAh2d6Xou7+peaCdxzJOhMf14e/vNiC12p6PfM2oyBY8gR9sMPKd1zgEepWsc+ePSazz3RO+zy9fbc5pJTLZdtswhL0xGhZKuYgYlctRId70DLeyiJHlvEQzEE8KB7QJqULfiB4lgMO84A+DhPeslR4F9Edbm+5P11/ycz4y8kzZQwnt5F4iIOC7HOPRSdGTYTxO53cEcqSfBI/wH7enb6Zt49h8mK4UyYW0fUuKBE7dPAjxC6IxbdabWdu8WefhxUR1oFx6BkdGWLLmj9ZOLMReTwnsJdK5xmoA8wQvV8MMlYiCgBuPj7mYce5s5hpglFxtJdEeDq6P2Mtusvj9uegGeFmCJSn1nbBhJr2r+WxLk/WpDO5lwhggW6V/wdvqcmRvaGHCFspVdzbC2qx104c8i+2wum6kMLHVTGAM9kTy4M5vHtvBELFl/qfldVQ8BK9hUvE9jdUbNQkoiBwFpPt2NNFYvz94CAxqbObxiZ7C1VhKWPH2AMX330wwjiHjh0eshve8e+pjBsDeM4/nTh3PH0P2XNUsomNEDxCQpXG7qngeiMXljTWmyGsLk56SzHFqfCgQX8fLlxv3PzSHXpCkAdymDxnJlcuK6WZIMj0AjQydGVSLgItD0boSI0YfvyDXhrO57OoFuwUU5Enq0do/w+quy8Qt0Qc9Q0afMg0GVUksiDfURVugssB75pqSqdNSrJy3wxM+kSBndgaiKYIakZ1idHkzpiGUshjyAr3V8/N1vW7VGyY2wnoquEclltaRAO6V+O8ymywFWL+/RrPEn4DKy8ul6EmHuryCQh1dfEPk5ZAgYg1K9ecbb2dLwTfMgXIhD/ar0ZfRO5OdwADW376","layer_level":1},{"id":"412f8cb5-54c1-4f32-8966-fa0e5e75bbca","repo_id":"1095f823-f6f5-4e66-9aad-9f0b5b6b99d1","name":"性能优化","description":"performance-optimization","prompt":"创建性能优化的详细文档。解释调度系统的性能瓶颈识别和优化策略,包括并发控制、资源管理和内存优化。详细说明异步任务的并发限制、数据库连接池配置和事件循环优化。文档化调度频率调优、批量处理策略和缓存机制。提供性能监控指标、基准测试方法和性能分析工具使用指南。包含实际的性能优化案例、配置参数调整和故障排查技巧。说明如何在高负载情况下保持系统的稳定性和响应性。","parent_id":"7416db23-312f-478d-8883-2fc3c41ac2e8","order":2,"progress_status":"completed","dependent_files":"backend/app/workers/scheduler.py","gmt_create":"2026-04-22T18:57:25.383759+08:00","gmt_modified":"2026-04-22T19:16:37.81704+08:00","raw_data":"WikiEncrypted:9uOBpMbLX4DyZqW4us3Wm3Q7klXxmeD+JMMoGiSO2oNryWBo1gw9kLkawvxQIW9CASZSiyAjiA/zeT5DwD4S8PDqEsVNE73i6DrCAWvPET3MMPQasVfJTaLge2tk6gbYlx3R6JKZcUoi06jS7okoLDzJAFru3F6zguqySliKZSG/00oFVcDHXlZZc0L7hiq11k1jOD8uBl6n35lAvst/AgFv9MUzrhf43XDwtHiMAxjCAkwKnrWOow44Lwzy5fG3nWKZLSHE3/CUmZ17U3GmEqfG43ai1yloAkMou+sTRIk73sRdXPDze0HhNdNfNXTaOHTxW0gT2TwKGHgG9Jt0Y+1qWq4Nxj/oJTP/hztBLy5SEPndXXqeZTkBaesRTr0adQv49fH0QoFV6D6dxlEOodMiFhvvYd1rvR+HwbQbqU3W5UDVnKfPlMXHsz0a9NPu4aGgk5yevh/s0AP/v2R8mgz3N41lETHxk6Q71f35L04S7u7P6MlorIwKzkeijhFf8sPrChMYX7dwf8dWba+Nwm6fgb+9AbSZ4VczhQInnbiv+GUKiFnezNVSHUUXqTCvRIuhF52jqnOqjPei/1oeS7xAMmB67o3v2so8T17xg94F9FoEl2XuuwA+RFDarVZKACDTPxjt70OXdAoxoERTZ3ivU93OANsuuWx1x0HgFdBj0q6seNC8cbySc3ZuQBWGu1YWMmyIYGL5l6L7CNSmkkl9/pkb1TSfkyM+Hk3VLXy8VIvtgHxGX2OU8yX1nX0DCGS9Yt3dK17lAVH2XF2mo39noQPG2nxjOc+lO/O9cL/CC1Bqzd51YLHapcRLPPbuaMT4ljyLvQ3GMvKHB6c0sjdaKjykN96LhXpO5PAqs3N2edkVKVMC6lg5fTBMZi6B8r4rup3M9CPDs4ehmVYTtnZpt5zKxyXP8QfTO1FfDyNQRpbXj8TyLOwwqEFvZPQlV7Iupj3lpi6crQhtpXBtU9M+vjP31rOrdFpBHXCckE4T9QryVWvQuNDjsc1+tYKLgF6S8ixDQFCHEAfzctdMM3iiLCeBy1szBZEZTE+OS0ERSbgqusmZBkz3ouKp6suUgXLJp3Kystu+dAVWhA6BAD2WHT76h+Hbazixj8F2qAoxmUb+P8Z7u0grbWJksg6u","layer_level":1},{"id":"40ac97e8-7ef0-4198-82d7-d2e332be9d34","repo_id":"1095f823-f6f5-4e66-9aad-9f0b5b6b99d1","name":"测试最佳实践","description":"test-best-practices","prompt":"创建GEO项目测试最佳实践的指导文档。详细说明测试代码的编写规范,包括命名约定、测试结构和注释标准。文档化测试覆盖率的要求和测量方法,包括行覆盖率、分支覆盖率和功能覆盖率。说明持续集成配置,包括GitHub Actions或类似CI/CD工具的设置。提供测试调试技巧,包括pytest调试选项、日志配置和错误排查方法。包含测试环境管理、测试数据管理和测试报告生成的实践指南。","parent_id":"fc6f24c3-594e-4153-854f-19250834eeb1","order":2,"progress_status":"completed","dependent_files":"tests/conftest.py,.pytest_cache/,backend/app/config.py","gmt_create":"2026-04-22T18:57:25.616954+08:00","gmt_modified":"2026-04-22T19:17:48.81542+08:00","raw_data":"WikiEncrypted:3lrOgsvw7LaJXRS/Bz00iEsb4RzJUAxxpmqaBblS/51b52WVRQtf4YGBQ9MC2MYcYNyKxRGZljd03HKmm078aoRU+suxjG3HIqwkvM6ruyPxwlLdBEn6ogbrhm8eOKuGWjiEso+PrOqSXW0boT4qGE+/L4MkPiyeOB9YnDB49/ByvDHsjeesTQqGwpa9FmIQtVqpqDZA3Sx+x8TB+MSqT5PMZ4egRgCW1ODcidZrTriWvseFNQDFLzo8g2H/HF5CFLcVsZVK+kWI7b7oWLmNlIKz2SyVJuYqvCblPzw+/773Wv4RVHYdK/pxISCon/L1KjPyfZjddr5sDjJO7rNFbBshPxUIQhtXnnAEqLOpzZwHm2a0bA3vSR42bZZoSAY0v3aZxXQ5IvxNT/aNAmiFzd4SkTlz0okDXnBsArnOUpLLRfjLhxt5ueRUi9Dl2edsdycd6XznT6/oAUHTf05zhhKC6JR1OsKiFQyoo0il7LYjDxXJM0dZycDlENYwZ3Bd/82Qr+7VNmgpLdnB/7z9DPG9iou6TIpztKrdSRYqWBcl75qs2L/R2Sy6MOyfSwALTRUi5udf8sNlsHOk5y2qY0h7vd1GzYwtxKQ63ypJLL/8fAcPKmH3FCwKvrN3zuEu0Meyq+y2v8eYeXNozeOa2zum6fI5sw7hnzX9Jqy7fyQD2yBFqyylQ1ZW3nwFd9liZLnWfm7zbLDlqSgzGYGxvNIe0X2rhwsthMZTLEXOZVDW1/NqHg2E9qXOfg7XhQRHKZz6Wu8eZ6MGyCvq6ft2SJI2vltHD0M4somneHGSMo4jKY8rMeGl7qkW1V7aaurBnh0xp6cOJ25IdbN4VEDYm1Oj5nlM4wnEQzWiVyEqA+3oU2k2k9Plm/xs6g846/lBJxHL9ztsKmm0BnrUFR1ttgTVRAFvHpfkmSgLGGB/9824DJpxXMiWnExCaZzWbFYPhXnDF6Kh3SB6P3NyVwVdC9/pkf4/UQ4Em3rvbVuWICjGSScoDtOu5MrHDaUSbtN/XtqOptA1ApGbnTSKxOm0KAck4ApFPdk6aRLdC4eRf9XWsWUaOFjkqAoU0Kp035pHaGrCrx4KmgoKBNFNbS55CA==","layer_level":1},{"id":"41a414d2-e13a-497c-8a03-212624dbf5fe","repo_id":"1095f823-f6f5-4e66-9aad-9f0b5b6b99d1","name":"引用数据接口","description":"citations-api","prompt":"创建引用数据查询和分析的完整API文档。详细记录引用数据的查询接口、统计分析功能和上下文提取机制。说明引用检测结果的数据结构、置信度评分和品牌识别算法。文档化引用趋势分析、平台对比和竞争品牌识别的API端点。包含数据过滤、排序和分页查询的参数说明。提供引用数据可视化和报告生成功能的接口使用指南。","parent_id":"dd12cc44-0c95-45d5-a726-e7b8bcf2531b","order":2,"progress_status":"completed","dependent_files":"backend/app/api/citations.py,backend/app/schemas/citation.py,backend/app/models/citation_record.py","gmt_create":"2026-04-22T18:57:37.836961+08:00","gmt_modified":"2026-04-22T19:18:18.055339+08:00","raw_data":"WikiEncrypted:qByx+WzXalKNnda2aYUs+Mi+kQm14b3+m7dy1helFRbYWzECOnPEzHl0ufCZlQvKjQqSxHIwqppPXSdvXYc/8Z7buvJqBV/Q/faiP/SBsAH3RrfF2Ppti6QanNvcAtBLcojqJkmfYWFej1OYdagzBcSAu0xIIA7qBG1LwkdNG8crxSwebM8is42SnI+aRvlbF4UdAqHHPdfUvnzs7zIODnildIoR60AvLFeNEWO4prQkFyS16p1YH96SousrFgBu2YZZYrNOOhDXyrRoW3TE6990oaIi3Xe0B7jFtC4pce8JamwzT8B33FAJ6utCOBMUkFKq6l0kD5rN2owZaBtGc4Q66Xcb62y3arqrvxcgE1ox1nAp2D9pNqRy3W1ePW2fWZk4+3co4z2+ANQ1JO8q5eAFI6Q6zG7hM4rvNlL07iD+hZeqd5+vGw0KmjkN4VMqJC5ypFf5UCF4qHgB6TS9ToQUAWk6HWlwBR1DVpCcK1kyGcunn6EiivJyjJLRYUXI66AmajxIzRHtyhxBnA5Q4hZNgr40jHMoUbWHmiQTQr7Ca4/VDS2V5FWlm6K1fN8xWRIUCI3VtH0A/wG+QBnJmF5YeqDZ37Nx9vkiaO+hutXsGHsjwj8+IZO/gpn6UT6QpOGaeqGl37HW+lMZSRUqFFaLg7jxlzSa3IliOyZI7N6xjFFFTrLV1ShVsDcWDg4eXL2IjJ7QfXjmD0vq5mH8mkZK6HbhpNH5kFXDuMYWPIHAXUk39ttNvut9r22RLpkXYWtxE7XoqXW+k+Edmt2eNvZImq/e7mUwa82Cae86WiRtz7B7TJeOf96EvN6EQBg8E8KT5Ckd1exHhFtySkw3tYfChBZfD75zY7tUcZcC+McO1Kf0ORqTZtnNjVnot7wirysiS6WKQ3O2L0CeBUUV7DlmFd8xAgJ8YhtHJKulJ2B0yCCswfb+PR6u9GKFVK1EcspZe5BsT22vlhQyAJxlqiAi9xRk+XaCWoUT5ymT+KMOXdLoB4EvD2ftgXy5GMxZIK2q1QtLAYEu7nOBsq2aNAg9i9IsVJ6OlCN7VMzDinzkoC1IAWKxKE67ZeLq/VfPmCqLKGl0z1JfkfC/kU8KFA==","layer_level":1},{"id":"2f7fa0ab-cd3d-4f45-a1c1-389d5a0c2561","repo_id":"1095f823-f6f5-4e66-9aad-9f0b5b6b99d1","name":"开发工具","description":"development-tools","prompt":"创建GEO项目开发工具使用文档。详细说明IDE配置和推荐插件,包括VS Code配置、Python和TypeScript扩展。文档化调试工具的使用方法,包括断点调试、日志分析和性能分析。说明开发辅助工具,如API测试工具、数据库管理工具和Docker容器管理。提供命令行工具和脚本的使用指南。包含开发环境的优化配置和故障排查方法。","parent_id":"2148d7d6-25c4-497f-8894-c4eb7a0d2bd7","order":2,"progress_status":"completed","dependent_files":"frontend/tsconfig.json,frontend/tailwind.config.ts,backend/requirements.txt,frontend/.eslintrc.json","gmt_create":"2026-04-22T18:57:39.374817+08:00","gmt_modified":"2026-04-22T19:17:43.353691+08:00","raw_data":"WikiEncrypted:F3QgleoEfoy16cQggYe9CzRj7niAsR4WPU/tuSJ2vBrZ49vjzLlsqusYQAR0/FVC/Mfa58hrglY/tUSn8LBYDGZlVr/UyLd9/U09SEPTjzLPzOXWOffceGYhaM8E9Cx6c+FHZRQ0fYUDQXxWM6dQF6WQbUmiZISlUpgtOkT5wX0oc/n1YeDUxEpgiCWnOdIBH6SDoRDdGUFrWdqF66bEdplp0Yy3VYVBKKwUy1XVXtLbdv1T5/0TVJO7EtkHdoheIwKCPIYHsaJqBv4U8cMNegSJ1Ti8bsgUakd6FM/X0ybfTay+IyTIqYXj/dS0tWMm22zjLqYmw59+s8gJ7AlgwXhqYhM5Ycwh/PNrDHHFbgQdt45DjAaMWjrjXrbIvM+kXuSiwxW0dEvQtouckPTVohVcRWEPbg2o02/8Y5DzmxpceOC7KgybfaaCQeJHbg9C91itVc+0NvorhivJt105EYs1ndSOla9hoFppywKIbIM61cvqgHjsJF5DrN1pneGmTtYxijl3J/QpJHn5QuIBR8ugoHdJ3EVjUR38vQReVBeDxI/VMe8k/l3EI/Zk7paXexGeTrJmmnZI1I6WbPN1TPS4nLFZWwkA5ZA7wMkdHiHdnt/FZGccFyq8X9Okog2xv6uqH6Kwz3hseWlrSygNPzDr0cFj2EQqDH7+xZDEkAvTuFLHn+HzUfBv0vfZFa/FRg+5/agC9EcMHM+75jEvtSeeHXHOLpuuFcyOcZ0IQP99QdzSEsLaISCINs5SKkzKAMQnJv4PEDo/vFAKBulCSqjXmLeyhcKmCGqafN7IMWUWF5pmZuXe7wL1F6n+x3+RvScmsWND74hQhn0/Sn8kpFHJ5xV/5t0GDZxWybDFRRuFC8oImKyB+6h8CstsERuFeiIjMv2TS5lz8+eb1/yCUkGO9X5mUpJZXfZ+0vu2SkEN3WR92tM5Di/78rDlulwZ4oykT8NzYMTzpX4WlgUfazNKLyIhSoFZcWUyOFcU8IWCoOdrBFn5CSpe0VXbOlP3pAU1Lz6Y016JUHo1t1YE9xU/m7OTxhMexA8jCoSswgGT+Cjs9u+KP1ji2RSyZHQ6","layer_level":1},{"id":"2713d5c6-c6b0-4a38-83f6-56940c2bf695","repo_id":"1095f823-f6f5-4e66-9aad-9f0b5b6b99d1","name":"监控与日志管理","description":"monitoring-logging","prompt":"创建GEO项目监控与日志管理的完整方案。说明应用健康检查的实现,包括服务可用性监控、响应时间监控和错误率统计。文档化日志收集和管理策略,包括结构化日志格式、日志轮转和存储策略。详细解释错误追踪机制,包括异常捕获、堆栈跟踪和告警通知。提供性能监控指标,包括CPU使用率、内存占用、数据库连接数和API响应时间。说明监控工具的选择和配置,如Prometheus、Grafana或云监控服务。包含日志分析和故障诊断的最佳实践。","parent_id":"803bfef4-3985-477e-a61c-915a246d0061","order":2,"progress_status":"completed","dependent_files":"docker-compose.yml,backend/app/main.py,frontend/app/layout.tsx","gmt_create":"2026-04-22T18:57:40.355514+08:00","gmt_modified":"2026-04-22T19:18:41.773778+08:00","raw_data":"WikiEncrypted:HL3VqGjXq8A3aGeLxAjVPg+lnGgkT5PNghnzp51sgLDjuJwvzPZp6KDp64sXTqk/PvlUYRCEe6pgM8WKdtus6ThN6y8bzS650UmrWXRgW48k0tbm2PEPd8NIqpzEYwRwyuzLECVz8rV+mgvy+OHzvrt+wEQeT7z1uljirnxeLZWJjIrFBr8Q1T8WQ9InM3Ttnvm7OYO+YH2Mqi6IC38bW7w4WGqApS+Byn7/ZrJhR3B/XWh91FPwq0GRUJ9cqrNuIcYtnWAfVIHWOe3iET8Jw+Un5x7ZRepcJlINGIIMBE2hO7UsbC/K3z8rkz7mx6uoPTPpxkKkgoQQ1OAsShE/wpHpRYSOJEnV26GFo4bXBTk6xJYw7daKnJVIYDSqSrtJQI4yPlTR0OtJescXSLobznoVSBo+L+PU/nRvotp5KzX0SUpbkqNzGychqcBuJhpS1eaEP0cTBjvjC4MJ5Lsye51X6aOdYYC7tBWHxtgBO93tkpcIRlHk8Dfmzh8nKcD0rPHYGnaeFpzXgGH7ZfabAwxiMhej6OXWsfnbHGg4gheWhXfokxCMKkFnzrsYcuFtB0BqUeadjP5LArbJJGeyVEZovmPxtzQ5z/ayxJs+oyc0oH2SMXCFtIQv2h03ZSOCkohVRs2oTJnMI2p41dY59B5qiSOp+0qwxTWL9NnpqM2gjlLZhcgwF//R7ag4ndECWejInOcA9Ayvx6cPAuH6uEoFTcUOCLaOZ/u9T8890S5KHS7PcNM8dEewoFviz/mRiernAhd08l7a9lR6zck842Ywi5H8+fuuHyt64Pwco/+52MhD01pkK+HWSR0EqPc8URlkOKjQSW0jd8E/9ow54aZA0+1Vto3d+Lqi/tAOlhRF34rIJgTEN3f/udCEVycON9KNtssYzZVNPdvTkvzPYdUHIcnYmz3jbQhnYnrYvuaWNvO0cPISLZI9szxLP8IhmUc9xT4U3OvoRfFka8TABGicEUAF6vpH6H2rCqnWdBydaTpRTa3VAR7QJ+M0aPlzeKov93eljMa/djYoQo+w8Rm3A9vGmGXJKfWdZobh+fQgc38Z/0yRCHnIPnY8o6CDBfwbANfjDRpjyVkqWq1cuqYNnMul/jpzDS9vMSbMnefISRuF0kH8XS5C7pIB+WFn1vxeYFBYED7ZI4FD9pxxS6GWGcYOXEoFcqtR+lEiMdj0Q09jo1nEuMKJbPQre/RG08O0boFCzF9KOSnS0UA09/82vFQyQZKHNwpz7OkZZa2cX5X1L/pdsDlDRoIdp2lzyAEOidStaIWywEj11EYVNbG7sK562p96Sr15ueIXP0s=","layer_level":1},{"id":"c8a468af-2982-4d9c-82c0-313b5d2ee89c","repo_id":"1095f823-f6f5-4e66-9aad-9f0b5b6b99d1","name":"第三方集成","description":"third-party-integration","prompt":"创建GEO项目第三方集成的详细指南。说明新AI平台接入的完整流程,包括适配器接口实现、平台认证配置和查询逻辑适配。详细介绍新数据库支持的集成方法,包括SQLAlchemy模型扩展、迁移脚本编写和连接配置。文档化新认证方式的集成步骤,包括OAuth提供商配置、JWT令牌处理和权限系统扩展。提供插件系统的使用指南,包括插件注册机制、生命周期管理和错误处理。包含具体的集成示例和常见问题解决方案。","parent_id":"b2bb2e3c-5661-497c-97dd-15bf6ee8b7d4","order":2,"progress_status":"completed","dependent_files":"backend/app/workers/platforms/base.py,backend/app/workers/platforms/kimi.py,backend/app/workers/platforms/wenxin.py,backend/app/services/auth.py","gmt_create":"2026-04-22T18:57:48.68499+08:00","gmt_modified":"2026-04-22T19:19:17.361215+08:00","raw_data":"WikiEncrypted:WxCGFGSl9zR6IDeUdkqKNACFcGLyx5HNn0UQzHtkOJVoVN2BLrMtPbbNkfhYYzEQGaeK3o4fBODff6YTXKxAV6HYhCHjmdXJqBaBsEPBB205lzDAllfBZL4/6ljz+/HZSgaWAxPECD1m2GUFvjlKHTSXEb0x5iVOg9R3VDjYQgKl1SF3S/AuJj7QBbGiwmkyPrqO8+NXDlKH7pI3G6me5ulZrK6M85KSH8nVAnqY/Mvjc6UGQJBwS1QyKJVzzK2JwKGhQSSLemxD887b22bSe7q1IEDRYcpqkbfyICB0zF1Gg1h/cAfQgzjiG0+MQiC5CF3QwkFteFbN4KZDEjCTcbIR+HqI+yCs8Wue/MwdoTYQQKpR9FyClONZn5T/UqHQaVT8SemYF0QC/kawyEZFH5Tkj/6RwS+taTWw1fx2QC69xQlW04ManahzsBDwfz2W4RkufM3ZfW8HAN7SorY7oYr1Vam2p2u/93jzHmi7PO/Y6VphQNACzUlfRYsPALVBkiqpN4TIiicrjOvhgATUxqpku2MrAtbXTkiuiiQBamK/XrF4JNlh+79VGoHKWniah1nvo+dzl7jll4j0woKwWKIzmfPXLS68HekW9h5BH9SUeuyAEW/pvnGAUw8Od3CgsEmap86k42Tg9pRZC/sT9bCWUbjO6ijJ9IPAgWE6bkLCu68L2BD1yKE3gfLg0hJmELn79lHaFCUc5jlRdJ4HEsalAFGS62beLGkude98NvSY5pQoO9jbTj3Da8t6Yj8p97WtE73vmWW9Pu/YyAtxJH7Cdwvv9mbvLYVnLzUWGwsaiaXmDJiqfSHiOrHQNyonHQa8N/LYrbB8qBSUmLyBUhgI1YfYMa+zNfCaeHvRLlmVZpui5MOegWen1Z61WhPc6WoFYHyFAdgS7k21cC9jVay3u87SjSzooFT3MJjN+yMIjrQ5U+tVFbiBQK7IGPLFHRmvFBrBwSFVBI5VnCxn4piz7VBp7mm3e6N3CJUKShQWQT9tmUIRXLmmzsKTit/kRAUrycFjixIK8Hm4kSwtVBREbX3opXE6clXKGVB0bpSDUzB8Ae7wOPE8Gqo/ewy3kh2mdNnvI3+MfOOgPc+Ovqu3KGFBH/MYKl2xIUGdYtEHfHRCIFFVVknX8+Q+tfbkmo/Tw+kJfq67IQO6VT1WjP/q1G3rOhp0Ah5h1wmxVfdIaHSUOT03yQTBm/tqCXlgUW7rZbTc2wF0zdUUWleQoq9pc14c0F2SNFCSaQNLhxvfeC2aH8O9nuZi+kVb+GVV4vWcxcz/7dfTkXpogDwy6uqVHySe/TAn04uWlCabYSrA3ahnl0VpBmalBU1dtaTG5apgcCJ9PULyHWKf+iW0vle9pOVgZQ4oUv0vXxDpZQkO1SOBCfKG20swUEItxbAxIVoMowR52maIRnCKh3g18NF3JUZX2ptDny7A2gmsYWU=","layer_level":1},{"id":"d907a8eb-795c-4060-9cdd-50d31cf39be3","repo_id":"1095f823-f6f5-4e66-9aad-9f0b5b6b99d1","name":"前端系统架构","description":"frontend-architecture","prompt":"创建GEO前端系统的架构文档。详细说明基于Next.js 14的应用架构设计,包括App Router的页面组织、服务器组件和客户端组件的混合使用模式。文档化认证系统的前端实现,包括NextAuth.js集成、会话管理和路由保护机制。解释UI组件库的设计理念、组件复用策略和样式系统配置。说明数据获取策略、状态管理和错误处理机制。包含响应式设计、可访问性支持和性能优化方案。提供前端开发的最佳实践和代码组织规范。","order":3,"progress_status":"completed","dependent_files":"frontend/app/(auth)/forgot-password/page.tsx,frontend/app/(auth)/reset-password/page.tsx,frontend/app/(auth)/verify-email/page.tsx,frontend/app/(dashboard)/dashboard/admin/page.tsx,frontend/app/(dashboard)/dashboard/settings/page.tsx,frontend/lib/api.ts,frontend/lib/auth.ts,frontend/app/layout.tsx,frontend/components/,frontend/next.config.mjs,frontend/tailwind.config.ts","gmt_create":"2026-04-22T18:56:47.082624+08:00","gmt_modified":"2026-04-24T11:01:58.108304+08:00","raw_data":"WikiEncrypted:caZUAHH9Plb/hKq4968GAlxdfXo1OZ/T5bAEX+yDDFnwmkOIiMXkaH0ZIHauIC0wfdpuxtoUKmX43kiFQyTbPAtTiYEiDR6Tc0QitLHu+/t2EuUEwUv7xUQwEV4sW//IvEpbtqaL5pRUagOGJPFa99C4e52Nk9vZW1Kx2qPB4qhq5J3Yu0nD02qlXghyoNL0NJHwuCxv7EahSsg/DYFr7sH0a3S5ETkZqxe96N44pBOsBHzuIrVBbRVxAXK34mDFp06Mg6X+bx/FzcoakGVIQ2IA1/sQmnUSpwDxGqn3UvGx6xVk7KBPYjKthY6SgyELy3XXUvLqYYrMzXJIpLCJenAAXTvXsseT+uR3pZTNb8c8t6DMq8wmc/nSYKx0/o0eWgxwGCW7U/hzreWW7EG1vT6Wvls/+9iCH022pB7CS06DX6cdGv+wSYp0wvWU6q7c+JXjhvI3Tz9BouXfgOipLBXfzo1GPVD211oTxUEOthWdIsJ/xrK33RKfN0edxP363h7CV1jAUHsZPO0hLP6ZZRpC7kDuFps/PTY5k+15rMjKsA3p4d2gO79r8IJ+nN0PDwK0ncShwqlQ74k0G1vS9tFBnH9lhq/1UdozkYQsNxDa5+YN28fNiYVXPNLS7cqj61w7y6GbW1rL7QuJy4pTuPCl1lJrFqDN0xi2a3KM4l00HZ9qbBQPyC2zF3cSmK/bbd8R4rrwbXzSJKOHyb/7Uhx0mbARihsrOJ9s68hspwmIvznUBYnF+y0y27DfTemQ5/UpNlT/WzU1zwIk8xA0KX1bdYS+fdH/CRZH7axSnG0WcjwloudpfvLbXWzUGypiGhAvZSnTEATuWW/rp86QszDvxQXgB7N1OSJFUuOUE6vxX1nwr/YGFsk75EmWWRT/5l3BoNW5rsNqeaOLPCUIe7RFj4U2hiWsrhjyXXyMpm/dpjmAIgPnYGeaPQ6+3ndGg1ooLn2zeijt4pY+yaM0JWp5giDt8jr7YhAcLRW7ojqK8IAhk51K/khU5x0HFI/rUYBS3k7j6V0pkUQYziBrVpYavetotm9w6yw1tQrB4G9Pkh4/NGGjdJ9ZtPdoAhxwq/vFKRixUOxtOzPW+gjiBJx5aBFLlGh4OeNikZu8dkvi4o72oyn86HfoxqjayhfyKFjnAhLuk7u4H7UAw5+imyWFIuT10HE4ku7WESF+jU2I9KtomZm4+j88sEG1m/c2PAvqMWR/TbzgZdogHbPk99qTZ9/Gxa8sAEqijUgFeXZHhD6fT+Owl9unUBxIhv0T7zY7KJFcowSL9eOirUOnlOuZcqFUdFT1pE9B9MpnS+aAo4H68NaI+k/JsFne7qyToLEjzezrMiWggu4qPvxqH/1YvhZKbm99SeiGQ/fSWhVKN3kcpby3wdWau5I3Eg0DApusN4Z+nnZY3kwY8CbBAHbv6lx5XVCfA2tw9MHDPpiVaxmBdA5fWmu4HSnt0v0Vrb5r3R/ZVl9ERMQUne52UjUl3II1fMML4ZrZzOexAOnQ1WJ+zHyQjGkcBkU6xS0R8uOhu5xA3obBmqzzET2RslAFXre9XhksI9E/qhzxB5abhiKMV8vs5G8GNJ1rQ0nQq0M/BbL6Rz6is7oJWTf8pL91hYykA0bUMRKq60t6umP9XKaKzF31+7PIs18PRJQ8Rzji9jXk2GJ9TpT4sc9ty9XTBQg6Je/vhkN2SlkNbxA0RoiWRMA5QxA4fnjOxWOFdP7X8ugdY1SIyFHmAR+TiEiGbH6qjNqMQD+PTmmi+1s="},{"id":"9eee7fab-6cd9-4ef3-9415-2f8137f1d199","repo_id":"1095f823-f6f5-4e66-9aad-9f0b5b6b99d1","name":"数据模型设计","description":"data-models","prompt":"为GEO数据模型创建全面的设计文档。详细解释SQLAlchemy ORM模型定义,包括类结构设计、字段类型选择和关系映射。文档化用户模型(User),包括用户属性、权限字段和关联关系。说明查询模型(Query)的设计,包括查询参数、执行状态和时间戳字段。解释引用记录模型(CitationRecord),包括品牌信息、置信度评分和上下文数据。详细描述查询任务模型(QueryTask),包括调度状态、执行历史和错误信息。包含订阅模型(Subscription)的设计和用途。提供模型间关系图、索引策略和性能优化建议。说明数据验证规则和业务约束。","parent_id":"7c2ac186-ec90-400a-ac1d-b3b7ca2f01d5","order":3,"progress_status":"completed","dependent_files":"backend/app/models/user.py,backend/app/models/query.py,backend/app/models/citation_record.py,backend/app/models/query_task.py,backend/app/models/subscription.py","gmt_create":"2026-04-22T18:57:02.317816+08:00","gmt_modified":"2026-04-22T19:19:19.281909+08:00","raw_data":"WikiEncrypted:klcgW2PbPxJambbKMzvFtzxL0nPpsuPMPxr5hj83lS7k/WfePQWgQNKbEysjyVqFS8lXlJL069Py2sSf8yXxHJzOE+5qAqcKClz711a5h2iXkF0al3mIdEvPGsZtmu7Tz91D+nYN6P20/dGDD6jbfsmIRXLEv3fpccmaTd5XoNj9Y/QT7a0xg+LkG6A8bzQONV8mQsFJZMj512PXdrzG8bSiiAdWa7PEbotJVKJRklAdLNFr4FCsLXLsdS/G2RlAo97zi5J4mpx26Q7SGM1kx14TxsQYatCIUYP+iZ14NDPPPp8tQ+HGPLEonVbYiRiktzJo8Iaqbcsh59qHBoGZBndXEwalDBXzD3sIbYrhxlOU509HDe43hiq+M5eC2SEeTfGdYZ412t/aAJFPEfq3dRl0wa6Oiw4t4rox0s/f+rCg9Sr5yX/vsXrADGwowbhqt/EdTudfsdha7MXN3Kn9e9TckQ+HOqdgqW3+RnY3B08ijVPZchn/Y7XZvx8GujUHSuM3x7EDAXegqkPwkfR+hl4yb4BuuY5AC17g3hvn9yDvBN3m/Ky7mJ4Q9qvXfFaUqDE/FxwPWjugAnVOgAmWns1elVLUS/2nol2BUAuyt1w821y7+N79TkQ07amTWILYvO7I/5v6hStaHk5+ftwpaWSLofuk3Nwbuab8ULq6lj/Tz3uWkEg5/nIIYGVDSN2y9JKgkNta0J9Y4C25DpKnPb2HPfbnD/315IEyxKddS9DpOHC92uT3Ad5v/X0LgVsefqUUep4D2mVUeevDE2o9NuUqYyWYu16AL2UaQOWH86Q97+Accmt37g5580pjdVyzcgVL6Lat1P4W42Nk0vOIncIdM8Bt+iWUIOjmIWDK6nUytRrluJ6RAGeewol6Eb8eMy65WkJ8SsDWFj936G3imq6uoKEsmn9kHznKIfsvt/p4IAv+IbkliuuV7/VNQdN4jgfgKyRp8b4aQd35Qrv1ypuTdf2HQS3w/t3nb8hBriaZZc8a93LekZYaGpvrws/aq3ESXMU+csJKfWhEGhH4VT4cjy6j+jHgihUuUWhO1X/Kpm8iseqreG85CZeU9woTd/nPIayXO14kUEfNVL1ih3p7GtsFGDYpr4EcPU7JpPp61gLhfdpHydKVDLW4eaaCuTR4REP2Vs2BxiwN8GCpJcCbpPeF52n9qB1DE3uIVBITabqC0jiIHeVfb8caysKpddelqqLNn4GGL7BeUFq4RKhlVTmCGuBRWABBDEhDRHXsScje6Av8bOxE/QFVlZmFE8EkDM/WhG9hB5BQ+8u4pKPxsL3/n7xyMyrBnO2n+nTEGscgwlEnpxknYpBTrtZQgU5YB8KRGG+VnvSlbM95vPmdiXS5y7JM9ftKUbdxgnxOVrM2ydbK+5IGvaNB27szvHBbvqtxiY8lXfLRhMYcQEIcD0AM4Xl1qH90xIrHF3lHogdPgwXR/UWGRDWDXKVUEXGRLQHTlRTCJ2oRBGig4FvIztUbBVqouwtJBqoGXoMET7JbuNkxdHs7pfsL8sV5FksVAyNxvV7rRG5QAMaIvUMdDT+XAhtcrNagCHcb53sPxuz9ldlj9adP1H+FxOw7","layer_level":1},{"id":"d9e45b2a-6443-4a9b-8ed3-4c3c04773772","repo_id":"1095f823-f6f5-4e66-9aad-9f0b5b6b99d1","name":"UI组件库","description":"ui-component-library","prompt":"创建UI组件库的详细文档。说明基于Radix UI的组件设计原则、可访问性和一致性保证。文档化基础UI组件的功能特性、属性配置和使用示例。解释组件的样式定制、主题支持和响应式行为。说明组件组合模式、状态管理和事件处理机制。包含组件的无障碍支持、键盘导航和屏幕阅读器兼容性。提供组件使用规范、最佳实践和自定义扩展指南。","parent_id":"d907a8eb-795c-4060-9cdd-50d31cf39be3","order":3,"progress_status":"completed","dependent_files":"frontend/components/ui/button.tsx,frontend/components/ui/input.tsx,frontend/components/ui/select.tsx,frontend/components/ui/dialog.tsx,frontend/components/ui/table.tsx,frontend/components/ui/card.tsx,frontend/components/ui/tabs.tsx,frontend/components/ui/dropdown-menu.tsx","gmt_create":"2026-04-22T18:57:04.216865+08:00","gmt_modified":"2026-04-23T15:22:23.573963+08:00","raw_data":"WikiEncrypted:mOhGqVhKXtp0S+QeVzok74WypWJ7klGHRH+KdUSnimLTYfyBjBDRPAzXT+gcOXfQVvcrNlnW0hq9eH7zZFCqkZsBgmYKEU+paWYmItwEmPFSm8j97/vwvs9ugP1aTV0WKgu1SgAg9UjbHTpC/aH+MMWl8IEcuuqWfI5XbGaUR87WXcEDmdrb3wUoUJRDu/cGjCf/fvmakwSGbuyVnUxAKC0b89qWigFSx7MqlY8I3hXqAtSNiskE28duoh2j488f5d1qN4KsTvxvRe26wRYqlD4qzi7WQGBZQUoeoyVRA8PrJFhxeH6clcVYO0kStx160hPPrlpF93ul/lDmdVwrTZfpWh5RRY5u02+lOo2Vcl73yz1ixYzt/OXYaenA0jUTFVdPJ2OcTZGDQV7xMOPFPX3iFNKxuHY9aks8ARFEUs2BtyH+KlyKfPdKqDAlklqIVzP4MH2E6uDcvYMSORu7S1T+53+R9br9Cfu1PSZkuVdmHNqUuKSLA7pMI1QiVYXtwk2GYmRGYUH7geeQddC61wxpCG1rXcVzBMSS8LxtR3SSj/9VQ0v2YyrqKzRh44BKjm+ojKbz8rNcf69UZ5Fu4dU5kGqXy/XWbFbSmoUmrWXnZ2zWPhMIgHAIsTe/iX6JC5Q3L70XVbXk4S/ffk/sKKtdV7XrQVmVPhSquUc7x1RcfMyLVgxyoFEOwwk9LfQIPE9n16lNCvDWX3UuK2TDcqDbwJQ/FMmjaZDilRQFs+8MA5I/UUtC5CyzoOiLRXvPqQQiqXjBs6jefxc0cpGAJwUkaISOvQum6WtKWK3y1CphRMH2hkB4bF7NgyOm8z/0JXMSpcPR8nMUY4M8pW9MZYQEL76sWcQAD/oiWlgAUccgiRPnCiU0Xz7/MplIj0jTRwXXzc8arUGle1DmiJFEVmztGZOQsIGDqSwKGG5XHEdLyKe2hWHqBGRWkqZrsBqS8KrFUWk5lefvdDZvi8ci+S4wdZQX8IDx0siYw5cfdMlilWuaptf6qf/qEVaIO5DX+MMGPmGBz7jnyaQfo2QWlpybbe/uLTvhZTe75uY9Revd+DPo+zgmDUmGj4hSliiZx0smUxDq2wMZmKLx3x7N8m1jdGgqT+LVQAhdUcmE1Qx3W7e51K9wB4PN3L8k8bDewzE25kuU6a7QpDLdn5lSa8n0E0Yug9cp3wgllhZVFVmyjVr/oC3c0I5z3elvtrYub9jPeRtR4AmW7w2RPcUt/8f7j8aMH/1lUBQk+GL6OhXAEnzmav2Q2smdsQqWS4cVj/FV1lrfoV+peL4fo5CxYMv/ZJSvbJaFSpBOPzf09qJBxUptVeosUyAUDv7YsJdUo02ZE8B3ZXZGcpKGKSRiBeLQKjuqkck1rBeJK4PnEEXZ5vtz2ONe8tddj5qna0a3","layer_level":1},{"id":"178b681f-d013-44b7-aef8-dee7ca8c22a9","repo_id":"1095f823-f6f5-4e66-9aad-9f0b5b6b99d1","name":"核心功能","description":"core-features","prompt":"为GEO项目创建核心功能概览文档。详细介绍GEO平台的主要功能模块,包括用户认证与权限管理、智能查询任务管理、品牌引用检测引擎、多AI平台数据集成、数据分析与可视化、报告导出等。解释每个功能模块的核心价值和使用场景,如查询任务的定时执行、引用检测的置信度评分、趋势图表的数据可视化等。说明功能模块之间的协作关系和数据流转。提供典型使用流程和操作示例,帮助用户快速理解如何使用各项功能。面向不同角色用户提供功能介绍,如管理员的系统管理、研究人员的查询分析等。","parent_id":"1bb55e12-24c4-42cb-8f59-ddc303460d45","order":3,"progress_status":"completed","dependent_files":"backend/app/api/queries.py,backend/app/api/citations.py,backend/app/workers/citation_engine.py,frontend/app/(dashboard)/dashboard/page.tsx","gmt_create":"2026-04-22T18:57:13.330097+08:00","gmt_modified":"2026-04-22T19:20:37.649775+08:00","raw_data":"WikiEncrypted:luoNp8LvFa7zGThvIT9T4gfD6KbzJyTAydbcRfVv0b4BXBAF9G/unmbHb0x4cm5f5JJeO16NqGe5C5EiggSB7moDpXZy5USSfpQ0OUKuil4F/RTioDPMtSUudIqxEjBd5ipsj1OYjuKwvCZDE5FVOSWKxyx9ABPAcj2ixa32ZPlrgZPKHD2EYG0qdFR1nrcOheMbdmmK/1DGPMM99yCcIRnhsKb5QMmqrZbFGo/SPCSXi/Ykr/zd7+VtVKLrPmeZHpaF0yafvwU0Sk0I8ne8YmfwUGC+cOZoDCI+UsE8IukB5R7bnolQRLXvVZdnHXG3b2DA0X4DxManWdKVUyJxI0KTcxcdI8DrpJB05TyoF/regQH6cLt9xm5r6oC5exXEvwhmfMoZVqZ2jp/7LVs83k3vKksFtqXA19YrxFliE+fS/7xxjhqFqC8gfV8eLWpHyIKgVobBj98SpzX6tRTXknjSX2kDpfKG1ECCqYBxGl+EcY3ofgMb9dgxDxdOaB1JU4iP8j0YMHe0vASK6GweE5UjId3SQsH4Qeng09dL1TY2uNr/6ZVhraG1xTMRFHeZNdCZtAWnUddTk6fiDJmF3zxyL7Wvgdc5vmSbfg0rFxTdxZEiGFHJoEQatTaUtv+NOJGQtnOuYzrhs6G59N5Bu3hnsT2Umn6jFryaWwluQaphllqim1VwA12J3iVLQZFZEVBhalhF5GQBDtl4zt6GFlKucztFwPZXIZTYJavPQP2xpvFDInehpuQcHilp3yHcA8+ucs0ani/GPME+nWnxyEDPhfu/FHkheybrXg084bLJG7E+o9XWBTlbISgl/1CuVNeWNj2ph9KIS+TAcq3NucrKast8dNM3bayIymMoemWvEcvuUjoRlABuJKAeAUQ2q5dFWVAZFvlK8de95GljY869ODymzBXnPjMOSCmHwZ51ImNKeIgHybmDkzT72uKyQcN8nty9DJKz0k6Kq5kib65fLCcoAEe/w3d/WVpmBqxU1Uh3yD+z1nEm++DCQTmK1jmwwLT9krps27ULzjOvLuJz2cJnCpSFeB2fBYxH5Wjbp3UZFwDWJWan/9xl9bIREOaZ7mmAz3b7YgA+106K4LV/Y4vBjtitwaM52IcTqvh0m2OKpQSYopXYE7hsG/CXE/MACxmx37ut0KpTFaM7N2GYOE8Z9hIsM53ueQhPuRvk2Hb3E8xbBs3mMtYON2ubkxuPdcQJmCKSHZTgVqD7NVWXIyDL87TjV3YTbdGq6KlIptH7MxMpAvL03xq0ApGXUlF7gt9qwpHG/tuVSmjPBAUAEXRZ3bC+1E0tvaaIPWgP63+hhl5S7970UrDCXrtzeN3l8mbplzeN8BTm9brd+gziF3NKUZgA2yM/OiHjy2jbsu2NmXU8Q3f57Q1MnJglrwSgciwgohkp5Q5XIBOCwyJuIcAxO6LJWzaXB+WOrB+xk7v3h8qxpMdfHMOLFTY8M5Rf6MoGtJPOtFpc1+0Cjg==","layer_level":1},{"id":"f210509a-2381-46fe-8c22-0ed768e6ca70","repo_id":"1095f823-f6f5-4e66-9aad-9f0b5b6b99d1","name":"数据库迁移","description":"database-migration","prompt":"创建GEO项目数据库迁移文档。详细说明Alembic迁移框架的配置和使用,包括迁移脚本的生成、版本管理和数据库升级策略。文档化初始迁移脚本的实现,包括表创建、索引建立和约束添加。解释迁移命令的使用方法,如upgrade、downgrade和autogenerate功能。说明迁移过程中的数据保护、回滚机制和版本控制。包含生产环境迁移的最佳实践和风险控制措施。","parent_id":"243a1a45-d31f-405e-a3b9-694d2fe617d5","order":3,"progress_status":"completed","dependent_files":"backend/alembic/,backend/alembic.ini,backend/alembic/versions/488d0bd5ab01_initial_migration.py","gmt_create":"2026-04-22T18:57:14.161329+08:00","gmt_modified":"2026-04-22T19:20:15.066432+08:00","raw_data":"WikiEncrypted:veTYwq2y4io5qXerCTrkkH9ryxDJ0NroguMukGrnBDccbI7FhPTNCbxlVVf68ZQ7vvUzAxXQ43tY1R33KAEW91uvBjnohUVl7Q+D/Ap3SUnHDpWQWBM8qdBbgPmANzeAhinu9R6LqaM1BaUXXk7OeSNamXR7nrg52Su/KTt/eSPCFzeoio7iY3vORVHeaHpWs3y+ipYf26jobCXk1cLVjF9BgaKQ8UIEk4JobP8DZM0dSC9SqfPLDnh2e6k9t39q8JNd3MaV90E75j7KuZKZZJemgTfwdUTe5c8Bn5uNxCf3TK5iuMxVxJXD1PTU+9tadOMcx1qXGJ3cb3nuH7g/03z2UrmsQfIRf/cZLGBqAdGIWhQpJph2OlUELy5WTq8t4R//c0t+IUVTKieR2A1E1U7uGurYXL5ymVtiLnckbHeLMEoxbJYmh7d4xn4mWF5hcIhAZoHvjqh+shIGNwCfXJQGswpnJNML0vWzQNhsJ1YcTUnHC0P8Y6nj9VmXMpUYuJLWuIRuqBS5lkS7ChcQMXO4wfad4N4RMHX9jLYytT/wOoty1KlEalUzriEMahdDn7h2DsLzOJL35SLwpVZ4NVnInvcE89IzYO4wyJIz4NdOfBYseoIv20Qv7qO8B7xhRtTudUyynfaz1jmkT8F9UgZFcdBJqg08MH6VdQSdrlKqUGSGsFAxtB9OC7yv25xznJq5n5SUwpLmFNbQ1evjOqqsogzLg8vClnH52aVuE6TfQWggj1wDjxG7jUj/W7mHSOsDI6AhtMWrP+2OVg2Wx9Bab3iLivdVe+mg93LH2FvF3a8iAdcDRseeNZj2UeJJfYnmzpsRpm+CeJo8Te1ab8UeOeGebDsnVTTILuEg+qe85nTuG8+PmgOs+n4r+781gUSlyoOO2Cde7QwES0X+oENbplkkSZM719jK09dcnbG27vqoeh8rTrzO9ygM48IjQzZWUJCnAIP4Y7VVrcTBiyrZhRLikSrVvSCvWU3K7KW18pnOJh1narIx0e6w+bctledpWsEGZJ9fwk/ae5P5ZvACxfM/2LOdDFqshVbr6grRIeSNNf+tl5nDunlOTUEY8fGNt4lsr35UgKwPwO9TxACZGCsd25DuEtHum9DU/GYli2+rgNaOokcc0Xtw/R8OuN2pa7ohiD6ACjJ82m0kKC0mBBymsNAdo3bDXv3yoyI=","layer_level":1},{"id":"aad61788-1dc9-4682-b743-47188d7aecb6","repo_id":"1095f823-f6f5-4e66-9aad-9f0b5b6b99d1","name":"引用检测算法","description":"citation-detection-algorithm","prompt":"创建引用检测算法的详细文档。详细解释引用检测引擎的核心算法实现,包括BrandMatcher品牌匹配策略和CompetitorDetector竞争品牌识别机制。文档化置信度评分系统的计算方法,包括关键词匹配权重、上下文相关性评估和结果排序规则。说明引用上下文提取技术,包括文本片段截取、语义分析和相关性判断。解释算法优化策略,包括性能提升技术和准确性改进方法。提供算法调优指南和实际应用场景示例。","parent_id":"7e66719b-4a8a-484d-889d-10fdc76788bb","order":3,"progress_status":"completed","dependent_files":"backend/app/workers/citation_engine.py","gmt_create":"2026-04-22T18:57:14.593043+08:00","gmt_modified":"2026-04-22T19:21:33.125768+08:00","raw_data":"WikiEncrypted:qByx+WzXalKNnda2aYUs+KheFrHbXoPYZO+RPCaekyWxjKaQvamRZeOm1WgroVS/6iDS9zNWvth+zIYrS27hz/NZLNtt2wOUw9iZG139S+OGMVcZB6KjsnlgG3fSA05ZEdrwDfB531npeEpy2DodlOkcXOSBrgCwkOsVexBDKcWLpthBpfOCieqWsVnTfFkeXE8VvMLROtjojlr+6So18lnYzdEekhgU4Az61W3QEoXC7l+uPBNpRUYZY9z5nLzihT1o3I2bDEfAACTaa8pU8izFltiEd4qID4z3TepI7IuVr7oTmPOaD4MzHULu/4RaMo7/7c9Ql0uGsFrxRb3QFXiiH6QZN++2X9EDTl4UjA5k2E+OTcO2UOZm2dV7vi51lNAZwI50VwaIjtaC4LrPpX7fklk3hQ1qbw4w0FPjYlraJyO5MLseOOQXmURr5BCOhJcWoJmwJadtfh8EAO/9XRK9CRjr2wpAuL9kan2Vkympa3UCszQwVox0j4IkjJNYlG/7UEt2ixgTU4pQi+CAJy+8tZGJxY1gk1MCILniaClaQQImJhi6TfYfWSVywTFVltVcxPd7kMwK116KQmtoiqet/DRC4rzqeEbb6w8I7HZu+VwSR1TXSN8teXJTRMAFEgg9vh+vAOconlX3LzcgvFPohvC+teXJqTADp9XvqcC6Xh41G53xVAvDteT9pJCZHMZsfgh0bErBFzrvnwSObsmJEkvWnlDRN5tdVsRIk9LGcvaflUwWHmIof5SJj7wO9fSm2BN0gW+VA9nbQxyuHt8YqvNR5D0WUpbY1/UDw6IDhAxuTh/6yyVt0HqirNDXslgDardkMaphsQs4xh1fShhK/PcG4y+xX5VsoXIm/tjfGAEXYIeGOHtVuldTaCxG32uSnuT/aFQh7H6df2Hhb7c576oZ6QbZ4HyiG+Qa9iZr6deKWdGhtuuUzj3FBAXLtLont+yuXSCWi/AWM5MOMVyScyci2LKIjH5haWCCgS4nm9tLvifzUgmdeycw/Dhve3nrgdkgO+bIRuUQxXRIxZRUdxEr0DKIa2tEKVeorc5pIX9m1bErC53nDhnrLBj4/ZQjHp33XcgGQ+4jAfmWK/AN+P/SNbyF/K6O0qlKXPqQk/w5bOZWCtcIjrDLhyxZce/pYHOGotrSGaKOK56cJA==","layer_level":1},{"id":"ac0658da-7670-4e41-9e57-02d9d0d50680","repo_id":"1095f823-f6f5-4e66-9aad-9f0b5b6b99d1","name":"报告导出接口","description":"reports-api","prompt":"创建报告导出系统的详细API文档。记录CSV格式数据导出的完整流程和参数配置。说明报告生成的触发机制、数据筛选条件和输出格式选项。文档化批量导出、定时导出和手动导出的不同模式。包含导出进度监控、错误处理和文件下载功能。提供报告模板定制、数据格式转换和性能优化的使用指南。","parent_id":"dd12cc44-0c95-45d5-a726-e7b8bcf2531b","order":3,"progress_status":"completed","dependent_files":"backend/app/api/reports.py","gmt_create":"2026-04-22T18:57:37.837258+08:00","gmt_modified":"2026-04-22T19:21:24.246329+08:00","raw_data":"WikiEncrypted:ncgUburcUGIQoFYRn+jCfmA+PbmqRFCE8+U3jYVfh2v8RywptgptFxq5lhwZlmleN1AF4e6ox3Zeepx7xqM72ox5n+mZFIvpPAV03iG0mffmuvwBURuWuzG3zvukYRbxLcpPqC6v5q4GXBz/rMTsxy+K9HHfwtlYbga6fioIcJrpFn0O0GBCxvse/EcV3UFGM+LHRaRVZqk3N16dHYVOsIgwcqfz+E1qQhOc9tSvlN8OuLBl1z0ukshjGXiX/lY4xzl1WSrFXAIsz6WAKGLPlkePgVZg61CHsK9/iXfq1HIs4Mv/RYwTtuMKkyWX9+6LO+AwRjoeHSIVgJsaSwMBS+MqugD6JwGdLsb5/QGcsDSVaN1zVhbjD1WnJ01uK+tBWcULWdYGAkgo7z9A/YQJsV8PUfXfdZnfuydZi59mopfaX1AYtCXeceMgKnzkAIwjWUl72+Pwtvdke5upjMFgEvoy5NrCoYwpZJBePLoPrgu0kURoy/vWGZ77WhOuGQs2/cn/pk4vCFes3r34gglCIF0tHwwh9piyAabHid5VZ3EIuOlhBHL4O9L6zlAgO0opbo23bXt7kIR8MIjEqb8b3SoUIGY7PElOLeOIwJiz1LzOnccT84S/avMIJR7fgzi/me7mJyD+8h7mZ3GY/AsbFhi2oh6bcqc7U1UcO40wTqx7myMlwrMOo9zRr+aAfR/lqH6YwFw89kkxflBfKQ8X7UwPI/vFeOnYkPFjj7XzgHUtclkOUbxztMSSnhxiBMGzbNf6/hnfqT9O5xO2ZF4ufJ0t2Ci/vTK7mqMRvj6sBAzXnGCig4zpnDKbOrVJnB53v6AnqjeFLvqUCGI5Aj9nn+g4LDMtPzzDhfm/HtoxVJjclFmC6FQSLvHlh2FILylIvVxzY7rDDuK3bTiuZFz9Hw==","layer_level":1},{"id":"7cb1d921-44ed-4e22-8bf9-baba7ff8b7c7","repo_id":"1095f823-f6f5-4e66-9aad-9f0b5b6b99d1","name":"新功能开发","description":"feature-development","prompt":"创建GEO项目新功能开发指导文档。详细说明功能模块设计原则,包括模块划分、接口定义和依赖管理。文档化API开发流程,包括路由设计、请求响应处理和错误处理。说明前端页面开发规范,包括页面组织、组件设计和状态管理。提供数据库模型设计指导,包括表结构设计、关系映射和索引策略。包含测试驱动开发(TDD)的最佳实践和单元测试编写指南。","parent_id":"2148d7d6-25c4-497f-8894-c4eb7a0d2bd7","order":3,"progress_status":"completed","dependent_files":"backend/app/api/__init__.py,backend/app/models/__init__.py,frontend/app/(dashboard)/layout.tsx,tests/conftest.py","gmt_create":"2026-04-22T18:57:39.375268+08:00","gmt_modified":"2026-04-22T19:21:46.916012+08:00","raw_data":"WikiEncrypted:5RlNBsIi2/3o8ATlHuzaYHdvL7yJfTe6YPwFoSkO/GgZuVYfBQkVBn+1kZzpIDRMGSVFSuoDX3pyax2f9XzBxnZshkSCM7o1L+HEG+sgCns6EUSGCL3KfZi4emTF8vVzG/3m0dhVOWuoQXf3TK1+2Aa07EE3HJ86aWB+sLQgQyR8gNqS+MsRztbE2Am9O9oDis36vAh+tGO64VIsi4ulSBpI8D3+dRXcAI8RsujwrZpp57UaW+DyGg8Jkp+WqqjfbgBGcdkno2KfRFyWKqKLB1g6yKJCePYymOK9DHhXbdBC9mKr7EWc8T394B1klPsqywIZs0i3xy/Pr5FAuzklEn/8jhNkYpmgcVvXaZ43AUVTklSOgSC0cwvfeHd91QuNSlfIbIs9Xh0pfhmz3XAts9WErkdoph3YSvrNDMuXK9CMNhlu9XMkMCQcV7ac8ax69JKW4uVaVHcjbU7PbzOeQ7vSALRtfK0zhIWlbQ3za72G9FvDogDqrLfOBzEXA/cyXMdpeZP/ICE7OsSCRM/i/yU/K2YUAWnRJczSn3cX/8lGIDywmB0jU+IL4l7eteQD1Ea3elS3ne3N6t0WqX/T4jybDWQQZqz0+gOrFuJUKTQ18p+2afWRjcYZnqg0EMvXxpXaT5fmpQAxMA89c70flWUr6l+ZNckhODBS1Uj27vp+ECTFfhbNt2CmqrDWIfdobRz1gXYkZI6LR+xgc598+CJDjc6zizQcychGbsbPqawU+CCQfSVqPCknZLlSyJrMF+FMoe4jm8fpOVyOOfqGN3N04W6++aIiU3eZIMB0F/1pjONP/d5egIYaJhs0Zo+ciWBBR+Me05kVd2tyIK0ldRH8iELZu4XmfrNdcGPMTZsENU4lZZiJxIXbeoKUQF7KbjsDcLTmuXfl4jcPFk48k+LwUEE2fyaAoG6SFrEaDZiZ/yR292cbQegdgcOrF+/QZDnMqVS6yFRaljF5C5+ce7VNxUOs5dzK46Z/0xD4kXHkT4QT5/727yUeQ8KmshnsLpu0XgxdbjIAKa0UpiByR2sen9DI8GblyzqpH/4jM/yMtc2COW+MLDnPw7xho10kjKNljBjsabSa5q/wLnYGofR/pA1CmnrwERR7Cytik91YmtyTb1D+rjh+uOjSVOB5NqjX7dqhFcV0CLE3KfUAkA==","layer_level":1},{"id":"c45e66b9-1ca0-41da-a796-6b98f394faa1","repo_id":"1095f823-f6f5-4e66-9aad-9f0b5b6b99d1","name":"运维最佳实践","description":"maintenance-operations","prompt":"创建GEO项目运维最佳实践指南。详细说明日常运维任务,包括定期备份策略、数据库维护和系统更新流程。文档化安全运维实践,包括漏洞扫描、安全补丁管理和访问审计。提供故障恢复流程,包括灾难恢复计划、数据恢复和系统回滚策略。说明容量规划和扩容策略,包括水平扩展和垂直扩展的决策因素。包含运维自动化脚本和CI/CD流水线配置。提供运维团队的职责分工和应急响应流程。包含成本优化建议和资源利用率监控方法。","parent_id":"803bfef4-3985-477e-a61c-915a246d0061","order":3,"progress_status":"completed","dependent_files":"docker-compose.yml,backend/requirements.txt,frontend/package.json","gmt_create":"2026-04-22T18:57:40.355828+08:00","gmt_modified":"2026-04-22T19:22:39.446821+08:00","raw_data":"WikiEncrypted:AymRokkaRBrPd1uk5umiX/dhQHTPPm6nf5mmDPb1IMODwfEt6djM0VBnDWaMwjVsVSuT1AHD1pfVap7WBute6Wsiarqj6ltamY09KvCs0YHxEqOor+0AYSzm2Aa31Dwx0HGTr+fgwTnE6RMJGGceRIs4cV8RBM7Bs4/C9pv4JQQe1wx9fBauJxXtVZgZmkTwsQz1zMKUv/my9/bZ9Q05aHGQVWSs0vQA7fX+eO9Ugt8ztv2KzLkMHjTPQwDUKBMhAsMb47fa/gUJRb4vX0XaRC/0NRwbOvV9kGE8ZhfJSMzck20DTmUNjRs+txGlORGu4UWZsefqLmppB1YdHehQUnSp53vMgJwj0a9BHe2ZU8oB3BBo+Ky3c3OR4uaa4rfHtatz+jzKcC5vq+Oa2OkwFMyKF/rHCf5c9kOD3c9bg/wQwxJpIov1DkWxrbmp2EHHUtHsb07ASQhGLV3SX7POirp4b3urFGRk2MwXKxT5U/gA8wytKMJhKBFtElvFBq2i7nSPeaH2xj0DS3o9rwbrhRJQvLfp/3z63umdp/84RCiI8SwdYgPx4ACqLY3QKXNo0LIi6rsgWkaf5Suyks+dimQcPtAllHZGQA/gcWYidV5oQCnhHJ/meCiKRy7Xb4GttMbIeOA7UNNRQ9IFS7wyprb/n36lYgLOcuQ5Nugly0pl7iFTkl4qWn4pZ+zE4TR9CK3+3oihqJMUeVFdsWHHzgVsh4Vy/4MCPUipHMfRj4T7BabCmkvaTRaf6oRiYEXPGH1mUXCLnQuty4lKx7e8LxdqWP6gciPJOcuRMBYoeBHqUKw/JNmAzN8FuypXsdUryS7GDozcilxOcRE9j3D0JEW+8ONdKF5sp2JAXYX0mhqtfB+RscbqU7E352fF8vZAqHdS0XHCguOUcPuOk1PjzrKK0PJcxoWJPrW1H76CpfhWX9kC1CX6ji8+oMevPaHlwwFIAPnELyRyWOvaAia+6TeiAn8YTup3BXf//p7UweBdBGz//qMDvWoMqMf67cKrFP45gozQjSEYzm8AQ8g0Rqx6ctmJotfnBMpbUoG/k/Br9U3yCwUW5C4ELNIkZ8HMTq1vu6GKzheTjgM5lsZSBhR9qgPwf7cYyU47KLN2oWaoSG9Ke9U5fc+blB461oN7Tb9p1M9jYYAi3IfY13WbWR9kQ09yQOl6zNP4E/TOZ/WG1O8YhDVo6O9b5nQ7Txck2F7a8+Oqzy404YpIRpdXWJvx2sNjxCQXQVXqKKTnxP5lOsLb4vYZqXeHpIw8VawHDzn9M5zowBo/3M96UZSy84F3QEP3JU1nF98Rqg82vqB50gv8dY6wl5RPTzKd+Fi2","layer_level":1},{"id":"243a1a45-d31f-405e-a3b9-694d2fe617d5","repo_id":"1095f823-f6f5-4e66-9aad-9f0b5b6b99d1","name":"数据库设计","description":"database-design","prompt":"创建GEO项目的数据库设计文档。详细描述基于PostgreSQL的关系型数据库架构,包括表结构设计、实体关系映射和索引策略。文档化SQLAlchemy ORM模型的实现,包括模型定义、关系配置和查询优化。说明数据库迁移管理、版本控制和部署策略。解释数据完整性约束、事务处理和并发控制机制。包含性能优化方案、查询分析和缓存策略。提供数据备份、恢复和维护的最佳实践。","order":4,"progress_status":"completed","dependent_files":"backend/alembic/versions/c3d5e7f9ab12_add_user_management_fields.py,backend/app/models/user.py,backend/alembic/versions/b2c4d6e8fa10_add_confidence_match_type_to_citation_records.py,backend/app/models/citation_record.py,backend/app/models/,backend/alembic/,backend/alembic.ini,backend/app/database.py","gmt_create":"2026-04-22T18:56:47.082886+08:00","gmt_modified":"2026-04-24T10:59:38.979085+08:00","raw_data":"WikiEncrypted:Zb5TNaG1u/mRrgPr+sDyCqW7t7yX8M+Ha+5tSgGfMUOChQVv8Rc8RrXA+lpSqmcv/gkaDzP81agTYjHvX46erg7PWFncGZ1TOXKqQP7QcGfliH5ak9tnEamgIuPyt7GD7X/ktYWZNBw0rkib1u8riLrYblHZPip1fA5nWgiNve9JAWR8A5LSXb1/MkK85pGhIT0hbxgGSC6PkPVIRisy/D8xDYn6rcwMs8isn1Q0j0kMKiUwDu5D73M4vDsI4y/ZxAWd6WYEFgkqYOoeV5KveiHRDQ1BWHqQDFCNR/UWM2lxXlj/whmN8VaSk9Ye/JHiiNYbkSuvcUcO2YiOPia8H44APQcfRpcKUh9SBToYsFV8Fu3Sz330VdqGSjrk4hlw+DAQy0ANf9SxneL1SSgh7UEQb3mCmwf4ol0W2OOEKOPj3+srwFiYVbOmSKLMUezu4sRx8BecH0DQJj+w6u0jFTCVwHJcsSZXsJ6ftM8zeW4Gb62L/9E3eGd5gznXE4MrfDGV0U+SHOXTHVLHjIiiDCFL5EKuriwMozfYOYiXp1kgte0NR3DLzOoxAk9NQViv6c9ckVvlxSytmvKn7bbuCU9m9ZkZwa/+maXmuIEHvYRmeD0JBzVAPZtqvr9Q0yjLJDSWQ4z/0GDbEER7obUFIM+E+N8/yfexWunfYvUfL0mWXCcTd9J82nMzWM+Wgy2xUD086AHFPLXHH07CREuqOjUxZsvdQDG1grk7lObH8izbD8w2Zxaayy9lIwqJBEPCqaRdF14OuD+avHkK3Llo+7V1HYjHFYLa73gJvxSO79Ww/qvzvLWynNytnZEci9NCrzeZdZ+0TKrk+9i9L/5cU33O7IFTcVDDUQKU/ZCbP4D+ICH+K0AmOTiZaS343BGpR6hGlcrljtEjmFjbtENwJ6Dj67zXXVvUFWRlWwnk1ueUMxE7uNPzkF8R6XnOJQZxjv1ZhoYTrCdpi1eofq2LSlp9DGEyVNgS2UvYp3ZKdt2nOQi+NGHfy4nEMXUm2HiIciMAWERbdIZFH7igmgNwCQvvOKfnwxsB9aToLxzFTklkYilSbsBc+lBi3dbwXpvyfvcETruYMAK6xpcl1vfnkx0UVzmWg5ScYPlMwAyAkThsdYB31r9HWM0W2zlrsan196zyJUp/Ga7/dTuGbTW9g8RIVFlbvyO2+q1QBoBXM4lBDOEZPZPxpCubiCkbvshTREXUBElpgabfbBe5oufQCqpMvpO22rjfEwEMp4XMcih8I7Me+WEJuO55dx7hs54WCDmTwEa9xLmb0hXAKG1v6asdjp08CZo4Jbvnp/BrARqvkJ04j9cZpY5ybL5tKEtCbWWnIkSTC14or1XZksHDT3UZgFTpCOoAIbC8wOL00HXgI+rkt7UFfccjoV/i+y2xOlkwPUt3/LqSnsYRftUSpnJIj/vsMl8Gt25CJqSzSyvVGY59wIhWaWWzMldJK0IvOnc8JOGNTLwumjK5BG1apFMsHQ5IsoaZlJ8jed5aM7jLsu4v7wCNEpb1mh2FX9ntfdmHo4fqvttaKBlZqzO6/2JSNVRJz7KekqHYM0Z5QJ4="},{"id":"05214c1a-d804-4f3c-9048-20ba4de3be0f","repo_id":"1095f823-f6f5-4e66-9aad-9f0b5b6b99d1","name":"引用检测引擎","description":"citation-engine","prompt":"为GEO引用检测引擎创建详细的技术文档。深入解释引用检测算法的实现原理,包括文本预处理、品牌识别和上下文分析。详细说明BrandMatcher类的设计和实现,包括品牌匹配策略、正则表达式规则和模糊匹配算法。文档化CompetitorDetector的竞争品牌识别机制,包括竞争关系定义、相似度计算和过滤规则。解释置信度评分系统,包括评分算法、阈值设置和结果排序。说明异步处理机制和并发控制策略。包含错误处理、日志记录和性能监控。提供算法优化建议和自定义扩展指南。详细描述与AI平台的集成接口和数据流转过程。","parent_id":"7c2ac186-ec90-400a-ac1d-b3b7ca2f01d5","order":4,"progress_status":"completed","dependent_files":"backend/app/workers/citation_engine.py,backend/app/services/citation.py","gmt_create":"2026-04-22T18:57:02.318113+08:00","gmt_modified":"2026-04-23T20:33:37.372717+08:00","raw_data":"WikiEncrypted:5AsZyvafBXiUtsQ5ntd2xSs3ILjH2jK3KRqQeqYdLK3xV++pdLq+4satUA35s4AktJpvtIlBIE91BpoSSxdMIJzlzjcEII8kW/R0EytB/VdNUbQKg1RverfqOp1bPEWLBmM0oXoe7+3qkzPC2Mf1ooT1qY+Wnye4CAfG78TD/q0AMQdykzQydTep7eypfUng3BGXStCcjUkwnitXy9jgftpC0/tEyMhSJIRwfEyHMC8pCZ3uBu05K/kbWJMAVzeN+RbpjqQl/AMRIDLTMg6TBQrvrH5uB7kEmNLnso0k4IwbKjYBfsoAT1f/RhrPR6uEpuyMZCI7868kZ98SRi4JNdev+YK7Ek74Y4AW+/z0d/9fpp2VQ3lDuYYADB2ihvzHrK09yCDPV5DfYbOE+YmgfP/W+1ZayVWcVf5jjw/kQ0+wXXpByj9Bf0MvKeJO8OmWNbW11YKf1Zhr9O9ssfAGhQ61tEWdGwr2vpPRZecLhmP/3vAso3UexUhMF+42ursRQIxusBVhGnBG3395aphiScvidcQ3AWZDt7qWaigup/9WWvvwKEk+gWaJBnO8dib6i/mBuB+XC33fXmvrkk6ESP9afV1Ag2XJnNosrx5wpwCnwwVeYm1+mo2FyjpkCyIesooi9FNVuMYQUiR7o2ORBBXyp8r8l4pab4wvhmQ5F/kvyrDq2IUoSgVwCe1WVokpscxHDzemlRiqQALcb9vHFogShoOIw4NQd8JE6Ciw2NTcEbgq5i0hiaO1w/VhbUyxoqA105/8aSzbEwdAcuMG9ciHKwbMkoyR0UaMKUZLJy6VO02JFFpRtlh3OD72t3VNoDS4lWyWJe4G6NccX+XAohN1rsZU+ROCL8Y63mODms+oacpzuNvCQC0f91XvoRbftpDjven11QkJUdRxC+QBid+X3RB5HjEUZI6amQjQESEX2z28T4td0i5MNlp7IQfJjM00IuaVZmFavGuu+RJfvR7n78hqrcdjNGJE2t3TTozXstxH3HLmjwKzaA1DGdcvjISEAlWpSDq1Z+8ExFSDbevtUFgnb30/rRPe8E/+VsDMR1FqWh+HovxPuOeMpbUi9ijTGv8ynn1DWdoSvT0kIfsNMhReSibvIGRprPdW7oZEiI5y1SQYXU4kMBOpPdNuCyaPRA/3Mx5z0o+l66QqRA2tAMfS5JvFR53tL+M8eEjH5xvgW0VmBTv2+9VGk9aRLHXSHANLk78McmWR3P66okFWF0OhqkaLPqj1lqn8SMDBv297qL/7vaz/5ZMq+1nKCtq/I4rY9/FziNmhBZi9jtXj+845Jyt4Qi7hprnHQYqmX7caLgy44MGdtGDcZ/fxMNY3A2QbuIeQRT767L2gpffBKmqQxLcfEBwxKol5OB8/jdyvVTpGLMdROGD3baQASEk3njuah/PfjZcfuARA6oVvcpj+RhM9HEGKondRlyBHvD2f5p7nK7WyubfWPvcD/iKl45JOn7zLMHQYvIYu5w==","layer_level":1},{"id":"bfca5ffe-8905-4ac2-a0a3-8e4dc43533b1","repo_id":"1095f823-f6f5-4e66-9aad-9f0b5b6b99d1","name":"数据可视化","description":"data-visualization","prompt":"创建数据可视化的详细实现文档。说明基于Recharts的图表组件设计和数据绑定机制。文档化趋势图表和平台对比图表的实现原理、数据格式和配置选项。解释图表的交互功能、动画效果和响应式适配。说明数据预处理、格式转换和实时更新机制。包含图表的主题定制、样式配置和可访问性支持。提供图表组件的使用示例、性能优化和调试方法。","parent_id":"d907a8eb-795c-4060-9cdd-50d31cf39be3","order":4,"progress_status":"completed","dependent_files":"frontend/components/charts/trend-chart.tsx,frontend/components/charts/platform-chart.tsx","gmt_create":"2026-04-22T18:57:04.217105+08:00","gmt_modified":"2026-04-22T19:23:03.405364+08:00","raw_data":"WikiEncrypted:LlssVZ/E1BSUywfa50FLlWyGoIcJJpOig8KP9B9gWWZZI8ePi8CsG3BxaOR4OzxCxm2XiNUDCA5f2LMwvnigr2SlxVBiSNHUI0lCgSHHEunmkPytqBjFiqGB9yeyKz3O1rSdq/m6COB07RDEp6Tymfd/Ich7hNqr0ALiJKFBMfTRXbiXa3naRlzgzc5/DA1h/zbAk9yl3yaR4bB4p7xAmyNn8C67e2gxrbHOKN7NK15dfXoIag0XHJMVwFE6SysJ+lA7fykhvt72SHx+Qz58/QamURb9OcCEnEtIYqW1uga1vc2HXP+r8Ud+tutKATUxPch908D2Dm70HjZTkDqV0y1RwdTE86O++EPgx5Sx24CmB2Y9KEs2TsxQBSxas2iX7ajhgIL9xFqjJIMVJWfRNeL/ql2x/OsrzEXUWybjh//bQHE/MIs2lMcn3jl6uggDT3q//Zf/jugKwK1117XAp1NDps6xhJqmTf0/J+uk2DjJwURNZ+f/hL4XNyCoPSOpjPZMIk+ikrqwiBBFy1t5dz/fksmYdzw5H1wSGwFPks461EvwT7SUd3qHg+HDEWwCrMRQLhaalcb+5T4rD4Gg7Aa0Y5Q7v043Oz/0rnmFckpB7QJrcI4yUtnbNxu/HuY+NFZLqpJUrNC6MhZKZ1Nf8HjXwbb7FvRLPTJk/0J2UGgZIuFkHqA398GnAHSj3OegnBaKM+qHr8cVs0wfQ/uFwwYzgoBd9gSGURpkSSDhsDUj2XJMeQPghyYg+au4UrCpUVHdYOyliR8OyttchGTRgDox14AD6X6BPxBueyw2Yb6orKjSBwNfDa9SZQK8dW9S0BehKqK7QLDHIzpglx66chB/QwWwaryM7BrEciDg6cdFeFQSmV+EgDmEePwse6hlzNdSXObTbNXLDwYhtifAxjK0xxhVUCtc7HVAFKLROk36HCFnlzxLpVmtppYzoprXfyXDe6BHU55d+PSdjtYyR7k/tigqJv5jX3TTrH6McF+/v+eR2ZtsTDIjWz+prq1cMVTVPgIB9WoT0+dXP1fMoZ52xLzWjSkgrQ7djAo7jyy1G9plvOx0bdGh5lBGOz+/zY7MTLVaKx8eK6kKS+juFkRK2kCuesUi79TGLidetA+vkruZiHzNPBJWntDodb79","layer_level":1},{"id":"b32b024e-2d06-45c8-94c2-a07fd25ab9b3","repo_id":"1095f823-f6f5-4e66-9aad-9f0b5b6b99d1","name":"快速开始","description":"quick-start","prompt":"为GEO项目创建快速开始指南。提供完整的环境搭建步骤,包括Python 3.9+、Node.js、Docker等前置条件的安装和配置。详细说明项目克隆、依赖安装、数据库初始化、环境变量配置等关键步骤。提供docker-compose一键启动的完整流程,包括容器编排、服务启动顺序、端口映射等。说明首次运行后的基本操作,如用户注册、创建查询任务、查看结果等。提供常见问题的解决方案和故障排除提示。确保新用户能够在最短时间内成功运行项目并体验核心功能。包含具体的命令行示例和预期输出结果。","parent_id":"1bb55e12-24c4-42cb-8f59-ddc303460d45","order":4,"progress_status":"completed","dependent_files":"docker-compose.yml,backend/requirements.txt,frontend/package.json,.env.example","gmt_create":"2026-04-22T18:57:13.330281+08:00","gmt_modified":"2026-04-22T19:23:49.7972+08:00","raw_data":"WikiEncrypted:1aHEw3M2aeluf1++NE1n1HTCzLNrSYNKzc2IVp06RQtbuAYcMEXChpU7tJYS1f3O0opR6Xc/vB+l5keQe8PgCR2ncFv/1Td0hCZ2YAOzrKcU9vT19aDXTs2wVsNg8N0rDLvVcTazfsrfReCkGbF3t4KIDlALR7E9k/sBc8Aux87FRnIqhElZnBvZS4Wsv6VYjg+rG70cB28ZbZapx09FwTbE2gyXj7Ck6qNOm9h31VGeQcyIEPfTlQzKWWghd2UuAwraAXbHFeTBwAzBOPZrVi2iMW5N0fiPvrofJe2RpvtWwEWsHguXuXUfXywdpjyOFbnrTokbwQiiwiHpgbktPSypaW3QvBywnGVAjxPBIfRlzbrxj8jlb7w8YznQPbWcNRuYRt3TVMBHR1Ix8UjdR2JwWu4yZQUrLOP4XJ1OVoFdLu5sT3ug3YetVAWSBGUiyUEIQ1U7QoHxxE03qI1ZmrGvC069cAhyU3YQYL0g+PfXWWo86/F20gUXppepBbqg0yRPlCX5asdDuL0vX+i9vl/JI2++deWQKu7cSc8+5tRNcN2AF8Klslhvy5KUEZpxqPaEhxXek/RE8thYcMjT02y2lWMR/WID/CEUm0DZjOC2fQE7kYjogUTC8OhNTBXocpLyn1sbyngxfQ3KsE6+Ysl41LroJ5F7SN8+p5pueRZgBbM32odMU1Dil6T14I/HwltMjiGAjHurPSB8hcX7nNvkuZnVTE2YMjB8ZEhhf76D9Pp1naI3P2d3j0DprvLXRiuPSfO9NBTu6LwZKuMaI2MBEDI2zoV182wdrC1T6AxOiHNcJXYiaF+ZOpMA0vabvcycoioAE6VOZ0mBQ9ZPVSZDf/Dw+VTsC8U1qruh1IAQVYCHsnjY9etX9sTaj6Izd3VrvgQkqP5vAteSDZTy1FOTlTi3X6RzcurXdR3833HqpXa/a0ot8JiRdmjIG0ydOuPYeZPs+Jb0FMN85H71mBziu41udCrikCTPBRTVz6VCG9yBdOgeW4s/iNhPqWCnDibKpfJy1GfSyZ7Jja1d4K91Y+IHVrJxB0+TZPezxY/htgMg4W7MtRoOOPc0eRqst/S2zmEgxMMpU4dfaQIne5zGbUEPNb24qp3HsO9v2un6P17rFQV86RwmPCnyngxtddo0vUNesY0s594GhsGEquA9XlaYa4/KNM14pVDEm4ReIC1JvvqdiQdUAPv3nMXASqe3FxbJmsi93mpWhKWx2q4W+P3ZivXtxhQ5OB4Rs2uXmArlB3MNPKk8TL7wHCUAsFUcCGoPtT2+ov9ntDTLyjKsb0YUGjYUqAceHGdvLCM=","layer_level":1},{"id":"15d6170d-716c-4d2a-833d-81211a59027c","repo_id":"1095f823-f6f5-4e66-9aad-9f0b5b6b99d1","name":"平台适配器扩展指南","description":"platform-adapter-extension","prompt":"创建平台适配器扩展指南的详细文档。提供新AI平台接入的完整流程和步骤说明,包括继承BasePlatformAdapter基类、实现必需方法和配置平台参数。详细说明不同类型平台的适配策略,包括基于浏览器的平台和基于API的平台的不同实现方式。提供代码模板和最佳实践示例,包括错误处理、资源管理和性能优化。解释平台适配器的测试方法和验证标准。包含常见问题排查和解决方案指南。","parent_id":"7e66719b-4a8a-484d-889d-10fdc76788bb","order":4,"progress_status":"completed","dependent_files":"backend/app/workers/platforms/base.py,backend/app/workers/platforms/kimi.py,backend/app/workers/platforms/wenxin.py","gmt_create":"2026-04-22T18:57:14.593273+08:00","gmt_modified":"2026-04-22T19:25:18.719953+08:00","raw_data":"WikiEncrypted:Djug3Ni1DAZ8Du2qShzHYuqLmnJOyyKhsCPSfayzAMoLf9J+rFBy0LePWIX3b5/HwiLgJX57X2JBlObsW70y9DLEgX5HDr3AAeBC0dRNACFssPk0GwpdFdJeFwRtoB01ZTdr+IpYAK2YG8gaEA/2ysFJOZzxpGWgTq/Xz+KO29a2kcDgYhZKt55uqT/Mo/5Dzr6AN+qXdLL5xSqrvCkpmhYMFmzgIBOUjJM1mUISEtf/X+gK0L0wXSj/tCJnDQtGJqbFK24HEYyVnkon1GdnIvb+Vptmby7Qg9iNT/xb8JEVTTLM92335BfpTwTp+D4fNkMNyZgXv/XW6K5J/dLRulOCKwxJxPROAyvyEc5xLI8vh6BGP2+b8TgKAKILZTXg3SemKVhGrB3MqY5+V6whOOMT57LHnuwJUEMNMJsswFiLp6UbAlqwiICRF/Jnb+bvCliw4xXvKC6xfAJDQ5qAtcTCAm0uGslNVB5T07pzLFy5EaJS00hqRmvac/P3e8UyL84KjzdngtT3yZ95yCL30Ad9SpGXt76JgCgVJoPFcnPYlJZiXneeB39wFX7rogSSye9XkcBSqEt2ZITemhNHF6LmqSUdnA3rX85S/zDmRiN2NjS1Zjvgc63JjB4B8gQhw3rDllzHDLPBIO3PNInvmVsx5zHOjAMZmyIaoVRtB9BQQnUdHn1WvHdRXmZfs3eVA7jNhDQmTtBzdGtJ31XIHAVkP5ul/NXNBKUytIXDS5hE2s/ZR6j60eIWBlCNxNIlj+42vefIOU+e5kJufMVcBv4aXyQHpunohRHMUYteEC24NO2CW1FNZJlH9BEyf8RKg1/0hDEmySMxcj/S/pXTp5i8nevE+JleHdj3zeyWlGqJsJa7arZV/Kj7qPJYtN4VHoDGp7MFHgKvq6W26lje9EuwJEikt3hqjinocemgMjzEx+PMVPovHIBXyCfuSOtygo59bhUm0pvPgdMmml9UgZeVV1GMzDT//kfmf33ZL+aXTl+zEmnw5fZYwccKfmY6Q++ZjfSQLB9eV6u79F0yq3zh7zGb4RqRR5ZeL2vQaNsL3wyqgNppyJMYSC6gX+ce1aAimwDx4Lr/EnY474W0FXvid1Xc6Bg6KdPrwnKJJpi18zMOmECI68RvMpwmM+92oe/m3dj6YGItooug3uasMy8SPsvLi1RV2F0CQD5CqYs=","layer_level":1},{"id":"7e66719b-4a8a-484d-889d-10fdc76788bb","repo_id":"1095f823-f6f5-4e66-9aad-9f0b5b6b99d1","name":"AI平台集成","description":"ai-platform-integration","prompt":"创建AI平台集成的详细文档。解释适配器架构设计,包括BasePlatformAdapter抽象基类的实现和扩展机制。详细说明Kimi平台的浏览器自动化集成,包括Playwright配置、页面交互逻辑和错误重试机制。文档化文心平台的API集成实现,包括请求封装、响应解析和配置管理。说明引用检测引擎的工作原理,包括品牌匹配策略、竞争品牌识别和置信度评分机制。提供新AI平台接入的扩展指南和最佳实践。","order":5,"progress_status":"completed","dependent_files":"backend/app/workers/platforms/tongyi.py,backend/app/workers/platforms/doubao.py,backend/app/workers/platforms/qingyan.py,backend/app/workers/platforms/tiangong.py,backend/app/workers/platforms/xinghuo.py,backend/app/workers/platforms/search_engine.py,backend/app/workers/platforms/base.py,backend/app/workers/platforms/kimi.py,backend/app/workers/platforms/wenxin.py,backend/app/workers/citation_engine.py","gmt_create":"2026-04-22T18:56:47.083138+08:00","gmt_modified":"2026-04-23T20:31:36.620063+08:00","raw_data":"WikiEncrypted:wpnkiTiqqfzSOLf9jfRAk0Q6rmj54V4PX4cfdCN1v7vUnV27EqfgO0UCzli2MtUnJ51CgpvG/pn/E3FsASRJX83W5OtoHXDNZ4j26fcGYWMK9zRC5hi8J/dMZoaQzJzzsT8qKvXJnD4D7Bjp4ZqFEme7Smze8hNvF5wytAi0n14HrcR90C0v1NYf6UWM/I1F5Nqo0+3N+pfMTr9vJAv1ZqDstNHpvNePzJyNYVmfwpIE7rezCdxATA1CVuPpwaFA5xsmJ+vkqC26R1ecrjj4kaKngH6RRRDgQhhQ6aRB3vt5nqJTkK/GUHcF5T1XjKaL+a/sKF+40wgULRooeO7uAuC8Zv55v4uHR206FqyBmzQ2n2oL7aEvTlkvDbpN4K4o46nOw6eAh4cC2u+M/6UyRJ/vHl8dGbnZjB21BICs+8mtyY9X8HX95c3q/eXaBcsnPvE/pQo/8Z6wSj7GzmxfueajIQAC0N3PypyM475sPJJAQYRRBk4tB8BeeHAheffcSAiLI86gW5xCar2+kHIHTkRg3pcdkaw1EkhKeqcQw6ew0Z83+q31K2+D+G5Dp7k0yg57Yy+wQYoQpi482aVJTCvTl4DM1GdhaLBYK1/O9ybs6CsHHuhAMGPJeOCtMI8ehbz37vhncd/r5KFUwVm+e8+iVqLPjIA7A6uUm8oef8IZswkzAIcBjZTd0HQmfhdO7p2GfuJKvyAMwWchCj+pryelFxsQ1XiY4QCO1g7ORVxu6x+4/k2PNCOhk6gEBxOjJQzXNM+PjMhiZHJslw5eSbtEAXm+1F5jyhyYY972p9cQQS3iRFts9dQK7qtI8+zm8/UMh2S3rh9y089hgBEUB71Gg5cUb7gaiI0gJYh5HrUXvqt3g6H5zQQs+913IJZ7giMElPAP2Qjbk7hKfAuLl+gm7pG21vEiGBgdafi0W/SeGMfEfargk5rycBiAux4yqzolMzt6ZY1G6bSEdxhBwAL7IPHlaguENQ7PIDWDT1mlEboyeR60e3xngdX3d6vQeuuV5+OWjDecOeZTiBxvDIPgHbMXc4UEzS0YKWD8ao1VsXgT+V+KP4QhvazHdx0dXUhAJlmfrXF13WzadCYVAAlfJ5iNGkT47I5Z7NwqDIF2jO1g5hfgR/LgTwdLyuzF0R79gBMRfYZusLAkvoVjfKdTxjMIrkuXKoXEbgtcZDj99mrJe5eVpoCtl/nL+FDv5U8e1VDikgYWnXY62y5ZnhnOcvlUDLD2mJVlDEbnDBkMkFc2WW6TRTZQAb1pLCRTbsDr+kQD5BLd0YLql1xTFN8IsAKgz3fkhafmSS0hAEBsKC2Ntov35ZpS0cXcMYb1oGIIGPVAMq4Uk43QUUSLac4pkX/xpRkDI/wPdmaebMbCDw83xHKBNY4h9STf5rFicv01m7HLBHfkB3BTFwYsKGhOqxnJPkYnD0ZSz+ia3lw0eV2RoqWx6ITdxEvkaka3zPxNSnqrnTBwjBwTbLz5tXrCmK8Fn5Dd5N9xlYM6+6iveOBt9he/WYkedO6pClHq3NK1RmLgTQWpL532vkJNeI9p8YUcv89XqnwXSi1YhPMe1PKgYTDGoZvsPk66RDWaeTNkfhF/vcZudTvgMmZzQVRfZ/clH6wRHfgZzl1X4HZ6WJ7PKSSwwUBw/jkvMZ2rixaio10OXuEfyOqYqV4EoQ/upbXArnmYKjEbhcULNFk="},{"id":"850fc702-3eb6-45b4-acd2-ae87fec1f4f1","repo_id":"1095f823-f6f5-4e66-9aad-9f0b5b6b99d1","name":"工作器系统","description":"worker-system","prompt":"为GEO工作器系统创建全面的架构文档。详细解释APScheduler任务调度器的配置和使用,包括调度策略、并发控制和错误恢复机制。文档化工作器抽象基类(BaseWorker)的设计,包括通用接口定义、生命周期管理和状态跟踪。说明平台适配器架构,包括BasePlatformAdapter抽象基类、接口规范和扩展机制。详细描述Kimi平台适配器的实现,包括Playwright浏览器自动化、页面交互逻辑和错误重试策略。解释文心平台适配器的设计,包括API调用封装、响应解析和配置管理。包含工作器注册、启动和停止流程。提供性能监控、资源管理和故障诊断指南。","parent_id":"7c2ac186-ec90-400a-ac1d-b3b7ca2f01d5","order":5,"progress_status":"completed","dependent_files":"backend/app/workers/scheduler.py,backend/app/workers/platforms/base.py,backend/app/workers/platforms/kimi.py,backend/app/workers/platforms/wenxin.py","gmt_create":"2026-04-22T18:57:02.318442+08:00","gmt_modified":"2026-04-22T19:24:30.529121+08:00","raw_data":"WikiEncrypted:NKkj/YX2GdbxYjFllBaf8+HUgx0ecKFsz1U3HC2t2IRMbOkBCmoy+IYbhzuQ50K4pCdPARIwK+MaHbv1MDUXpcbdnvRL12GKezTnD100oXzQKqQkhZdDDC4nIEcp6weWLVGVffqyB7aL/dnt1QlE63XyJfCwizBlecxl1GDUB4J0O7SsTFL5gI6enVYO6hOzx3JrWnEFzirRjA6Llz1iFiFUWxTjxjToT1qkxAdREq2omi39vXL1s84I0XOA1blljfNNIGbpkxXW5uohJBndl6l7Bh23wF8z1LfdAavsFmljavCWqoMvA61Dn4jpJT9oDmaKXZpVSuxfMF2Tu3WOJZwISUGfGBJfdbfxNalhuFff+bhZR8P717nLoM3Do7T26rsqW/pr0NJL6aKxrlPCeIzL0v6Ct+HU3ULHT0EZpG8HfU2NhGWAJd0NhX8RZ8B2ZpfXZKioKtCkLhl4oWV6P8/k5g1nWpnP3wpmDwvp+/pGBeaBcYSenwJWgcGR2s0KgVsEW1niM8+JLaK15wFrmKcxve0hIWBiiPnbZKscAYq+5hj3ecte8h/JevEf+SBNB7ify6uUGU3Eve1jXyPeBrc2FCU5ueeJSFD3wu5pHlkzm7PP8UAbQOfwmENf/Mc1YRNi1FJsujdQuJ67474CyCTkCWFhTC539/6iIa7hN8505GK99PxHcIrsPMMT5LU69r67SizSnWV5bawiMPKGosexCHZfhT1jrScQCKeuld0X/lE1WXXm6ADBbfxZrn/iEFK0zc0WKsnT0X/nQI+ycJaw40Cm+soCO6/KtdYYGEzpzViqi2KxYhRyey+o+yIi8V7nVsxUCbaVRVmYNjnK9yX+3ypdVpJLIJXQ5ywaUWfvqgCrsC7Xxba9P9D+0kmnq6jH6ZdIuubXp0yOtWxe+VC4bHAWoc08RoBdLrlTCGz/hmgi5S83hM8MN0gLdQtc2YDsc0Pxw60+ylnkdlKIefBmb7XPiD8RMRvcbDUCGnrpenbxf5eoWLjLWfyULNQHoYINDdIFvn+skLu10KkfTf8lpRNqd2uHkHVhTTCFh25GlRLAdL7QDHMMQbmwG9OTjjt1tMlW6aYJ/pvYQq95uzmLAiICIsf+nT4xgqoFK+tTBmOst7Z3+bj1YJCPtUNyIzC9a3YYfRwlB1ckjgJaCURcXpImdkDtdpl3GP2mtDp9O52ZDAQVAJFVA3wFFV1G+qjqGRl4cDFK7BlAs04O4fvskn26jrDYiVqgdF0pc6eIiPhAJg/1BabciIggV78rEnEg6jiNJ8AhUmKLo8JOvL/C3m1mfcaUbU2K7oK8damVm8BSmIypHMJfCXzHIt6i+CaJLNlZ+c+MJ4WhqgPWc263/SnxO24wH0vaRtqmZ8g72SSFVa+6E65bdhSUaIejIDvILaBv+73KdUt7LGKPmqKoftErfP4grQZACnS3zQLXmnMfdzurPkKbBI1PkyT/ase2Czwu5/LwHWdWDcRQD2uZmUjndsKpbR6/xVu5Ry5VLB/ds2BrgjUp5pD+Z0U995X4yVwpr9oCNxR5r1sl+2Wv3jotf19l+safw9XwODQoURKcJiGxtJDymJvVEyl3ZEe1Izwl7SF4UqtboIYt9vEoEIilsuPPDtujnpN5pkY=","layer_level":1},{"id":"fda0598d-7e92-4b8b-be52-92ae63c3cd98","repo_id":"1095f823-f6f5-4e66-9aad-9f0b5b6b99d1","name":"API客户端","description":"api-client","prompt":"创建API客户端的详细实现文档。说明RESTful API的封装设计、请求配置和响应处理机制。文档化API客户端的错误处理、重试机制和超时控制。解释请求拦截器、响应拦截器和中间件模式。说明API版本管理、URL构建和参数序列化。包含认证头自动添加、状态码处理和错误消息格式化。提供API调用的最佳实践、性能优化和调试技巧。","parent_id":"d907a8eb-795c-4060-9cdd-50d31cf39be3","order":5,"progress_status":"completed","dependent_files":"frontend/lib/api.ts","gmt_create":"2026-04-22T18:57:04.217601+08:00","gmt_modified":"2026-04-22T19:24:50.486294+08:00","raw_data":"WikiEncrypted:/umMwKXdJhL9PqhJYRia9MjBtE8cuBSpJq1+zwyrvadwhOTuxc7+NNlJizkRp6kCDsj6HmsrrrEG2WmrNf4m1kFf/yUci2Hny4otqjfpEsOXzmFIxnq13zAZFe1oDyDiHr+shS0DH1omM5IrOroFuNXfBlFlOGXuTKJ3wXXPweq+qAH9QLU237hwRdKdI1UNXoGFfFF9nN8NzOmkwSQ0cRMvswtunfw+yphm0doFqLjrjc0WUZSar4loGeSR6pOSLU8ebi/JkrnwesaWnoYc/1aUJBPdJqVPSJQzjx/Oupuf/R1ihtrn81TMYOUvEaKLk9wVSfSvjh8RGttelGQzTBNJsssgMeqcDh+Qz6r4RJeFKgaRlhn753ONhpYFsHOA/05biB01p6yVuJUR2A3I4tqTlKZ+Xt5K6nvklSqGfR/asdknv3YOkVZOtQxAjyjg/RmmtnslgrEae+k+pBRvgZU23ZT5nZ82LarvwQLYZlu2F16oJjpKEgT3cw98zGHlLEIanqAXIOhT8iR7Fwk6TTKreGcH+oOkFNmbXHWXAD9ixtGbLqoidjzBlLLSR1++hGoabWTFiJX2LKj3lCJ4z30snHEvEL5ruTnKMF+gXM+truHTDsrO5CuaWyGY3WYVTndJKFLi2PQu5FclItm6ykG7LLkMlOXcKTmOrUqOgQhgDR0R7UuPYneG3+8tP49Gar78dBGx+Da8xGwikj9K9OJYAlHpVo05oKo78qku6h+6J2fHgIvIyJPSC88Whc+HpqTBbVMAIjzOQDzTTafDZnEoLWczvFoR5x2aPLnYwXdjyljOhmpXH/bShHcfo1W4KEEzka0Yp+DMZpTiSyhBpA5iLdjZdU9RnTUPTwMtqSXfdbbf0fdgem+z3CsmiuZJVViFNkOfRqL5f7Np4ITC0v2XwLSWr/bC7gbUZiEQdwEr7jwVO1Bk6/MCzvN1G217W7/RUPA4Up/Iu6PRBPcC4dd2r16kpGY4U68Ud7F6iXnc1Twr1Znb+cuTdO4Fu2DQ","layer_level":1},{"id":"7416db23-312f-478d-8883-2fc3c41ac2e8","repo_id":"1095f823-f6f5-4e66-9aad-9f0b5b6b99d1","name":"任务调度系统","description":"task-scheduling-system","prompt":"创建任务调度系统的详细文档。解释基于APScheduler的异步任务调度架构,包括调度器配置、任务队列管理和并发控制机制。详细说明查询任务的生命周期管理,包括任务创建、状态跟踪、执行监控和错误恢复。文档化异步任务处理流程,包括任务分发、执行优先级和资源管理。说明调度系统的性能优化策略、监控指标和故障处理机制。提供任务调度的配置选项、扩展方法和调试技巧。","order":6,"progress_status":"completed","dependent_files":"backend/app/workers/scheduler.py,tests/test_scheduler.py,backend/app/workers/citation_engine.py","gmt_create":"2026-04-22T18:56:47.083393+08:00","gmt_modified":"2026-04-23T15:20:09.061178+08:00","raw_data":"WikiEncrypted:VyywLMbCKto41PC5aDsBo+87rJy1wKhB+t/+dFn1cQKhRzLNGkc+cdUADwdeiVqAIwtiwaq+rwA2WFYQdbiGz8cyKHFmC9lmt3Jas1uZAz4Osy7WTe5xdzE2SEY35xhzdqPvBbNe/p8j0HjSJGFgENGbjEhhukipSO73yvj8CPLzAxa5OEqoQt3uMA0dCSgyFv2LovXFxAXl3U9omZ+jIerOmf0scDYFZ4Cjk4x8Bzb0xm/6wMRJahXUi7eKOQNBfFSlRnxNY+u8u6x0eLR9rZQJsBFNgTapyPe11i341lFAvV8GVMJsgmLfZeTV/A+CJWTGWbc7TTvNnWcbYK7l8zeSZ7dH4rEnOvERyY5kxDrOEwU/Yjdg0OIz0cgmb+dlRmAPiX3OWjxUXJg4aSEFFG16FvCKl2nOFUF8LecaPl1ENKZOzyeeouQpzJp6MwRbCvWKCbKjmM2LofkPlbYC3ljZcmitkM3M0iUQSDo8uwQ71JEBqciChTxdYCFkbs5lTGlaj7NMUVD0hinIuBaEJQ1j0Irfxqf1ncrLdx8ZNQfA0gzLgSYcvydd0BeII/j0Mao27RFzOAqYLYT4lwZn3J2ZefvqYbOF2Sifr+D0ZdG7elOtYhiRAUEHGhPSUWaoI5CpzqRPYnRva8JuLDZi4Kj0EyjpgPrSYN9dp01ryHcTMd7FaHIiskbn258Y9zpaK7mnlVvyKtjxlJL6MtuIV32lhcB+5EW7WH/6QDYQTwSBHw8UP0tyMyNbps8z+8Q5FmgH8vHxFljollei7t8eaPHYkk5rnVsXfTSQ4SjT3Ki6R/yfZ5BEnJidV+OTY4jtwp6TKE+kf6ioudhBQQXHEpufZoZaVaTZXTiIGuNSUBDlZ8hnbIS8ou6QcKMly3uw16qq1jpI+sVrLhWSLFcfRqW774uvsXptcHlY3jyOYYvgNSnLk9DHpURDX2VPzmVnzh4qOFmePV/gjmpSqLQpV1/iNIt9g3DADVd6eBWCjpp7/eefKoA1yLf1v3cLqoz1NFJZDj+xZBAIGNokT1IaiTnENcvwwJWL3xKUl+n4thAe+UgHXKJZ2an3jTF5IKjCZK3wFTIHqnkVBqLbYTnNr8t764mZT1/9wh4OKLf46TVR2knmcx1cuUtGr3Sewy3daul0qF4ixlI8qx00gkAJPhMSgdD9NphN7vd38cFIdIrhJ257ibJH98P6LFTvtBlJtLNk0e8UNLU9gvqtKe+mlotbHy1WlN3l1P02b370hBTcnBA0JVykYqIO2Yux+kvP"},{"id":"dd12cc44-0c95-45d5-a726-e7b8bcf2531b","repo_id":"1095f823-f6f5-4e66-9aad-9f0b5b6b99d1","name":"API接口文档","description":"api-documentation","prompt":"创建GEO平台的完整API接口文档。详细记录所有RESTful API端点,包括HTTP方法、URL模式、请求参数和响应格式。文档化认证接口的JWT令牌管理、用户注册登录和权限验证机制。说明查询管理接口的任务创建、编辑、删除和执行功能。详细描述引用数据接口的数据查询、统计分析和上下文提取功能。文档化报告导出接口的CSV格式生成和数据导出流程。包含错误处理、状态码说明和API使用示例。","order":7,"progress_status":"completed","dependent_files":"backend/app/api/subscriptions.py,backend/app/api/admin.py,backend/app/middleware/rate_limit.py,backend/app/middleware/logging_middleware.py,backend/app/services/citation.py,backend/app/api/auth.py,backend/app/api/queries.py,backend/app/api/citations.py,backend/app/api/reports.py,backend/app/api/deps.py","gmt_create":"2026-04-22T18:56:47.083629+08:00","gmt_modified":"2026-04-24T11:02:30.089402+08:00","raw_data":"WikiEncrypted:rEJA+fDSevRLFPlWlcH+C02eArPzlHQTxpYkpRmh+m+CmPwrZOHSqyEVvpFbcfuzlCdXmMyG1qoekj03JLnUhMCX8p4fjuyWVCjGyWgOqZfEYH4zqWamc16YOPdK+sCFQ4QmdrKW6cFcIs/JSz1BcE42L6PRCsFSdjC3x3Ir2kmeZ2xCyI4DTuIg5MWkYlr15jZuzLH5rMyvHib5uxo2LCklVn7i/8Yc6NLOW0AIHuLJGKU9hVU2nes18OolWvbkowwiJKV4MSqSrfUSL53HCd6IbvHajavu3hulkI00H4b/6Rkqq/mkJOEzBVSWXMI2Vj0Ww7mlzTkfkOv9v5Kp1CMC2qupcuFy78Q2J8fnj+tjDbvXOrkAe3LGWo59kGJXRS+LdWUjxsPwbaItkh9PFj2MOBQJ4dj38tLJ7OTH8Zag/VQP1Rr0yLqacQC0kduxAW/GKP5mj949etgdOr5Lsjt2hG9a/1bqVl7DWYX88aeyobv3qSg0/o/486gC040fYXNi3RFhZJev7cFLhxmkWPUFqKblmvIDwS5eDfYnWF4VVACVcqUVKWN/0V1whA2/u83e0nSdQLHU6gs1dAadBeJ0WvtCalaRzumPYSlz4Aw8pywfTE9u5GXpaONFFjCfgFuf6Mm3qpvL8InOKs1DhtGavpj+3P8MaFERk72a/Gb08fD1Ri60LsgMXjD5XdSw7IDRukJVTBRP80/vYYdNlDoeuM6uHvxuORxFCZNsTmC6PSerCo3AGnfpERUDzSV+ejU1fSrOc18pronb4I2lfIHjNpr3mjVLfnNEbsMRu/VHtk9lrPlkd3RxYRlC76W8XAK1cJr8Q6qtOz7qkNAs4W5VZoSO+6QAec2P5ej0aUJ0xR0Z1ZZhFyYPQE0VCrvcKSUJgeHUhcoBWbkPuxmk1l0FC4+Cu8JOksLcMRzb/2trJowZ57fQA7N/3YYOKlKW7wFqNXNJQ2djP2A5WflT9OL22/D0Py4o2wLDr7vtXv/4E2A0YJAPcqdwbeeYHN8Cika4GiA0Z48TomRK5PEPSop0NRekjHc2q3gppQK0+Pwy8GM0JOO04VeLCsbRKwjCrIB9+B9ciiBEDh2F/9+OxmySWZVKQB32NFozE4bT00ufcsFWApvwewZkiqUTWBaDjTrXxm1AnewI+T+/bLaY+m6Lr4yGO7jAuUDYkTSVT+IVNFX9ep2FVdMUqZFYp6+Vukj3nVwL8lRaG8zJaJ5TxxiB7grWdRXzaNT5CJlkTSEdFBkExAkNik1S4Xhfs2uU+BSvjZTzB7gOZKEYhjkV5m707rsT75hYFqeRLdIaCSWxZzHIHHTCxOfrAncP+2EkLHjP8bWAOjhdABT3djMsTSgm15W9NG8oAayRIoAE6M/ZAizrqiaAAKxQFAthKpGNTZZfdHNbxIfhk+D65kW8zTuk1aWN2k1ktFAc/sjQplPFkr/rY9K0PiBMFlXrye60kFAtFxjRpPUbtuRr3sMdJjPiHxB/bIi9XODVl9m7eyjDeTZFKmmxzafzNT9VP+YpBSy4QdKXaZkR219fdyhs52iRnGXP+9Phy6uUEh650InWE9CNFGZMSTRPpUkn9xJq/mVLJ667r9W0/aAs7ETC4g=="},{"id":"fc6f24c3-594e-4153-854f-19250834eeb1","repo_id":"1095f823-f6f5-4e66-9aad-9f0b5b6b99d1","name":"测试策略","description":"testing-strategy","prompt":"创建GEO项目的测试策略文档。详细说明Pytest测试框架的配置和使用方法,包括测试夹具、模拟对象和测试数据管理。文档化单元测试的实现,包括认证模块、引用引擎、查询处理等功能的测试用例设计。说明集成测试的策略,包括API端到端测试、数据库测试和系统集成测试。提供测试最佳实践,包括测试覆盖率要求、持续集成配置和测试环境管理。包含测试调试技巧和性能测试方法。","order":8,"progress_status":"completed","dependent_files":"test_output.txt,tests/test_business_flow.py,tests/test_scheduler.py,tests/,tests/conftest.py,tests/test_auth.py,tests/test_citation_engine.py,tests/test_citations.py,tests/test_queries.py","gmt_create":"2026-04-22T18:56:47.083879+08:00","gmt_modified":"2026-04-23T21:02:44.23225+08:00","raw_data":"WikiEncrypted:Xd2Zu8BM8p49theGlFJHkHqkA5ycuMpwkltd7rjxfkZm5u2F/OCOa2rxC3NxLrZDZf5D15q4Vh8tHCK9cPrOS/yjJEFoGKYx888+pCfJVQGvOvV8lbxJ/fNWDqo3ccIMDBY5poew3y/74L1tz0L9vjHRBLPVQADCR3UfTk94UBhlYGXamKDS74D8TgPqiuz1dVhmkX95unpFQiGQxCgxeV/sDgwTl7DYpnPy4VqFJbcPHD2Xvv828icOoxqz7hWaOp/65B5Vcn9P4LVk7dQmHzrLBdrDLBe+5Rv6mDD3+Rqrv3ZX+1v7tJ1dnmaQ2ZF8tE9ttI6ENeaFys0BrcucTSrsbSDtmFINzGh/aW0G3Q/YRtNfmkC9t+R8wRSnAgYadYSkUuNTVWQRRs4JxAcn+cHODObsEdp79EwDCqcLktVlpNaLJ//B0sOyLQA741MiLH5iM6tglYaOoQ48Ydyw7Fp5U9agWwgK7yZO7REk4ZB9U+juDzjf+qUHyjIVlXUxJXg7ATsy4euCmDpjyxJGRH7Z89wWkOotsSC3igqSM391kOqbzl9P5ZiruYliru20PndDwtXbJQ0jcvvKJsK3RkIYX0ml7BOL9H7Y16TL1Jwc6DVcRkwWQ4IEKG1fJhqYcb4WI/vPDD1jIhHBe6O5VAZtPPA+SIpYJg8+/qf0FQY73EPqWe0jPuc6I2jyN7UbjUMHRAeb0sVvj18qVYb4E+KKwNZyuAs+0SvTk/nTgqFPdNrOZ923/jnJTNt2Df1p89NDS0NGeHobiC4XD8koxe9vshUUdeDjXIopttcYBg4LcWAudoq8OO07eB6xiqn/MwXPaZySdWrqr3bh2xxxaQPR/NTrfrBkN+81NO784cJEkYHfSfUzIqhLhTTNEQpfl12WDM+GnbHWCcyWuN2dvZ6Op/ZCpLO+cQhZnXFPILnCzFf8DyNrbD3niQYcOC6H1nFlaGSmx57lswjyX14vwqOB+yNR8n+xG1a7JwxscBYaNQG5kvfLaJJKpxIdSB2YIKrIwImPHtzTI1Qahh3MfLtqI99aH9p/1LMaKJQsASKr1Ja1X3dO+ZpIiQRTeDR/jdWnzBA7Hk9SjB6ALHJhLYTutqKVkeIL08U9HNeWn3BFwCthEXMHapg0Vh/guoIq1j28UwzPkqMcSynuv98uyhHfUgRbOWQ9WTDis8gPn2jxpoCZyVCAxOTfF+67GDoTn6smJmqHIkQkMjrxLVZE3FfMtXHAcZ2kG9DC1aLVFNm64bP9X/W11dT6vm5SkabIiu1AzYuZDce+Rbg73WaCMrv4sXmBpNYhYUkLRj4gwNEFSd+eOJ/GS6MZSkA7p6A73OY1PHXlRnFrcLN10/XzFaPAM8L3h4WmqYoxFNJPTx5hRuwX2MfiwZgZlaICfBuO"},{"id":"803bfef4-3985-477e-a61c-915a246d0061","repo_id":"1095f823-f6f5-4e66-9aad-9f0b5b6b99d1","name":"部署与运维","description":"deployment-operations","prompt":"创建GEO项目的部署与运维文档。详细说明Docker容器化部署的完整流程,包括镜像构建、容器编排和环境配置。文档化生产环境的部署策略,包括Nginx反向代理配置、SSL证书管理和负载均衡设置。说明监控和日志管理方案,包括应用健康检查、错误追踪和性能监控。提供运维最佳实践,包括备份策略、安全配置和故障恢复流程。包含CI/CD流水线配置和自动化部署方法。","order":9,"progress_status":"completed","dependent_files":"docker-compose.yml,backend/Dockerfile,frontend/Dockerfile,backend/requirements.txt,frontend/package.json","gmt_create":"2026-04-22T18:56:47.08417+08:00","gmt_modified":"2026-04-22T19:02:23.851886+08:00","raw_data":"WikiEncrypted:0IKfLNOWe9mZfG1jVts3w2XbjO+yyEmY3ONOjrL5GjA8+3c0QEcD9OcCVHu+1BW/N5NkoQV86wegqQ9ShX8iSWP5bp76U/WBxmHscWo6tU/8QlGuoaRAEg/ev4XsKkgC39pvYnfm60PfrpsE2hL1E2GfNGgG77OCHFDgZXXNbh9eCPmSkW8+YhED55nkyvxbnzr0nBnhsGtTzPUxHW1tar+GAvP539R0R/4mYQI87YJ70yZ7fcsaLwgOXmzP3dVnnmpLv+9t7xJhpCjyQsxfBfLLWBAADnbPD/XDJUZjfKYBtzZr96wOF29GlOAKy0gF60uUu4ldT+fyQn+nYlMXrNBIPA4xv5zs0p3ITXaqvMn5CnUdObefSllD9bB5ZAVzibfAxAovDM6bFfCBg78rOiHHyhVisNUpyQVL18Ac1DA/7UfdJH03ceu0hk7swBM7UlLgBUuU8iZZq8IKLS9Hunf/aF7T2fuFhJB+LGpBGwV+3OqWaT6v4reKhSW8vMM4x8XvLXgDttwPeltWlMknvzqijyjE0V38mue+Fe5fYrBZIK66PxnXrGUJKvZPwyAC/8LX6Hk+M3aBWjL4QkiKpbN2/pXCR6dXuPfbswZ11T0xSYdC8m+8SmC5UAgcryC0PI+ULgqxDhrheiaPIpfOAGnPr19iY2++A+xP/IPZf4L9hg2cNxi5vJ+ws54SmeQDUdbzx15ZECbSbz9xkShlRAYOjuUB9/IpZFt7EqH7sEqsFlbF73qp72JFPp2/QYv9av/WYcw6WVtRJG4TQ/Z9jB+DN6yCeSC6B/CfK05zoF7yrVWkLPiSSVYGDSBndH9EFJEJJvzO27tkS1wZXs4fTTE1StkTjYn8EBSRVvIs3Ywg1+iM2SFYcbn3I6QCeqaXuMJ/yEJikxIeLJGlNjiShYEo2FOMQ/6Xk+TlHkxUTepgnzhxFkPq9S2dqK/ZunroHtiqObkTqfkqta9V4EreMpXtO/FUBsVUrmehzAmO7CQ53L74HnyAqFJYWA/iDUt8rABkFT69QahL9BU4bts3AKhAypInqPXBL+0v0WyatxLd1jURgSq11VX9UBNBi4li3TcoFc9wsZpX3LeH1vNueLQzvssRDfTY9doM+g0rgBXDOO59DyyOKrDDMU5D52k5KI5SJOaWWxEa24TOoTfC79Jpc6tW0zAhdvdLD6u/pfsZd693uN4RM8fMtZPh58w5rcXuEHrhVI/0JThluHDnb6a962K0mt7d1makwsRTPZvpvaTrgiaoByIyOuKY7q1L"},{"id":"2148d7d6-25c4-497f-8894-c4eb7a0d2bd7","repo_id":"1095f823-f6f5-4e66-9aad-9f0b5b6b99d1","name":"开发指南","description":"development-guide","prompt":"创建GEO项目的开发指南文档。详细说明代码规范和最佳实践,包括Python代码风格、TypeScript类型规范和命名约定。文档化开发流程和工作流,包括Git分支策略、代码审查流程和版本发布管理。说明开发工具的使用方法,包括IDE配置、调试技巧和性能分析工具。提供新功能开发的指导原则,包括模块设计、接口定义和测试要求。包含常见开发问题的解决方案和故障排查方法。","order":10,"progress_status":"completed","dependent_files":"push_script.sh,frontend/tsconfig.json,frontend/tailwind.config.ts,frontend/.eslintrc.json,backend/requirements.txt,CONTRIBUTING.md","gmt_create":"2026-04-22T18:56:47.084469+08:00","gmt_modified":"2026-04-23T21:00:59.749127+08:00","raw_data":"WikiEncrypted:9b1XqHriaqPGsMtQmhzV28eiWwL8soWZUx4jD7Lpj1ZvEeRHqDXnLB57Wv0GJdW0bSai+es/AGcSLV4r5Y1zXQCgYNssGUbbdn66dv22fGk42xijVyio7TzEJPm2vZsrwpJe+/yfqkj5uigIlIv06GRfmEvdn6T8ivaGf4o8qPrbbaCqfb656Ecihx7i5F1ZXK+etNk5HJeheOAvl/WoiZD0TchF59yuuB06Rl/W0/sfm7xUtkC5QYYoo6qYsIuOIE9ynhoHFI2junjkQwS3m3E/W3kKHTNe57a56kaMBo2fa1in+LuWr0jPxfsXJWHwwN47eEs+neAYXoxz+AHzJxrd+FTvW8o+Jr7hmJjODk/1u5VGWqquek2DS33JHThmmD3ant8C85SI0QDd2Rez4xia2mCq+kIzwnOuORyodpDeIHYWrwbL0X6Q4KzwwZKXYBlWZH+PqiovtlIQpZ+FrabfOImECKTIsdYECFDGwvOvZdH09Kmi2TqBszsArbv/apEc8HtRyn3MbxlOmBZ3C86pepDzntKeY8OsRhZv1/EHc12+zlfgBxkzS7g3sZhf01vr2xPsYdFU6Zpts9eWNmMJAthuG+wyeYrGDXuGHQFbXa7Rhz/mWmDKqcUZcrGo2ScQwNuk19uCmQ5x7ZTM1iNSbKYWaJwW4jn9gG8sw9+saye/tFTCyDoaqyyumHT8s/aE3bvalg4fA4AE8RigKIlwzLKW7sZmL8sY6b3PBgIJB054DRRSUF/jEW24wPDgcW29SEG6MwyqEVCpBGvI1t7zhmmM6IRklQNvVzGaoQ5GkTDxAaMh5ULEbqPdmjMJkyTP8xtyLhrJz/UJRuvvFOpf2zyyHg8Do9zNEP/FNUbq2sjjMPwMUwZAVcU2jQvNyiUYJXLvzaYk7fSEr74I3YbU9XE+/dofBpCd8tPG/BmV09UZCVgI3UrSRYd+GcgziKhnbDf/UVR691bhj4lUBtNzyNM2AnUWoQN9IMyjpMEo6EDlTrIL6wqn36aRNqPibx1vbsAdFAwmJQbf0oVZ43AGDJde58EOtIh6QzXdY5yj+UYIl8iCXO0VtnMm79ouguB3g59SOTIbv6X/iFjQ3rvERX6pFPBI9GyKfhKQTwib98D+9pkHnU2n625WeukHx67ieQLvZ7pZLfqMYTEQvo80N0JfbAP4FNz4Mtuc7jpXm2JyV/tAI/Y4Lbx1KMUq2mDsZRamD6HWF61GEGr94VsrM8kFcf2RHb9C6Lt3EuKlasgwJqSnr8iO5oONILiT"},{"id":"b2bb2e3c-5661-497c-97dd-15bf6ee8b7d4","repo_id":"1095f823-f6f5-4e66-9aad-9f0b5b6b99d1","name":"扩展与定制","description":"extension-customization","prompt":"创建GEO项目的扩展与定制文档。详细说明系统的扩展机制,包括新增API接口、前端页面扩展和数据模型扩展的方法。文档化配置定制选项,包括环境变量配置、功能开关和性能调优参数。说明第三方集成的扩展方法,包括新AI平台接入、新数据库支持和新认证方式的集成流程。提供插件系统的使用指南和扩展开发的最佳实践。包含系统定制化的案例研究和实施建议。","order":11,"progress_status":"completed","dependent_files":"backend/app/workers/platforms/base.py,backend/app/models/,frontend/components/,backend/app/api/","gmt_create":"2026-04-22T18:56:47.085228+08:00","gmt_modified":"2026-04-22T19:03:46.033162+08:00","raw_data":"WikiEncrypted:9tFZPEMPWdLFkkE2XbXYMuMB8FuOYQ0fj+/JXYKsHGVuXRejugUICkyxL86Ju3MeDs2yZuuby22yn9F5xTbpPvuSC/FoLxV09I2ZpvfpcQFUCVmZyQN67BPwYA36FWIbbHI5AJYWayiJUo+io2WnBda4ESUkmi1Ifq6VpdD6Et8Rw2b8dgDDMxi9XaN9V0JJWAK4CsV0ZYGNAK947J00M9KveVb322Q2MkjA5aw0eylKLH0fzY4qNXNGDmfCOuncuvGiH/5DvAXCDuDLYzVd1AHr/9UgPCvmp017Oo8KijVdD66YD+QM7Rh+24GqNvD5xFbOQGd7ey9Mzs33E6JIrsbUhBvbLJOVlRo0EdScVPZsU4HO6zqDAg0ozD1a5kGX/WxHBvhKBJATucW9vC2XG5g21SjjE6NdebD3z3ZjN+cu8jYHMi1BwWhOmvNRvN8HIGjzntLglg7fNrii0iJXTxpZ8Mbpmu6Tk88oMecsGleuA2xhK1yEWycuQ2dZn5e179BE3mGaSOT0Fvp5yXgL4htvqVTAu4QZ+JFJVk8e4NkI2KaoEgS8vmkD+tvnSal6LUgMzXvRJVj5c7y5LEqxY7QwEbvunmtmHaw9xxVNmfj54tFWSDCSUVCBp+otUfdEq+e6UMOQ64QITUXyYlP+zGW5J0ZWBf9GlU5j70IekNuO3mLp/yU922OD64PhCEL3HOTmAtV1L1vunWchdtvyht6rkYuys0Al1WSGeCmVT23fmJlSuKe++K/qQ/TheLhgA4euY3OnlacLzbia76+B2p4tJY+XvzzDZ5c3M6YdKmW0+iKB+TRJgVz1Q8GpFIzUk/ShBam/TanUxOcC0ci89hjchiYImL1tQeigX4Rgfcn8mXYH956z7eyiSYtqk7uIsQYfiW7tqvcyN0jJpGUVHd9IzvK2NAC+ICHilErsg5hRJ66KFaugTnjd2WoIkU8rktkywDasvD24NZM417z8B8l8uHq9XNcg+2bdPA9hqx5ujEUiGXyWkBNvwCZXg9aL2q+4y5NMoZh6ak8uEjC1kc1S61q2kFyKyIjV7QbCMaHhjnrBnkSg/kV2cGrBPeOqWdtANBw5wZ/OJ38FLWJ5nPOzreTmQ/R6J6YNCfmRPpfpVj0tH0o+0rffNxxXa2TnUbu4OSSLdCljK6CsfuYmBOStwIQtEs8T8/+PsrbQKY9NM1KHqhg5Nk72UNylvGupV/Zccfjg3z78M9uUqtXSOA=="},{"id":"8e3d62e8-ddbe-4820-bc41-7da9e91ea598","repo_id":"1095f823-f6f5-4e66-9aad-9f0b5b6b99d1","name":"故障排除与FAQ","description":"troubleshooting-faq","prompt":"创建GEO项目的故障排除与常见问题解答文档。详细列举和解决常见的认证问题、数据库连接问题、API调用问题和性能问题。提供系统监控和诊断的方法,包括健康检查、错误日志分析和性能指标监控。说明调试技巧和工具使用,包括开发环境调试、生产环境问题排查和性能分析方法。包含常见错误代码的含义和解决方案,以及预防性维护的最佳实践。提供紧急情况下的故障恢复流程和应急处理方案。","order":12,"progress_status":"completed","dependent_files":"backend/app/main.py,backend/app/config.py,frontend/lib/api.ts,docker-compose.yml","gmt_create":"2026-04-22T18:56:47.085508+08:00","gmt_modified":"2026-04-22T19:04:06.13183+08:00","raw_data":"WikiEncrypted:CaKOW8OSSWs4aEYk06Hu0tuZET5JxbVXxA/4vFailoRiq8l6SCRMdp2PbHfZPheZXyPTAgE3AT8Ce8j9xPOCdJxNKAOstuOjZEIRRi9OOYwoluR4MUnob24X+IyLHwTgsJGf9uPY1LVFTI9RTQt8aG1cBHibaRNEJ8+DVkXJW/EDypOxFpOxDxlaCscMdiPRLwhr9V4vJqWV9j2rk1LjP2/M8SJJQ8hbaDoeLevKdECB+aEw9JrL9ycGW0dhxKxQLf/ril9zNHrvahlSXbVZSZ39dpBl57NdFcFaOYt+paf3O6hv3bCTAKGLTRnYa/IuAZ6Xa7YnhqaGQ684LKCBz6VySRNYVUCEvZotYHf1IQdWOj0zFzR7LEIEikIlZyKak++yTNYfbQyBEzye3g6YCmlh6VaVmtGIRzjOYpu0K1UftNcRa1mWnIMrB/Pqe9DpNTg+Yxo3ZHrPyv3ZAmrd8MqA+T+P+/NerCmFD3dRf94NLPP8KU7in+VSfEjVmdE0N+3OfntU+uvNL/kkOhyWNRUKYKFxbqdwCTKqv3Nchs73XyhfNRP7gPkR/stgnowCRnKWS4ncUEJDZTWVFID52kE8nH7Kq/yuB5bJxFX9AeUUaNSBgvMc5YNkq3vULFEqC1/N0bpU4r9+0/U/BcMktmNrRr1HnOIPl3QzwjIsT3j2lp4UXS3Qm4BZFJsh8MVLfgOIMbO1jbuGCXHl88T/rZOCNwf4q93vWo2HnOxDkbdICWgZ9dinRr85RkFQjNWlXdAk0XG8lQPotwJLvS+ZASOv1aWyL42jk/mTJcOU53PFT5rf3+WpVmhNWQGguZ0l04eubO4Va39c6h/+DNsl0OEAiozIMohEgz77qsD47Kf0KZMLnqL3o30TYXYamX/CP8+epBqSWgmzX/ETrrRl/1/JPkSDc//0VC8UmWBJAsdUdzyQh9v9iQddyIZ4MV1k4MGTJ6GwrUqVTszShZJVG80wDMLQvJGqJ0T5rH1P7kBaJ5nBnth822MBy7B1IhN6nDqtLhOJcqT8Qt6x8ODGFx1QMNBdS4lHq5IcRy+nZKiPP3V7uMuuFQsNNodTRhmNnuAliJACWS89hPiGroan2VkusxIu2DW8wdQ/3Z31mIn4cE3O3+Aq6lO+BEMAuYh5WkOEmGsF3cjX/zPPiuBSP7Vd2a9o6gPA7MBfneMWyqodMp6PKh7EG26gaKUaIGq6VkQobSAVfbLxmfIMW6cZ5STH4U1/A7gV2PeuWzwwEJz7axGVQIJ6A9geQevZvD/cnX6BQBuOMkdAOB6PApCpQA=="}],"wiki_items":[{"catalog_id":"1bb55e12-24c4-42cb-8f59-ddc303460d45","title":"项目概述","description":"project-overview","extend":"{}","progress_status":"completed","repo_id":"1095f823-f6f5-4e66-9aad-9f0b5b6b99d1","id":"34e572eb-6fc8-4de7-8061-63783ef8be24","gmt_create":"2026-04-22T18:58:50.323135+08:00","gmt_modified":"2026-04-24T10:58:35.431256+08:00"},{"catalog_id":"e3ae8925-4862-4280-b85a-0b376841b15e","title":"快速开始","description":"getting-started","extend":"{}","progress_status":"completed","repo_id":"1095f823-f6f5-4e66-9aad-9f0b5b6b99d1","id":"7f028ad1-e989-43ea-b945-c79c33e6f0e3","gmt_create":"2026-04-22T18:58:54.232866+08:00","gmt_modified":"2026-04-22T18:58:54.238013+08:00"},{"catalog_id":"7c2ac186-ec90-400a-ac1d-b3b7ca2f01d5","title":"后端系统架构","description":"backend-architecture","extend":"{}","progress_status":"completed","repo_id":"1095f823-f6f5-4e66-9aad-9f0b5b6b99d1","id":"c7eb113b-b503-4d83-be7f-9ccf3350c9d9","gmt_create":"2026-04-22T18:59:20.999631+08:00","gmt_modified":"2026-04-24T10:58:51.177364+08:00"},{"catalog_id":"d907a8eb-795c-4060-9cdd-50d31cf39be3","title":"前端系统架构","description":"frontend-architecture","extend":"{}","progress_status":"completed","repo_id":"1095f823-f6f5-4e66-9aad-9f0b5b6b99d1","id":"3af3bb9e-4d99-4dc3-b1ed-2686db385c26","gmt_create":"2026-04-22T18:59:54.989699+08:00","gmt_modified":"2026-04-24T11:01:58.108443+08:00"},{"catalog_id":"243a1a45-d31f-405e-a3b9-694d2fe617d5","title":"数据库设计","description":"database-design","extend":"{}","progress_status":"completed","repo_id":"1095f823-f6f5-4e66-9aad-9f0b5b6b99d1","id":"ffbb970e-56e0-40ad-bd88-1a1e55482d96","gmt_create":"2026-04-22T19:00:15.762815+08:00","gmt_modified":"2026-04-24T10:59:38.979212+08:00"},{"catalog_id":"7416db23-312f-478d-8883-2fc3c41ac2e8","title":"任务调度系统","description":"task-scheduling-system","extend":"{}","progress_status":"completed","repo_id":"1095f823-f6f5-4e66-9aad-9f0b5b6b99d1","id":"deb919cc-9541-4ed7-a581-ae2876ea67c2","gmt_create":"2026-04-22T19:01:21.979952+08:00","gmt_modified":"2026-04-23T15:20:09.061378+08:00"},{"catalog_id":"7e66719b-4a8a-484d-889d-10fdc76788bb","title":"AI平台集成","description":"ai-platform-integration","extend":"{}","progress_status":"completed","repo_id":"1095f823-f6f5-4e66-9aad-9f0b5b6b99d1","id":"cfc48cde-e1c3-47f6-afe2-a6d7a8f4ab69","gmt_create":"2026-04-22T19:01:25.981164+08:00","gmt_modified":"2026-04-23T20:31:36.620216+08:00"},{"catalog_id":"dd12cc44-0c95-45d5-a726-e7b8bcf2531b","title":"API接口文档","description":"api-documentation","extend":"{}","progress_status":"completed","repo_id":"1095f823-f6f5-4e66-9aad-9f0b5b6b99d1","id":"49915365-e38e-43b5-beac-6aa7d5a74cbb","gmt_create":"2026-04-22T19:01:28.269494+08:00","gmt_modified":"2026-04-24T11:02:30.089537+08:00"},{"catalog_id":"803bfef4-3985-477e-a61c-915a246d0061","title":"部署与运维","description":"deployment-operations","extend":"{}","progress_status":"completed","repo_id":"1095f823-f6f5-4e66-9aad-9f0b5b6b99d1","id":"98909ecc-fceb-4ab7-a26f-741838eb2e50","gmt_create":"2026-04-22T19:02:23.847103+08:00","gmt_modified":"2026-04-22T19:02:23.852058+08:00"},{"catalog_id":"2148d7d6-25c4-497f-8894-c4eb7a0d2bd7","title":"开发指南","description":"development-guide","extend":"{}","progress_status":"completed","repo_id":"1095f823-f6f5-4e66-9aad-9f0b5b6b99d1","id":"643984fc-5a57-498b-8f25-68cc318d9d82","gmt_create":"2026-04-22T19:02:27.517117+08:00","gmt_modified":"2026-04-23T21:00:59.749244+08:00"},{"catalog_id":"fc6f24c3-594e-4153-854f-19250834eeb1","title":"测试策略","description":"testing-strategy","extend":"{}","progress_status":"completed","repo_id":"1095f823-f6f5-4e66-9aad-9f0b5b6b99d1","id":"b0c36b2b-bb03-4624-933d-c1f6a320b7ca","gmt_create":"2026-04-22T19:02:30.709013+08:00","gmt_modified":"2026-04-23T21:02:44.232375+08:00"},{"catalog_id":"7c3e3c0b-5d1f-4d64-99be-668041c6cd9d","title":"核心框架配置","description":"core-framework","extend":"{}","progress_status":"completed","repo_id":"1095f823-f6f5-4e66-9aad-9f0b5b6b99d1","id":"f94da0b4-8a07-4de1-b0b3-d3b32a12c3c1","gmt_create":"2026-04-22T19:03:21.689103+08:00","gmt_modified":"2026-04-22T19:03:21.693211+08:00"},{"catalog_id":"b2bb2e3c-5661-497c-97dd-15bf6ee8b7d4","title":"扩展与定制","description":"extension-customization","extend":"{}","progress_status":"completed","repo_id":"1095f823-f6f5-4e66-9aad-9f0b5b6b99d1","id":"c5849940-e223-4222-be17-aa0a6cb36bc8","gmt_create":"2026-04-22T19:03:46.027426+08:00","gmt_modified":"2026-04-22T19:03:46.033304+08:00"},{"catalog_id":"8e3d62e8-ddbe-4820-bc41-7da9e91ea598","title":"故障排除与FAQ","description":"troubleshooting-faq","extend":"{}","progress_status":"completed","repo_id":"1095f823-f6f5-4e66-9aad-9f0b5b6b99d1","id":"85306af2-0edf-42b8-b7ad-c03e769cb1e8","gmt_create":"2026-04-22T19:04:06.127415+08:00","gmt_modified":"2026-04-22T19:04:06.131953+08:00"},{"catalog_id":"bcaa04da-04e3-427f-ba01-847ad657e78a","title":"Next.js应用配置","description":"nextjs-app-config","extend":"{}","progress_status":"completed","repo_id":"1095f823-f6f5-4e66-9aad-9f0b5b6b99d1","id":"c112a3f4-b0a1-4c4a-a325-e3ede8c90be6","gmt_create":"2026-04-22T19:04:47.356556+08:00","gmt_modified":"2026-04-22T19:04:47.361504+08:00"},{"catalog_id":"9e3d703f-f424-47f4-84df-b99873b93e5a","title":"项目介绍","description":"project-introduction","extend":"{}","progress_status":"completed","repo_id":"1095f823-f6f5-4e66-9aad-9f0b5b6b99d1","id":"2793782c-91c8-4052-b9db-39513426c736","gmt_create":"2026-04-22T19:05:00.372036+08:00","gmt_modified":"2026-04-22T19:05:00.376145+08:00"},{"catalog_id":"a06436ee-1678-4a51-bbf8-b0d0ac3456b9","title":"数据库架构","description":"database-architecture","extend":"{}","progress_status":"completed","repo_id":"1095f823-f6f5-4e66-9aad-9f0b5b6b99d1","id":"d5c75004-b01b-416f-850a-4791c5489a32","gmt_create":"2026-04-22T19:05:13.619093+08:00","gmt_modified":"2026-04-22T19:05:13.624074+08:00"},{"catalog_id":"7fea5a24-e6de-4003-bc70-9dae6d8fdb25","title":"适配器架构设计","description":"adapter-architecture","extend":"{}","progress_status":"completed","repo_id":"1095f823-f6f5-4e66-9aad-9f0b5b6b99d1","id":"37003fc0-1cf5-4264-996b-40807001875f","gmt_create":"2026-04-22T19:06:14.01196+08:00","gmt_modified":"2026-04-22T19:06:14.016291+08:00"},{"catalog_id":"b027f234-4ac5-4d6d-9b38-afc8054325f5","title":"单元测试","description":"unit-testing","extend":"{}","progress_status":"completed","repo_id":"1095f823-f6f5-4e66-9aad-9f0b5b6b99d1","id":"8150ddbb-7aa9-48d0-9953-2ef55e4bcfd5","gmt_create":"2026-04-22T19:06:55.084551+08:00","gmt_modified":"2026-04-22T19:06:55.090188+08:00"},{"catalog_id":"940e5918-1689-4001-a284-44f2de75b8ee","title":"认证接口","description":"authentication-api","extend":"{}","progress_status":"completed","repo_id":"1095f823-f6f5-4e66-9aad-9f0b5b6b99d1","id":"7c7564ee-7fe2-4555-8ff0-4ec1b757997a","gmt_create":"2026-04-22T19:07:12.352034+08:00","gmt_modified":"2026-04-22T19:07:12.356599+08:00"},{"catalog_id":"78288302-33bd-44f7-8b29-24f516c8b6bb","title":"调度器设计","description":"scheduler-design","extend":"{}","progress_status":"completed","repo_id":"1095f823-f6f5-4e66-9aad-9f0b5b6b99d1","id":"a1cc822d-5382-431c-8c49-cf398fb5eb3c","gmt_create":"2026-04-22T19:07:22.166733+08:00","gmt_modified":"2026-04-23T20:33:30.132576+08:00"},{"catalog_id":"6406f42a-e10b-4a2b-84a5-0a21c1c759ea","title":"代码规范","description":"code-standards","extend":"{}","progress_status":"completed","repo_id":"1095f823-f6f5-4e66-9aad-9f0b5b6b99d1","id":"13c568d2-dfa7-4d1b-81c0-dfef247cbb67","gmt_create":"2026-04-22T19:07:51.271116+08:00","gmt_modified":"2026-04-22T19:07:51.274241+08:00"},{"catalog_id":"a91fff3d-ec5e-43df-8176-22f0084109ef","title":"功能扩展","description":"feature-extension","extend":"{}","progress_status":"completed","repo_id":"1095f823-f6f5-4e66-9aad-9f0b5b6b99d1","id":"d2c7157d-157f-4990-8f76-11f3ea5435f7","gmt_create":"2026-04-22T19:08:25.13644+08:00","gmt_modified":"2026-04-22T19:08:25.14088+08:00"},{"catalog_id":"e8ec6ac6-ad1a-4332-a7be-727b47d71233","title":"Docker容器化部署","description":"docker-containerization","extend":"{}","progress_status":"completed","repo_id":"1095f823-f6f5-4e66-9aad-9f0b5b6b99d1","id":"1ed0b482-3d6a-4bfd-af40-47a5d1f3e802","gmt_create":"2026-04-22T19:08:34.079807+08:00","gmt_modified":"2026-04-22T19:08:34.084736+08:00"},{"catalog_id":"c19260e2-5163-43d4-b35a-b48aae995f4a","title":"认证系统","description":"authentication-system","extend":"{}","progress_status":"completed","repo_id":"1095f823-f6f5-4e66-9aad-9f0b5b6b99d1","id":"df661133-efbf-43fe-97c3-f581c81f47a7","gmt_create":"2026-04-22T19:09:25.676813+08:00","gmt_modified":"2026-04-24T11:02:17.638458+08:00"},{"catalog_id":"9b71fe02-5927-4a19-8db8-66eb129ecd9a","title":"认证系统前端实现","description":"auth-system-frontend","extend":"{}","progress_status":"completed","repo_id":"1095f823-f6f5-4e66-9aad-9f0b5b6b99d1","id":"2b32ec11-d228-42c0-9232-103ba7e44f71","gmt_create":"2026-04-22T19:09:48.743111+08:00","gmt_modified":"2026-04-22T19:09:48.747746+08:00"},{"catalog_id":"b80dc237-1a6a-401f-9f4d-14190edebcdd","title":"技术栈","description":"technology-stack","extend":"{}","progress_status":"completed","repo_id":"1095f823-f6f5-4e66-9aad-9f0b5b6b99d1","id":"e23bd86e-b4ac-40eb-b1c1-38d929fd5419","gmt_create":"2026-04-22T19:09:54.21211+08:00","gmt_modified":"2026-04-22T19:09:54.216205+08:00"},{"catalog_id":"7e5c3b8e-5aa3-448d-ae52-d5a96a413b0b","title":"表结构设计","description":"table-schema-design","extend":"{}","progress_status":"completed","repo_id":"1095f823-f6f5-4e66-9aad-9f0b5b6b99d1","id":"c3fa653f-8dd7-41fe-8c2e-8b60adbf70f4","gmt_create":"2026-04-22T19:10:23.573187+08:00","gmt_modified":"2026-04-22T19:10:23.576944+08:00"},{"catalog_id":"cc7a1f1b-c70e-4c61-bfbc-6dc408a12ff2","title":"查询执行流程","description":"query-execution-flow","extend":"{}","progress_status":"completed","repo_id":"1095f823-f6f5-4e66-9aad-9f0b5b6b99d1","id":"2fc79486-ec65-4533-860a-89c8877c2ea0","gmt_create":"2026-04-22T19:11:29.34722+08:00","gmt_modified":"2026-04-22T19:11:29.353951+08:00"},{"catalog_id":"fec685a0-c9bb-4048-baf4-40b56b2aa29c","title":"集成测试","description":"integration-testing","extend":"{}","progress_status":"completed","repo_id":"1095f823-f6f5-4e66-9aad-9f0b5b6b99d1","id":"8c17b44f-1586-459b-a83d-c9b961cd2142","gmt_create":"2026-04-22T19:12:37.811472+08:00","gmt_modified":"2026-04-22T19:12:37.820956+08:00"},{"catalog_id":"9fe32b83-3697-4939-8b10-524f5ed3e65e","title":"Kimi平台集成","description":"kimi-platform-integration","extend":"{}","progress_status":"completed","repo_id":"1095f823-f6f5-4e66-9aad-9f0b5b6b99d1","id":"2126339b-b0f5-4152-924b-cbe028cd0c39","gmt_create":"2026-04-22T19:12:57.009145+08:00","gmt_modified":"2026-04-23T20:35:18.737804+08:00"},{"catalog_id":"b10c2334-a850-471a-9851-a1c698e3a485","title":"查询管理接口","description":"queries-api","extend":"{}","progress_status":"completed","repo_id":"1095f823-f6f5-4e66-9aad-9f0b5b6b99d1","id":"74d3018f-4e23-4687-8bf4-7fb403f479f7","gmt_create":"2026-04-22T19:13:13.111099+08:00","gmt_modified":"2026-04-23T20:33:57.632097+08:00"},{"catalog_id":"0c1d3542-92cf-4796-8dba-82caf2f7b361","title":"开发流程","description":"development-workflow","extend":"{}","progress_status":"completed","repo_id":"1095f823-f6f5-4e66-9aad-9f0b5b6b99d1","id":"222a9371-45c1-4e0d-b1da-e8ada1c501c2","gmt_create":"2026-04-22T19:13:23.079488+08:00","gmt_modified":"2026-04-22T19:13:23.082539+08:00"},{"catalog_id":"109a8fb1-6619-4bc7-8481-e28cc2127d24","title":"生产环境部署","description":"production-deployment","extend":"{}","progress_status":"completed","repo_id":"1095f823-f6f5-4e66-9aad-9f0b5b6b99d1","id":"26f80935-eac2-44ee-bcdb-d6a79c537750","gmt_create":"2026-04-22T19:13:58.693673+08:00","gmt_modified":"2026-04-22T19:13:58.69756+08:00"},{"catalog_id":"4d5ac6d7-8812-414b-b8df-68574cc36d7d","title":"配置定制","description":"configuration-customization","extend":"{}","progress_status":"completed","repo_id":"1095f823-f6f5-4e66-9aad-9f0b5b6b99d1","id":"e1e0bd0e-01b3-4543-9781-d9beb32b9a57","gmt_create":"2026-04-22T19:14:17.837895+08:00","gmt_modified":"2026-04-22T19:14:17.84356+08:00"},{"catalog_id":"159f2ccf-71b7-4d1b-a4c4-c15b23a4126e","title":"API接口设计","description":"api-design","extend":"{}","progress_status":"completed","repo_id":"1095f823-f6f5-4e66-9aad-9f0b5b6b99d1","id":"11936bb5-374f-40f4-bb53-b75264fc4b9d","gmt_create":"2026-04-22T19:15:14.073829+08:00","gmt_modified":"2026-04-22T19:15:14.079089+08:00"},{"catalog_id":"9cc59a5a-f597-4707-b994-b6c49514d553","title":"页面组件设计","description":"page-components","extend":"{}","progress_status":"completed","repo_id":"1095f823-f6f5-4e66-9aad-9f0b5b6b99d1","id":"ba0390b3-c249-4e92-a3c8-6820343aeda9","gmt_create":"2026-04-22T19:15:16.958138+08:00","gmt_modified":"2026-04-23T15:19:43.818584+08:00"},{"catalog_id":"f70f5d9b-d7c7-4dc6-b36a-5f4508e6acaa","title":"系统架构","description":"system-architecture","extend":"{}","progress_status":"completed","repo_id":"1095f823-f6f5-4e66-9aad-9f0b5b6b99d1","id":"70b3948e-f456-42d2-b7ad-a0097ad5ee5f","gmt_create":"2026-04-22T19:15:17.448445+08:00","gmt_modified":"2026-04-22T19:15:17.452857+08:00"},{"catalog_id":"816a2805-76c9-4f32-a3cf-96428208081e","title":"数据模型","description":"data-models","extend":"{}","progress_status":"completed","repo_id":"1095f823-f6f5-4e66-9aad-9f0b5b6b99d1","id":"262a3941-fdc6-46b0-b767-be40aa9d5761","gmt_create":"2026-04-22T19:16:35.087998+08:00","gmt_modified":"2026-04-23T15:21:46.785271+08:00"},{"catalog_id":"64cbb894-755f-47b5-854e-c26c7821e9b2","title":"文心平台集成","description":"wenxin-platform-integration","extend":"{}","progress_status":"completed","repo_id":"1095f823-f6f5-4e66-9aad-9f0b5b6b99d1","id":"fab60eaf-9652-4cb5-9f9e-0525caa62d63","gmt_create":"2026-04-22T19:16:36.921828+08:00","gmt_modified":"2026-04-23T20:31:50.506906+08:00"},{"catalog_id":"412f8cb5-54c1-4f32-8966-fa0e5e75bbca","title":"性能优化","description":"performance-optimization","extend":"{}","progress_status":"completed","repo_id":"1095f823-f6f5-4e66-9aad-9f0b5b6b99d1","id":"d8e2cef5-37e6-44e7-8a7b-9bd365b82a72","gmt_create":"2026-04-22T19:16:37.806188+08:00","gmt_modified":"2026-04-22T19:16:37.81795+08:00"},{"catalog_id":"2f7fa0ab-cd3d-4f45-a1c1-389d5a0c2561","title":"开发工具","description":"development-tools","extend":"{}","progress_status":"completed","repo_id":"1095f823-f6f5-4e66-9aad-9f0b5b6b99d1","id":"979be617-a83d-4db9-b73e-38581348f8c1","gmt_create":"2026-04-22T19:17:43.348035+08:00","gmt_modified":"2026-04-22T19:17:43.3539+08:00"},{"catalog_id":"40ac97e8-7ef0-4198-82d7-d2e332be9d34","title":"测试最佳实践","description":"test-best-practices","extend":"{}","progress_status":"completed","repo_id":"1095f823-f6f5-4e66-9aad-9f0b5b6b99d1","id":"05e59a75-d52f-42e1-a924-f6a32f06f2fe","gmt_create":"2026-04-22T19:17:48.811042+08:00","gmt_modified":"2026-04-22T19:17:48.815559+08:00"},{"catalog_id":"41a414d2-e13a-497c-8a03-212624dbf5fe","title":"引用数据接口","description":"citations-api","extend":"{}","progress_status":"completed","repo_id":"1095f823-f6f5-4e66-9aad-9f0b5b6b99d1","id":"737f8d6c-bd8f-4c11-b142-71a400423323","gmt_create":"2026-04-22T19:18:18.048509+08:00","gmt_modified":"2026-04-22T19:18:18.055466+08:00"},{"catalog_id":"2713d5c6-c6b0-4a38-83f6-56940c2bf695","title":"监控与日志管理","description":"monitoring-logging","extend":"{}","progress_status":"completed","repo_id":"1095f823-f6f5-4e66-9aad-9f0b5b6b99d1","id":"eb1288f7-5ea1-413a-8f54-4f870306d14d","gmt_create":"2026-04-22T19:18:41.294736+08:00","gmt_modified":"2026-04-22T19:18:41.773932+08:00"},{"catalog_id":"c8a468af-2982-4d9c-82c0-313b5d2ee89c","title":"第三方集成","description":"third-party-integration","extend":"{}","progress_status":"completed","repo_id":"1095f823-f6f5-4e66-9aad-9f0b5b6b99d1","id":"e9a02c86-236b-49cb-bbed-9462ee123c04","gmt_create":"2026-04-22T19:19:17.34688+08:00","gmt_modified":"2026-04-22T19:19:17.362503+08:00"},{"catalog_id":"9eee7fab-6cd9-4ef3-9415-2f8137f1d199","title":"数据模型设计","description":"data-models","extend":"{}","progress_status":"completed","repo_id":"1095f823-f6f5-4e66-9aad-9f0b5b6b99d1","id":"23ad3419-5473-4e2c-ac87-d9715090279d","gmt_create":"2026-04-22T19:19:19.260533+08:00","gmt_modified":"2026-04-22T19:19:19.282116+08:00"},{"catalog_id":"f210509a-2381-46fe-8c22-0ed768e6ca70","title":"数据库迁移","description":"database-migration","extend":"{}","progress_status":"completed","repo_id":"1095f823-f6f5-4e66-9aad-9f0b5b6b99d1","id":"7c0201f7-9e02-4cba-9ee1-81c3477f049a","gmt_create":"2026-04-22T19:20:15.023549+08:00","gmt_modified":"2026-04-22T19:20:15.06665+08:00"},{"catalog_id":"d9e45b2a-6443-4a9b-8ed3-4c3c04773772","title":"UI组件库","description":"ui-component-library","extend":"{}","progress_status":"completed","repo_id":"1095f823-f6f5-4e66-9aad-9f0b5b6b99d1","id":"760610d4-dff6-4c6d-831f-7c9078db86a6","gmt_create":"2026-04-22T19:20:16.20858+08:00","gmt_modified":"2026-04-23T15:22:23.574113+08:00"},{"catalog_id":"178b681f-d013-44b7-aef8-dee7ca8c22a9","title":"核心功能","description":"core-features","extend":"{}","progress_status":"completed","repo_id":"1095f823-f6f5-4e66-9aad-9f0b5b6b99d1","id":"1c4316a1-f1d7-46da-bcfc-ea2fa0c56110","gmt_create":"2026-04-22T19:20:37.644038+08:00","gmt_modified":"2026-04-22T19:20:37.649918+08:00"},{"catalog_id":"ac0658da-7670-4e41-9e57-02d9d0d50680","title":"报告导出接口","description":"reports-api","extend":"{}","progress_status":"completed","repo_id":"1095f823-f6f5-4e66-9aad-9f0b5b6b99d1","id":"ae62f4a8-8840-4c8e-9a42-3373370299ff","gmt_create":"2026-04-22T19:21:24.241821+08:00","gmt_modified":"2026-04-22T19:21:24.246484+08:00"},{"catalog_id":"aad61788-1dc9-4682-b743-47188d7aecb6","title":"引用检测算法","description":"citation-detection-algorithm","extend":"{}","progress_status":"completed","repo_id":"1095f823-f6f5-4e66-9aad-9f0b5b6b99d1","id":"00359e45-209d-4be3-8795-50dea52bdba1","gmt_create":"2026-04-22T19:21:33.106655+08:00","gmt_modified":"2026-04-22T19:21:33.125906+08:00"},{"catalog_id":"7cb1d921-44ed-4e22-8bf9-baba7ff8b7c7","title":"新功能开发","description":"feature-development","extend":"{}","progress_status":"completed","repo_id":"1095f823-f6f5-4e66-9aad-9f0b5b6b99d1","id":"422c46b3-e69c-4023-a878-411a48ae182f","gmt_create":"2026-04-22T19:21:46.910999+08:00","gmt_modified":"2026-04-22T19:21:46.916175+08:00"},{"catalog_id":"c45e66b9-1ca0-41da-a796-6b98f394faa1","title":"运维最佳实践","description":"maintenance-operations","extend":"{}","progress_status":"completed","repo_id":"1095f823-f6f5-4e66-9aad-9f0b5b6b99d1","id":"aa6db9b6-71e1-4497-a0e2-f3ff25358d3a","gmt_create":"2026-04-22T19:22:39.442855+08:00","gmt_modified":"2026-04-22T19:22:39.447035+08:00"},{"catalog_id":"bfca5ffe-8905-4ac2-a0a3-8e4dc43533b1","title":"数据可视化","description":"data-visualization","extend":"{}","progress_status":"completed","repo_id":"1095f823-f6f5-4e66-9aad-9f0b5b6b99d1","id":"a40267bc-925a-4364-a01f-b96d3df60aea","gmt_create":"2026-04-22T19:23:03.398982+08:00","gmt_modified":"2026-04-22T19:23:03.405853+08:00"},{"catalog_id":"05214c1a-d804-4f3c-9048-20ba4de3be0f","title":"引用检测引擎","description":"citation-engine","extend":"{}","progress_status":"completed","repo_id":"1095f823-f6f5-4e66-9aad-9f0b5b6b99d1","id":"19e75845-5147-4aeb-90be-16f3aa270465","gmt_create":"2026-04-22T19:23:12.049419+08:00","gmt_modified":"2026-04-23T20:33:37.372858+08:00"},{"catalog_id":"b32b024e-2d06-45c8-94c2-a07fd25ab9b3","title":"快速开始","description":"quick-start","extend":"{}","progress_status":"completed","repo_id":"1095f823-f6f5-4e66-9aad-9f0b5b6b99d1","id":"7e679d62-c415-4d6a-a7e5-d41d00e0ed69","gmt_create":"2026-04-22T19:23:49.794133+08:00","gmt_modified":"2026-04-22T19:23:49.797304+08:00"},{"catalog_id":"850fc702-3eb6-45b4-acd2-ae87fec1f4f1","title":"工作器系统","description":"worker-system","extend":"{}","progress_status":"completed","repo_id":"1095f823-f6f5-4e66-9aad-9f0b5b6b99d1","id":"83fe6837-7874-4467-8114-103062f15f58","gmt_create":"2026-04-22T19:24:30.524061+08:00","gmt_modified":"2026-04-22T19:24:30.529283+08:00"},{"catalog_id":"fda0598d-7e92-4b8b-be52-92ae63c3cd98","title":"API客户端","description":"api-client","extend":"{}","progress_status":"completed","repo_id":"1095f823-f6f5-4e66-9aad-9f0b5b6b99d1","id":"7bd2c461-81b0-48e8-8cb3-b4b14305806d","gmt_create":"2026-04-22T19:24:50.482622+08:00","gmt_modified":"2026-04-22T19:24:50.486476+08:00"},{"catalog_id":"15d6170d-716c-4d2a-833d-81211a59027c","title":"平台适配器扩展指南","description":"platform-adapter-extension","extend":"{}","progress_status":"completed","repo_id":"1095f823-f6f5-4e66-9aad-9f0b5b6b99d1","id":"2632a6f9-774e-4a91-94da-a984bdb20758","gmt_create":"2026-04-22T19:25:18.714623+08:00","gmt_modified":"2026-04-22T19:25:18.720105+08:00"},{"catalog_id":"a232faa5-28b0-4235-8ad4-b082fd226e69","title":"订阅管理系统","description":"subscription-management-system","extend":"{}","progress_status":"completed","repo_id":"1095f823-f6f5-4e66-9aad-9f0b5b6b99d1","id":"ec2f1708-d31e-42bb-8959-fa405db7d6da","gmt_create":"2026-04-24T11:04:05.337544+08:00","gmt_modified":"2026-04-24T11:04:05.339776+08:00"},{"catalog_id":"9ac86c99-3b7e-4745-bc95-9586153d616e","title":"管理员仪表板系统","description":"admin-dashboard-system","extend":"{}","progress_status":"completed","repo_id":"1095f823-f6f5-4e66-9aad-9f0b5b6b99d1","id":"2059d1cd-98a3-4b7f-b29b-69acf8a0d751","gmt_create":"2026-04-24T11:06:01.087669+08:00","gmt_modified":"2026-04-24T11:06:01.089977+08:00"},{"catalog_id":"d54446b1-5984-4fe6-8fc1-ad0322ab7914","title":"安全增强功能","description":"security-enhancements","extend":"{}","progress_status":"completed","repo_id":"1095f823-f6f5-4e66-9aad-9f0b5b6b99d1","id":"d474a7a6-e056-4456-ba79-4aedbb7add58","gmt_create":"2026-04-24T11:07:19.926098+08:00","gmt_modified":"2026-04-24T11:07:19.927668+08:00"},{"catalog_id":"d645182f-1eaa-4439-854c-0437806ceebb","title":"PDF报告系统","description":"pdf-reporting-system","extend":"{}","progress_status":"completed","repo_id":"1095f823-f6f5-4e66-9aad-9f0b5b6b99d1","id":"2d7c030d-7b82-418c-9a16-67b067cac93c","gmt_create":"2026-04-24T11:08:42.186525+08:00","gmt_modified":"2026-04-24T11:08:42.188311+08:00"}],"wiki_overview":{"content":"\u003cblog\u003e\n\n# GEO 平台项目全面分析\n\n## 1. 项目介绍\n\n### 目标与愿景\nGEO 平台是一个基于人工智能技术的学术查询与引用管理系统,旨在为用户提供智能化的品牌引用检测和数据分析服务。该项目通过集成多个AI平台,实现对网络内容中特定品牌引用的自动检测和统计分析。\n\n### 核心目标\n- **智能引用检测**:自动识别网络内容中对特定品牌的引用情况\n- **多平台集成**:支持多个AI平台的数据获取和处理\n- **实时监控**:提供定时查询和实时更新功能\n- **数据可视化**:通过图表展示引用趋势和统计数据\n\n### 目标用户\n- 学术研究人员\n- 市场分析师\n- 品牌监测机构\n- 内容创作者\n\n## 2. 技术架构\n\n### 整体架构设计\n\n```mermaid\ngraph TB\n subgraph \"前端层\"\n FE[Next.js 前端]\n UI[React 组件]\n Auth[认证系统]\n end\n \n subgraph \"后端层\"\n API[FastAPI API]\n WS[工作器]\n SCH[调度器]\n end\n \n subgraph \"数据层\"\n DB[(PostgreSQL)]\n RD[Redis 缓存]\n end\n \n subgraph \"AI平台\"\n WX[Wenxin 平台]\n KM[Kimi 平台]\n end\n \n FE --\u003e API\n UI --\u003e FE\n Auth --\u003e FE\n API --\u003e DB\n API --\u003e RD\n WS --\u003e WX\n WS --\u003e KM\n SCH --\u003e WS\n API --\u003e WS\n```\n\n### 核心设计模式\n- **分层架构**:清晰的前后端分离和业务逻辑分层\n- **异步编程**:基于 asyncio 的高性能异步处理\n- **依赖注入**:通过 FastAPI 的依赖系统管理服务\n- **适配器模式**:统一不同AI平台的接口调用\n\n### 系统关系图\n\n```mermaid\nsequenceDiagram\n participant U as 用户\n participant F as 前端\n participant B as 后端API\n participant S as 调度器\n participant W as 引用引擎\n participant P as AI平台\n \n U-\u003e\u003eF: 发起查询请求\n F-\u003e\u003eB: HTTP请求\n B-\u003e\u003eS: 触发查询任务\n S-\u003e\u003eW: 执行查询\n W-\u003e\u003eP: 调用AI平台\n P--\u003e\u003eW: 返回结果\n W--\u003e\u003eB: 处理后的数据\n B--\u003e\u003eF: 响应结果\n F--\u003e\u003eU: 展示数据\n```\n\n## 3. 关键实现\n\n### 主要入口点\n\n**后端主入口**\n- `backend/app/main.py` - FastAPI 应用主入口,包含路由注册和中间件配置\n\n**前端主入口**\n- `frontend/app/layout.tsx` - Next.js 应用布局组件,包含全局样式和提供者配置\n\n### 核心模块\n\n**数据库配置**\n- `backend/app/database.py` - SQLAlchemy 异步数据库配置和会话管理\n\n**配置管理**\n- `backend/app/config.py` - Pydantic 设置类,管理环境变量和配置参数\n\n**工作器系统**\n- `backend/app/workers/scheduler.py` - APScheduler 定时任务调度器\n- `backend/app/workers/citation_engine.py` - 引用检测引擎核心\n\n**API 路由**\n- `backend/app/api/auth.py` - 用户认证相关接口\n- `backend/app/api/citations.py` - 引用数据相关接口\n- `backend/app/api/queries.py` - 查询任务相关接口\n\n### 配置方法\n\n**Docker 配置**\n- `docker-compose.yml` - 多容器部署配置,包含数据库、缓存和应用服务\n\n**依赖管理**\n- `backend/requirements.txt` - Python 后端依赖包\n- `frontend/package.json` - Node.js 前端依赖包\n\n### 外部依赖\n\n**后端关键技术栈**\n- FastAPI + Uvicorn:高性能异步Web框架\n- SQLAlchemy 2.0:异步ORM框架\n- APScheduler:任务调度框架\n- Redis:缓存和队列存储\n- Playwright:浏览器自动化\n\n**前端关键技术栈**\n- Next.js 14:React 框架\n- Radix UI:可访问性UI组件库\n- Recharts:数据可视化图表\n- Tailwind CSS:CSS框架\n\n### 集成点\n\n**AI平台适配**\n- `backend/app/workers/platforms/kimi.py` - Kimi AI平台适配器\n- `backend/app/workers/platforms/wenxin.py` - 百度文心平台适配器\n\n**认证集成**\n- `frontend/components/providers.tsx` - NextAuth.js 认证提供者\n- `frontend/lib/auth.ts` - 前端认证工具函数\n\n### 组件关系图\n\n```mermaid\ngraph LR\n subgraph \"认证模块\"\n AUTH_API[认证API]\n AUTH_FE[认证前端]\n NEXT_AUTH[NextAuth集成]\n end\n \n subgraph \"查询模块\"\n QUERY_API[查询API]\n QUERY_FE[查询前端]\n SCHEDULER[调度器]\n ENGINE[引用引擎]\n end\n \n subgraph \"数据模块\"\n MODELS[数据模型]\n DB[(数据库)]\n REDIS[(Redis)]\n end\n \n AUTH_API --\u003e MODELS\n QUERY_API --\u003e MODELS\n ENGINE --\u003e MODELS\n AUTH_FE --\u003e AUTH_API\n QUERY_FE --\u003e QUERY_API\n SCHEDULER --\u003e ENGINE\n ENGINE --\u003e DB\n ENGINE --\u003e REDIS\n AUTH_API --\u003e DB\n QUERY_API --\u003e DB\n```\n\n## 4. 核心功能\n\n### 功能概览\n\n**用户管理功能**\n- 用户注册和登录认证\n- JWT 令牌管理和会话维护\n- 用户权限控制\n\n**查询管理功能**\n- 自定义关键词查询\n- 多平台AI数据获取\n- 定时任务调度\n- 查询历史记录\n\n**引用检测功能**\n- 品牌引用自动检测\n- 置信度评分算法\n- 竞争品牌识别\n- 文本上下文提取\n\n**数据分析功能**\n- 引用趋势图表\n- 平台对比分析\n- 统计报表生成\n\n### 实现亮点\n\n**智能匹配算法**\n- `backend/app/workers/citation_engine.py` - 实现精确匹配、别名匹配和模糊匹配三种策略\n- 支持中文和英文混合文本处理\n- 提供置信度评分和位置信息\n\n**异步任务处理**\n- `backend/app/workers/scheduler.py` - 基于 APScheduler 的异步任务调度\n- 支持多平台并发查询\n- 完善的任务状态跟踪\n\n**响应式前端界面**\n- `frontend/app/(dashboard)/` - Next.js App Router 页面组织\n- `frontend/components/charts/` - 数据可视化组件\n- `frontend/components/ui/` - 可复用UI组件库\n\n### 功能架构图\n\n```mermaid\nstateDiagram-v2\n [*] --\u003e 用户认证\n 用户认证 --\u003e 查询管理: 登录成功\n 查询管理 --\u003e 任务调度: 创建查询\n 任务调度 --\u003e 引用检测: 定时触发\n 引用检测 --\u003e 数据处理: 获取AI结果\n 数据处理 --\u003e 结果展示: 处理完成\n 结果展示 --\u003e 查询管理: 新查询\n 结果展示 --\u003e [*]: 退出系统\n \n state 查询管理 {\n [*] --\u003e 创建查询\n 创建查询 --\u003e 编辑查询\n 编辑查询 --\u003e 删除查询\n 删除查询 --\u003e [*]\n }\n \n state 引用检测 {\n [*] --\u003e 平台查询\n 平台查询 --\u003e 品牌匹配\n 品牌匹配 --\u003e 竞争检测\n 竞争检测 --\u003e [*]\n }\n```\n\n## 5. 总结与建议\n\n### 项目架构特点\n\n**架构优势**\n- 清晰的分层设计,前后端职责明确\n- 异步编程模型提升了系统性能\n- 模块化设计便于功能扩展和维护\n- 完善的错误处理和日志记录机制\n\n**技术亮点**\n- 基于现代技术栈的全栈开发\n- 智能算法与工程实践的结合\n- 完整的开发到部署流程\n- 良好的代码组织和文档规范\n\n### 改进建议\n\n**性能优化**\n- 考虑引入连接池优化数据库连接\n- 实现缓存策略减少重复查询\n- 添加限流机制防止API滥用\n\n**功能扩展**\n- 增加更多AI平台支持\n- 实现批量查询功能\n- 添加导出数据功能\n- 增强搜索过滤条件\n\n**代码质量**\n- 完善单元测试覆盖率\n- 添加API文档自动生成\n- 实现更详细的错误处理\n- 优化前端组件复用性\n\n### 下一步发展\n\n**短期目标**\n- 完善用户认证和权限系统\n- 优化引用检测算法准确性\n- 增强前端用户体验\n\n**长期规划**\n- 支持多语言和国际化\n- 实现移动端应用\n- 添加机器学习模型优化\n- 构建开发者API平台\n\nSources:\n- [main.py](backend/app/main.py)\n- [config.py](backend/app/config.py)\n- [database.py](backend/app/database.py)\n- [layout.tsx](frontend/app/layout.tsx)\n- [providers.tsx](frontend/components/providers.tsx)\n- [scheduler.py](backend/app/workers/scheduler.py)\n- [citation_engine.py](backend/app/workers/citation_engine.py)\n- [auth.py](backend/app/api/auth.py)\n- [docker-compose.yml](docker-compose.yml)\n- [requirements.txt](backend/requirements.txt)\n- [package.json](frontend/package.json)\n\n\u003c/blog\u003e","gmt_create":"2026-04-22T18:54:45.079999+08:00","gmt_modified":"2026-04-22T18:54:45.079999+08:00","id":"1e2d007d-9249-436e-8822-c9b1a31580d1","repo_id":"1095f823-f6f5-4e66-9aad-9f0b5b6b99d1"},"wiki_readme":{"content":"No readme file","gmt_create":"2026-04-22T18:53:55.057287+08:00","gmt_modified":"2026-04-22T18:53:55.057287+08:00","id":"354aa9f0-35fb-44a7-98d6-034981f130e6","repo_id":"1095f823-f6f5-4e66-9aad-9f0b5b6b99d1"},"wiki_repo":{"id":"1095f823-f6f5-4e66-9aad-9f0b5b6b99d1","name":"GEO","progress_status":"completed","wiki_present_status":"COMPLETED","optimized_catalog":"\".\\n├── .npm-cache/\\n│ ├── _cacache/\\n│ ├── _logs/\\n│ └── _npx/\\n├── .pytest_cache/\\n├── backend/\\n│ ├── alembic/\\n│ │ ├── __pycache__/\\n│ │ ├── versions/\\n│ │ │ ├── __pycache__/\\n│ │ │ └── 488d0bd5ab01_initial_migration.py\\n│ │ ├── README\\n│ │ ├── env.py\\n│ │ └── script.py.mako\\n│ ├── app/\\n│ │ ├── __pycache__/\\n│ │ ├── api/\\n│ │ │ ├── __pycache__/\\n│ │ │ ├── __init__.py\\n│ │ │ ├── auth.py\\n│ │ │ ├── citations.py\\n│ │ │ ├── deps.py\\n│ │ │ ├── queries.py\\n│ │ │ └── reports.py\\n│ │ ├── models/\\n│ │ │ ├── __pycache__/\\n│ │ │ ├── __init__.py\\n│ │ │ ├── citation_record.py\\n│ │ │ ├── query.py\\n│ │ │ ├── query_task.py\\n│ │ │ ├── subscription.py\\n│ │ │ └── user.py\\n│ │ ├── schemas/\\n│ │ │ ├── __pycache__/\\n│ │ │ ├── auth.py\\n│ │ │ ├── citation.py\\n│ │ │ └── query.py\\n│ │ ├── services/\\n│ │ │ ├── __pycache__/\\n│ │ │ ├── auth.py\\n│ │ │ ├── citation.py\\n│ │ │ └── query.py\\n│ │ ├── utils/\\n│ │ ├── workers/\\n│ │ │ ├── __pycache__/\\n│ │ │ ├── platforms/\\n│ │ │ │ ├── __pycache__/\\n│ │ │ │ ├── base.py\\n│ │ │ │ ├── kimi.py\\n│ │ │ │ └── wenxin.py\\n│ │ │ ├── __init__.py\\n│ │ │ ├── citation_engine.py\\n│ │ │ └── scheduler.py\\n│ │ ├── config.py\\n│ │ ├── database.py\\n│ │ └── main.py\\n│ ├── venv/\\n│ ├── Dockerfile\\n│ ├── alembic.ini\\n│ └── requirements.txt\\n├── docs/\\n├── frontend/\\n│ ├── .next/\\n│ ├── app/\\n│ │ ├── (auth)/\\n│ │ │ ├── login/\\n│ │ │ │ └── page.tsx\\n│ │ │ ├── register/\\n│ │ │ │ └── page.tsx\\n│ │ │ └── layout.tsx\\n│ │ ├── (dashboard)/\\n│ │ │ ├── dashboard/\\n│ │ │ │ ├── citations/\\n│ │ │ │ │ └── page.tsx\\n│ │ │ │ ├── queries/\\n│ │ │ │ │ └── page.tsx\\n│ │ │ │ ├── reports/\\n│ │ │ │ │ └── page.tsx\\n│ │ │ │ ├── settings/\\n│ │ │ │ │ └── page.tsx\\n│ │ │ │ └── page.tsx\\n│ │ │ └── layout.tsx\\n│ │ ├── api/auth/[...nextauth]/\\n│ │ │ └── route.ts\\n│ │ ├── fonts/\\n│ │ ├── globals.css\\n│ │ ├── layout.tsx\\n│ │ └── page.tsx\\n│ ├── components/\\n│ │ ├── charts/\\n│ │ │ ├── platform-chart.tsx\\n│ │ │ └── trend-chart.tsx\\n│ │ ├── layout/\\n│ │ │ ├── header.tsx\\n│ │ │ └── sidebar.tsx\\n│ │ ├── ui/\\n│ │ │ ├── badge.tsx\\n│ │ │ ├── button.tsx\\n│ │ │ ├── card.tsx\\n│ │ │ ├── dialog.tsx\\n│ │ │ ├── dropdown-menu.tsx\\n│ │ │ ├── input.tsx\\n│ │ │ ├── label.tsx\\n│ │ │ ├── select.tsx\\n│ │ │ ├── table.tsx\\n│ │ │ └── tabs.tsx\\n│ │ └── providers.tsx\\n│ ├── lib/\\n│ │ ├── api.ts\\n│ │ ├── auth.ts\\n│ │ ├── platforms.ts\\n│ │ └── utils.ts\\n│ ├── node_modules/\\n│ ├── types/\\n│ │ └── next-auth.d.ts\\n│ ├── .eslintrc.json\\n│ ├── .gitignore\\n│ ├── Dockerfile\\n│ ├── README.md\\n│ ├── next-env.d.ts\\n│ ├── next.config.mjs\\n│ ├── package-lock.json\\n│ ├── package.json\\n│ ├── postcss.config.mjs\\n│ ├── tailwind.config.ts\\n│ ├── tsconfig.json\\n│ └── tsconfig.tsbuildinfo\\n├── tests/\\n│ ├── __pycache__/\\n│ ├── conftest.py\\n│ ├── test_auth.py\\n│ ├── test_citation_engine.py\\n│ ├── test_citations.py\\n│ └── test_queries.py\\n└── docker-compose.yml\\n\"","current_document_structure":"WikiEncrypted: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","catalogue_think_content":"WikiEncrypted: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","recovery_checkpoint":"wiki_generation_completed","last_commit_id":"47879a11f762e40ad2bc967aba5ae76752a794ed","last_commit_update":"2026-04-24T11:08:43.103258+08:00","gmt_create":"2026-04-22T17:58:32.591608+08:00","gmt_modified":"2026-04-24T11:08:43.103259+08:00","extend_info":"{\"language\":\"zh\",\"active\":true,\"branch\":\"main\",\"shareStatus\":\"\",\"server_error_code\":\"\",\"cosy_version\":\"\"}"}} \ No newline at end of file +{"code_snippets":[{"id":"8a466b0c6eac2ccb54c5da7e13854646","path":"frontend/app/layout.tsx","line_range":"1-37","gmt_create":"2026-04-23T15:19:43.759937+08:00","gmt_modified":"2026-04-23T15:19:43.759937+08:00"},{"id":"3bd4eedea376e3a3d9f9fbff4fe27a65","path":"frontend/components/layout/sidebar.tsx","line_range":"1-54","gmt_create":"2026-04-23T15:19:43.760535+08:00","gmt_modified":"2026-04-23T15:19:43.760535+08:00"},{"id":"0d903468b55bdc63cc7e25a87a89c522","path":"frontend/components/layout/header.tsx","line_range":"1-30","gmt_create":"2026-04-23T15:19:43.760868+08:00","gmt_modified":"2026-04-23T15:19:43.760868+08:00"},{"id":"3bab92a09e9fb456e0303bb1e04afc7e","path":"frontend/components/ui/table.tsx","line_range":"1-118","gmt_create":"2026-04-23T15:19:43.762327+08:00","gmt_modified":"2026-04-23T15:19:43.762327+08:00"},{"id":"0eed9f61572209dd754611fc7c690d5a","path":"frontend/components/ui/dialog.tsx","line_range":"1-123","gmt_create":"2026-04-23T15:19:43.762637+08:00","gmt_modified":"2026-04-23T15:19:43.762637+08:00"},{"id":"b7796fc6197ecce5beb461b9466e54a0","path":"frontend/components/charts/trend-chart.tsx","line_range":"1-60","gmt_create":"2026-04-23T15:19:43.762953+08:00","gmt_modified":"2026-04-23T15:19:43.762953+08:00"},{"id":"6b9f52af0b6d78c17ff9bbc42d760ea2","path":"frontend/components/charts/platform-chart.tsx","line_range":"1-68","gmt_create":"2026-04-23T15:19:43.763292+08:00","gmt_modified":"2026-04-23T15:19:43.763292+08:00"},{"id":"a829403082cc3460c01e0110229c53c4","path":"frontend/lib/platforms.ts","line_range":"1-18","gmt_create":"2026-04-23T15:19:43.763596+08:00","gmt_modified":"2026-04-23T15:19:43.763596+08:00"},{"id":"dcfa308ef4ec368c5a51a17acbfc8e2c","path":"frontend/lib/utils.ts","line_range":"1-7","gmt_create":"2026-04-23T15:19:43.763899+08:00","gmt_modified":"2026-04-23T15:19:43.763899+08:00"},{"id":"0f87c8089f548883d056f0a0d79e273f","path":"frontend/lib/api.ts","line_range":"1-79","gmt_create":"2026-04-23T15:19:43.764207+08:00","gmt_modified":"2026-04-23T15:19:43.764207+08:00"},{"id":"9beee1f41fe8f0750fd97155f9d54bbb","path":"frontend/lib/api.ts","line_range":"67-70","gmt_create":"2026-04-23T15:19:43.7681+08:00","gmt_modified":"2026-04-23T15:19:43.7681+08:00"},{"id":"8fe2e22a963442076e1ce16ab777573c","path":"frontend/lib/api.ts","line_range":"56-66","gmt_create":"2026-04-23T15:19:43.769967+08:00","gmt_modified":"2026-04-23T15:19:43.769967+08:00"},{"id":"3124ad882ca2cf8fecb6b93696c7f233","path":"frontend/lib/api.ts","line_range":"72-77","gmt_create":"2026-04-23T15:19:43.77323+08:00","gmt_modified":"2026-04-23T15:19:43.773231+08:00"},{"id":"17a97b4ac37fb67b8eda7ce2887c38e7","path":"frontend/app/layout.tsx","line_range":"17-20","gmt_create":"2026-04-23T15:19:43.777372+08:00","gmt_modified":"2026-04-23T15:19:43.777372+08:00"},{"id":"84cba1e0d516e8c9859402fd5c1bc83c","path":"frontend/lib/api.ts","line_range":"3-40","gmt_create":"2026-04-23T15:19:43.777696+08:00","gmt_modified":"2026-04-23T15:19:43.777696+08:00"},{"id":"b55a164add5a8fec2ef0e489f7234829","path":"backend/app/main.py","line_range":"24-47","gmt_create":"2026-04-23T15:19:45.591156+08:00","gmt_modified":"2026-04-23T15:19:45.591157+08:00"},{"id":"ae9de874df4a46f4197b6c157c25ec6e","path":"backend/app/api/queries.py","line_range":"15-85","gmt_create":"2026-04-23T15:19:45.594458+08:00","gmt_modified":"2026-04-23T15:19:45.594458+08:00"},{"id":"c066a8d4bffabed87a2e38ccad81c107","path":"backend/app/api/citations.py","line_range":"25-77","gmt_create":"2026-04-23T15:19:45.594783+08:00","gmt_modified":"2026-04-23T15:19:45.594783+08:00"},{"id":"177c73dc4e71186d9eaa1157fc0fe97f","path":"backend/app/api/reports.py","line_range":"16-46","gmt_create":"2026-04-23T15:19:45.595098+08:00","gmt_modified":"2026-04-23T15:19:45.595098+08:00"},{"id":"bcdf50f6234651cb9863ab210e6473e5","path":"backend/app/api/deps.py","line_range":"16-42","gmt_create":"2026-04-23T15:19:45.595733+08:00","gmt_modified":"2026-04-23T15:19:45.595733+08:00"},{"id":"6df0277c2486b148fa26c2682dbdaa4c","path":"backend/app/services/auth.py","line_range":"37-68","gmt_create":"2026-04-23T15:19:45.59605+08:00","gmt_modified":"2026-04-23T15:19:45.59605+08:00"},{"id":"5ea5f192d580031ffe57e1582b70c67e","path":"backend/app/services/query.py","line_range":"12-123","gmt_create":"2026-04-23T15:19:45.596359+08:00","gmt_modified":"2026-04-23T15:19:45.596359+08:00"},{"id":"fe4a793f16cd4e12b56253c0a6d53ae0","path":"backend/app/services/citation.py","line_range":"24-359","gmt_create":"2026-04-23T15:19:45.596722+08:00","gmt_modified":"2026-04-23T15:19:45.596723+08:00"},{"id":"9552bd8a528207f18e4f3a1696f26a55","path":"backend/app/api/auth.py","line_range":"13-37","gmt_create":"2026-04-23T15:19:45.597032+08:00","gmt_modified":"2026-04-23T15:19:45.597032+08:00"},{"id":"4aad38dfc00a0877bd965c3d0b3c280c","path":"backend/app/schemas/auth.py","line_range":"7-34","gmt_create":"2026-04-23T15:19:45.598915+08:00","gmt_modified":"2026-04-23T15:19:45.598915+08:00"},{"id":"9b10dac7dbbb1327afc8a525bf4bd0c3","path":"backend/app/services/query.py","line_range":"45-81","gmt_create":"2026-04-23T15:19:45.599689+08:00","gmt_modified":"2026-04-23T15:19:45.599689+08:00"},{"id":"69118807690ef351a9de910414d5e676","path":"backend/app/schemas/query.py","line_range":"11-94","gmt_create":"2026-04-23T15:19:45.6004+08:00","gmt_modified":"2026-04-23T15:19:45.6004+08:00"},{"id":"212d822d207a4c0bd7825bbf20e188e9","path":"backend/app/api/citations.py","line_range":"59-77","gmt_create":"2026-04-23T15:19:45.601069+08:00","gmt_modified":"2026-04-23T15:19:45.601069+08:00"},{"id":"b0777c7da17be89abb333c81c0dcf349","path":"backend/app/services/citation.py","line_range":"204-261","gmt_create":"2026-04-23T15:19:45.601383+08:00","gmt_modified":"2026-04-23T15:19:45.601384+08:00"},{"id":"26288877e8e1f6c4ff5aca12610b0218","path":"backend/app/schemas/citation.py","line_range":"7-50","gmt_create":"2026-04-23T15:19:45.602042+08:00","gmt_modified":"2026-04-23T15:19:45.602042+08:00"},{"id":"56e46969bdb790a5e8f333184b878d6d","path":"backend/app/models/user.py","line_range":"11-41","gmt_create":"2026-04-23T15:19:45.605045+08:00","gmt_modified":"2026-04-23T15:19:45.605046+08:00"},{"id":"4fb8856be3a581fe8303d11b2284ca29","path":"backend/app/models/query.py","line_range":"11-55","gmt_create":"2026-04-23T15:19:45.605965+08:00","gmt_modified":"2026-04-23T15:19:45.605965+08:00"},{"id":"fd541971cebf8a7c167d717f5c5d1ff6","path":"backend/app/models/citation_record.py","line_range":"11-42","gmt_create":"2026-04-23T15:19:45.606627+08:00","gmt_modified":"2026-04-23T15:19:45.606627+08:00"},{"id":"b84f46f058847733347974841f613688","path":"backend/app/models/query_task.py","line_range":"11-39","gmt_create":"2026-04-23T15:19:45.607023+08:00","gmt_modified":"2026-04-23T15:19:45.607023+08:00"},{"id":"1a2657244414b5681afded9565a86422","path":"backend/app/models/user.py","line_range":"35-40","gmt_create":"2026-04-23T15:19:45.60817+08:00","gmt_modified":"2026-04-23T15:19:45.60817+08:00"},{"id":"acd5a29be2bdd4ae251e10ca266ffe13","path":"backend/app/models/query.py","line_range":"43-48","gmt_create":"2026-04-23T15:19:45.608565+08:00","gmt_modified":"2026-04-23T15:19:45.608565+08:00"},{"id":"27a5e2dd1d197b2e3a45be41c57a6183","path":"backend/app/models/citation_record.py","line_range":"35","gmt_create":"2026-04-23T15:19:45.609141+08:00","gmt_modified":"2026-04-23T15:19:45.609141+08:00"},{"id":"c43e8fc0c04c5ed2db7798d99c8c77b8","path":"backend/app/models/query_task.py","line_range":"34","gmt_create":"2026-04-23T15:19:45.609534+08:00","gmt_modified":"2026-04-23T15:19:45.609534+08:00"},{"id":"a50f983ec39bac67dff5df80f6dad837","path":"backend/app/services/query.py","line_range":"59-60","gmt_create":"2026-04-23T15:19:45.61019+08:00","gmt_modified":"2026-04-23T15:19:45.61019+08:00"},{"id":"55f1628f1ab6f323710e367e12146b1a","path":"backend/app/api/citations.py","line_range":"67-71","gmt_create":"2026-04-23T15:19:45.610496+08:00","gmt_modified":"2026-04-23T15:19:45.610496+08:00"},{"id":"096856da621e23e78422a15e2bfce1f1","path":"backend/app/main.py","line_range":"13-22","gmt_create":"2026-04-23T15:20:08.95664+08:00","gmt_modified":"2026-04-23T15:20:08.95664+08:00"},{"id":"e230904202fcf7a861c6f49b84f9f863","path":"backend/app/workers/scheduler.py","line_range":"25-95","gmt_create":"2026-04-23T15:20:08.956979+08:00","gmt_modified":"2026-04-23T15:20:08.956979+08:00"},{"id":"309607c54b12a6340edc086ffb4737c9","path":"backend/app/workers/citation_engine.py","line_range":"148-309","gmt_create":"2026-04-23T15:20:08.957311+08:00","gmt_modified":"2026-04-23T15:20:08.957311+08:00"},{"id":"d7c319a04abbc6704da53107e07dd8e7","path":"backend/app/services/query.py","line_range":"12-130","gmt_create":"2026-04-23T15:20:08.958773+08:00","gmt_modified":"2026-04-23T15:20:08.958773+08:00"},{"id":"9bfc041fe426da2eb78353827e8d9163","path":"backend/app/database.py","line_range":"1-29","gmt_create":"2026-04-23T15:20:08.95909+08:00","gmt_modified":"2026-04-23T15:20:08.95909+08:00"},{"id":"ad67863041d9eea2b0fb542b5aa33aca","path":"backend/app/workers/platforms/base.py","line_range":"4-18","gmt_create":"2026-04-23T15:20:08.959413+08:00","gmt_modified":"2026-04-23T15:20:08.959413+08:00"},{"id":"eecf9581dbaa0a515cf11514175e7ef9","path":"backend/app/workers/platforms/kimi.py","line_range":"11-206","gmt_create":"2026-04-23T15:20:08.959726+08:00","gmt_modified":"2026-04-23T15:20:08.959726+08:00"},{"id":"5563c29185326a59be61ee0a6eec4463","path":"backend/app/workers/platforms/wenxin.py","line_range":"11-205","gmt_create":"2026-04-23T15:20:08.960155+08:00","gmt_modified":"2026-04-23T15:20:08.960155+08:00"},{"id":"2d35e1345d25020f8e7ac1318db06f7b","path":"backend/app/workers/scheduler.py","line_range":"30-90","gmt_create":"2026-04-23T15:20:08.96886+08:00","gmt_modified":"2026-04-23T15:20:08.968861+08:00"},{"id":"91bda120c0ab69e0e7103a1c89c82424","path":"backend/app/workers/scheduler.py","line_range":"95-172","gmt_create":"2026-04-23T15:20:08.969219+08:00","gmt_modified":"2026-04-23T15:20:08.969219+08:00"},{"id":"160b5326537d25444c40a459a01e79c6","path":"backend/app/workers/citation_engine.py","line_range":"159-234","gmt_create":"2026-04-23T15:20:08.969565+08:00","gmt_modified":"2026-04-23T15:20:08.969565+08:00"},{"id":"6712051c987e10a7c26b089063367398","path":"backend/app/models/query.py","line_range":"24-31","gmt_create":"2026-04-23T15:20:08.970051+08:00","gmt_modified":"2026-04-23T15:20:08.970052+08:00"},{"id":"ac5982063da5f04315f3e82a0d653902","path":"backend/app/models/query_task.py","line_range":"24-32","gmt_create":"2026-04-23T15:20:08.970717+08:00","gmt_modified":"2026-04-23T15:20:08.970717+08:00"},{"id":"06ed912983db33bb8aca162fed68282b","path":"backend/app/models/citation_record.py","line_range":"24-29","gmt_create":"2026-04-23T15:20:08.971135+08:00","gmt_modified":"2026-04-23T15:20:08.971135+08:00"},{"id":"b624be78e3bffd876e403cff2557b088","path":"backend/app/workers/citation_engine.py","line_range":"19-120","gmt_create":"2026-04-23T15:20:08.973448+08:00","gmt_modified":"2026-04-23T15:20:08.973448+08:00"},{"id":"40d0b169aad65c8bb38077deb052fc72","path":"backend/app/workers/platforms/kimi.py","line_range":"33-125","gmt_create":"2026-04-23T15:20:08.97414+08:00","gmt_modified":"2026-04-23T15:20:08.97414+08:00"},{"id":"8b5af998852596e1e08b0e0216bc4b93","path":"backend/app/workers/platforms/wenxin.py","line_range":"33-124","gmt_create":"2026-04-23T15:20:08.974449+08:00","gmt_modified":"2026-04-23T15:20:08.974449+08:00"},{"id":"fe70b1fef9f36e73d26d84987e927c7a","path":"backend/app/api/queries.py","line_range":"15-86","gmt_create":"2026-04-23T15:20:08.978743+08:00","gmt_modified":"2026-04-23T15:20:08.978743+08:00"},{"id":"e1d2b027678118df4d0a50ce9269271d","path":"backend/app/workers/scheduler.py","line_range":"42-90","gmt_create":"2026-04-23T15:20:08.982815+08:00","gmt_modified":"2026-04-23T15:20:08.982815+08:00"},{"id":"e79301a4bc26aa6b49f3f52c3182c3f9","path":"backend/app/workers/citation_engine.py","line_range":"175-234","gmt_create":"2026-04-23T15:20:08.983609+08:00","gmt_modified":"2026-04-23T15:20:08.983609+08:00"},{"id":"1e85186eded8743ff5f231df4aa6df3f","path":"backend/app/workers/platforms/kimi.py","line_range":"21-48","gmt_create":"2026-04-23T15:20:08.98454+08:00","gmt_modified":"2026-04-23T15:20:08.98454+08:00"},{"id":"e2b1718570fb714b2f4342221898ab30","path":"backend/app/workers/platforms/wenxin.py","line_range":"21-48","gmt_create":"2026-04-23T15:20:08.985237+08:00","gmt_modified":"2026-04-23T15:20:08.985237+08:00"},{"id":"e4a49039dae40b7433896c81737fcf8c","path":"backend/app/config.py","line_range":"7-14","gmt_create":"2026-04-23T15:20:08.985763+08:00","gmt_modified":"2026-04-23T15:20:08.985763+08:00"},{"id":"2ee31d68c409e96e951f6cfa7027bca7","path":"backend/app/main.py","line_range":"24-42","gmt_create":"2026-04-23T15:20:08.986265+08:00","gmt_modified":"2026-04-23T15:20:08.986265+08:00"},{"id":"79d6e169e36e6b7493898b5f863e07dc","path":"backend/app/workers/citation_engine.py","line_range":"152-157","gmt_create":"2026-04-23T15:20:08.987693+08:00","gmt_modified":"2026-04-23T15:20:08.987693+08:00"},{"id":"1552315d5fb9f6d7aba5f7e8fa93a975","path":"backend/app/database.py","line_range":"6-10","gmt_create":"2026-04-23T15:20:08.988709+08:00","gmt_modified":"2026-04-23T15:20:08.988709+08:00"},{"id":"599cca7536cae4a7e0ae93043c476a7f","path":"tests/test_queries.py","line_range":"10-154","gmt_create":"2026-04-23T15:20:08.989011+08:00","gmt_modified":"2026-04-23T15:20:08.989011+08:00"},{"id":"2ec3d45edd6221e0cedf7f8887fe090d","path":"tests/test_scheduler.py","line_range":"17-123","gmt_create":"2026-04-23T15:20:08.989312+08:00","gmt_modified":"2026-04-23T15:20:08.989312+08:00"},{"id":"4d323bf0aaf4078f09726dc0890e5955","path":"backend/app/models/subscription.py","line_range":"11-37","gmt_create":"2026-04-23T15:21:46.688165+08:00","gmt_modified":"2026-04-23T15:21:46.688166+08:00"},{"id":"4cef9e740b6feb68c6bd22b660c47320","path":"backend/app/services/query.py","line_range":"1-123","gmt_create":"2026-04-23T15:21:46.688903+08:00","gmt_modified":"2026-04-23T15:21:46.688903+08:00"},{"id":"121203f7f9f539ffb1456c3f5cdfd842","path":"backend/app/services/citation.py","line_range":"1-359","gmt_create":"2026-04-23T15:21:46.689338+08:00","gmt_modified":"2026-04-23T15:21:46.689338+08:00"},{"id":"10d1e37bdc9f353c189b7a2fe79dc85e","path":"backend/app/api/queries.py","line_range":"1-86","gmt_create":"2026-04-23T15:21:46.689691+08:00","gmt_modified":"2026-04-23T15:21:46.689691+08:00"},{"id":"cbd0101fa84d957bcb1baaa623c6b31c","path":"backend/app/api/citations.py","line_range":"1-78","gmt_create":"2026-04-23T15:21:46.690036+08:00","gmt_modified":"2026-04-23T15:21:46.690036+08:00"},{"id":"afe4138895492c26aac5c0120ef46cd8","path":"backend/app/models/__init__.py","line_range":"1-14","gmt_create":"2026-04-23T15:21:46.69035+08:00","gmt_modified":"2026-04-23T15:21:46.69035+08:00"},{"id":"4d11ddf7abb8076d81b30c4315786f9a","path":"backend/alembic/versions/488d0bd5ab01_initial_migration.py","line_range":"21-128","gmt_create":"2026-04-23T15:21:46.693035+08:00","gmt_modified":"2026-04-23T15:21:46.693035+08:00"},{"id":"e454b4a54500bd81e7599e6ec97bf12b","path":"backend/alembic/versions/488d0bd5ab01_initial_migration.py","line_range":"23-37","gmt_create":"2026-04-23T15:21:46.695671+08:00","gmt_modified":"2026-04-23T15:21:46.695671+08:00"},{"id":"1965adf7cfc65447e3c1ae21fbf6d1c5","path":"backend/alembic/versions/488d0bd5ab01_initial_migration.py","line_range":"39-59","gmt_create":"2026-04-23T15:21:46.696432+08:00","gmt_modified":"2026-04-23T15:21:46.696432+08:00"},{"id":"c730faefb34bb87c40c5f636b4ff7f41","path":"backend/alembic/versions/488d0bd5ab01_initial_migration.py","line_range":"80-94","gmt_create":"2026-04-23T15:21:46.697413+08:00","gmt_modified":"2026-04-23T15:21:46.697413+08:00"},{"id":"b9978c3eccea3ef566b003216e5047af","path":"backend/alembic/versions/488d0bd5ab01_initial_migration.py","line_range":"61-78","gmt_create":"2026-04-23T15:21:46.698274+08:00","gmt_modified":"2026-04-23T15:21:46.698274+08:00"},{"id":"eb6ff4361d7413b57f1f70b1ec2f0c94","path":"backend/alembic/versions/488d0bd5ab01_initial_migration.py","line_range":"96-111","gmt_create":"2026-04-23T15:21:46.699021+08:00","gmt_modified":"2026-04-23T15:21:46.699021+08:00"},{"id":"f6c9f1b4e8646c366a31426a4537675d","path":"backend/app/models/query_task.py","line_range":"36-38","gmt_create":"2026-04-23T15:21:46.700462+08:00","gmt_modified":"2026-04-23T15:21:46.700462+08:00"},{"id":"a2adbf02c71e4eb2cf1f120e1a2ff517","path":"backend/app/models/citation_record.py","line_range":"37-41","gmt_create":"2026-04-23T15:21:46.70082+08:00","gmt_modified":"2026-04-23T15:21:46.700821+08:00"},{"id":"0907fc2974ec31c23aaaef02076700a1","path":"backend/app/models/user.py","line_range":"25-33","gmt_create":"2026-04-23T15:21:46.702342+08:00","gmt_modified":"2026-04-23T15:21:46.702342+08:00"},{"id":"842f74e2cc054608242e93fbefd96b45","path":"backend/app/models/query.py","line_range":"32-40","gmt_create":"2026-04-23T15:21:46.702652+08:00","gmt_modified":"2026-04-23T15:21:46.702652+08:00"},{"id":"aed9e839038c45e6ce2023c4e05adb76","path":"backend/app/models/query_task.py","line_range":"27-32","gmt_create":"2026-04-23T15:21:46.702999+08:00","gmt_modified":"2026-04-23T15:21:46.703+08:00"},{"id":"2181318c993526c86458f5eef134aed6","path":"backend/app/services/query.py","line_range":"62-77","gmt_create":"2026-04-23T15:21:46.703419+08:00","gmt_modified":"2026-04-23T15:21:46.703419+08:00"},{"id":"a817488dc968d761a8977fb5bb8d01a2","path":"backend/app/services/query.py","line_range":"45-129","gmt_create":"2026-04-23T15:21:46.703795+08:00","gmt_modified":"2026-04-23T15:21:46.703795+08:00"},{"id":"d20fc729a5d3986b1c077f9e07ece9c4","path":"backend/app/config.py","line_range":"7","gmt_create":"2026-04-23T15:21:46.704958+08:00","gmt_modified":"2026-04-23T15:21:46.704958+08:00"},{"id":"ea655c6d147bc98beb42955d437260cc","path":"backend/app/config.py","line_range":"1-23","gmt_create":"2026-04-23T15:21:46.705746+08:00","gmt_modified":"2026-04-23T15:21:46.705746+08:00"},{"id":"37868a5af96edcdad149caf9a184435a","path":"backend/app/api/queries.py","line_range":"42-85","gmt_create":"2026-04-23T15:21:46.706426+08:00","gmt_modified":"2026-04-23T15:21:46.706426+08:00"},{"id":"601b981b00d93b941843f046a163d5a3","path":"backend/app/schemas/query.py","line_range":"18-33","gmt_create":"2026-04-23T15:21:46.706755+08:00","gmt_modified":"2026-04-23T15:21:46.706755+08:00"},{"id":"290df8332b3d104e5ea8d71dc39315b5","path":"tests/conftest.py","line_range":"1-123","gmt_create":"2026-04-23T15:22:15.985975+08:00","gmt_modified":"2026-04-23T15:22:15.985975+08:00"},{"id":"c2747ca16b879bca0f68955534c3c4fc","path":"backend/app/main.py","line_range":"1-48","gmt_create":"2026-04-23T15:22:15.986592+08:00","gmt_modified":"2026-04-23T15:22:15.986592+08:00"},{"id":"76e6c0abb49fec57cac4892837a143c9","path":"backend/app/api/deps.py","line_range":"1-43","gmt_create":"2026-04-23T15:22:15.987077+08:00","gmt_modified":"2026-04-23T15:22:15.987077+08:00"},{"id":"f66d9907b467b110c638bd527efd95c5","path":"backend/app/api/auth.py","line_range":"1-43","gmt_create":"2026-04-23T15:22:15.987417+08:00","gmt_modified":"2026-04-23T15:22:15.987417+08:00"},{"id":"116584ea9162c1bc05911f39f9ef82b6","path":"backend/app/workers/citation_engine.py","line_range":"1-309","gmt_create":"2026-04-23T15:22:15.988451+08:00","gmt_modified":"2026-04-23T15:22:15.988451+08:00"},{"id":"9630036e63fc15cb81b202cf79671aab","path":"backend/app/workers/scheduler.py","line_range":"1-182","gmt_create":"2026-04-23T15:22:15.988885+08:00","gmt_modified":"2026-04-23T15:22:15.988885+08:00"},{"id":"84fbed7d35f7752e2117a74fcaf5f0e9","path":"backend/app/config.py","line_range":"1-17","gmt_create":"2026-04-23T15:22:15.989594+08:00","gmt_modified":"2026-04-23T15:22:15.989594+08:00"},{"id":"5ddf0c8d7b38e4f6126a5d85da1dfeda","path":"tests/conftest.py","line_range":"19-123","gmt_create":"2026-04-23T15:22:15.990689+08:00","gmt_modified":"2026-04-23T15:22:15.990689+08:00"},{"id":"9df233ef1be4b95068ed91bf01083ae7","path":"tests/conftest.py","line_range":"117-123","gmt_create":"2026-04-23T15:22:15.99106+08:00","gmt_modified":"2026-04-23T15:22:15.99106+08:00"},{"id":"6286d4be455dc058c8be2ee4e0d1175a","path":"backend/app/main.py","line_range":"38-42","gmt_create":"2026-04-23T15:22:15.991399+08:00","gmt_modified":"2026-04-23T15:22:15.991399+08:00"},{"id":"069243fafe60a85cf16a0ca40fa07180","path":"backend/app/api/deps.py","line_range":"16-43","gmt_create":"2026-04-23T15:22:15.991722+08:00","gmt_modified":"2026-04-23T15:22:15.991722+08:00"},{"id":"d5a1fb0bd23ce9240fbf79529ef94a45","path":"backend/app/api/auth.py","line_range":"13-43","gmt_create":"2026-04-23T15:22:15.992045+08:00","gmt_modified":"2026-04-23T15:22:15.992045+08:00"},{"id":"735aef72b4fe6ca4f407e69b7dda8b43","path":"backend/app/api/citations.py","line_range":"25-78","gmt_create":"2026-04-23T15:22:15.992721+08:00","gmt_modified":"2026-04-23T15:22:15.992721+08:00"},{"id":"8128dd67cf376d2cadf7c2d3831c380a","path":"backend/app/database.py","line_range":"23-29","gmt_create":"2026-04-23T15:22:15.993159+08:00","gmt_modified":"2026-04-23T15:22:15.993159+08:00"},{"id":"1721defc3d6206478d3c0692cc821761","path":"tests/test_auth.py","line_range":"25-104","gmt_create":"2026-04-23T15:22:15.9936+08:00","gmt_modified":"2026-04-23T15:22:15.9936+08:00"},{"id":"753a437d837246ead62b0e16c6331284","path":"backend/app/services/auth.py","line_range":"37-69","gmt_create":"2026-04-23T15:22:15.994329+08:00","gmt_modified":"2026-04-23T15:22:15.994329+08:00"},{"id":"d820e2daf2ea133a7aa17cdc475e44a4","path":"tests/test_auth.py","line_range":"1-104","gmt_create":"2026-04-23T15:22:15.99504+08:00","gmt_modified":"2026-04-23T15:22:15.99504+08:00"},{"id":"1a439c5fed6cfd188c646e1614d56371","path":"backend/app/services/auth.py","line_range":"1-69","gmt_create":"2026-04-23T15:22:15.995715+08:00","gmt_modified":"2026-04-23T15:22:15.995715+08:00"},{"id":"5c67e2f70283956b2d29a3c1443eb514","path":"backend/app/workers/citation_engine.py","line_range":"122-146","gmt_create":"2026-04-23T15:22:15.996787+08:00","gmt_modified":"2026-04-23T15:22:15.996787+08:00"},{"id":"a57acd9da5287c915ac823784a409292","path":"tests/test_citation_engine.py","line_range":"1-127","gmt_create":"2026-04-23T15:22:15.99744+08:00","gmt_modified":"2026-04-23T15:22:15.99744+08:00"},{"id":"2a4f741f31f62dce8ad63be2e831f520","path":"tests/test_citations.py","line_range":"23-93","gmt_create":"2026-04-23T15:22:15.998141+08:00","gmt_modified":"2026-04-23T15:22:15.998141+08:00"},{"id":"692ac240965eff7e66945aa3c4c270f7","path":"tests/test_citations.py","line_range":"1-93","gmt_create":"2026-04-23T15:22:15.998797+08:00","gmt_modified":"2026-04-23T15:22:15.998797+08:00"},{"id":"32a0a52faca2d8d488e49c63c86075b1","path":"tests/test_queries.py","line_range":"29-154","gmt_create":"2026-04-23T15:22:15.999443+08:00","gmt_modified":"2026-04-23T15:22:15.999444+08:00"},{"id":"7804331f5f8c1ba5a3b6d9c1ae1c78c1","path":"tests/test_queries.py","line_range":"1-154","gmt_create":"2026-04-23T15:22:16.000539+08:00","gmt_modified":"2026-04-23T15:22:16.000539+08:00"},{"id":"3a6e1b738967bf8cc651e57f48e2e126","path":"tests/test_business_flow.py","line_range":"83-126","gmt_create":"2026-04-23T15:22:16.00171+08:00","gmt_modified":"2026-04-23T15:22:16.00171+08:00"},{"id":"b1afd377757f1d0e9bdf87edfff3ad88","path":"tests/test_business_flow.py","line_range":"131-186","gmt_create":"2026-04-23T15:22:16.002219+08:00","gmt_modified":"2026-04-23T15:22:16.002219+08:00"},{"id":"de05ec7eed033e432991e5a88e1b5a06","path":"tests/test_business_flow.py","line_range":"192-222","gmt_create":"2026-04-23T15:22:16.002653+08:00","gmt_modified":"2026-04-23T15:22:16.002653+08:00"},{"id":"7fd61a451248b6b129299d6246f711c7","path":"tests/test_business_flow.py","line_range":"228-296","gmt_create":"2026-04-23T15:22:16.003121+08:00","gmt_modified":"2026-04-23T15:22:16.003121+08:00"},{"id":"53eedffff456a566fa7b0cecc7169f56","path":"tests/test_business_flow.py","line_range":"1-441","gmt_create":"2026-04-23T15:22:16.003614+08:00","gmt_modified":"2026-04-23T15:22:16.003615+08:00"},{"id":"906f7a8288e38d4244211f3f538fe7b6","path":"backend/app/workers/scheduler.py","line_range":"27-182","gmt_create":"2026-04-23T15:22:16.004044+08:00","gmt_modified":"2026-04-23T15:22:16.004044+08:00"},{"id":"1647ee2066de2ae59ba8cf88e33c5e02","path":"tests/test_scheduler.py","line_range":"1-123","gmt_create":"2026-04-23T15:22:16.004461+08:00","gmt_modified":"2026-04-23T15:22:16.004461+08:00"},{"id":"fd18328b6582e68c30b130b912891992","path":"frontend/components/providers.tsx","line_range":"1-9","gmt_create":"2026-04-23T15:22:23.501815+08:00","gmt_modified":"2026-04-23T15:22:23.501815+08:00"},{"id":"71a37a516437e94fd82a87efc70a3f16","path":"frontend/package.json","line_range":"1-40","gmt_create":"2026-04-23T15:22:23.503888+08:00","gmt_modified":"2026-04-23T15:22:23.503888+08:00"},{"id":"89d70e5f89be23a229e3ee59982b8e6e","path":"frontend/tailwind.config.ts","line_range":"1-57","gmt_create":"2026-04-23T15:22:23.504853+08:00","gmt_modified":"2026-04-23T15:22:23.504853+08:00"},{"id":"95be577a89fbeb02578e4c3718c6ec86","path":"frontend/components/ui/button.tsx","line_range":"1-57","gmt_create":"2026-04-23T15:22:23.505579+08:00","gmt_modified":"2026-04-23T15:22:23.505579+08:00"},{"id":"607bb628918a7a5d54cbf74763f94d07","path":"frontend/components/ui/input.tsx","line_range":"1-23","gmt_create":"2026-04-23T15:22:23.506257+08:00","gmt_modified":"2026-04-23T15:22:23.506257+08:00"},{"id":"325e25d1dda0f7bfd9d7adfe35ecf3b5","path":"frontend/components/ui/select.tsx","line_range":"1-161","gmt_create":"2026-04-23T15:22:23.507044+08:00","gmt_modified":"2026-04-23T15:22:23.507044+08:00"},{"id":"ad6ff021b2126ad5c42323305eb6d8b0","path":"frontend/components/ui/dropdown-menu.tsx","line_range":"1-201","gmt_create":"2026-04-23T15:22:23.507926+08:00","gmt_modified":"2026-04-23T15:22:23.507926+08:00"},{"id":"a85f004dca63614b4e734ba63b45ef9e","path":"frontend/components/ui/card.tsx","line_range":"1-80","gmt_create":"2026-04-23T15:22:23.508411+08:00","gmt_modified":"2026-04-23T15:22:23.508411+08:00"},{"id":"bd3042a8d9b602334720b0d7b4e8ab3d","path":"frontend/components/ui/tabs.tsx","line_range":"1-56","gmt_create":"2026-04-23T15:22:23.509355+08:00","gmt_modified":"2026-04-23T15:22:23.509355+08:00"},{"id":"379443f450513b5492e2d9d5fca94a42","path":"frontend/components/ui/label.tsx","line_range":"1-27","gmt_create":"2026-04-23T15:22:23.509832+08:00","gmt_modified":"2026-04-23T15:22:23.509832+08:00"},{"id":"4aa6ad434a73143bb7a2072124f63be0","path":"frontend/components/ui/badge.tsx","line_range":"1-37","gmt_create":"2026-04-23T15:22:23.510286+08:00","gmt_modified":"2026-04-23T15:22:23.510286+08:00"},{"id":"c45dbdda70a8b9f02b52af4991644d0b","path":"frontend/package.json","line_range":"11-27","gmt_create":"2026-04-23T15:22:23.511056+08:00","gmt_modified":"2026-04-23T15:22:23.511056+08:00"},{"id":"6ac6943c93570294e4fb15a862be2616","path":"frontend/components/ui/button.tsx","line_range":"36-54","gmt_create":"2026-04-23T15:22:23.51229+08:00","gmt_modified":"2026-04-23T15:22:23.51229+08:00"},{"id":"4bfb5059c685e9878aed64cb5347ccec","path":"frontend/components/ui/dialog.tsx","line_range":"9-54","gmt_create":"2026-04-23T15:22:23.513266+08:00","gmt_modified":"2026-04-23T15:22:23.513266+08:00"},{"id":"0af48b69fe8fb9e480fa1656f36a4330","path":"frontend/components/ui/dropdown-menu.tsx","line_range":"21-75","gmt_create":"2026-04-23T15:22:23.514127+08:00","gmt_modified":"2026-04-23T15:22:23.514127+08:00"},{"id":"09971e31ab658e119d4c0ad948282107","path":"frontend/components/ui/select.tsx","line_range":"15-100","gmt_create":"2026-04-23T15:22:23.514956+08:00","gmt_modified":"2026-04-23T15:22:23.514956+08:00"},{"id":"31aa8777de6043883950d2668094e388","path":"frontend/components/ui/table.tsx","line_range":"5-106","gmt_create":"2026-04-23T15:22:23.515769+08:00","gmt_modified":"2026-04-23T15:22:23.515769+08:00"},{"id":"28baf3cedb89a21c6d542b7ce2439b24","path":"frontend/components/ui/tabs.tsx","line_range":"8-53","gmt_create":"2026-04-23T15:22:23.516573+08:00","gmt_modified":"2026-04-23T15:22:23.516573+08:00"},{"id":"28b0f4797c6084272244175a24b961cb","path":"frontend/components/ui/card.tsx","line_range":"5-77","gmt_create":"2026-04-23T15:22:23.518527+08:00","gmt_modified":"2026-04-23T15:22:23.518527+08:00"},{"id":"a6e0b3fa65906c3c3cd88707e1d40059","path":"frontend/components/ui/label.tsx","line_range":"9-23","gmt_create":"2026-04-23T15:22:23.520181+08:00","gmt_modified":"2026-04-23T15:22:23.520181+08:00"},{"id":"9a909775022010b4686c2b00cdf1c165","path":"frontend/components/ui/badge.tsx","line_range":"6-34","gmt_create":"2026-04-23T15:22:23.521343+08:00","gmt_modified":"2026-04-23T15:22:23.521343+08:00"},{"id":"ce1cd184945ae56cf63f55168afd8050","path":"frontend/components/ui/dialog.tsx","line_range":"47-50","gmt_create":"2026-04-23T15:22:23.523823+08:00","gmt_modified":"2026-04-23T15:22:23.523823+08:00"},{"id":"4a2a06e1efcbc85deaa013dca155f20c","path":"frontend/tailwind.config.ts","line_range":"10-54","gmt_create":"2026-04-23T15:22:23.524333+08:00","gmt_modified":"2026-04-23T15:22:23.524333+08:00"},{"id":"8b00ea4aba57ea6ed982287fb7840805","path":"frontend/lib/utils.ts","line_range":"4-6","gmt_create":"2026-04-23T15:22:23.524876+08:00","gmt_modified":"2026-04-23T15:22:23.524876+08:00"},{"id":"7c0831c17e8c65eaed9511e17ed2a2ef","path":"backend/app/services/citation.py","line_range":"1-269","gmt_create":"2026-04-23T20:31:36.482111+08:00","gmt_modified":"2026-04-23T20:31:36.482111+08:00"},{"id":"71f98c8993fb42b108e34a554247869b","path":"backend/app/workers/scheduler.py","line_range":"1-95","gmt_create":"2026-04-23T20:31:36.482732+08:00","gmt_modified":"2026-04-23T20:31:36.482732+08:00"},{"id":"8d5aac2ae0671f05d7c0807ba9296cdf","path":"backend/app/workers/citation_engine.py","line_range":"1-330","gmt_create":"2026-04-23T20:31:36.4831+08:00","gmt_modified":"2026-04-23T20:31:36.4831+08:00"},{"id":"debd789847d1eed2d54198772edf68a2","path":"backend/app/workers/platforms/tongyi.py","line_range":"1-38","gmt_create":"2026-04-23T20:31:36.483423+08:00","gmt_modified":"2026-04-23T20:31:36.483423+08:00"},{"id":"3bde521d18cc7221ae2f14637e163aac","path":"backend/app/workers/platforms/doubao.py","line_range":"1-38","gmt_create":"2026-04-23T20:31:36.483821+08:00","gmt_modified":"2026-04-23T20:31:36.483821+08:00"},{"id":"c26862d9e0fc878b51a2668cfd2ec827","path":"backend/app/workers/platforms/qingyan.py","line_range":"1-38","gmt_create":"2026-04-23T20:31:36.484113+08:00","gmt_modified":"2026-04-23T20:31:36.484114+08:00"},{"id":"0fcc9c2e0d33b887c5f18a3807b64a1e","path":"backend/app/workers/platforms/tiangong.py","line_range":"1-38","gmt_create":"2026-04-23T20:31:36.484512+08:00","gmt_modified":"2026-04-23T20:31:36.484512+08:00"},{"id":"a4baa2444208b3f9a3f42bc492038207","path":"backend/app/workers/platforms/xinghuo.py","line_range":"1-38","gmt_create":"2026-04-23T20:31:36.485041+08:00","gmt_modified":"2026-04-23T20:31:36.485041+08:00"},{"id":"9f82f6d82bf914a608d6afa3d9854abf","path":"backend/app/workers/platforms/search_engine.py","line_range":"1-174","gmt_create":"2026-04-23T20:31:36.485492+08:00","gmt_modified":"2026-04-23T20:31:36.485492+08:00"},{"id":"6281fff17a86ec1895c64d87c2ae7fb1","path":"backend/app/models/query.py","line_range":"1-55","gmt_create":"2026-04-23T20:31:36.486251+08:00","gmt_modified":"2026-04-23T20:31:36.486251+08:00"},{"id":"943c18db69a04b3137fba4cebcfea87e","path":"backend/app/models/citation_record.py","line_range":"1-42","gmt_create":"2026-04-23T20:31:36.48687+08:00","gmt_modified":"2026-04-23T20:31:36.48687+08:00"},{"id":"6628e006b8e5ca16160743528b6b0506","path":"backend/app/models/query_task.py","line_range":"1-39","gmt_create":"2026-04-23T20:31:36.487305+08:00","gmt_modified":"2026-04-23T20:31:36.487305+08:00"},{"id":"72a110dca58d8152758e2fdab4e94761","path":"backend/app/workers/platforms/base.py","line_range":"1-18","gmt_create":"2026-04-23T20:31:36.490327+08:00","gmt_modified":"2026-04-23T20:31:36.490328+08:00"},{"id":"300e43c7a648440163f81039eaa47b5a","path":"frontend/lib/platforms.ts","line_range":"1-24","gmt_create":"2026-04-23T20:31:36.494718+08:00","gmt_modified":"2026-04-23T20:31:36.494718+08:00"},{"id":"caf1970ded8fc5d3921005e166e2100b","path":"backend/app/api/citations.py","line_range":"59-78","gmt_create":"2026-04-23T20:31:36.499676+08:00","gmt_modified":"2026-04-23T20:31:36.499677+08:00"},{"id":"4ded871d02b8119cdd985de8b220b084","path":"backend/app/services/citation.py","line_range":"204-234","gmt_create":"2026-04-23T20:31:36.500626+08:00","gmt_modified":"2026-04-23T20:31:36.500626+08:00"},{"id":"448970b02d89d5e1576f70bdb0063363","path":"backend/app/workers/scheduler.py","line_range":"51-84","gmt_create":"2026-04-23T20:31:36.501136+08:00","gmt_modified":"2026-04-23T20:31:36.501136+08:00"},{"id":"362d22f423631cda39404660b3317a2f","path":"backend/app/workers/citation_engine.py","line_range":"177-254","gmt_create":"2026-04-23T20:31:36.501596+08:00","gmt_modified":"2026-04-23T20:31:36.501596+08:00"},{"id":"b475ff5225ac403c7fcf3dd7e14cbac6","path":"backend/app/workers/platforms/tongyi.py","line_range":"16-33","gmt_create":"2026-04-23T20:31:36.502032+08:00","gmt_modified":"2026-04-23T20:31:36.502032+08:00"},{"id":"557ae34b57a5dd8e8fa3bb2a6ce178a7","path":"backend/app/workers/platforms/search_engine.py","line_range":"163-174","gmt_create":"2026-04-23T20:31:36.502504+08:00","gmt_modified":"2026-04-23T20:31:36.502504+08:00"},{"id":"75c6ab0599d304bf36d290d4143d3d2f","path":"backend/app/models/query.py","line_range":"29-31","gmt_create":"2026-04-23T20:31:36.502934+08:00","gmt_modified":"2026-04-23T20:31:36.502934+08:00"},{"id":"2a6780838f1415dcb7d0fa611f64cee7","path":"backend/app/workers/platforms/base.py","line_range":"4-17","gmt_create":"2026-04-23T20:31:36.504228+08:00","gmt_modified":"2026-04-23T20:31:36.504228+08:00"},{"id":"c5ae7697193b2b93425ff25d2d7d54a9","path":"backend/app/workers/platforms/tongyi.py","line_range":"10-38","gmt_create":"2026-04-23T20:31:36.505069+08:00","gmt_modified":"2026-04-23T20:31:36.505069+08:00"},{"id":"aa8c3fa3bc509dafe64d113bdd09eafa","path":"backend/app/workers/platforms/doubao.py","line_range":"10-38","gmt_create":"2026-04-23T20:31:36.505502+08:00","gmt_modified":"2026-04-23T20:31:36.505503+08:00"},{"id":"eabb031e538ea62cab69b01368740d20","path":"backend/app/workers/platforms/qingyan.py","line_range":"10-38","gmt_create":"2026-04-23T20:31:36.505932+08:00","gmt_modified":"2026-04-23T20:31:36.505932+08:00"},{"id":"b1c09e372a63e9854886adaea1663bea","path":"backend/app/workers/platforms/tiangong.py","line_range":"10-38","gmt_create":"2026-04-23T20:31:36.50633+08:00","gmt_modified":"2026-04-23T20:31:36.50633+08:00"},{"id":"79793bcd507f9d287d19014b60d963d3","path":"backend/app/workers/platforms/xinghuo.py","line_range":"10-38","gmt_create":"2026-04-23T20:31:36.506717+08:00","gmt_modified":"2026-04-23T20:31:36.506717+08:00"},{"id":"102223dd13475177a1ade8b9be14fbd1","path":"backend/app/workers/platforms/search_engine.py","line_range":"79-144","gmt_create":"2026-04-23T20:31:36.509667+08:00","gmt_modified":"2026-04-23T20:31:36.509667+08:00"},{"id":"8565f299083b4dcba5a328c947f06fee","path":"backend/app/workers/citation_engine.py","line_range":"256-287","gmt_create":"2026-04-23T20:31:36.512515+08:00","gmt_modified":"2026-04-23T20:31:36.512515+08:00"},{"id":"8af91caf063c12c8236f9675769ce4a1","path":"tests/test_citation_engine.py","line_range":"1-54","gmt_create":"2026-04-23T20:31:36.51401+08:00","gmt_modified":"2026-04-23T20:31:36.51401+08:00"},{"id":"005172b71dc742cf6803c5eb0185091e","path":"backend/requirements.txt","line_range":"1-36","gmt_create":"2026-04-23T20:31:36.516249+08:00","gmt_modified":"2026-04-23T20:31:36.516249+08:00"},{"id":"b55cc5936c299f819b57b899858438e6","path":"backend/app/workers/platforms/search_engine.py","line_range":"139-144","gmt_create":"2026-04-23T20:31:36.518228+08:00","gmt_modified":"2026-04-23T20:31:36.518228+08:00"},{"id":"384b1939e53970ce7ae75d241a49da5f","path":"backend/app/workers/platforms/tongyi.py","line_range":"22-29","gmt_create":"2026-04-23T20:31:36.518493+08:00","gmt_modified":"2026-04-23T20:31:36.518493+08:00"},{"id":"f096aa3ea82e9fa625a9acb1309b4c50","path":"backend/app/workers/citation_engine.py","line_range":"231-247","gmt_create":"2026-04-23T20:31:36.518795+08:00","gmt_modified":"2026-04-23T20:31:36.518795+08:00"},{"id":"15b8ebf74b0a5dfac58024d323ca8d0a","path":"backend/app/workers/citation_engine.py","line_range":"164-175","gmt_create":"2026-04-23T20:31:36.519395+08:00","gmt_modified":"2026-04-23T20:31:36.519395+08:00"},{"id":"bcfade20d923c8efa713808ca9af94ca","path":"backend/app/workers/platforms/wenxin.py","line_range":"10-38","gmt_create":"2026-04-23T20:31:50.45294+08:00","gmt_modified":"2026-04-23T20:31:50.45294+08:00"},{"id":"ca7e1232fbba5fb75e04ab8e491bfbd1","path":"backend/app/workers/platforms/kimi.py","line_range":"10-38","gmt_create":"2026-04-23T20:31:50.453339+08:00","gmt_modified":"2026-04-23T20:31:50.453339+08:00"},{"id":"9720b93ed7247efb685e2825e5f964bf","path":"backend/app/workers/citation_engine.py","line_range":"161-176","gmt_create":"2026-04-23T20:31:50.454207+08:00","gmt_modified":"2026-04-23T20:31:50.454207+08:00"},{"id":"0d226400124ba891a46f59c36781ccd8","path":"backend/app/config.py","line_range":"9-23","gmt_create":"2026-04-23T20:31:50.454503+08:00","gmt_modified":"2026-04-23T20:31:50.454503+08:00"},{"id":"412695e5de2014514a8f62f98c573656","path":"backend/Dockerfile","line_range":"1-41","gmt_create":"2026-04-23T20:31:50.454798+08:00","gmt_modified":"2026-04-23T20:31:50.454798+08:00"},{"id":"485e15eb30a5b08da38a628c9dd5053e","path":"backend/app/workers/platforms/search_engine.py","line_range":"16-77","gmt_create":"2026-04-23T20:31:50.459138+08:00","gmt_modified":"2026-04-23T20:31:50.459138+08:00"},{"id":"77158a6f887e224a03552893bfec7c92","path":"backend/app/workers/platforms/wenxin.py","line_range":"16-33","gmt_create":"2026-04-23T20:31:50.461662+08:00","gmt_modified":"2026-04-23T20:31:50.461662+08:00"},{"id":"5c3f336b5a7b4af4cc2f2ac183539218","path":"backend/app/workers/platforms/search_engine.py","line_range":"79-145","gmt_create":"2026-04-23T20:31:50.464823+08:00","gmt_modified":"2026-04-23T20:31:50.464823+08:00"},{"id":"3894c1ed9dca2ebf2359f40ebdb1959e","path":"backend/app/workers/platforms/search_engine.py","line_range":"147-174","gmt_create":"2026-04-23T20:31:50.465221+08:00","gmt_modified":"2026-04-23T20:31:50.465221+08:00"},{"id":"e27bcba24aaadeec1922d2b4e5b8386b","path":"backend/app/api/queries.py","line_range":"1-109","gmt_create":"2026-04-23T20:31:50.46721+08:00","gmt_modified":"2026-04-23T20:31:50.46721+08:00"},{"id":"5f893f5078aa8e549284feb057aa45da","path":"backend/app/workers/platforms/wenxin.py","line_range":"16-29","gmt_create":"2026-04-23T20:31:50.469467+08:00","gmt_modified":"2026-04-23T20:31:50.469467+08:00"},{"id":"e0b68d2d24760689a0f4f00dfee5f9f2","path":"backend/app/workers/platforms/search_engine.py","line_range":"28-76","gmt_create":"2026-04-23T20:31:50.470319+08:00","gmt_modified":"2026-04-23T20:31:50.470319+08:00"},{"id":"e9b98ae83632342d8e06cde39e9c9462","path":"backend/app/workers/platforms/search_engine.py","line_range":"105-137","gmt_create":"2026-04-23T20:31:50.470672+08:00","gmt_modified":"2026-04-23T20:31:50.470672+08:00"},{"id":"c86edb7a95fbe4b431ac65a0e2b8636e","path":"backend/app/api/queries.py","line_range":"90-109","gmt_create":"2026-04-23T20:31:50.471824+08:00","gmt_modified":"2026-04-23T20:31:50.471825+08:00"},{"id":"6e054d9a78c0c8c9da8dec4c4bda62ab","path":"backend/app/database.py","line_range":"6-28","gmt_create":"2026-04-23T20:33:29.972803+08:00","gmt_modified":"2026-04-23T20:33:29.972803+08:00"},{"id":"9c16a069e5154660bfdfa48f3518fc6a","path":"backend/app/models/query_task.py","line_range":"11-38","gmt_create":"2026-04-23T20:33:29.980385+08:00","gmt_modified":"2026-04-23T20:33:29.980385+08:00"},{"id":"a4918fcbd21492ad996d7f5496f03a4b","path":"backend/app/workers/platforms/kimi.py","line_range":"33-48","gmt_create":"2026-04-23T20:33:29.982795+08:00","gmt_modified":"2026-04-23T20:33:29.982795+08:00"},{"id":"bc38d046b4b1410ae2165cee2272839e","path":"backend/app/workers/platforms/wenxin.py","line_range":"33-48","gmt_create":"2026-04-23T20:33:29.983597+08:00","gmt_modified":"2026-04-23T20:33:29.983597+08:00"},{"id":"72f6d334026866e8a61d2ffb1d83370a","path":"backend/app/workers/citation_engine.py","line_range":"19-100","gmt_create":"2026-04-23T20:33:29.986927+08:00","gmt_modified":"2026-04-23T20:33:29.986928+08:00"},{"id":"1d84b9a7eb013882953a2d1d948299e4","path":"backend/app/workers/platforms/kimi.py","line_range":"126-197","gmt_create":"2026-04-23T20:33:29.990308+08:00","gmt_modified":"2026-04-23T20:33:29.990308+08:00"},{"id":"ba687f2c64aff92b3906658359ed953a","path":"backend/app/workers/platforms/wenxin.py","line_range":"124-195","gmt_create":"2026-04-23T20:33:29.991213+08:00","gmt_modified":"2026-04-23T20:33:29.991213+08:00"},{"id":"52ee729b02c992c689522c7956c14128","path":"backend/app/workers/scheduler.py","line_range":"57-62","gmt_create":"2026-04-23T20:33:29.992799+08:00","gmt_modified":"2026-04-23T20:33:29.992799+08:00"},{"id":"c9e32b7324cce60c8887deb8404ee759","path":"backend/app/workers/scheduler.py","line_range":"107-112","gmt_create":"2026-04-23T20:33:29.99333+08:00","gmt_modified":"2026-04-23T20:33:29.99333+08:00"},{"id":"8355d3821337334caee57a75dc8c8865","path":"backend/app/services/query.py","line_range":"116-130","gmt_create":"2026-04-23T20:33:29.994505+08:00","gmt_modified":"2026-04-23T20:33:29.994505+08:00"},{"id":"4fe27d4d1323b500e72d870aa6212a1a","path":"backend/app/workers/scheduler.py","line_range":"13-20","gmt_create":"2026-04-23T20:33:29.996199+08:00","gmt_modified":"2026-04-23T20:33:29.996199+08:00"},{"id":"3729543092bccad8926c5ea852db1e69","path":"backend/app/workers/citation_engine.py","line_range":"148-157","gmt_create":"2026-04-23T20:33:29.996517+08:00","gmt_modified":"2026-04-23T20:33:29.996517+08:00"},{"id":"1ee5153c867fc6e9d277a3067963a1fc","path":"backend/app/workers/scheduler.py","line_range":"32-38","gmt_create":"2026-04-23T20:33:29.997154+08:00","gmt_modified":"2026-04-23T20:33:29.997154+08:00"},{"id":"ed527c7a549ec333c2b30b59614343df","path":"backend/app/models/query.py","line_range":"50-54","gmt_create":"2026-04-23T20:33:29.997453+08:00","gmt_modified":"2026-04-23T20:33:29.997453+08:00"},{"id":"1a3351698ecc7cd4e508b7a792804fc4","path":"backend/app/workers/citation_engine.py","line_range":"302-309","gmt_create":"2026-04-23T20:33:29.999284+08:00","gmt_modified":"2026-04-23T20:33:29.999284+08:00"},{"id":"e3e9710c7eead933c936519395f792e0","path":"backend/app/workers/scheduler.py","line_range":"44-49","gmt_create":"2026-04-23T20:33:30.00043+08:00","gmt_modified":"2026-04-23T20:33:30.000431+08:00"},{"id":"a4143cc29b14f1f5bc75a5e021690666","path":"backend/app/workers/platforms/kimi.py","line_range":"23-31","gmt_create":"2026-04-23T20:33:30.001466+08:00","gmt_modified":"2026-04-23T20:33:30.001466+08:00"},{"id":"7192cfda5508e7587efd91d26cf1f018","path":"backend/app/workers/platforms/wenxin.py","line_range":"23-31","gmt_create":"2026-04-23T20:33:30.002099+08:00","gmt_modified":"2026-04-23T20:33:30.002099+08:00"},{"id":"38142b7d7016c5590e638fafcdcb1a19","path":"backend/app/workers/citation_engine.py","line_range":"211-227","gmt_create":"2026-04-23T20:33:30.002775+08:00","gmt_modified":"2026-04-23T20:33:30.002775+08:00"},{"id":"fb5276346dcc4e7044d8765a8572e7a8","path":"backend/app/config.py","line_range":"4-16","gmt_create":"2026-04-23T20:33:30.003374+08:00","gmt_modified":"2026-04-23T20:33:30.003377+08:00"},{"id":"482d573f97b482b99bcde1c399eceb73","path":"backend/app/api/queries.py","line_range":"90-108","gmt_create":"2026-04-23T20:33:37.21132+08:00","gmt_modified":"2026-04-23T20:33:37.21132+08:00"},{"id":"56f44cc97867cee3e5663424134d6072","path":"backend/app/workers/platforms/kimi.py","line_range":"1-37","gmt_create":"2026-04-23T20:33:37.212923+08:00","gmt_modified":"2026-04-23T20:33:37.212923+08:00"},{"id":"2e326ef8322619f1e8b3873022cb0437","path":"backend/app/workers/platforms/wenxin.py","line_range":"1-37","gmt_create":"2026-04-23T20:33:37.213348+08:00","gmt_modified":"2026-04-23T20:33:37.213348+08:00"},{"id":"4cac57dbc530f0335c913ec5725dfa4f","path":"backend/app/workers/scheduler.py","line_range":"1-121","gmt_create":"2026-04-23T20:33:37.215373+08:00","gmt_modified":"2026-04-23T20:33:37.215373+08:00"},{"id":"db174cfe219fc84d0dd26529f047b1d0","path":"backend/app/workers/citation_engine.py","line_range":"161-330","gmt_create":"2026-04-23T20:33:37.22028+08:00","gmt_modified":"2026-04-23T20:33:37.22028+08:00"},{"id":"f36452f78aabfb0c46da03bbe25dff06","path":"backend/app/services/citation.py","line_range":"219-295","gmt_create":"2026-04-23T20:33:37.223165+08:00","gmt_modified":"2026-04-23T20:33:37.223165+08:00"},{"id":"52c01d7b9c17aa16944cbfcf8885be61","path":"backend/app/workers/platforms/kimi.py","line_range":"16-33","gmt_create":"2026-04-23T20:33:37.227954+08:00","gmt_modified":"2026-04-23T20:33:37.227954+08:00"},{"id":"9d352899554ab41b65b2e9f32558d811","path":"backend/app/workers/citation_engine.py","line_range":"39-113","gmt_create":"2026-04-23T20:33:37.229053+08:00","gmt_modified":"2026-04-23T20:33:37.229053+08:00"},{"id":"b1ee5a992230844ba898765be63f7b27","path":"backend/app/workers/citation_engine.py","line_range":"32-133","gmt_create":"2026-04-23T20:33:37.229555+08:00","gmt_modified":"2026-04-23T20:33:37.229555+08:00"},{"id":"cb098a3cd32339e99f755dfd0fc35b5c","path":"tests/test_citation_engine.py","line_range":"6-127","gmt_create":"2026-04-23T20:33:37.230048+08:00","gmt_modified":"2026-04-23T20:33:37.230049+08:00"},{"id":"3d2dab79f7a3fedf24f0212cc9ef7aa1","path":"backend/app/workers/citation_engine.py","line_range":"145-158","gmt_create":"2026-04-23T20:33:37.230491+08:00","gmt_modified":"2026-04-23T20:33:37.230491+08:00"},{"id":"4e9b3d0e94282f4bc6fa500f4eed61a1","path":"backend/app/workers/citation_engine.py","line_range":"135-159","gmt_create":"2026-04-23T20:33:37.231003+08:00","gmt_modified":"2026-04-23T20:33:37.231003+08:00"},{"id":"8e3201561a9dd9a06ee3bf68ffdb3f99","path":"tests/test_citation_engine.py","line_range":"39-109","gmt_create":"2026-04-23T20:33:37.231501+08:00","gmt_modified":"2026-04-23T20:33:37.231501+08:00"},{"id":"c3a417be3d61f5bcd3fbf976e0c4f15a","path":"backend/app/workers/scheduler.py","line_range":"33-121","gmt_create":"2026-04-23T20:33:37.238099+08:00","gmt_modified":"2026-04-23T20:33:37.238099+08:00"},{"id":"7ce954ed7d3bc4dcf78630124cc0dd88","path":"backend/app/services/citation.py","line_range":"264-295","gmt_create":"2026-04-23T20:33:37.244499+08:00","gmt_modified":"2026-04-23T20:33:37.244499+08:00"},{"id":"7289a3568c137c8a671fc8c963bb8d28","path":"backend/requirements.txt","line_range":"1-35","gmt_create":"2026-04-23T20:33:37.24795+08:00","gmt_modified":"2026-04-23T20:33:37.24795+08:00"},{"id":"ef82ce4377c549013c200e19701a6805","path":"backend/app/workers/platforms/kimi.py","line_range":"21-32","gmt_create":"2026-04-23T20:33:37.254004+08:00","gmt_modified":"2026-04-23T20:33:37.254004+08:00"},{"id":"c7986eb1be0ffdd9ec4e243be4270119","path":"backend/app/workers/platforms/wenxin.py","line_range":"21-32","gmt_create":"2026-04-23T20:33:37.254558+08:00","gmt_modified":"2026-04-23T20:33:37.254558+08:00"},{"id":"5563b3bd56550648dc70302c1762ce5a","path":"backend/app/workers/platforms/tongyi.py","line_range":"18-29","gmt_create":"2026-04-23T20:33:37.255643+08:00","gmt_modified":"2026-04-23T20:33:37.255643+08:00"},{"id":"91852ef8dcc844a2f85e9fce0227ab74","path":"backend/app/workers/platforms/doubao.py","line_range":"18-29","gmt_create":"2026-04-23T20:33:37.25603+08:00","gmt_modified":"2026-04-23T20:33:37.25603+08:00"},{"id":"1b46fab9e22f53db30ead5677d03e3e2","path":"backend/app/workers/citation_engine.py","line_range":"11-16","gmt_create":"2026-04-23T20:33:37.256413+08:00","gmt_modified":"2026-04-23T20:33:37.256413+08:00"},{"id":"4a2fa09aa3a948dec5ef8ba873b0e716","path":"backend/app/services/citation.py","line_range":"14-42","gmt_create":"2026-04-23T20:33:37.257057+08:00","gmt_modified":"2026-04-23T20:33:37.257057+08:00"},{"id":"e7afbab5932c93c3469f1a225e6c7156","path":"backend/app/api/citations.py","line_range":"1-55","gmt_create":"2026-04-23T20:33:57.479092+08:00","gmt_modified":"2026-04-23T20:33:57.479092+08:00"},{"id":"a0eac56d622a2fff529bc2b796064bcd","path":"backend/app/schemas/query.py","line_range":"1-94","gmt_create":"2026-04-23T20:33:57.479659+08:00","gmt_modified":"2026-04-23T20:33:57.479659+08:00"},{"id":"174be58163b6f72b4cd4a493f3463ce4","path":"backend/app/schemas/citation.py","line_range":"1-52","gmt_create":"2026-04-23T20:33:57.480222+08:00","gmt_modified":"2026-04-23T20:33:57.480222+08:00"},{"id":"136f172c732d0cc130532a4f0df475a4","path":"backend/app/models/user.py","line_range":"1-41","gmt_create":"2026-04-23T20:33:57.481714+08:00","gmt_modified":"2026-04-23T20:33:57.481714+08:00"},{"id":"916551131bd9ac8c9f9c8bb762af1fa4","path":"backend/app/services/query.py","line_range":"1-130","gmt_create":"2026-04-23T20:33:57.482172+08:00","gmt_modified":"2026-04-23T20:33:57.482172+08:00"},{"id":"5d2836286eb7d4eb6039b004a9744d26","path":"backend/app/services/citation.py","line_range":"1-429","gmt_create":"2026-04-23T20:33:57.482643+08:00","gmt_modified":"2026-04-23T20:33:57.482643+08:00"},{"id":"39a3b2d9301fa4eff7bef0fda3352790","path":"backend/app/workers/platforms/kimi.py","line_range":"1-206","gmt_create":"2026-04-23T20:33:57.484464+08:00","gmt_modified":"2026-04-23T20:33:57.484464+08:00"},{"id":"fbcfae3b1238b3da5329ebafe4294861","path":"backend/app/workers/platforms/wenxin.py","line_range":"1-205","gmt_create":"2026-04-23T20:33:57.484977+08:00","gmt_modified":"2026-04-23T20:33:57.484977+08:00"},{"id":"c4273407c88f470df7daf6a8ad5ce969","path":"backend/app/api/queries.py","line_range":"15-109","gmt_create":"2026-04-23T20:33:57.485748+08:00","gmt_modified":"2026-04-23T20:33:57.485748+08:00"},{"id":"35774e0a09ac5459c868914d7182ca95","path":"backend/app/api/citations.py","line_range":"19-55","gmt_create":"2026-04-23T20:33:57.486195+08:00","gmt_modified":"2026-04-23T20:33:57.486195+08:00"},{"id":"f639b566c26dfd18b24e3dfd2e9853ac","path":"backend/app/schemas/citation.py","line_range":"7-52","gmt_create":"2026-04-23T20:33:57.486916+08:00","gmt_modified":"2026-04-23T20:33:57.486916+08:00"},{"id":"b46654006178160f12897e2c5baac8fa","path":"backend/app/services/citation.py","line_range":"219-429","gmt_create":"2026-04-23T20:33:57.488934+08:00","gmt_modified":"2026-04-23T20:33:57.488934+08:00"},{"id":"82265d393c20d0af96beec6b9c657c27","path":"backend/app/api/queries.py","line_range":"28-41","gmt_create":"2026-04-23T20:33:57.49175+08:00","gmt_modified":"2026-04-23T20:33:57.49175+08:00"},{"id":"93e5c95b1691bb81a36bf9a0ac889030","path":"backend/app/services/citation.py","line_range":"219-261","gmt_create":"2026-04-23T20:33:57.493276+08:00","gmt_modified":"2026-04-23T20:33:57.493276+08:00"},{"id":"374200f0bf946f0399351756977d0495","path":"backend/app/workers/citation_engine.py","line_range":"176-234","gmt_create":"2026-04-23T20:33:57.498134+08:00","gmt_modified":"2026-04-23T20:33:57.498134+08:00"},{"id":"9a8d9100a6bc34ebae9ee065def7e88a","path":"backend/app/schemas/query.py","line_range":"44-72","gmt_create":"2026-04-23T20:33:57.500036+08:00","gmt_modified":"2026-04-23T20:33:57.500036+08:00"},{"id":"93c23bcc3456826af17e26a6d4c32116","path":"backend/app/schemas/query.py","line_range":"6-9","gmt_create":"2026-04-23T20:33:57.500633+08:00","gmt_modified":"2026-04-23T20:33:57.500633+08:00"},{"id":"c17eeb8726297096cd5542283f11494f","path":"backend/app/api/queries.py","line_range":"17-109","gmt_create":"2026-04-23T20:33:57.5019+08:00","gmt_modified":"2026-04-23T20:33:57.5019+08:00"},{"id":"08fec4718be6991260c00ca532f9173a","path":"backend/app/api/citations.py","line_range":"22-55","gmt_create":"2026-04-23T20:33:57.502347+08:00","gmt_modified":"2026-04-23T20:33:57.502347+08:00"},{"id":"08007199eea846dd14f15f7dc70419e2","path":"backend/app/schemas/citation.py","line_range":"48-52","gmt_create":"2026-04-23T20:33:57.50265+08:00","gmt_modified":"2026-04-23T20:33:57.50265+08:00"},{"id":"4caff756fd4da029bd64cd16e7ef5960","path":"backend/app/api/queries.py","line_range":"32-39","gmt_create":"2026-04-23T20:33:57.50293+08:00","gmt_modified":"2026-04-23T20:33:57.50293+08:00"},{"id":"b0220895f66f1273966ad5b2c3266952","path":"backend/app/api/queries.py","line_range":"49-53","gmt_create":"2026-04-23T20:33:57.503622+08:00","gmt_modified":"2026-04-23T20:33:57.503622+08:00"},{"id":"44f88f9664fdf6e84ffb7e0675a86a28","path":"backend/app/api/queries.py","line_range":"64-69","gmt_create":"2026-04-23T20:33:57.504188+08:00","gmt_modified":"2026-04-23T20:33:57.504188+08:00"},{"id":"91f280f51389bd1cf711dcf33a4da681","path":"backend/app/api/queries.py","line_range":"79-84","gmt_create":"2026-04-23T20:33:57.504712+08:00","gmt_modified":"2026-04-23T20:33:57.504712+08:00"},{"id":"ab50466a57c77659d7b469d3a8a04ddb","path":"backend/app/api/queries.py","line_range":"96-103","gmt_create":"2026-04-23T20:33:57.505025+08:00","gmt_modified":"2026-04-23T20:33:57.505025+08:00"},{"id":"572c2dece1fbc13aa2bb7d6b61b0fd5c","path":"backend/app/api/citations.py","line_range":"65-71","gmt_create":"2026-04-23T20:33:57.505311+08:00","gmt_modified":"2026-04-23T20:33:57.505311+08:00"},{"id":"82386bc7ca57d9ccc94b656e52bc89f6","path":"backend/app/api/queries.py","line_range":"1-14","gmt_create":"2026-04-23T20:33:57.506573+08:00","gmt_modified":"2026-04-23T20:33:57.506573+08:00"},{"id":"7ab79ab21d7d6e4dbcb224572516f6f6","path":"backend/app/api/citations.py","line_range":"1-19","gmt_create":"2026-04-23T20:33:57.507421+08:00","gmt_modified":"2026-04-23T20:33:57.507422+08:00"},{"id":"8433204d7a82a1f480e57df9ceee5581","path":"backend/app/services/query.py","line_range":"1-10","gmt_create":"2026-04-23T20:33:57.507906+08:00","gmt_modified":"2026-04-23T20:33:57.507906+08:00"},{"id":"3957ee6f15a01b7b541490438ef18684","path":"backend/app/services/citation.py","line_range":"1-17","gmt_create":"2026-04-23T20:33:57.508376+08:00","gmt_modified":"2026-04-23T20:33:57.508376+08:00"},{"id":"fcae8d1d281ad7186999cc4ca8e43db7","path":"backend/app/workers/scheduler.py","line_range":"25-39","gmt_create":"2026-04-23T20:33:57.509666+08:00","gmt_modified":"2026-04-23T20:33:57.509666+08:00"},{"id":"ee12a84ac6334b13e20132181454488b","path":"backend/app/workers/scheduler.py","line_range":"13-19","gmt_create":"2026-04-23T20:33:57.510112+08:00","gmt_modified":"2026-04-23T20:33:57.510112+08:00"},{"id":"897e047b94772e5a0ff57cf773a7f965","path":"backend/app/workers/platforms/kimi.py","line_range":"17-32","gmt_create":"2026-04-23T20:33:57.510534+08:00","gmt_modified":"2026-04-23T20:33:57.510534+08:00"},{"id":"53e8ec81b4d2dbb13c831048e5897036","path":"backend/app/workers/platforms/wenxin.py","line_range":"17-32","gmt_create":"2026-04-23T20:33:57.510845+08:00","gmt_modified":"2026-04-23T20:33:57.510845+08:00"},{"id":"fd3145047b9c813cc8e64b9322e531f9","path":"backend/app/services/citation.py","line_range":"219-327","gmt_create":"2026-04-23T20:33:57.516693+08:00","gmt_modified":"2026-04-23T20:33:57.516693+08:00"},{"id":"b09a0f415030d91b25e6cabd8a0a93fc","path":"backend/app/models/query_task.py","line_range":"176-289","gmt_create":"2026-04-23T20:33:57.51758+08:00","gmt_modified":"2026-04-23T20:33:57.51758+08:00"},{"id":"e2168959b26c386940370b5f1bf48d7d","path":"backend/app/models/citation_record.py","line_range":"194-204","gmt_create":"2026-04-23T20:33:57.517939+08:00","gmt_modified":"2026-04-23T20:33:57.517939+08:00"},{"id":"129573d2bbcde48697ed0e75dea12396","path":"backend/app/workers/scheduler.py","line_range":"25-40","gmt_create":"2026-04-23T20:35:18.586153+08:00","gmt_modified":"2026-04-23T20:35:18.586153+08:00"},{"id":"cf18c97a9be6c78aa43cc229ed3dad20","path":"backend/app/workers/citation_engine.py","line_range":"164-173","gmt_create":"2026-04-23T20:35:18.586656+08:00","gmt_modified":"2026-04-23T20:35:18.586656+08:00"},{"id":"3c7ca5d582dca31c2530b1ce9c058e95","path":"backend/app/workers/platforms/kimi.py","line_range":"10-37","gmt_create":"2026-04-23T20:35:18.587239+08:00","gmt_modified":"2026-04-23T20:35:18.587239+08:00"},{"id":"27047f868643e5457d4f242b4298a9f6","path":"frontend/lib/platforms.ts","line_range":"1-23","gmt_create":"2026-04-23T20:35:18.590782+08:00","gmt_modified":"2026-04-23T20:35:18.590782+08:00"},{"id":"1526e4e02133a48eac04befb74ec5bd1","path":"backend/app/workers/citation_engine.py","line_range":"161-173","gmt_create":"2026-04-23T20:35:18.592183+08:00","gmt_modified":"2026-04-23T20:35:18.592183+08:00"},{"id":"98c02d9bb7aa6e2b6be5f7381e64fd99","path":"backend/app/api/queries.py","line_range":"26-39","gmt_create":"2026-04-23T20:35:18.594026+08:00","gmt_modified":"2026-04-23T20:35:18.594026+08:00"},{"id":"2a971cb83924013902324eceeab22559","path":"backend/app/workers/platforms/kimi.py","line_range":"16-29","gmt_create":"2026-04-23T20:35:18.596805+08:00","gmt_modified":"2026-04-23T20:35:18.596805+08:00"},{"id":"99326fedad9275392719105b5b6782d6","path":"backend/app/workers/platforms/kimi.py","line_range":"31-33","gmt_create":"2026-04-23T20:35:18.597389+08:00","gmt_modified":"2026-04-23T20:35:18.597389+08:00"},{"id":"5e5dacc623918c0f1eba234154c99291","path":"backend/app/workers/platforms/search_engine.py","line_range":"16-76","gmt_create":"2026-04-23T20:35:18.598978+08:00","gmt_modified":"2026-04-23T20:35:18.598978+08:00"},{"id":"5be7e6cf82d6359efddaf131aaf92615","path":"backend/app/workers/citation_engine.py","line_range":"323-330","gmt_create":"2026-04-23T20:35:18.604342+08:00","gmt_modified":"2026-04-23T20:35:18.604342+08:00"},{"id":"129b746e71a9013ceb1b0fcc59942b39","path":"backend/app/workers/scheduler.py","line_range":"86-90","gmt_create":"2026-04-23T20:35:18.611167+08:00","gmt_modified":"2026-04-23T20:35:18.611167+08:00"},{"id":"d780e807ee751f39f331a658b47c4ed3","path":"backend/app/services/citation.py","line_range":"24-269","gmt_create":"2026-04-23T20:35:18.619146+08:00","gmt_modified":"2026-04-23T20:35:18.619146+08:00"},{"id":"8eea43550951387ac740b5e3e64c7691","path":"backend/app/workers/platforms/search_engine.py","line_range":"94-96","gmt_create":"2026-04-23T20:35:18.629044+08:00","gmt_modified":"2026-04-23T20:35:18.629044+08:00"},{"id":"37769b7e6b5588be0065681dedf514ed","path":"backend/app/workers/platforms/search_engine.py","line_range":"140-144","gmt_create":"2026-04-23T20:35:18.631486+08:00","gmt_modified":"2026-04-23T20:35:18.631486+08:00"},{"id":"518d184988b97ebc7ef0c0bf5c10f42c","path":"backend/app/workers/platforms/kimi.py","line_range":"24-29","gmt_create":"2026-04-23T20:35:18.631835+08:00","gmt_modified":"2026-04-23T20:35:18.631835+08:00"},{"id":"818504ee2e17d2f9cc8fe115ca321138","path":"backend/app/api/queries.py","line_range":"34-38","gmt_create":"2026-04-23T20:35:18.632132+08:00","gmt_modified":"2026-04-23T20:35:18.632132+08:00"},{"id":"8a1a0ffd82ac6ff54d3410e4ce59a6b8","path":"backend/app/api/citations.py","line_range":"25-56","gmt_create":"2026-04-23T20:35:18.633686+08:00","gmt_modified":"2026-04-23T20:35:18.633686+08:00"},{"id":"86e37040be1aeb400fab9b529f5404c8","path":"backend/app/models/subscription.py","line_range":"1-37","gmt_create":"2026-04-23T20:35:45.583254+08:00","gmt_modified":"2026-04-23T20:35:45.583254+08:00"},{"id":"211463f5b49610f09594c40c0a235943","path":"backend/alembic/env.py","line_range":"1-89","gmt_create":"2026-04-23T20:35:45.584058+08:00","gmt_modified":"2026-04-23T20:35:45.584058+08:00"},{"id":"48d22eaee09e364a293ad6c4750f5c5a","path":"docker-compose.yml","line_range":"1-71","gmt_create":"2026-04-23T20:35:45.587653+08:00","gmt_modified":"2026-04-23T20:35:45.587653+08:00"},{"id":"98cc82f62b83678f06a33cf9231ecdf8","path":"backend/alembic/versions/488d0bd5ab01_initial_migration.py","line_range":"1-128","gmt_create":"2026-04-23T20:35:45.597037+08:00","gmt_modified":"2026-04-23T20:35:45.597037+08:00"},{"id":"e1aabd52989e47806fb997157381e1cf","path":"backend/alembic/versions/b2c4d6e8fa10_add_confidence_match_type_to_citation_records.py","line_range":"1-37","gmt_create":"2026-04-23T20:35:45.597747+08:00","gmt_modified":"2026-04-23T20:35:45.597747+08:00"},{"id":"ac77e4875817616194b7b5997d4fb1ae","path":"backend/alembic/versions/488d0bd5ab01_initial_migration.py","line_range":"57-94","gmt_create":"2026-04-23T20:35:45.611901+08:00","gmt_modified":"2026-04-23T20:35:45.611901+08:00"},{"id":"0e57efd98dacc85da21f995980371ee4","path":"backend/alembic/versions/b2c4d6e8fa10_add_confidence_match_type_to_citation_records.py","line_range":"21-37","gmt_create":"2026-04-23T20:35:45.61338+08:00","gmt_modified":"2026-04-23T20:35:45.61338+08:00"},{"id":"d34337b9ff77246979252d2fd8fb8018","path":"backend/alembic/env.py","line_range":"33-88","gmt_create":"2026-04-23T20:35:45.628352+08:00","gmt_modified":"2026-04-23T20:35:45.628353+08:00"},{"id":"eb63042f04a22f9a67bd498df1684d20","path":"backend/alembic/versions/488d0bd5ab01_initial_migration.py","line_range":"36-111","gmt_create":"2026-04-23T20:35:45.634829+08:00","gmt_modified":"2026-04-23T20:35:45.634829+08:00"},{"id":"c651c7ad6747a92ee96eabb2eb82afdd","path":"backend/app/database.py","line_range":"12-18","gmt_create":"2026-04-23T20:35:45.637195+08:00","gmt_modified":"2026-04-23T20:35:45.637195+08:00"},{"id":"dd01eee487298a28e950f6345196f1d4","path":"backend/app/services/citation.py","line_range":"30-79","gmt_create":"2026-04-23T20:35:45.637815+08:00","gmt_modified":"2026-04-23T20:35:45.637815+08:00"},{"id":"7dae7237f11c5100bf7889c105193cf6","path":"backend/app/services/query.py","line_range":"12-32","gmt_create":"2026-04-23T20:35:45.638422+08:00","gmt_modified":"2026-04-23T20:35:45.638422+08:00"},{"id":"cc64cf609f5ff218f618e0664ffa7cc7","path":"backend/app/services/citation.py","line_range":"298-308","gmt_create":"2026-04-23T20:35:45.641905+08:00","gmt_modified":"2026-04-23T20:35:45.641905+08:00"},{"id":"ce7e334595a4ce912e0d116314db9a35","path":"backend/app/services/citation.py","line_range":"342-429","gmt_create":"2026-04-23T20:35:45.6442+08:00","gmt_modified":"2026-04-23T20:35:45.6442+08:00"},{"id":"2f46f212597e3c245b9e5dcc5dbc863d","path":"backend/app/schemas/citation.py","line_range":"7-18","gmt_create":"2026-04-23T20:35:45.64501+08:00","gmt_modified":"2026-04-23T20:35:45.64501+08:00"},{"id":"dc40f1dd3e59ee7f046019201068bea1","path":"backend/app/services/citation.py","line_range":"14-22","gmt_create":"2026-04-23T20:35:45.659571+08:00","gmt_modified":"2026-04-23T20:35:45.659571+08:00"},{"id":"01a0c4b40819965823b56e9da858c024","path":"frontend/Dockerfile","line_range":"1-15","gmt_create":"2026-04-23T21:00:59.634151+08:00","gmt_modified":"2026-04-23T21:00:59.634151+08:00"},{"id":"13f6ca76349ef86ae756bb519f122bc5","path":"backend/alembic.ini","line_range":"1-150","gmt_create":"2026-04-23T21:00:59.636129+08:00","gmt_modified":"2026-04-23T21:00:59.636129+08:00"},{"id":"74abd6612105c29b67178fa9dbd04b61","path":"frontend/tsconfig.json","line_range":"1-27","gmt_create":"2026-04-23T21:00:59.639808+08:00","gmt_modified":"2026-04-23T21:00:59.639808+08:00"},{"id":"9482f4f6279a4f636b77e69b8273b996","path":"backend/alembic.ini","line_range":"86-114","gmt_create":"2026-04-23T21:00:59.64068+08:00","gmt_modified":"2026-04-23T21:00:59.64068+08:00"},{"id":"397b266f19a1addebdf6c32db71ae77f","path":"tests/conftest.py","line_range":"1-71","gmt_create":"2026-04-23T21:00:59.640958+08:00","gmt_modified":"2026-04-23T21:00:59.640958+08:00"},{"id":"eb603ec2611957de67af00756f4b1efa","path":"backend/app/config.py","line_range":"7-13","gmt_create":"2026-04-23T21:00:59.64236+08:00","gmt_modified":"2026-04-23T21:00:59.64236+08:00"},{"id":"c25b39830f3b7734da975acc7f214666","path":"backend/Dockerfile","line_range":"31-33","gmt_create":"2026-04-23T21:00:59.642682+08:00","gmt_modified":"2026-04-23T21:00:59.642682+08:00"},{"id":"4c9d362ecce8e796e6f14850def049b0","path":"docker-compose.yml","line_range":"4-20","gmt_create":"2026-04-23T21:00:59.642976+08:00","gmt_modified":"2026-04-23T21:00:59.642976+08:00"},{"id":"d5827be2cfbe41c8177660ae877e93a4","path":"docker-compose.yml","line_range":"22-34","gmt_create":"2026-04-23T21:00:59.643262+08:00","gmt_modified":"2026-04-23T21:00:59.643262+08:00"},{"id":"03a65cdcfc173217d12ad8a417f8f033","path":"backend/app/main.py","line_range":"13-21","gmt_create":"2026-04-23T21:00:59.643535+08:00","gmt_modified":"2026-04-23T21:00:59.643535+08:00"},{"id":"3365fa8db33d43bab1d0a614e8af3a70","path":"backend/app/main.py","line_range":"45-47","gmt_create":"2026-04-23T21:00:59.644124+08:00","gmt_modified":"2026-04-23T21:00:59.644124+08:00"},{"id":"6f637c2b0796ec533aafb3b865c11cf0","path":"backend/app/schemas/auth.py","line_range":"1-34","gmt_create":"2026-04-23T21:00:59.646408+08:00","gmt_modified":"2026-04-23T21:00:59.646408+08:00"},{"id":"37bbab6e4f16db7eac6eee9d05e80e46","path":"README.md","line_range":"1-3","gmt_create":"2026-04-23T21:00:59.649625+08:00","gmt_modified":"2026-04-23T21:00:59.649625+08:00"},{"id":"bf363deac5ef38c8dc80c73b862e730b","path":"docker-compose.yml","line_range":"4-34","gmt_create":"2026-04-23T21:00:59.651828+08:00","gmt_modified":"2026-04-23T21:00:59.651828+08:00"},{"id":"c6e94075e5f689bfa2fe16f8cf965203","path":"tests/conftest.py","line_range":"19-50","gmt_create":"2026-04-23T21:00:59.65241+08:00","gmt_modified":"2026-04-23T21:00:59.65241+08:00"},{"id":"1a78f5574add6d07a1d7c947dba3f23d","path":"backend/alembic.ini","line_range":"115-150","gmt_create":"2026-04-23T21:00:59.652679+08:00","gmt_modified":"2026-04-23T21:00:59.652679+08:00"},{"id":"f6810849c947471a4b45d7ca01ec8c5f","path":"frontend/tailwind.config.ts","line_range":"5-9","gmt_create":"2026-04-23T21:00:59.653659+08:00","gmt_modified":"2026-04-23T21:00:59.653659+08:00"},{"id":"9f6d9941f3b93e29d714bfec7e83434c","path":"backend/app/main.py","line_range":"30-36","gmt_create":"2026-04-23T21:00:59.653983+08:00","gmt_modified":"2026-04-23T21:00:59.653984+08:00"},{"id":"85792f0b1e34b5b48b0300aa606ed6e6","path":"backend/app/main.py","line_range":"1-56","gmt_create":"2026-04-23T21:02:44.159246+08:00","gmt_modified":"2026-04-23T21:02:44.159246+08:00"},{"id":"f240c1067c223a019ba05b0fbd718aa4","path":"backend/app/main.py","line_range":"1-84","gmt_create":"2026-04-24T10:58:35.335284+08:00","gmt_modified":"2026-04-24T10:58:35.335284+08:00"},{"id":"a9fb75d1fdb833a11b36bc7b298f19be","path":"frontend/lib/api.ts","line_range":"1-154","gmt_create":"2026-04-24T10:58:35.349742+08:00","gmt_modified":"2026-04-24T10:58:35.349742+08:00"},{"id":"40325db1cb621a9af027150a8c5cf8e9","path":"frontend/lib/auth.ts","line_range":"1-73","gmt_create":"2026-04-24T10:58:35.350062+08:00","gmt_modified":"2026-04-24T10:58:35.350062+08:00"},{"id":"93d8c6a312849c344b6a9713b671840f","path":"backend/requirements.txt","line_range":"1-39","gmt_create":"2026-04-24T10:58:35.35098+08:00","gmt_modified":"2026-04-24T10:58:35.35098+08:00"},{"id":"844b21a35ae39ead76ff8831eb974e5a","path":"backend/app/main.py","line_range":"81-84","gmt_create":"2026-04-24T10:58:35.352287+08:00","gmt_modified":"2026-04-24T10:58:35.352287+08:00"},{"id":"3af33bd686ce3d418e31843cac66f58b","path":"backend/README.md","line_range":"12-67","gmt_create":"2026-04-24T10:58:35.35614+08:00","gmt_modified":"2026-04-24T10:58:35.356141+08:00"},{"id":"06c6dfcd66159d42fa9b9eafd1e36a04","path":"frontend/README.md","line_range":"11-34","gmt_create":"2026-04-24T10:58:35.35673+08:00","gmt_modified":"2026-04-24T10:58:35.35673+08:00"},{"id":"903da86dc3fb26783f45f247d60e9534","path":"backend/README.md","line_range":"69-126","gmt_create":"2026-04-24T10:58:35.357072+08:00","gmt_modified":"2026-04-24T10:58:35.357072+08:00"},{"id":"0ffe337a73c8fb7254f3e48932a8ae7f","path":"backend/README.md","line_range":"209-234","gmt_create":"2026-04-24T10:58:35.357641+08:00","gmt_modified":"2026-04-24T10:58:35.357642+08:00"},{"id":"55369db351eb916a3210b22f3d672162","path":"frontend/README.md","line_range":"161-170","gmt_create":"2026-04-24T10:58:35.358984+08:00","gmt_modified":"2026-04-24T10:58:35.358984+08:00"},{"id":"6c080aba7d0e611bd4e7f268835b630f","path":"backend/app/middleware/logging_middleware.py","line_range":"1-24","gmt_create":"2026-04-24T10:58:51.060864+08:00","gmt_modified":"2026-04-24T10:58:51.060864+08:00"},{"id":"a7bba55ddc4dd5d215e881e8432d83ea","path":"backend/app/middleware/rate_limit.py","line_range":"1-83","gmt_create":"2026-04-24T10:58:51.061198+08:00","gmt_modified":"2026-04-24T10:58:51.061198+08:00"},{"id":"7c7425c51cc43b8840cefd9764b47204","path":"backend/app/api/admin.py","line_range":"1-108","gmt_create":"2026-04-24T10:58:51.061492+08:00","gmt_modified":"2026-04-24T10:58:51.061492+08:00"},{"id":"6e4a52820e780e4b42651a8214ad4493","path":"backend/app/api/reports.py","line_range":"1-75","gmt_create":"2026-04-24T10:58:51.061762+08:00","gmt_modified":"2026-04-24T10:58:51.061763+08:00"},{"id":"4247da3fc00a7e5f8b73775321eccf8e","path":"backend/app/api/subscriptions.py","line_range":"1-77","gmt_create":"2026-04-24T10:58:51.062039+08:00","gmt_modified":"2026-04-24T10:58:51.062039+08:00"},{"id":"9bdd2f6103cf3cc8b3914b9d6d8812fb","path":"backend/app/services/admin.py","line_range":"1-188","gmt_create":"2026-04-24T10:58:51.062452+08:00","gmt_modified":"2026-04-24T10:58:51.062452+08:00"},{"id":"557281ca025f76d0dc2db67e56b44053","path":"backend/app/services/subscription.py","line_range":"1-155","gmt_create":"2026-04-24T10:58:51.062795+08:00","gmt_modified":"2026-04-24T10:58:51.062795+08:00"},{"id":"e2d4838e58acc0eee236ef586abab64e","path":"backend/app/main.py","line_range":"13-48","gmt_create":"2026-04-24T10:58:51.064016+08:00","gmt_modified":"2026-04-24T10:58:51.064016+08:00"},{"id":"8aee7654d1f435ab53d8ddaabd269fed","path":"backend/app/database.py","line_range":"6-29","gmt_create":"2026-04-24T10:58:51.06434+08:00","gmt_modified":"2026-04-24T10:58:51.06434+08:00"},{"id":"acd9e6c32084e589d5aeb1665d918dfd","path":"backend/app/api/deps.py","line_range":"13-43","gmt_create":"2026-04-24T10:58:51.064666+08:00","gmt_modified":"2026-04-24T10:58:51.064667+08:00"},{"id":"33ec8bca51cb9f667bf91088dd6b6a70","path":"backend/app/main.py","line_range":"24-48","gmt_create":"2026-04-24T10:58:51.065096+08:00","gmt_modified":"2026-04-24T10:58:51.065096+08:00"},{"id":"712424bd3bd3d5f39b1a0a72acc9952a","path":"backend/app/middleware/rate_limit.py","line_range":"10-83","gmt_create":"2026-04-24T10:58:51.065564+08:00","gmt_modified":"2026-04-24T10:58:51.065564+08:00"},{"id":"9357a0fcca02068d428f4a191d08fdcd","path":"backend/app/middleware/logging_middleware.py","line_range":"8-24","gmt_create":"2026-04-24T10:58:51.065888+08:00","gmt_modified":"2026-04-24T10:58:51.065888+08:00"},{"id":"8efcce12915471fe5b88fe058bcf238e","path":"backend/app/services/auth.py","line_range":"16-69","gmt_create":"2026-04-24T10:58:51.06648+08:00","gmt_modified":"2026-04-24T10:58:51.06648+08:00"},{"id":"7f81ebbdde3496054e6f43f5eef366dc","path":"backend/app/services/admin.py","line_range":"14-188","gmt_create":"2026-04-24T10:58:51.06683+08:00","gmt_modified":"2026-04-24T10:58:51.06683+08:00"},{"id":"f4d57f9a78585969a006b7451ea8ce84","path":"backend/app/services/subscription.py","line_range":"69-155","gmt_create":"2026-04-24T10:58:51.06716+08:00","gmt_modified":"2026-04-24T10:58:51.06716+08:00"},{"id":"608c00e1835ad72363ef08796961faca","path":"backend/app/config.py","line_range":"4-17","gmt_create":"2026-04-24T10:58:51.068971+08:00","gmt_modified":"2026-04-24T10:58:51.068971+08:00"},{"id":"ec4bf600a513dc2b014c85e141d7582d","path":"backend/app/workers/scheduler.py","line_range":"51-85","gmt_create":"2026-04-24T10:58:51.0746+08:00","gmt_modified":"2026-04-24T10:58:51.0746+08:00"},{"id":"9606b8243736b4a6f5ecfe152b2ab6dd","path":"backend/app/middleware/rate_limit.py","line_range":"34-83","gmt_create":"2026-04-24T10:58:51.079072+08:00","gmt_modified":"2026-04-24T10:58:51.079072+08:00"},{"id":"05664cbd35007caa5290760cc1ef1b99","path":"backend/app/api/admin.py","line_range":"29-108","gmt_create":"2026-04-24T10:58:51.079983+08:00","gmt_modified":"2026-04-24T10:58:51.079983+08:00"},{"id":"3d85cad939ce858f9c6d153d425c19fb","path":"backend/app/services/subscription.py","line_range":"25-155","gmt_create":"2026-04-24T10:58:51.081143+08:00","gmt_modified":"2026-04-24T10:58:51.081143+08:00"},{"id":"36769bd305cd5f664fa6e28f82e4b3e7","path":"backend/app/schemas/subscription.py","line_range":"1-41","gmt_create":"2026-04-24T10:58:51.08184+08:00","gmt_modified":"2026-04-24T10:58:51.08184+08:00"},{"id":"14c2d098319eeab16c64ff7d1447df6b","path":"backend/app/api/reports.py","line_range":"18-75","gmt_create":"2026-04-24T10:58:51.082903+08:00","gmt_modified":"2026-04-24T10:58:51.082904+08:00"},{"id":"1f8d26b6a5da49d89d95bb13c7ace2c6","path":"backend/app/models/user.py","line_range":"1-48","gmt_create":"2026-04-24T10:59:38.896976+08:00","gmt_modified":"2026-04-24T10:59:38.896976+08:00"},{"id":"c8f2dbcb7475bd189a34c7061ea46c6d","path":"backend/alembic/versions/c3d5e7f9ab12_add_user_management_fields.py","line_range":"1-41","gmt_create":"2026-04-24T10:59:38.901742+08:00","gmt_modified":"2026-04-24T10:59:38.901742+08:00"},{"id":"08c1475254a5bc8877ff29a895de3b6a","path":"backend/app/services/auth.py","line_range":"1-175","gmt_create":"2026-04-24T10:59:38.902658+08:00","gmt_modified":"2026-04-24T10:59:38.902658+08:00"},{"id":"f5978358d04c3c917d9ca5044c7f36fa","path":"backend/app/models/user.py","line_range":"11-48","gmt_create":"2026-04-24T10:59:38.903869+08:00","gmt_modified":"2026-04-24T10:59:38.903869+08:00"},{"id":"675ab6c1ae510ca753b5e966b7b6a10c","path":"backend/alembic/versions/c3d5e7f9ab12_add_user_management_fields.py","line_range":"21-41","gmt_create":"2026-04-24T10:59:38.907463+08:00","gmt_modified":"2026-04-24T10:59:38.907463+08:00"},{"id":"fe351bf59a46bec7f77ffe40a68a5993","path":"backend/app/services/auth.py","line_range":"40-56","gmt_create":"2026-04-24T10:59:38.917216+08:00","gmt_modified":"2026-04-24T10:59:38.917216+08:00"},{"id":"46e69841e5c5dc62faa55c9f066586d6","path":"backend/app/services/auth.py","line_range":"74-107","gmt_create":"2026-04-24T10:59:38.919469+08:00","gmt_modified":"2026-04-24T10:59:38.919469+08:00"},{"id":"cecc8857775f7928d465b68e429493d2","path":"backend/app/services/auth.py","line_range":"110-140","gmt_create":"2026-04-24T10:59:38.91977+08:00","gmt_modified":"2026-04-24T10:59:38.91977+08:00"},{"id":"1153d8a149a70bc79ca59a9dcba5945c","path":"backend/app/schemas/auth.py","line_range":"8-55","gmt_create":"2026-04-24T10:59:38.920046+08:00","gmt_modified":"2026-04-24T10:59:38.920046+08:00"},{"id":"35dd08df9c7a562d9c7b8edf740eaf3c","path":"backend/app/api/auth.py","line_range":"33-115","gmt_create":"2026-04-24T10:59:38.920424+08:00","gmt_modified":"2026-04-24T10:59:38.920424+08:00"},{"id":"dc735ee4a0f12140bcee122a67f4a13b","path":"frontend/components/layout/sidebar.tsx","line_range":"1-63","gmt_create":"2026-04-24T11:01:58.065941+08:00","gmt_modified":"2026-04-24T11:01:58.065941+08:00"},{"id":"f990ecd63842b3ab82f5b8c8dcde2a6b","path":"frontend/next.config.mjs","line_range":"1-5","gmt_create":"2026-04-24T11:01:58.066899+08:00","gmt_modified":"2026-04-24T11:01:58.0669+08:00"},{"id":"d5efa0fbc545b778dd913854d860c502","path":"frontend/types/next-auth.d.ts","line_range":"1-29","gmt_create":"2026-04-24T11:01:58.069351+08:00","gmt_modified":"2026-04-24T11:01:58.069351+08:00"},{"id":"46434c04e402674d97a6e2017a3a13c0","path":"backend/app/schemas/auth.py","line_range":"8-62","gmt_create":"2026-04-24T11:02:17.54295+08:00","gmt_modified":"2026-04-24T11:02:17.54295+08:00"},{"id":"3a0fd619768c80d413f8b02b3daec229","path":"backend/app/services/auth.py","line_range":"74-175","gmt_create":"2026-04-24T11:02:17.543584+08:00","gmt_modified":"2026-04-24T11:02:17.543584+08:00"},{"id":"86af0295eebcd62f33207e158db86c81","path":"backend/app/api/auth.py","line_range":"65-115","gmt_create":"2026-04-24T11:02:17.544119+08:00","gmt_modified":"2026-04-24T11:02:17.544119+08:00"},{"id":"809fc86e3ce390a1af1db1e0cd5ad787","path":"frontend/lib/api.ts","line_range":"55-84","gmt_create":"2026-04-24T11:02:17.544907+08:00","gmt_modified":"2026-04-24T11:02:17.544908+08:00"},{"id":"29ee02d164db08d7b9bd4591195e191b","path":"frontend/lib/auth.ts","line_range":"5-56","gmt_create":"2026-04-24T11:02:17.550558+08:00","gmt_modified":"2026-04-24T11:02:17.550559+08:00"},{"id":"73c4889fcacaea737921a568bf20383d","path":"frontend/lib/auth.ts","line_range":"13-32","gmt_create":"2026-04-24T11:02:17.552671+08:00","gmt_modified":"2026-04-24T11:02:17.552672+08:00"},{"id":"11c2505e56ba9a48c50be4c915f22c9d","path":"backend/app/services/auth.py","line_range":"27-37","gmt_create":"2026-04-24T11:02:17.554379+08:00","gmt_modified":"2026-04-24T11:02:17.554379+08:00"},{"id":"5f32b18b18cea3b2bdc9150366c24e5e","path":"backend/app/api/deps.py","line_range":"26-37","gmt_create":"2026-04-24T11:02:17.554832+08:00","gmt_modified":"2026-04-24T11:02:17.554832+08:00"},{"id":"c4abaa8a82ad75d09ee66f97fbad4b96","path":"backend/app/config.py","line_range":"9-10","gmt_create":"2026-04-24T11:02:17.555347+08:00","gmt_modified":"2026-04-24T11:02:17.555347+08:00"},{"id":"08ac91fb508b386f0e6c66e53b03a471","path":"backend/app/schemas/auth.py","line_range":"8-11","gmt_create":"2026-04-24T11:02:17.556938+08:00","gmt_modified":"2026-04-24T11:02:17.556938+08:00"},{"id":"d4ea500c0acb4ebf267a44908e23f787","path":"backend/app/services/auth.py","line_range":"40-55","gmt_create":"2026-04-24T11:02:17.557577+08:00","gmt_modified":"2026-04-24T11:02:17.557577+08:00"},{"id":"b4f0bea37f71296167571d8831ebe6d5","path":"tests/test_auth.py","line_range":"25-58","gmt_create":"2026-04-24T11:02:17.558569+08:00","gmt_modified":"2026-04-24T11:02:17.558569+08:00"},{"id":"46f7431da5eb82bbd7686a71abaddf78","path":"backend/app/api/auth.py","line_range":"42-57","gmt_create":"2026-04-24T11:02:17.558961+08:00","gmt_modified":"2026-04-24T11:02:17.558961+08:00"},{"id":"0ba2ea54873608360c48c8b5aaeea20f","path":"backend/app/services/auth.py","line_range":"58-71","gmt_create":"2026-04-24T11:02:17.559312+08:00","gmt_modified":"2026-04-24T11:02:17.559312+08:00"},{"id":"2d170933ae8c838199f6d68a2b9165c0","path":"tests/test_auth.py","line_range":"61-84","gmt_create":"2026-04-24T11:02:17.560326+08:00","gmt_modified":"2026-04-24T11:02:17.560327+08:00"},{"id":"0ea85b56099b9087bd22eec96b7bb752","path":"backend/app/services/auth.py","line_range":"74-140","gmt_create":"2026-04-24T11:02:17.560916+08:00","gmt_modified":"2026-04-24T11:02:17.560916+08:00"},{"id":"2a4087b6941ca17dd651147f2f23451c","path":"backend/app/api/auth.py","line_range":"65-90","gmt_create":"2026-04-24T11:02:17.561945+08:00","gmt_modified":"2026-04-24T11:02:17.561945+08:00"},{"id":"88c12e200d5c3ea53c695aa4209cecd9","path":"backend/app/api/auth.py","line_range":"65-76","gmt_create":"2026-04-24T11:02:17.562602+08:00","gmt_modified":"2026-04-24T11:02:17.562603+08:00"},{"id":"42b92d878423a23067e9a6da104e3a5e","path":"backend/app/api/auth.py","line_range":"79-90","gmt_create":"2026-04-24T11:02:17.564153+08:00","gmt_modified":"2026-04-24T11:02:17.564153+08:00"},{"id":"abadc99952ad6e00ab4bfb66b84732bb","path":"backend/app/schemas/auth.py","line_range":"33-41","gmt_create":"2026-04-24T11:02:17.56603+08:00","gmt_modified":"2026-04-24T11:02:17.56603+08:00"},{"id":"f784a33e47128515d518555d99103f62","path":"backend/app/services/auth.py","line_range":"143-175","gmt_create":"2026-04-24T11:02:17.566806+08:00","gmt_modified":"2026-04-24T11:02:17.566806+08:00"},{"id":"173f8de5896e18fc81cdd5d72e2a8c07","path":"backend/app/api/auth.py","line_range":"93-115","gmt_create":"2026-04-24T11:02:17.567894+08:00","gmt_modified":"2026-04-24T11:02:17.567894+08:00"},{"id":"3ab144009e705151f69698d2d8a81cea","path":"backend/app/services/auth.py","line_range":"35-37","gmt_create":"2026-04-24T11:02:17.56892+08:00","gmt_modified":"2026-04-24T11:02:17.56892+08:00"},{"id":"570a917d85850ab1208fce5823b110a3","path":"backend/app/api/auth.py","line_range":"60-62","gmt_create":"2026-04-24T11:02:17.569617+08:00","gmt_modified":"2026-04-24T11:02:17.569617+08:00"},{"id":"f92c0c41197c488f04f994bf0f7ea465","path":"tests/test_auth.py","line_range":"87-104","gmt_create":"2026-04-24T11:02:17.570008+08:00","gmt_modified":"2026-04-24T11:02:17.570008+08:00"},{"id":"5688471e2418628ac2a6409451708d06","path":"backend/app/api/auth.py","line_range":"1-115","gmt_create":"2026-04-24T11:02:17.571751+08:00","gmt_modified":"2026-04-24T11:02:17.571751+08:00"},{"id":"7075cde1c771c46dbbd37b3c09dac53d","path":"backend/app/api/deps.py","line_range":"20-41","gmt_create":"2026-04-24T11:02:17.576276+08:00","gmt_modified":"2026-04-24T11:02:17.576276+08:00"},{"id":"607e99e751640281d26516c772548b93","path":"frontend/lib/api.ts","line_range":"17-39","gmt_create":"2026-04-24T11:02:17.576883+08:00","gmt_modified":"2026-04-24T11:02:17.576883+08:00"},{"id":"0fcc0fe680a7ca8b8c7f4d579b77aeec","path":"backend/app/main.py","line_range":"12-78","gmt_create":"2026-04-24T11:02:30.018464+08:00","gmt_modified":"2026-04-24T11:02:30.018464+08:00"},{"id":"10d3948b1394ffa0110796edfa0bfc25","path":"backend/app/api/auth.py","line_range":"30","gmt_create":"2026-04-24T11:02:30.018782+08:00","gmt_modified":"2026-04-24T11:02:30.018782+08:00"},{"id":"d6ebce8c7d9e9de127486400670ebed0","path":"backend/app/main.py","line_range":"39-84","gmt_create":"2026-04-24T11:02:30.020913+08:00","gmt_modified":"2026-04-24T11:02:30.020913+08:00"},{"id":"ec3ed02cad3cd8af4bacb5c978273092","path":"backend/app/api/subscriptions.py","line_range":"26-77","gmt_create":"2026-04-24T11:02:30.021508+08:00","gmt_modified":"2026-04-24T11:02:30.021509+08:00"},{"id":"2db9940a42c91fc92f23595491ea93d1","path":"backend/app/main.py","line_range":"67-78","gmt_create":"2026-04-24T11:02:30.022384+08:00","gmt_modified":"2026-04-24T11:02:30.022384+08:00"},{"id":"68fbb2bd365f96a98ea187a9738c4460","path":"backend/app/api/auth.py","line_range":"33-57","gmt_create":"2026-04-24T11:02:30.024114+08:00","gmt_modified":"2026-04-24T11:02:30.024114+08:00"},{"id":"44f9c9f195e096efbd6c6a6f97880944","path":"backend/app/api/reports.py","line_range":"51-75","gmt_create":"2026-04-24T11:02:30.02932+08:00","gmt_modified":"2026-04-24T11:02:30.02932+08:00"},{"id":"cbe8ffc1cfb98ac79c7659e968191837","path":"backend/app/services/citation.py","line_range":"343-466","gmt_create":"2026-04-24T11:02:30.029647+08:00","gmt_modified":"2026-04-24T11:02:30.029647+08:00"},{"id":"97f9b6149bd43feb0f69cf2582ab6305","path":"backend/app/services/subscription.py","line_range":"85-117","gmt_create":"2026-04-24T11:02:30.030707+08:00","gmt_modified":"2026-04-24T11:02:30.030707+08:00"},{"id":"ce4de96353f8f81ca825173ddbec1150","path":"backend/app/schemas/subscription.py","line_range":"12-41","gmt_create":"2026-04-24T11:02:30.031384+08:00","gmt_modified":"2026-04-24T11:02:30.031384+08:00"},{"id":"a87a1a7c1723518159d5818c197996cc","path":"backend/app/services/subscription.py","line_range":"56-155","gmt_create":"2026-04-24T11:02:30.031685+08:00","gmt_modified":"2026-04-24T11:02:30.031686+08:00"},{"id":"0e4bc0a539e0ccc6832031bdaf1eb1ca","path":"backend/app/api/admin.py","line_range":"29-45","gmt_create":"2026-04-24T11:02:30.031966+08:00","gmt_modified":"2026-04-24T11:02:30.031966+08:00"},{"id":"f7314a4515e822cba6f37d7a8f1970f3","path":"backend/app/services/admin.py","line_range":"14-46","gmt_create":"2026-04-24T11:02:30.032241+08:00","gmt_modified":"2026-04-24T11:02:30.032242+08:00"},{"id":"ef31f4aa4fbd1b6ff76eba467b757a04","path":"backend/app/middleware/rate_limit.py","line_range":"34-69","gmt_create":"2026-04-24T11:02:30.033139+08:00","gmt_modified":"2026-04-24T11:02:30.03314+08:00"},{"id":"3a7201f4564dbcf35c5771f1b5d58cb6","path":"backend/app/api/auth.py","line_range":"46-50","gmt_create":"2026-04-24T11:02:30.037193+08:00","gmt_modified":"2026-04-24T11:02:30.037193+08:00"},{"id":"39c3dbe67ab2ae74446fe6a118bd8738","path":"backend/app/api/reports.py","line_range":"25-29","gmt_create":"2026-04-24T11:02:30.038125+08:00","gmt_modified":"2026-04-24T11:02:30.038125+08:00"},{"id":"68d937267aab2509edc0c7b67e1b5ef6","path":"backend/app/api/subscriptions.py","line_range":"53-57","gmt_create":"2026-04-24T11:02:30.038578+08:00","gmt_modified":"2026-04-24T11:02:30.038578+08:00"},{"id":"3d0bf5a05f6a7d2b8b12bb91e8f93642","path":"backend/app/api/admin.py","line_range":"22-25","gmt_create":"2026-04-24T11:02:30.038936+08:00","gmt_modified":"2026-04-24T11:02:30.038936+08:00"},{"id":"a9c1b0716ae36af22fce6148c2e40ce5","path":"backend/app/middleware/rate_limit.py","line_range":"47-49","gmt_create":"2026-04-24T11:02:30.039285+08:00","gmt_modified":"2026-04-24T11:02:30.039285+08:00"},{"id":"461200c8ca02024dd32c214c679b9664","path":"backend/app/agent_framework/agents/content_generator_agent.py","line_range":"1-299","gmt_create":"2026-05-23T15:16:36.150133+08:00","gmt_modified":"2026-05-23T15:16:36.150133+08:00"},{"id":"7f44b646183e17098f8ce4d2be931d3e","path":"backend/app/agent_framework/agents/deai_agent.py","line_range":"1-156","gmt_create":"2026-05-23T15:16:36.15079+08:00","gmt_modified":"2026-05-23T15:16:36.15079+08:00"},{"id":"45778eaa35d92099677ba180f1067905","path":"backend/app/agent_framework/agents/geo_optimizer_agent.py","line_range":"1-198","gmt_create":"2026-05-23T15:16:36.151168+08:00","gmt_modified":"2026-05-23T15:16:36.151168+08:00"},{"id":"74bf1d1b17dff651c44a2f4dc12d7bc7","path":"backend/app/agent_framework/pipeline/engine.py","line_range":"1-536","gmt_create":"2026-05-23T15:16:36.151542+08:00","gmt_modified":"2026-05-23T15:16:36.151542+08:00"},{"id":"d8a98dd989912e358f7dbd278e1c5353","path":"backend/app/agent_framework/pipeline/loader.py","line_range":"1-283","gmt_create":"2026-05-23T15:16:36.152324+08:00","gmt_modified":"2026-05-23T15:16:36.152324+08:00"},{"id":"3d0cd79c03fc72299fb184947c5d0d6c","path":"backend/app/services/llm/factory.py","line_range":"1-66","gmt_create":"2026-05-23T15:16:36.152776+08:00","gmt_modified":"2026-05-23T15:16:36.152776+08:00"},{"id":"c43dadd2749edf2a89b29068d7644bb9","path":"tests/test_content_agents.py","line_range":"26-54","gmt_create":"2026-05-23T15:16:36.155935+08:00","gmt_modified":"2026-05-23T15:16:36.155935+08:00"},{"id":"3251d42aeb8cbe7f90d0e9827fbecdb8","path":"tests/test_pipeline_engine.py","line_range":"148-166","gmt_create":"2026-05-23T15:16:36.156829+08:00","gmt_modified":"2026-05-23T15:16:36.156829+08:00"},{"id":"8cdfa09247c1ca69fa5581194d1dc998","path":"tests/test_content_agents.py","line_range":"75-116","gmt_create":"2026-05-23T15:16:36.17723+08:00","gmt_modified":"2026-05-23T15:16:36.177231+08:00"},{"id":"4d43427ff0dc504c0665bd3e3f86d68c","path":"tests/test_content_agents.py","line_range":"200-236","gmt_create":"2026-05-23T15:16:36.178007+08:00","gmt_modified":"2026-05-23T15:16:36.178008+08:00"},{"id":"7ec53d0bb9dd7a59cedbd4d3865fddf8","path":"tests/test_content_agents.py","line_range":"268-320","gmt_create":"2026-05-23T15:16:36.178749+08:00","gmt_modified":"2026-05-23T15:16:36.178749+08:00"},{"id":"67b04d8d66c36c9362f3c42260f08d77","path":"tests/test_content_agents.py","line_range":"1-358","gmt_create":"2026-05-23T15:16:36.179312+08:00","gmt_modified":"2026-05-23T15:16:36.179312+08:00"},{"id":"a29fa4c505649339b1a61e2bd730e05a","path":"tests/test_llm_provider.py","line_range":"24-67","gmt_create":"2026-05-23T15:16:36.181057+08:00","gmt_modified":"2026-05-23T15:16:36.181057+08:00"},{"id":"892c4889ccac1ebb4f9871633c633fb0","path":"tests/test_llm_provider.py","line_range":"94-153","gmt_create":"2026-05-23T15:16:36.181436+08:00","gmt_modified":"2026-05-23T15:16:36.181436+08:00"},{"id":"5a90244fc04639f59621ea190b395d53","path":"tests/test_llm_provider.py","line_range":"200-204","gmt_create":"2026-05-23T15:16:36.18181+08:00","gmt_modified":"2026-05-23T15:16:36.18181+08:00"},{"id":"7a5c445db631fd099bd752645fe46eeb","path":"backend/app/services/llm/factory.py","line_range":"8-66","gmt_create":"2026-05-23T15:16:36.182157+08:00","gmt_modified":"2026-05-23T15:16:36.182157+08:00"},{"id":"470e94b38cfbc9bfa40075043a5ff609","path":"tests/test_llm_provider.py","line_range":"1-205","gmt_create":"2026-05-23T15:16:36.182504+08:00","gmt_modified":"2026-05-23T15:16:36.182504+08:00"},{"id":"e2014a3633197a028b389f084f136010","path":"tests/test_pipeline_engine.py","line_range":"55-98","gmt_create":"2026-05-23T15:16:36.18324+08:00","gmt_modified":"2026-05-23T15:16:36.183241+08:00"},{"id":"4d80ca6fa9f1355807471a059213113a","path":"tests/test_pipeline_engine.py","line_range":"148-223","gmt_create":"2026-05-23T15:16:36.183606+08:00","gmt_modified":"2026-05-23T15:16:36.183606+08:00"},{"id":"1c16d98271c83e4d1bf7759d6eff90e7","path":"backend/app/agent_framework/pipeline/loader.py","line_range":"41-134","gmt_create":"2026-05-23T15:16:36.183951+08:00","gmt_modified":"2026-05-23T15:16:36.183951+08:00"},{"id":"32e64c6a06a68a4c10f248296033c62e","path":"backend/app/agent_framework/pipeline/engine.py","line_range":"31-176","gmt_create":"2026-05-23T15:16:36.184299+08:00","gmt_modified":"2026-05-23T15:16:36.184299+08:00"},{"id":"a593c13b0e0e255b16b161d69fcd4c09","path":"tests/test_pipeline_engine.py","line_range":"1-255","gmt_create":"2026-05-23T15:16:36.184645+08:00","gmt_modified":"2026-05-23T15:16:36.184646+08:00"},{"id":"7a0c4604142743b83dfb37f2ff1aa3e8","path":"backend/tests/test_integration/test_full_flow.py","line_range":"94-223","gmt_create":"2026-05-23T15:16:36.186659+08:00","gmt_modified":"2026-05-23T15:16:36.18666+08:00"},{"id":"3548385bba6b1c5a95d40191fbb95fc4","path":"backend/tests/test_integration/test_full_flow.py","line_range":"228-298","gmt_create":"2026-05-23T15:16:36.187173+08:00","gmt_modified":"2026-05-23T15:16:36.187174+08:00"},{"id":"4c439b670fff499e1277c271ed2e3598","path":"backend/tests/test_integration/test_full_flow.py","line_range":"1-322","gmt_create":"2026-05-23T15:16:36.187672+08:00","gmt_modified":"2026-05-23T15:16:36.187672+08:00"},{"id":"0a5c3d0a239107364b77b52d4ff33454","path":"backend/app/api/agents.py","line_range":"29","gmt_create":"2026-05-23T15:17:24.09425+08:00","gmt_modified":"2026-05-23T15:17:24.09425+08:00"},{"id":"6c9ecb8d32dfd5ce9b2dc95f1a110d97","path":"backend/app/api/analytics.py","line_range":"26","gmt_create":"2026-05-23T15:17:24.095854+08:00","gmt_modified":"2026-05-23T15:17:24.095854+08:00"},{"id":"6242be39e66058ce4f2dd93974e98599","path":"backend/app/api/lifecycle.py","line_range":"24","gmt_create":"2026-05-23T15:17:24.096741+08:00","gmt_modified":"2026-05-23T15:17:24.096741+08:00"},{"id":"3dde6ad029645735cef7c4edf22b28c3","path":"backend/app/api/knowledge.py","line_range":"38","gmt_create":"2026-05-23T15:17:24.097406+08:00","gmt_modified":"2026-05-23T15:17:24.097406+08:00"},{"id":"c7cbd948815aa81602e95e7e469a2b80","path":"backend/app/api/agents.py","line_range":"66-299","gmt_create":"2026-05-23T15:17:24.099768+08:00","gmt_modified":"2026-05-23T15:17:24.099769+08:00"},{"id":"c666a867c1b927bcc12241a45e84cd71","path":"backend/app/api/analytics.py","line_range":"47-243","gmt_create":"2026-05-23T15:17:24.100264+08:00","gmt_modified":"2026-05-23T15:17:24.100264+08:00"},{"id":"196c325b93526e566ba9f2560a82c2ac","path":"backend/app/api/lifecycle.py","line_range":"85-297","gmt_create":"2026-05-23T15:17:24.100674+08:00","gmt_modified":"2026-05-23T15:17:24.100674+08:00"},{"id":"f617a59447265c18ad5d4c79e9db8e12","path":"backend/app/api/knowledge.py","line_range":"81-502","gmt_create":"2026-05-23T15:17:24.101317+08:00","gmt_modified":"2026-05-23T15:17:24.101318+08:00"},{"id":"ffb5c89d546d3895e7ac0ed320a6ed90","path":"backend/app/api/agents.py","line_range":"186-222","gmt_create":"2026-05-23T15:17:24.127315+08:00","gmt_modified":"2026-05-23T15:17:24.127315+08:00"},{"id":"e6fe884abc694714e2eb8bf1be27d72b","path":"backend/app/models/agent.py","line_range":"98-155","gmt_create":"2026-05-23T15:17:24.128304+08:00","gmt_modified":"2026-05-23T15:17:24.128304+08:00"},{"id":"ebc123c07512c5d5aeb1011d228a895c","path":"backend/app/models/agent.py","line_range":"12-206","gmt_create":"2026-05-23T15:17:24.129859+08:00","gmt_modified":"2026-05-23T15:17:24.129859+08:00"},{"id":"9cbf60c1b6ff2f8c74be2f168f4f44eb","path":"backend/app/api/analytics.py","line_range":"47-60","gmt_create":"2026-05-23T15:17:24.130699+08:00","gmt_modified":"2026-05-23T15:17:24.130699+08:00"},{"id":"eb865aa7324cbb6c6ec83cf884c36b98","path":"backend/app/api/analytics.py","line_range":"206-212","gmt_create":"2026-05-23T15:17:24.131272+08:00","gmt_modified":"2026-05-23T15:17:24.131272+08:00"},{"id":"68580333c31256edc20b45d90197222c","path":"backend/app/schemas/analytics.py","line_range":"14-145","gmt_create":"2026-05-23T15:17:24.13239+08:00","gmt_modified":"2026-05-23T15:17:24.13239+08:00"},{"id":"98d6d7fe81309b5f48907ff2c96bd9e9","path":"backend/app/api/lifecycle.py","line_range":"190-230","gmt_create":"2026-05-23T15:17:24.133293+08:00","gmt_modified":"2026-05-23T15:17:24.133293+08:00"},{"id":"4d98c570e47fa5aa35c93cc23d9a9531","path":"backend/app/schemas/lifecycle.py","line_range":"9-68","gmt_create":"2026-05-23T15:17:24.134291+08:00","gmt_modified":"2026-05-23T15:17:24.134291+08:00"},{"id":"6a2a5a7cb69cc0e72c2e90e1d9e48037","path":"backend/app/models/lifecycle.py","line_range":"12-92","gmt_create":"2026-05-23T15:17:24.134691+08:00","gmt_modified":"2026-05-23T15:17:24.134692+08:00"},{"id":"f38b21f300a72d77625c203e8d9e5916","path":"backend/app/api/knowledge.py","line_range":"424-501","gmt_create":"2026-05-23T15:17:24.135099+08:00","gmt_modified":"2026-05-23T15:17:24.135099+08:00"},{"id":"02ee224326bf5a0307c63b44ccb270ac","path":"backend/app/schemas/knowledge.py","line_range":"9-77","gmt_create":"2026-05-23T15:17:24.135982+08:00","gmt_modified":"2026-05-23T15:17:24.135983+08:00"},{"id":"f043b2767c713f94381e9f7154cd904a","path":"backend/app/models/knowledge.py","line_range":"22-213","gmt_create":"2026-05-23T15:17:24.136389+08:00","gmt_modified":"2026-05-23T15:17:24.136389+08:00"},{"id":"934240d46ff47296dae2c8aef650b86f","path":"backend/app/api/agents.py","line_range":"84-88","gmt_create":"2026-05-23T15:17:24.153907+08:00","gmt_modified":"2026-05-23T15:17:24.153907+08:00"},{"id":"be2989f88e1e49d5282ec7353c9c4e89","path":"backend/app/api/analytics.py","line_range":"36-40","gmt_create":"2026-05-23T15:17:24.154515+08:00","gmt_modified":"2026-05-23T15:17:24.154515+08:00"},{"id":"3b33430ff6a3ac8b10af49dc35af8231","path":"backend/app/api/lifecycle.py","line_range":"146","gmt_create":"2026-05-23T15:17:24.155164+08:00","gmt_modified":"2026-05-23T15:17:24.155164+08:00"},{"id":"59b4deade567af54c91f1a162e57b5be","path":"backend/app/api/knowledge.py","line_range":"92-96","gmt_create":"2026-05-23T15:17:24.155766+08:00","gmt_modified":"2026-05-23T15:17:24.155766+08:00"},{"id":"6171fd1748ad5189394ba670000e7e75","path":"frontend/package.json","line_range":"1-45","gmt_create":"2026-05-23T15:18:41.062838+08:00","gmt_modified":"2026-05-23T15:18:41.062838+08:00"},{"id":"00502fc9ffc15147665f96f056735d74","path":"backend/requirements.txt","line_range":"1-42","gmt_create":"2026-05-23T15:18:41.064091+08:00","gmt_modified":"2026-05-23T15:18:41.064092+08:00"},{"id":"dd36901ce62b8cc1d66667dcdc45e637","path":"backend/app/config.py","line_range":"1-46","gmt_create":"2026-05-23T15:18:41.071093+08:00","gmt_modified":"2026-05-23T15:18:41.071093+08:00"},{"id":"36ca3ba8293eaed314a7628b0272e957","path":"frontend/.eslintrc.json","line_range":"1-14","gmt_create":"2026-05-23T15:18:41.088084+08:00","gmt_modified":"2026-05-23T15:18:41.088084+08:00"},{"id":"03b024618527c930185a98873f353b45","path":"backend/app/config.py","line_range":"12-18","gmt_create":"2026-05-23T15:18:41.091753+08:00","gmt_modified":"2026-05-23T15:18:41.091753+08:00"},{"id":"1693d293c428ed4a66bd90519a1bbad5","path":"backend/app/config.py","line_range":"12-13","gmt_create":"2026-05-23T15:18:41.103505+08:00","gmt_modified":"2026-05-23T15:18:41.103505+08:00"},{"id":"c4f552eaa67bc052a06af7e5399d954c","path":"backend/app/config.py","line_range":"9-46","gmt_create":"2026-05-23T15:18:41.11012+08:00","gmt_modified":"2026-05-23T15:18:41.11012+08:00"},{"id":"db1c839ece4f3899017126c9b5b36016","path":"docs/03-development/coding-standards.md","line_range":"1-29","gmt_create":"2026-05-23T15:18:41.114928+08:00","gmt_modified":"2026-05-23T15:18:41.114928+08:00"},{"id":"9efa352ff057d696763b5eca047c0ca1","path":"docs/03-development/dev-guide.md","line_range":"1-32","gmt_create":"2026-05-23T15:18:41.116419+08:00","gmt_modified":"2026-05-23T15:18:41.11642+08:00"},{"id":"10a5c824715b3c199eb40e1531c64150","path":"docs/03-development/tdd-workflow.md","line_range":"1-583","gmt_create":"2026-05-23T15:18:41.118231+08:00","gmt_modified":"2026-05-23T15:18:41.118231+08:00"},{"id":"a47a364b551a984436d38cc17a272ef5","path":"docs/04-testing/test-strategy.md","line_range":"1-33","gmt_create":"2026-05-23T15:18:41.118882+08:00","gmt_modified":"2026-05-23T15:18:41.118882+08:00"},{"id":"6d2bbc04de724a57683b6d1af6f76e5b","path":"docs/05-deployment/deployment-guide.md","line_range":"1-32","gmt_create":"2026-05-23T15:18:41.11976+08:00","gmt_modified":"2026-05-23T15:18:41.11976+08:00"},{"id":"67f5802e0fa695697eb6eeb1d1071448","path":"docs/00-project/tech-stack.md","line_range":"1-71","gmt_create":"2026-05-23T15:18:41.123994+08:00","gmt_modified":"2026-05-23T15:18:41.123994+08:00"},{"id":"87eaeed0bc611204a7529b148ae846e2","path":"backend/app/models/lifecycle.py","line_range":"1-92","gmt_create":"2026-05-23T15:19:23.483625+08:00","gmt_modified":"2026-05-23T15:19:23.483626+08:00"},{"id":"790fb08a04a977bb97a81ea19d785777","path":"backend/app/models/analytics.py","line_range":"1-64","gmt_create":"2026-05-23T15:19:23.48412+08:00","gmt_modified":"2026-05-23T15:19:23.48412+08:00"},{"id":"7bf4a8a5aa73c1704f76f4947a1a327a","path":"backend/app/models/alert.py","line_range":"1-75","gmt_create":"2026-05-23T15:19:23.484664+08:00","gmt_modified":"2026-05-23T15:19:23.484664+08:00"},{"id":"9b03c2a2c7f00f40338248fa6d6f5c8b","path":"backend/app/models/knowledge.py","line_range":"1-213","gmt_create":"2026-05-23T15:19:23.485069+08:00","gmt_modified":"2026-05-23T15:19:23.485069+08:00"},{"id":"d15e1f6c18afa7505178062959fe7333","path":"backend/alembic/versions/d4f6g8h0ab23_add_geo_lifecycle_tables.py","line_range":"1-398","gmt_create":"2026-05-23T15:19:23.493615+08:00","gmt_modified":"2026-05-23T15:19:23.493616+08:00"},{"id":"762a2f675ceac5ab98af9a601f886b64","path":"backend/alembic/versions/f6g8h0i2de56_add_analytics_tables.py","line_range":"1-125","gmt_create":"2026-05-23T15:19:23.49436+08:00","gmt_modified":"2026-05-23T15:19:23.494361+08:00"},{"id":"2df394b949344fe9ab2c77227b91a836","path":"backend/alembic/versions/e5f7a9b1cd34_add_alerts_and_alert_settings_tables.py","line_range":"1-86","gmt_create":"2026-05-23T15:19:23.494948+08:00","gmt_modified":"2026-05-23T15:19:23.494949+08:00"},{"id":"0dc739a646e968be4ef81f8d6f73172f","path":"backend/alembic/versions/e5f7g9h1cd45_add_knowledge_base_tables.py","line_range":"1-224","gmt_create":"2026-05-23T15:19:23.495801+08:00","gmt_modified":"2026-05-23T15:19:23.495802+08:00"},{"id":"867308b1867163b86fcf5da125bff7bd","path":"backend/app/models/analytics.py","line_range":"9-64","gmt_create":"2026-05-23T15:19:23.500977+08:00","gmt_modified":"2026-05-23T15:19:23.500977+08:00"},{"id":"7bb1fe5eea543a455c000decbf835a87","path":"backend/app/models/alert.py","line_range":"24-75","gmt_create":"2026-05-23T15:19:23.50143+08:00","gmt_modified":"2026-05-23T15:19:23.50143+08:00"},{"id":"14d45085df87325a1a8a05e5a7306ea9","path":"backend/alembic/versions/d4f6g8h0ab23_add_geo_lifecycle_tables.py","line_range":"24-398","gmt_create":"2026-05-23T15:19:23.507299+08:00","gmt_modified":"2026-05-23T15:19:23.507299+08:00"},{"id":"ab4062f7b12bddc89c8a6ecb5716ec22","path":"backend/alembic/versions/f6g8h0i2de56_add_analytics_tables.py","line_range":"24-125","gmt_create":"2026-05-23T15:19:23.508028+08:00","gmt_modified":"2026-05-23T15:19:23.508028+08:00"},{"id":"d8c1ac7c70dcfce3893bb34ccad2ea86","path":"backend/alembic/versions/e5f7a9b1cd34_add_alerts_and_alert_settings_tables.py","line_range":"24-86","gmt_create":"2026-05-23T15:19:23.508459+08:00","gmt_modified":"2026-05-23T15:19:23.50846+08:00"},{"id":"3f54e06cbaf0717d01fb0f4cb7294795","path":"backend/alembic/versions/e5f7g9h1cd45_add_knowledge_base_tables.py","line_range":"30-224","gmt_create":"2026-05-23T15:19:23.509955+08:00","gmt_modified":"2026-05-23T15:19:23.509955+08:00"},{"id":"948aa417b68df80b5de0cfdb37e5455e","path":"backend/alembic/versions/d4f6g8h0ab23_add_geo_lifecycle_tables.py","line_range":"21-398","gmt_create":"2026-05-23T15:19:23.520133+08:00","gmt_modified":"2026-05-23T15:19:23.520133+08:00"},{"id":"96de5ca994afbb0cc75f2b0d419d69f7","path":"backend/alembic/versions/e5f7a9b1cd34_add_alerts_and_alert_settings_tables.py","line_range":"21-86","gmt_create":"2026-05-23T15:19:23.520982+08:00","gmt_modified":"2026-05-23T15:19:23.520983+08:00"},{"id":"5f830240a0d18e5b3718cd8cabebed6e","path":"backend/alembic/versions/e5f7g9h1cd45_add_knowledge_base_tables.py","line_range":"21-224","gmt_create":"2026-05-23T15:19:23.521489+08:00","gmt_modified":"2026-05-23T15:19:23.521489+08:00"},{"id":"4a7611bf0d84c8d44518673bbe5af6ad","path":"backend/alembic/versions/f6g8h0i2de56_add_analytics_tables.py","line_range":"20-125","gmt_create":"2026-05-23T15:19:23.521904+08:00","gmt_modified":"2026-05-23T15:19:23.521904+08:00"},{"id":"cb292fb9d8227e14f98eed613b793a74","path":"backend/app/main.py","line_range":"1-100","gmt_create":"2026-05-23T15:19:55.736691+08:00","gmt_modified":"2026-05-23T15:19:55.736691+08:00"},{"id":"1aa2eb624a63acddcd9638630606b2e9","path":"backend/app/workers/scheduler.py","line_range":"1-189","gmt_create":"2026-05-23T15:19:55.738809+08:00","gmt_modified":"2026-05-23T15:19:55.738809+08:00"},{"id":"a03d722c5d84b49db41742b78679a2f8","path":"docker-compose.yml","line_range":"36-66","gmt_create":"2026-05-23T15:19:55.748044+08:00","gmt_modified":"2026-05-23T15:19:55.748045+08:00"},{"id":"f7e662afe370f458b73886fe90709a23","path":"backend/app/main.py","line_range":"97-100","gmt_create":"2026-05-23T15:19:55.748518+08:00","gmt_modified":"2026-05-23T15:19:55.748519+08:00"},{"id":"50925c15ef4105b22c55cd16d44103a1","path":"backend/app/main.py","line_range":"33-45","gmt_create":"2026-05-23T15:19:55.749705+08:00","gmt_modified":"2026-05-23T15:19:55.749705+08:00"},{"id":"6d4024210922cde4cb5f7944996640c5","path":"backend/app/config.py","line_range":"12-14","gmt_create":"2026-05-23T15:19:55.750168+08:00","gmt_modified":"2026-05-23T15:19:55.750169+08:00"},{"id":"b32f57d9055ac4c655dfc976b1fd51a4","path":"backend/app/workers/scheduler.py","line_range":"33-51","gmt_create":"2026-05-23T15:19:55.751771+08:00","gmt_modified":"2026-05-23T15:19:55.751771+08:00"},{"id":"60f56d5de44cd7f96dbf71d74290910d","path":"backend/app/main.py","line_range":"53-63","gmt_create":"2026-05-23T15:19:55.756309+08:00","gmt_modified":"2026-05-23T15:19:55.756309+08:00"},{"id":"0d92cb154d0e27b75793e9a25e3211c4","path":"backend/alembic.ini","line_range":"86-89","gmt_create":"2026-05-23T15:19:55.757947+08:00","gmt_modified":"2026-05-23T15:19:55.757948+08:00"},{"id":"13b13aa0fd51de34b0cfb27187df0eb0","path":"backend/app/config.py","line_range":"14","gmt_create":"2026-05-23T15:19:55.76513+08:00","gmt_modified":"2026-05-23T15:19:55.76513+08:00"},{"id":"dfaa01739b500883c182fe0ee7b38f02","path":"backend/requirements.txt","line_range":"35-42","gmt_create":"2026-05-23T15:19:55.774961+08:00","gmt_modified":"2026-05-23T15:19:55.774961+08:00"},{"id":"ffb7b526b388c92bf932d701fee71671","path":"backend/alembic/env.py","line_range":"64-89","gmt_create":"2026-05-23T15:19:55.781247+08:00","gmt_modified":"2026-05-23T15:19:55.781247+08:00"},{"id":"8b7ecdb77bf7d73f30b64d82972bf1f5","path":"frontend/tailwind.config.ts","line_range":"1-121","gmt_create":"2026-05-23T15:22:58.307417+08:00","gmt_modified":"2026-05-23T15:22:58.307417+08:00"},{"id":"a8bbf13a4b60cc33fd76c99c6bd6b36f","path":"frontend/playwright.config.ts","line_range":"1-39","gmt_create":"2026-05-23T15:22:58.309871+08:00","gmt_modified":"2026-05-23T15:22:58.309871+08:00"},{"id":"8ca9b37cfe665abc053e0258b0d036d4","path":"frontend/components/business/index.ts","line_range":"1-29","gmt_create":"2026-05-23T15:22:58.310692+08:00","gmt_modified":"2026-05-23T15:22:58.310692+08:00"},{"id":"76edaefb3ec9610b238b448a797795a1","path":"frontend/e2e/tests/dashboard-health.spec.ts","line_range":"1-264","gmt_create":"2026-05-23T15:22:58.349241+08:00","gmt_modified":"2026-05-23T15:22:58.349241+08:00"},{"id":"c413ca9685496f180a8e469f24ed082f","path":"frontend/e2e/tests/login.spec.ts","line_range":"1-126","gmt_create":"2026-05-23T15:22:58.351302+08:00","gmt_modified":"2026-05-23T15:22:58.351303+08:00"},{"id":"912411178607f349a732c3e67dccf631","path":"frontend/e2e/pages/login.page.ts","line_range":"1-36","gmt_create":"2026-05-23T15:22:58.390493+08:00","gmt_modified":"2026-05-23T15:22:58.390493+08:00"},{"id":"4f2c0f1deb411b6b716e7cd04f42a519","path":"frontend/e2e/pages/dashboard.page.ts","line_range":"1-74","gmt_create":"2026-05-23T15:22:58.391143+08:00","gmt_modified":"2026-05-23T15:22:58.391144+08:00"},{"id":"05a55dacbbd018dc394fa656f4e06a62","path":"frontend/components/business/agent-status-card.tsx","line_range":"1-134","gmt_create":"2026-05-23T15:22:58.392949+08:00","gmt_modified":"2026-05-23T15:22:58.39295+08:00"},{"id":"554c0874b68d357f426fe79db129ea9f","path":"frontend/components/business/alert-card.tsx","line_range":"1-203","gmt_create":"2026-05-23T15:22:58.394029+08:00","gmt_modified":"2026-05-23T15:22:58.394029+08:00"},{"id":"d592b986bbd1c67a5932c77ea0341bed","path":"backend/app/api/reports.py","line_range":"1-47","gmt_create":"2026-05-23T15:23:21.384011+08:00","gmt_modified":"2026-05-23T15:23:21.384011+08:00"},{"id":"d2a5fdb4be830adefb3b04de2c90f204","path":"backend/app/api/lifecycle.py","line_range":"1-297","gmt_create":"2026-05-23T15:23:21.385978+08:00","gmt_modified":"2026-05-23T15:23:21.385979+08:00"},{"id":"23914bed50c54bb11234aa5819aec0df","path":"backend/app/api/knowledge.py","line_range":"1-502","gmt_create":"2026-05-23T15:23:21.387916+08:00","gmt_modified":"2026-05-23T15:23:21.387917+08:00"},{"id":"2014cd6665b187d6dccb007539278ae7","path":"backend/app/services/analytics/tracker.py","line_range":"1-230","gmt_create":"2026-05-23T15:23:21.392304+08:00","gmt_modified":"2026-05-23T15:23:21.392304+08:00"},{"id":"451a0398486fbfcc669dc4e50c9ad6e2","path":"backend/app/services/analytics/insights.py","line_range":"1-313","gmt_create":"2026-05-23T15:23:21.393333+08:00","gmt_modified":"2026-05-23T15:23:21.393333+08:00"},{"id":"897891ede0baa5b92d1b9f030a781753","path":"backend/app/services/knowledge/rag_service.py","line_range":"1-43","gmt_create":"2026-05-23T15:23:21.394491+08:00","gmt_modified":"2026-05-23T15:23:21.394491+08:00"},{"id":"ba54afe1867c2fa2046f8f62ad1caf3c","path":"backend/app/agent_framework/agents/__init__.py","line_range":"1-14","gmt_create":"2026-05-23T15:23:21.396278+08:00","gmt_modified":"2026-05-23T15:23:21.396278+08:00"},{"id":"5dd1642d800053635d9827e12e6ea120","path":"backend/app/agent_framework/dispatcher.py","line_range":"1-367","gmt_create":"2026-05-23T15:23:21.401816+08:00","gmt_modified":"2026-05-23T15:23:21.401816+08:00"},{"id":"fa6144407f88a3c04dfcbac3b39bf8b1","path":"backend/app/models/lifecycle.py","line_range":"1-91","gmt_create":"2026-05-23T15:23:21.406648+08:00","gmt_modified":"2026-05-23T15:23:21.406648+08:00"},{"id":"78d92049eebb9a8ceb231e7d2308aa78","path":"backend/app/models/knowledge.py","line_range":"1-43","gmt_create":"2026-05-23T15:23:21.408411+08:00","gmt_modified":"2026-05-23T15:23:21.408411+08:00"},{"id":"9aac0f12a7ab3ebafd07a8bc408dbdcd","path":"backend/workers/scheduler.py","line_range":"1-95","gmt_create":"2026-05-23T15:23:21.409388+08:00","gmt_modified":"2026-05-23T15:23:21.409389+08:00"},{"id":"00a305280b8ae4fb67df733a6d4c0c89","path":"backend/workers/citation_engine.py","line_range":"1-309","gmt_create":"2026-05-23T15:23:21.40999+08:00","gmt_modified":"2026-05-23T15:23:21.40999+08:00"},{"id":"68338b3901163c41ed55d1ce10ea219a","path":"backend/workers/scheduler.py","line_range":"51-84","gmt_create":"2026-05-23T15:23:21.452583+08:00","gmt_modified":"2026-05-23T15:23:21.452583+08:00"},{"id":"0bc629b80b2505420d45840e98a2b92d","path":"backend/workers/citation_engine.py","line_range":"159-234","gmt_create":"2026-05-23T15:23:21.45373+08:00","gmt_modified":"2026-05-23T15:23:21.453731+08:00"},{"id":"f90f382f226eeca8bb1c111d10941fa0","path":"backend/app/agent_framework/dispatcher.py","line_range":"54-117","gmt_create":"2026-05-23T15:23:21.455605+08:00","gmt_modified":"2026-05-23T15:23:21.455605+08:00"},{"id":"8ece81c4077ec3e9c702e5e1092119a2","path":"backend/app/agent_framework/pipeline/engine.py","line_range":"51-176","gmt_create":"2026-05-23T15:23:21.456738+08:00","gmt_modified":"2026-05-23T15:23:21.456738+08:00"},{"id":"168f54bd5cbe07c656ec3905e567862c","path":"backend/app/workers/citation_engine.py","line_range":"291-300","gmt_create":"2026-05-23T15:23:21.472842+08:00","gmt_modified":"2026-05-23T15:23:21.472842+08:00"},{"id":"d3e817d678735f63b277894d26626924","path":"backend/app/workers/platforms/base.py","line_range":"10-17","gmt_create":"2026-05-23T15:23:21.491085+08:00","gmt_modified":"2026-05-23T15:23:21.491085+08:00"},{"id":"f0421deca067a246711e95817e1f1b1a","path":"backend/app/workers/citation_engine.py","line_range":"151-157","gmt_create":"2026-05-23T15:23:21.493895+08:00","gmt_modified":"2026-05-23T15:23:21.493895+08:00"},{"id":"6a21ee5392ba55b57659d404ebf5355e","path":"backend/app/agent_framework/agents/citation_detector.py","line_range":"24-218","gmt_create":"2026-05-23T15:23:21.495149+08:00","gmt_modified":"2026-05-23T15:23:21.49515+08:00"},{"id":"76381105cd13daa99ac6376cfdab39f0","path":"backend/app/agent_framework/agents/content_generator_agent.py","line_range":"23-299","gmt_create":"2026-05-23T15:23:21.496545+08:00","gmt_modified":"2026-05-23T15:23:21.496545+08:00"},{"id":"ff0389ece7f710d431371a409553989c","path":"backend/app/agent_framework/agents/deai_agent.py","line_range":"21-156","gmt_create":"2026-05-23T15:23:21.497794+08:00","gmt_modified":"2026-05-23T15:23:21.497794+08:00"},{"id":"f30316a028f81ac1c0e2f77568ba64f5","path":"backend/app/agent_framework/agents/geo_optimizer_agent.py","line_range":"23-198","gmt_create":"2026-05-23T15:23:21.49926+08:00","gmt_modified":"2026-05-23T15:23:21.499261+08:00"},{"id":"72c6b8f0be1248c2ce6e84247e81416d","path":"backend/app/agent_framework/pipeline/engine.py","line_range":"31-536","gmt_create":"2026-05-23T15:23:21.500251+08:00","gmt_modified":"2026-05-23T15:23:21.500252+08:00"},{"id":"af5a9cdc724669f93a0f9f1dd790717b","path":"backend/app/agent_framework/dispatcher.py","line_range":"32-367","gmt_create":"2026-05-23T15:23:21.501171+08:00","gmt_modified":"2026-05-23T15:23:21.501171+08:00"},{"id":"8e264e08029549dd5af31f4238522cc1","path":"backend/app/agent_framework/agents/citation_detector.py","line_range":"1-218","gmt_create":"2026-05-23T15:23:21.502734+08:00","gmt_modified":"2026-05-23T15:23:21.502734+08:00"},{"id":"12b7988890a9e461cbccd36564a6cc82","path":"backend/app/api/lifecycle.py","line_range":"138-187","gmt_create":"2026-05-23T15:23:21.511092+08:00","gmt_modified":"2026-05-23T15:23:21.511092+08:00"},{"id":"5c9cde497ea1c98e6fe63e808f1d8ca5","path":"backend/app/models/lifecycle.py","line_range":"12-91","gmt_create":"2026-05-23T15:23:21.513446+08:00","gmt_modified":"2026-05-23T15:23:21.513447+08:00"},{"id":"058be4ad1752d83067d65bf59f958461","path":"frontend/lib/api/lifecycle.ts","line_range":"53-95","gmt_create":"2026-05-23T15:23:21.51664+08:00","gmt_modified":"2026-05-23T15:23:21.51664+08:00"},{"id":"c549a2efc417d5646c81a100701cf72a","path":"backend/app/services/analytics/tracker.py","line_range":"16-51","gmt_create":"2026-05-23T15:23:21.517746+08:00","gmt_modified":"2026-05-23T15:23:21.517747+08:00"},{"id":"33c1014641412422e2687463885aef5f","path":"backend/app/services/analytics/insights.py","line_range":"40-103","gmt_create":"2026-05-23T15:23:21.518793+08:00","gmt_modified":"2026-05-23T15:23:21.518794+08:00"},{"id":"befab5441502d9e867d85550072130fa","path":"backend/app/services/analytics/tracker.py","line_range":"53-128","gmt_create":"2026-05-23T15:23:21.520036+08:00","gmt_modified":"2026-05-23T15:23:21.520036+08:00"},{"id":"1d1a90f9679ff5937c688d465591a0ab","path":"backend/app/api/knowledge.py","line_range":"217-293","gmt_create":"2026-05-23T15:23:21.523435+08:00","gmt_modified":"2026-05-23T15:23:21.523436+08:00"},{"id":"7f9b9025f56d8baba8136ab1b8ed49b3","path":"backend/app/services/knowledge/rag_service.py","line_range":"33-43","gmt_create":"2026-05-23T15:23:21.537403+08:00","gmt_modified":"2026-05-23T15:23:21.537403+08:00"},{"id":"16f20ee7078a57c6910a20d49deb646f","path":"frontend/components/charts/trend-chart.tsx","line_range":"22-59","gmt_create":"2026-05-23T15:23:21.544768+08:00","gmt_modified":"2026-05-23T15:23:21.544768+08:00"},{"id":"f457c5ae12bb63dcd5d83e4ede8efb15","path":"backend/app/api/citations.py","line_range":"49-56","gmt_create":"2026-05-23T15:23:21.546995+08:00","gmt_modified":"2026-05-23T15:23:21.546996+08:00"},{"id":"cb57298d603df7c5572310807b629516","path":"backend/app/services/citation.py","line_range":"76-201","gmt_create":"2026-05-23T15:23:21.549395+08:00","gmt_modified":"2026-05-23T15:23:21.549395+08:00"},{"id":"84d5ec753cc381b480dfd2cc2f4228a0","path":"backend/app/services/citation.py","line_range":"237-268","gmt_create":"2026-05-23T15:23:21.557366+08:00","gmt_modified":"2026-05-23T15:23:21.557366+08:00"},{"id":"d49ddf2ff36cff1ba6702d9fe3bd253d","path":"backend/app/agent_framework/dispatcher.py","line_range":"35-46","gmt_create":"2026-05-23T15:23:21.571357+08:00","gmt_modified":"2026-05-23T15:23:21.571358+08:00"},{"id":"89c74d1f6c264e3b6b0232f7c2385cc7","path":"backend/app/workers/scheduler.py","line_range":"30-40","gmt_create":"2026-05-23T15:23:21.592339+08:00","gmt_modified":"2026-05-23T15:23:21.59234+08:00"},{"id":"d51485da00706b78a1bc7eb4290c8044","path":"backend/app/agent_framework/dispatcher.py","line_range":"118-154","gmt_create":"2026-05-23T15:23:21.594039+08:00","gmt_modified":"2026-05-23T15:23:21.59404+08:00"},{"id":"041b88dd888e1118b1b0be80f9ec4904","path":"backend/app/agent_framework/base.py","line_range":"1-223","gmt_create":"2026-05-23T15:24:01.695238+08:00","gmt_modified":"2026-05-23T15:24:01.695238+08:00"},{"id":"aba7dcba1181acae0e810fe447807010","path":"backend/app/agent_framework/registry.py","line_range":"1-219","gmt_create":"2026-05-23T15:24:01.696671+08:00","gmt_modified":"2026-05-23T15:24:01.696671+08:00"},{"id":"4a0f6c5332f954161992df9247e63a97","path":"backend/app/workers/llm_adapter.py","line_range":"1-281","gmt_create":"2026-05-23T15:24:01.701215+08:00","gmt_modified":"2026-05-23T15:24:01.701216+08:00"},{"id":"d432677dc357ec0518cc70701962e6bd","path":"backend/pipelines/content_production.yaml","line_range":"1-65","gmt_create":"2026-05-23T15:24:01.702282+08:00","gmt_modified":"2026-05-23T15:24:01.702283+08:00"},{"id":"3d50a008bc36ea9fed48168c2597933d","path":"backend/pipelines/diagnosis.yaml","line_range":"1-30","gmt_create":"2026-05-23T15:24:01.703321+08:00","gmt_modified":"2026-05-23T15:24:01.703321+08:00"},{"id":"bf0d60f20f3ea5a2f2458ba86d3f9173","path":"backend/app/models/agent.py","line_range":"1-206","gmt_create":"2026-05-23T15:24:01.784724+08:00","gmt_modified":"2026-05-23T15:24:01.784725+08:00"},{"id":"81d750ebce1c6f458a3499de79002778","path":"backend/app/agent_framework/base.py","line_range":"52-114","gmt_create":"2026-05-23T15:24:01.786275+08:00","gmt_modified":"2026-05-23T15:24:01.786276+08:00"},{"id":"07fd98ac292cc72700ce97168ed58d9a","path":"backend/app/agent_framework/base.py","line_range":"148-182","gmt_create":"2026-05-23T15:24:01.789406+08:00","gmt_modified":"2026-05-23T15:24:01.789406+08:00"},{"id":"ff27531ef3cacd097bc66aa7e982158d","path":"backend/app/agent_framework/registry.py","line_range":"29-80","gmt_create":"2026-05-23T15:24:01.791256+08:00","gmt_modified":"2026-05-23T15:24:01.791256+08:00"},{"id":"27a49e5089cfba7405dc53418c54dd37","path":"backend/app/agent_framework/registry.py","line_range":"156-172","gmt_create":"2026-05-23T15:24:01.792132+08:00","gmt_modified":"2026-05-23T15:24:01.792133+08:00"},{"id":"c0d940dbb4ac9ef819aad6c16edc0d60","path":"backend/app/agent_framework/registry.py","line_range":"174-201","gmt_create":"2026-05-23T15:24:01.79304+08:00","gmt_modified":"2026-05-23T15:24:01.79304+08:00"},{"id":"7a66c4fd8249f7d534ebe9092faa1124","path":"backend/app/agent_framework/dispatcher.py","line_range":"169-218","gmt_create":"2026-05-23T15:24:01.794779+08:00","gmt_modified":"2026-05-23T15:24:01.794779+08:00"},{"id":"962888e682bf9d3ceaa4d5bd5e75bb2c","path":"backend/app/services/llm/factory.py","line_range":"25-50","gmt_create":"2026-05-23T15:24:01.800754+08:00","gmt_modified":"2026-05-23T15:24:01.800755+08:00"},{"id":"ea929f7dbed5834bb5b3e24ebb32a0bc","path":"backend/app/workers/llm_adapter.py","line_range":"71-110","gmt_create":"2026-05-23T15:24:01.801726+08:00","gmt_modified":"2026-05-23T15:24:01.801727+08:00"},{"id":"ef16244eb1b5c1ab8774199c05bf0151","path":"backend/app/workers/llm_adapter.py","line_range":"220-270","gmt_create":"2026-05-23T15:24:01.803485+08:00","gmt_modified":"2026-05-23T15:24:01.803486+08:00"},{"id":"678dbba75fa1ffc2d9230f9e3ef7cc6f","path":"backend/app/agent_framework/agents/content_generator_agent.py","line_range":"111-182","gmt_create":"2026-05-23T15:24:01.806876+08:00","gmt_modified":"2026-05-23T15:24:01.806876+08:00"},{"id":"c32c02777f644d164c73710bcdd9c25c","path":"backend/app/agent_framework/agents/content_generator_agent.py","line_range":"184-252","gmt_create":"2026-05-23T15:24:01.807789+08:00","gmt_modified":"2026-05-23T15:24:01.80779+08:00"},{"id":"860a2f84ff90988124545bb7386f7e45","path":"backend/app/agent_framework/agents/geo_optimizer_agent.py","line_range":"104-180","gmt_create":"2026-05-23T15:24:01.808664+08:00","gmt_modified":"2026-05-23T15:24:01.808664+08:00"},{"id":"ccbe69d125e99e73a7907f2c94c59cc3","path":"backend/pipelines/content_production.yaml","line_range":"9-65","gmt_create":"2026-05-23T15:24:01.811957+08:00","gmt_modified":"2026-05-23T15:24:01.811958+08:00"},{"id":"63b5e7a6a9a5545b70747bcbcae293f9","path":"backend/pipelines/diagnosis.yaml","line_range":"8-30","gmt_create":"2026-05-23T15:24:01.814726+08:00","gmt_modified":"2026-05-23T15:24:01.814726+08:00"},{"id":"cdcf6ce33785e1c04e59e8244ca38ec8","path":"backend/app/agent_framework/pipeline/engine.py","line_range":"256-327","gmt_create":"2026-05-23T15:24:01.817005+08:00","gmt_modified":"2026-05-23T15:24:01.817006+08:00"},{"id":"8d044a978198d9cd54d1b3d8e41194c0","path":"backend/app/agent_framework/pipeline/schema.py","line_range":"1-102","gmt_create":"2026-05-23T15:24:01.820305+08:00","gmt_modified":"2026-05-23T15:24:01.820305+08:00"},{"id":"960edc307c80a05c1d234e641a795b35","path":"backend/app/workers/llm_adapter.py","line_range":"141-218","gmt_create":"2026-05-23T15:24:01.888133+08:00","gmt_modified":"2026-05-23T15:24:01.888133+08:00"},{"id":"8bf01ba5b11502e9f6f9802c9735f370","path":"backend/app/agent_framework/pipeline/loader.py","line_range":"124-134","gmt_create":"2026-05-23T15:24:01.889218+08:00","gmt_modified":"2026-05-23T15:24:01.889219+08:00"},{"id":"70985e6be46865e7b0a26fdaab7ce0d2","path":"frontend/lib/api.ts","line_range":"1-58","gmt_create":"2026-05-23T15:26:09.829344+08:00","gmt_modified":"2026-05-23T15:26:09.829344+08:00"},{"id":"42315d289241195bda33f7251dff0396","path":"frontend/lib/api/agents.ts","line_range":"1-57","gmt_create":"2026-05-23T15:26:09.830427+08:00","gmt_modified":"2026-05-23T15:26:09.830427+08:00"},{"id":"370e7d15bc2a240ba54af22c704f8192","path":"backend/app/agent_framework/config_manager.py","line_range":"1-191","gmt_create":"2026-05-23T15:26:09.842759+08:00","gmt_modified":"2026-05-23T15:26:09.842759+08:00"},{"id":"db3ad017a4a81f38a1e6008d01fb07fb","path":"backend/app/agent_framework/pipeline/engine.py","line_range":"1-376","gmt_create":"2026-05-23T15:26:09.844277+08:00","gmt_modified":"2026-05-23T15:26:09.844277+08:00"},{"id":"41c1962c6c680f23f0fde4efc0edc618","path":"backend/app/api/agents.py","line_range":"1-299","gmt_create":"2026-05-23T15:26:09.848268+08:00","gmt_modified":"2026-05-23T15:26:09.848268+08:00"},{"id":"08d06b8b6e8c01974ec66e0a5b10795f","path":"backend/app/schemas/query.py","line_range":"6-8","gmt_create":"2026-05-23T15:26:09.909298+08:00","gmt_modified":"2026-05-23T15:26:09.909298+08:00"},{"id":"a6811a3e7a5e0874867a1839912ac150","path":"frontend/lib/api.ts","line_range":"1","gmt_create":"2026-05-23T15:26:09.911586+08:00","gmt_modified":"2026-05-23T15:26:09.911586+08:00"},{"id":"7480204ff8e76e1fedc3c82967acbddf","path":".env.example","line_range":"1-35","gmt_create":"2026-05-23T15:26:09.913415+08:00","gmt_modified":"2026-05-23T15:26:09.913415+08:00"},{"id":"b41c589b6a7e0c0addb0aa1d78666cf7","path":"backend/app/schemas/query.py","line_range":"6","gmt_create":"2026-05-23T15:26:09.925138+08:00","gmt_modified":"2026-05-23T15:26:09.925138+08:00"},{"id":"05089063cd933e72db9ddd32806194bb","path":"backend/requirements.txt","line_range":"5-8","gmt_create":"2026-05-23T15:26:09.926939+08:00","gmt_modified":"2026-05-23T15:26:09.92694+08:00"},{"id":"0a7f1ad960e7961b21073bdd1dbef2cb","path":"frontend/lib/api.ts","line_range":"3-21","gmt_create":"2026-05-23T15:26:09.928426+08:00","gmt_modified":"2026-05-23T15:26:09.928426+08:00"},{"id":"c099b506f31f17751b7e08f64b2b1cbe","path":"frontend/lib/api.ts","line_range":"16-21","gmt_create":"2026-05-23T15:26:09.941061+08:00","gmt_modified":"2026-05-23T15:26:09.941062+08:00"},{"id":"6997483bdbba1455b9454fe4cccbba45","path":"backend/app/workers/platforms/kimi.py","line_range":"23-32","gmt_create":"2026-05-23T15:26:09.953513+08:00","gmt_modified":"2026-05-23T15:26:09.953513+08:00"}],"knowledge_relations":[{"id":48,"source_id":"ba0390b3-c249-4e92-a3c8-6820343aeda9","target_id":"12e2c3d7b9a92dc44a6ee29b85e10df6","source_type":"WIKI_ITEM","target_type":"SOURCE_FILE","relationship_type":"REFERENCED_BY","extra":"Wiki references source file: frontend/app/layout.tsx","gmt_create":"2026-04-23T15:19:43.777831+08:00","gmt_modified":"2026-04-23T15:19:43.777831+08:00"},{"id":49,"source_id":"ba0390b3-c249-4e92-a3c8-6820343aeda9","target_id":"2a1c745c7b3fb7f600596be3d979bba1","source_type":"WIKI_ITEM","target_type":"SOURCE_FILE","relationship_type":"REFERENCED_BY","extra":"Wiki references source file: frontend/app/(dashboard","gmt_create":"2026-04-23T15:19:43.778774+08:00","gmt_modified":"2026-04-23T15:19:43.778774+08:00"},{"id":50,"source_id":"ba0390b3-c249-4e92-a3c8-6820343aeda9","target_id":"eca13a610badfc5ffc6210827fb96991","source_type":"WIKI_ITEM","target_type":"SOURCE_FILE","relationship_type":"REFERENCED_BY","extra":"Wiki references source file: frontend/components/layout/header.tsx","gmt_create":"2026-04-23T15:19:43.779153+08:00","gmt_modified":"2026-04-23T15:19:43.779154+08:00"},{"id":51,"source_id":"ba0390b3-c249-4e92-a3c8-6820343aeda9","target_id":"18a0651d895fba9bb4e0c0229459efdc","source_type":"WIKI_ITEM","target_type":"SOURCE_FILE","relationship_type":"REFERENCED_BY","extra":"Wiki references source file: frontend/components/layout/sidebar.tsx","gmt_create":"2026-04-23T15:19:43.779524+08:00","gmt_modified":"2026-04-23T15:19:43.779524+08:00"},{"id":52,"source_id":"ba0390b3-c249-4e92-a3c8-6820343aeda9","target_id":"5d7886d0dc99f81073a578b8aefdd375","source_type":"WIKI_ITEM","target_type":"SOURCE_FILE","relationship_type":"REFERENCED_BY","extra":"Wiki references source file: frontend/lib/api.ts","gmt_create":"2026-04-23T15:19:43.779869+08:00","gmt_modified":"2026-04-23T15:19:43.779869+08:00"},{"id":53,"source_id":"ba0390b3-c249-4e92-a3c8-6820343aeda9","target_id":"0c0b0f4e2cf44facd9d5b57de0d0bf0c","source_type":"WIKI_ITEM","target_type":"SOURCE_FILE","relationship_type":"REFERENCED_BY","extra":"Wiki references source file: frontend/components/ui/table.tsx","gmt_create":"2026-04-23T15:19:43.780775+08:00","gmt_modified":"2026-04-23T15:19:43.780775+08:00"},{"id":54,"source_id":"ba0390b3-c249-4e92-a3c8-6820343aeda9","target_id":"108b0c4b4dcfb6aa39a5eb138225c148","source_type":"WIKI_ITEM","target_type":"SOURCE_FILE","relationship_type":"REFERENCED_BY","extra":"Wiki references source file: frontend/components/ui/dialog.tsx","gmt_create":"2026-04-23T15:19:43.781767+08:00","gmt_modified":"2026-04-23T15:19:43.781767+08:00"},{"id":55,"source_id":"ba0390b3-c249-4e92-a3c8-6820343aeda9","target_id":"ef72f0c3cedb9fd9a87352fe493053dc","source_type":"WIKI_ITEM","target_type":"SOURCE_FILE","relationship_type":"REFERENCED_BY","extra":"Wiki references source file: frontend/lib/platforms.ts","gmt_create":"2026-04-23T15:19:43.782177+08:00","gmt_modified":"2026-04-23T15:19:43.782177+08:00"},{"id":56,"source_id":"ba0390b3-c249-4e92-a3c8-6820343aeda9","target_id":"f93ae024fe0a2e69698037dff6df205f","source_type":"WIKI_ITEM","target_type":"SOURCE_FILE","relationship_type":"REFERENCED_BY","extra":"Wiki references source file: frontend/lib/utils.ts","gmt_create":"2026-04-23T15:19:43.782527+08:00","gmt_modified":"2026-04-23T15:19:43.782527+08:00"},{"id":57,"source_id":"ba0390b3-c249-4e92-a3c8-6820343aeda9","target_id":"d5f2266643d2011c66e86af088ec637f","source_type":"WIKI_ITEM","target_type":"SOURCE_FILE","relationship_type":"REFERENCED_BY","extra":"Wiki references source file: frontend/components/charts/trend-chart.tsx","gmt_create":"2026-04-23T15:19:43.782861+08:00","gmt_modified":"2026-04-23T15:19:43.782861+08:00"},{"id":58,"source_id":"ba0390b3-c249-4e92-a3c8-6820343aeda9","target_id":"f1a7d61831cc0a45ac6220294f15c21d","source_type":"WIKI_ITEM","target_type":"SOURCE_FILE","relationship_type":"REFERENCED_BY","extra":"Wiki references source file: frontend/components/charts/platform-chart.tsx","gmt_create":"2026-04-23T15:19:43.783164+08:00","gmt_modified":"2026-04-23T15:19:43.783165+08:00"},{"id":59,"source_id":"ba0390b3-c249-4e92-a3c8-6820343aeda9","target_id":"8a466b0c6eac2ccb54c5da7e13854646","source_type":"WIKI_ITEM","target_type":"CODE_SNIPPET","relationship_type":"CONTAINS","extra":"Wiki contains code snippet: frontend/app/layout.tsx#1-37","gmt_create":"2026-04-23T15:19:43.783668+08:00","gmt_modified":"2026-04-23T15:19:43.783668+08:00"},{"id":60,"source_id":"12e2c3d7b9a92dc44a6ee29b85e10df6","target_id":"8a466b0c6eac2ccb54c5da7e13854646","source_type":"SOURCE_FILE","target_type":"CODE_SNIPPET","relationship_type":"CONTAINS","extra":"Source file contains code snippet: 1-37","gmt_create":"2026-04-23T15:19:43.783987+08:00","gmt_modified":"2026-04-23T15:19:43.783987+08:00"},{"id":61,"source_id":"ba0390b3-c249-4e92-a3c8-6820343aeda9","target_id":"3bd4eedea376e3a3d9f9fbff4fe27a65","source_type":"WIKI_ITEM","target_type":"CODE_SNIPPET","relationship_type":"CONTAINS","extra":"Wiki contains code snippet: frontend/components/layout/sidebar.tsx#1-54","gmt_create":"2026-04-23T15:19:43.784455+08:00","gmt_modified":"2026-04-23T15:19:43.784455+08:00"},{"id":62,"source_id":"18a0651d895fba9bb4e0c0229459efdc","target_id":"3bd4eedea376e3a3d9f9fbff4fe27a65","source_type":"SOURCE_FILE","target_type":"CODE_SNIPPET","relationship_type":"CONTAINS","extra":"Source file contains code snippet: 1-54","gmt_create":"2026-04-23T15:19:43.784807+08:00","gmt_modified":"2026-04-23T15:19:43.784807+08:00"},{"id":63,"source_id":"ba0390b3-c249-4e92-a3c8-6820343aeda9","target_id":"0d903468b55bdc63cc7e25a87a89c522","source_type":"WIKI_ITEM","target_type":"CODE_SNIPPET","relationship_type":"CONTAINS","extra":"Wiki contains code snippet: frontend/components/layout/header.tsx#1-30","gmt_create":"2026-04-23T15:19:43.785303+08:00","gmt_modified":"2026-04-23T15:19:43.785303+08:00"},{"id":64,"source_id":"eca13a610badfc5ffc6210827fb96991","target_id":"0d903468b55bdc63cc7e25a87a89c522","source_type":"SOURCE_FILE","target_type":"CODE_SNIPPET","relationship_type":"CONTAINS","extra":"Source file contains code snippet: 1-30","gmt_create":"2026-04-23T15:19:43.785622+08:00","gmt_modified":"2026-04-23T15:19:43.785622+08:00"},{"id":65,"source_id":"ba0390b3-c249-4e92-a3c8-6820343aeda9","target_id":"3bab92a09e9fb456e0303bb1e04afc7e","source_type":"WIKI_ITEM","target_type":"CODE_SNIPPET","relationship_type":"CONTAINS","extra":"Wiki contains code snippet: frontend/components/ui/table.tsx#1-118","gmt_create":"2026-04-23T15:19:43.78727+08:00","gmt_modified":"2026-04-23T15:19:43.787271+08:00"},{"id":66,"source_id":"0c0b0f4e2cf44facd9d5b57de0d0bf0c","target_id":"3bab92a09e9fb456e0303bb1e04afc7e","source_type":"SOURCE_FILE","target_type":"CODE_SNIPPET","relationship_type":"CONTAINS","extra":"Source file contains code snippet: 1-118","gmt_create":"2026-04-23T15:19:43.788224+08:00","gmt_modified":"2026-04-23T15:19:43.788224+08:00"},{"id":67,"source_id":"ba0390b3-c249-4e92-a3c8-6820343aeda9","target_id":"0eed9f61572209dd754611fc7c690d5a","source_type":"WIKI_ITEM","target_type":"CODE_SNIPPET","relationship_type":"CONTAINS","extra":"Wiki contains code snippet: frontend/components/ui/dialog.tsx#1-123","gmt_create":"2026-04-23T15:19:43.789533+08:00","gmt_modified":"2026-04-23T15:19:43.789533+08:00"},{"id":68,"source_id":"108b0c4b4dcfb6aa39a5eb138225c148","target_id":"0eed9f61572209dd754611fc7c690d5a","source_type":"SOURCE_FILE","target_type":"CODE_SNIPPET","relationship_type":"CONTAINS","extra":"Source file contains code snippet: 1-123","gmt_create":"2026-04-23T15:19:43.790255+08:00","gmt_modified":"2026-04-23T15:19:43.790255+08:00"},{"id":69,"source_id":"ba0390b3-c249-4e92-a3c8-6820343aeda9","target_id":"b7796fc6197ecce5beb461b9466e54a0","source_type":"WIKI_ITEM","target_type":"CODE_SNIPPET","relationship_type":"CONTAINS","extra":"Wiki contains code snippet: frontend/components/charts/trend-chart.tsx#1-60","gmt_create":"2026-04-23T15:19:43.790795+08:00","gmt_modified":"2026-04-23T15:19:43.790795+08:00"},{"id":70,"source_id":"d5f2266643d2011c66e86af088ec637f","target_id":"b7796fc6197ecce5beb461b9466e54a0","source_type":"SOURCE_FILE","target_type":"CODE_SNIPPET","relationship_type":"CONTAINS","extra":"Source file contains code snippet: 1-60","gmt_create":"2026-04-23T15:19:43.791134+08:00","gmt_modified":"2026-04-23T15:19:43.791134+08:00"},{"id":71,"source_id":"ba0390b3-c249-4e92-a3c8-6820343aeda9","target_id":"6b9f52af0b6d78c17ff9bbc42d760ea2","source_type":"WIKI_ITEM","target_type":"CODE_SNIPPET","relationship_type":"CONTAINS","extra":"Wiki contains code snippet: frontend/components/charts/platform-chart.tsx#1-68","gmt_create":"2026-04-23T15:19:43.791601+08:00","gmt_modified":"2026-04-23T15:19:43.791601+08:00"},{"id":72,"source_id":"f1a7d61831cc0a45ac6220294f15c21d","target_id":"6b9f52af0b6d78c17ff9bbc42d760ea2","source_type":"SOURCE_FILE","target_type":"CODE_SNIPPET","relationship_type":"CONTAINS","extra":"Source file contains code snippet: 1-68","gmt_create":"2026-04-23T15:19:43.791902+08:00","gmt_modified":"2026-04-23T15:19:43.791902+08:00"},{"id":73,"source_id":"ba0390b3-c249-4e92-a3c8-6820343aeda9","target_id":"a829403082cc3460c01e0110229c53c4","source_type":"WIKI_ITEM","target_type":"CODE_SNIPPET","relationship_type":"CONTAINS","extra":"Wiki contains code snippet: frontend/lib/platforms.ts#1-18","gmt_create":"2026-04-23T15:19:43.792356+08:00","gmt_modified":"2026-04-23T15:19:43.792356+08:00"},{"id":74,"source_id":"ef72f0c3cedb9fd9a87352fe493053dc","target_id":"a829403082cc3460c01e0110229c53c4","source_type":"SOURCE_FILE","target_type":"CODE_SNIPPET","relationship_type":"CONTAINS","extra":"Source file contains code snippet: 1-18","gmt_create":"2026-04-23T15:19:43.79267+08:00","gmt_modified":"2026-04-23T15:19:43.79267+08:00"},{"id":75,"source_id":"ba0390b3-c249-4e92-a3c8-6820343aeda9","target_id":"dcfa308ef4ec368c5a51a17acbfc8e2c","source_type":"WIKI_ITEM","target_type":"CODE_SNIPPET","relationship_type":"CONTAINS","extra":"Wiki contains code snippet: frontend/lib/utils.ts#1-7","gmt_create":"2026-04-23T15:19:43.79312+08:00","gmt_modified":"2026-04-23T15:19:43.79312+08:00"},{"id":76,"source_id":"f93ae024fe0a2e69698037dff6df205f","target_id":"dcfa308ef4ec368c5a51a17acbfc8e2c","source_type":"SOURCE_FILE","target_type":"CODE_SNIPPET","relationship_type":"CONTAINS","extra":"Source file contains code snippet: 1-7","gmt_create":"2026-04-23T15:19:43.793455+08:00","gmt_modified":"2026-04-23T15:19:43.793455+08:00"},{"id":77,"source_id":"ba0390b3-c249-4e92-a3c8-6820343aeda9","target_id":"0f87c8089f548883d056f0a0d79e273f","source_type":"WIKI_ITEM","target_type":"CODE_SNIPPET","relationship_type":"CONTAINS","extra":"Wiki contains code snippet: frontend/lib/api.ts#1-79","gmt_create":"2026-04-23T15:19:43.793866+08:00","gmt_modified":"2026-04-23T15:19:43.793866+08:00"},{"id":78,"source_id":"5d7886d0dc99f81073a578b8aefdd375","target_id":"0f87c8089f548883d056f0a0d79e273f","source_type":"SOURCE_FILE","target_type":"CODE_SNIPPET","relationship_type":"CONTAINS","extra":"Source file contains code snippet: 1-79","gmt_create":"2026-04-23T15:19:43.794158+08:00","gmt_modified":"2026-04-23T15:19:43.794158+08:00"},{"id":79,"source_id":"ba0390b3-c249-4e92-a3c8-6820343aeda9","target_id":"9beee1f41fe8f0750fd97155f9d54bbb","source_type":"WIKI_ITEM","target_type":"CODE_SNIPPET","relationship_type":"CONTAINS","extra":"Wiki contains code snippet: frontend/lib/api.ts#67-70","gmt_create":"2026-04-23T15:19:43.797877+08:00","gmt_modified":"2026-04-23T15:19:43.797877+08:00"},{"id":80,"source_id":"5d7886d0dc99f81073a578b8aefdd375","target_id":"9beee1f41fe8f0750fd97155f9d54bbb","source_type":"SOURCE_FILE","target_type":"CODE_SNIPPET","relationship_type":"CONTAINS","extra":"Source file contains code snippet: 67-70","gmt_create":"2026-04-23T15:19:43.798244+08:00","gmt_modified":"2026-04-23T15:19:43.798244+08:00"},{"id":81,"source_id":"ba0390b3-c249-4e92-a3c8-6820343aeda9","target_id":"8fe2e22a963442076e1ce16ab777573c","source_type":"WIKI_ITEM","target_type":"CODE_SNIPPET","relationship_type":"CONTAINS","extra":"Wiki contains code snippet: frontend/lib/api.ts#56-66","gmt_create":"2026-04-23T15:19:43.799319+08:00","gmt_modified":"2026-04-23T15:19:43.799319+08:00"},{"id":82,"source_id":"5d7886d0dc99f81073a578b8aefdd375","target_id":"8fe2e22a963442076e1ce16ab777573c","source_type":"SOURCE_FILE","target_type":"CODE_SNIPPET","relationship_type":"CONTAINS","extra":"Source file contains code snippet: 56-66","gmt_create":"2026-04-23T15:19:43.799625+08:00","gmt_modified":"2026-04-23T15:19:43.799625+08:00"},{"id":83,"source_id":"ba0390b3-c249-4e92-a3c8-6820343aeda9","target_id":"3124ad882ca2cf8fecb6b93696c7f233","source_type":"WIKI_ITEM","target_type":"CODE_SNIPPET","relationship_type":"CONTAINS","extra":"Wiki contains code snippet: frontend/lib/api.ts#72-77","gmt_create":"2026-04-23T15:19:43.801555+08:00","gmt_modified":"2026-04-23T15:19:43.801555+08:00"},{"id":84,"source_id":"5d7886d0dc99f81073a578b8aefdd375","target_id":"3124ad882ca2cf8fecb6b93696c7f233","source_type":"SOURCE_FILE","target_type":"CODE_SNIPPET","relationship_type":"CONTAINS","extra":"Source file contains code snippet: 72-77","gmt_create":"2026-04-23T15:19:43.801939+08:00","gmt_modified":"2026-04-23T15:19:43.801939+08:00"},{"id":85,"source_id":"ba0390b3-c249-4e92-a3c8-6820343aeda9","target_id":"17a97b4ac37fb67b8eda7ce2887c38e7","source_type":"WIKI_ITEM","target_type":"CODE_SNIPPET","relationship_type":"CONTAINS","extra":"Wiki contains code snippet: frontend/app/layout.tsx#17-20","gmt_create":"2026-04-23T15:19:43.806186+08:00","gmt_modified":"2026-04-23T15:19:43.806186+08:00"},{"id":86,"source_id":"12e2c3d7b9a92dc44a6ee29b85e10df6","target_id":"17a97b4ac37fb67b8eda7ce2887c38e7","source_type":"SOURCE_FILE","target_type":"CODE_SNIPPET","relationship_type":"CONTAINS","extra":"Source file contains code snippet: 17-20","gmt_create":"2026-04-23T15:19:43.80664+08:00","gmt_modified":"2026-04-23T15:19:43.80664+08:00"},{"id":87,"source_id":"ba0390b3-c249-4e92-a3c8-6820343aeda9","target_id":"84cba1e0d516e8c9859402fd5c1bc83c","source_type":"WIKI_ITEM","target_type":"CODE_SNIPPET","relationship_type":"CONTAINS","extra":"Wiki contains code snippet: frontend/lib/api.ts#3-40","gmt_create":"2026-04-23T15:19:43.815637+08:00","gmt_modified":"2026-04-23T15:19:43.815637+08:00"},{"id":88,"source_id":"5d7886d0dc99f81073a578b8aefdd375","target_id":"84cba1e0d516e8c9859402fd5c1bc83c","source_type":"SOURCE_FILE","target_type":"CODE_SNIPPET","relationship_type":"CONTAINS","extra":"Source file contains code snippet: 3-40","gmt_create":"2026-04-23T15:19:43.817147+08:00","gmt_modified":"2026-04-23T15:19:43.817147+08:00"},{"id":107,"source_id":"9228ff67d4c757a85d9421b71f4b29f5","target_id":"b55a164add5a8fec2ef0e489f7234829","source_type":"SOURCE_FILE","target_type":"CODE_SNIPPET","relationship_type":"CONTAINS","extra":"Source file contains code snippet: 24-47","gmt_create":"2026-04-23T15:19:45.617445+08:00","gmt_modified":"2026-04-23T15:19:45.617445+08:00"},{"id":109,"source_id":"93022c8938ce318f167277cfa65c29a7","target_id":"16d619435094a63740357cd6317b52cb","source_type":"SOURCE_FILE","target_type":"CODE_SNIPPET","relationship_type":"CONTAINS","extra":"Source file contains code snippet: 10","gmt_create":"2026-04-23T15:19:45.618177+08:00","gmt_modified":"2026-04-23T15:19:45.618177+08:00"},{"id":111,"source_id":"6b3d903205941aa9391dd90016e1102c","target_id":"fa1ee5e3822128a37e9d03af74083392","source_type":"SOURCE_FILE","target_type":"CODE_SNIPPET","relationship_type":"CONTAINS","extra":"Source file contains code snippet: 12","gmt_create":"2026-04-23T15:19:45.619215+08:00","gmt_modified":"2026-04-23T15:19:45.619215+08:00"},{"id":113,"source_id":"7538ffe4902ab6041adb28b19844962a","target_id":"7e908f05baccdfcf7f4a3ef3c9cd5c38","source_type":"SOURCE_FILE","target_type":"CODE_SNIPPET","relationship_type":"CONTAINS","extra":"Source file contains code snippet: 21","gmt_create":"2026-04-23T15:19:45.620246+08:00","gmt_modified":"2026-04-23T15:19:45.620246+08:00"},{"id":115,"source_id":"58901c94d975d87e652a4dc6c8dda656","target_id":"ffe6df344be81bde3941ad8f0d77910b","source_type":"SOURCE_FILE","target_type":"CODE_SNIPPET","relationship_type":"CONTAINS","extra":"Source file contains code snippet: 13","gmt_create":"2026-04-23T15:19:45.623067+08:00","gmt_modified":"2026-04-23T15:19:45.623067+08:00"},{"id":117,"source_id":"9d08667997a868fc07c9b4e328e44224","target_id":"c71fb14f8866e34c679c94a4e2432bc7","source_type":"SOURCE_FILE","target_type":"CODE_SNIPPET","relationship_type":"CONTAINS","extra":"Source file contains code snippet: 13","gmt_create":"2026-04-23T15:19:45.624846+08:00","gmt_modified":"2026-04-23T15:19:45.624846+08:00"},{"id":119,"source_id":"9228ff67d4c757a85d9421b71f4b29f5","target_id":"3c68f1581d2fd6aa845dd71111a9aa9d","source_type":"SOURCE_FILE","target_type":"CODE_SNIPPET","relationship_type":"CONTAINS","extra":"Source file contains code snippet: 1-57","gmt_create":"2026-04-23T15:19:45.625985+08:00","gmt_modified":"2026-04-23T15:19:45.625985+08:00"},{"id":121,"source_id":"9228ff67d4c757a85d9421b71f4b29f5","target_id":"39afb05755a93800fd685af7274110cb","source_type":"SOURCE_FILE","target_type":"CODE_SNIPPET","relationship_type":"CONTAINS","extra":"Source file contains code snippet: 13-57","gmt_create":"2026-04-23T15:19:45.626917+08:00","gmt_modified":"2026-04-23T15:19:45.626917+08:00"},{"id":123,"source_id":"93022c8938ce318f167277cfa65c29a7","target_id":"87a177f17800991e1ed1fb7be03abdb2","source_type":"SOURCE_FILE","target_type":"CODE_SNIPPET","relationship_type":"CONTAINS","extra":"Source file contains code snippet: 13-42","gmt_create":"2026-04-23T15:19:45.627772+08:00","gmt_modified":"2026-04-23T15:19:45.627772+08:00"},{"id":125,"source_id":"6b3d903205941aa9391dd90016e1102c","target_id":"ae9de874df4a46f4197b6c157c25ec6e","source_type":"SOURCE_FILE","target_type":"CODE_SNIPPET","relationship_type":"CONTAINS","extra":"Source file contains code snippet: 15-85","gmt_create":"2026-04-23T15:19:45.628538+08:00","gmt_modified":"2026-04-23T15:19:45.628538+08:00"},{"id":127,"source_id":"7538ffe4902ab6041adb28b19844962a","target_id":"c066a8d4bffabed87a2e38ccad81c107","source_type":"SOURCE_FILE","target_type":"CODE_SNIPPET","relationship_type":"CONTAINS","extra":"Source file contains code snippet: 25-77","gmt_create":"2026-04-23T15:19:45.629465+08:00","gmt_modified":"2026-04-23T15:19:45.629465+08:00"},{"id":129,"source_id":"58901c94d975d87e652a4dc6c8dda656","target_id":"177c73dc4e71186d9eaa1157fc0fe97f","source_type":"SOURCE_FILE","target_type":"CODE_SNIPPET","relationship_type":"CONTAINS","extra":"Source file contains code snippet: 16-46","gmt_create":"2026-04-23T15:19:45.630333+08:00","gmt_modified":"2026-04-23T15:19:45.630333+08:00"},{"id":131,"source_id":"9228ff67d4c757a85d9421b71f4b29f5","target_id":"a0be0cbddb559575861620b5b7579634","source_type":"SOURCE_FILE","target_type":"CODE_SNIPPET","relationship_type":"CONTAINS","extra":"Source file contains code snippet: 38-51","gmt_create":"2026-04-23T15:19:45.631178+08:00","gmt_modified":"2026-04-23T15:19:45.631178+08:00"},{"id":133,"source_id":"9d08667997a868fc07c9b4e328e44224","target_id":"bcdf50f6234651cb9863ab210e6473e5","source_type":"SOURCE_FILE","target_type":"CODE_SNIPPET","relationship_type":"CONTAINS","extra":"Source file contains code snippet: 16-42","gmt_create":"2026-04-23T15:19:45.632177+08:00","gmt_modified":"2026-04-23T15:19:45.632177+08:00"},{"id":135,"source_id":"4d2f3847b7c10634733118b70a1aea0b","target_id":"6df0277c2486b148fa26c2682dbdaa4c","source_type":"SOURCE_FILE","target_type":"CODE_SNIPPET","relationship_type":"CONTAINS","extra":"Source file contains code snippet: 37-68","gmt_create":"2026-04-23T15:19:45.63307+08:00","gmt_modified":"2026-04-23T15:19:45.63307+08:00"},{"id":137,"source_id":"88d22de3b2a7419868e8ae19130d860c","target_id":"5ea5f192d580031ffe57e1582b70c67e","source_type":"SOURCE_FILE","target_type":"CODE_SNIPPET","relationship_type":"CONTAINS","extra":"Source file contains code snippet: 12-123","gmt_create":"2026-04-23T15:19:45.633929+08:00","gmt_modified":"2026-04-23T15:19:45.633929+08:00"},{"id":139,"source_id":"04e3926c080e795713bff683e7dc9d3e","target_id":"fe4a793f16cd4e12b56253c0a6d53ae0","source_type":"SOURCE_FILE","target_type":"CODE_SNIPPET","relationship_type":"CONTAINS","extra":"Source file contains code snippet: 24-359","gmt_create":"2026-04-23T15:19:45.634775+08:00","gmt_modified":"2026-04-23T15:19:45.634775+08:00"},{"id":141,"source_id":"93022c8938ce318f167277cfa65c29a7","target_id":"9552bd8a528207f18e4f3a1696f26a55","source_type":"SOURCE_FILE","target_type":"CODE_SNIPPET","relationship_type":"CONTAINS","extra":"Source file contains code snippet: 13-37","gmt_create":"2026-04-23T15:19:45.635763+08:00","gmt_modified":"2026-04-23T15:19:45.635763+08:00"},{"id":143,"source_id":"e0c0ca66b8b81cf66e078a7ab162c07f","target_id":"4aad38dfc00a0877bd965c3d0b3c280c","source_type":"SOURCE_FILE","target_type":"CODE_SNIPPET","relationship_type":"CONTAINS","extra":"Source file contains code snippet: 7-34","gmt_create":"2026-04-23T15:19:45.639659+08:00","gmt_modified":"2026-04-23T15:19:45.63966+08:00"},{"id":145,"source_id":"88d22de3b2a7419868e8ae19130d860c","target_id":"9b10dac7dbbb1327afc8a525bf4bd0c3","source_type":"SOURCE_FILE","target_type":"CODE_SNIPPET","relationship_type":"CONTAINS","extra":"Source file contains code snippet: 45-81","gmt_create":"2026-04-23T15:19:45.641965+08:00","gmt_modified":"2026-04-23T15:19:45.641965+08:00"},{"id":147,"source_id":"f301b79d833233ce39d350e82a71c938","target_id":"69118807690ef351a9de910414d5e676","source_type":"SOURCE_FILE","target_type":"CODE_SNIPPET","relationship_type":"CONTAINS","extra":"Source file contains code snippet: 11-94","gmt_create":"2026-04-23T15:19:45.643362+08:00","gmt_modified":"2026-04-23T15:19:45.643362+08:00"},{"id":149,"source_id":"7538ffe4902ab6041adb28b19844962a","target_id":"212d822d207a4c0bd7825bbf20e188e9","source_type":"SOURCE_FILE","target_type":"CODE_SNIPPET","relationship_type":"CONTAINS","extra":"Source file contains code snippet: 59-77","gmt_create":"2026-04-23T15:19:45.644457+08:00","gmt_modified":"2026-04-23T15:19:45.644457+08:00"},{"id":151,"source_id":"04e3926c080e795713bff683e7dc9d3e","target_id":"b0777c7da17be89abb333c81c0dcf349","source_type":"SOURCE_FILE","target_type":"CODE_SNIPPET","relationship_type":"CONTAINS","extra":"Source file contains code snippet: 204-261","gmt_create":"2026-04-23T15:19:45.645243+08:00","gmt_modified":"2026-04-23T15:19:45.645243+08:00"},{"id":153,"source_id":"1a3336b4af8a39a055e912724338580c","target_id":"26288877e8e1f6c4ff5aca12610b0218","source_type":"SOURCE_FILE","target_type":"CODE_SNIPPET","relationship_type":"CONTAINS","extra":"Source file contains code snippet: 7-50","gmt_create":"2026-04-23T15:19:45.646445+08:00","gmt_modified":"2026-04-23T15:19:45.646445+08:00"},{"id":155,"source_id":"04e3926c080e795713bff683e7dc9d3e","target_id":"dbf5f8a57778cf6363e834081f3d771c","source_type":"SOURCE_FILE","target_type":"CODE_SNIPPET","relationship_type":"CONTAINS","extra":"Source file contains code snippet: 327-359","gmt_create":"2026-04-23T15:19:45.647935+08:00","gmt_modified":"2026-04-23T15:19:45.647935+08:00"},{"id":157,"source_id":"c59f8c276697a070dffc581fe94d809c","target_id":"56e46969bdb790a5e8f333184b878d6d","source_type":"SOURCE_FILE","target_type":"CODE_SNIPPET","relationship_type":"CONTAINS","extra":"Source file contains code snippet: 11-41","gmt_create":"2026-04-23T15:19:45.649807+08:00","gmt_modified":"2026-04-23T15:19:45.649807+08:00"},{"id":159,"source_id":"b74caccb06844efcdb14d8324cff65c2","target_id":"4fb8856be3a581fe8303d11b2284ca29","source_type":"SOURCE_FILE","target_type":"CODE_SNIPPET","relationship_type":"CONTAINS","extra":"Source file contains code snippet: 11-55","gmt_create":"2026-04-23T15:19:45.650642+08:00","gmt_modified":"2026-04-23T15:19:45.650642+08:00"},{"id":161,"source_id":"b4a81ef789630d0af6a8d50859d01bf3","target_id":"fd541971cebf8a7c167d717f5c5d1ff6","source_type":"SOURCE_FILE","target_type":"CODE_SNIPPET","relationship_type":"CONTAINS","extra":"Source file contains code snippet: 11-42","gmt_create":"2026-04-23T15:19:45.651529+08:00","gmt_modified":"2026-04-23T15:19:45.651529+08:00"},{"id":163,"source_id":"069738f21ac2da7349d22683e8c36929","target_id":"b84f46f058847733347974841f613688","source_type":"SOURCE_FILE","target_type":"CODE_SNIPPET","relationship_type":"CONTAINS","extra":"Source file contains code snippet: 11-39","gmt_create":"2026-04-23T15:19:45.65251+08:00","gmt_modified":"2026-04-23T15:19:45.65251+08:00"},{"id":165,"source_id":"c59f8c276697a070dffc581fe94d809c","target_id":"1a2657244414b5681afded9565a86422","source_type":"SOURCE_FILE","target_type":"CODE_SNIPPET","relationship_type":"CONTAINS","extra":"Source file contains code snippet: 35-40","gmt_create":"2026-04-23T15:19:45.655814+08:00","gmt_modified":"2026-04-23T15:19:45.655814+08:00"},{"id":167,"source_id":"b74caccb06844efcdb14d8324cff65c2","target_id":"acd5a29be2bdd4ae251e10ca266ffe13","source_type":"SOURCE_FILE","target_type":"CODE_SNIPPET","relationship_type":"CONTAINS","extra":"Source file contains code snippet: 43-48","gmt_create":"2026-04-23T15:19:45.657941+08:00","gmt_modified":"2026-04-23T15:19:45.657942+08:00"},{"id":169,"source_id":"b4a81ef789630d0af6a8d50859d01bf3","target_id":"27a5e2dd1d197b2e3a45be41c57a6183","source_type":"SOURCE_FILE","target_type":"CODE_SNIPPET","relationship_type":"CONTAINS","extra":"Source file contains code snippet: 35","gmt_create":"2026-04-23T15:19:45.658966+08:00","gmt_modified":"2026-04-23T15:19:45.658966+08:00"},{"id":171,"source_id":"069738f21ac2da7349d22683e8c36929","target_id":"c43e8fc0c04c5ed2db7798d99c8c77b8","source_type":"SOURCE_FILE","target_type":"CODE_SNIPPET","relationship_type":"CONTAINS","extra":"Source file contains code snippet: 34","gmt_create":"2026-04-23T15:19:45.659763+08:00","gmt_modified":"2026-04-23T15:19:45.659763+08:00"},{"id":173,"source_id":"93022c8938ce318f167277cfa65c29a7","target_id":"8868ab86034eecf40e80347ef8cbdebd","source_type":"SOURCE_FILE","target_type":"CODE_SNIPPET","relationship_type":"CONTAINS","extra":"Source file contains code snippet: 26-30","gmt_create":"2026-04-23T15:19:45.660491+08:00","gmt_modified":"2026-04-23T15:19:45.660491+08:00"},{"id":175,"source_id":"88d22de3b2a7419868e8ae19130d860c","target_id":"a50f983ec39bac67dff5df80f6dad837","source_type":"SOURCE_FILE","target_type":"CODE_SNIPPET","relationship_type":"CONTAINS","extra":"Source file contains code snippet: 59-60","gmt_create":"2026-04-23T15:19:45.661271+08:00","gmt_modified":"2026-04-23T15:19:45.661271+08:00"},{"id":177,"source_id":"7538ffe4902ab6041adb28b19844962a","target_id":"55f1628f1ab6f323710e367e12146b1a","source_type":"SOURCE_FILE","target_type":"CODE_SNIPPET","relationship_type":"CONTAINS","extra":"Source file contains code snippet: 67-71","gmt_create":"2026-04-23T15:19:45.662055+08:00","gmt_modified":"2026-04-23T15:19:45.662055+08:00"},{"id":179,"source_id":"58901c94d975d87e652a4dc6c8dda656","target_id":"6ef6d32f97d7b50b7a4da541137423c0","source_type":"SOURCE_FILE","target_type":"CODE_SNIPPET","relationship_type":"CONTAINS","extra":"Source file contains code snippet: 23-27","gmt_create":"2026-04-23T15:19:45.662999+08:00","gmt_modified":"2026-04-23T15:19:45.662999+08:00"},{"id":180,"source_id":"deb919cc-9541-4ed7-a581-ae2876ea67c2","target_id":"5cbb1e3f112aeba62a14b0b8999fc0f5","source_type":"WIKI_ITEM","target_type":"SOURCE_FILE","relationship_type":"REFERENCED_BY","extra":"Wiki references source file: backend/app/workers/scheduler.py","gmt_create":"2026-04-23T15:20:08.989793+08:00","gmt_modified":"2026-04-23T15:20:08.989793+08:00"},{"id":181,"source_id":"deb919cc-9541-4ed7-a581-ae2876ea67c2","target_id":"74040de652d5e57f548bb5c4adc3e1a0","source_type":"WIKI_ITEM","target_type":"SOURCE_FILE","relationship_type":"REFERENCED_BY","extra":"Wiki references source file: backend/app/workers/citation_engine.py","gmt_create":"2026-04-23T15:20:08.990186+08:00","gmt_modified":"2026-04-23T15:20:08.990186+08:00"},{"id":182,"source_id":"deb919cc-9541-4ed7-a581-ae2876ea67c2","target_id":"8f973791233c698b3e64a4fb28a93d4b","source_type":"WIKI_ITEM","target_type":"SOURCE_FILE","relationship_type":"REFERENCED_BY","extra":"Wiki references source file: backend/app/workers/platforms/kimi.py","gmt_create":"2026-04-23T15:20:08.990539+08:00","gmt_modified":"2026-04-23T15:20:08.990539+08:00"},{"id":183,"source_id":"deb919cc-9541-4ed7-a581-ae2876ea67c2","target_id":"f642fc1c2f34e15572d9d98aa6c18813","source_type":"WIKI_ITEM","target_type":"SOURCE_FILE","relationship_type":"REFERENCED_BY","extra":"Wiki references source file: backend/app/workers/platforms/wenxin.py","gmt_create":"2026-04-23T15:20:08.990851+08:00","gmt_modified":"2026-04-23T15:20:08.990851+08:00"},{"id":184,"source_id":"deb919cc-9541-4ed7-a581-ae2876ea67c2","target_id":"a16cf42e9559523c4f96ca4c79f9488d","source_type":"WIKI_ITEM","target_type":"SOURCE_FILE","relationship_type":"REFERENCED_BY","extra":"Wiki references source file: backend/app/workers/platforms/base.py","gmt_create":"2026-04-23T15:20:08.991166+08:00","gmt_modified":"2026-04-23T15:20:08.991166+08:00"},{"id":185,"source_id":"deb919cc-9541-4ed7-a581-ae2876ea67c2","target_id":"b74caccb06844efcdb14d8324cff65c2","source_type":"WIKI_ITEM","target_type":"SOURCE_FILE","relationship_type":"REFERENCED_BY","extra":"Wiki references source file: backend/app/models/query.py","gmt_create":"2026-04-23T15:20:08.991471+08:00","gmt_modified":"2026-04-23T15:20:08.991472+08:00"},{"id":186,"source_id":"deb919cc-9541-4ed7-a581-ae2876ea67c2","target_id":"069738f21ac2da7349d22683e8c36929","source_type":"WIKI_ITEM","target_type":"SOURCE_FILE","relationship_type":"REFERENCED_BY","extra":"Wiki references source file: backend/app/models/query_task.py","gmt_create":"2026-04-23T15:20:08.991772+08:00","gmt_modified":"2026-04-23T15:20:08.991772+08:00"},{"id":187,"source_id":"deb919cc-9541-4ed7-a581-ae2876ea67c2","target_id":"b4a81ef789630d0af6a8d50859d01bf3","source_type":"WIKI_ITEM","target_type":"SOURCE_FILE","relationship_type":"REFERENCED_BY","extra":"Wiki references source file: backend/app/models/citation_record.py","gmt_create":"2026-04-23T15:20:08.992186+08:00","gmt_modified":"2026-04-23T15:20:08.992186+08:00"},{"id":188,"source_id":"deb919cc-9541-4ed7-a581-ae2876ea67c2","target_id":"88d22de3b2a7419868e8ae19130d860c","source_type":"WIKI_ITEM","target_type":"SOURCE_FILE","relationship_type":"REFERENCED_BY","extra":"Wiki references source file: backend/app/services/query.py","gmt_create":"2026-04-23T15:20:08.992542+08:00","gmt_modified":"2026-04-23T15:20:08.992542+08:00"},{"id":189,"source_id":"deb919cc-9541-4ed7-a581-ae2876ea67c2","target_id":"6b3d903205941aa9391dd90016e1102c","source_type":"WIKI_ITEM","target_type":"SOURCE_FILE","relationship_type":"REFERENCED_BY","extra":"Wiki references source file: backend/app/api/queries.py","gmt_create":"2026-04-23T15:20:08.992879+08:00","gmt_modified":"2026-04-23T15:20:08.992879+08:00"},{"id":190,"source_id":"deb919cc-9541-4ed7-a581-ae2876ea67c2","target_id":"b0c428683c8a3e6922d90ca0d8c2736d","source_type":"WIKI_ITEM","target_type":"SOURCE_FILE","relationship_type":"REFERENCED_BY","extra":"Wiki references source file: backend/app/database.py","gmt_create":"2026-04-23T15:20:08.997487+08:00","gmt_modified":"2026-04-23T15:20:08.997487+08:00"},{"id":191,"source_id":"deb919cc-9541-4ed7-a581-ae2876ea67c2","target_id":"9ff19022ef915615911280e3c49ed44b","source_type":"WIKI_ITEM","target_type":"SOURCE_FILE","relationship_type":"REFERENCED_BY","extra":"Wiki references source file: backend/app/config.py","gmt_create":"2026-04-23T15:20:08.998695+08:00","gmt_modified":"2026-04-23T15:20:08.998696+08:00"},{"id":192,"source_id":"deb919cc-9541-4ed7-a581-ae2876ea67c2","target_id":"9228ff67d4c757a85d9421b71f4b29f5","source_type":"WIKI_ITEM","target_type":"SOURCE_FILE","relationship_type":"REFERENCED_BY","extra":"Wiki references source file: backend/app/main.py","gmt_create":"2026-04-23T15:20:08.999402+08:00","gmt_modified":"2026-04-23T15:20:08.999402+08:00"},{"id":193,"source_id":"deb919cc-9541-4ed7-a581-ae2876ea67c2","target_id":"b2f0d46a31a5441594f2e777365fc156","source_type":"WIKI_ITEM","target_type":"SOURCE_FILE","relationship_type":"REFERENCED_BY","extra":"Wiki references source file: tests/test_scheduler.py","gmt_create":"2026-04-23T15:20:09.000067+08:00","gmt_modified":"2026-04-23T15:20:09.000067+08:00"},{"id":194,"source_id":"deb919cc-9541-4ed7-a581-ae2876ea67c2","target_id":"0613e76b9679be7f998fb8fd8056e686","source_type":"WIKI_ITEM","target_type":"SOURCE_FILE","relationship_type":"REFERENCED_BY","extra":"Wiki references source file: tests/test_queries.py","gmt_create":"2026-04-23T15:20:09.000413+08:00","gmt_modified":"2026-04-23T15:20:09.000413+08:00"},{"id":195,"source_id":"deb919cc-9541-4ed7-a581-ae2876ea67c2","target_id":"096856da621e23e78422a15e2bfce1f1","source_type":"WIKI_ITEM","target_type":"CODE_SNIPPET","relationship_type":"CONTAINS","extra":"Wiki contains code snippet: backend/app/main.py#13-22","gmt_create":"2026-04-23T15:20:09.000893+08:00","gmt_modified":"2026-04-23T15:20:09.000893+08:00"},{"id":196,"source_id":"9228ff67d4c757a85d9421b71f4b29f5","target_id":"096856da621e23e78422a15e2bfce1f1","source_type":"SOURCE_FILE","target_type":"CODE_SNIPPET","relationship_type":"CONTAINS","extra":"Source file contains code snippet: 13-22","gmt_create":"2026-04-23T15:20:09.00176+08:00","gmt_modified":"2026-04-23T15:20:09.00176+08:00"},{"id":197,"source_id":"deb919cc-9541-4ed7-a581-ae2876ea67c2","target_id":"e230904202fcf7a861c6f49b84f9f863","source_type":"WIKI_ITEM","target_type":"CODE_SNIPPET","relationship_type":"CONTAINS","extra":"Wiki contains code snippet: backend/app/workers/scheduler.py#25-95","gmt_create":"2026-04-23T15:20:09.003004+08:00","gmt_modified":"2026-04-23T15:20:09.003004+08:00"},{"id":198,"source_id":"5cbb1e3f112aeba62a14b0b8999fc0f5","target_id":"e230904202fcf7a861c6f49b84f9f863","source_type":"SOURCE_FILE","target_type":"CODE_SNIPPET","relationship_type":"CONTAINS","extra":"Source file contains code snippet: 25-95","gmt_create":"2026-04-23T15:20:09.003771+08:00","gmt_modified":"2026-04-23T15:20:09.003771+08:00"},{"id":199,"source_id":"deb919cc-9541-4ed7-a581-ae2876ea67c2","target_id":"309607c54b12a6340edc086ffb4737c9","source_type":"WIKI_ITEM","target_type":"CODE_SNIPPET","relationship_type":"CONTAINS","extra":"Wiki contains code snippet: backend/app/workers/citation_engine.py#148-309","gmt_create":"2026-04-23T15:20:09.005186+08:00","gmt_modified":"2026-04-23T15:20:09.005186+08:00"},{"id":200,"source_id":"74040de652d5e57f548bb5c4adc3e1a0","target_id":"309607c54b12a6340edc086ffb4737c9","source_type":"SOURCE_FILE","target_type":"CODE_SNIPPET","relationship_type":"CONTAINS","extra":"Source file contains code snippet: 148-309","gmt_create":"2026-04-23T15:20:09.00622+08:00","gmt_modified":"2026-04-23T15:20:09.00622+08:00"},{"id":201,"source_id":"deb919cc-9541-4ed7-a581-ae2876ea67c2","target_id":"4fb8856be3a581fe8303d11b2284ca29","source_type":"WIKI_ITEM","target_type":"CODE_SNIPPET","relationship_type":"CONTAINS","extra":"Wiki contains code snippet: backend/app/models/query.py#11-55","gmt_create":"2026-04-23T15:20:09.006997+08:00","gmt_modified":"2026-04-23T15:20:09.006997+08:00"},{"id":202,"source_id":"deb919cc-9541-4ed7-a581-ae2876ea67c2","target_id":"b84f46f058847733347974841f613688","source_type":"WIKI_ITEM","target_type":"CODE_SNIPPET","relationship_type":"CONTAINS","extra":"Wiki contains code snippet: backend/app/models/query_task.py#11-39","gmt_create":"2026-04-23T15:20:09.007995+08:00","gmt_modified":"2026-04-23T15:20:09.007995+08:00"},{"id":203,"source_id":"deb919cc-9541-4ed7-a581-ae2876ea67c2","target_id":"fd541971cebf8a7c167d717f5c5d1ff6","source_type":"WIKI_ITEM","target_type":"CODE_SNIPPET","relationship_type":"CONTAINS","extra":"Wiki contains code snippet: backend/app/models/citation_record.py#11-42","gmt_create":"2026-04-23T15:20:09.009222+08:00","gmt_modified":"2026-04-23T15:20:09.009222+08:00"},{"id":204,"source_id":"deb919cc-9541-4ed7-a581-ae2876ea67c2","target_id":"d7c319a04abbc6704da53107e07dd8e7","source_type":"WIKI_ITEM","target_type":"CODE_SNIPPET","relationship_type":"CONTAINS","extra":"Wiki contains code snippet: backend/app/services/query.py#12-130","gmt_create":"2026-04-23T15:20:09.010245+08:00","gmt_modified":"2026-04-23T15:20:09.010245+08:00"},{"id":205,"source_id":"88d22de3b2a7419868e8ae19130d860c","target_id":"d7c319a04abbc6704da53107e07dd8e7","source_type":"SOURCE_FILE","target_type":"CODE_SNIPPET","relationship_type":"CONTAINS","extra":"Source file contains code snippet: 12-130","gmt_create":"2026-04-23T15:20:09.011044+08:00","gmt_modified":"2026-04-23T15:20:09.011044+08:00"},{"id":206,"source_id":"deb919cc-9541-4ed7-a581-ae2876ea67c2","target_id":"9bfc041fe426da2eb78353827e8d9163","source_type":"WIKI_ITEM","target_type":"CODE_SNIPPET","relationship_type":"CONTAINS","extra":"Wiki contains code snippet: backend/app/database.py#1-29","gmt_create":"2026-04-23T15:20:09.012195+08:00","gmt_modified":"2026-04-23T15:20:09.012195+08:00"},{"id":207,"source_id":"b0c428683c8a3e6922d90ca0d8c2736d","target_id":"9bfc041fe426da2eb78353827e8d9163","source_type":"SOURCE_FILE","target_type":"CODE_SNIPPET","relationship_type":"CONTAINS","extra":"Source file contains code snippet: 1-29","gmt_create":"2026-04-23T15:20:09.01291+08:00","gmt_modified":"2026-04-23T15:20:09.012911+08:00"},{"id":208,"source_id":"deb919cc-9541-4ed7-a581-ae2876ea67c2","target_id":"ad67863041d9eea2b0fb542b5aa33aca","source_type":"WIKI_ITEM","target_type":"CODE_SNIPPET","relationship_type":"CONTAINS","extra":"Wiki contains code snippet: backend/app/workers/platforms/base.py#4-18","gmt_create":"2026-04-23T15:20:09.013886+08:00","gmt_modified":"2026-04-23T15:20:09.013886+08:00"},{"id":209,"source_id":"a16cf42e9559523c4f96ca4c79f9488d","target_id":"ad67863041d9eea2b0fb542b5aa33aca","source_type":"SOURCE_FILE","target_type":"CODE_SNIPPET","relationship_type":"CONTAINS","extra":"Source file contains code snippet: 4-18","gmt_create":"2026-04-23T15:20:09.014746+08:00","gmt_modified":"2026-04-23T15:20:09.014746+08:00"},{"id":210,"source_id":"deb919cc-9541-4ed7-a581-ae2876ea67c2","target_id":"eecf9581dbaa0a515cf11514175e7ef9","source_type":"WIKI_ITEM","target_type":"CODE_SNIPPET","relationship_type":"CONTAINS","extra":"Wiki contains code snippet: backend/app/workers/platforms/kimi.py#11-206","gmt_create":"2026-04-23T15:20:09.015594+08:00","gmt_modified":"2026-04-23T15:20:09.015594+08:00"},{"id":211,"source_id":"8f973791233c698b3e64a4fb28a93d4b","target_id":"eecf9581dbaa0a515cf11514175e7ef9","source_type":"SOURCE_FILE","target_type":"CODE_SNIPPET","relationship_type":"CONTAINS","extra":"Source file contains code snippet: 11-206","gmt_create":"2026-04-23T15:20:09.016313+08:00","gmt_modified":"2026-04-23T15:20:09.016313+08:00"},{"id":212,"source_id":"deb919cc-9541-4ed7-a581-ae2876ea67c2","target_id":"5563c29185326a59be61ee0a6eec4463","source_type":"WIKI_ITEM","target_type":"CODE_SNIPPET","relationship_type":"CONTAINS","extra":"Wiki contains code snippet: backend/app/workers/platforms/wenxin.py#11-205","gmt_create":"2026-04-23T15:20:09.017693+08:00","gmt_modified":"2026-04-23T15:20:09.017693+08:00"},{"id":213,"source_id":"f642fc1c2f34e15572d9d98aa6c18813","target_id":"5563c29185326a59be61ee0a6eec4463","source_type":"SOURCE_FILE","target_type":"CODE_SNIPPET","relationship_type":"CONTAINS","extra":"Source file contains code snippet: 11-205","gmt_create":"2026-04-23T15:20:09.018896+08:00","gmt_modified":"2026-04-23T15:20:09.018896+08:00"},{"id":214,"source_id":"deb919cc-9541-4ed7-a581-ae2876ea67c2","target_id":"2d35e1345d25020f8e7ac1318db06f7b","source_type":"WIKI_ITEM","target_type":"CODE_SNIPPET","relationship_type":"CONTAINS","extra":"Wiki contains code snippet: backend/app/workers/scheduler.py#30-90","gmt_create":"2026-04-23T15:20:09.025147+08:00","gmt_modified":"2026-04-23T15:20:09.025147+08:00"},{"id":215,"source_id":"5cbb1e3f112aeba62a14b0b8999fc0f5","target_id":"2d35e1345d25020f8e7ac1318db06f7b","source_type":"SOURCE_FILE","target_type":"CODE_SNIPPET","relationship_type":"CONTAINS","extra":"Source file contains code snippet: 30-90","gmt_create":"2026-04-23T15:20:09.02579+08:00","gmt_modified":"2026-04-23T15:20:09.02579+08:00"},{"id":216,"source_id":"deb919cc-9541-4ed7-a581-ae2876ea67c2","target_id":"91bda120c0ab69e0e7103a1c89c82424","source_type":"WIKI_ITEM","target_type":"CODE_SNIPPET","relationship_type":"CONTAINS","extra":"Wiki contains code snippet: backend/app/workers/scheduler.py#95-172","gmt_create":"2026-04-23T15:20:09.026853+08:00","gmt_modified":"2026-04-23T15:20:09.026853+08:00"},{"id":217,"source_id":"5cbb1e3f112aeba62a14b0b8999fc0f5","target_id":"91bda120c0ab69e0e7103a1c89c82424","source_type":"SOURCE_FILE","target_type":"CODE_SNIPPET","relationship_type":"CONTAINS","extra":"Source file contains code snippet: 95-172","gmt_create":"2026-04-23T15:20:09.027566+08:00","gmt_modified":"2026-04-23T15:20:09.027566+08:00"},{"id":218,"source_id":"deb919cc-9541-4ed7-a581-ae2876ea67c2","target_id":"160b5326537d25444c40a459a01e79c6","source_type":"WIKI_ITEM","target_type":"CODE_SNIPPET","relationship_type":"CONTAINS","extra":"Wiki contains code snippet: backend/app/workers/citation_engine.py#159-234","gmt_create":"2026-04-23T15:20:09.028202+08:00","gmt_modified":"2026-04-23T15:20:09.028202+08:00"},{"id":219,"source_id":"74040de652d5e57f548bb5c4adc3e1a0","target_id":"160b5326537d25444c40a459a01e79c6","source_type":"SOURCE_FILE","target_type":"CODE_SNIPPET","relationship_type":"CONTAINS","extra":"Source file contains code snippet: 159-234","gmt_create":"2026-04-23T15:20:09.028744+08:00","gmt_modified":"2026-04-23T15:20:09.028744+08:00"},{"id":220,"source_id":"deb919cc-9541-4ed7-a581-ae2876ea67c2","target_id":"6712051c987e10a7c26b089063367398","source_type":"WIKI_ITEM","target_type":"CODE_SNIPPET","relationship_type":"CONTAINS","extra":"Wiki contains code snippet: backend/app/models/query.py#24-31","gmt_create":"2026-04-23T15:20:09.029494+08:00","gmt_modified":"2026-04-23T15:20:09.029494+08:00"},{"id":221,"source_id":"b74caccb06844efcdb14d8324cff65c2","target_id":"6712051c987e10a7c26b089063367398","source_type":"SOURCE_FILE","target_type":"CODE_SNIPPET","relationship_type":"CONTAINS","extra":"Source file contains code snippet: 24-31","gmt_create":"2026-04-23T15:20:09.030084+08:00","gmt_modified":"2026-04-23T15:20:09.030084+08:00"},{"id":222,"source_id":"deb919cc-9541-4ed7-a581-ae2876ea67c2","target_id":"ac5982063da5f04315f3e82a0d653902","source_type":"WIKI_ITEM","target_type":"CODE_SNIPPET","relationship_type":"CONTAINS","extra":"Wiki contains code snippet: backend/app/models/query_task.py#24-32","gmt_create":"2026-04-23T15:20:09.030828+08:00","gmt_modified":"2026-04-23T15:20:09.030828+08:00"},{"id":223,"source_id":"069738f21ac2da7349d22683e8c36929","target_id":"ac5982063da5f04315f3e82a0d653902","source_type":"SOURCE_FILE","target_type":"CODE_SNIPPET","relationship_type":"CONTAINS","extra":"Source file contains code snippet: 24-32","gmt_create":"2026-04-23T15:20:09.031632+08:00","gmt_modified":"2026-04-23T15:20:09.031632+08:00"},{"id":224,"source_id":"deb919cc-9541-4ed7-a581-ae2876ea67c2","target_id":"06ed912983db33bb8aca162fed68282b","source_type":"WIKI_ITEM","target_type":"CODE_SNIPPET","relationship_type":"CONTAINS","extra":"Wiki contains code snippet: backend/app/models/citation_record.py#24-29","gmt_create":"2026-04-23T15:20:09.032417+08:00","gmt_modified":"2026-04-23T15:20:09.032417+08:00"},{"id":225,"source_id":"b4a81ef789630d0af6a8d50859d01bf3","target_id":"06ed912983db33bb8aca162fed68282b","source_type":"SOURCE_FILE","target_type":"CODE_SNIPPET","relationship_type":"CONTAINS","extra":"Source file contains code snippet: 24-29","gmt_create":"2026-04-23T15:20:09.032976+08:00","gmt_modified":"2026-04-23T15:20:09.032976+08:00"},{"id":226,"source_id":"deb919cc-9541-4ed7-a581-ae2876ea67c2","target_id":"b624be78e3bffd876e403cff2557b088","source_type":"WIKI_ITEM","target_type":"CODE_SNIPPET","relationship_type":"CONTAINS","extra":"Wiki contains code snippet: backend/app/workers/citation_engine.py#19-120","gmt_create":"2026-04-23T15:20:09.037331+08:00","gmt_modified":"2026-04-23T15:20:09.037331+08:00"},{"id":227,"source_id":"74040de652d5e57f548bb5c4adc3e1a0","target_id":"b624be78e3bffd876e403cff2557b088","source_type":"SOURCE_FILE","target_type":"CODE_SNIPPET","relationship_type":"CONTAINS","extra":"Source file contains code snippet: 19-120","gmt_create":"2026-04-23T15:20:09.038413+08:00","gmt_modified":"2026-04-23T15:20:09.038413+08:00"},{"id":228,"source_id":"deb919cc-9541-4ed7-a581-ae2876ea67c2","target_id":"40d0b169aad65c8bb38077deb052fc72","source_type":"WIKI_ITEM","target_type":"CODE_SNIPPET","relationship_type":"CONTAINS","extra":"Wiki contains code snippet: backend/app/workers/platforms/kimi.py#33-125","gmt_create":"2026-04-23T15:20:09.040261+08:00","gmt_modified":"2026-04-23T15:20:09.040261+08:00"},{"id":229,"source_id":"8f973791233c698b3e64a4fb28a93d4b","target_id":"40d0b169aad65c8bb38077deb052fc72","source_type":"SOURCE_FILE","target_type":"CODE_SNIPPET","relationship_type":"CONTAINS","extra":"Source file contains code snippet: 33-125","gmt_create":"2026-04-23T15:20:09.04098+08:00","gmt_modified":"2026-04-23T15:20:09.04098+08:00"},{"id":230,"source_id":"deb919cc-9541-4ed7-a581-ae2876ea67c2","target_id":"8b5af998852596e1e08b0e0216bc4b93","source_type":"WIKI_ITEM","target_type":"CODE_SNIPPET","relationship_type":"CONTAINS","extra":"Wiki contains code snippet: backend/app/workers/platforms/wenxin.py#33-124","gmt_create":"2026-04-23T15:20:09.041526+08:00","gmt_modified":"2026-04-23T15:20:09.041526+08:00"},{"id":231,"source_id":"f642fc1c2f34e15572d9d98aa6c18813","target_id":"8b5af998852596e1e08b0e0216bc4b93","source_type":"SOURCE_FILE","target_type":"CODE_SNIPPET","relationship_type":"CONTAINS","extra":"Source file contains code snippet: 33-124","gmt_create":"2026-04-23T15:20:09.041834+08:00","gmt_modified":"2026-04-23T15:20:09.041834+08:00"},{"id":232,"source_id":"deb919cc-9541-4ed7-a581-ae2876ea67c2","target_id":"fe70b1fef9f36e73d26d84987e927c7a","source_type":"WIKI_ITEM","target_type":"CODE_SNIPPET","relationship_type":"CONTAINS","extra":"Wiki contains code snippet: backend/app/api/queries.py#15-86","gmt_create":"2026-04-23T15:20:09.04598+08:00","gmt_modified":"2026-04-23T15:20:09.04598+08:00"},{"id":233,"source_id":"6b3d903205941aa9391dd90016e1102c","target_id":"fe70b1fef9f36e73d26d84987e927c7a","source_type":"SOURCE_FILE","target_type":"CODE_SNIPPET","relationship_type":"CONTAINS","extra":"Source file contains code snippet: 15-86","gmt_create":"2026-04-23T15:20:09.046352+08:00","gmt_modified":"2026-04-23T15:20:09.046352+08:00"},{"id":234,"source_id":"deb919cc-9541-4ed7-a581-ae2876ea67c2","target_id":"e1d2b027678118df4d0a50ce9269271d","source_type":"WIKI_ITEM","target_type":"CODE_SNIPPET","relationship_type":"CONTAINS","extra":"Wiki contains code snippet: backend/app/workers/scheduler.py#42-90","gmt_create":"2026-04-23T15:20:09.050041+08:00","gmt_modified":"2026-04-23T15:20:09.050041+08:00"},{"id":235,"source_id":"5cbb1e3f112aeba62a14b0b8999fc0f5","target_id":"e1d2b027678118df4d0a50ce9269271d","source_type":"SOURCE_FILE","target_type":"CODE_SNIPPET","relationship_type":"CONTAINS","extra":"Source file contains code snippet: 42-90","gmt_create":"2026-04-23T15:20:09.050351+08:00","gmt_modified":"2026-04-23T15:20:09.050351+08:00"},{"id":236,"source_id":"deb919cc-9541-4ed7-a581-ae2876ea67c2","target_id":"e79301a4bc26aa6b49f3f52c3182c3f9","source_type":"WIKI_ITEM","target_type":"CODE_SNIPPET","relationship_type":"CONTAINS","extra":"Wiki contains code snippet: backend/app/workers/citation_engine.py#175-234","gmt_create":"2026-04-23T15:20:09.051815+08:00","gmt_modified":"2026-04-23T15:20:09.051815+08:00"},{"id":237,"source_id":"74040de652d5e57f548bb5c4adc3e1a0","target_id":"e79301a4bc26aa6b49f3f52c3182c3f9","source_type":"SOURCE_FILE","target_type":"CODE_SNIPPET","relationship_type":"CONTAINS","extra":"Source file contains code snippet: 175-234","gmt_create":"2026-04-23T15:20:09.052165+08:00","gmt_modified":"2026-04-23T15:20:09.052166+08:00"},{"id":238,"source_id":"deb919cc-9541-4ed7-a581-ae2876ea67c2","target_id":"1e85186eded8743ff5f231df4aa6df3f","source_type":"WIKI_ITEM","target_type":"CODE_SNIPPET","relationship_type":"CONTAINS","extra":"Wiki contains code snippet: backend/app/workers/platforms/kimi.py#21-48","gmt_create":"2026-04-23T15:20:09.052615+08:00","gmt_modified":"2026-04-23T15:20:09.052615+08:00"},{"id":239,"source_id":"8f973791233c698b3e64a4fb28a93d4b","target_id":"1e85186eded8743ff5f231df4aa6df3f","source_type":"SOURCE_FILE","target_type":"CODE_SNIPPET","relationship_type":"CONTAINS","extra":"Source file contains code snippet: 21-48","gmt_create":"2026-04-23T15:20:09.052947+08:00","gmt_modified":"2026-04-23T15:20:09.052947+08:00"},{"id":240,"source_id":"deb919cc-9541-4ed7-a581-ae2876ea67c2","target_id":"e2b1718570fb714b2f4342221898ab30","source_type":"WIKI_ITEM","target_type":"CODE_SNIPPET","relationship_type":"CONTAINS","extra":"Wiki contains code snippet: backend/app/workers/platforms/wenxin.py#21-48","gmt_create":"2026-04-23T15:20:09.053449+08:00","gmt_modified":"2026-04-23T15:20:09.053449+08:00"},{"id":241,"source_id":"f642fc1c2f34e15572d9d98aa6c18813","target_id":"e2b1718570fb714b2f4342221898ab30","source_type":"SOURCE_FILE","target_type":"CODE_SNIPPET","relationship_type":"CONTAINS","extra":"Source file contains code snippet: 21-48","gmt_create":"2026-04-23T15:20:09.053892+08:00","gmt_modified":"2026-04-23T15:20:09.053892+08:00"},{"id":242,"source_id":"deb919cc-9541-4ed7-a581-ae2876ea67c2","target_id":"e4a49039dae40b7433896c81737fcf8c","source_type":"WIKI_ITEM","target_type":"CODE_SNIPPET","relationship_type":"CONTAINS","extra":"Wiki contains code snippet: backend/app/config.py#7-14","gmt_create":"2026-04-23T15:20:09.05437+08:00","gmt_modified":"2026-04-23T15:20:09.05437+08:00"},{"id":243,"source_id":"9ff19022ef915615911280e3c49ed44b","target_id":"e4a49039dae40b7433896c81737fcf8c","source_type":"SOURCE_FILE","target_type":"CODE_SNIPPET","relationship_type":"CONTAINS","extra":"Source file contains code snippet: 7-14","gmt_create":"2026-04-23T15:20:09.054841+08:00","gmt_modified":"2026-04-23T15:20:09.054841+08:00"},{"id":244,"source_id":"deb919cc-9541-4ed7-a581-ae2876ea67c2","target_id":"2ee31d68c409e96e951f6cfa7027bca7","source_type":"WIKI_ITEM","target_type":"CODE_SNIPPET","relationship_type":"CONTAINS","extra":"Wiki contains code snippet: backend/app/main.py#24-42","gmt_create":"2026-04-23T15:20:09.055328+08:00","gmt_modified":"2026-04-23T15:20:09.055328+08:00"},{"id":245,"source_id":"9228ff67d4c757a85d9421b71f4b29f5","target_id":"2ee31d68c409e96e951f6cfa7027bca7","source_type":"SOURCE_FILE","target_type":"CODE_SNIPPET","relationship_type":"CONTAINS","extra":"Source file contains code snippet: 24-42","gmt_create":"2026-04-23T15:20:09.055781+08:00","gmt_modified":"2026-04-23T15:20:09.055781+08:00"},{"id":246,"source_id":"deb919cc-9541-4ed7-a581-ae2876ea67c2","target_id":"79d6e169e36e6b7493898b5f863e07dc","source_type":"WIKI_ITEM","target_type":"CODE_SNIPPET","relationship_type":"CONTAINS","extra":"Wiki contains code snippet: backend/app/workers/citation_engine.py#152-157","gmt_create":"2026-04-23T15:20:09.056898+08:00","gmt_modified":"2026-04-23T15:20:09.056898+08:00"},{"id":247,"source_id":"74040de652d5e57f548bb5c4adc3e1a0","target_id":"79d6e169e36e6b7493898b5f863e07dc","source_type":"SOURCE_FILE","target_type":"CODE_SNIPPET","relationship_type":"CONTAINS","extra":"Source file contains code snippet: 152-157","gmt_create":"2026-04-23T15:20:09.057188+08:00","gmt_modified":"2026-04-23T15:20:09.057188+08:00"},{"id":248,"source_id":"deb919cc-9541-4ed7-a581-ae2876ea67c2","target_id":"1552315d5fb9f6d7aba5f7e8fa93a975","source_type":"WIKI_ITEM","target_type":"CODE_SNIPPET","relationship_type":"CONTAINS","extra":"Wiki contains code snippet: backend/app/database.py#6-10","gmt_create":"2026-04-23T15:20:09.058217+08:00","gmt_modified":"2026-04-23T15:20:09.058217+08:00"},{"id":249,"source_id":"b0c428683c8a3e6922d90ca0d8c2736d","target_id":"1552315d5fb9f6d7aba5f7e8fa93a975","source_type":"SOURCE_FILE","target_type":"CODE_SNIPPET","relationship_type":"CONTAINS","extra":"Source file contains code snippet: 6-10","gmt_create":"2026-04-23T15:20:09.058503+08:00","gmt_modified":"2026-04-23T15:20:09.058503+08:00"},{"id":250,"source_id":"deb919cc-9541-4ed7-a581-ae2876ea67c2","target_id":"599cca7536cae4a7e0ae93043c476a7f","source_type":"WIKI_ITEM","target_type":"CODE_SNIPPET","relationship_type":"CONTAINS","extra":"Wiki contains code snippet: tests/test_queries.py#10-154","gmt_create":"2026-04-23T15:20:09.058947+08:00","gmt_modified":"2026-04-23T15:20:09.058947+08:00"},{"id":251,"source_id":"0613e76b9679be7f998fb8fd8056e686","target_id":"599cca7536cae4a7e0ae93043c476a7f","source_type":"SOURCE_FILE","target_type":"CODE_SNIPPET","relationship_type":"CONTAINS","extra":"Source file contains code snippet: 10-154","gmt_create":"2026-04-23T15:20:09.059242+08:00","gmt_modified":"2026-04-23T15:20:09.059242+08:00"},{"id":252,"source_id":"deb919cc-9541-4ed7-a581-ae2876ea67c2","target_id":"2ec3d45edd6221e0cedf7f8887fe090d","source_type":"WIKI_ITEM","target_type":"CODE_SNIPPET","relationship_type":"CONTAINS","extra":"Wiki contains code snippet: tests/test_scheduler.py#17-123","gmt_create":"2026-04-23T15:20:09.059776+08:00","gmt_modified":"2026-04-23T15:20:09.059776+08:00"},{"id":253,"source_id":"b2f0d46a31a5441594f2e777365fc156","target_id":"2ec3d45edd6221e0cedf7f8887fe090d","source_type":"SOURCE_FILE","target_type":"CODE_SNIPPET","relationship_type":"CONTAINS","extra":"Source file contains code snippet: 17-123","gmt_create":"2026-04-23T15:20:09.060064+08:00","gmt_modified":"2026-04-23T15:20:09.060064+08:00"},{"id":254,"source_id":"262a3941-fdc6-46b0-b767-be40aa9d5761","target_id":"99fe1b288fd41daa86c2dfbab819abf0","source_type":"WIKI_ITEM","target_type":"SOURCE_FILE","relationship_type":"REFERENCED_BY","extra":"Wiki references source file: backend/app/models/__init__.py","gmt_create":"2026-04-23T15:21:46.707277+08:00","gmt_modified":"2026-04-23T15:21:46.707277+08:00"},{"id":255,"source_id":"262a3941-fdc6-46b0-b767-be40aa9d5761","target_id":"c59f8c276697a070dffc581fe94d809c","source_type":"WIKI_ITEM","target_type":"SOURCE_FILE","relationship_type":"REFERENCED_BY","extra":"Wiki references source file: backend/app/models/user.py","gmt_create":"2026-04-23T15:21:46.707879+08:00","gmt_modified":"2026-04-23T15:21:46.707879+08:00"},{"id":256,"source_id":"262a3941-fdc6-46b0-b767-be40aa9d5761","target_id":"b74caccb06844efcdb14d8324cff65c2","source_type":"WIKI_ITEM","target_type":"SOURCE_FILE","relationship_type":"REFERENCED_BY","extra":"Wiki references source file: backend/app/models/query.py","gmt_create":"2026-04-23T15:21:46.708322+08:00","gmt_modified":"2026-04-23T15:21:46.708322+08:00"},{"id":257,"source_id":"262a3941-fdc6-46b0-b767-be40aa9d5761","target_id":"069738f21ac2da7349d22683e8c36929","source_type":"WIKI_ITEM","target_type":"SOURCE_FILE","relationship_type":"REFERENCED_BY","extra":"Wiki references source file: backend/app/models/query_task.py","gmt_create":"2026-04-23T15:21:46.708702+08:00","gmt_modified":"2026-04-23T15:21:46.708702+08:00"},{"id":258,"source_id":"262a3941-fdc6-46b0-b767-be40aa9d5761","target_id":"b4a81ef789630d0af6a8d50859d01bf3","source_type":"WIKI_ITEM","target_type":"SOURCE_FILE","relationship_type":"REFERENCED_BY","extra":"Wiki references source file: backend/app/models/citation_record.py","gmt_create":"2026-04-23T15:21:46.709093+08:00","gmt_modified":"2026-04-23T15:21:46.709093+08:00"},{"id":259,"source_id":"262a3941-fdc6-46b0-b767-be40aa9d5761","target_id":"bceca00463fe55d3bcafda728f97f723","source_type":"WIKI_ITEM","target_type":"SOURCE_FILE","relationship_type":"REFERENCED_BY","extra":"Wiki references source file: backend/app/models/subscription.py","gmt_create":"2026-04-23T15:21:46.709712+08:00","gmt_modified":"2026-04-23T15:21:46.709713+08:00"},{"id":260,"source_id":"262a3941-fdc6-46b0-b767-be40aa9d5761","target_id":"b0c428683c8a3e6922d90ca0d8c2736d","source_type":"WIKI_ITEM","target_type":"SOURCE_FILE","relationship_type":"REFERENCED_BY","extra":"Wiki references source file: backend/app/database.py","gmt_create":"2026-04-23T15:21:46.710101+08:00","gmt_modified":"2026-04-23T15:21:46.710101+08:00"},{"id":261,"source_id":"262a3941-fdc6-46b0-b767-be40aa9d5761","target_id":"d4f95fcf50683b5bf6167c7d2a6b126d","source_type":"WIKI_ITEM","target_type":"SOURCE_FILE","relationship_type":"REFERENCED_BY","extra":"Wiki references source file: backend/alembic/versions/488d0bd5ab01_initial_migration.py","gmt_create":"2026-04-23T15:21:46.710429+08:00","gmt_modified":"2026-04-23T15:21:46.710429+08:00"},{"id":262,"source_id":"262a3941-fdc6-46b0-b767-be40aa9d5761","target_id":"f301b79d833233ce39d350e82a71c938","source_type":"WIKI_ITEM","target_type":"SOURCE_FILE","relationship_type":"REFERENCED_BY","extra":"Wiki references source file: backend/app/schemas/query.py","gmt_create":"2026-04-23T15:21:46.710829+08:00","gmt_modified":"2026-04-23T15:21:46.710829+08:00"},{"id":263,"source_id":"262a3941-fdc6-46b0-b767-be40aa9d5761","target_id":"1a3336b4af8a39a055e912724338580c","source_type":"WIKI_ITEM","target_type":"SOURCE_FILE","relationship_type":"REFERENCED_BY","extra":"Wiki references source file: backend/app/schemas/citation.py","gmt_create":"2026-04-23T15:21:46.711181+08:00","gmt_modified":"2026-04-23T15:21:46.711181+08:00"},{"id":264,"source_id":"262a3941-fdc6-46b0-b767-be40aa9d5761","target_id":"88d22de3b2a7419868e8ae19130d860c","source_type":"WIKI_ITEM","target_type":"SOURCE_FILE","relationship_type":"REFERENCED_BY","extra":"Wiki references source file: backend/app/services/query.py","gmt_create":"2026-04-23T15:21:46.711568+08:00","gmt_modified":"2026-04-23T15:21:46.711568+08:00"},{"id":265,"source_id":"262a3941-fdc6-46b0-b767-be40aa9d5761","target_id":"6b3d903205941aa9391dd90016e1102c","source_type":"WIKI_ITEM","target_type":"SOURCE_FILE","relationship_type":"REFERENCED_BY","extra":"Wiki references source file: backend/app/api/queries.py","gmt_create":"2026-04-23T15:21:46.711965+08:00","gmt_modified":"2026-04-23T15:21:46.711965+08:00"},{"id":266,"source_id":"262a3941-fdc6-46b0-b767-be40aa9d5761","target_id":"04e3926c080e795713bff683e7dc9d3e","source_type":"WIKI_ITEM","target_type":"SOURCE_FILE","relationship_type":"REFERENCED_BY","extra":"Wiki references source file: backend/app/services/citation.py","gmt_create":"2026-04-23T15:21:46.712296+08:00","gmt_modified":"2026-04-23T15:21:46.712296+08:00"},{"id":267,"source_id":"262a3941-fdc6-46b0-b767-be40aa9d5761","target_id":"7538ffe4902ab6041adb28b19844962a","source_type":"WIKI_ITEM","target_type":"SOURCE_FILE","relationship_type":"REFERENCED_BY","extra":"Wiki references source file: backend/app/api/citations.py","gmt_create":"2026-04-23T15:21:46.712792+08:00","gmt_modified":"2026-04-23T15:21:46.712792+08:00"},{"id":268,"source_id":"262a3941-fdc6-46b0-b767-be40aa9d5761","target_id":"9ff19022ef915615911280e3c49ed44b","source_type":"WIKI_ITEM","target_type":"SOURCE_FILE","relationship_type":"REFERENCED_BY","extra":"Wiki references source file: backend/app/config.py","gmt_create":"2026-04-23T15:21:46.713121+08:00","gmt_modified":"2026-04-23T15:21:46.713121+08:00"},{"id":269,"source_id":"262a3941-fdc6-46b0-b767-be40aa9d5761","target_id":"9d08667997a868fc07c9b4e328e44224","source_type":"WIKI_ITEM","target_type":"SOURCE_FILE","relationship_type":"REFERENCED_BY","extra":"Wiki references source file: backend/app/api/deps.py","gmt_create":"2026-04-23T15:21:46.713538+08:00","gmt_modified":"2026-04-23T15:21:46.713538+08:00"},{"id":270,"source_id":"262a3941-fdc6-46b0-b767-be40aa9d5761","target_id":"56e46969bdb790a5e8f333184b878d6d","source_type":"WIKI_ITEM","target_type":"CODE_SNIPPET","relationship_type":"CONTAINS","extra":"Wiki contains code snippet: backend/app/models/user.py#11-41","gmt_create":"2026-04-23T15:21:46.71408+08:00","gmt_modified":"2026-04-23T15:21:46.71408+08:00"},{"id":271,"source_id":"262a3941-fdc6-46b0-b767-be40aa9d5761","target_id":"4fb8856be3a581fe8303d11b2284ca29","source_type":"WIKI_ITEM","target_type":"CODE_SNIPPET","relationship_type":"CONTAINS","extra":"Wiki contains code snippet: backend/app/models/query.py#11-55","gmt_create":"2026-04-23T15:21:46.714746+08:00","gmt_modified":"2026-04-23T15:21:46.714746+08:00"},{"id":272,"source_id":"262a3941-fdc6-46b0-b767-be40aa9d5761","target_id":"b84f46f058847733347974841f613688","source_type":"WIKI_ITEM","target_type":"CODE_SNIPPET","relationship_type":"CONTAINS","extra":"Wiki contains code snippet: backend/app/models/query_task.py#11-39","gmt_create":"2026-04-23T15:21:46.715399+08:00","gmt_modified":"2026-04-23T15:21:46.7154+08:00"},{"id":273,"source_id":"262a3941-fdc6-46b0-b767-be40aa9d5761","target_id":"fd541971cebf8a7c167d717f5c5d1ff6","source_type":"WIKI_ITEM","target_type":"CODE_SNIPPET","relationship_type":"CONTAINS","extra":"Wiki contains code snippet: backend/app/models/citation_record.py#11-42","gmt_create":"2026-04-23T15:21:46.716178+08:00","gmt_modified":"2026-04-23T15:21:46.716178+08:00"},{"id":274,"source_id":"262a3941-fdc6-46b0-b767-be40aa9d5761","target_id":"4d323bf0aaf4078f09726dc0890e5955","source_type":"WIKI_ITEM","target_type":"CODE_SNIPPET","relationship_type":"CONTAINS","extra":"Wiki contains code snippet: backend/app/models/subscription.py#11-37","gmt_create":"2026-04-23T15:21:46.717324+08:00","gmt_modified":"2026-04-23T15:21:46.717324+08:00"},{"id":275,"source_id":"bceca00463fe55d3bcafda728f97f723","target_id":"4d323bf0aaf4078f09726dc0890e5955","source_type":"SOURCE_FILE","target_type":"CODE_SNIPPET","relationship_type":"CONTAINS","extra":"Source file contains code snippet: 11-37","gmt_create":"2026-04-23T15:21:46.718049+08:00","gmt_modified":"2026-04-23T15:21:46.71805+08:00"},{"id":276,"source_id":"262a3941-fdc6-46b0-b767-be40aa9d5761","target_id":"9bfc041fe426da2eb78353827e8d9163","source_type":"WIKI_ITEM","target_type":"CODE_SNIPPET","relationship_type":"CONTAINS","extra":"Wiki contains code snippet: backend/app/database.py#1-29","gmt_create":"2026-04-23T15:21:46.718816+08:00","gmt_modified":"2026-04-23T15:21:46.718816+08:00"},{"id":277,"source_id":"262a3941-fdc6-46b0-b767-be40aa9d5761","target_id":"4cef9e740b6feb68c6bd22b660c47320","source_type":"WIKI_ITEM","target_type":"CODE_SNIPPET","relationship_type":"CONTAINS","extra":"Wiki contains code snippet: backend/app/services/query.py#1-123","gmt_create":"2026-04-23T15:21:46.719468+08:00","gmt_modified":"2026-04-23T15:21:46.719468+08:00"},{"id":278,"source_id":"88d22de3b2a7419868e8ae19130d860c","target_id":"4cef9e740b6feb68c6bd22b660c47320","source_type":"SOURCE_FILE","target_type":"CODE_SNIPPET","relationship_type":"CONTAINS","extra":"Source file contains code snippet: 1-123","gmt_create":"2026-04-23T15:21:46.720008+08:00","gmt_modified":"2026-04-23T15:21:46.720008+08:00"},{"id":279,"source_id":"262a3941-fdc6-46b0-b767-be40aa9d5761","target_id":"121203f7f9f539ffb1456c3f5cdfd842","source_type":"WIKI_ITEM","target_type":"CODE_SNIPPET","relationship_type":"CONTAINS","extra":"Wiki contains code snippet: backend/app/services/citation.py#1-359","gmt_create":"2026-04-23T15:21:46.720615+08:00","gmt_modified":"2026-04-23T15:21:46.720615+08:00"},{"id":280,"source_id":"04e3926c080e795713bff683e7dc9d3e","target_id":"121203f7f9f539ffb1456c3f5cdfd842","source_type":"SOURCE_FILE","target_type":"CODE_SNIPPET","relationship_type":"CONTAINS","extra":"Source file contains code snippet: 1-359","gmt_create":"2026-04-23T15:21:46.721095+08:00","gmt_modified":"2026-04-23T15:21:46.721095+08:00"},{"id":281,"source_id":"262a3941-fdc6-46b0-b767-be40aa9d5761","target_id":"10d1e37bdc9f353c189b7a2fe79dc85e","source_type":"WIKI_ITEM","target_type":"CODE_SNIPPET","relationship_type":"CONTAINS","extra":"Wiki contains code snippet: backend/app/api/queries.py#1-86","gmt_create":"2026-04-23T15:21:46.721634+08:00","gmt_modified":"2026-04-23T15:21:46.721634+08:00"},{"id":282,"source_id":"6b3d903205941aa9391dd90016e1102c","target_id":"10d1e37bdc9f353c189b7a2fe79dc85e","source_type":"SOURCE_FILE","target_type":"CODE_SNIPPET","relationship_type":"CONTAINS","extra":"Source file contains code snippet: 1-86","gmt_create":"2026-04-23T15:21:46.722019+08:00","gmt_modified":"2026-04-23T15:21:46.722019+08:00"},{"id":283,"source_id":"262a3941-fdc6-46b0-b767-be40aa9d5761","target_id":"cbd0101fa84d957bcb1baaa623c6b31c","source_type":"WIKI_ITEM","target_type":"CODE_SNIPPET","relationship_type":"CONTAINS","extra":"Wiki contains code snippet: backend/app/api/citations.py#1-78","gmt_create":"2026-04-23T15:21:46.722621+08:00","gmt_modified":"2026-04-23T15:21:46.722621+08:00"},{"id":284,"source_id":"7538ffe4902ab6041adb28b19844962a","target_id":"cbd0101fa84d957bcb1baaa623c6b31c","source_type":"SOURCE_FILE","target_type":"CODE_SNIPPET","relationship_type":"CONTAINS","extra":"Source file contains code snippet: 1-78","gmt_create":"2026-04-23T15:21:46.723064+08:00","gmt_modified":"2026-04-23T15:21:46.723064+08:00"},{"id":285,"source_id":"262a3941-fdc6-46b0-b767-be40aa9d5761","target_id":"afe4138895492c26aac5c0120ef46cd8","source_type":"WIKI_ITEM","target_type":"CODE_SNIPPET","relationship_type":"CONTAINS","extra":"Wiki contains code snippet: backend/app/models/__init__.py#1-14","gmt_create":"2026-04-23T15:21:46.72357+08:00","gmt_modified":"2026-04-23T15:21:46.72357+08:00"},{"id":286,"source_id":"99fe1b288fd41daa86c2dfbab819abf0","target_id":"afe4138895492c26aac5c0120ef46cd8","source_type":"SOURCE_FILE","target_type":"CODE_SNIPPET","relationship_type":"CONTAINS","extra":"Source file contains code snippet: 1-14","gmt_create":"2026-04-23T15:21:46.723873+08:00","gmt_modified":"2026-04-23T15:21:46.723873+08:00"},{"id":287,"source_id":"262a3941-fdc6-46b0-b767-be40aa9d5761","target_id":"4d11ddf7abb8076d81b30c4315786f9a","source_type":"WIKI_ITEM","target_type":"CODE_SNIPPET","relationship_type":"CONTAINS","extra":"Wiki contains code snippet: backend/alembic/versions/488d0bd5ab01_initial_migration.py#21-128","gmt_create":"2026-04-23T15:21:46.726415+08:00","gmt_modified":"2026-04-23T15:21:46.726416+08:00"},{"id":288,"source_id":"d4f95fcf50683b5bf6167c7d2a6b126d","target_id":"4d11ddf7abb8076d81b30c4315786f9a","source_type":"SOURCE_FILE","target_type":"CODE_SNIPPET","relationship_type":"CONTAINS","extra":"Source file contains code snippet: 21-128","gmt_create":"2026-04-23T15:21:46.726829+08:00","gmt_modified":"2026-04-23T15:21:46.726829+08:00"},{"id":289,"source_id":"262a3941-fdc6-46b0-b767-be40aa9d5761","target_id":"e454b4a54500bd81e7599e6ec97bf12b","source_type":"WIKI_ITEM","target_type":"CODE_SNIPPET","relationship_type":"CONTAINS","extra":"Wiki contains code snippet: backend/alembic/versions/488d0bd5ab01_initial_migration.py#23-37","gmt_create":"2026-04-23T15:21:46.735019+08:00","gmt_modified":"2026-04-23T15:21:46.735019+08:00"},{"id":290,"source_id":"d4f95fcf50683b5bf6167c7d2a6b126d","target_id":"e454b4a54500bd81e7599e6ec97bf12b","source_type":"SOURCE_FILE","target_type":"CODE_SNIPPET","relationship_type":"CONTAINS","extra":"Source file contains code snippet: 23-37","gmt_create":"2026-04-23T15:21:46.735734+08:00","gmt_modified":"2026-04-23T15:21:46.735734+08:00"},{"id":291,"source_id":"262a3941-fdc6-46b0-b767-be40aa9d5761","target_id":"1965adf7cfc65447e3c1ae21fbf6d1c5","source_type":"WIKI_ITEM","target_type":"CODE_SNIPPET","relationship_type":"CONTAINS","extra":"Wiki contains code snippet: backend/alembic/versions/488d0bd5ab01_initial_migration.py#39-59","gmt_create":"2026-04-23T15:21:46.737007+08:00","gmt_modified":"2026-04-23T15:21:46.737007+08:00"},{"id":292,"source_id":"d4f95fcf50683b5bf6167c7d2a6b126d","target_id":"1965adf7cfc65447e3c1ae21fbf6d1c5","source_type":"SOURCE_FILE","target_type":"CODE_SNIPPET","relationship_type":"CONTAINS","extra":"Source file contains code snippet: 39-59","gmt_create":"2026-04-23T15:21:46.744358+08:00","gmt_modified":"2026-04-23T15:21:46.744358+08:00"},{"id":293,"source_id":"262a3941-fdc6-46b0-b767-be40aa9d5761","target_id":"c730faefb34bb87c40c5f636b4ff7f41","source_type":"WIKI_ITEM","target_type":"CODE_SNIPPET","relationship_type":"CONTAINS","extra":"Wiki contains code snippet: backend/alembic/versions/488d0bd5ab01_initial_migration.py#80-94","gmt_create":"2026-04-23T15:21:46.747533+08:00","gmt_modified":"2026-04-23T15:21:46.747534+08:00"},{"id":294,"source_id":"d4f95fcf50683b5bf6167c7d2a6b126d","target_id":"c730faefb34bb87c40c5f636b4ff7f41","source_type":"SOURCE_FILE","target_type":"CODE_SNIPPET","relationship_type":"CONTAINS","extra":"Source file contains code snippet: 80-94","gmt_create":"2026-04-23T15:21:46.748811+08:00","gmt_modified":"2026-04-23T15:21:46.748811+08:00"},{"id":295,"source_id":"262a3941-fdc6-46b0-b767-be40aa9d5761","target_id":"b9978c3eccea3ef566b003216e5047af","source_type":"WIKI_ITEM","target_type":"CODE_SNIPPET","relationship_type":"CONTAINS","extra":"Wiki contains code snippet: backend/alembic/versions/488d0bd5ab01_initial_migration.py#61-78","gmt_create":"2026-04-23T15:21:46.751629+08:00","gmt_modified":"2026-04-23T15:21:46.751629+08:00"},{"id":296,"source_id":"d4f95fcf50683b5bf6167c7d2a6b126d","target_id":"b9978c3eccea3ef566b003216e5047af","source_type":"SOURCE_FILE","target_type":"CODE_SNIPPET","relationship_type":"CONTAINS","extra":"Source file contains code snippet: 61-78","gmt_create":"2026-04-23T15:21:46.752497+08:00","gmt_modified":"2026-04-23T15:21:46.752497+08:00"},{"id":297,"source_id":"262a3941-fdc6-46b0-b767-be40aa9d5761","target_id":"eb6ff4361d7413b57f1f70b1ec2f0c94","source_type":"WIKI_ITEM","target_type":"CODE_SNIPPET","relationship_type":"CONTAINS","extra":"Wiki contains code snippet: backend/alembic/versions/488d0bd5ab01_initial_migration.py#96-111","gmt_create":"2026-04-23T15:21:46.753732+08:00","gmt_modified":"2026-04-23T15:21:46.753732+08:00"},{"id":298,"source_id":"d4f95fcf50683b5bf6167c7d2a6b126d","target_id":"eb6ff4361d7413b57f1f70b1ec2f0c94","source_type":"SOURCE_FILE","target_type":"CODE_SNIPPET","relationship_type":"CONTAINS","extra":"Source file contains code snippet: 96-111","gmt_create":"2026-04-23T15:21:46.754523+08:00","gmt_modified":"2026-04-23T15:21:46.754523+08:00"},{"id":299,"source_id":"262a3941-fdc6-46b0-b767-be40aa9d5761","target_id":"1a2657244414b5681afded9565a86422","source_type":"WIKI_ITEM","target_type":"CODE_SNIPPET","relationship_type":"CONTAINS","extra":"Wiki contains code snippet: backend/app/models/user.py#35-40","gmt_create":"2026-04-23T15:21:46.755683+08:00","gmt_modified":"2026-04-23T15:21:46.755683+08:00"},{"id":300,"source_id":"262a3941-fdc6-46b0-b767-be40aa9d5761","target_id":"acd5a29be2bdd4ae251e10ca266ffe13","source_type":"WIKI_ITEM","target_type":"CODE_SNIPPET","relationship_type":"CONTAINS","extra":"Wiki contains code snippet: backend/app/models/query.py#43-48","gmt_create":"2026-04-23T15:21:46.756979+08:00","gmt_modified":"2026-04-23T15:21:46.756979+08:00"},{"id":301,"source_id":"262a3941-fdc6-46b0-b767-be40aa9d5761","target_id":"f6c9f1b4e8646c366a31426a4537675d","source_type":"WIKI_ITEM","target_type":"CODE_SNIPPET","relationship_type":"CONTAINS","extra":"Wiki contains code snippet: backend/app/models/query_task.py#36-38","gmt_create":"2026-04-23T15:21:46.75809+08:00","gmt_modified":"2026-04-23T15:21:46.75809+08:00"},{"id":302,"source_id":"069738f21ac2da7349d22683e8c36929","target_id":"f6c9f1b4e8646c366a31426a4537675d","source_type":"SOURCE_FILE","target_type":"CODE_SNIPPET","relationship_type":"CONTAINS","extra":"Source file contains code snippet: 36-38","gmt_create":"2026-04-23T15:21:46.759234+08:00","gmt_modified":"2026-04-23T15:21:46.759234+08:00"},{"id":303,"source_id":"262a3941-fdc6-46b0-b767-be40aa9d5761","target_id":"a2adbf02c71e4eb2cf1f120e1a2ff517","source_type":"WIKI_ITEM","target_type":"CODE_SNIPPET","relationship_type":"CONTAINS","extra":"Wiki contains code snippet: backend/app/models/citation_record.py#37-41","gmt_create":"2026-04-23T15:21:46.760054+08:00","gmt_modified":"2026-04-23T15:21:46.760054+08:00"},{"id":304,"source_id":"b4a81ef789630d0af6a8d50859d01bf3","target_id":"a2adbf02c71e4eb2cf1f120e1a2ff517","source_type":"SOURCE_FILE","target_type":"CODE_SNIPPET","relationship_type":"CONTAINS","extra":"Source file contains code snippet: 37-41","gmt_create":"2026-04-23T15:21:46.761257+08:00","gmt_modified":"2026-04-23T15:21:46.761257+08:00"},{"id":305,"source_id":"262a3941-fdc6-46b0-b767-be40aa9d5761","target_id":"69118807690ef351a9de910414d5e676","source_type":"WIKI_ITEM","target_type":"CODE_SNIPPET","relationship_type":"CONTAINS","extra":"Wiki contains code snippet: backend/app/schemas/query.py#11-94","gmt_create":"2026-04-23T15:21:46.76204+08:00","gmt_modified":"2026-04-23T15:21:46.762041+08:00"},{"id":306,"source_id":"262a3941-fdc6-46b0-b767-be40aa9d5761","target_id":"26288877e8e1f6c4ff5aca12610b0218","source_type":"WIKI_ITEM","target_type":"CODE_SNIPPET","relationship_type":"CONTAINS","extra":"Wiki contains code snippet: backend/app/schemas/citation.py#7-50","gmt_create":"2026-04-23T15:21:46.763512+08:00","gmt_modified":"2026-04-23T15:21:46.763512+08:00"},{"id":307,"source_id":"262a3941-fdc6-46b0-b767-be40aa9d5761","target_id":"0907fc2974ec31c23aaaef02076700a1","source_type":"WIKI_ITEM","target_type":"CODE_SNIPPET","relationship_type":"CONTAINS","extra":"Wiki contains code snippet: backend/app/models/user.py#25-33","gmt_create":"2026-04-23T15:21:46.764956+08:00","gmt_modified":"2026-04-23T15:21:46.764956+08:00"},{"id":308,"source_id":"c59f8c276697a070dffc581fe94d809c","target_id":"0907fc2974ec31c23aaaef02076700a1","source_type":"SOURCE_FILE","target_type":"CODE_SNIPPET","relationship_type":"CONTAINS","extra":"Source file contains code snippet: 25-33","gmt_create":"2026-04-23T15:21:46.766604+08:00","gmt_modified":"2026-04-23T15:21:46.766605+08:00"},{"id":309,"source_id":"262a3941-fdc6-46b0-b767-be40aa9d5761","target_id":"842f74e2cc054608242e93fbefd96b45","source_type":"WIKI_ITEM","target_type":"CODE_SNIPPET","relationship_type":"CONTAINS","extra":"Wiki contains code snippet: backend/app/models/query.py#32-40","gmt_create":"2026-04-23T15:21:46.767787+08:00","gmt_modified":"2026-04-23T15:21:46.767787+08:00"},{"id":310,"source_id":"b74caccb06844efcdb14d8324cff65c2","target_id":"842f74e2cc054608242e93fbefd96b45","source_type":"SOURCE_FILE","target_type":"CODE_SNIPPET","relationship_type":"CONTAINS","extra":"Source file contains code snippet: 32-40","gmt_create":"2026-04-23T15:21:46.769407+08:00","gmt_modified":"2026-04-23T15:21:46.769407+08:00"},{"id":311,"source_id":"262a3941-fdc6-46b0-b767-be40aa9d5761","target_id":"aed9e839038c45e6ce2023c4e05adb76","source_type":"WIKI_ITEM","target_type":"CODE_SNIPPET","relationship_type":"CONTAINS","extra":"Wiki contains code snippet: backend/app/models/query_task.py#27-32","gmt_create":"2026-04-23T15:21:46.770612+08:00","gmt_modified":"2026-04-23T15:21:46.770612+08:00"},{"id":312,"source_id":"069738f21ac2da7349d22683e8c36929","target_id":"aed9e839038c45e6ce2023c4e05adb76","source_type":"SOURCE_FILE","target_type":"CODE_SNIPPET","relationship_type":"CONTAINS","extra":"Source file contains code snippet: 27-32","gmt_create":"2026-04-23T15:21:46.771344+08:00","gmt_modified":"2026-04-23T15:21:46.771345+08:00"},{"id":313,"source_id":"262a3941-fdc6-46b0-b767-be40aa9d5761","target_id":"2181318c993526c86458f5eef134aed6","source_type":"WIKI_ITEM","target_type":"CODE_SNIPPET","relationship_type":"CONTAINS","extra":"Wiki contains code snippet: backend/app/services/query.py#62-77","gmt_create":"2026-04-23T15:21:46.77237+08:00","gmt_modified":"2026-04-23T15:21:46.77237+08:00"},{"id":314,"source_id":"88d22de3b2a7419868e8ae19130d860c","target_id":"2181318c993526c86458f5eef134aed6","source_type":"SOURCE_FILE","target_type":"CODE_SNIPPET","relationship_type":"CONTAINS","extra":"Source file contains code snippet: 62-77","gmt_create":"2026-04-23T15:21:46.773284+08:00","gmt_modified":"2026-04-23T15:21:46.773284+08:00"},{"id":315,"source_id":"262a3941-fdc6-46b0-b767-be40aa9d5761","target_id":"a817488dc968d761a8977fb5bb8d01a2","source_type":"WIKI_ITEM","target_type":"CODE_SNIPPET","relationship_type":"CONTAINS","extra":"Wiki contains code snippet: backend/app/services/query.py#45-129","gmt_create":"2026-04-23T15:21:46.774203+08:00","gmt_modified":"2026-04-23T15:21:46.774203+08:00"},{"id":316,"source_id":"88d22de3b2a7419868e8ae19130d860c","target_id":"a817488dc968d761a8977fb5bb8d01a2","source_type":"SOURCE_FILE","target_type":"CODE_SNIPPET","relationship_type":"CONTAINS","extra":"Source file contains code snippet: 45-129","gmt_create":"2026-04-23T15:21:46.775081+08:00","gmt_modified":"2026-04-23T15:21:46.775081+08:00"},{"id":317,"source_id":"262a3941-fdc6-46b0-b767-be40aa9d5761","target_id":"fe70b1fef9f36e73d26d84987e927c7a","source_type":"WIKI_ITEM","target_type":"CODE_SNIPPET","relationship_type":"CONTAINS","extra":"Wiki contains code snippet: backend/app/api/queries.py#15-86","gmt_create":"2026-04-23T15:21:46.775898+08:00","gmt_modified":"2026-04-23T15:21:46.775898+08:00"},{"id":318,"source_id":"262a3941-fdc6-46b0-b767-be40aa9d5761","target_id":"d20fc729a5d3986b1c077f9e07ece9c4","source_type":"WIKI_ITEM","target_type":"CODE_SNIPPET","relationship_type":"CONTAINS","extra":"Wiki contains code snippet: backend/app/config.py#7","gmt_create":"2026-04-23T15:21:46.777494+08:00","gmt_modified":"2026-04-23T15:21:46.777494+08:00"},{"id":319,"source_id":"9ff19022ef915615911280e3c49ed44b","target_id":"d20fc729a5d3986b1c077f9e07ece9c4","source_type":"SOURCE_FILE","target_type":"CODE_SNIPPET","relationship_type":"CONTAINS","extra":"Source file contains code snippet: 7","gmt_create":"2026-04-23T15:21:46.778103+08:00","gmt_modified":"2026-04-23T15:21:46.778103+08:00"},{"id":320,"source_id":"262a3941-fdc6-46b0-b767-be40aa9d5761","target_id":"ea655c6d147bc98beb42955d437260cc","source_type":"WIKI_ITEM","target_type":"CODE_SNIPPET","relationship_type":"CONTAINS","extra":"Wiki contains code snippet: backend/app/config.py#1-23","gmt_create":"2026-04-23T15:21:46.779313+08:00","gmt_modified":"2026-04-23T15:21:46.779314+08:00"},{"id":321,"source_id":"9ff19022ef915615911280e3c49ed44b","target_id":"ea655c6d147bc98beb42955d437260cc","source_type":"SOURCE_FILE","target_type":"CODE_SNIPPET","relationship_type":"CONTAINS","extra":"Source file contains code snippet: 1-23","gmt_create":"2026-04-23T15:21:46.780075+08:00","gmt_modified":"2026-04-23T15:21:46.780075+08:00"},{"id":322,"source_id":"262a3941-fdc6-46b0-b767-be40aa9d5761","target_id":"37868a5af96edcdad149caf9a184435a","source_type":"WIKI_ITEM","target_type":"CODE_SNIPPET","relationship_type":"CONTAINS","extra":"Wiki contains code snippet: backend/app/api/queries.py#42-85","gmt_create":"2026-04-23T15:21:46.781141+08:00","gmt_modified":"2026-04-23T15:21:46.781141+08:00"},{"id":323,"source_id":"6b3d903205941aa9391dd90016e1102c","target_id":"37868a5af96edcdad149caf9a184435a","source_type":"SOURCE_FILE","target_type":"CODE_SNIPPET","relationship_type":"CONTAINS","extra":"Source file contains code snippet: 42-85","gmt_create":"2026-04-23T15:21:46.781803+08:00","gmt_modified":"2026-04-23T15:21:46.781803+08:00"},{"id":324,"source_id":"262a3941-fdc6-46b0-b767-be40aa9d5761","target_id":"601b981b00d93b941843f046a163d5a3","source_type":"WIKI_ITEM","target_type":"CODE_SNIPPET","relationship_type":"CONTAINS","extra":"Wiki contains code snippet: backend/app/schemas/query.py#18-33","gmt_create":"2026-04-23T15:21:46.783498+08:00","gmt_modified":"2026-04-23T15:21:46.783498+08:00"},{"id":325,"source_id":"f301b79d833233ce39d350e82a71c938","target_id":"601b981b00d93b941843f046a163d5a3","source_type":"SOURCE_FILE","target_type":"CODE_SNIPPET","relationship_type":"CONTAINS","extra":"Source file contains code snippet: 18-33","gmt_create":"2026-04-23T15:21:46.784342+08:00","gmt_modified":"2026-04-23T15:21:46.784343+08:00"},{"id":344,"source_id":"0ef1efea889dba3e1f299626df479571","target_id":"290df8332b3d104e5ea8d71dc39315b5","source_type":"SOURCE_FILE","target_type":"CODE_SNIPPET","relationship_type":"CONTAINS","extra":"Source file contains code snippet: 1-123","gmt_create":"2026-04-23T15:22:16.017503+08:00","gmt_modified":"2026-04-23T15:22:16.017503+08:00"},{"id":346,"source_id":"9228ff67d4c757a85d9421b71f4b29f5","target_id":"c2747ca16b879bca0f68955534c3c4fc","source_type":"SOURCE_FILE","target_type":"CODE_SNIPPET","relationship_type":"CONTAINS","extra":"Source file contains code snippet: 1-48","gmt_create":"2026-04-23T15:22:16.019099+08:00","gmt_modified":"2026-04-23T15:22:16.019099+08:00"},{"id":348,"source_id":"9d08667997a868fc07c9b4e328e44224","target_id":"76e6c0abb49fec57cac4892837a143c9","source_type":"SOURCE_FILE","target_type":"CODE_SNIPPET","relationship_type":"CONTAINS","extra":"Source file contains code snippet: 1-43","gmt_create":"2026-04-23T15:22:16.020577+08:00","gmt_modified":"2026-04-23T15:22:16.020577+08:00"},{"id":350,"source_id":"93022c8938ce318f167277cfa65c29a7","target_id":"f66d9907b467b110c638bd527efd95c5","source_type":"SOURCE_FILE","target_type":"CODE_SNIPPET","relationship_type":"CONTAINS","extra":"Source file contains code snippet: 1-43","gmt_create":"2026-04-23T15:22:16.021841+08:00","gmt_modified":"2026-04-23T15:22:16.021841+08:00"},{"id":354,"source_id":"74040de652d5e57f548bb5c4adc3e1a0","target_id":"116584ea9162c1bc05911f39f9ef82b6","source_type":"SOURCE_FILE","target_type":"CODE_SNIPPET","relationship_type":"CONTAINS","extra":"Source file contains code snippet: 1-309","gmt_create":"2026-04-23T15:22:16.023827+08:00","gmt_modified":"2026-04-23T15:22:16.023827+08:00"},{"id":356,"source_id":"5cbb1e3f112aeba62a14b0b8999fc0f5","target_id":"9630036e63fc15cb81b202cf79671aab","source_type":"SOURCE_FILE","target_type":"CODE_SNIPPET","relationship_type":"CONTAINS","extra":"Source file contains code snippet: 1-182","gmt_create":"2026-04-23T15:22:16.024606+08:00","gmt_modified":"2026-04-23T15:22:16.024606+08:00"},{"id":359,"source_id":"9ff19022ef915615911280e3c49ed44b","target_id":"84fbed7d35f7752e2117a74fcaf5f0e9","source_type":"SOURCE_FILE","target_type":"CODE_SNIPPET","relationship_type":"CONTAINS","extra":"Source file contains code snippet: 1-17","gmt_create":"2026-04-23T15:22:16.026089+08:00","gmt_modified":"2026-04-23T15:22:16.02609+08:00"},{"id":361,"source_id":"0ef1efea889dba3e1f299626df479571","target_id":"5ddf0c8d7b38e4f6126a5d85da1dfeda","source_type":"SOURCE_FILE","target_type":"CODE_SNIPPET","relationship_type":"CONTAINS","extra":"Source file contains code snippet: 19-123","gmt_create":"2026-04-23T15:22:16.02774+08:00","gmt_modified":"2026-04-23T15:22:16.02774+08:00"},{"id":363,"source_id":"0ef1efea889dba3e1f299626df479571","target_id":"9df233ef1be4b95068ed91bf01083ae7","source_type":"SOURCE_FILE","target_type":"CODE_SNIPPET","relationship_type":"CONTAINS","extra":"Source file contains code snippet: 117-123","gmt_create":"2026-04-23T15:22:16.028504+08:00","gmt_modified":"2026-04-23T15:22:16.028504+08:00"},{"id":365,"source_id":"9228ff67d4c757a85d9421b71f4b29f5","target_id":"6286d4be455dc058c8be2ee4e0d1175a","source_type":"SOURCE_FILE","target_type":"CODE_SNIPPET","relationship_type":"CONTAINS","extra":"Source file contains code snippet: 38-42","gmt_create":"2026-04-23T15:22:16.029449+08:00","gmt_modified":"2026-04-23T15:22:16.029449+08:00"},{"id":367,"source_id":"9d08667997a868fc07c9b4e328e44224","target_id":"069243fafe60a85cf16a0ca40fa07180","source_type":"SOURCE_FILE","target_type":"CODE_SNIPPET","relationship_type":"CONTAINS","extra":"Source file contains code snippet: 16-43","gmt_create":"2026-04-23T15:22:16.030648+08:00","gmt_modified":"2026-04-23T15:22:16.030648+08:00"},{"id":369,"source_id":"93022c8938ce318f167277cfa65c29a7","target_id":"d5a1fb0bd23ce9240fbf79529ef94a45","source_type":"SOURCE_FILE","target_type":"CODE_SNIPPET","relationship_type":"CONTAINS","extra":"Source file contains code snippet: 13-43","gmt_create":"2026-04-23T15:22:16.03168+08:00","gmt_modified":"2026-04-23T15:22:16.03168+08:00"},{"id":372,"source_id":"7538ffe4902ab6041adb28b19844962a","target_id":"735aef72b4fe6ca4f407e69b7dda8b43","source_type":"SOURCE_FILE","target_type":"CODE_SNIPPET","relationship_type":"CONTAINS","extra":"Source file contains code snippet: 25-78","gmt_create":"2026-04-23T15:22:16.03298+08:00","gmt_modified":"2026-04-23T15:22:16.03298+08:00"},{"id":374,"source_id":"b0c428683c8a3e6922d90ca0d8c2736d","target_id":"8128dd67cf376d2cadf7c2d3831c380a","source_type":"SOURCE_FILE","target_type":"CODE_SNIPPET","relationship_type":"CONTAINS","extra":"Source file contains code snippet: 23-29","gmt_create":"2026-04-23T15:22:16.035564+08:00","gmt_modified":"2026-04-23T15:22:16.035564+08:00"},{"id":376,"source_id":"389d631bc6c7111ba411b0b79fca455e","target_id":"1721defc3d6206478d3c0692cc821761","source_type":"SOURCE_FILE","target_type":"CODE_SNIPPET","relationship_type":"CONTAINS","extra":"Source file contains code snippet: 25-104","gmt_create":"2026-04-23T15:22:16.036753+08:00","gmt_modified":"2026-04-23T15:22:16.036753+08:00"},{"id":378,"source_id":"4d2f3847b7c10634733118b70a1aea0b","target_id":"753a437d837246ead62b0e16c6331284","source_type":"SOURCE_FILE","target_type":"CODE_SNIPPET","relationship_type":"CONTAINS","extra":"Source file contains code snippet: 37-69","gmt_create":"2026-04-23T15:22:16.038261+08:00","gmt_modified":"2026-04-23T15:22:16.038261+08:00"},{"id":380,"source_id":"389d631bc6c7111ba411b0b79fca455e","target_id":"d820e2daf2ea133a7aa17cdc475e44a4","source_type":"SOURCE_FILE","target_type":"CODE_SNIPPET","relationship_type":"CONTAINS","extra":"Source file contains code snippet: 1-104","gmt_create":"2026-04-23T15:22:16.039369+08:00","gmt_modified":"2026-04-23T15:22:16.039369+08:00"},{"id":382,"source_id":"4d2f3847b7c10634733118b70a1aea0b","target_id":"1a439c5fed6cfd188c646e1614d56371","source_type":"SOURCE_FILE","target_type":"CODE_SNIPPET","relationship_type":"CONTAINS","extra":"Source file contains code snippet: 1-69","gmt_create":"2026-04-23T15:22:16.040483+08:00","gmt_modified":"2026-04-23T15:22:16.040483+08:00"},{"id":385,"source_id":"74040de652d5e57f548bb5c4adc3e1a0","target_id":"5c67e2f70283956b2d29a3c1443eb514","source_type":"SOURCE_FILE","target_type":"CODE_SNIPPET","relationship_type":"CONTAINS","extra":"Source file contains code snippet: 122-146","gmt_create":"2026-04-23T15:22:16.042829+08:00","gmt_modified":"2026-04-23T15:22:16.042829+08:00"},{"id":388,"source_id":"b07a4fb9cecbbd66a6910ccbc7651f19","target_id":"a57acd9da5287c915ac823784a409292","source_type":"SOURCE_FILE","target_type":"CODE_SNIPPET","relationship_type":"CONTAINS","extra":"Source file contains code snippet: 1-127","gmt_create":"2026-04-23T15:22:16.045132+08:00","gmt_modified":"2026-04-23T15:22:16.045132+08:00"},{"id":390,"source_id":"42ff5383133d176cec9eb88682483be3","target_id":"2a4f741f31f62dce8ad63be2e831f520","source_type":"SOURCE_FILE","target_type":"CODE_SNIPPET","relationship_type":"CONTAINS","extra":"Source file contains code snippet: 23-93","gmt_create":"2026-04-23T15:22:16.046367+08:00","gmt_modified":"2026-04-23T15:22:16.046367+08:00"},{"id":392,"source_id":"42ff5383133d176cec9eb88682483be3","target_id":"692ac240965eff7e66945aa3c4c270f7","source_type":"SOURCE_FILE","target_type":"CODE_SNIPPET","relationship_type":"CONTAINS","extra":"Source file contains code snippet: 1-93","gmt_create":"2026-04-23T15:22:16.047995+08:00","gmt_modified":"2026-04-23T15:22:16.047995+08:00"},{"id":394,"source_id":"0613e76b9679be7f998fb8fd8056e686","target_id":"32a0a52faca2d8d488e49c63c86075b1","source_type":"SOURCE_FILE","target_type":"CODE_SNIPPET","relationship_type":"CONTAINS","extra":"Source file contains code snippet: 29-154","gmt_create":"2026-04-23T15:22:16.049251+08:00","gmt_modified":"2026-04-23T15:22:16.049251+08:00"},{"id":396,"source_id":"0613e76b9679be7f998fb8fd8056e686","target_id":"7804331f5f8c1ba5a3b6d9c1ae1c78c1","source_type":"SOURCE_FILE","target_type":"CODE_SNIPPET","relationship_type":"CONTAINS","extra":"Source file contains code snippet: 1-154","gmt_create":"2026-04-23T15:22:16.051952+08:00","gmt_modified":"2026-04-23T15:22:16.051952+08:00"},{"id":398,"source_id":"80a0429cc47931de27ddb17a62b8dd9c","target_id":"3a6e1b738967bf8cc651e57f48e2e126","source_type":"SOURCE_FILE","target_type":"CODE_SNIPPET","relationship_type":"CONTAINS","extra":"Source file contains code snippet: 83-126","gmt_create":"2026-04-23T15:22:16.053692+08:00","gmt_modified":"2026-04-23T15:22:16.053693+08:00"},{"id":400,"source_id":"80a0429cc47931de27ddb17a62b8dd9c","target_id":"b1afd377757f1d0e9bdf87edfff3ad88","source_type":"SOURCE_FILE","target_type":"CODE_SNIPPET","relationship_type":"CONTAINS","extra":"Source file contains code snippet: 131-186","gmt_create":"2026-04-23T15:22:16.054533+08:00","gmt_modified":"2026-04-23T15:22:16.054533+08:00"},{"id":402,"source_id":"80a0429cc47931de27ddb17a62b8dd9c","target_id":"de05ec7eed033e432991e5a88e1b5a06","source_type":"SOURCE_FILE","target_type":"CODE_SNIPPET","relationship_type":"CONTAINS","extra":"Source file contains code snippet: 192-222","gmt_create":"2026-04-23T15:22:16.055495+08:00","gmt_modified":"2026-04-23T15:22:16.055495+08:00"},{"id":404,"source_id":"80a0429cc47931de27ddb17a62b8dd9c","target_id":"7fd61a451248b6b129299d6246f711c7","source_type":"SOURCE_FILE","target_type":"CODE_SNIPPET","relationship_type":"CONTAINS","extra":"Source file contains code snippet: 228-296","gmt_create":"2026-04-23T15:22:16.056294+08:00","gmt_modified":"2026-04-23T15:22:16.056294+08:00"},{"id":406,"source_id":"80a0429cc47931de27ddb17a62b8dd9c","target_id":"53eedffff456a566fa7b0cecc7169f56","source_type":"SOURCE_FILE","target_type":"CODE_SNIPPET","relationship_type":"CONTAINS","extra":"Source file contains code snippet: 1-441","gmt_create":"2026-04-23T15:22:16.05703+08:00","gmt_modified":"2026-04-23T15:22:16.05703+08:00"},{"id":408,"source_id":"5cbb1e3f112aeba62a14b0b8999fc0f5","target_id":"906f7a8288e38d4244211f3f538fe7b6","source_type":"SOURCE_FILE","target_type":"CODE_SNIPPET","relationship_type":"CONTAINS","extra":"Source file contains code snippet: 27-182","gmt_create":"2026-04-23T15:22:16.062545+08:00","gmt_modified":"2026-04-23T15:22:16.062545+08:00"},{"id":410,"source_id":"b2f0d46a31a5441594f2e777365fc156","target_id":"1647ee2066de2ae59ba8cf88e33c5e02","source_type":"SOURCE_FILE","target_type":"CODE_SNIPPET","relationship_type":"CONTAINS","extra":"Source file contains code snippet: 1-123","gmt_create":"2026-04-23T15:22:16.064587+08:00","gmt_modified":"2026-04-23T15:22:16.064587+08:00"},{"id":411,"source_id":"760610d4-dff6-4c6d-831f-7c9078db86a6","target_id":"aaf5bce6be82d2f947bfa5c1806de452","source_type":"WIKI_ITEM","target_type":"SOURCE_FILE","relationship_type":"REFERENCED_BY","extra":"Wiki references source file: frontend/package.json","gmt_create":"2026-04-23T15:22:23.52554+08:00","gmt_modified":"2026-04-23T15:22:23.52554+08:00"},{"id":412,"source_id":"760610d4-dff6-4c6d-831f-7c9078db86a6","target_id":"01056dad8851d3e9bd532eb4cab33792","source_type":"WIKI_ITEM","target_type":"SOURCE_FILE","relationship_type":"REFERENCED_BY","extra":"Wiki references source file: frontend/tailwind.config.ts","gmt_create":"2026-04-23T15:22:23.52643+08:00","gmt_modified":"2026-04-23T15:22:23.526431+08:00"},{"id":413,"source_id":"760610d4-dff6-4c6d-831f-7c9078db86a6","target_id":"f93ae024fe0a2e69698037dff6df205f","source_type":"WIKI_ITEM","target_type":"SOURCE_FILE","relationship_type":"REFERENCED_BY","extra":"Wiki references source file: frontend/lib/utils.ts","gmt_create":"2026-04-23T15:22:23.527272+08:00","gmt_modified":"2026-04-23T15:22:23.527272+08:00"},{"id":414,"source_id":"760610d4-dff6-4c6d-831f-7c9078db86a6","target_id":"ac1acbc54c49ee1de13369f6c6827568","source_type":"WIKI_ITEM","target_type":"SOURCE_FILE","relationship_type":"REFERENCED_BY","extra":"Wiki references source file: frontend/components/ui/button.tsx","gmt_create":"2026-04-23T15:22:23.528155+08:00","gmt_modified":"2026-04-23T15:22:23.528155+08:00"},{"id":415,"source_id":"760610d4-dff6-4c6d-831f-7c9078db86a6","target_id":"108b0c4b4dcfb6aa39a5eb138225c148","source_type":"WIKI_ITEM","target_type":"SOURCE_FILE","relationship_type":"REFERENCED_BY","extra":"Wiki references source file: frontend/components/ui/dialog.tsx","gmt_create":"2026-04-23T15:22:23.529196+08:00","gmt_modified":"2026-04-23T15:22:23.529196+08:00"},{"id":416,"source_id":"760610d4-dff6-4c6d-831f-7c9078db86a6","target_id":"0186dc8a89340139a84e1e3c5571a57f","source_type":"WIKI_ITEM","target_type":"SOURCE_FILE","relationship_type":"REFERENCED_BY","extra":"Wiki references source file: frontend/components/ui/dropdown-menu.tsx","gmt_create":"2026-04-23T15:22:23.530077+08:00","gmt_modified":"2026-04-23T15:22:23.530077+08:00"},{"id":417,"source_id":"760610d4-dff6-4c6d-831f-7c9078db86a6","target_id":"3cf787fa77a15b2b1783560c6d83ed21","source_type":"WIKI_ITEM","target_type":"SOURCE_FILE","relationship_type":"REFERENCED_BY","extra":"Wiki references source file: frontend/components/ui/input.tsx","gmt_create":"2026-04-23T15:22:23.530977+08:00","gmt_modified":"2026-04-23T15:22:23.530977+08:00"},{"id":418,"source_id":"760610d4-dff6-4c6d-831f-7c9078db86a6","target_id":"3c56e1c079959bfcc985183805e5874f","source_type":"WIKI_ITEM","target_type":"SOURCE_FILE","relationship_type":"REFERENCED_BY","extra":"Wiki references source file: frontend/components/ui/select.tsx","gmt_create":"2026-04-23T15:22:23.531664+08:00","gmt_modified":"2026-04-23T15:22:23.531664+08:00"},{"id":419,"source_id":"760610d4-dff6-4c6d-831f-7c9078db86a6","target_id":"0d5ef537f7c0b8c390f8b31d7cf47b56","source_type":"WIKI_ITEM","target_type":"SOURCE_FILE","relationship_type":"REFERENCED_BY","extra":"Wiki references source file: frontend/components/ui/card.tsx","gmt_create":"2026-04-23T15:22:23.532588+08:00","gmt_modified":"2026-04-23T15:22:23.532588+08:00"},{"id":420,"source_id":"760610d4-dff6-4c6d-831f-7c9078db86a6","target_id":"51821ca9ec2a1c972f3c9d111e19db8a","source_type":"WIKI_ITEM","target_type":"SOURCE_FILE","relationship_type":"REFERENCED_BY","extra":"Wiki references source file: frontend/components/ui/badge.tsx","gmt_create":"2026-04-23T15:22:23.53409+08:00","gmt_modified":"2026-04-23T15:22:23.53409+08:00"},{"id":421,"source_id":"760610d4-dff6-4c6d-831f-7c9078db86a6","target_id":"0c0b0f4e2cf44facd9d5b57de0d0bf0c","source_type":"WIKI_ITEM","target_type":"SOURCE_FILE","relationship_type":"REFERENCED_BY","extra":"Wiki references source file: frontend/components/ui/table.tsx","gmt_create":"2026-04-23T15:22:23.535512+08:00","gmt_modified":"2026-04-23T15:22:23.535512+08:00"},{"id":422,"source_id":"760610d4-dff6-4c6d-831f-7c9078db86a6","target_id":"beb87ab5aad9532647e9dbd2db7ef587","source_type":"WIKI_ITEM","target_type":"SOURCE_FILE","relationship_type":"REFERENCED_BY","extra":"Wiki references source file: frontend/components/ui/tabs.tsx","gmt_create":"2026-04-23T15:22:23.536664+08:00","gmt_modified":"2026-04-23T15:22:23.536665+08:00"},{"id":423,"source_id":"760610d4-dff6-4c6d-831f-7c9078db86a6","target_id":"792b8e2c16c9ff2095d83b8972313be4","source_type":"WIKI_ITEM","target_type":"SOURCE_FILE","relationship_type":"REFERENCED_BY","extra":"Wiki references source file: frontend/components/ui/label.tsx","gmt_create":"2026-04-23T15:22:23.537365+08:00","gmt_modified":"2026-04-23T15:22:23.537365+08:00"},{"id":424,"source_id":"760610d4-dff6-4c6d-831f-7c9078db86a6","target_id":"546e01c5f73aaf5140eee922f4b9a441","source_type":"WIKI_ITEM","target_type":"SOURCE_FILE","relationship_type":"REFERENCED_BY","extra":"Wiki references source file: frontend/components/providers.tsx","gmt_create":"2026-04-23T15:22:23.538246+08:00","gmt_modified":"2026-04-23T15:22:23.538246+08:00"},{"id":425,"source_id":"760610d4-dff6-4c6d-831f-7c9078db86a6","target_id":"12e2c3d7b9a92dc44a6ee29b85e10df6","source_type":"WIKI_ITEM","target_type":"SOURCE_FILE","relationship_type":"REFERENCED_BY","extra":"Wiki references source file: frontend/app/layout.tsx","gmt_create":"2026-04-23T15:22:23.53929+08:00","gmt_modified":"2026-04-23T15:22:23.53929+08:00"},{"id":426,"source_id":"760610d4-dff6-4c6d-831f-7c9078db86a6","target_id":"2a1c745c7b3fb7f600596be3d979bba1","source_type":"WIKI_ITEM","target_type":"SOURCE_FILE","relationship_type":"REFERENCED_BY","extra":"Wiki references source file: frontend/app/(dashboard","gmt_create":"2026-04-23T15:22:23.540469+08:00","gmt_modified":"2026-04-23T15:22:23.540469+08:00"},{"id":427,"source_id":"760610d4-dff6-4c6d-831f-7c9078db86a6","target_id":"8a466b0c6eac2ccb54c5da7e13854646","source_type":"WIKI_ITEM","target_type":"CODE_SNIPPET","relationship_type":"CONTAINS","extra":"Wiki contains code snippet: frontend/app/layout.tsx#1-37","gmt_create":"2026-04-23T15:22:23.541484+08:00","gmt_modified":"2026-04-23T15:22:23.541484+08:00"},{"id":428,"source_id":"760610d4-dff6-4c6d-831f-7c9078db86a6","target_id":"fd18328b6582e68c30b130b912891992","source_type":"WIKI_ITEM","target_type":"CODE_SNIPPET","relationship_type":"CONTAINS","extra":"Wiki contains code snippet: frontend/components/providers.tsx#1-9","gmt_create":"2026-04-23T15:22:23.542098+08:00","gmt_modified":"2026-04-23T15:22:23.542098+08:00"},{"id":429,"source_id":"546e01c5f73aaf5140eee922f4b9a441","target_id":"fd18328b6582e68c30b130b912891992","source_type":"SOURCE_FILE","target_type":"CODE_SNIPPET","relationship_type":"CONTAINS","extra":"Source file contains code snippet: 1-9","gmt_create":"2026-04-23T15:22:23.542482+08:00","gmt_modified":"2026-04-23T15:22:23.542482+08:00"},{"id":430,"source_id":"760610d4-dff6-4c6d-831f-7c9078db86a6","target_id":"dcfa308ef4ec368c5a51a17acbfc8e2c","source_type":"WIKI_ITEM","target_type":"CODE_SNIPPET","relationship_type":"CONTAINS","extra":"Wiki contains code snippet: frontend/lib/utils.ts#1-7","gmt_create":"2026-04-23T15:22:23.542958+08:00","gmt_modified":"2026-04-23T15:22:23.542958+08:00"},{"id":431,"source_id":"760610d4-dff6-4c6d-831f-7c9078db86a6","target_id":"71a37a516437e94fd82a87efc70a3f16","source_type":"WIKI_ITEM","target_type":"CODE_SNIPPET","relationship_type":"CONTAINS","extra":"Wiki contains code snippet: frontend/package.json#1-40","gmt_create":"2026-04-23T15:22:23.54348+08:00","gmt_modified":"2026-04-23T15:22:23.54348+08:00"},{"id":432,"source_id":"aaf5bce6be82d2f947bfa5c1806de452","target_id":"71a37a516437e94fd82a87efc70a3f16","source_type":"SOURCE_FILE","target_type":"CODE_SNIPPET","relationship_type":"CONTAINS","extra":"Source file contains code snippet: 1-40","gmt_create":"2026-04-23T15:22:23.543767+08:00","gmt_modified":"2026-04-23T15:22:23.543768+08:00"},{"id":433,"source_id":"760610d4-dff6-4c6d-831f-7c9078db86a6","target_id":"89d70e5f89be23a229e3ee59982b8e6e","source_type":"WIKI_ITEM","target_type":"CODE_SNIPPET","relationship_type":"CONTAINS","extra":"Wiki contains code snippet: frontend/tailwind.config.ts#1-57","gmt_create":"2026-04-23T15:22:23.544176+08:00","gmt_modified":"2026-04-23T15:22:23.544176+08:00"},{"id":434,"source_id":"01056dad8851d3e9bd532eb4cab33792","target_id":"89d70e5f89be23a229e3ee59982b8e6e","source_type":"SOURCE_FILE","target_type":"CODE_SNIPPET","relationship_type":"CONTAINS","extra":"Source file contains code snippet: 1-57","gmt_create":"2026-04-23T15:22:23.544513+08:00","gmt_modified":"2026-04-23T15:22:23.544513+08:00"},{"id":435,"source_id":"760610d4-dff6-4c6d-831f-7c9078db86a6","target_id":"95be577a89fbeb02578e4c3718c6ec86","source_type":"WIKI_ITEM","target_type":"CODE_SNIPPET","relationship_type":"CONTAINS","extra":"Wiki contains code snippet: frontend/components/ui/button.tsx#1-57","gmt_create":"2026-04-23T15:22:23.545023+08:00","gmt_modified":"2026-04-23T15:22:23.545023+08:00"},{"id":436,"source_id":"ac1acbc54c49ee1de13369f6c6827568","target_id":"95be577a89fbeb02578e4c3718c6ec86","source_type":"SOURCE_FILE","target_type":"CODE_SNIPPET","relationship_type":"CONTAINS","extra":"Source file contains code snippet: 1-57","gmt_create":"2026-04-23T15:22:23.545376+08:00","gmt_modified":"2026-04-23T15:22:23.545376+08:00"},{"id":437,"source_id":"760610d4-dff6-4c6d-831f-7c9078db86a6","target_id":"607bb628918a7a5d54cbf74763f94d07","source_type":"WIKI_ITEM","target_type":"CODE_SNIPPET","relationship_type":"CONTAINS","extra":"Wiki contains code snippet: frontend/components/ui/input.tsx#1-23","gmt_create":"2026-04-23T15:22:23.545898+08:00","gmt_modified":"2026-04-23T15:22:23.545899+08:00"},{"id":438,"source_id":"3cf787fa77a15b2b1783560c6d83ed21","target_id":"607bb628918a7a5d54cbf74763f94d07","source_type":"SOURCE_FILE","target_type":"CODE_SNIPPET","relationship_type":"CONTAINS","extra":"Source file contains code snippet: 1-23","gmt_create":"2026-04-23T15:22:23.546272+08:00","gmt_modified":"2026-04-23T15:22:23.546272+08:00"},{"id":439,"source_id":"760610d4-dff6-4c6d-831f-7c9078db86a6","target_id":"325e25d1dda0f7bfd9d7adfe35ecf3b5","source_type":"WIKI_ITEM","target_type":"CODE_SNIPPET","relationship_type":"CONTAINS","extra":"Wiki contains code snippet: frontend/components/ui/select.tsx#1-161","gmt_create":"2026-04-23T15:22:23.546653+08:00","gmt_modified":"2026-04-23T15:22:23.546653+08:00"},{"id":440,"source_id":"3c56e1c079959bfcc985183805e5874f","target_id":"325e25d1dda0f7bfd9d7adfe35ecf3b5","source_type":"SOURCE_FILE","target_type":"CODE_SNIPPET","relationship_type":"CONTAINS","extra":"Source file contains code snippet: 1-161","gmt_create":"2026-04-23T15:22:23.546906+08:00","gmt_modified":"2026-04-23T15:22:23.546907+08:00"},{"id":441,"source_id":"760610d4-dff6-4c6d-831f-7c9078db86a6","target_id":"0eed9f61572209dd754611fc7c690d5a","source_type":"WIKI_ITEM","target_type":"CODE_SNIPPET","relationship_type":"CONTAINS","extra":"Wiki contains code snippet: frontend/components/ui/dialog.tsx#1-123","gmt_create":"2026-04-23T15:22:23.547243+08:00","gmt_modified":"2026-04-23T15:22:23.547244+08:00"},{"id":442,"source_id":"760610d4-dff6-4c6d-831f-7c9078db86a6","target_id":"ad6ff021b2126ad5c42323305eb6d8b0","source_type":"WIKI_ITEM","target_type":"CODE_SNIPPET","relationship_type":"CONTAINS","extra":"Wiki contains code snippet: frontend/components/ui/dropdown-menu.tsx#1-201","gmt_create":"2026-04-23T15:22:23.547645+08:00","gmt_modified":"2026-04-23T15:22:23.547645+08:00"},{"id":443,"source_id":"0186dc8a89340139a84e1e3c5571a57f","target_id":"ad6ff021b2126ad5c42323305eb6d8b0","source_type":"SOURCE_FILE","target_type":"CODE_SNIPPET","relationship_type":"CONTAINS","extra":"Source file contains code snippet: 1-201","gmt_create":"2026-04-23T15:22:23.547892+08:00","gmt_modified":"2026-04-23T15:22:23.547892+08:00"},{"id":444,"source_id":"760610d4-dff6-4c6d-831f-7c9078db86a6","target_id":"a85f004dca63614b4e734ba63b45ef9e","source_type":"WIKI_ITEM","target_type":"CODE_SNIPPET","relationship_type":"CONTAINS","extra":"Wiki contains code snippet: frontend/components/ui/card.tsx#1-80","gmt_create":"2026-04-23T15:22:23.548296+08:00","gmt_modified":"2026-04-23T15:22:23.548296+08:00"},{"id":445,"source_id":"0d5ef537f7c0b8c390f8b31d7cf47b56","target_id":"a85f004dca63614b4e734ba63b45ef9e","source_type":"SOURCE_FILE","target_type":"CODE_SNIPPET","relationship_type":"CONTAINS","extra":"Source file contains code snippet: 1-80","gmt_create":"2026-04-23T15:22:23.548561+08:00","gmt_modified":"2026-04-23T15:22:23.548561+08:00"},{"id":446,"source_id":"760610d4-dff6-4c6d-831f-7c9078db86a6","target_id":"3bab92a09e9fb456e0303bb1e04afc7e","source_type":"WIKI_ITEM","target_type":"CODE_SNIPPET","relationship_type":"CONTAINS","extra":"Wiki contains code snippet: frontend/components/ui/table.tsx#1-118","gmt_create":"2026-04-23T15:22:23.548946+08:00","gmt_modified":"2026-04-23T15:22:23.548946+08:00"},{"id":447,"source_id":"760610d4-dff6-4c6d-831f-7c9078db86a6","target_id":"bd3042a8d9b602334720b0d7b4e8ab3d","source_type":"WIKI_ITEM","target_type":"CODE_SNIPPET","relationship_type":"CONTAINS","extra":"Wiki contains code snippet: frontend/components/ui/tabs.tsx#1-56","gmt_create":"2026-04-23T15:22:23.549383+08:00","gmt_modified":"2026-04-23T15:22:23.549383+08:00"},{"id":448,"source_id":"beb87ab5aad9532647e9dbd2db7ef587","target_id":"bd3042a8d9b602334720b0d7b4e8ab3d","source_type":"SOURCE_FILE","target_type":"CODE_SNIPPET","relationship_type":"CONTAINS","extra":"Source file contains code snippet: 1-56","gmt_create":"2026-04-23T15:22:23.549652+08:00","gmt_modified":"2026-04-23T15:22:23.549653+08:00"},{"id":449,"source_id":"760610d4-dff6-4c6d-831f-7c9078db86a6","target_id":"379443f450513b5492e2d9d5fca94a42","source_type":"WIKI_ITEM","target_type":"CODE_SNIPPET","relationship_type":"CONTAINS","extra":"Wiki contains code snippet: frontend/components/ui/label.tsx#1-27","gmt_create":"2026-04-23T15:22:23.550013+08:00","gmt_modified":"2026-04-23T15:22:23.550014+08:00"},{"id":450,"source_id":"792b8e2c16c9ff2095d83b8972313be4","target_id":"379443f450513b5492e2d9d5fca94a42","source_type":"SOURCE_FILE","target_type":"CODE_SNIPPET","relationship_type":"CONTAINS","extra":"Source file contains code snippet: 1-27","gmt_create":"2026-04-23T15:22:23.550267+08:00","gmt_modified":"2026-04-23T15:22:23.550267+08:00"},{"id":451,"source_id":"760610d4-dff6-4c6d-831f-7c9078db86a6","target_id":"4aa6ad434a73143bb7a2072124f63be0","source_type":"WIKI_ITEM","target_type":"CODE_SNIPPET","relationship_type":"CONTAINS","extra":"Wiki contains code snippet: frontend/components/ui/badge.tsx#1-37","gmt_create":"2026-04-23T15:22:23.551155+08:00","gmt_modified":"2026-04-23T15:22:23.551155+08:00"},{"id":452,"source_id":"51821ca9ec2a1c972f3c9d111e19db8a","target_id":"4aa6ad434a73143bb7a2072124f63be0","source_type":"SOURCE_FILE","target_type":"CODE_SNIPPET","relationship_type":"CONTAINS","extra":"Source file contains code snippet: 1-37","gmt_create":"2026-04-23T15:22:23.551858+08:00","gmt_modified":"2026-04-23T15:22:23.551858+08:00"},{"id":453,"source_id":"760610d4-dff6-4c6d-831f-7c9078db86a6","target_id":"c45dbdda70a8b9f02b52af4991644d0b","source_type":"WIKI_ITEM","target_type":"CODE_SNIPPET","relationship_type":"CONTAINS","extra":"Wiki contains code snippet: frontend/package.json#11-27","gmt_create":"2026-04-23T15:22:23.552353+08:00","gmt_modified":"2026-04-23T15:22:23.552353+08:00"},{"id":454,"source_id":"aaf5bce6be82d2f947bfa5c1806de452","target_id":"c45dbdda70a8b9f02b52af4991644d0b","source_type":"SOURCE_FILE","target_type":"CODE_SNIPPET","relationship_type":"CONTAINS","extra":"Source file contains code snippet: 11-27","gmt_create":"2026-04-23T15:22:23.552845+08:00","gmt_modified":"2026-04-23T15:22:23.552845+08:00"},{"id":455,"source_id":"760610d4-dff6-4c6d-831f-7c9078db86a6","target_id":"6ac6943c93570294e4fb15a862be2616","source_type":"WIKI_ITEM","target_type":"CODE_SNIPPET","relationship_type":"CONTAINS","extra":"Wiki contains code snippet: frontend/components/ui/button.tsx#36-54","gmt_create":"2026-04-23T15:22:23.553797+08:00","gmt_modified":"2026-04-23T15:22:23.553797+08:00"},{"id":456,"source_id":"ac1acbc54c49ee1de13369f6c6827568","target_id":"6ac6943c93570294e4fb15a862be2616","source_type":"SOURCE_FILE","target_type":"CODE_SNIPPET","relationship_type":"CONTAINS","extra":"Source file contains code snippet: 36-54","gmt_create":"2026-04-23T15:22:23.554077+08:00","gmt_modified":"2026-04-23T15:22:23.554077+08:00"},{"id":457,"source_id":"760610d4-dff6-4c6d-831f-7c9078db86a6","target_id":"4bfb5059c685e9878aed64cb5347ccec","source_type":"WIKI_ITEM","target_type":"CODE_SNIPPET","relationship_type":"CONTAINS","extra":"Wiki contains code snippet: frontend/components/ui/dialog.tsx#9-54","gmt_create":"2026-04-23T15:22:23.554645+08:00","gmt_modified":"2026-04-23T15:22:23.554645+08:00"},{"id":458,"source_id":"108b0c4b4dcfb6aa39a5eb138225c148","target_id":"4bfb5059c685e9878aed64cb5347ccec","source_type":"SOURCE_FILE","target_type":"CODE_SNIPPET","relationship_type":"CONTAINS","extra":"Source file contains code snippet: 9-54","gmt_create":"2026-04-23T15:22:23.554875+08:00","gmt_modified":"2026-04-23T15:22:23.554875+08:00"},{"id":459,"source_id":"760610d4-dff6-4c6d-831f-7c9078db86a6","target_id":"0af48b69fe8fb9e480fa1656f36a4330","source_type":"WIKI_ITEM","target_type":"CODE_SNIPPET","relationship_type":"CONTAINS","extra":"Wiki contains code snippet: frontend/components/ui/dropdown-menu.tsx#21-75","gmt_create":"2026-04-23T15:22:23.555418+08:00","gmt_modified":"2026-04-23T15:22:23.555418+08:00"},{"id":460,"source_id":"0186dc8a89340139a84e1e3c5571a57f","target_id":"0af48b69fe8fb9e480fa1656f36a4330","source_type":"SOURCE_FILE","target_type":"CODE_SNIPPET","relationship_type":"CONTAINS","extra":"Source file contains code snippet: 21-75","gmt_create":"2026-04-23T15:22:23.55574+08:00","gmt_modified":"2026-04-23T15:22:23.55574+08:00"},{"id":461,"source_id":"760610d4-dff6-4c6d-831f-7c9078db86a6","target_id":"09971e31ab658e119d4c0ad948282107","source_type":"WIKI_ITEM","target_type":"CODE_SNIPPET","relationship_type":"CONTAINS","extra":"Wiki contains code snippet: frontend/components/ui/select.tsx#15-100","gmt_create":"2026-04-23T15:22:23.556401+08:00","gmt_modified":"2026-04-23T15:22:23.556401+08:00"},{"id":462,"source_id":"3c56e1c079959bfcc985183805e5874f","target_id":"09971e31ab658e119d4c0ad948282107","source_type":"SOURCE_FILE","target_type":"CODE_SNIPPET","relationship_type":"CONTAINS","extra":"Source file contains code snippet: 15-100","gmt_create":"2026-04-23T15:22:23.556634+08:00","gmt_modified":"2026-04-23T15:22:23.556634+08:00"},{"id":463,"source_id":"760610d4-dff6-4c6d-831f-7c9078db86a6","target_id":"31aa8777de6043883950d2668094e388","source_type":"WIKI_ITEM","target_type":"CODE_SNIPPET","relationship_type":"CONTAINS","extra":"Wiki contains code snippet: frontend/components/ui/table.tsx#5-106","gmt_create":"2026-04-23T15:22:23.55717+08:00","gmt_modified":"2026-04-23T15:22:23.55717+08:00"},{"id":464,"source_id":"0c0b0f4e2cf44facd9d5b57de0d0bf0c","target_id":"31aa8777de6043883950d2668094e388","source_type":"SOURCE_FILE","target_type":"CODE_SNIPPET","relationship_type":"CONTAINS","extra":"Source file contains code snippet: 5-106","gmt_create":"2026-04-23T15:22:23.557428+08:00","gmt_modified":"2026-04-23T15:22:23.557429+08:00"},{"id":465,"source_id":"760610d4-dff6-4c6d-831f-7c9078db86a6","target_id":"28baf3cedb89a21c6d542b7ce2439b24","source_type":"WIKI_ITEM","target_type":"CODE_SNIPPET","relationship_type":"CONTAINS","extra":"Wiki contains code snippet: frontend/components/ui/tabs.tsx#8-53","gmt_create":"2026-04-23T15:22:23.558002+08:00","gmt_modified":"2026-04-23T15:22:23.558002+08:00"},{"id":466,"source_id":"beb87ab5aad9532647e9dbd2db7ef587","target_id":"28baf3cedb89a21c6d542b7ce2439b24","source_type":"SOURCE_FILE","target_type":"CODE_SNIPPET","relationship_type":"CONTAINS","extra":"Source file contains code snippet: 8-53","gmt_create":"2026-04-23T15:22:23.558316+08:00","gmt_modified":"2026-04-23T15:22:23.558316+08:00"},{"id":467,"source_id":"760610d4-dff6-4c6d-831f-7c9078db86a6","target_id":"28b0f4797c6084272244175a24b961cb","source_type":"WIKI_ITEM","target_type":"CODE_SNIPPET","relationship_type":"CONTAINS","extra":"Wiki contains code snippet: frontend/components/ui/card.tsx#5-77","gmt_create":"2026-04-23T15:22:23.558858+08:00","gmt_modified":"2026-04-23T15:22:23.558858+08:00"},{"id":468,"source_id":"0d5ef537f7c0b8c390f8b31d7cf47b56","target_id":"28b0f4797c6084272244175a24b961cb","source_type":"SOURCE_FILE","target_type":"CODE_SNIPPET","relationship_type":"CONTAINS","extra":"Source file contains code snippet: 5-77","gmt_create":"2026-04-23T15:22:23.559082+08:00","gmt_modified":"2026-04-23T15:22:23.559082+08:00"},{"id":469,"source_id":"760610d4-dff6-4c6d-831f-7c9078db86a6","target_id":"a6e0b3fa65906c3c3cd88707e1d40059","source_type":"WIKI_ITEM","target_type":"CODE_SNIPPET","relationship_type":"CONTAINS","extra":"Wiki contains code snippet: frontend/components/ui/label.tsx#9-23","gmt_create":"2026-04-23T15:22:23.559653+08:00","gmt_modified":"2026-04-23T15:22:23.559653+08:00"},{"id":470,"source_id":"792b8e2c16c9ff2095d83b8972313be4","target_id":"a6e0b3fa65906c3c3cd88707e1d40059","source_type":"SOURCE_FILE","target_type":"CODE_SNIPPET","relationship_type":"CONTAINS","extra":"Source file contains code snippet: 9-23","gmt_create":"2026-04-23T15:22:23.560391+08:00","gmt_modified":"2026-04-23T15:22:23.560392+08:00"},{"id":471,"source_id":"760610d4-dff6-4c6d-831f-7c9078db86a6","target_id":"9a909775022010b4686c2b00cdf1c165","source_type":"WIKI_ITEM","target_type":"CODE_SNIPPET","relationship_type":"CONTAINS","extra":"Wiki contains code snippet: frontend/components/ui/badge.tsx#6-34","gmt_create":"2026-04-23T15:22:23.562216+08:00","gmt_modified":"2026-04-23T15:22:23.562216+08:00"},{"id":472,"source_id":"51821ca9ec2a1c972f3c9d111e19db8a","target_id":"9a909775022010b4686c2b00cdf1c165","source_type":"SOURCE_FILE","target_type":"CODE_SNIPPET","relationship_type":"CONTAINS","extra":"Source file contains code snippet: 6-34","gmt_create":"2026-04-23T15:22:23.562602+08:00","gmt_modified":"2026-04-23T15:22:23.562602+08:00"},{"id":473,"source_id":"760610d4-dff6-4c6d-831f-7c9078db86a6","target_id":"ce1cd184945ae56cf63f55168afd8050","source_type":"WIKI_ITEM","target_type":"CODE_SNIPPET","relationship_type":"CONTAINS","extra":"Wiki contains code snippet: frontend/components/ui/dialog.tsx#47-50","gmt_create":"2026-04-23T15:22:23.565009+08:00","gmt_modified":"2026-04-23T15:22:23.565009+08:00"},{"id":474,"source_id":"108b0c4b4dcfb6aa39a5eb138225c148","target_id":"ce1cd184945ae56cf63f55168afd8050","source_type":"SOURCE_FILE","target_type":"CODE_SNIPPET","relationship_type":"CONTAINS","extra":"Source file contains code snippet: 47-50","gmt_create":"2026-04-23T15:22:23.565469+08:00","gmt_modified":"2026-04-23T15:22:23.565469+08:00"},{"id":475,"source_id":"760610d4-dff6-4c6d-831f-7c9078db86a6","target_id":"4a2a06e1efcbc85deaa013dca155f20c","source_type":"WIKI_ITEM","target_type":"CODE_SNIPPET","relationship_type":"CONTAINS","extra":"Wiki contains code snippet: frontend/tailwind.config.ts#10-54","gmt_create":"2026-04-23T15:22:23.57102+08:00","gmt_modified":"2026-04-23T15:22:23.57102+08:00"},{"id":476,"source_id":"01056dad8851d3e9bd532eb4cab33792","target_id":"4a2a06e1efcbc85deaa013dca155f20c","source_type":"SOURCE_FILE","target_type":"CODE_SNIPPET","relationship_type":"CONTAINS","extra":"Source file contains code snippet: 10-54","gmt_create":"2026-04-23T15:22:23.571491+08:00","gmt_modified":"2026-04-23T15:22:23.571491+08:00"},{"id":477,"source_id":"760610d4-dff6-4c6d-831f-7c9078db86a6","target_id":"8b00ea4aba57ea6ed982287fb7840805","source_type":"WIKI_ITEM","target_type":"CODE_SNIPPET","relationship_type":"CONTAINS","extra":"Wiki contains code snippet: frontend/lib/utils.ts#4-6","gmt_create":"2026-04-23T15:22:23.572188+08:00","gmt_modified":"2026-04-23T15:22:23.572188+08:00"},{"id":478,"source_id":"f93ae024fe0a2e69698037dff6df205f","target_id":"8b00ea4aba57ea6ed982287fb7840805","source_type":"SOURCE_FILE","target_type":"CODE_SNIPPET","relationship_type":"CONTAINS","extra":"Source file contains code snippet: 4-6","gmt_create":"2026-04-23T15:22:23.572722+08:00","gmt_modified":"2026-04-23T15:22:23.572722+08:00"},{"id":483,"source_id":"deb919cc-9541-4ed7-a581-ae2876ea67c2","target_id":"2fc79486-ec65-4533-860a-89c8877c2ea0","source_type":"WIKI_ITEM","target_type":"WIKI_ITEM","relationship_type":"PARENT_CHILD","extra":"Wiki parent-child relationship: deb919cc-9541-4ed7-a581-ae2876ea67c2 -\u003e 2fc79486-ec65-4533-860a-89c8877c2ea0","gmt_create":"2026-04-23T15:22:24.563092+08:00","gmt_modified":"2026-04-23T15:22:24.563092+08:00"},{"id":484,"source_id":"deb919cc-9541-4ed7-a581-ae2876ea67c2","target_id":"d8e2cef5-37e6-44e7-8a7b-9bd365b82a72","source_type":"WIKI_ITEM","target_type":"WIKI_ITEM","relationship_type":"PARENT_CHILD","extra":"Wiki parent-child relationship: deb919cc-9541-4ed7-a581-ae2876ea67c2 -\u003e d8e2cef5-37e6-44e7-8a7b-9bd365b82a72","gmt_create":"2026-04-23T15:22:24.564188+08:00","gmt_modified":"2026-04-23T15:22:24.564188+08:00"},{"id":492,"source_id":"cfc48cde-e1c3-47f6-afe2-a6d7a8f4ab69","target_id":"a16cf42e9559523c4f96ca4c79f9488d","source_type":"WIKI_ITEM","target_type":"SOURCE_FILE","relationship_type":"REFERENCED_BY","extra":"Wiki references source file: backend/app/workers/platforms/base.py","gmt_create":"2026-04-23T20:31:36.520458+08:00","gmt_modified":"2026-04-23T20:31:36.520458+08:00"},{"id":493,"source_id":"cfc48cde-e1c3-47f6-afe2-a6d7a8f4ab69","target_id":"8f973791233c698b3e64a4fb28a93d4b","source_type":"WIKI_ITEM","target_type":"SOURCE_FILE","relationship_type":"REFERENCED_BY","extra":"Wiki references source file: backend/app/workers/platforms/kimi.py","gmt_create":"2026-04-23T20:31:36.521676+08:00","gmt_modified":"2026-04-23T20:31:36.521677+08:00"},{"id":494,"source_id":"cfc48cde-e1c3-47f6-afe2-a6d7a8f4ab69","target_id":"f642fc1c2f34e15572d9d98aa6c18813","source_type":"WIKI_ITEM","target_type":"SOURCE_FILE","relationship_type":"REFERENCED_BY","extra":"Wiki references source file: backend/app/workers/platforms/wenxin.py","gmt_create":"2026-04-23T20:31:36.522472+08:00","gmt_modified":"2026-04-23T20:31:36.522472+08:00"},{"id":495,"source_id":"cfc48cde-e1c3-47f6-afe2-a6d7a8f4ab69","target_id":"e68ad5186f1e47610ab3d9f14a794393","source_type":"WIKI_ITEM","target_type":"SOURCE_FILE","relationship_type":"REFERENCED_BY","extra":"Wiki references source file: backend/app/workers/platforms/tongyi.py","gmt_create":"2026-04-23T20:31:36.522898+08:00","gmt_modified":"2026-04-23T20:31:36.522898+08:00"},{"id":496,"source_id":"cfc48cde-e1c3-47f6-afe2-a6d7a8f4ab69","target_id":"404f6d0765a8c6e77e33b7fc21b377a4","source_type":"WIKI_ITEM","target_type":"SOURCE_FILE","relationship_type":"REFERENCED_BY","extra":"Wiki references source file: backend/app/workers/platforms/doubao.py","gmt_create":"2026-04-23T20:31:36.523305+08:00","gmt_modified":"2026-04-23T20:31:36.523305+08:00"},{"id":497,"source_id":"cfc48cde-e1c3-47f6-afe2-a6d7a8f4ab69","target_id":"303e80519e946904d1cb3ac32cbb0814","source_type":"WIKI_ITEM","target_type":"SOURCE_FILE","relationship_type":"REFERENCED_BY","extra":"Wiki references source file: backend/app/workers/platforms/qingyan.py","gmt_create":"2026-04-23T20:31:36.524292+08:00","gmt_modified":"2026-04-23T20:31:36.524292+08:00"},{"id":498,"source_id":"cfc48cde-e1c3-47f6-afe2-a6d7a8f4ab69","target_id":"5af7301fe056fc3d10820d820e8ad777","source_type":"WIKI_ITEM","target_type":"SOURCE_FILE","relationship_type":"REFERENCED_BY","extra":"Wiki references source file: backend/app/workers/platforms/tiangong.py","gmt_create":"2026-04-23T20:31:36.525283+08:00","gmt_modified":"2026-04-23T20:31:36.525283+08:00"},{"id":499,"source_id":"cfc48cde-e1c3-47f6-afe2-a6d7a8f4ab69","target_id":"0e38ad5d2d3daaad08c9302df8805b15","source_type":"WIKI_ITEM","target_type":"SOURCE_FILE","relationship_type":"REFERENCED_BY","extra":"Wiki references source file: backend/app/workers/platforms/xinghuo.py","gmt_create":"2026-04-23T20:31:36.52736+08:00","gmt_modified":"2026-04-23T20:31:36.52736+08:00"},{"id":500,"source_id":"cfc48cde-e1c3-47f6-afe2-a6d7a8f4ab69","target_id":"6a63f048c16c60c5d2d57012c810ee0e","source_type":"WIKI_ITEM","target_type":"SOURCE_FILE","relationship_type":"REFERENCED_BY","extra":"Wiki references source file: backend/app/workers/platforms/search_engine.py","gmt_create":"2026-04-23T20:31:36.527985+08:00","gmt_modified":"2026-04-23T20:31:36.527985+08:00"},{"id":501,"source_id":"cfc48cde-e1c3-47f6-afe2-a6d7a8f4ab69","target_id":"74040de652d5e57f548bb5c4adc3e1a0","source_type":"WIKI_ITEM","target_type":"SOURCE_FILE","relationship_type":"REFERENCED_BY","extra":"Wiki references source file: backend/app/workers/citation_engine.py","gmt_create":"2026-04-23T20:31:36.530076+08:00","gmt_modified":"2026-04-23T20:31:36.530076+08:00"},{"id":502,"source_id":"cfc48cde-e1c3-47f6-afe2-a6d7a8f4ab69","target_id":"9ff19022ef915615911280e3c49ed44b","source_type":"WIKI_ITEM","target_type":"SOURCE_FILE","relationship_type":"REFERENCED_BY","extra":"Wiki references source file: backend/app/config.py","gmt_create":"2026-04-23T20:31:36.531496+08:00","gmt_modified":"2026-04-23T20:31:36.531496+08:00"},{"id":503,"source_id":"cfc48cde-e1c3-47f6-afe2-a6d7a8f4ab69","target_id":"b74caccb06844efcdb14d8324cff65c2","source_type":"WIKI_ITEM","target_type":"SOURCE_FILE","relationship_type":"REFERENCED_BY","extra":"Wiki references source file: backend/app/models/query.py","gmt_create":"2026-04-23T20:31:36.532308+08:00","gmt_modified":"2026-04-23T20:31:36.532308+08:00"},{"id":504,"source_id":"cfc48cde-e1c3-47f6-afe2-a6d7a8f4ab69","target_id":"b4a81ef789630d0af6a8d50859d01bf3","source_type":"WIKI_ITEM","target_type":"SOURCE_FILE","relationship_type":"REFERENCED_BY","extra":"Wiki references source file: backend/app/models/citation_record.py","gmt_create":"2026-04-23T20:31:36.533202+08:00","gmt_modified":"2026-04-23T20:31:36.533203+08:00"},{"id":505,"source_id":"cfc48cde-e1c3-47f6-afe2-a6d7a8f4ab69","target_id":"069738f21ac2da7349d22683e8c36929","source_type":"WIKI_ITEM","target_type":"SOURCE_FILE","relationship_type":"REFERENCED_BY","extra":"Wiki references source file: backend/app/models/query_task.py","gmt_create":"2026-04-23T20:31:36.533733+08:00","gmt_modified":"2026-04-23T20:31:36.533733+08:00"},{"id":506,"source_id":"cfc48cde-e1c3-47f6-afe2-a6d7a8f4ab69","target_id":"5cbb1e3f112aeba62a14b0b8999fc0f5","source_type":"WIKI_ITEM","target_type":"SOURCE_FILE","relationship_type":"REFERENCED_BY","extra":"Wiki references source file: backend/app/workers/scheduler.py","gmt_create":"2026-04-23T20:31:36.534166+08:00","gmt_modified":"2026-04-23T20:31:36.534166+08:00"},{"id":507,"source_id":"cfc48cde-e1c3-47f6-afe2-a6d7a8f4ab69","target_id":"7538ffe4902ab6041adb28b19844962a","source_type":"WIKI_ITEM","target_type":"SOURCE_FILE","relationship_type":"REFERENCED_BY","extra":"Wiki references source file: backend/app/api/citations.py","gmt_create":"2026-04-23T20:31:36.535208+08:00","gmt_modified":"2026-04-23T20:31:36.535208+08:00"},{"id":508,"source_id":"cfc48cde-e1c3-47f6-afe2-a6d7a8f4ab69","target_id":"04e3926c080e795713bff683e7dc9d3e","source_type":"WIKI_ITEM","target_type":"SOURCE_FILE","relationship_type":"REFERENCED_BY","extra":"Wiki references source file: backend/app/services/citation.py","gmt_create":"2026-04-23T20:31:36.536177+08:00","gmt_modified":"2026-04-23T20:31:36.536177+08:00"},{"id":509,"source_id":"cfc48cde-e1c3-47f6-afe2-a6d7a8f4ab69","target_id":"ef72f0c3cedb9fd9a87352fe493053dc","source_type":"WIKI_ITEM","target_type":"SOURCE_FILE","relationship_type":"REFERENCED_BY","extra":"Wiki references source file: frontend/lib/platforms.ts","gmt_create":"2026-04-23T20:31:36.536784+08:00","gmt_modified":"2026-04-23T20:31:36.536784+08:00"},{"id":510,"source_id":"cfc48cde-e1c3-47f6-afe2-a6d7a8f4ab69","target_id":"b07a4fb9cecbbd66a6910ccbc7651f19","source_type":"WIKI_ITEM","target_type":"SOURCE_FILE","relationship_type":"REFERENCED_BY","extra":"Wiki references source file: tests/test_citation_engine.py","gmt_create":"2026-04-23T20:31:36.537249+08:00","gmt_modified":"2026-04-23T20:31:36.537249+08:00"},{"id":511,"source_id":"cfc48cde-e1c3-47f6-afe2-a6d7a8f4ab69","target_id":"a26ee01cf41da3b956e1650448c156fa","source_type":"WIKI_ITEM","target_type":"SOURCE_FILE","relationship_type":"REFERENCED_BY","extra":"Wiki references source file: backend/requirements.txt","gmt_create":"2026-04-23T20:31:36.53817+08:00","gmt_modified":"2026-04-23T20:31:36.538171+08:00"},{"id":512,"source_id":"cfc48cde-e1c3-47f6-afe2-a6d7a8f4ab69","target_id":"cbd0101fa84d957bcb1baaa623c6b31c","source_type":"WIKI_ITEM","target_type":"CODE_SNIPPET","relationship_type":"CONTAINS","extra":"Wiki contains code snippet: backend/app/api/citations.py#1-78","gmt_create":"2026-04-23T20:31:36.53929+08:00","gmt_modified":"2026-04-23T20:31:36.53929+08:00"},{"id":513,"source_id":"cfc48cde-e1c3-47f6-afe2-a6d7a8f4ab69","target_id":"7c0831c17e8c65eaed9511e17ed2a2ef","source_type":"WIKI_ITEM","target_type":"CODE_SNIPPET","relationship_type":"CONTAINS","extra":"Wiki contains code snippet: backend/app/services/citation.py#1-269","gmt_create":"2026-04-23T20:31:36.540413+08:00","gmt_modified":"2026-04-23T20:31:36.540413+08:00"},{"id":514,"source_id":"04e3926c080e795713bff683e7dc9d3e","target_id":"7c0831c17e8c65eaed9511e17ed2a2ef","source_type":"SOURCE_FILE","target_type":"CODE_SNIPPET","relationship_type":"CONTAINS","extra":"Source file contains code snippet: 1-269","gmt_create":"2026-04-23T20:31:36.541301+08:00","gmt_modified":"2026-04-23T20:31:36.541301+08:00"},{"id":515,"source_id":"cfc48cde-e1c3-47f6-afe2-a6d7a8f4ab69","target_id":"71f98c8993fb42b108e34a554247869b","source_type":"WIKI_ITEM","target_type":"CODE_SNIPPET","relationship_type":"CONTAINS","extra":"Wiki contains code snippet: backend/app/workers/scheduler.py#1-95","gmt_create":"2026-04-23T20:31:36.541996+08:00","gmt_modified":"2026-04-23T20:31:36.541996+08:00"},{"id":516,"source_id":"5cbb1e3f112aeba62a14b0b8999fc0f5","target_id":"71f98c8993fb42b108e34a554247869b","source_type":"SOURCE_FILE","target_type":"CODE_SNIPPET","relationship_type":"CONTAINS","extra":"Source file contains code snippet: 1-95","gmt_create":"2026-04-23T20:31:36.542269+08:00","gmt_modified":"2026-04-23T20:31:36.542269+08:00"},{"id":517,"source_id":"cfc48cde-e1c3-47f6-afe2-a6d7a8f4ab69","target_id":"8d5aac2ae0671f05d7c0807ba9296cdf","source_type":"WIKI_ITEM","target_type":"CODE_SNIPPET","relationship_type":"CONTAINS","extra":"Wiki contains code snippet: backend/app/workers/citation_engine.py#1-330","gmt_create":"2026-04-23T20:31:36.543463+08:00","gmt_modified":"2026-04-23T20:31:36.543463+08:00"},{"id":518,"source_id":"74040de652d5e57f548bb5c4adc3e1a0","target_id":"8d5aac2ae0671f05d7c0807ba9296cdf","source_type":"SOURCE_FILE","target_type":"CODE_SNIPPET","relationship_type":"CONTAINS","extra":"Source file contains code snippet: 1-330","gmt_create":"2026-04-23T20:31:36.543912+08:00","gmt_modified":"2026-04-23T20:31:36.543912+08:00"},{"id":519,"source_id":"cfc48cde-e1c3-47f6-afe2-a6d7a8f4ab69","target_id":"debd789847d1eed2d54198772edf68a2","source_type":"WIKI_ITEM","target_type":"CODE_SNIPPET","relationship_type":"CONTAINS","extra":"Wiki contains code snippet: backend/app/workers/platforms/tongyi.py#1-38","gmt_create":"2026-04-23T20:31:36.545278+08:00","gmt_modified":"2026-04-23T20:31:36.545279+08:00"},{"id":520,"source_id":"e68ad5186f1e47610ab3d9f14a794393","target_id":"debd789847d1eed2d54198772edf68a2","source_type":"SOURCE_FILE","target_type":"CODE_SNIPPET","relationship_type":"CONTAINS","extra":"Source file contains code snippet: 1-38","gmt_create":"2026-04-23T20:31:36.545752+08:00","gmt_modified":"2026-04-23T20:31:36.545752+08:00"},{"id":521,"source_id":"cfc48cde-e1c3-47f6-afe2-a6d7a8f4ab69","target_id":"3bde521d18cc7221ae2f14637e163aac","source_type":"WIKI_ITEM","target_type":"CODE_SNIPPET","relationship_type":"CONTAINS","extra":"Wiki contains code snippet: backend/app/workers/platforms/doubao.py#1-38","gmt_create":"2026-04-23T20:31:36.546456+08:00","gmt_modified":"2026-04-23T20:31:36.546457+08:00"},{"id":522,"source_id":"404f6d0765a8c6e77e33b7fc21b377a4","target_id":"3bde521d18cc7221ae2f14637e163aac","source_type":"SOURCE_FILE","target_type":"CODE_SNIPPET","relationship_type":"CONTAINS","extra":"Source file contains code snippet: 1-38","gmt_create":"2026-04-23T20:31:36.546804+08:00","gmt_modified":"2026-04-23T20:31:36.546804+08:00"},{"id":523,"source_id":"cfc48cde-e1c3-47f6-afe2-a6d7a8f4ab69","target_id":"c26862d9e0fc878b51a2668cfd2ec827","source_type":"WIKI_ITEM","target_type":"CODE_SNIPPET","relationship_type":"CONTAINS","extra":"Wiki contains code snippet: backend/app/workers/platforms/qingyan.py#1-38","gmt_create":"2026-04-23T20:31:36.547594+08:00","gmt_modified":"2026-04-23T20:31:36.547594+08:00"},{"id":524,"source_id":"303e80519e946904d1cb3ac32cbb0814","target_id":"c26862d9e0fc878b51a2668cfd2ec827","source_type":"SOURCE_FILE","target_type":"CODE_SNIPPET","relationship_type":"CONTAINS","extra":"Source file contains code snippet: 1-38","gmt_create":"2026-04-23T20:31:36.548009+08:00","gmt_modified":"2026-04-23T20:31:36.548009+08:00"},{"id":525,"source_id":"cfc48cde-e1c3-47f6-afe2-a6d7a8f4ab69","target_id":"0fcc9c2e0d33b887c5f18a3807b64a1e","source_type":"WIKI_ITEM","target_type":"CODE_SNIPPET","relationship_type":"CONTAINS","extra":"Wiki contains code snippet: backend/app/workers/platforms/tiangong.py#1-38","gmt_create":"2026-04-23T20:31:36.548333+08:00","gmt_modified":"2026-04-23T20:31:36.548333+08:00"},{"id":526,"source_id":"5af7301fe056fc3d10820d820e8ad777","target_id":"0fcc9c2e0d33b887c5f18a3807b64a1e","source_type":"SOURCE_FILE","target_type":"CODE_SNIPPET","relationship_type":"CONTAINS","extra":"Source file contains code snippet: 1-38","gmt_create":"2026-04-23T20:31:36.548917+08:00","gmt_modified":"2026-04-23T20:31:36.548917+08:00"},{"id":527,"source_id":"cfc48cde-e1c3-47f6-afe2-a6d7a8f4ab69","target_id":"a4baa2444208b3f9a3f42bc492038207","source_type":"WIKI_ITEM","target_type":"CODE_SNIPPET","relationship_type":"CONTAINS","extra":"Wiki contains code snippet: backend/app/workers/platforms/xinghuo.py#1-38","gmt_create":"2026-04-23T20:31:36.549296+08:00","gmt_modified":"2026-04-23T20:31:36.549296+08:00"},{"id":528,"source_id":"0e38ad5d2d3daaad08c9302df8805b15","target_id":"a4baa2444208b3f9a3f42bc492038207","source_type":"SOURCE_FILE","target_type":"CODE_SNIPPET","relationship_type":"CONTAINS","extra":"Source file contains code snippet: 1-38","gmt_create":"2026-04-23T20:31:36.54956+08:00","gmt_modified":"2026-04-23T20:31:36.54956+08:00"},{"id":529,"source_id":"cfc48cde-e1c3-47f6-afe2-a6d7a8f4ab69","target_id":"9f82f6d82bf914a608d6afa3d9854abf","source_type":"WIKI_ITEM","target_type":"CODE_SNIPPET","relationship_type":"CONTAINS","extra":"Wiki contains code snippet: backend/app/workers/platforms/search_engine.py#1-174","gmt_create":"2026-04-23T20:31:36.549907+08:00","gmt_modified":"2026-04-23T20:31:36.549907+08:00"},{"id":530,"source_id":"6a63f048c16c60c5d2d57012c810ee0e","target_id":"9f82f6d82bf914a608d6afa3d9854abf","source_type":"SOURCE_FILE","target_type":"CODE_SNIPPET","relationship_type":"CONTAINS","extra":"Source file contains code snippet: 1-174","gmt_create":"2026-04-23T20:31:36.55085+08:00","gmt_modified":"2026-04-23T20:31:36.55085+08:00"},{"id":531,"source_id":"cfc48cde-e1c3-47f6-afe2-a6d7a8f4ab69","target_id":"84fbed7d35f7752e2117a74fcaf5f0e9","source_type":"WIKI_ITEM","target_type":"CODE_SNIPPET","relationship_type":"CONTAINS","extra":"Wiki contains code snippet: backend/app/config.py#1-17","gmt_create":"2026-04-23T20:31:36.551428+08:00","gmt_modified":"2026-04-23T20:31:36.551428+08:00"},{"id":532,"source_id":"cfc48cde-e1c3-47f6-afe2-a6d7a8f4ab69","target_id":"6281fff17a86ec1895c64d87c2ae7fb1","source_type":"WIKI_ITEM","target_type":"CODE_SNIPPET","relationship_type":"CONTAINS","extra":"Wiki contains code snippet: backend/app/models/query.py#1-55","gmt_create":"2026-04-23T20:31:36.552386+08:00","gmt_modified":"2026-04-23T20:31:36.552386+08:00"},{"id":533,"source_id":"b74caccb06844efcdb14d8324cff65c2","target_id":"6281fff17a86ec1895c64d87c2ae7fb1","source_type":"SOURCE_FILE","target_type":"CODE_SNIPPET","relationship_type":"CONTAINS","extra":"Source file contains code snippet: 1-55","gmt_create":"2026-04-23T20:31:36.553134+08:00","gmt_modified":"2026-04-23T20:31:36.553134+08:00"},{"id":534,"source_id":"cfc48cde-e1c3-47f6-afe2-a6d7a8f4ab69","target_id":"943c18db69a04b3137fba4cebcfea87e","source_type":"WIKI_ITEM","target_type":"CODE_SNIPPET","relationship_type":"CONTAINS","extra":"Wiki contains code snippet: backend/app/models/citation_record.py#1-42","gmt_create":"2026-04-23T20:31:36.553656+08:00","gmt_modified":"2026-04-23T20:31:36.553656+08:00"},{"id":535,"source_id":"b4a81ef789630d0af6a8d50859d01bf3","target_id":"943c18db69a04b3137fba4cebcfea87e","source_type":"SOURCE_FILE","target_type":"CODE_SNIPPET","relationship_type":"CONTAINS","extra":"Source file contains code snippet: 1-42","gmt_create":"2026-04-23T20:31:36.554174+08:00","gmt_modified":"2026-04-23T20:31:36.554174+08:00"},{"id":536,"source_id":"cfc48cde-e1c3-47f6-afe2-a6d7a8f4ab69","target_id":"6628e006b8e5ca16160743528b6b0506","source_type":"WIKI_ITEM","target_type":"CODE_SNIPPET","relationship_type":"CONTAINS","extra":"Wiki contains code snippet: backend/app/models/query_task.py#1-39","gmt_create":"2026-04-23T20:31:36.555503+08:00","gmt_modified":"2026-04-23T20:31:36.555503+08:00"},{"id":537,"source_id":"069738f21ac2da7349d22683e8c36929","target_id":"6628e006b8e5ca16160743528b6b0506","source_type":"SOURCE_FILE","target_type":"CODE_SNIPPET","relationship_type":"CONTAINS","extra":"Source file contains code snippet: 1-39","gmt_create":"2026-04-23T20:31:36.556658+08:00","gmt_modified":"2026-04-23T20:31:36.556658+08:00"},{"id":538,"source_id":"cfc48cde-e1c3-47f6-afe2-a6d7a8f4ab69","target_id":"72a110dca58d8152758e2fdab4e94761","source_type":"WIKI_ITEM","target_type":"CODE_SNIPPET","relationship_type":"CONTAINS","extra":"Wiki contains code snippet: backend/app/workers/platforms/base.py#1-18","gmt_create":"2026-04-23T20:31:36.558991+08:00","gmt_modified":"2026-04-23T20:31:36.558991+08:00"},{"id":539,"source_id":"a16cf42e9559523c4f96ca4c79f9488d","target_id":"72a110dca58d8152758e2fdab4e94761","source_type":"SOURCE_FILE","target_type":"CODE_SNIPPET","relationship_type":"CONTAINS","extra":"Source file contains code snippet: 1-18","gmt_create":"2026-04-23T20:31:36.559781+08:00","gmt_modified":"2026-04-23T20:31:36.559781+08:00"},{"id":540,"source_id":"cfc48cde-e1c3-47f6-afe2-a6d7a8f4ab69","target_id":"300e43c7a648440163f81039eaa47b5a","source_type":"WIKI_ITEM","target_type":"CODE_SNIPPET","relationship_type":"CONTAINS","extra":"Wiki contains code snippet: frontend/lib/platforms.ts#1-24","gmt_create":"2026-04-23T20:31:36.563289+08:00","gmt_modified":"2026-04-23T20:31:36.563289+08:00"},{"id":541,"source_id":"ef72f0c3cedb9fd9a87352fe493053dc","target_id":"300e43c7a648440163f81039eaa47b5a","source_type":"SOURCE_FILE","target_type":"CODE_SNIPPET","relationship_type":"CONTAINS","extra":"Source file contains code snippet: 1-24","gmt_create":"2026-04-23T20:31:36.563813+08:00","gmt_modified":"2026-04-23T20:31:36.563813+08:00"},{"id":542,"source_id":"cfc48cde-e1c3-47f6-afe2-a6d7a8f4ab69","target_id":"caf1970ded8fc5d3921005e166e2100b","source_type":"WIKI_ITEM","target_type":"CODE_SNIPPET","relationship_type":"CONTAINS","extra":"Wiki contains code snippet: backend/app/api/citations.py#59-78","gmt_create":"2026-04-23T20:31:36.567359+08:00","gmt_modified":"2026-04-23T20:31:36.567359+08:00"},{"id":543,"source_id":"7538ffe4902ab6041adb28b19844962a","target_id":"caf1970ded8fc5d3921005e166e2100b","source_type":"SOURCE_FILE","target_type":"CODE_SNIPPET","relationship_type":"CONTAINS","extra":"Source file contains code snippet: 59-78","gmt_create":"2026-04-23T20:31:36.567845+08:00","gmt_modified":"2026-04-23T20:31:36.567845+08:00"},{"id":544,"source_id":"cfc48cde-e1c3-47f6-afe2-a6d7a8f4ab69","target_id":"4ded871d02b8119cdd985de8b220b084","source_type":"WIKI_ITEM","target_type":"CODE_SNIPPET","relationship_type":"CONTAINS","extra":"Wiki contains code snippet: backend/app/services/citation.py#204-234","gmt_create":"2026-04-23T20:31:36.568622+08:00","gmt_modified":"2026-04-23T20:31:36.568622+08:00"},{"id":545,"source_id":"04e3926c080e795713bff683e7dc9d3e","target_id":"4ded871d02b8119cdd985de8b220b084","source_type":"SOURCE_FILE","target_type":"CODE_SNIPPET","relationship_type":"CONTAINS","extra":"Source file contains code snippet: 204-234","gmt_create":"2026-04-23T20:31:36.569217+08:00","gmt_modified":"2026-04-23T20:31:36.569217+08:00"},{"id":546,"source_id":"cfc48cde-e1c3-47f6-afe2-a6d7a8f4ab69","target_id":"448970b02d89d5e1576f70bdb0063363","source_type":"WIKI_ITEM","target_type":"CODE_SNIPPET","relationship_type":"CONTAINS","extra":"Wiki contains code snippet: backend/app/workers/scheduler.py#51-84","gmt_create":"2026-04-23T20:31:36.569785+08:00","gmt_modified":"2026-04-23T20:31:36.569785+08:00"},{"id":547,"source_id":"5cbb1e3f112aeba62a14b0b8999fc0f5","target_id":"448970b02d89d5e1576f70bdb0063363","source_type":"SOURCE_FILE","target_type":"CODE_SNIPPET","relationship_type":"CONTAINS","extra":"Source file contains code snippet: 51-84","gmt_create":"2026-04-23T20:31:36.570169+08:00","gmt_modified":"2026-04-23T20:31:36.570169+08:00"},{"id":548,"source_id":"cfc48cde-e1c3-47f6-afe2-a6d7a8f4ab69","target_id":"362d22f423631cda39404660b3317a2f","source_type":"WIKI_ITEM","target_type":"CODE_SNIPPET","relationship_type":"CONTAINS","extra":"Wiki contains code snippet: backend/app/workers/citation_engine.py#177-254","gmt_create":"2026-04-23T20:31:36.570576+08:00","gmt_modified":"2026-04-23T20:31:36.570576+08:00"},{"id":549,"source_id":"74040de652d5e57f548bb5c4adc3e1a0","target_id":"362d22f423631cda39404660b3317a2f","source_type":"SOURCE_FILE","target_type":"CODE_SNIPPET","relationship_type":"CONTAINS","extra":"Source file contains code snippet: 177-254","gmt_create":"2026-04-23T20:31:36.571472+08:00","gmt_modified":"2026-04-23T20:31:36.571472+08:00"},{"id":550,"source_id":"cfc48cde-e1c3-47f6-afe2-a6d7a8f4ab69","target_id":"b475ff5225ac403c7fcf3dd7e14cbac6","source_type":"WIKI_ITEM","target_type":"CODE_SNIPPET","relationship_type":"CONTAINS","extra":"Wiki contains code snippet: backend/app/workers/platforms/tongyi.py#16-33","gmt_create":"2026-04-23T20:31:36.572484+08:00","gmt_modified":"2026-04-23T20:31:36.572484+08:00"},{"id":551,"source_id":"e68ad5186f1e47610ab3d9f14a794393","target_id":"b475ff5225ac403c7fcf3dd7e14cbac6","source_type":"SOURCE_FILE","target_type":"CODE_SNIPPET","relationship_type":"CONTAINS","extra":"Source file contains code snippet: 16-33","gmt_create":"2026-04-23T20:31:36.573312+08:00","gmt_modified":"2026-04-23T20:31:36.573312+08:00"},{"id":552,"source_id":"cfc48cde-e1c3-47f6-afe2-a6d7a8f4ab69","target_id":"557ae34b57a5dd8e8fa3bb2a6ce178a7","source_type":"WIKI_ITEM","target_type":"CODE_SNIPPET","relationship_type":"CONTAINS","extra":"Wiki contains code snippet: backend/app/workers/platforms/search_engine.py#163-174","gmt_create":"2026-04-23T20:31:36.574111+08:00","gmt_modified":"2026-04-23T20:31:36.574112+08:00"},{"id":553,"source_id":"6a63f048c16c60c5d2d57012c810ee0e","target_id":"557ae34b57a5dd8e8fa3bb2a6ce178a7","source_type":"SOURCE_FILE","target_type":"CODE_SNIPPET","relationship_type":"CONTAINS","extra":"Source file contains code snippet: 163-174","gmt_create":"2026-04-23T20:31:36.574746+08:00","gmt_modified":"2026-04-23T20:31:36.574746+08:00"},{"id":554,"source_id":"cfc48cde-e1c3-47f6-afe2-a6d7a8f4ab69","target_id":"75c6ab0599d304bf36d290d4143d3d2f","source_type":"WIKI_ITEM","target_type":"CODE_SNIPPET","relationship_type":"CONTAINS","extra":"Wiki contains code snippet: backend/app/models/query.py#29-31","gmt_create":"2026-04-23T20:31:36.590144+08:00","gmt_modified":"2026-04-23T20:31:36.590144+08:00"},{"id":555,"source_id":"b74caccb06844efcdb14d8324cff65c2","target_id":"75c6ab0599d304bf36d290d4143d3d2f","source_type":"SOURCE_FILE","target_type":"CODE_SNIPPET","relationship_type":"CONTAINS","extra":"Source file contains code snippet: 29-31","gmt_create":"2026-04-23T20:31:36.591214+08:00","gmt_modified":"2026-04-23T20:31:36.591214+08:00"},{"id":556,"source_id":"cfc48cde-e1c3-47f6-afe2-a6d7a8f4ab69","target_id":"fd541971cebf8a7c167d717f5c5d1ff6","source_type":"WIKI_ITEM","target_type":"CODE_SNIPPET","relationship_type":"CONTAINS","extra":"Wiki contains code snippet: backend/app/models/citation_record.py#11-42","gmt_create":"2026-04-23T20:31:36.591664+08:00","gmt_modified":"2026-04-23T20:31:36.591664+08:00"},{"id":557,"source_id":"cfc48cde-e1c3-47f6-afe2-a6d7a8f4ab69","target_id":"b84f46f058847733347974841f613688","source_type":"WIKI_ITEM","target_type":"CODE_SNIPPET","relationship_type":"CONTAINS","extra":"Wiki contains code snippet: backend/app/models/query_task.py#11-39","gmt_create":"2026-04-23T20:31:36.592665+08:00","gmt_modified":"2026-04-23T20:31:36.592666+08:00"},{"id":558,"source_id":"cfc48cde-e1c3-47f6-afe2-a6d7a8f4ab69","target_id":"2a6780838f1415dcb7d0fa611f64cee7","source_type":"WIKI_ITEM","target_type":"CODE_SNIPPET","relationship_type":"CONTAINS","extra":"Wiki contains code snippet: backend/app/workers/platforms/base.py#4-17","gmt_create":"2026-04-23T20:31:36.593186+08:00","gmt_modified":"2026-04-23T20:31:36.593186+08:00"},{"id":559,"source_id":"a16cf42e9559523c4f96ca4c79f9488d","target_id":"2a6780838f1415dcb7d0fa611f64cee7","source_type":"SOURCE_FILE","target_type":"CODE_SNIPPET","relationship_type":"CONTAINS","extra":"Source file contains code snippet: 4-17","gmt_create":"2026-04-23T20:31:36.59372+08:00","gmt_modified":"2026-04-23T20:31:36.59372+08:00"},{"id":560,"source_id":"cfc48cde-e1c3-47f6-afe2-a6d7a8f4ab69","target_id":"c5ae7697193b2b93425ff25d2d7d54a9","source_type":"WIKI_ITEM","target_type":"CODE_SNIPPET","relationship_type":"CONTAINS","extra":"Wiki contains code snippet: backend/app/workers/platforms/tongyi.py#10-38","gmt_create":"2026-04-23T20:31:36.595227+08:00","gmt_modified":"2026-04-23T20:31:36.595227+08:00"},{"id":561,"source_id":"e68ad5186f1e47610ab3d9f14a794393","target_id":"c5ae7697193b2b93425ff25d2d7d54a9","source_type":"SOURCE_FILE","target_type":"CODE_SNIPPET","relationship_type":"CONTAINS","extra":"Source file contains code snippet: 10-38","gmt_create":"2026-04-23T20:31:36.596503+08:00","gmt_modified":"2026-04-23T20:31:36.596503+08:00"},{"id":562,"source_id":"cfc48cde-e1c3-47f6-afe2-a6d7a8f4ab69","target_id":"aa8c3fa3bc509dafe64d113bdd09eafa","source_type":"WIKI_ITEM","target_type":"CODE_SNIPPET","relationship_type":"CONTAINS","extra":"Wiki contains code snippet: backend/app/workers/platforms/doubao.py#10-38","gmt_create":"2026-04-23T20:31:36.597069+08:00","gmt_modified":"2026-04-23T20:31:36.597069+08:00"},{"id":563,"source_id":"404f6d0765a8c6e77e33b7fc21b377a4","target_id":"aa8c3fa3bc509dafe64d113bdd09eafa","source_type":"SOURCE_FILE","target_type":"CODE_SNIPPET","relationship_type":"CONTAINS","extra":"Source file contains code snippet: 10-38","gmt_create":"2026-04-23T20:31:36.597765+08:00","gmt_modified":"2026-04-23T20:31:36.597765+08:00"},{"id":564,"source_id":"cfc48cde-e1c3-47f6-afe2-a6d7a8f4ab69","target_id":"eabb031e538ea62cab69b01368740d20","source_type":"WIKI_ITEM","target_type":"CODE_SNIPPET","relationship_type":"CONTAINS","extra":"Wiki contains code snippet: backend/app/workers/platforms/qingyan.py#10-38","gmt_create":"2026-04-23T20:31:36.598445+08:00","gmt_modified":"2026-04-23T20:31:36.598445+08:00"},{"id":565,"source_id":"303e80519e946904d1cb3ac32cbb0814","target_id":"eabb031e538ea62cab69b01368740d20","source_type":"SOURCE_FILE","target_type":"CODE_SNIPPET","relationship_type":"CONTAINS","extra":"Source file contains code snippet: 10-38","gmt_create":"2026-04-23T20:31:36.599093+08:00","gmt_modified":"2026-04-23T20:31:36.599093+08:00"},{"id":566,"source_id":"cfc48cde-e1c3-47f6-afe2-a6d7a8f4ab69","target_id":"b1c09e372a63e9854886adaea1663bea","source_type":"WIKI_ITEM","target_type":"CODE_SNIPPET","relationship_type":"CONTAINS","extra":"Wiki contains code snippet: backend/app/workers/platforms/tiangong.py#10-38","gmt_create":"2026-04-23T20:31:36.599896+08:00","gmt_modified":"2026-04-23T20:31:36.599896+08:00"},{"id":567,"source_id":"5af7301fe056fc3d10820d820e8ad777","target_id":"b1c09e372a63e9854886adaea1663bea","source_type":"SOURCE_FILE","target_type":"CODE_SNIPPET","relationship_type":"CONTAINS","extra":"Source file contains code snippet: 10-38","gmt_create":"2026-04-23T20:31:36.600604+08:00","gmt_modified":"2026-04-23T20:31:36.600604+08:00"},{"id":568,"source_id":"cfc48cde-e1c3-47f6-afe2-a6d7a8f4ab69","target_id":"79793bcd507f9d287d19014b60d963d3","source_type":"WIKI_ITEM","target_type":"CODE_SNIPPET","relationship_type":"CONTAINS","extra":"Wiki contains code snippet: backend/app/workers/platforms/xinghuo.py#10-38","gmt_create":"2026-04-23T20:31:36.601204+08:00","gmt_modified":"2026-04-23T20:31:36.601204+08:00"},{"id":569,"source_id":"0e38ad5d2d3daaad08c9302df8805b15","target_id":"79793bcd507f9d287d19014b60d963d3","source_type":"SOURCE_FILE","target_type":"CODE_SNIPPET","relationship_type":"CONTAINS","extra":"Source file contains code snippet: 10-38","gmt_create":"2026-04-23T20:31:36.60148+08:00","gmt_modified":"2026-04-23T20:31:36.60148+08:00"},{"id":570,"source_id":"cfc48cde-e1c3-47f6-afe2-a6d7a8f4ab69","target_id":"102223dd13475177a1ade8b9be14fbd1","source_type":"WIKI_ITEM","target_type":"CODE_SNIPPET","relationship_type":"CONTAINS","extra":"Wiki contains code snippet: backend/app/workers/platforms/search_engine.py#79-144","gmt_create":"2026-04-23T20:31:36.603752+08:00","gmt_modified":"2026-04-23T20:31:36.603752+08:00"},{"id":571,"source_id":"6a63f048c16c60c5d2d57012c810ee0e","target_id":"102223dd13475177a1ade8b9be14fbd1","source_type":"SOURCE_FILE","target_type":"CODE_SNIPPET","relationship_type":"CONTAINS","extra":"Source file contains code snippet: 79-144","gmt_create":"2026-04-23T20:31:36.606514+08:00","gmt_modified":"2026-04-23T20:31:36.606514+08:00"},{"id":572,"source_id":"cfc48cde-e1c3-47f6-afe2-a6d7a8f4ab69","target_id":"8565f299083b4dcba5a328c947f06fee","source_type":"WIKI_ITEM","target_type":"CODE_SNIPPET","relationship_type":"CONTAINS","extra":"Wiki contains code snippet: backend/app/workers/citation_engine.py#256-287","gmt_create":"2026-04-23T20:31:36.609013+08:00","gmt_modified":"2026-04-23T20:31:36.609013+08:00"},{"id":573,"source_id":"74040de652d5e57f548bb5c4adc3e1a0","target_id":"8565f299083b4dcba5a328c947f06fee","source_type":"SOURCE_FILE","target_type":"CODE_SNIPPET","relationship_type":"CONTAINS","extra":"Source file contains code snippet: 256-287","gmt_create":"2026-04-23T20:31:36.609501+08:00","gmt_modified":"2026-04-23T20:31:36.609501+08:00"},{"id":574,"source_id":"cfc48cde-e1c3-47f6-afe2-a6d7a8f4ab69","target_id":"8af91caf063c12c8236f9675769ce4a1","source_type":"WIKI_ITEM","target_type":"CODE_SNIPPET","relationship_type":"CONTAINS","extra":"Wiki contains code snippet: tests/test_citation_engine.py#1-54","gmt_create":"2026-04-23T20:31:36.610558+08:00","gmt_modified":"2026-04-23T20:31:36.610558+08:00"},{"id":575,"source_id":"b07a4fb9cecbbd66a6910ccbc7651f19","target_id":"8af91caf063c12c8236f9675769ce4a1","source_type":"SOURCE_FILE","target_type":"CODE_SNIPPET","relationship_type":"CONTAINS","extra":"Source file contains code snippet: 1-54","gmt_create":"2026-04-23T20:31:36.610946+08:00","gmt_modified":"2026-04-23T20:31:36.610946+08:00"},{"id":576,"source_id":"cfc48cde-e1c3-47f6-afe2-a6d7a8f4ab69","target_id":"005172b71dc742cf6803c5eb0185091e","source_type":"WIKI_ITEM","target_type":"CODE_SNIPPET","relationship_type":"CONTAINS","extra":"Wiki contains code snippet: backend/requirements.txt#1-36","gmt_create":"2026-04-23T20:31:36.612653+08:00","gmt_modified":"2026-04-23T20:31:36.612653+08:00"},{"id":577,"source_id":"a26ee01cf41da3b956e1650448c156fa","target_id":"005172b71dc742cf6803c5eb0185091e","source_type":"SOURCE_FILE","target_type":"CODE_SNIPPET","relationship_type":"CONTAINS","extra":"Source file contains code snippet: 1-36","gmt_create":"2026-04-23T20:31:36.613263+08:00","gmt_modified":"2026-04-23T20:31:36.613263+08:00"},{"id":578,"source_id":"cfc48cde-e1c3-47f6-afe2-a6d7a8f4ab69","target_id":"b55cc5936c299f819b57b899858438e6","source_type":"WIKI_ITEM","target_type":"CODE_SNIPPET","relationship_type":"CONTAINS","extra":"Wiki contains code snippet: backend/app/workers/platforms/search_engine.py#139-144","gmt_create":"2026-04-23T20:31:36.614861+08:00","gmt_modified":"2026-04-23T20:31:36.614861+08:00"},{"id":579,"source_id":"6a63f048c16c60c5d2d57012c810ee0e","target_id":"b55cc5936c299f819b57b899858438e6","source_type":"SOURCE_FILE","target_type":"CODE_SNIPPET","relationship_type":"CONTAINS","extra":"Source file contains code snippet: 139-144","gmt_create":"2026-04-23T20:31:36.615692+08:00","gmt_modified":"2026-04-23T20:31:36.615692+08:00"},{"id":580,"source_id":"cfc48cde-e1c3-47f6-afe2-a6d7a8f4ab69","target_id":"384b1939e53970ce7ae75d241a49da5f","source_type":"WIKI_ITEM","target_type":"CODE_SNIPPET","relationship_type":"CONTAINS","extra":"Wiki contains code snippet: backend/app/workers/platforms/tongyi.py#22-29","gmt_create":"2026-04-23T20:31:36.615996+08:00","gmt_modified":"2026-04-23T20:31:36.615996+08:00"},{"id":581,"source_id":"e68ad5186f1e47610ab3d9f14a794393","target_id":"384b1939e53970ce7ae75d241a49da5f","source_type":"SOURCE_FILE","target_type":"CODE_SNIPPET","relationship_type":"CONTAINS","extra":"Source file contains code snippet: 22-29","gmt_create":"2026-04-23T20:31:36.61682+08:00","gmt_modified":"2026-04-23T20:31:36.61682+08:00"},{"id":582,"source_id":"cfc48cde-e1c3-47f6-afe2-a6d7a8f4ab69","target_id":"f096aa3ea82e9fa625a9acb1309b4c50","source_type":"WIKI_ITEM","target_type":"CODE_SNIPPET","relationship_type":"CONTAINS","extra":"Wiki contains code snippet: backend/app/workers/citation_engine.py#231-247","gmt_create":"2026-04-23T20:31:36.617171+08:00","gmt_modified":"2026-04-23T20:31:36.617171+08:00"},{"id":583,"source_id":"74040de652d5e57f548bb5c4adc3e1a0","target_id":"f096aa3ea82e9fa625a9acb1309b4c50","source_type":"SOURCE_FILE","target_type":"CODE_SNIPPET","relationship_type":"CONTAINS","extra":"Source file contains code snippet: 231-247","gmt_create":"2026-04-23T20:31:36.617385+08:00","gmt_modified":"2026-04-23T20:31:36.617385+08:00"},{"id":584,"source_id":"cfc48cde-e1c3-47f6-afe2-a6d7a8f4ab69","target_id":"15b8ebf74b0a5dfac58024d323ca8d0a","source_type":"WIKI_ITEM","target_type":"CODE_SNIPPET","relationship_type":"CONTAINS","extra":"Wiki contains code snippet: backend/app/workers/citation_engine.py#164-175","gmt_create":"2026-04-23T20:31:36.618327+08:00","gmt_modified":"2026-04-23T20:31:36.618327+08:00"},{"id":585,"source_id":"74040de652d5e57f548bb5c4adc3e1a0","target_id":"15b8ebf74b0a5dfac58024d323ca8d0a","source_type":"SOURCE_FILE","target_type":"CODE_SNIPPET","relationship_type":"CONTAINS","extra":"Source file contains code snippet: 164-175","gmt_create":"2026-04-23T20:31:36.618609+08:00","gmt_modified":"2026-04-23T20:31:36.618609+08:00"},{"id":586,"source_id":"fab60eaf-9652-4cb5-9f9e-0525caa62d63","target_id":"f642fc1c2f34e15572d9d98aa6c18813","source_type":"WIKI_ITEM","target_type":"SOURCE_FILE","relationship_type":"REFERENCED_BY","extra":"Wiki references source file: backend/app/workers/platforms/wenxin.py","gmt_create":"2026-04-23T20:31:50.473102+08:00","gmt_modified":"2026-04-23T20:31:50.473102+08:00"},{"id":587,"source_id":"fab60eaf-9652-4cb5-9f9e-0525caa62d63","target_id":"a16cf42e9559523c4f96ca4c79f9488d","source_type":"WIKI_ITEM","target_type":"SOURCE_FILE","relationship_type":"REFERENCED_BY","extra":"Wiki references source file: backend/app/workers/platforms/base.py","gmt_create":"2026-04-23T20:31:50.473614+08:00","gmt_modified":"2026-04-23T20:31:50.473614+08:00"},{"id":588,"source_id":"fab60eaf-9652-4cb5-9f9e-0525caa62d63","target_id":"6a63f048c16c60c5d2d57012c810ee0e","source_type":"WIKI_ITEM","target_type":"SOURCE_FILE","relationship_type":"REFERENCED_BY","extra":"Wiki references source file: backend/app/workers/platforms/search_engine.py","gmt_create":"2026-04-23T20:31:50.474171+08:00","gmt_modified":"2026-04-23T20:31:50.474171+08:00"},{"id":589,"source_id":"fab60eaf-9652-4cb5-9f9e-0525caa62d63","target_id":"74040de652d5e57f548bb5c4adc3e1a0","source_type":"WIKI_ITEM","target_type":"SOURCE_FILE","relationship_type":"REFERENCED_BY","extra":"Wiki references source file: backend/app/workers/citation_engine.py","gmt_create":"2026-04-23T20:31:50.474429+08:00","gmt_modified":"2026-04-23T20:31:50.474429+08:00"},{"id":590,"source_id":"fab60eaf-9652-4cb5-9f9e-0525caa62d63","target_id":"9ff19022ef915615911280e3c49ed44b","source_type":"WIKI_ITEM","target_type":"SOURCE_FILE","relationship_type":"REFERENCED_BY","extra":"Wiki references source file: backend/app/config.py","gmt_create":"2026-04-23T20:31:50.474658+08:00","gmt_modified":"2026-04-23T20:31:50.474658+08:00"},{"id":591,"source_id":"fab60eaf-9652-4cb5-9f9e-0525caa62d63","target_id":"b74caccb06844efcdb14d8324cff65c2","source_type":"WIKI_ITEM","target_type":"SOURCE_FILE","relationship_type":"REFERENCED_BY","extra":"Wiki references source file: backend/app/models/query.py","gmt_create":"2026-04-23T20:31:50.474883+08:00","gmt_modified":"2026-04-23T20:31:50.474883+08:00"},{"id":592,"source_id":"fab60eaf-9652-4cb5-9f9e-0525caa62d63","target_id":"6b3d903205941aa9391dd90016e1102c","source_type":"WIKI_ITEM","target_type":"SOURCE_FILE","relationship_type":"REFERENCED_BY","extra":"Wiki references source file: backend/app/api/queries.py","gmt_create":"2026-04-23T20:31:50.475158+08:00","gmt_modified":"2026-04-23T20:31:50.475158+08:00"},{"id":593,"source_id":"fab60eaf-9652-4cb5-9f9e-0525caa62d63","target_id":"e9b52adbec3c07cf021e488dd3f99ab4","source_type":"WIKI_ITEM","target_type":"SOURCE_FILE","relationship_type":"REFERENCED_BY","extra":"Wiki references source file: backend/Dockerfile","gmt_create":"2026-04-23T20:31:50.475559+08:00","gmt_modified":"2026-04-23T20:31:50.475559+08:00"},{"id":594,"source_id":"fab60eaf-9652-4cb5-9f9e-0525caa62d63","target_id":"8f973791233c698b3e64a4fb28a93d4b","source_type":"WIKI_ITEM","target_type":"SOURCE_FILE","relationship_type":"REFERENCED_BY","extra":"Wiki references source file: backend/app/workers/platforms/kimi.py","gmt_create":"2026-04-23T20:31:50.475799+08:00","gmt_modified":"2026-04-23T20:31:50.475799+08:00"},{"id":595,"source_id":"fab60eaf-9652-4cb5-9f9e-0525caa62d63","target_id":"e68ad5186f1e47610ab3d9f14a794393","source_type":"WIKI_ITEM","target_type":"SOURCE_FILE","relationship_type":"REFERENCED_BY","extra":"Wiki references source file: backend/app/workers/platforms/tongyi.py","gmt_create":"2026-04-23T20:31:50.47602+08:00","gmt_modified":"2026-04-23T20:31:50.47602+08:00"},{"id":596,"source_id":"fab60eaf-9652-4cb5-9f9e-0525caa62d63","target_id":"42ff5383133d176cec9eb88682483be3","source_type":"WIKI_ITEM","target_type":"SOURCE_FILE","relationship_type":"REFERENCED_BY","extra":"Wiki references source file: tests/test_citations.py","gmt_create":"2026-04-23T20:31:50.476237+08:00","gmt_modified":"2026-04-23T20:31:50.476237+08:00"},{"id":597,"source_id":"fab60eaf-9652-4cb5-9f9e-0525caa62d63","target_id":"72a110dca58d8152758e2fdab4e94761","source_type":"WIKI_ITEM","target_type":"CODE_SNIPPET","relationship_type":"CONTAINS","extra":"Wiki contains code snippet: backend/app/workers/platforms/base.py#1-18","gmt_create":"2026-04-23T20:31:50.476528+08:00","gmt_modified":"2026-04-23T20:31:50.476528+08:00"},{"id":598,"source_id":"fab60eaf-9652-4cb5-9f9e-0525caa62d63","target_id":"bcfade20d923c8efa713808ca9af94ca","source_type":"WIKI_ITEM","target_type":"CODE_SNIPPET","relationship_type":"CONTAINS","extra":"Wiki contains code snippet: backend/app/workers/platforms/wenxin.py#10-38","gmt_create":"2026-04-23T20:31:50.476982+08:00","gmt_modified":"2026-04-23T20:31:50.476982+08:00"},{"id":599,"source_id":"f642fc1c2f34e15572d9d98aa6c18813","target_id":"bcfade20d923c8efa713808ca9af94ca","source_type":"SOURCE_FILE","target_type":"CODE_SNIPPET","relationship_type":"CONTAINS","extra":"Source file contains code snippet: 10-38","gmt_create":"2026-04-23T20:31:50.477216+08:00","gmt_modified":"2026-04-23T20:31:50.477216+08:00"},{"id":600,"source_id":"fab60eaf-9652-4cb5-9f9e-0525caa62d63","target_id":"ca7e1232fbba5fb75e04ab8e491bfbd1","source_type":"WIKI_ITEM","target_type":"CODE_SNIPPET","relationship_type":"CONTAINS","extra":"Wiki contains code snippet: backend/app/workers/platforms/kimi.py#10-38","gmt_create":"2026-04-23T20:31:50.477565+08:00","gmt_modified":"2026-04-23T20:31:50.477565+08:00"},{"id":601,"source_id":"8f973791233c698b3e64a4fb28a93d4b","target_id":"ca7e1232fbba5fb75e04ab8e491bfbd1","source_type":"SOURCE_FILE","target_type":"CODE_SNIPPET","relationship_type":"CONTAINS","extra":"Source file contains code snippet: 10-38","gmt_create":"2026-04-23T20:31:50.477978+08:00","gmt_modified":"2026-04-23T20:31:50.477978+08:00"},{"id":602,"source_id":"fab60eaf-9652-4cb5-9f9e-0525caa62d63","target_id":"c5ae7697193b2b93425ff25d2d7d54a9","source_type":"WIKI_ITEM","target_type":"CODE_SNIPPET","relationship_type":"CONTAINS","extra":"Wiki contains code snippet: backend/app/workers/platforms/tongyi.py#10-38","gmt_create":"2026-04-23T20:31:50.478592+08:00","gmt_modified":"2026-04-23T20:31:50.478592+08:00"},{"id":603,"source_id":"fab60eaf-9652-4cb5-9f9e-0525caa62d63","target_id":"557ae34b57a5dd8e8fa3bb2a6ce178a7","source_type":"WIKI_ITEM","target_type":"CODE_SNIPPET","relationship_type":"CONTAINS","extra":"Wiki contains code snippet: backend/app/workers/platforms/search_engine.py#163-174","gmt_create":"2026-04-23T20:31:50.479311+08:00","gmt_modified":"2026-04-23T20:31:50.479311+08:00"},{"id":604,"source_id":"fab60eaf-9652-4cb5-9f9e-0525caa62d63","target_id":"9720b93ed7247efb685e2825e5f964bf","source_type":"WIKI_ITEM","target_type":"CODE_SNIPPET","relationship_type":"CONTAINS","extra":"Wiki contains code snippet: backend/app/workers/citation_engine.py#161-176","gmt_create":"2026-04-23T20:31:50.479856+08:00","gmt_modified":"2026-04-23T20:31:50.479856+08:00"},{"id":605,"source_id":"74040de652d5e57f548bb5c4adc3e1a0","target_id":"9720b93ed7247efb685e2825e5f964bf","source_type":"SOURCE_FILE","target_type":"CODE_SNIPPET","relationship_type":"CONTAINS","extra":"Source file contains code snippet: 161-176","gmt_create":"2026-04-23T20:31:50.48037+08:00","gmt_modified":"2026-04-23T20:31:50.48037+08:00"},{"id":606,"source_id":"fab60eaf-9652-4cb5-9f9e-0525caa62d63","target_id":"0d226400124ba891a46f59c36781ccd8","source_type":"WIKI_ITEM","target_type":"CODE_SNIPPET","relationship_type":"CONTAINS","extra":"Wiki contains code snippet: backend/app/config.py#9-23","gmt_create":"2026-04-23T20:31:50.481311+08:00","gmt_modified":"2026-04-23T20:31:50.481311+08:00"},{"id":607,"source_id":"9ff19022ef915615911280e3c49ed44b","target_id":"0d226400124ba891a46f59c36781ccd8","source_type":"SOURCE_FILE","target_type":"CODE_SNIPPET","relationship_type":"CONTAINS","extra":"Source file contains code snippet: 9-23","gmt_create":"2026-04-23T20:31:50.481625+08:00","gmt_modified":"2026-04-23T20:31:50.481625+08:00"},{"id":608,"source_id":"fab60eaf-9652-4cb5-9f9e-0525caa62d63","target_id":"412695e5de2014514a8f62f98c573656","source_type":"WIKI_ITEM","target_type":"CODE_SNIPPET","relationship_type":"CONTAINS","extra":"Wiki contains code snippet: backend/Dockerfile#1-41","gmt_create":"2026-04-23T20:31:50.482236+08:00","gmt_modified":"2026-04-23T20:31:50.482236+08:00"},{"id":609,"source_id":"e9b52adbec3c07cf021e488dd3f99ab4","target_id":"412695e5de2014514a8f62f98c573656","source_type":"SOURCE_FILE","target_type":"CODE_SNIPPET","relationship_type":"CONTAINS","extra":"Source file contains code snippet: 1-41","gmt_create":"2026-04-23T20:31:50.483281+08:00","gmt_modified":"2026-04-23T20:31:50.483281+08:00"},{"id":610,"source_id":"fab60eaf-9652-4cb5-9f9e-0525caa62d63","target_id":"4fb8856be3a581fe8303d11b2284ca29","source_type":"WIKI_ITEM","target_type":"CODE_SNIPPET","relationship_type":"CONTAINS","extra":"Wiki contains code snippet: backend/app/models/query.py#11-55","gmt_create":"2026-04-23T20:31:50.483853+08:00","gmt_modified":"2026-04-23T20:31:50.483854+08:00"},{"id":611,"source_id":"fab60eaf-9652-4cb5-9f9e-0525caa62d63","target_id":"485e15eb30a5b08da38a628c9dd5053e","source_type":"WIKI_ITEM","target_type":"CODE_SNIPPET","relationship_type":"CONTAINS","extra":"Wiki contains code snippet: backend/app/workers/platforms/search_engine.py#16-77","gmt_create":"2026-04-23T20:31:50.48646+08:00","gmt_modified":"2026-04-23T20:31:50.48646+08:00"},{"id":612,"source_id":"6a63f048c16c60c5d2d57012c810ee0e","target_id":"485e15eb30a5b08da38a628c9dd5053e","source_type":"SOURCE_FILE","target_type":"CODE_SNIPPET","relationship_type":"CONTAINS","extra":"Source file contains code snippet: 16-77","gmt_create":"2026-04-23T20:31:50.486841+08:00","gmt_modified":"2026-04-23T20:31:50.486841+08:00"},{"id":613,"source_id":"fab60eaf-9652-4cb5-9f9e-0525caa62d63","target_id":"ad67863041d9eea2b0fb542b5aa33aca","source_type":"WIKI_ITEM","target_type":"CODE_SNIPPET","relationship_type":"CONTAINS","extra":"Wiki contains code snippet: backend/app/workers/platforms/base.py#4-18","gmt_create":"2026-04-23T20:31:50.487399+08:00","gmt_modified":"2026-04-23T20:31:50.487399+08:00"},{"id":614,"source_id":"fab60eaf-9652-4cb5-9f9e-0525caa62d63","target_id":"8565f299083b4dcba5a328c947f06fee","source_type":"WIKI_ITEM","target_type":"CODE_SNIPPET","relationship_type":"CONTAINS","extra":"Wiki contains code snippet: backend/app/workers/citation_engine.py#256-287","gmt_create":"2026-04-23T20:31:50.488281+08:00","gmt_modified":"2026-04-23T20:31:50.488281+08:00"},{"id":615,"source_id":"fab60eaf-9652-4cb5-9f9e-0525caa62d63","target_id":"77158a6f887e224a03552893bfec7c92","source_type":"WIKI_ITEM","target_type":"CODE_SNIPPET","relationship_type":"CONTAINS","extra":"Wiki contains code snippet: backend/app/workers/platforms/wenxin.py#16-33","gmt_create":"2026-04-23T20:31:50.488807+08:00","gmt_modified":"2026-04-23T20:31:50.488807+08:00"},{"id":616,"source_id":"f642fc1c2f34e15572d9d98aa6c18813","target_id":"77158a6f887e224a03552893bfec7c92","source_type":"SOURCE_FILE","target_type":"CODE_SNIPPET","relationship_type":"CONTAINS","extra":"Source file contains code snippet: 16-33","gmt_create":"2026-04-23T20:31:50.489038+08:00","gmt_modified":"2026-04-23T20:31:50.489038+08:00"},{"id":617,"source_id":"fab60eaf-9652-4cb5-9f9e-0525caa62d63","target_id":"5c3f336b5a7b4af4cc2f2ac183539218","source_type":"WIKI_ITEM","target_type":"CODE_SNIPPET","relationship_type":"CONTAINS","extra":"Wiki contains code snippet: backend/app/workers/platforms/search_engine.py#79-145","gmt_create":"2026-04-23T20:31:50.491706+08:00","gmt_modified":"2026-04-23T20:31:50.491706+08:00"},{"id":618,"source_id":"6a63f048c16c60c5d2d57012c810ee0e","target_id":"5c3f336b5a7b4af4cc2f2ac183539218","source_type":"SOURCE_FILE","target_type":"CODE_SNIPPET","relationship_type":"CONTAINS","extra":"Source file contains code snippet: 79-145","gmt_create":"2026-04-23T20:31:50.492445+08:00","gmt_modified":"2026-04-23T20:31:50.492445+08:00"},{"id":619,"source_id":"fab60eaf-9652-4cb5-9f9e-0525caa62d63","target_id":"3894c1ed9dca2ebf2359f40ebdb1959e","source_type":"WIKI_ITEM","target_type":"CODE_SNIPPET","relationship_type":"CONTAINS","extra":"Wiki contains code snippet: backend/app/workers/platforms/search_engine.py#147-174","gmt_create":"2026-04-23T20:31:50.493129+08:00","gmt_modified":"2026-04-23T20:31:50.493129+08:00"},{"id":620,"source_id":"6a63f048c16c60c5d2d57012c810ee0e","target_id":"3894c1ed9dca2ebf2359f40ebdb1959e","source_type":"SOURCE_FILE","target_type":"CODE_SNIPPET","relationship_type":"CONTAINS","extra":"Source file contains code snippet: 147-174","gmt_create":"2026-04-23T20:31:50.493716+08:00","gmt_modified":"2026-04-23T20:31:50.493716+08:00"},{"id":621,"source_id":"fab60eaf-9652-4cb5-9f9e-0525caa62d63","target_id":"362d22f423631cda39404660b3317a2f","source_type":"WIKI_ITEM","target_type":"CODE_SNIPPET","relationship_type":"CONTAINS","extra":"Wiki contains code snippet: backend/app/workers/citation_engine.py#177-254","gmt_create":"2026-04-23T20:31:50.494347+08:00","gmt_modified":"2026-04-23T20:31:50.494348+08:00"},{"id":622,"source_id":"fab60eaf-9652-4cb5-9f9e-0525caa62d63","target_id":"e27bcba24aaadeec1922d2b4e5b8386b","source_type":"WIKI_ITEM","target_type":"CODE_SNIPPET","relationship_type":"CONTAINS","extra":"Wiki contains code snippet: backend/app/api/queries.py#1-109","gmt_create":"2026-04-23T20:31:50.496521+08:00","gmt_modified":"2026-04-23T20:31:50.496521+08:00"},{"id":623,"source_id":"6b3d903205941aa9391dd90016e1102c","target_id":"e27bcba24aaadeec1922d2b4e5b8386b","source_type":"SOURCE_FILE","target_type":"CODE_SNIPPET","relationship_type":"CONTAINS","extra":"Source file contains code snippet: 1-109","gmt_create":"2026-04-23T20:31:50.496915+08:00","gmt_modified":"2026-04-23T20:31:50.496915+08:00"},{"id":624,"source_id":"fab60eaf-9652-4cb5-9f9e-0525caa62d63","target_id":"5f893f5078aa8e549284feb057aa45da","source_type":"WIKI_ITEM","target_type":"CODE_SNIPPET","relationship_type":"CONTAINS","extra":"Wiki contains code snippet: backend/app/workers/platforms/wenxin.py#16-29","gmt_create":"2026-04-23T20:31:50.499115+08:00","gmt_modified":"2026-04-23T20:31:50.499115+08:00"},{"id":625,"source_id":"f642fc1c2f34e15572d9d98aa6c18813","target_id":"5f893f5078aa8e549284feb057aa45da","source_type":"SOURCE_FILE","target_type":"CODE_SNIPPET","relationship_type":"CONTAINS","extra":"Source file contains code snippet: 16-29","gmt_create":"2026-04-23T20:31:50.49944+08:00","gmt_modified":"2026-04-23T20:31:50.49944+08:00"},{"id":626,"source_id":"fab60eaf-9652-4cb5-9f9e-0525caa62d63","target_id":"b55cc5936c299f819b57b899858438e6","source_type":"WIKI_ITEM","target_type":"CODE_SNIPPET","relationship_type":"CONTAINS","extra":"Wiki contains code snippet: backend/app/workers/platforms/search_engine.py#139-144","gmt_create":"2026-04-23T20:31:50.50016+08:00","gmt_modified":"2026-04-23T20:31:50.50016+08:00"},{"id":627,"source_id":"fab60eaf-9652-4cb5-9f9e-0525caa62d63","target_id":"e0b68d2d24760689a0f4f00dfee5f9f2","source_type":"WIKI_ITEM","target_type":"CODE_SNIPPET","relationship_type":"CONTAINS","extra":"Wiki contains code snippet: backend/app/workers/platforms/search_engine.py#28-76","gmt_create":"2026-04-23T20:31:50.500908+08:00","gmt_modified":"2026-04-23T20:31:50.500908+08:00"},{"id":628,"source_id":"6a63f048c16c60c5d2d57012c810ee0e","target_id":"e0b68d2d24760689a0f4f00dfee5f9f2","source_type":"SOURCE_FILE","target_type":"CODE_SNIPPET","relationship_type":"CONTAINS","extra":"Source file contains code snippet: 28-76","gmt_create":"2026-04-23T20:31:50.501388+08:00","gmt_modified":"2026-04-23T20:31:50.501388+08:00"},{"id":629,"source_id":"fab60eaf-9652-4cb5-9f9e-0525caa62d63","target_id":"e9b98ae83632342d8e06cde39e9c9462","source_type":"WIKI_ITEM","target_type":"CODE_SNIPPET","relationship_type":"CONTAINS","extra":"Wiki contains code snippet: backend/app/workers/platforms/search_engine.py#105-137","gmt_create":"2026-04-23T20:31:50.502229+08:00","gmt_modified":"2026-04-23T20:31:50.502229+08:00"},{"id":630,"source_id":"6a63f048c16c60c5d2d57012c810ee0e","target_id":"e9b98ae83632342d8e06cde39e9c9462","source_type":"SOURCE_FILE","target_type":"CODE_SNIPPET","relationship_type":"CONTAINS","extra":"Source file contains code snippet: 105-137","gmt_create":"2026-04-23T20:31:50.502758+08:00","gmt_modified":"2026-04-23T20:31:50.502758+08:00"},{"id":631,"source_id":"fab60eaf-9652-4cb5-9f9e-0525caa62d63","target_id":"f096aa3ea82e9fa625a9acb1309b4c50","source_type":"WIKI_ITEM","target_type":"CODE_SNIPPET","relationship_type":"CONTAINS","extra":"Wiki contains code snippet: backend/app/workers/citation_engine.py#231-247","gmt_create":"2026-04-23T20:31:50.503532+08:00","gmt_modified":"2026-04-23T20:31:50.503532+08:00"},{"id":632,"source_id":"fab60eaf-9652-4cb5-9f9e-0525caa62d63","target_id":"2a4f741f31f62dce8ad63be2e831f520","source_type":"WIKI_ITEM","target_type":"CODE_SNIPPET","relationship_type":"CONTAINS","extra":"Wiki contains code snippet: tests/test_citations.py#23-93","gmt_create":"2026-04-23T20:31:50.504205+08:00","gmt_modified":"2026-04-23T20:31:50.504206+08:00"},{"id":633,"source_id":"fab60eaf-9652-4cb5-9f9e-0525caa62d63","target_id":"c86edb7a95fbe4b431ac65a0e2b8636e","source_type":"WIKI_ITEM","target_type":"CODE_SNIPPET","relationship_type":"CONTAINS","extra":"Wiki contains code snippet: backend/app/api/queries.py#90-109","gmt_create":"2026-04-23T20:31:50.504719+08:00","gmt_modified":"2026-04-23T20:31:50.504719+08:00"},{"id":634,"source_id":"6b3d903205941aa9391dd90016e1102c","target_id":"c86edb7a95fbe4b431ac65a0e2b8636e","source_type":"SOURCE_FILE","target_type":"CODE_SNIPPET","relationship_type":"CONTAINS","extra":"Source file contains code snippet: 90-109","gmt_create":"2026-04-23T20:31:50.505358+08:00","gmt_modified":"2026-04-23T20:31:50.505358+08:00"},{"id":635,"source_id":"a1cc822d-5382-431c-8c49-cf398fb5eb3c","target_id":"5cbb1e3f112aeba62a14b0b8999fc0f5","source_type":"WIKI_ITEM","target_type":"SOURCE_FILE","relationship_type":"REFERENCED_BY","extra":"Wiki references source file: backend/app/workers/scheduler.py","gmt_create":"2026-04-23T20:33:30.005285+08:00","gmt_modified":"2026-04-23T20:33:30.005285+08:00"},{"id":636,"source_id":"a1cc822d-5382-431c-8c49-cf398fb5eb3c","target_id":"74040de652d5e57f548bb5c4adc3e1a0","source_type":"WIKI_ITEM","target_type":"SOURCE_FILE","relationship_type":"REFERENCED_BY","extra":"Wiki references source file: backend/app/workers/citation_engine.py","gmt_create":"2026-04-23T20:33:30.006785+08:00","gmt_modified":"2026-04-23T20:33:30.006785+08:00"},{"id":637,"source_id":"a1cc822d-5382-431c-8c49-cf398fb5eb3c","target_id":"b74caccb06844efcdb14d8324cff65c2","source_type":"WIKI_ITEM","target_type":"SOURCE_FILE","relationship_type":"REFERENCED_BY","extra":"Wiki references source file: backend/app/models/query.py","gmt_create":"2026-04-23T20:33:30.008852+08:00","gmt_modified":"2026-04-23T20:33:30.008852+08:00"},{"id":638,"source_id":"a1cc822d-5382-431c-8c49-cf398fb5eb3c","target_id":"069738f21ac2da7349d22683e8c36929","source_type":"WIKI_ITEM","target_type":"SOURCE_FILE","relationship_type":"REFERENCED_BY","extra":"Wiki references source file: backend/app/models/query_task.py","gmt_create":"2026-04-23T20:33:30.010802+08:00","gmt_modified":"2026-04-23T20:33:30.010803+08:00"},{"id":639,"source_id":"a1cc822d-5382-431c-8c49-cf398fb5eb3c","target_id":"9228ff67d4c757a85d9421b71f4b29f5","source_type":"WIKI_ITEM","target_type":"SOURCE_FILE","relationship_type":"REFERENCED_BY","extra":"Wiki references source file: backend/app/main.py","gmt_create":"2026-04-23T20:33:30.011496+08:00","gmt_modified":"2026-04-23T20:33:30.011496+08:00"},{"id":640,"source_id":"a1cc822d-5382-431c-8c49-cf398fb5eb3c","target_id":"b0c428683c8a3e6922d90ca0d8c2736d","source_type":"WIKI_ITEM","target_type":"SOURCE_FILE","relationship_type":"REFERENCED_BY","extra":"Wiki references source file: backend/app/database.py","gmt_create":"2026-04-23T20:33:30.012521+08:00","gmt_modified":"2026-04-23T20:33:30.012521+08:00"},{"id":641,"source_id":"a1cc822d-5382-431c-8c49-cf398fb5eb3c","target_id":"9ff19022ef915615911280e3c49ed44b","source_type":"WIKI_ITEM","target_type":"SOURCE_FILE","relationship_type":"REFERENCED_BY","extra":"Wiki references source file: backend/app/config.py","gmt_create":"2026-04-23T20:33:30.013288+08:00","gmt_modified":"2026-04-23T20:33:30.013288+08:00"},{"id":642,"source_id":"a1cc822d-5382-431c-8c49-cf398fb5eb3c","target_id":"8f973791233c698b3e64a4fb28a93d4b","source_type":"WIKI_ITEM","target_type":"SOURCE_FILE","relationship_type":"REFERENCED_BY","extra":"Wiki references source file: backend/app/workers/platforms/kimi.py","gmt_create":"2026-04-23T20:33:30.014048+08:00","gmt_modified":"2026-04-23T20:33:30.014048+08:00"},{"id":643,"source_id":"a1cc822d-5382-431c-8c49-cf398fb5eb3c","target_id":"f642fc1c2f34e15572d9d98aa6c18813","source_type":"WIKI_ITEM","target_type":"SOURCE_FILE","relationship_type":"REFERENCED_BY","extra":"Wiki references source file: backend/app/workers/platforms/wenxin.py","gmt_create":"2026-04-23T20:33:30.014998+08:00","gmt_modified":"2026-04-23T20:33:30.014998+08:00"},{"id":644,"source_id":"a1cc822d-5382-431c-8c49-cf398fb5eb3c","target_id":"a16cf42e9559523c4f96ca4c79f9488d","source_type":"WIKI_ITEM","target_type":"SOURCE_FILE","relationship_type":"REFERENCED_BY","extra":"Wiki references source file: backend/app/workers/platforms/base.py","gmt_create":"2026-04-23T20:33:30.015593+08:00","gmt_modified":"2026-04-23T20:33:30.015593+08:00"},{"id":645,"source_id":"a1cc822d-5382-431c-8c49-cf398fb5eb3c","target_id":"7538ffe4902ab6041adb28b19844962a","source_type":"WIKI_ITEM","target_type":"SOURCE_FILE","relationship_type":"REFERENCED_BY","extra":"Wiki references source file: backend/app/api/citations.py","gmt_create":"2026-04-23T20:33:30.016186+08:00","gmt_modified":"2026-04-23T20:33:30.016187+08:00"},{"id":646,"source_id":"a1cc822d-5382-431c-8c49-cf398fb5eb3c","target_id":"88d22de3b2a7419868e8ae19130d860c","source_type":"WIKI_ITEM","target_type":"SOURCE_FILE","relationship_type":"REFERENCED_BY","extra":"Wiki references source file: backend/app/services/query.py","gmt_create":"2026-04-23T20:33:30.017118+08:00","gmt_modified":"2026-04-23T20:33:30.017118+08:00"},{"id":647,"source_id":"a1cc822d-5382-431c-8c49-cf398fb5eb3c","target_id":"b2f0d46a31a5441594f2e777365fc156","source_type":"WIKI_ITEM","target_type":"SOURCE_FILE","relationship_type":"REFERENCED_BY","extra":"Wiki references source file: tests/test_scheduler.py","gmt_create":"2026-04-23T20:33:30.017481+08:00","gmt_modified":"2026-04-23T20:33:30.017481+08:00"},{"id":648,"source_id":"a1cc822d-5382-431c-8c49-cf398fb5eb3c","target_id":"096856da621e23e78422a15e2bfce1f1","source_type":"WIKI_ITEM","target_type":"CODE_SNIPPET","relationship_type":"CONTAINS","extra":"Wiki contains code snippet: backend/app/main.py#13-22","gmt_create":"2026-04-23T20:33:30.018279+08:00","gmt_modified":"2026-04-23T20:33:30.018279+08:00"},{"id":649,"source_id":"a1cc822d-5382-431c-8c49-cf398fb5eb3c","target_id":"e230904202fcf7a861c6f49b84f9f863","source_type":"WIKI_ITEM","target_type":"CODE_SNIPPET","relationship_type":"CONTAINS","extra":"Wiki contains code snippet: backend/app/workers/scheduler.py#25-95","gmt_create":"2026-04-23T20:33:30.019076+08:00","gmt_modified":"2026-04-23T20:33:30.019076+08:00"},{"id":650,"source_id":"a1cc822d-5382-431c-8c49-cf398fb5eb3c","target_id":"309607c54b12a6340edc086ffb4737c9","source_type":"WIKI_ITEM","target_type":"CODE_SNIPPET","relationship_type":"CONTAINS","extra":"Wiki contains code snippet: backend/app/workers/citation_engine.py#148-309","gmt_create":"2026-04-23T20:33:30.020384+08:00","gmt_modified":"2026-04-23T20:33:30.020384+08:00"},{"id":651,"source_id":"a1cc822d-5382-431c-8c49-cf398fb5eb3c","target_id":"6e054d9a78c0c8c9da8dec4c4bda62ab","source_type":"WIKI_ITEM","target_type":"CODE_SNIPPET","relationship_type":"CONTAINS","extra":"Wiki contains code snippet: backend/app/database.py#6-28","gmt_create":"2026-04-23T20:33:30.021894+08:00","gmt_modified":"2026-04-23T20:33:30.021895+08:00"},{"id":652,"source_id":"b0c428683c8a3e6922d90ca0d8c2736d","target_id":"6e054d9a78c0c8c9da8dec4c4bda62ab","source_type":"SOURCE_FILE","target_type":"CODE_SNIPPET","relationship_type":"CONTAINS","extra":"Source file contains code snippet: 6-28","gmt_create":"2026-04-23T20:33:30.022319+08:00","gmt_modified":"2026-04-23T20:33:30.022319+08:00"},{"id":653,"source_id":"a1cc822d-5382-431c-8c49-cf398fb5eb3c","target_id":"4fb8856be3a581fe8303d11b2284ca29","source_type":"WIKI_ITEM","target_type":"CODE_SNIPPET","relationship_type":"CONTAINS","extra":"Wiki contains code snippet: backend/app/models/query.py#11-55","gmt_create":"2026-04-23T20:33:30.039084+08:00","gmt_modified":"2026-04-23T20:33:30.039085+08:00"},{"id":654,"source_id":"a1cc822d-5382-431c-8c49-cf398fb5eb3c","target_id":"c2747ca16b879bca0f68955534c3c4fc","source_type":"WIKI_ITEM","target_type":"CODE_SNIPPET","relationship_type":"CONTAINS","extra":"Wiki contains code snippet: backend/app/main.py#1-48","gmt_create":"2026-04-23T20:33:30.042279+08:00","gmt_modified":"2026-04-23T20:33:30.042279+08:00"},{"id":655,"source_id":"a1cc822d-5382-431c-8c49-cf398fb5eb3c","target_id":"71f98c8993fb42b108e34a554247869b","source_type":"WIKI_ITEM","target_type":"CODE_SNIPPET","relationship_type":"CONTAINS","extra":"Wiki contains code snippet: backend/app/workers/scheduler.py#1-95","gmt_create":"2026-04-23T20:33:30.043781+08:00","gmt_modified":"2026-04-23T20:33:30.043781+08:00"},{"id":656,"source_id":"a1cc822d-5382-431c-8c49-cf398fb5eb3c","target_id":"9bfc041fe426da2eb78353827e8d9163","source_type":"WIKI_ITEM","target_type":"CODE_SNIPPET","relationship_type":"CONTAINS","extra":"Wiki contains code snippet: backend/app/database.py#1-29","gmt_create":"2026-04-23T20:33:30.048591+08:00","gmt_modified":"2026-04-23T20:33:30.048591+08:00"},{"id":657,"source_id":"a1cc822d-5382-431c-8c49-cf398fb5eb3c","target_id":"6281fff17a86ec1895c64d87c2ae7fb1","source_type":"WIKI_ITEM","target_type":"CODE_SNIPPET","relationship_type":"CONTAINS","extra":"Wiki contains code snippet: backend/app/models/query.py#1-55","gmt_create":"2026-04-23T20:33:30.049875+08:00","gmt_modified":"2026-04-23T20:33:30.049875+08:00"},{"id":658,"source_id":"a1cc822d-5382-431c-8c49-cf398fb5eb3c","target_id":"eecf9581dbaa0a515cf11514175e7ef9","source_type":"WIKI_ITEM","target_type":"CODE_SNIPPET","relationship_type":"CONTAINS","extra":"Wiki contains code snippet: backend/app/workers/platforms/kimi.py#11-206","gmt_create":"2026-04-23T20:33:30.052505+08:00","gmt_modified":"2026-04-23T20:33:30.052505+08:00"},{"id":659,"source_id":"a1cc822d-5382-431c-8c49-cf398fb5eb3c","target_id":"5563c29185326a59be61ee0a6eec4463","source_type":"WIKI_ITEM","target_type":"CODE_SNIPPET","relationship_type":"CONTAINS","extra":"Wiki contains code snippet: backend/app/workers/platforms/wenxin.py#11-205","gmt_create":"2026-04-23T20:33:30.054452+08:00","gmt_modified":"2026-04-23T20:33:30.054452+08:00"},{"id":660,"source_id":"a1cc822d-5382-431c-8c49-cf398fb5eb3c","target_id":"9c16a069e5154660bfdfa48f3518fc6a","source_type":"WIKI_ITEM","target_type":"CODE_SNIPPET","relationship_type":"CONTAINS","extra":"Wiki contains code snippet: backend/app/models/query_task.py#11-38","gmt_create":"2026-04-23T20:33:30.056033+08:00","gmt_modified":"2026-04-23T20:33:30.056033+08:00"},{"id":661,"source_id":"069738f21ac2da7349d22683e8c36929","target_id":"9c16a069e5154660bfdfa48f3518fc6a","source_type":"SOURCE_FILE","target_type":"CODE_SNIPPET","relationship_type":"CONTAINS","extra":"Source file contains code snippet: 11-38","gmt_create":"2026-04-23T20:33:30.056759+08:00","gmt_modified":"2026-04-23T20:33:30.056759+08:00"},{"id":662,"source_id":"a1cc822d-5382-431c-8c49-cf398fb5eb3c","target_id":"2d35e1345d25020f8e7ac1318db06f7b","source_type":"WIKI_ITEM","target_type":"CODE_SNIPPET","relationship_type":"CONTAINS","extra":"Wiki contains code snippet: backend/app/workers/scheduler.py#30-90","gmt_create":"2026-04-23T20:33:30.060127+08:00","gmt_modified":"2026-04-23T20:33:30.060127+08:00"},{"id":663,"source_id":"a1cc822d-5382-431c-8c49-cf398fb5eb3c","target_id":"160b5326537d25444c40a459a01e79c6","source_type":"WIKI_ITEM","target_type":"CODE_SNIPPET","relationship_type":"CONTAINS","extra":"Wiki contains code snippet: backend/app/workers/citation_engine.py#159-234","gmt_create":"2026-04-23T20:33:30.06165+08:00","gmt_modified":"2026-04-23T20:33:30.06165+08:00"},{"id":664,"source_id":"a1cc822d-5382-431c-8c49-cf398fb5eb3c","target_id":"a4918fcbd21492ad996d7f5496f03a4b","source_type":"WIKI_ITEM","target_type":"CODE_SNIPPET","relationship_type":"CONTAINS","extra":"Wiki contains code snippet: backend/app/workers/platforms/kimi.py#33-48","gmt_create":"2026-04-23T20:33:30.063084+08:00","gmt_modified":"2026-04-23T20:33:30.063084+08:00"},{"id":665,"source_id":"8f973791233c698b3e64a4fb28a93d4b","target_id":"a4918fcbd21492ad996d7f5496f03a4b","source_type":"SOURCE_FILE","target_type":"CODE_SNIPPET","relationship_type":"CONTAINS","extra":"Source file contains code snippet: 33-48","gmt_create":"2026-04-23T20:33:30.063941+08:00","gmt_modified":"2026-04-23T20:33:30.063941+08:00"},{"id":666,"source_id":"a1cc822d-5382-431c-8c49-cf398fb5eb3c","target_id":"bc38d046b4b1410ae2165cee2272839e","source_type":"WIKI_ITEM","target_type":"CODE_SNIPPET","relationship_type":"CONTAINS","extra":"Wiki contains code snippet: backend/app/workers/platforms/wenxin.py#33-48","gmt_create":"2026-04-23T20:33:30.065013+08:00","gmt_modified":"2026-04-23T20:33:30.065013+08:00"},{"id":667,"source_id":"f642fc1c2f34e15572d9d98aa6c18813","target_id":"bc38d046b4b1410ae2165cee2272839e","source_type":"SOURCE_FILE","target_type":"CODE_SNIPPET","relationship_type":"CONTAINS","extra":"Source file contains code snippet: 33-48","gmt_create":"2026-04-23T20:33:30.066091+08:00","gmt_modified":"2026-04-23T20:33:30.066091+08:00"},{"id":668,"source_id":"a1cc822d-5382-431c-8c49-cf398fb5eb3c","target_id":"72f6d334026866e8a61d2ffb1d83370a","source_type":"WIKI_ITEM","target_type":"CODE_SNIPPET","relationship_type":"CONTAINS","extra":"Wiki contains code snippet: backend/app/workers/citation_engine.py#19-100","gmt_create":"2026-04-23T20:33:30.06977+08:00","gmt_modified":"2026-04-23T20:33:30.06977+08:00"},{"id":669,"source_id":"74040de652d5e57f548bb5c4adc3e1a0","target_id":"72f6d334026866e8a61d2ffb1d83370a","source_type":"SOURCE_FILE","target_type":"CODE_SNIPPET","relationship_type":"CONTAINS","extra":"Source file contains code snippet: 19-100","gmt_create":"2026-04-23T20:33:30.070839+08:00","gmt_modified":"2026-04-23T20:33:30.070839+08:00"},{"id":670,"source_id":"a1cc822d-5382-431c-8c49-cf398fb5eb3c","target_id":"5c67e2f70283956b2d29a3c1443eb514","source_type":"WIKI_ITEM","target_type":"CODE_SNIPPET","relationship_type":"CONTAINS","extra":"Wiki contains code snippet: backend/app/workers/citation_engine.py#122-146","gmt_create":"2026-04-23T20:33:30.07226+08:00","gmt_modified":"2026-04-23T20:33:30.07226+08:00"},{"id":671,"source_id":"a1cc822d-5382-431c-8c49-cf398fb5eb3c","target_id":"ad67863041d9eea2b0fb542b5aa33aca","source_type":"WIKI_ITEM","target_type":"CODE_SNIPPET","relationship_type":"CONTAINS","extra":"Wiki contains code snippet: backend/app/workers/platforms/base.py#4-18","gmt_create":"2026-04-23T20:33:30.076075+08:00","gmt_modified":"2026-04-23T20:33:30.076076+08:00"},{"id":672,"source_id":"a1cc822d-5382-431c-8c49-cf398fb5eb3c","target_id":"1e85186eded8743ff5f231df4aa6df3f","source_type":"WIKI_ITEM","target_type":"CODE_SNIPPET","relationship_type":"CONTAINS","extra":"Wiki contains code snippet: backend/app/workers/platforms/kimi.py#21-48","gmt_create":"2026-04-23T20:33:30.080882+08:00","gmt_modified":"2026-04-23T20:33:30.080882+08:00"},{"id":673,"source_id":"a1cc822d-5382-431c-8c49-cf398fb5eb3c","target_id":"1d84b9a7eb013882953a2d1d948299e4","source_type":"WIKI_ITEM","target_type":"CODE_SNIPPET","relationship_type":"CONTAINS","extra":"Wiki contains code snippet: backend/app/workers/platforms/kimi.py#126-197","gmt_create":"2026-04-23T20:33:30.082996+08:00","gmt_modified":"2026-04-23T20:33:30.082997+08:00"},{"id":674,"source_id":"8f973791233c698b3e64a4fb28a93d4b","target_id":"1d84b9a7eb013882953a2d1d948299e4","source_type":"SOURCE_FILE","target_type":"CODE_SNIPPET","relationship_type":"CONTAINS","extra":"Source file contains code snippet: 126-197","gmt_create":"2026-04-23T20:33:30.084021+08:00","gmt_modified":"2026-04-23T20:33:30.084021+08:00"},{"id":675,"source_id":"a1cc822d-5382-431c-8c49-cf398fb5eb3c","target_id":"e2b1718570fb714b2f4342221898ab30","source_type":"WIKI_ITEM","target_type":"CODE_SNIPPET","relationship_type":"CONTAINS","extra":"Wiki contains code snippet: backend/app/workers/platforms/wenxin.py#21-48","gmt_create":"2026-04-23T20:33:30.08518+08:00","gmt_modified":"2026-04-23T20:33:30.085181+08:00"},{"id":676,"source_id":"a1cc822d-5382-431c-8c49-cf398fb5eb3c","target_id":"ba687f2c64aff92b3906658359ed953a","source_type":"WIKI_ITEM","target_type":"CODE_SNIPPET","relationship_type":"CONTAINS","extra":"Wiki contains code snippet: backend/app/workers/platforms/wenxin.py#124-195","gmt_create":"2026-04-23T20:33:30.086912+08:00","gmt_modified":"2026-04-23T20:33:30.086913+08:00"},{"id":677,"source_id":"f642fc1c2f34e15572d9d98aa6c18813","target_id":"ba687f2c64aff92b3906658359ed953a","source_type":"SOURCE_FILE","target_type":"CODE_SNIPPET","relationship_type":"CONTAINS","extra":"Source file contains code snippet: 124-195","gmt_create":"2026-04-23T20:33:30.087917+08:00","gmt_modified":"2026-04-23T20:33:30.087917+08:00"},{"id":678,"source_id":"a1cc822d-5382-431c-8c49-cf398fb5eb3c","target_id":"52ee729b02c992c689522c7956c14128","source_type":"WIKI_ITEM","target_type":"CODE_SNIPPET","relationship_type":"CONTAINS","extra":"Wiki contains code snippet: backend/app/workers/scheduler.py#57-62","gmt_create":"2026-04-23T20:33:30.090606+08:00","gmt_modified":"2026-04-23T20:33:30.090606+08:00"},{"id":679,"source_id":"5cbb1e3f112aeba62a14b0b8999fc0f5","target_id":"52ee729b02c992c689522c7956c14128","source_type":"SOURCE_FILE","target_type":"CODE_SNIPPET","relationship_type":"CONTAINS","extra":"Source file contains code snippet: 57-62","gmt_create":"2026-04-23T20:33:30.092747+08:00","gmt_modified":"2026-04-23T20:33:30.092747+08:00"},{"id":680,"source_id":"a1cc822d-5382-431c-8c49-cf398fb5eb3c","target_id":"c9e32b7324cce60c8887deb8404ee759","source_type":"WIKI_ITEM","target_type":"CODE_SNIPPET","relationship_type":"CONTAINS","extra":"Wiki contains code snippet: backend/app/workers/scheduler.py#107-112","gmt_create":"2026-04-23T20:33:30.094246+08:00","gmt_modified":"2026-04-23T20:33:30.094246+08:00"},{"id":681,"source_id":"5cbb1e3f112aeba62a14b0b8999fc0f5","target_id":"c9e32b7324cce60c8887deb8404ee759","source_type":"SOURCE_FILE","target_type":"CODE_SNIPPET","relationship_type":"CONTAINS","extra":"Source file contains code snippet: 107-112","gmt_create":"2026-04-23T20:33:30.095189+08:00","gmt_modified":"2026-04-23T20:33:30.095189+08:00"},{"id":682,"source_id":"a1cc822d-5382-431c-8c49-cf398fb5eb3c","target_id":"212d822d207a4c0bd7825bbf20e188e9","source_type":"WIKI_ITEM","target_type":"CODE_SNIPPET","relationship_type":"CONTAINS","extra":"Wiki contains code snippet: backend/app/api/citations.py#59-77","gmt_create":"2026-04-23T20:33:30.096673+08:00","gmt_modified":"2026-04-23T20:33:30.096673+08:00"},{"id":683,"source_id":"a1cc822d-5382-431c-8c49-cf398fb5eb3c","target_id":"8355d3821337334caee57a75dc8c8865","source_type":"WIKI_ITEM","target_type":"CODE_SNIPPET","relationship_type":"CONTAINS","extra":"Wiki contains code snippet: backend/app/services/query.py#116-130","gmt_create":"2026-04-23T20:33:30.098422+08:00","gmt_modified":"2026-04-23T20:33:30.098422+08:00"},{"id":684,"source_id":"88d22de3b2a7419868e8ae19130d860c","target_id":"8355d3821337334caee57a75dc8c8865","source_type":"SOURCE_FILE","target_type":"CODE_SNIPPET","relationship_type":"CONTAINS","extra":"Source file contains code snippet: 116-130","gmt_create":"2026-04-23T20:33:30.099427+08:00","gmt_modified":"2026-04-23T20:33:30.099427+08:00"},{"id":685,"source_id":"a1cc822d-5382-431c-8c49-cf398fb5eb3c","target_id":"4fe27d4d1323b500e72d870aa6212a1a","source_type":"WIKI_ITEM","target_type":"CODE_SNIPPET","relationship_type":"CONTAINS","extra":"Wiki contains code snippet: backend/app/workers/scheduler.py#13-20","gmt_create":"2026-04-23T20:33:30.101771+08:00","gmt_modified":"2026-04-23T20:33:30.101771+08:00"},{"id":686,"source_id":"5cbb1e3f112aeba62a14b0b8999fc0f5","target_id":"4fe27d4d1323b500e72d870aa6212a1a","source_type":"SOURCE_FILE","target_type":"CODE_SNIPPET","relationship_type":"CONTAINS","extra":"Source file contains code snippet: 13-20","gmt_create":"2026-04-23T20:33:30.102515+08:00","gmt_modified":"2026-04-23T20:33:30.102515+08:00"},{"id":687,"source_id":"a1cc822d-5382-431c-8c49-cf398fb5eb3c","target_id":"3729543092bccad8926c5ea852db1e69","source_type":"WIKI_ITEM","target_type":"CODE_SNIPPET","relationship_type":"CONTAINS","extra":"Wiki contains code snippet: backend/app/workers/citation_engine.py#148-157","gmt_create":"2026-04-23T20:33:30.103598+08:00","gmt_modified":"2026-04-23T20:33:30.103599+08:00"},{"id":688,"source_id":"74040de652d5e57f548bb5c4adc3e1a0","target_id":"3729543092bccad8926c5ea852db1e69","source_type":"SOURCE_FILE","target_type":"CODE_SNIPPET","relationship_type":"CONTAINS","extra":"Source file contains code snippet: 148-157","gmt_create":"2026-04-23T20:33:30.104105+08:00","gmt_modified":"2026-04-23T20:33:30.104105+08:00"},{"id":689,"source_id":"a1cc822d-5382-431c-8c49-cf398fb5eb3c","target_id":"1ee5153c867fc6e9d277a3067963a1fc","source_type":"WIKI_ITEM","target_type":"CODE_SNIPPET","relationship_type":"CONTAINS","extra":"Wiki contains code snippet: backend/app/workers/scheduler.py#32-38","gmt_create":"2026-04-23T20:33:30.105113+08:00","gmt_modified":"2026-04-23T20:33:30.105113+08:00"},{"id":690,"source_id":"5cbb1e3f112aeba62a14b0b8999fc0f5","target_id":"1ee5153c867fc6e9d277a3067963a1fc","source_type":"SOURCE_FILE","target_type":"CODE_SNIPPET","relationship_type":"CONTAINS","extra":"Source file contains code snippet: 32-38","gmt_create":"2026-04-23T20:33:30.105627+08:00","gmt_modified":"2026-04-23T20:33:30.105627+08:00"},{"id":691,"source_id":"a1cc822d-5382-431c-8c49-cf398fb5eb3c","target_id":"ed527c7a549ec333c2b30b59614343df","source_type":"WIKI_ITEM","target_type":"CODE_SNIPPET","relationship_type":"CONTAINS","extra":"Wiki contains code snippet: backend/app/models/query.py#50-54","gmt_create":"2026-04-23T20:33:30.106672+08:00","gmt_modified":"2026-04-23T20:33:30.106672+08:00"},{"id":692,"source_id":"b74caccb06844efcdb14d8324cff65c2","target_id":"ed527c7a549ec333c2b30b59614343df","source_type":"SOURCE_FILE","target_type":"CODE_SNIPPET","relationship_type":"CONTAINS","extra":"Source file contains code snippet: 50-54","gmt_create":"2026-04-23T20:33:30.107651+08:00","gmt_modified":"2026-04-23T20:33:30.107651+08:00"},{"id":693,"source_id":"a1cc822d-5382-431c-8c49-cf398fb5eb3c","target_id":"f6c9f1b4e8646c366a31426a4537675d","source_type":"WIKI_ITEM","target_type":"CODE_SNIPPET","relationship_type":"CONTAINS","extra":"Wiki contains code snippet: backend/app/models/query_task.py#36-38","gmt_create":"2026-04-23T20:33:30.109238+08:00","gmt_modified":"2026-04-23T20:33:30.109238+08:00"},{"id":694,"source_id":"a1cc822d-5382-431c-8c49-cf398fb5eb3c","target_id":"1a3351698ecc7cd4e508b7a792804fc4","source_type":"WIKI_ITEM","target_type":"CODE_SNIPPET","relationship_type":"CONTAINS","extra":"Wiki contains code snippet: backend/app/workers/citation_engine.py#302-309","gmt_create":"2026-04-23T20:33:30.111966+08:00","gmt_modified":"2026-04-23T20:33:30.111966+08:00"},{"id":695,"source_id":"74040de652d5e57f548bb5c4adc3e1a0","target_id":"1a3351698ecc7cd4e508b7a792804fc4","source_type":"SOURCE_FILE","target_type":"CODE_SNIPPET","relationship_type":"CONTAINS","extra":"Source file contains code snippet: 302-309","gmt_create":"2026-04-23T20:33:30.112959+08:00","gmt_modified":"2026-04-23T20:33:30.11296+08:00"},{"id":696,"source_id":"a1cc822d-5382-431c-8c49-cf398fb5eb3c","target_id":"e3e9710c7eead933c936519395f792e0","source_type":"WIKI_ITEM","target_type":"CODE_SNIPPET","relationship_type":"CONTAINS","extra":"Wiki contains code snippet: backend/app/workers/scheduler.py#44-49","gmt_create":"2026-04-23T20:33:30.114604+08:00","gmt_modified":"2026-04-23T20:33:30.114605+08:00"},{"id":697,"source_id":"5cbb1e3f112aeba62a14b0b8999fc0f5","target_id":"e3e9710c7eead933c936519395f792e0","source_type":"SOURCE_FILE","target_type":"CODE_SNIPPET","relationship_type":"CONTAINS","extra":"Source file contains code snippet: 44-49","gmt_create":"2026-04-23T20:33:30.115247+08:00","gmt_modified":"2026-04-23T20:33:30.115247+08:00"},{"id":698,"source_id":"a1cc822d-5382-431c-8c49-cf398fb5eb3c","target_id":"d20fc729a5d3986b1c077f9e07ece9c4","source_type":"WIKI_ITEM","target_type":"CODE_SNIPPET","relationship_type":"CONTAINS","extra":"Wiki contains code snippet: backend/app/config.py#7","gmt_create":"2026-04-23T20:33:30.116587+08:00","gmt_modified":"2026-04-23T20:33:30.116587+08:00"},{"id":699,"source_id":"a1cc822d-5382-431c-8c49-cf398fb5eb3c","target_id":"a4143cc29b14f1f5bc75a5e021690666","source_type":"WIKI_ITEM","target_type":"CODE_SNIPPET","relationship_type":"CONTAINS","extra":"Wiki contains code snippet: backend/app/workers/platforms/kimi.py#23-31","gmt_create":"2026-04-23T20:33:30.117646+08:00","gmt_modified":"2026-04-23T20:33:30.117646+08:00"},{"id":700,"source_id":"8f973791233c698b3e64a4fb28a93d4b","target_id":"a4143cc29b14f1f5bc75a5e021690666","source_type":"SOURCE_FILE","target_type":"CODE_SNIPPET","relationship_type":"CONTAINS","extra":"Source file contains code snippet: 23-31","gmt_create":"2026-04-23T20:33:30.118764+08:00","gmt_modified":"2026-04-23T20:33:30.118764+08:00"},{"id":701,"source_id":"a1cc822d-5382-431c-8c49-cf398fb5eb3c","target_id":"7192cfda5508e7587efd91d26cf1f018","source_type":"WIKI_ITEM","target_type":"CODE_SNIPPET","relationship_type":"CONTAINS","extra":"Wiki contains code snippet: backend/app/workers/platforms/wenxin.py#23-31","gmt_create":"2026-04-23T20:33:30.120253+08:00","gmt_modified":"2026-04-23T20:33:30.120253+08:00"},{"id":702,"source_id":"f642fc1c2f34e15572d9d98aa6c18813","target_id":"7192cfda5508e7587efd91d26cf1f018","source_type":"SOURCE_FILE","target_type":"CODE_SNIPPET","relationship_type":"CONTAINS","extra":"Source file contains code snippet: 23-31","gmt_create":"2026-04-23T20:33:30.121853+08:00","gmt_modified":"2026-04-23T20:33:30.121853+08:00"},{"id":703,"source_id":"a1cc822d-5382-431c-8c49-cf398fb5eb3c","target_id":"38142b7d7016c5590e638fafcdcb1a19","source_type":"WIKI_ITEM","target_type":"CODE_SNIPPET","relationship_type":"CONTAINS","extra":"Wiki contains code snippet: backend/app/workers/citation_engine.py#211-227","gmt_create":"2026-04-23T20:33:30.1234+08:00","gmt_modified":"2026-04-23T20:33:30.1234+08:00"},{"id":704,"source_id":"74040de652d5e57f548bb5c4adc3e1a0","target_id":"38142b7d7016c5590e638fafcdcb1a19","source_type":"SOURCE_FILE","target_type":"CODE_SNIPPET","relationship_type":"CONTAINS","extra":"Source file contains code snippet: 211-227","gmt_create":"2026-04-23T20:33:30.125433+08:00","gmt_modified":"2026-04-23T20:33:30.125433+08:00"},{"id":705,"source_id":"a1cc822d-5382-431c-8c49-cf398fb5eb3c","target_id":"fb5276346dcc4e7044d8765a8572e7a8","source_type":"WIKI_ITEM","target_type":"CODE_SNIPPET","relationship_type":"CONTAINS","extra":"Wiki contains code snippet: backend/app/config.py#4-16","gmt_create":"2026-04-23T20:33:30.128657+08:00","gmt_modified":"2026-04-23T20:33:30.128657+08:00"},{"id":706,"source_id":"9ff19022ef915615911280e3c49ed44b","target_id":"fb5276346dcc4e7044d8765a8572e7a8","source_type":"SOURCE_FILE","target_type":"CODE_SNIPPET","relationship_type":"CONTAINS","extra":"Source file contains code snippet: 4-16","gmt_create":"2026-04-23T20:33:30.129814+08:00","gmt_modified":"2026-04-23T20:33:30.129814+08:00"},{"id":707,"source_id":"19e75845-5147-4aeb-90be-16f3aa270465","target_id":"74040de652d5e57f548bb5c4adc3e1a0","source_type":"WIKI_ITEM","target_type":"SOURCE_FILE","relationship_type":"REFERENCED_BY","extra":"Wiki references source file: backend/app/workers/citation_engine.py","gmt_create":"2026-04-23T20:33:37.259749+08:00","gmt_modified":"2026-04-23T20:33:37.259749+08:00"},{"id":708,"source_id":"19e75845-5147-4aeb-90be-16f3aa270465","target_id":"a16cf42e9559523c4f96ca4c79f9488d","source_type":"WIKI_ITEM","target_type":"SOURCE_FILE","relationship_type":"REFERENCED_BY","extra":"Wiki references source file: backend/app/workers/platforms/base.py","gmt_create":"2026-04-23T20:33:37.26107+08:00","gmt_modified":"2026-04-23T20:33:37.26107+08:00"},{"id":709,"source_id":"19e75845-5147-4aeb-90be-16f3aa270465","target_id":"8f973791233c698b3e64a4fb28a93d4b","source_type":"WIKI_ITEM","target_type":"SOURCE_FILE","relationship_type":"REFERENCED_BY","extra":"Wiki references source file: backend/app/workers/platforms/kimi.py","gmt_create":"2026-04-23T20:33:37.261714+08:00","gmt_modified":"2026-04-23T20:33:37.261714+08:00"},{"id":710,"source_id":"19e75845-5147-4aeb-90be-16f3aa270465","target_id":"f642fc1c2f34e15572d9d98aa6c18813","source_type":"WIKI_ITEM","target_type":"SOURCE_FILE","relationship_type":"REFERENCED_BY","extra":"Wiki references source file: backend/app/workers/platforms/wenxin.py","gmt_create":"2026-04-23T20:33:37.262532+08:00","gmt_modified":"2026-04-23T20:33:37.262532+08:00"},{"id":711,"source_id":"19e75845-5147-4aeb-90be-16f3aa270465","target_id":"e68ad5186f1e47610ab3d9f14a794393","source_type":"WIKI_ITEM","target_type":"SOURCE_FILE","relationship_type":"REFERENCED_BY","extra":"Wiki references source file: backend/app/workers/platforms/tongyi.py","gmt_create":"2026-04-23T20:33:37.263665+08:00","gmt_modified":"2026-04-23T20:33:37.263665+08:00"},{"id":712,"source_id":"19e75845-5147-4aeb-90be-16f3aa270465","target_id":"404f6d0765a8c6e77e33b7fc21b377a4","source_type":"WIKI_ITEM","target_type":"SOURCE_FILE","relationship_type":"REFERENCED_BY","extra":"Wiki references source file: backend/app/workers/platforms/doubao.py","gmt_create":"2026-04-23T20:33:37.26425+08:00","gmt_modified":"2026-04-23T20:33:37.26425+08:00"},{"id":713,"source_id":"19e75845-5147-4aeb-90be-16f3aa270465","target_id":"303e80519e946904d1cb3ac32cbb0814","source_type":"WIKI_ITEM","target_type":"SOURCE_FILE","relationship_type":"REFERENCED_BY","extra":"Wiki references source file: backend/app/workers/platforms/qingyan.py","gmt_create":"2026-04-23T20:33:37.265278+08:00","gmt_modified":"2026-04-23T20:33:37.265278+08:00"},{"id":714,"source_id":"19e75845-5147-4aeb-90be-16f3aa270465","target_id":"5af7301fe056fc3d10820d820e8ad777","source_type":"WIKI_ITEM","target_type":"SOURCE_FILE","relationship_type":"REFERENCED_BY","extra":"Wiki references source file: backend/app/workers/platforms/tiangong.py","gmt_create":"2026-04-23T20:33:37.265809+08:00","gmt_modified":"2026-04-23T20:33:37.265809+08:00"},{"id":715,"source_id":"19e75845-5147-4aeb-90be-16f3aa270465","target_id":"0e38ad5d2d3daaad08c9302df8805b15","source_type":"WIKI_ITEM","target_type":"SOURCE_FILE","relationship_type":"REFERENCED_BY","extra":"Wiki references source file: backend/app/workers/platforms/xinghuo.py","gmt_create":"2026-04-23T20:33:37.266496+08:00","gmt_modified":"2026-04-23T20:33:37.266496+08:00"},{"id":716,"source_id":"19e75845-5147-4aeb-90be-16f3aa270465","target_id":"6a63f048c16c60c5d2d57012c810ee0e","source_type":"WIKI_ITEM","target_type":"SOURCE_FILE","relationship_type":"REFERENCED_BY","extra":"Wiki references source file: backend/app/workers/platforms/search_engine.py","gmt_create":"2026-04-23T20:33:37.267203+08:00","gmt_modified":"2026-04-23T20:33:37.267203+08:00"},{"id":717,"source_id":"19e75845-5147-4aeb-90be-16f3aa270465","target_id":"5cbb1e3f112aeba62a14b0b8999fc0f5","source_type":"WIKI_ITEM","target_type":"SOURCE_FILE","relationship_type":"REFERENCED_BY","extra":"Wiki references source file: backend/app/workers/scheduler.py","gmt_create":"2026-04-23T20:33:37.268722+08:00","gmt_modified":"2026-04-23T20:33:37.268722+08:00"},{"id":718,"source_id":"19e75845-5147-4aeb-90be-16f3aa270465","target_id":"04e3926c080e795713bff683e7dc9d3e","source_type":"WIKI_ITEM","target_type":"SOURCE_FILE","relationship_type":"REFERENCED_BY","extra":"Wiki references source file: backend/app/services/citation.py","gmt_create":"2026-04-23T20:33:37.269288+08:00","gmt_modified":"2026-04-23T20:33:37.269288+08:00"},{"id":719,"source_id":"19e75845-5147-4aeb-90be-16f3aa270465","target_id":"7538ffe4902ab6041adb28b19844962a","source_type":"WIKI_ITEM","target_type":"SOURCE_FILE","relationship_type":"REFERENCED_BY","extra":"Wiki references source file: backend/app/api/citations.py","gmt_create":"2026-04-23T20:33:37.270139+08:00","gmt_modified":"2026-04-23T20:33:37.270139+08:00"},{"id":720,"source_id":"19e75845-5147-4aeb-90be-16f3aa270465","target_id":"b4a81ef789630d0af6a8d50859d01bf3","source_type":"WIKI_ITEM","target_type":"SOURCE_FILE","relationship_type":"REFERENCED_BY","extra":"Wiki references source file: backend/app/models/citation_record.py","gmt_create":"2026-04-23T20:33:37.273632+08:00","gmt_modified":"2026-04-23T20:33:37.273632+08:00"},{"id":721,"source_id":"19e75845-5147-4aeb-90be-16f3aa270465","target_id":"b74caccb06844efcdb14d8324cff65c2","source_type":"WIKI_ITEM","target_type":"SOURCE_FILE","relationship_type":"REFERENCED_BY","extra":"Wiki references source file: backend/app/models/query.py","gmt_create":"2026-04-23T20:33:37.275218+08:00","gmt_modified":"2026-04-23T20:33:37.275218+08:00"},{"id":722,"source_id":"19e75845-5147-4aeb-90be-16f3aa270465","target_id":"069738f21ac2da7349d22683e8c36929","source_type":"WIKI_ITEM","target_type":"SOURCE_FILE","relationship_type":"REFERENCED_BY","extra":"Wiki references source file: backend/app/models/query_task.py","gmt_create":"2026-04-23T20:33:37.276269+08:00","gmt_modified":"2026-04-23T20:33:37.27627+08:00"},{"id":723,"source_id":"19e75845-5147-4aeb-90be-16f3aa270465","target_id":"9ff19022ef915615911280e3c49ed44b","source_type":"WIKI_ITEM","target_type":"SOURCE_FILE","relationship_type":"REFERENCED_BY","extra":"Wiki references source file: backend/app/config.py","gmt_create":"2026-04-23T20:33:37.277294+08:00","gmt_modified":"2026-04-23T20:33:37.277294+08:00"},{"id":724,"source_id":"19e75845-5147-4aeb-90be-16f3aa270465","target_id":"9228ff67d4c757a85d9421b71f4b29f5","source_type":"WIKI_ITEM","target_type":"SOURCE_FILE","relationship_type":"REFERENCED_BY","extra":"Wiki references source file: backend/app/main.py","gmt_create":"2026-04-23T20:33:37.278423+08:00","gmt_modified":"2026-04-23T20:33:37.278423+08:00"},{"id":725,"source_id":"19e75845-5147-4aeb-90be-16f3aa270465","target_id":"b07a4fb9cecbbd66a6910ccbc7651f19","source_type":"WIKI_ITEM","target_type":"SOURCE_FILE","relationship_type":"REFERENCED_BY","extra":"Wiki references source file: tests/test_citation_engine.py","gmt_create":"2026-04-23T20:33:37.279079+08:00","gmt_modified":"2026-04-23T20:33:37.279079+08:00"},{"id":726,"source_id":"19e75845-5147-4aeb-90be-16f3aa270465","target_id":"a26ee01cf41da3b956e1650448c156fa","source_type":"WIKI_ITEM","target_type":"SOURCE_FILE","relationship_type":"REFERENCED_BY","extra":"Wiki references source file: backend/requirements.txt","gmt_create":"2026-04-23T20:33:37.279629+08:00","gmt_modified":"2026-04-23T20:33:37.27963+08:00"},{"id":727,"source_id":"19e75845-5147-4aeb-90be-16f3aa270465","target_id":"cbd0101fa84d957bcb1baaa623c6b31c","source_type":"WIKI_ITEM","target_type":"CODE_SNIPPET","relationship_type":"CONTAINS","extra":"Wiki contains code snippet: backend/app/api/citations.py#1-78","gmt_create":"2026-04-23T20:33:37.280454+08:00","gmt_modified":"2026-04-23T20:33:37.280454+08:00"},{"id":728,"source_id":"19e75845-5147-4aeb-90be-16f3aa270465","target_id":"6b3d903205941aa9391dd90016e1102c","source_type":"WIKI_ITEM","target_type":"SOURCE_FILE","relationship_type":"REFERENCED_BY","extra":"Wiki references source file: backend/app/api/queries.py","gmt_create":"2026-04-23T20:33:37.281512+08:00","gmt_modified":"2026-04-23T20:33:37.281513+08:00"},{"id":729,"source_id":"19e75845-5147-4aeb-90be-16f3aa270465","target_id":"482d573f97b482b99bcde1c399eceb73","source_type":"WIKI_ITEM","target_type":"CODE_SNIPPET","relationship_type":"CONTAINS","extra":"Wiki contains code snippet: backend/app/api/queries.py#90-108","gmt_create":"2026-04-23T20:33:37.281875+08:00","gmt_modified":"2026-04-23T20:33:37.281876+08:00"},{"id":730,"source_id":"6b3d903205941aa9391dd90016e1102c","target_id":"482d573f97b482b99bcde1c399eceb73","source_type":"SOURCE_FILE","target_type":"CODE_SNIPPET","relationship_type":"CONTAINS","extra":"Source file contains code snippet: 90-108","gmt_create":"2026-04-23T20:33:37.28285+08:00","gmt_modified":"2026-04-23T20:33:37.28285+08:00"},{"id":731,"source_id":"19e75845-5147-4aeb-90be-16f3aa270465","target_id":"7c0831c17e8c65eaed9511e17ed2a2ef","source_type":"WIKI_ITEM","target_type":"CODE_SNIPPET","relationship_type":"CONTAINS","extra":"Wiki contains code snippet: backend/app/services/citation.py#1-269","gmt_create":"2026-04-23T20:33:37.283208+08:00","gmt_modified":"2026-04-23T20:33:37.283208+08:00"},{"id":732,"source_id":"19e75845-5147-4aeb-90be-16f3aa270465","target_id":"88d22de3b2a7419868e8ae19130d860c","source_type":"WIKI_ITEM","target_type":"SOURCE_FILE","relationship_type":"REFERENCED_BY","extra":"Wiki references source file: backend/app/services/query.py","gmt_create":"2026-04-23T20:33:37.283598+08:00","gmt_modified":"2026-04-23T20:33:37.283598+08:00"},{"id":733,"source_id":"19e75845-5147-4aeb-90be-16f3aa270465","target_id":"4cef9e740b6feb68c6bd22b660c47320","source_type":"WIKI_ITEM","target_type":"CODE_SNIPPET","relationship_type":"CONTAINS","extra":"Wiki contains code snippet: backend/app/services/query.py#1-123","gmt_create":"2026-04-23T20:33:37.284031+08:00","gmt_modified":"2026-04-23T20:33:37.284031+08:00"},{"id":734,"source_id":"19e75845-5147-4aeb-90be-16f3aa270465","target_id":"8d5aac2ae0671f05d7c0807ba9296cdf","source_type":"WIKI_ITEM","target_type":"CODE_SNIPPET","relationship_type":"CONTAINS","extra":"Wiki contains code snippet: backend/app/workers/citation_engine.py#1-330","gmt_create":"2026-04-23T20:33:37.284881+08:00","gmt_modified":"2026-04-23T20:33:37.284881+08:00"},{"id":735,"source_id":"19e75845-5147-4aeb-90be-16f3aa270465","target_id":"72a110dca58d8152758e2fdab4e94761","source_type":"WIKI_ITEM","target_type":"CODE_SNIPPET","relationship_type":"CONTAINS","extra":"Wiki contains code snippet: backend/app/workers/platforms/base.py#1-18","gmt_create":"2026-04-23T20:33:37.285439+08:00","gmt_modified":"2026-04-23T20:33:37.285439+08:00"},{"id":736,"source_id":"19e75845-5147-4aeb-90be-16f3aa270465","target_id":"56f44cc97867cee3e5663424134d6072","source_type":"WIKI_ITEM","target_type":"CODE_SNIPPET","relationship_type":"CONTAINS","extra":"Wiki contains code snippet: backend/app/workers/platforms/kimi.py#1-37","gmt_create":"2026-04-23T20:33:37.285889+08:00","gmt_modified":"2026-04-23T20:33:37.285889+08:00"},{"id":737,"source_id":"8f973791233c698b3e64a4fb28a93d4b","target_id":"56f44cc97867cee3e5663424134d6072","source_type":"SOURCE_FILE","target_type":"CODE_SNIPPET","relationship_type":"CONTAINS","extra":"Source file contains code snippet: 1-37","gmt_create":"2026-04-23T20:33:37.286195+08:00","gmt_modified":"2026-04-23T20:33:37.286195+08:00"},{"id":738,"source_id":"19e75845-5147-4aeb-90be-16f3aa270465","target_id":"2e326ef8322619f1e8b3873022cb0437","source_type":"WIKI_ITEM","target_type":"CODE_SNIPPET","relationship_type":"CONTAINS","extra":"Wiki contains code snippet: backend/app/workers/platforms/wenxin.py#1-37","gmt_create":"2026-04-23T20:33:37.286846+08:00","gmt_modified":"2026-04-23T20:33:37.286846+08:00"},{"id":739,"source_id":"f642fc1c2f34e15572d9d98aa6c18813","target_id":"2e326ef8322619f1e8b3873022cb0437","source_type":"SOURCE_FILE","target_type":"CODE_SNIPPET","relationship_type":"CONTAINS","extra":"Source file contains code snippet: 1-37","gmt_create":"2026-04-23T20:33:37.287299+08:00","gmt_modified":"2026-04-23T20:33:37.287299+08:00"},{"id":740,"source_id":"19e75845-5147-4aeb-90be-16f3aa270465","target_id":"debd789847d1eed2d54198772edf68a2","source_type":"WIKI_ITEM","target_type":"CODE_SNIPPET","relationship_type":"CONTAINS","extra":"Wiki contains code snippet: backend/app/workers/platforms/tongyi.py#1-38","gmt_create":"2026-04-23T20:33:37.28771+08:00","gmt_modified":"2026-04-23T20:33:37.287711+08:00"},{"id":741,"source_id":"19e75845-5147-4aeb-90be-16f3aa270465","target_id":"3bde521d18cc7221ae2f14637e163aac","source_type":"WIKI_ITEM","target_type":"CODE_SNIPPET","relationship_type":"CONTAINS","extra":"Wiki contains code snippet: backend/app/workers/platforms/doubao.py#1-38","gmt_create":"2026-04-23T20:33:37.288659+08:00","gmt_modified":"2026-04-23T20:33:37.288659+08:00"},{"id":742,"source_id":"19e75845-5147-4aeb-90be-16f3aa270465","target_id":"c26862d9e0fc878b51a2668cfd2ec827","source_type":"WIKI_ITEM","target_type":"CODE_SNIPPET","relationship_type":"CONTAINS","extra":"Wiki contains code snippet: backend/app/workers/platforms/qingyan.py#1-38","gmt_create":"2026-04-23T20:33:37.290497+08:00","gmt_modified":"2026-04-23T20:33:37.290498+08:00"},{"id":743,"source_id":"19e75845-5147-4aeb-90be-16f3aa270465","target_id":"0fcc9c2e0d33b887c5f18a3807b64a1e","source_type":"WIKI_ITEM","target_type":"CODE_SNIPPET","relationship_type":"CONTAINS","extra":"Wiki contains code snippet: backend/app/workers/platforms/tiangong.py#1-38","gmt_create":"2026-04-23T20:33:37.292345+08:00","gmt_modified":"2026-04-23T20:33:37.292345+08:00"},{"id":744,"source_id":"19e75845-5147-4aeb-90be-16f3aa270465","target_id":"a4baa2444208b3f9a3f42bc492038207","source_type":"WIKI_ITEM","target_type":"CODE_SNIPPET","relationship_type":"CONTAINS","extra":"Wiki contains code snippet: backend/app/workers/platforms/xinghuo.py#1-38","gmt_create":"2026-04-23T20:33:37.293708+08:00","gmt_modified":"2026-04-23T20:33:37.293708+08:00"},{"id":745,"source_id":"19e75845-5147-4aeb-90be-16f3aa270465","target_id":"9f82f6d82bf914a608d6afa3d9854abf","source_type":"WIKI_ITEM","target_type":"CODE_SNIPPET","relationship_type":"CONTAINS","extra":"Wiki contains code snippet: backend/app/workers/platforms/search_engine.py#1-174","gmt_create":"2026-04-23T20:33:37.2944+08:00","gmt_modified":"2026-04-23T20:33:37.2944+08:00"},{"id":746,"source_id":"19e75845-5147-4aeb-90be-16f3aa270465","target_id":"4cac57dbc530f0335c913ec5725dfa4f","source_type":"WIKI_ITEM","target_type":"CODE_SNIPPET","relationship_type":"CONTAINS","extra":"Wiki contains code snippet: backend/app/workers/scheduler.py#1-121","gmt_create":"2026-04-23T20:33:37.295331+08:00","gmt_modified":"2026-04-23T20:33:37.295331+08:00"},{"id":747,"source_id":"5cbb1e3f112aeba62a14b0b8999fc0f5","target_id":"4cac57dbc530f0335c913ec5725dfa4f","source_type":"SOURCE_FILE","target_type":"CODE_SNIPPET","relationship_type":"CONTAINS","extra":"Source file contains code snippet: 1-121","gmt_create":"2026-04-23T20:33:37.296239+08:00","gmt_modified":"2026-04-23T20:33:37.296239+08:00"},{"id":748,"source_id":"19e75845-5147-4aeb-90be-16f3aa270465","target_id":"6281fff17a86ec1895c64d87c2ae7fb1","source_type":"WIKI_ITEM","target_type":"CODE_SNIPPET","relationship_type":"CONTAINS","extra":"Wiki contains code snippet: backend/app/models/query.py#1-55","gmt_create":"2026-04-23T20:33:37.296858+08:00","gmt_modified":"2026-04-23T20:33:37.296858+08:00"},{"id":749,"source_id":"19e75845-5147-4aeb-90be-16f3aa270465","target_id":"6628e006b8e5ca16160743528b6b0506","source_type":"WIKI_ITEM","target_type":"CODE_SNIPPET","relationship_type":"CONTAINS","extra":"Wiki contains code snippet: backend/app/models/query_task.py#1-39","gmt_create":"2026-04-23T20:33:37.297624+08:00","gmt_modified":"2026-04-23T20:33:37.297624+08:00"},{"id":750,"source_id":"19e75845-5147-4aeb-90be-16f3aa270465","target_id":"943c18db69a04b3137fba4cebcfea87e","source_type":"WIKI_ITEM","target_type":"CODE_SNIPPET","relationship_type":"CONTAINS","extra":"Wiki contains code snippet: backend/app/models/citation_record.py#1-42","gmt_create":"2026-04-23T20:33:37.298765+08:00","gmt_modified":"2026-04-23T20:33:37.298765+08:00"},{"id":751,"source_id":"19e75845-5147-4aeb-90be-16f3aa270465","target_id":"84fbed7d35f7752e2117a74fcaf5f0e9","source_type":"WIKI_ITEM","target_type":"CODE_SNIPPET","relationship_type":"CONTAINS","extra":"Wiki contains code snippet: backend/app/config.py#1-17","gmt_create":"2026-04-23T20:33:37.299752+08:00","gmt_modified":"2026-04-23T20:33:37.299752+08:00"},{"id":752,"source_id":"19e75845-5147-4aeb-90be-16f3aa270465","target_id":"c2747ca16b879bca0f68955534c3c4fc","source_type":"WIKI_ITEM","target_type":"CODE_SNIPPET","relationship_type":"CONTAINS","extra":"Wiki contains code snippet: backend/app/main.py#1-48","gmt_create":"2026-04-23T20:33:37.30067+08:00","gmt_modified":"2026-04-23T20:33:37.30067+08:00"},{"id":753,"source_id":"19e75845-5147-4aeb-90be-16f3aa270465","target_id":"db174cfe219fc84d0dd26529f047b1d0","source_type":"WIKI_ITEM","target_type":"CODE_SNIPPET","relationship_type":"CONTAINS","extra":"Wiki contains code snippet: backend/app/workers/citation_engine.py#161-330","gmt_create":"2026-04-23T20:33:37.304109+08:00","gmt_modified":"2026-04-23T20:33:37.304109+08:00"},{"id":754,"source_id":"74040de652d5e57f548bb5c4adc3e1a0","target_id":"db174cfe219fc84d0dd26529f047b1d0","source_type":"SOURCE_FILE","target_type":"CODE_SNIPPET","relationship_type":"CONTAINS","extra":"Source file contains code snippet: 161-330","gmt_create":"2026-04-23T20:33:37.304836+08:00","gmt_modified":"2026-04-23T20:33:37.304836+08:00"},{"id":755,"source_id":"19e75845-5147-4aeb-90be-16f3aa270465","target_id":"f36452f78aabfb0c46da03bbe25dff06","source_type":"WIKI_ITEM","target_type":"CODE_SNIPPET","relationship_type":"CONTAINS","extra":"Wiki contains code snippet: backend/app/services/citation.py#219-295","gmt_create":"2026-04-23T20:33:37.307629+08:00","gmt_modified":"2026-04-23T20:33:37.307629+08:00"},{"id":756,"source_id":"04e3926c080e795713bff683e7dc9d3e","target_id":"f36452f78aabfb0c46da03bbe25dff06","source_type":"SOURCE_FILE","target_type":"CODE_SNIPPET","relationship_type":"CONTAINS","extra":"Source file contains code snippet: 219-295","gmt_create":"2026-04-23T20:33:37.308258+08:00","gmt_modified":"2026-04-23T20:33:37.308258+08:00"},{"id":757,"source_id":"19e75845-5147-4aeb-90be-16f3aa270465","target_id":"362d22f423631cda39404660b3317a2f","source_type":"WIKI_ITEM","target_type":"CODE_SNIPPET","relationship_type":"CONTAINS","extra":"Wiki contains code snippet: backend/app/workers/citation_engine.py#177-254","gmt_create":"2026-04-23T20:33:37.310127+08:00","gmt_modified":"2026-04-23T20:33:37.310127+08:00"},{"id":758,"source_id":"19e75845-5147-4aeb-90be-16f3aa270465","target_id":"b475ff5225ac403c7fcf3dd7e14cbac6","source_type":"WIKI_ITEM","target_type":"CODE_SNIPPET","relationship_type":"CONTAINS","extra":"Wiki contains code snippet: backend/app/workers/platforms/tongyi.py#16-33","gmt_create":"2026-04-23T20:33:37.31061+08:00","gmt_modified":"2026-04-23T20:33:37.31061+08:00"},{"id":759,"source_id":"19e75845-5147-4aeb-90be-16f3aa270465","target_id":"557ae34b57a5dd8e8fa3bb2a6ce178a7","source_type":"WIKI_ITEM","target_type":"CODE_SNIPPET","relationship_type":"CONTAINS","extra":"Wiki contains code snippet: backend/app/workers/platforms/search_engine.py#163-174","gmt_create":"2026-04-23T20:33:37.311106+08:00","gmt_modified":"2026-04-23T20:33:37.311106+08:00"},{"id":760,"source_id":"19e75845-5147-4aeb-90be-16f3aa270465","target_id":"52c01d7b9c17aa16944cbfcf8885be61","source_type":"WIKI_ITEM","target_type":"CODE_SNIPPET","relationship_type":"CONTAINS","extra":"Wiki contains code snippet: backend/app/workers/platforms/kimi.py#16-33","gmt_create":"2026-04-23T20:33:37.311558+08:00","gmt_modified":"2026-04-23T20:33:37.311558+08:00"},{"id":761,"source_id":"8f973791233c698b3e64a4fb28a93d4b","target_id":"52c01d7b9c17aa16944cbfcf8885be61","source_type":"SOURCE_FILE","target_type":"CODE_SNIPPET","relationship_type":"CONTAINS","extra":"Source file contains code snippet: 16-33","gmt_create":"2026-04-23T20:33:37.319146+08:00","gmt_modified":"2026-04-23T20:33:37.319146+08:00"},{"id":762,"source_id":"19e75845-5147-4aeb-90be-16f3aa270465","target_id":"77158a6f887e224a03552893bfec7c92","source_type":"WIKI_ITEM","target_type":"CODE_SNIPPET","relationship_type":"CONTAINS","extra":"Wiki contains code snippet: backend/app/workers/platforms/wenxin.py#16-33","gmt_create":"2026-04-23T20:33:37.320166+08:00","gmt_modified":"2026-04-23T20:33:37.320166+08:00"},{"id":763,"source_id":"19e75845-5147-4aeb-90be-16f3aa270465","target_id":"9d352899554ab41b65b2e9f32558d811","source_type":"WIKI_ITEM","target_type":"CODE_SNIPPET","relationship_type":"CONTAINS","extra":"Wiki contains code snippet: backend/app/workers/citation_engine.py#39-113","gmt_create":"2026-04-23T20:33:37.321322+08:00","gmt_modified":"2026-04-23T20:33:37.321322+08:00"},{"id":764,"source_id":"74040de652d5e57f548bb5c4adc3e1a0","target_id":"9d352899554ab41b65b2e9f32558d811","source_type":"SOURCE_FILE","target_type":"CODE_SNIPPET","relationship_type":"CONTAINS","extra":"Source file contains code snippet: 39-113","gmt_create":"2026-04-23T20:33:37.322276+08:00","gmt_modified":"2026-04-23T20:33:37.322276+08:00"},{"id":765,"source_id":"19e75845-5147-4aeb-90be-16f3aa270465","target_id":"b1ee5a992230844ba898765be63f7b27","source_type":"WIKI_ITEM","target_type":"CODE_SNIPPET","relationship_type":"CONTAINS","extra":"Wiki contains code snippet: backend/app/workers/citation_engine.py#32-133","gmt_create":"2026-04-23T20:33:37.323119+08:00","gmt_modified":"2026-04-23T20:33:37.323119+08:00"},{"id":766,"source_id":"74040de652d5e57f548bb5c4adc3e1a0","target_id":"b1ee5a992230844ba898765be63f7b27","source_type":"SOURCE_FILE","target_type":"CODE_SNIPPET","relationship_type":"CONTAINS","extra":"Source file contains code snippet: 32-133","gmt_create":"2026-04-23T20:33:37.323615+08:00","gmt_modified":"2026-04-23T20:33:37.323615+08:00"},{"id":767,"source_id":"19e75845-5147-4aeb-90be-16f3aa270465","target_id":"cb098a3cd32339e99f755dfd0fc35b5c","source_type":"WIKI_ITEM","target_type":"CODE_SNIPPET","relationship_type":"CONTAINS","extra":"Wiki contains code snippet: tests/test_citation_engine.py#6-127","gmt_create":"2026-04-23T20:33:37.324259+08:00","gmt_modified":"2026-04-23T20:33:37.324259+08:00"},{"id":768,"source_id":"b07a4fb9cecbbd66a6910ccbc7651f19","target_id":"cb098a3cd32339e99f755dfd0fc35b5c","source_type":"SOURCE_FILE","target_type":"CODE_SNIPPET","relationship_type":"CONTAINS","extra":"Source file contains code snippet: 6-127","gmt_create":"2026-04-23T20:33:37.32508+08:00","gmt_modified":"2026-04-23T20:33:37.32508+08:00"},{"id":769,"source_id":"19e75845-5147-4aeb-90be-16f3aa270465","target_id":"3d2dab79f7a3fedf24f0212cc9ef7aa1","source_type":"WIKI_ITEM","target_type":"CODE_SNIPPET","relationship_type":"CONTAINS","extra":"Wiki contains code snippet: backend/app/workers/citation_engine.py#145-158","gmt_create":"2026-04-23T20:33:37.325915+08:00","gmt_modified":"2026-04-23T20:33:37.325915+08:00"},{"id":770,"source_id":"74040de652d5e57f548bb5c4adc3e1a0","target_id":"3d2dab79f7a3fedf24f0212cc9ef7aa1","source_type":"SOURCE_FILE","target_type":"CODE_SNIPPET","relationship_type":"CONTAINS","extra":"Source file contains code snippet: 145-158","gmt_create":"2026-04-23T20:33:37.327012+08:00","gmt_modified":"2026-04-23T20:33:37.327012+08:00"},{"id":771,"source_id":"19e75845-5147-4aeb-90be-16f3aa270465","target_id":"4e9b3d0e94282f4bc6fa500f4eed61a1","source_type":"WIKI_ITEM","target_type":"CODE_SNIPPET","relationship_type":"CONTAINS","extra":"Wiki contains code snippet: backend/app/workers/citation_engine.py#135-159","gmt_create":"2026-04-23T20:33:37.327853+08:00","gmt_modified":"2026-04-23T20:33:37.327853+08:00"},{"id":772,"source_id":"74040de652d5e57f548bb5c4adc3e1a0","target_id":"4e9b3d0e94282f4bc6fa500f4eed61a1","source_type":"SOURCE_FILE","target_type":"CODE_SNIPPET","relationship_type":"CONTAINS","extra":"Source file contains code snippet: 135-159","gmt_create":"2026-04-23T20:33:37.328872+08:00","gmt_modified":"2026-04-23T20:33:37.328872+08:00"},{"id":773,"source_id":"19e75845-5147-4aeb-90be-16f3aa270465","target_id":"8e3201561a9dd9a06ee3bf68ffdb3f99","source_type":"WIKI_ITEM","target_type":"CODE_SNIPPET","relationship_type":"CONTAINS","extra":"Wiki contains code snippet: tests/test_citation_engine.py#39-109","gmt_create":"2026-04-23T20:33:37.32989+08:00","gmt_modified":"2026-04-23T20:33:37.32989+08:00"},{"id":774,"source_id":"b07a4fb9cecbbd66a6910ccbc7651f19","target_id":"8e3201561a9dd9a06ee3bf68ffdb3f99","source_type":"SOURCE_FILE","target_type":"CODE_SNIPPET","relationship_type":"CONTAINS","extra":"Source file contains code snippet: 39-109","gmt_create":"2026-04-23T20:33:37.33132+08:00","gmt_modified":"2026-04-23T20:33:37.33132+08:00"},{"id":775,"source_id":"19e75845-5147-4aeb-90be-16f3aa270465","target_id":"c3a417be3d61f5bcd3fbf976e0c4f15a","source_type":"WIKI_ITEM","target_type":"CODE_SNIPPET","relationship_type":"CONTAINS","extra":"Wiki contains code snippet: backend/app/workers/scheduler.py#33-121","gmt_create":"2026-04-23T20:33:37.336944+08:00","gmt_modified":"2026-04-23T20:33:37.336944+08:00"},{"id":776,"source_id":"5cbb1e3f112aeba62a14b0b8999fc0f5","target_id":"c3a417be3d61f5bcd3fbf976e0c4f15a","source_type":"SOURCE_FILE","target_type":"CODE_SNIPPET","relationship_type":"CONTAINS","extra":"Source file contains code snippet: 33-121","gmt_create":"2026-04-23T20:33:37.337655+08:00","gmt_modified":"2026-04-23T20:33:37.337655+08:00"},{"id":777,"source_id":"19e75845-5147-4aeb-90be-16f3aa270465","target_id":"096856da621e23e78422a15e2bfce1f1","source_type":"WIKI_ITEM","target_type":"CODE_SNIPPET","relationship_type":"CONTAINS","extra":"Wiki contains code snippet: backend/app/main.py#13-22","gmt_create":"2026-04-23T20:33:37.339169+08:00","gmt_modified":"2026-04-23T20:33:37.339169+08:00"},{"id":778,"source_id":"19e75845-5147-4aeb-90be-16f3aa270465","target_id":"7ce954ed7d3bc4dcf78630124cc0dd88","source_type":"WIKI_ITEM","target_type":"CODE_SNIPPET","relationship_type":"CONTAINS","extra":"Wiki contains code snippet: backend/app/services/citation.py#264-295","gmt_create":"2026-04-23T20:33:37.34124+08:00","gmt_modified":"2026-04-23T20:33:37.34124+08:00"},{"id":779,"source_id":"04e3926c080e795713bff683e7dc9d3e","target_id":"7ce954ed7d3bc4dcf78630124cc0dd88","source_type":"SOURCE_FILE","target_type":"CODE_SNIPPET","relationship_type":"CONTAINS","extra":"Source file contains code snippet: 264-295","gmt_create":"2026-04-23T20:33:37.342433+08:00","gmt_modified":"2026-04-23T20:33:37.342433+08:00"},{"id":780,"source_id":"19e75845-5147-4aeb-90be-16f3aa270465","target_id":"7289a3568c137c8a671fc8c963bb8d28","source_type":"WIKI_ITEM","target_type":"CODE_SNIPPET","relationship_type":"CONTAINS","extra":"Wiki contains code snippet: backend/requirements.txt#1-35","gmt_create":"2026-04-23T20:33:37.346038+08:00","gmt_modified":"2026-04-23T20:33:37.346038+08:00"},{"id":781,"source_id":"a26ee01cf41da3b956e1650448c156fa","target_id":"7289a3568c137c8a671fc8c963bb8d28","source_type":"SOURCE_FILE","target_type":"CODE_SNIPPET","relationship_type":"CONTAINS","extra":"Source file contains code snippet: 1-35","gmt_create":"2026-04-23T20:33:37.346577+08:00","gmt_modified":"2026-04-23T20:33:37.346577+08:00"},{"id":782,"source_id":"19e75845-5147-4aeb-90be-16f3aa270465","target_id":"ef82ce4377c549013c200e19701a6805","source_type":"WIKI_ITEM","target_type":"CODE_SNIPPET","relationship_type":"CONTAINS","extra":"Wiki contains code snippet: backend/app/workers/platforms/kimi.py#21-32","gmt_create":"2026-04-23T20:33:37.352671+08:00","gmt_modified":"2026-04-23T20:33:37.352671+08:00"},{"id":783,"source_id":"8f973791233c698b3e64a4fb28a93d4b","target_id":"ef82ce4377c549013c200e19701a6805","source_type":"SOURCE_FILE","target_type":"CODE_SNIPPET","relationship_type":"CONTAINS","extra":"Source file contains code snippet: 21-32","gmt_create":"2026-04-23T20:33:37.354355+08:00","gmt_modified":"2026-04-23T20:33:37.354355+08:00"},{"id":784,"source_id":"19e75845-5147-4aeb-90be-16f3aa270465","target_id":"c7986eb1be0ffdd9ec4e243be4270119","source_type":"WIKI_ITEM","target_type":"CODE_SNIPPET","relationship_type":"CONTAINS","extra":"Wiki contains code snippet: backend/app/workers/platforms/wenxin.py#21-32","gmt_create":"2026-04-23T20:33:37.355472+08:00","gmt_modified":"2026-04-23T20:33:37.355472+08:00"},{"id":785,"source_id":"f642fc1c2f34e15572d9d98aa6c18813","target_id":"c7986eb1be0ffdd9ec4e243be4270119","source_type":"SOURCE_FILE","target_type":"CODE_SNIPPET","relationship_type":"CONTAINS","extra":"Source file contains code snippet: 21-32","gmt_create":"2026-04-23T20:33:37.357613+08:00","gmt_modified":"2026-04-23T20:33:37.357613+08:00"},{"id":786,"source_id":"19e75845-5147-4aeb-90be-16f3aa270465","target_id":"b55cc5936c299f819b57b899858438e6","source_type":"WIKI_ITEM","target_type":"CODE_SNIPPET","relationship_type":"CONTAINS","extra":"Wiki contains code snippet: backend/app/workers/platforms/search_engine.py#139-144","gmt_create":"2026-04-23T20:33:37.358273+08:00","gmt_modified":"2026-04-23T20:33:37.358273+08:00"},{"id":787,"source_id":"19e75845-5147-4aeb-90be-16f3aa270465","target_id":"5563b3bd56550648dc70302c1762ce5a","source_type":"WIKI_ITEM","target_type":"CODE_SNIPPET","relationship_type":"CONTAINS","extra":"Wiki contains code snippet: backend/app/workers/platforms/tongyi.py#18-29","gmt_create":"2026-04-23T20:33:37.360657+08:00","gmt_modified":"2026-04-23T20:33:37.360657+08:00"},{"id":788,"source_id":"e68ad5186f1e47610ab3d9f14a794393","target_id":"5563b3bd56550648dc70302c1762ce5a","source_type":"SOURCE_FILE","target_type":"CODE_SNIPPET","relationship_type":"CONTAINS","extra":"Source file contains code snippet: 18-29","gmt_create":"2026-04-23T20:33:37.361776+08:00","gmt_modified":"2026-04-23T20:33:37.361776+08:00"},{"id":789,"source_id":"19e75845-5147-4aeb-90be-16f3aa270465","target_id":"91852ef8dcc844a2f85e9fce0227ab74","source_type":"WIKI_ITEM","target_type":"CODE_SNIPPET","relationship_type":"CONTAINS","extra":"Wiki contains code snippet: backend/app/workers/platforms/doubao.py#18-29","gmt_create":"2026-04-23T20:33:37.363109+08:00","gmt_modified":"2026-04-23T20:33:37.363109+08:00"},{"id":790,"source_id":"404f6d0765a8c6e77e33b7fc21b377a4","target_id":"91852ef8dcc844a2f85e9fce0227ab74","source_type":"SOURCE_FILE","target_type":"CODE_SNIPPET","relationship_type":"CONTAINS","extra":"Source file contains code snippet: 18-29","gmt_create":"2026-04-23T20:33:37.363811+08:00","gmt_modified":"2026-04-23T20:33:37.363811+08:00"},{"id":791,"source_id":"19e75845-5147-4aeb-90be-16f3aa270465","target_id":"1b46fab9e22f53db30ead5677d03e3e2","source_type":"WIKI_ITEM","target_type":"CODE_SNIPPET","relationship_type":"CONTAINS","extra":"Wiki contains code snippet: backend/app/workers/citation_engine.py#11-16","gmt_create":"2026-04-23T20:33:37.364819+08:00","gmt_modified":"2026-04-23T20:33:37.364819+08:00"},{"id":792,"source_id":"74040de652d5e57f548bb5c4adc3e1a0","target_id":"1b46fab9e22f53db30ead5677d03e3e2","source_type":"SOURCE_FILE","target_type":"CODE_SNIPPET","relationship_type":"CONTAINS","extra":"Source file contains code snippet: 11-16","gmt_create":"2026-04-23T20:33:37.365554+08:00","gmt_modified":"2026-04-23T20:33:37.365554+08:00"},{"id":793,"source_id":"19e75845-5147-4aeb-90be-16f3aa270465","target_id":"f096aa3ea82e9fa625a9acb1309b4c50","source_type":"WIKI_ITEM","target_type":"CODE_SNIPPET","relationship_type":"CONTAINS","extra":"Wiki contains code snippet: backend/app/workers/citation_engine.py#231-247","gmt_create":"2026-04-23T20:33:37.36634+08:00","gmt_modified":"2026-04-23T20:33:37.366341+08:00"},{"id":794,"source_id":"19e75845-5147-4aeb-90be-16f3aa270465","target_id":"4a2fa09aa3a948dec5ef8ba873b0e716","source_type":"WIKI_ITEM","target_type":"CODE_SNIPPET","relationship_type":"CONTAINS","extra":"Wiki contains code snippet: backend/app/services/citation.py#14-42","gmt_create":"2026-04-23T20:33:37.367379+08:00","gmt_modified":"2026-04-23T20:33:37.367379+08:00"},{"id":795,"source_id":"04e3926c080e795713bff683e7dc9d3e","target_id":"4a2fa09aa3a948dec5ef8ba873b0e716","source_type":"SOURCE_FILE","target_type":"CODE_SNIPPET","relationship_type":"CONTAINS","extra":"Source file contains code snippet: 14-42","gmt_create":"2026-04-23T20:33:37.368233+08:00","gmt_modified":"2026-04-23T20:33:37.368233+08:00"},{"id":796,"source_id":"74d3018f-4e23-4687-8bf4-7fb403f479f7","target_id":"6b3d903205941aa9391dd90016e1102c","source_type":"WIKI_ITEM","target_type":"SOURCE_FILE","relationship_type":"REFERENCED_BY","extra":"Wiki references source file: backend/app/api/queries.py","gmt_create":"2026-04-23T20:33:57.518077+08:00","gmt_modified":"2026-04-23T20:33:57.518077+08:00"},{"id":797,"source_id":"74d3018f-4e23-4687-8bf4-7fb403f479f7","target_id":"f301b79d833233ce39d350e82a71c938","source_type":"WIKI_ITEM","target_type":"SOURCE_FILE","relationship_type":"REFERENCED_BY","extra":"Wiki references source file: backend/app/schemas/query.py","gmt_create":"2026-04-23T20:33:57.518453+08:00","gmt_modified":"2026-04-23T20:33:57.518454+08:00"},{"id":798,"source_id":"74d3018f-4e23-4687-8bf4-7fb403f479f7","target_id":"1a3336b4af8a39a055e912724338580c","source_type":"WIKI_ITEM","target_type":"SOURCE_FILE","relationship_type":"REFERENCED_BY","extra":"Wiki references source file: backend/app/schemas/citation.py","gmt_create":"2026-04-23T20:33:57.519644+08:00","gmt_modified":"2026-04-23T20:33:57.519644+08:00"},{"id":799,"source_id":"74d3018f-4e23-4687-8bf4-7fb403f479f7","target_id":"b74caccb06844efcdb14d8324cff65c2","source_type":"WIKI_ITEM","target_type":"SOURCE_FILE","relationship_type":"REFERENCED_BY","extra":"Wiki references source file: backend/app/models/query.py","gmt_create":"2026-04-23T20:33:57.521079+08:00","gmt_modified":"2026-04-23T20:33:57.521079+08:00"},{"id":800,"source_id":"74d3018f-4e23-4687-8bf4-7fb403f479f7","target_id":"069738f21ac2da7349d22683e8c36929","source_type":"WIKI_ITEM","target_type":"SOURCE_FILE","relationship_type":"REFERENCED_BY","extra":"Wiki references source file: backend/app/models/query_task.py","gmt_create":"2026-04-23T20:33:57.522061+08:00","gmt_modified":"2026-04-23T20:33:57.522061+08:00"},{"id":801,"source_id":"74d3018f-4e23-4687-8bf4-7fb403f479f7","target_id":"b4a81ef789630d0af6a8d50859d01bf3","source_type":"WIKI_ITEM","target_type":"SOURCE_FILE","relationship_type":"REFERENCED_BY","extra":"Wiki references source file: backend/app/models/citation_record.py","gmt_create":"2026-04-23T20:33:57.523189+08:00","gmt_modified":"2026-04-23T20:33:57.523189+08:00"},{"id":802,"source_id":"74d3018f-4e23-4687-8bf4-7fb403f479f7","target_id":"c59f8c276697a070dffc581fe94d809c","source_type":"WIKI_ITEM","target_type":"SOURCE_FILE","relationship_type":"REFERENCED_BY","extra":"Wiki references source file: backend/app/models/user.py","gmt_create":"2026-04-23T20:33:57.52383+08:00","gmt_modified":"2026-04-23T20:33:57.52383+08:00"},{"id":803,"source_id":"74d3018f-4e23-4687-8bf4-7fb403f479f7","target_id":"88d22de3b2a7419868e8ae19130d860c","source_type":"WIKI_ITEM","target_type":"SOURCE_FILE","relationship_type":"REFERENCED_BY","extra":"Wiki references source file: backend/app/services/query.py","gmt_create":"2026-04-23T20:33:57.524563+08:00","gmt_modified":"2026-04-23T20:33:57.524563+08:00"},{"id":804,"source_id":"74d3018f-4e23-4687-8bf4-7fb403f479f7","target_id":"04e3926c080e795713bff683e7dc9d3e","source_type":"WIKI_ITEM","target_type":"SOURCE_FILE","relationship_type":"REFERENCED_BY","extra":"Wiki references source file: backend/app/services/citation.py","gmt_create":"2026-04-23T20:33:57.525774+08:00","gmt_modified":"2026-04-23T20:33:57.525774+08:00"},{"id":805,"source_id":"74d3018f-4e23-4687-8bf4-7fb403f479f7","target_id":"5cbb1e3f112aeba62a14b0b8999fc0f5","source_type":"WIKI_ITEM","target_type":"SOURCE_FILE","relationship_type":"REFERENCED_BY","extra":"Wiki references source file: backend/app/workers/scheduler.py","gmt_create":"2026-04-23T20:33:57.526492+08:00","gmt_modified":"2026-04-23T20:33:57.526492+08:00"},{"id":806,"source_id":"74d3018f-4e23-4687-8bf4-7fb403f479f7","target_id":"74040de652d5e57f548bb5c4adc3e1a0","source_type":"WIKI_ITEM","target_type":"SOURCE_FILE","relationship_type":"REFERENCED_BY","extra":"Wiki references source file: backend/app/workers/citation_engine.py","gmt_create":"2026-04-23T20:33:57.527326+08:00","gmt_modified":"2026-04-23T20:33:57.527326+08:00"},{"id":807,"source_id":"74d3018f-4e23-4687-8bf4-7fb403f479f7","target_id":"a16cf42e9559523c4f96ca4c79f9488d","source_type":"WIKI_ITEM","target_type":"SOURCE_FILE","relationship_type":"REFERENCED_BY","extra":"Wiki references source file: backend/app/workers/platforms/base.py","gmt_create":"2026-04-23T20:33:57.527983+08:00","gmt_modified":"2026-04-23T20:33:57.527983+08:00"},{"id":808,"source_id":"74d3018f-4e23-4687-8bf4-7fb403f479f7","target_id":"8f973791233c698b3e64a4fb28a93d4b","source_type":"WIKI_ITEM","target_type":"SOURCE_FILE","relationship_type":"REFERENCED_BY","extra":"Wiki references source file: backend/app/workers/platforms/kimi.py","gmt_create":"2026-04-23T20:33:57.529144+08:00","gmt_modified":"2026-04-23T20:33:57.529144+08:00"},{"id":809,"source_id":"74d3018f-4e23-4687-8bf4-7fb403f479f7","target_id":"f642fc1c2f34e15572d9d98aa6c18813","source_type":"WIKI_ITEM","target_type":"SOURCE_FILE","relationship_type":"REFERENCED_BY","extra":"Wiki references source file: backend/app/workers/platforms/wenxin.py","gmt_create":"2026-04-23T20:33:57.529998+08:00","gmt_modified":"2026-04-23T20:33:57.529998+08:00"},{"id":810,"source_id":"74d3018f-4e23-4687-8bf4-7fb403f479f7","target_id":"7538ffe4902ab6041adb28b19844962a","source_type":"WIKI_ITEM","target_type":"SOURCE_FILE","relationship_type":"REFERENCED_BY","extra":"Wiki references source file: backend/app/api/citations.py","gmt_create":"2026-04-23T20:33:57.530659+08:00","gmt_modified":"2026-04-23T20:33:57.530659+08:00"},{"id":811,"source_id":"74d3018f-4e23-4687-8bf4-7fb403f479f7","target_id":"9228ff67d4c757a85d9421b71f4b29f5","source_type":"WIKI_ITEM","target_type":"SOURCE_FILE","relationship_type":"REFERENCED_BY","extra":"Wiki references source file: backend/app/main.py","gmt_create":"2026-04-23T20:33:57.531953+08:00","gmt_modified":"2026-04-23T20:33:57.531953+08:00"},{"id":812,"source_id":"74d3018f-4e23-4687-8bf4-7fb403f479f7","target_id":"0613e76b9679be7f998fb8fd8056e686","source_type":"WIKI_ITEM","target_type":"SOURCE_FILE","relationship_type":"REFERENCED_BY","extra":"Wiki references source file: tests/test_queries.py","gmt_create":"2026-04-23T20:33:57.532681+08:00","gmt_modified":"2026-04-23T20:33:57.532681+08:00"},{"id":813,"source_id":"74d3018f-4e23-4687-8bf4-7fb403f479f7","target_id":"80a0429cc47931de27ddb17a62b8dd9c","source_type":"WIKI_ITEM","target_type":"SOURCE_FILE","relationship_type":"REFERENCED_BY","extra":"Wiki references source file: tests/test_business_flow.py","gmt_create":"2026-04-23T20:33:57.533708+08:00","gmt_modified":"2026-04-23T20:33:57.533708+08:00"},{"id":814,"source_id":"74d3018f-4e23-4687-8bf4-7fb403f479f7","target_id":"e27bcba24aaadeec1922d2b4e5b8386b","source_type":"WIKI_ITEM","target_type":"CODE_SNIPPET","relationship_type":"CONTAINS","extra":"Wiki contains code snippet: backend/app/api/queries.py#1-109","gmt_create":"2026-04-23T20:33:57.534482+08:00","gmt_modified":"2026-04-23T20:33:57.534482+08:00"},{"id":815,"source_id":"74d3018f-4e23-4687-8bf4-7fb403f479f7","target_id":"e7afbab5932c93c3469f1a225e6c7156","source_type":"WIKI_ITEM","target_type":"CODE_SNIPPET","relationship_type":"CONTAINS","extra":"Wiki contains code snippet: backend/app/api/citations.py#1-55","gmt_create":"2026-04-23T20:33:57.535515+08:00","gmt_modified":"2026-04-23T20:33:57.535515+08:00"},{"id":816,"source_id":"7538ffe4902ab6041adb28b19844962a","target_id":"e7afbab5932c93c3469f1a225e6c7156","source_type":"SOURCE_FILE","target_type":"CODE_SNIPPET","relationship_type":"CONTAINS","extra":"Source file contains code snippet: 1-55","gmt_create":"2026-04-23T20:33:57.536318+08:00","gmt_modified":"2026-04-23T20:33:57.536318+08:00"},{"id":817,"source_id":"74d3018f-4e23-4687-8bf4-7fb403f479f7","target_id":"a0eac56d622a2fff529bc2b796064bcd","source_type":"WIKI_ITEM","target_type":"CODE_SNIPPET","relationship_type":"CONTAINS","extra":"Wiki contains code snippet: backend/app/schemas/query.py#1-94","gmt_create":"2026-04-23T20:33:57.537094+08:00","gmt_modified":"2026-04-23T20:33:57.537094+08:00"},{"id":818,"source_id":"f301b79d833233ce39d350e82a71c938","target_id":"a0eac56d622a2fff529bc2b796064bcd","source_type":"SOURCE_FILE","target_type":"CODE_SNIPPET","relationship_type":"CONTAINS","extra":"Source file contains code snippet: 1-94","gmt_create":"2026-04-23T20:33:57.537769+08:00","gmt_modified":"2026-04-23T20:33:57.53777+08:00"},{"id":819,"source_id":"74d3018f-4e23-4687-8bf4-7fb403f479f7","target_id":"174be58163b6f72b4cd4a493f3463ce4","source_type":"WIKI_ITEM","target_type":"CODE_SNIPPET","relationship_type":"CONTAINS","extra":"Wiki contains code snippet: backend/app/schemas/citation.py#1-52","gmt_create":"2026-04-23T20:33:57.53855+08:00","gmt_modified":"2026-04-23T20:33:57.53855+08:00"},{"id":820,"source_id":"1a3336b4af8a39a055e912724338580c","target_id":"174be58163b6f72b4cd4a493f3463ce4","source_type":"SOURCE_FILE","target_type":"CODE_SNIPPET","relationship_type":"CONTAINS","extra":"Source file contains code snippet: 1-52","gmt_create":"2026-04-23T20:33:57.53965+08:00","gmt_modified":"2026-04-23T20:33:57.53965+08:00"},{"id":821,"source_id":"74d3018f-4e23-4687-8bf4-7fb403f479f7","target_id":"6281fff17a86ec1895c64d87c2ae7fb1","source_type":"WIKI_ITEM","target_type":"CODE_SNIPPET","relationship_type":"CONTAINS","extra":"Wiki contains code snippet: backend/app/models/query.py#1-55","gmt_create":"2026-04-23T20:33:57.54057+08:00","gmt_modified":"2026-04-23T20:33:57.54057+08:00"},{"id":822,"source_id":"74d3018f-4e23-4687-8bf4-7fb403f479f7","target_id":"6628e006b8e5ca16160743528b6b0506","source_type":"WIKI_ITEM","target_type":"CODE_SNIPPET","relationship_type":"CONTAINS","extra":"Wiki contains code snippet: backend/app/models/query_task.py#1-39","gmt_create":"2026-04-23T20:33:57.541654+08:00","gmt_modified":"2026-04-23T20:33:57.541654+08:00"},{"id":823,"source_id":"74d3018f-4e23-4687-8bf4-7fb403f479f7","target_id":"943c18db69a04b3137fba4cebcfea87e","source_type":"WIKI_ITEM","target_type":"CODE_SNIPPET","relationship_type":"CONTAINS","extra":"Wiki contains code snippet: backend/app/models/citation_record.py#1-42","gmt_create":"2026-04-23T20:33:57.543056+08:00","gmt_modified":"2026-04-23T20:33:57.543056+08:00"},{"id":824,"source_id":"74d3018f-4e23-4687-8bf4-7fb403f479f7","target_id":"136f172c732d0cc130532a4f0df475a4","source_type":"WIKI_ITEM","target_type":"CODE_SNIPPET","relationship_type":"CONTAINS","extra":"Wiki contains code snippet: backend/app/models/user.py#1-41","gmt_create":"2026-04-23T20:33:57.543958+08:00","gmt_modified":"2026-04-23T20:33:57.543958+08:00"},{"id":825,"source_id":"c59f8c276697a070dffc581fe94d809c","target_id":"136f172c732d0cc130532a4f0df475a4","source_type":"SOURCE_FILE","target_type":"CODE_SNIPPET","relationship_type":"CONTAINS","extra":"Source file contains code snippet: 1-41","gmt_create":"2026-04-23T20:33:57.544974+08:00","gmt_modified":"2026-04-23T20:33:57.544974+08:00"},{"id":826,"source_id":"74d3018f-4e23-4687-8bf4-7fb403f479f7","target_id":"916551131bd9ac8c9f9c8bb762af1fa4","source_type":"WIKI_ITEM","target_type":"CODE_SNIPPET","relationship_type":"CONTAINS","extra":"Wiki contains code snippet: backend/app/services/query.py#1-130","gmt_create":"2026-04-23T20:33:57.545482+08:00","gmt_modified":"2026-04-23T20:33:57.545482+08:00"},{"id":827,"source_id":"88d22de3b2a7419868e8ae19130d860c","target_id":"916551131bd9ac8c9f9c8bb762af1fa4","source_type":"SOURCE_FILE","target_type":"CODE_SNIPPET","relationship_type":"CONTAINS","extra":"Source file contains code snippet: 1-130","gmt_create":"2026-04-23T20:33:57.545785+08:00","gmt_modified":"2026-04-23T20:33:57.545785+08:00"},{"id":828,"source_id":"74d3018f-4e23-4687-8bf4-7fb403f479f7","target_id":"5d2836286eb7d4eb6039b004a9744d26","source_type":"WIKI_ITEM","target_type":"CODE_SNIPPET","relationship_type":"CONTAINS","extra":"Wiki contains code snippet: backend/app/services/citation.py#1-429","gmt_create":"2026-04-23T20:33:57.546196+08:00","gmt_modified":"2026-04-23T20:33:57.546196+08:00"},{"id":829,"source_id":"04e3926c080e795713bff683e7dc9d3e","target_id":"5d2836286eb7d4eb6039b004a9744d26","source_type":"SOURCE_FILE","target_type":"CODE_SNIPPET","relationship_type":"CONTAINS","extra":"Source file contains code snippet: 1-429","gmt_create":"2026-04-23T20:33:57.546517+08:00","gmt_modified":"2026-04-23T20:33:57.546517+08:00"},{"id":830,"source_id":"74d3018f-4e23-4687-8bf4-7fb403f479f7","target_id":"71f98c8993fb42b108e34a554247869b","source_type":"WIKI_ITEM","target_type":"CODE_SNIPPET","relationship_type":"CONTAINS","extra":"Wiki contains code snippet: backend/app/workers/scheduler.py#1-95","gmt_create":"2026-04-23T20:33:57.547004+08:00","gmt_modified":"2026-04-23T20:33:57.547005+08:00"},{"id":831,"source_id":"74d3018f-4e23-4687-8bf4-7fb403f479f7","target_id":"116584ea9162c1bc05911f39f9ef82b6","source_type":"WIKI_ITEM","target_type":"CODE_SNIPPET","relationship_type":"CONTAINS","extra":"Wiki contains code snippet: backend/app/workers/citation_engine.py#1-309","gmt_create":"2026-04-23T20:33:57.5475+08:00","gmt_modified":"2026-04-23T20:33:57.5475+08:00"},{"id":832,"source_id":"74d3018f-4e23-4687-8bf4-7fb403f479f7","target_id":"72a110dca58d8152758e2fdab4e94761","source_type":"WIKI_ITEM","target_type":"CODE_SNIPPET","relationship_type":"CONTAINS","extra":"Wiki contains code snippet: backend/app/workers/platforms/base.py#1-18","gmt_create":"2026-04-23T20:33:57.548046+08:00","gmt_modified":"2026-04-23T20:33:57.548046+08:00"},{"id":833,"source_id":"74d3018f-4e23-4687-8bf4-7fb403f479f7","target_id":"39a3b2d9301fa4eff7bef0fda3352790","source_type":"WIKI_ITEM","target_type":"CODE_SNIPPET","relationship_type":"CONTAINS","extra":"Wiki contains code snippet: backend/app/workers/platforms/kimi.py#1-206","gmt_create":"2026-04-23T20:33:57.548538+08:00","gmt_modified":"2026-04-23T20:33:57.548538+08:00"},{"id":834,"source_id":"8f973791233c698b3e64a4fb28a93d4b","target_id":"39a3b2d9301fa4eff7bef0fda3352790","source_type":"SOURCE_FILE","target_type":"CODE_SNIPPET","relationship_type":"CONTAINS","extra":"Source file contains code snippet: 1-206","gmt_create":"2026-04-23T20:33:57.548868+08:00","gmt_modified":"2026-04-23T20:33:57.548868+08:00"},{"id":835,"source_id":"74d3018f-4e23-4687-8bf4-7fb403f479f7","target_id":"fbcfae3b1238b3da5329ebafe4294861","source_type":"WIKI_ITEM","target_type":"CODE_SNIPPET","relationship_type":"CONTAINS","extra":"Wiki contains code snippet: backend/app/workers/platforms/wenxin.py#1-205","gmt_create":"2026-04-23T20:33:57.549268+08:00","gmt_modified":"2026-04-23T20:33:57.549268+08:00"},{"id":836,"source_id":"f642fc1c2f34e15572d9d98aa6c18813","target_id":"fbcfae3b1238b3da5329ebafe4294861","source_type":"SOURCE_FILE","target_type":"CODE_SNIPPET","relationship_type":"CONTAINS","extra":"Source file contains code snippet: 1-205","gmt_create":"2026-04-23T20:33:57.549553+08:00","gmt_modified":"2026-04-23T20:33:57.549553+08:00"},{"id":837,"source_id":"74d3018f-4e23-4687-8bf4-7fb403f479f7","target_id":"c2747ca16b879bca0f68955534c3c4fc","source_type":"WIKI_ITEM","target_type":"CODE_SNIPPET","relationship_type":"CONTAINS","extra":"Wiki contains code snippet: backend/app/main.py#1-48","gmt_create":"2026-04-23T20:33:57.550006+08:00","gmt_modified":"2026-04-23T20:33:57.550006+08:00"},{"id":838,"source_id":"74d3018f-4e23-4687-8bf4-7fb403f479f7","target_id":"c4273407c88f470df7daf6a8ad5ce969","source_type":"WIKI_ITEM","target_type":"CODE_SNIPPET","relationship_type":"CONTAINS","extra":"Wiki contains code snippet: backend/app/api/queries.py#15-109","gmt_create":"2026-04-23T20:33:57.550496+08:00","gmt_modified":"2026-04-23T20:33:57.550496+08:00"},{"id":839,"source_id":"6b3d903205941aa9391dd90016e1102c","target_id":"c4273407c88f470df7daf6a8ad5ce969","source_type":"SOURCE_FILE","target_type":"CODE_SNIPPET","relationship_type":"CONTAINS","extra":"Source file contains code snippet: 15-109","gmt_create":"2026-04-23T20:33:57.551777+08:00","gmt_modified":"2026-04-23T20:33:57.551777+08:00"},{"id":840,"source_id":"74d3018f-4e23-4687-8bf4-7fb403f479f7","target_id":"35774e0a09ac5459c868914d7182ca95","source_type":"WIKI_ITEM","target_type":"CODE_SNIPPET","relationship_type":"CONTAINS","extra":"Wiki contains code snippet: backend/app/api/citations.py#19-55","gmt_create":"2026-04-23T20:33:57.552775+08:00","gmt_modified":"2026-04-23T20:33:57.552775+08:00"},{"id":841,"source_id":"7538ffe4902ab6041adb28b19844962a","target_id":"35774e0a09ac5459c868914d7182ca95","source_type":"SOURCE_FILE","target_type":"CODE_SNIPPET","relationship_type":"CONTAINS","extra":"Source file contains code snippet: 19-55","gmt_create":"2026-04-23T20:33:57.553082+08:00","gmt_modified":"2026-04-23T20:33:57.553082+08:00"},{"id":842,"source_id":"74d3018f-4e23-4687-8bf4-7fb403f479f7","target_id":"69118807690ef351a9de910414d5e676","source_type":"WIKI_ITEM","target_type":"CODE_SNIPPET","relationship_type":"CONTAINS","extra":"Wiki contains code snippet: backend/app/schemas/query.py#11-94","gmt_create":"2026-04-23T20:33:57.553571+08:00","gmt_modified":"2026-04-23T20:33:57.553571+08:00"},{"id":843,"source_id":"74d3018f-4e23-4687-8bf4-7fb403f479f7","target_id":"f639b566c26dfd18b24e3dfd2e9853ac","source_type":"WIKI_ITEM","target_type":"CODE_SNIPPET","relationship_type":"CONTAINS","extra":"Wiki contains code snippet: backend/app/schemas/citation.py#7-52","gmt_create":"2026-04-23T20:33:57.554164+08:00","gmt_modified":"2026-04-23T20:33:57.554164+08:00"},{"id":844,"source_id":"1a3336b4af8a39a055e912724338580c","target_id":"f639b566c26dfd18b24e3dfd2e9853ac","source_type":"SOURCE_FILE","target_type":"CODE_SNIPPET","relationship_type":"CONTAINS","extra":"Source file contains code snippet: 7-52","gmt_create":"2026-04-23T20:33:57.554458+08:00","gmt_modified":"2026-04-23T20:33:57.554458+08:00"},{"id":845,"source_id":"74d3018f-4e23-4687-8bf4-7fb403f479f7","target_id":"4fb8856be3a581fe8303d11b2284ca29","source_type":"WIKI_ITEM","target_type":"CODE_SNIPPET","relationship_type":"CONTAINS","extra":"Wiki contains code snippet: backend/app/models/query.py#11-55","gmt_create":"2026-04-23T20:33:57.55511+08:00","gmt_modified":"2026-04-23T20:33:57.55511+08:00"},{"id":846,"source_id":"74d3018f-4e23-4687-8bf4-7fb403f479f7","target_id":"b84f46f058847733347974841f613688","source_type":"WIKI_ITEM","target_type":"CODE_SNIPPET","relationship_type":"CONTAINS","extra":"Wiki contains code snippet: backend/app/models/query_task.py#11-39","gmt_create":"2026-04-23T20:33:57.557064+08:00","gmt_modified":"2026-04-23T20:33:57.557064+08:00"},{"id":847,"source_id":"74d3018f-4e23-4687-8bf4-7fb403f479f7","target_id":"fd541971cebf8a7c167d717f5c5d1ff6","source_type":"WIKI_ITEM","target_type":"CODE_SNIPPET","relationship_type":"CONTAINS","extra":"Wiki contains code snippet: backend/app/models/citation_record.py#11-42","gmt_create":"2026-04-23T20:33:57.558255+08:00","gmt_modified":"2026-04-23T20:33:57.558255+08:00"},{"id":848,"source_id":"74d3018f-4e23-4687-8bf4-7fb403f479f7","target_id":"56e46969bdb790a5e8f333184b878d6d","source_type":"WIKI_ITEM","target_type":"CODE_SNIPPET","relationship_type":"CONTAINS","extra":"Wiki contains code snippet: backend/app/models/user.py#11-41","gmt_create":"2026-04-23T20:33:57.558894+08:00","gmt_modified":"2026-04-23T20:33:57.558894+08:00"},{"id":849,"source_id":"74d3018f-4e23-4687-8bf4-7fb403f479f7","target_id":"d7c319a04abbc6704da53107e07dd8e7","source_type":"WIKI_ITEM","target_type":"CODE_SNIPPET","relationship_type":"CONTAINS","extra":"Wiki contains code snippet: backend/app/services/query.py#12-130","gmt_create":"2026-04-23T20:33:57.560321+08:00","gmt_modified":"2026-04-23T20:33:57.560321+08:00"},{"id":850,"source_id":"74d3018f-4e23-4687-8bf4-7fb403f479f7","target_id":"b46654006178160f12897e2c5baac8fa","source_type":"WIKI_ITEM","target_type":"CODE_SNIPPET","relationship_type":"CONTAINS","extra":"Wiki contains code snippet: backend/app/services/citation.py#219-429","gmt_create":"2026-04-23T20:33:57.561417+08:00","gmt_modified":"2026-04-23T20:33:57.561417+08:00"},{"id":851,"source_id":"04e3926c080e795713bff683e7dc9d3e","target_id":"b46654006178160f12897e2c5baac8fa","source_type":"SOURCE_FILE","target_type":"CODE_SNIPPET","relationship_type":"CONTAINS","extra":"Source file contains code snippet: 219-429","gmt_create":"2026-04-23T20:33:57.561724+08:00","gmt_modified":"2026-04-23T20:33:57.561724+08:00"},{"id":852,"source_id":"74d3018f-4e23-4687-8bf4-7fb403f479f7","target_id":"e230904202fcf7a861c6f49b84f9f863","source_type":"WIKI_ITEM","target_type":"CODE_SNIPPET","relationship_type":"CONTAINS","extra":"Wiki contains code snippet: backend/app/workers/scheduler.py#25-95","gmt_create":"2026-04-23T20:33:57.562679+08:00","gmt_modified":"2026-04-23T20:33:57.562679+08:00"},{"id":853,"source_id":"74d3018f-4e23-4687-8bf4-7fb403f479f7","target_id":"309607c54b12a6340edc086ffb4737c9","source_type":"WIKI_ITEM","target_type":"CODE_SNIPPET","relationship_type":"CONTAINS","extra":"Wiki contains code snippet: backend/app/workers/citation_engine.py#148-309","gmt_create":"2026-04-23T20:33:57.563303+08:00","gmt_modified":"2026-04-23T20:33:57.563303+08:00"},{"id":854,"source_id":"74d3018f-4e23-4687-8bf4-7fb403f479f7","target_id":"ad67863041d9eea2b0fb542b5aa33aca","source_type":"WIKI_ITEM","target_type":"CODE_SNIPPET","relationship_type":"CONTAINS","extra":"Wiki contains code snippet: backend/app/workers/platforms/base.py#4-18","gmt_create":"2026-04-23T20:33:57.563842+08:00","gmt_modified":"2026-04-23T20:33:57.563842+08:00"},{"id":855,"source_id":"74d3018f-4e23-4687-8bf4-7fb403f479f7","target_id":"82265d393c20d0af96beec6b9c657c27","source_type":"WIKI_ITEM","target_type":"CODE_SNIPPET","relationship_type":"CONTAINS","extra":"Wiki contains code snippet: backend/app/api/queries.py#28-41","gmt_create":"2026-04-23T20:33:57.564486+08:00","gmt_modified":"2026-04-23T20:33:57.564486+08:00"},{"id":856,"source_id":"6b3d903205941aa9391dd90016e1102c","target_id":"82265d393c20d0af96beec6b9c657c27","source_type":"SOURCE_FILE","target_type":"CODE_SNIPPET","relationship_type":"CONTAINS","extra":"Source file contains code snippet: 28-41","gmt_create":"2026-04-23T20:33:57.564788+08:00","gmt_modified":"2026-04-23T20:33:57.564788+08:00"},{"id":857,"source_id":"74d3018f-4e23-4687-8bf4-7fb403f479f7","target_id":"c86edb7a95fbe4b431ac65a0e2b8636e","source_type":"WIKI_ITEM","target_type":"CODE_SNIPPET","relationship_type":"CONTAINS","extra":"Wiki contains code snippet: backend/app/api/queries.py#90-109","gmt_create":"2026-04-23T20:33:57.565285+08:00","gmt_modified":"2026-04-23T20:33:57.565285+08:00"},{"id":858,"source_id":"74d3018f-4e23-4687-8bf4-7fb403f479f7","target_id":"9b10dac7dbbb1327afc8a525bf4bd0c3","source_type":"WIKI_ITEM","target_type":"CODE_SNIPPET","relationship_type":"CONTAINS","extra":"Wiki contains code snippet: backend/app/services/query.py#45-81","gmt_create":"2026-04-23T20:33:57.565809+08:00","gmt_modified":"2026-04-23T20:33:57.565809+08:00"},{"id":859,"source_id":"74d3018f-4e23-4687-8bf4-7fb403f479f7","target_id":"93e5c95b1691bb81a36bf9a0ac889030","source_type":"WIKI_ITEM","target_type":"CODE_SNIPPET","relationship_type":"CONTAINS","extra":"Wiki contains code snippet: backend/app/services/citation.py#219-261","gmt_create":"2026-04-23T20:33:57.566399+08:00","gmt_modified":"2026-04-23T20:33:57.566399+08:00"},{"id":860,"source_id":"04e3926c080e795713bff683e7dc9d3e","target_id":"93e5c95b1691bb81a36bf9a0ac889030","source_type":"SOURCE_FILE","target_type":"CODE_SNIPPET","relationship_type":"CONTAINS","extra":"Source file contains code snippet: 219-261","gmt_create":"2026-04-23T20:33:57.578474+08:00","gmt_modified":"2026-04-23T20:33:57.578474+08:00"},{"id":861,"source_id":"74d3018f-4e23-4687-8bf4-7fb403f479f7","target_id":"448970b02d89d5e1576f70bdb0063363","source_type":"WIKI_ITEM","target_type":"CODE_SNIPPET","relationship_type":"CONTAINS","extra":"Wiki contains code snippet: backend/app/workers/scheduler.py#51-84","gmt_create":"2026-04-23T20:33:57.580464+08:00","gmt_modified":"2026-04-23T20:33:57.580464+08:00"},{"id":862,"source_id":"74d3018f-4e23-4687-8bf4-7fb403f479f7","target_id":"160b5326537d25444c40a459a01e79c6","source_type":"WIKI_ITEM","target_type":"CODE_SNIPPET","relationship_type":"CONTAINS","extra":"Wiki contains code snippet: backend/app/workers/citation_engine.py#159-234","gmt_create":"2026-04-23T20:33:57.581421+08:00","gmt_modified":"2026-04-23T20:33:57.581422+08:00"},{"id":863,"source_id":"74d3018f-4e23-4687-8bf4-7fb403f479f7","target_id":"a4918fcbd21492ad996d7f5496f03a4b","source_type":"WIKI_ITEM","target_type":"CODE_SNIPPET","relationship_type":"CONTAINS","extra":"Wiki contains code snippet: backend/app/workers/platforms/kimi.py#33-48","gmt_create":"2026-04-23T20:33:57.58279+08:00","gmt_modified":"2026-04-23T20:33:57.58279+08:00"},{"id":864,"source_id":"74d3018f-4e23-4687-8bf4-7fb403f479f7","target_id":"bc38d046b4b1410ae2165cee2272839e","source_type":"WIKI_ITEM","target_type":"CODE_SNIPPET","relationship_type":"CONTAINS","extra":"Wiki contains code snippet: backend/app/workers/platforms/wenxin.py#33-48","gmt_create":"2026-04-23T20:33:57.583676+08:00","gmt_modified":"2026-04-23T20:33:57.583676+08:00"},{"id":865,"source_id":"74d3018f-4e23-4687-8bf4-7fb403f479f7","target_id":"374200f0bf946f0399351756977d0495","source_type":"WIKI_ITEM","target_type":"CODE_SNIPPET","relationship_type":"CONTAINS","extra":"Wiki contains code snippet: backend/app/workers/citation_engine.py#176-234","gmt_create":"2026-04-23T20:33:57.588601+08:00","gmt_modified":"2026-04-23T20:33:57.588601+08:00"},{"id":866,"source_id":"74040de652d5e57f548bb5c4adc3e1a0","target_id":"374200f0bf946f0399351756977d0495","source_type":"SOURCE_FILE","target_type":"CODE_SNIPPET","relationship_type":"CONTAINS","extra":"Source file contains code snippet: 176-234","gmt_create":"2026-04-23T20:33:57.589609+08:00","gmt_modified":"2026-04-23T20:33:57.589609+08:00"},{"id":867,"source_id":"74d3018f-4e23-4687-8bf4-7fb403f479f7","target_id":"ac5982063da5f04315f3e82a0d653902","source_type":"WIKI_ITEM","target_type":"CODE_SNIPPET","relationship_type":"CONTAINS","extra":"Wiki contains code snippet: backend/app/models/query_task.py#24-32","gmt_create":"2026-04-23T20:33:57.590732+08:00","gmt_modified":"2026-04-23T20:33:57.590732+08:00"},{"id":868,"source_id":"74d3018f-4e23-4687-8bf4-7fb403f479f7","target_id":"601b981b00d93b941843f046a163d5a3","source_type":"WIKI_ITEM","target_type":"CODE_SNIPPET","relationship_type":"CONTAINS","extra":"Wiki contains code snippet: backend/app/schemas/query.py#18-33","gmt_create":"2026-04-23T20:33:57.592508+08:00","gmt_modified":"2026-04-23T20:33:57.592508+08:00"},{"id":869,"source_id":"74d3018f-4e23-4687-8bf4-7fb403f479f7","target_id":"9a8d9100a6bc34ebae9ee065def7e88a","source_type":"WIKI_ITEM","target_type":"CODE_SNIPPET","relationship_type":"CONTAINS","extra":"Wiki contains code snippet: backend/app/schemas/query.py#44-72","gmt_create":"2026-04-23T20:33:57.593647+08:00","gmt_modified":"2026-04-23T20:33:57.593647+08:00"},{"id":870,"source_id":"f301b79d833233ce39d350e82a71c938","target_id":"9a8d9100a6bc34ebae9ee065def7e88a","source_type":"SOURCE_FILE","target_type":"CODE_SNIPPET","relationship_type":"CONTAINS","extra":"Source file contains code snippet: 44-72","gmt_create":"2026-04-23T20:33:57.594757+08:00","gmt_modified":"2026-04-23T20:33:57.594757+08:00"},{"id":871,"source_id":"74d3018f-4e23-4687-8bf4-7fb403f479f7","target_id":"93c23bcc3456826af17e26a6d4c32116","source_type":"WIKI_ITEM","target_type":"CODE_SNIPPET","relationship_type":"CONTAINS","extra":"Wiki contains code snippet: backend/app/schemas/query.py#6-9","gmt_create":"2026-04-23T20:33:57.595474+08:00","gmt_modified":"2026-04-23T20:33:57.595474+08:00"},{"id":872,"source_id":"f301b79d833233ce39d350e82a71c938","target_id":"93c23bcc3456826af17e26a6d4c32116","source_type":"SOURCE_FILE","target_type":"CODE_SNIPPET","relationship_type":"CONTAINS","extra":"Source file contains code snippet: 6-9","gmt_create":"2026-04-23T20:33:57.596276+08:00","gmt_modified":"2026-04-23T20:33:57.596276+08:00"},{"id":873,"source_id":"74d3018f-4e23-4687-8bf4-7fb403f479f7","target_id":"c17eeb8726297096cd5542283f11494f","source_type":"WIKI_ITEM","target_type":"CODE_SNIPPET","relationship_type":"CONTAINS","extra":"Wiki contains code snippet: backend/app/api/queries.py#17-109","gmt_create":"2026-04-23T20:33:57.597516+08:00","gmt_modified":"2026-04-23T20:33:57.597516+08:00"},{"id":874,"source_id":"6b3d903205941aa9391dd90016e1102c","target_id":"c17eeb8726297096cd5542283f11494f","source_type":"SOURCE_FILE","target_type":"CODE_SNIPPET","relationship_type":"CONTAINS","extra":"Source file contains code snippet: 17-109","gmt_create":"2026-04-23T20:33:57.598386+08:00","gmt_modified":"2026-04-23T20:33:57.598386+08:00"},{"id":875,"source_id":"74d3018f-4e23-4687-8bf4-7fb403f479f7","target_id":"08fec4718be6991260c00ca532f9173a","source_type":"WIKI_ITEM","target_type":"CODE_SNIPPET","relationship_type":"CONTAINS","extra":"Wiki contains code snippet: backend/app/api/citations.py#22-55","gmt_create":"2026-04-23T20:33:57.599188+08:00","gmt_modified":"2026-04-23T20:33:57.599188+08:00"},{"id":876,"source_id":"7538ffe4902ab6041adb28b19844962a","target_id":"08fec4718be6991260c00ca532f9173a","source_type":"SOURCE_FILE","target_type":"CODE_SNIPPET","relationship_type":"CONTAINS","extra":"Source file contains code snippet: 22-55","gmt_create":"2026-04-23T20:33:57.600043+08:00","gmt_modified":"2026-04-23T20:33:57.600043+08:00"},{"id":877,"source_id":"74d3018f-4e23-4687-8bf4-7fb403f479f7","target_id":"08007199eea846dd14f15f7dc70419e2","source_type":"WIKI_ITEM","target_type":"CODE_SNIPPET","relationship_type":"CONTAINS","extra":"Wiki contains code snippet: backend/app/schemas/citation.py#48-52","gmt_create":"2026-04-23T20:33:57.600852+08:00","gmt_modified":"2026-04-23T20:33:57.600852+08:00"},{"id":878,"source_id":"1a3336b4af8a39a055e912724338580c","target_id":"08007199eea846dd14f15f7dc70419e2","source_type":"SOURCE_FILE","target_type":"CODE_SNIPPET","relationship_type":"CONTAINS","extra":"Source file contains code snippet: 48-52","gmt_create":"2026-04-23T20:33:57.601489+08:00","gmt_modified":"2026-04-23T20:33:57.601489+08:00"},{"id":879,"source_id":"74d3018f-4e23-4687-8bf4-7fb403f479f7","target_id":"4caff756fd4da029bd64cd16e7ef5960","source_type":"WIKI_ITEM","target_type":"CODE_SNIPPET","relationship_type":"CONTAINS","extra":"Wiki contains code snippet: backend/app/api/queries.py#32-39","gmt_create":"2026-04-23T20:33:57.602322+08:00","gmt_modified":"2026-04-23T20:33:57.602323+08:00"},{"id":880,"source_id":"6b3d903205941aa9391dd90016e1102c","target_id":"4caff756fd4da029bd64cd16e7ef5960","source_type":"SOURCE_FILE","target_type":"CODE_SNIPPET","relationship_type":"CONTAINS","extra":"Source file contains code snippet: 32-39","gmt_create":"2026-04-23T20:33:57.602918+08:00","gmt_modified":"2026-04-23T20:33:57.602918+08:00"},{"id":881,"source_id":"74d3018f-4e23-4687-8bf4-7fb403f479f7","target_id":"b0220895f66f1273966ad5b2c3266952","source_type":"WIKI_ITEM","target_type":"CODE_SNIPPET","relationship_type":"CONTAINS","extra":"Wiki contains code snippet: backend/app/api/queries.py#49-53","gmt_create":"2026-04-23T20:33:57.603881+08:00","gmt_modified":"2026-04-23T20:33:57.603881+08:00"},{"id":882,"source_id":"6b3d903205941aa9391dd90016e1102c","target_id":"b0220895f66f1273966ad5b2c3266952","source_type":"SOURCE_FILE","target_type":"CODE_SNIPPET","relationship_type":"CONTAINS","extra":"Source file contains code snippet: 49-53","gmt_create":"2026-04-23T20:33:57.604555+08:00","gmt_modified":"2026-04-23T20:33:57.604555+08:00"},{"id":883,"source_id":"74d3018f-4e23-4687-8bf4-7fb403f479f7","target_id":"44f88f9664fdf6e84ffb7e0675a86a28","source_type":"WIKI_ITEM","target_type":"CODE_SNIPPET","relationship_type":"CONTAINS","extra":"Wiki contains code snippet: backend/app/api/queries.py#64-69","gmt_create":"2026-04-23T20:33:57.605262+08:00","gmt_modified":"2026-04-23T20:33:57.605262+08:00"},{"id":884,"source_id":"6b3d903205941aa9391dd90016e1102c","target_id":"44f88f9664fdf6e84ffb7e0675a86a28","source_type":"SOURCE_FILE","target_type":"CODE_SNIPPET","relationship_type":"CONTAINS","extra":"Source file contains code snippet: 64-69","gmt_create":"2026-04-23T20:33:57.606324+08:00","gmt_modified":"2026-04-23T20:33:57.606324+08:00"},{"id":885,"source_id":"74d3018f-4e23-4687-8bf4-7fb403f479f7","target_id":"91f280f51389bd1cf711dcf33a4da681","source_type":"WIKI_ITEM","target_type":"CODE_SNIPPET","relationship_type":"CONTAINS","extra":"Wiki contains code snippet: backend/app/api/queries.py#79-84","gmt_create":"2026-04-23T20:33:57.607055+08:00","gmt_modified":"2026-04-23T20:33:57.607055+08:00"},{"id":886,"source_id":"6b3d903205941aa9391dd90016e1102c","target_id":"91f280f51389bd1cf711dcf33a4da681","source_type":"SOURCE_FILE","target_type":"CODE_SNIPPET","relationship_type":"CONTAINS","extra":"Source file contains code snippet: 79-84","gmt_create":"2026-04-23T20:33:57.608388+08:00","gmt_modified":"2026-04-23T20:33:57.608388+08:00"},{"id":887,"source_id":"74d3018f-4e23-4687-8bf4-7fb403f479f7","target_id":"ab50466a57c77659d7b469d3a8a04ddb","source_type":"WIKI_ITEM","target_type":"CODE_SNIPPET","relationship_type":"CONTAINS","extra":"Wiki contains code snippet: backend/app/api/queries.py#96-103","gmt_create":"2026-04-23T20:33:57.609206+08:00","gmt_modified":"2026-04-23T20:33:57.609206+08:00"},{"id":888,"source_id":"6b3d903205941aa9391dd90016e1102c","target_id":"ab50466a57c77659d7b469d3a8a04ddb","source_type":"SOURCE_FILE","target_type":"CODE_SNIPPET","relationship_type":"CONTAINS","extra":"Source file contains code snippet: 96-103","gmt_create":"2026-04-23T20:33:57.609975+08:00","gmt_modified":"2026-04-23T20:33:57.609975+08:00"},{"id":889,"source_id":"74d3018f-4e23-4687-8bf4-7fb403f479f7","target_id":"572c2dece1fbc13aa2bb7d6b61b0fd5c","source_type":"WIKI_ITEM","target_type":"CODE_SNIPPET","relationship_type":"CONTAINS","extra":"Wiki contains code snippet: backend/app/api/citations.py#65-71","gmt_create":"2026-04-23T20:33:57.61104+08:00","gmt_modified":"2026-04-23T20:33:57.611041+08:00"},{"id":890,"source_id":"7538ffe4902ab6041adb28b19844962a","target_id":"572c2dece1fbc13aa2bb7d6b61b0fd5c","source_type":"SOURCE_FILE","target_type":"CODE_SNIPPET","relationship_type":"CONTAINS","extra":"Source file contains code snippet: 65-71","gmt_create":"2026-04-23T20:33:57.611833+08:00","gmt_modified":"2026-04-23T20:33:57.611833+08:00"},{"id":891,"source_id":"74d3018f-4e23-4687-8bf4-7fb403f479f7","target_id":"82386bc7ca57d9ccc94b656e52bc89f6","source_type":"WIKI_ITEM","target_type":"CODE_SNIPPET","relationship_type":"CONTAINS","extra":"Wiki contains code snippet: backend/app/api/queries.py#1-14","gmt_create":"2026-04-23T20:33:57.612865+08:00","gmt_modified":"2026-04-23T20:33:57.612865+08:00"},{"id":892,"source_id":"6b3d903205941aa9391dd90016e1102c","target_id":"82386bc7ca57d9ccc94b656e52bc89f6","source_type":"SOURCE_FILE","target_type":"CODE_SNIPPET","relationship_type":"CONTAINS","extra":"Source file contains code snippet: 1-14","gmt_create":"2026-04-23T20:33:57.613537+08:00","gmt_modified":"2026-04-23T20:33:57.613537+08:00"},{"id":893,"source_id":"74d3018f-4e23-4687-8bf4-7fb403f479f7","target_id":"7ab79ab21d7d6e4dbcb224572516f6f6","source_type":"WIKI_ITEM","target_type":"CODE_SNIPPET","relationship_type":"CONTAINS","extra":"Wiki contains code snippet: backend/app/api/citations.py#1-19","gmt_create":"2026-04-23T20:33:57.613967+08:00","gmt_modified":"2026-04-23T20:33:57.613968+08:00"},{"id":894,"source_id":"7538ffe4902ab6041adb28b19844962a","target_id":"7ab79ab21d7d6e4dbcb224572516f6f6","source_type":"SOURCE_FILE","target_type":"CODE_SNIPPET","relationship_type":"CONTAINS","extra":"Source file contains code snippet: 1-19","gmt_create":"2026-04-23T20:33:57.61426+08:00","gmt_modified":"2026-04-23T20:33:57.61426+08:00"},{"id":895,"source_id":"74d3018f-4e23-4687-8bf4-7fb403f479f7","target_id":"8433204d7a82a1f480e57df9ceee5581","source_type":"WIKI_ITEM","target_type":"CODE_SNIPPET","relationship_type":"CONTAINS","extra":"Wiki contains code snippet: backend/app/services/query.py#1-10","gmt_create":"2026-04-23T20:33:57.614658+08:00","gmt_modified":"2026-04-23T20:33:57.614658+08:00"},{"id":896,"source_id":"88d22de3b2a7419868e8ae19130d860c","target_id":"8433204d7a82a1f480e57df9ceee5581","source_type":"SOURCE_FILE","target_type":"CODE_SNIPPET","relationship_type":"CONTAINS","extra":"Source file contains code snippet: 1-10","gmt_create":"2026-04-23T20:33:57.614988+08:00","gmt_modified":"2026-04-23T20:33:57.614988+08:00"},{"id":897,"source_id":"74d3018f-4e23-4687-8bf4-7fb403f479f7","target_id":"3957ee6f15a01b7b541490438ef18684","source_type":"WIKI_ITEM","target_type":"CODE_SNIPPET","relationship_type":"CONTAINS","extra":"Wiki contains code snippet: backend/app/services/citation.py#1-17","gmt_create":"2026-04-23T20:33:57.615388+08:00","gmt_modified":"2026-04-23T20:33:57.615388+08:00"},{"id":898,"source_id":"04e3926c080e795713bff683e7dc9d3e","target_id":"3957ee6f15a01b7b541490438ef18684","source_type":"SOURCE_FILE","target_type":"CODE_SNIPPET","relationship_type":"CONTAINS","extra":"Source file contains code snippet: 1-17","gmt_create":"2026-04-23T20:33:57.615908+08:00","gmt_modified":"2026-04-23T20:33:57.615908+08:00"},{"id":899,"source_id":"74d3018f-4e23-4687-8bf4-7fb403f479f7","target_id":"3729543092bccad8926c5ea852db1e69","source_type":"WIKI_ITEM","target_type":"CODE_SNIPPET","relationship_type":"CONTAINS","extra":"Wiki contains code snippet: backend/app/workers/citation_engine.py#148-157","gmt_create":"2026-04-23T20:33:57.61673+08:00","gmt_modified":"2026-04-23T20:33:57.61673+08:00"},{"id":900,"source_id":"74d3018f-4e23-4687-8bf4-7fb403f479f7","target_id":"fcae8d1d281ad7186999cc4ca8e43db7","source_type":"WIKI_ITEM","target_type":"CODE_SNIPPET","relationship_type":"CONTAINS","extra":"Wiki contains code snippet: backend/app/workers/scheduler.py#25-39","gmt_create":"2026-04-23T20:33:57.617716+08:00","gmt_modified":"2026-04-23T20:33:57.617716+08:00"},{"id":901,"source_id":"5cbb1e3f112aeba62a14b0b8999fc0f5","target_id":"fcae8d1d281ad7186999cc4ca8e43db7","source_type":"SOURCE_FILE","target_type":"CODE_SNIPPET","relationship_type":"CONTAINS","extra":"Source file contains code snippet: 25-39","gmt_create":"2026-04-23T20:33:57.618148+08:00","gmt_modified":"2026-04-23T20:33:57.618148+08:00"},{"id":902,"source_id":"74d3018f-4e23-4687-8bf4-7fb403f479f7","target_id":"ee12a84ac6334b13e20132181454488b","source_type":"WIKI_ITEM","target_type":"CODE_SNIPPET","relationship_type":"CONTAINS","extra":"Wiki contains code snippet: backend/app/workers/scheduler.py#13-19","gmt_create":"2026-04-23T20:33:57.6192+08:00","gmt_modified":"2026-04-23T20:33:57.6192+08:00"},{"id":903,"source_id":"5cbb1e3f112aeba62a14b0b8999fc0f5","target_id":"ee12a84ac6334b13e20132181454488b","source_type":"SOURCE_FILE","target_type":"CODE_SNIPPET","relationship_type":"CONTAINS","extra":"Source file contains code snippet: 13-19","gmt_create":"2026-04-23T20:33:57.619587+08:00","gmt_modified":"2026-04-23T20:33:57.619587+08:00"},{"id":904,"source_id":"74d3018f-4e23-4687-8bf4-7fb403f479f7","target_id":"897e047b94772e5a0ff57cf773a7f965","source_type":"WIKI_ITEM","target_type":"CODE_SNIPPET","relationship_type":"CONTAINS","extra":"Wiki contains code snippet: backend/app/workers/platforms/kimi.py#17-32","gmt_create":"2026-04-23T20:33:57.620024+08:00","gmt_modified":"2026-04-23T20:33:57.620024+08:00"},{"id":905,"source_id":"8f973791233c698b3e64a4fb28a93d4b","target_id":"897e047b94772e5a0ff57cf773a7f965","source_type":"SOURCE_FILE","target_type":"CODE_SNIPPET","relationship_type":"CONTAINS","extra":"Source file contains code snippet: 17-32","gmt_create":"2026-04-23T20:33:57.620315+08:00","gmt_modified":"2026-04-23T20:33:57.620315+08:00"},{"id":906,"source_id":"74d3018f-4e23-4687-8bf4-7fb403f479f7","target_id":"53e8ec81b4d2dbb13c831048e5897036","source_type":"WIKI_ITEM","target_type":"CODE_SNIPPET","relationship_type":"CONTAINS","extra":"Wiki contains code snippet: backend/app/workers/platforms/wenxin.py#17-32","gmt_create":"2026-04-23T20:33:57.620909+08:00","gmt_modified":"2026-04-23T20:33:57.620909+08:00"},{"id":907,"source_id":"f642fc1c2f34e15572d9d98aa6c18813","target_id":"53e8ec81b4d2dbb13c831048e5897036","source_type":"SOURCE_FILE","target_type":"CODE_SNIPPET","relationship_type":"CONTAINS","extra":"Source file contains code snippet: 17-32","gmt_create":"2026-04-23T20:33:57.621267+08:00","gmt_modified":"2026-04-23T20:33:57.621267+08:00"},{"id":908,"source_id":"74d3018f-4e23-4687-8bf4-7fb403f479f7","target_id":"096856da621e23e78422a15e2bfce1f1","source_type":"WIKI_ITEM","target_type":"CODE_SNIPPET","relationship_type":"CONTAINS","extra":"Wiki contains code snippet: backend/app/main.py#13-22","gmt_create":"2026-04-23T20:33:57.621687+08:00","gmt_modified":"2026-04-23T20:33:57.621687+08:00"},{"id":909,"source_id":"74d3018f-4e23-4687-8bf4-7fb403f479f7","target_id":"ef82ce4377c549013c200e19701a6805","source_type":"WIKI_ITEM","target_type":"CODE_SNIPPET","relationship_type":"CONTAINS","extra":"Wiki contains code snippet: backend/app/workers/platforms/kimi.py#21-32","gmt_create":"2026-04-23T20:33:57.62216+08:00","gmt_modified":"2026-04-23T20:33:57.62216+08:00"},{"id":910,"source_id":"74d3018f-4e23-4687-8bf4-7fb403f479f7","target_id":"c7986eb1be0ffdd9ec4e243be4270119","source_type":"WIKI_ITEM","target_type":"CODE_SNIPPET","relationship_type":"CONTAINS","extra":"Wiki contains code snippet: backend/app/workers/platforms/wenxin.py#21-32","gmt_create":"2026-04-23T20:33:57.623241+08:00","gmt_modified":"2026-04-23T20:33:57.623241+08:00"},{"id":911,"source_id":"74d3018f-4e23-4687-8bf4-7fb403f479f7","target_id":"eecf9581dbaa0a515cf11514175e7ef9","source_type":"WIKI_ITEM","target_type":"CODE_SNIPPET","relationship_type":"CONTAINS","extra":"Wiki contains code snippet: backend/app/workers/platforms/kimi.py#11-206","gmt_create":"2026-04-23T20:33:57.627555+08:00","gmt_modified":"2026-04-23T20:33:57.627555+08:00"},{"id":912,"source_id":"74d3018f-4e23-4687-8bf4-7fb403f479f7","target_id":"5563c29185326a59be61ee0a6eec4463","source_type":"WIKI_ITEM","target_type":"CODE_SNIPPET","relationship_type":"CONTAINS","extra":"Wiki contains code snippet: backend/app/workers/platforms/wenxin.py#11-205","gmt_create":"2026-04-23T20:33:57.62809+08:00","gmt_modified":"2026-04-23T20:33:57.62809+08:00"},{"id":913,"source_id":"74d3018f-4e23-4687-8bf4-7fb403f479f7","target_id":"fd3145047b9c813cc8e64b9322e531f9","source_type":"WIKI_ITEM","target_type":"CODE_SNIPPET","relationship_type":"CONTAINS","extra":"Wiki contains code snippet: backend/app/services/citation.py#219-327","gmt_create":"2026-04-23T20:33:57.62931+08:00","gmt_modified":"2026-04-23T20:33:57.62931+08:00"},{"id":914,"source_id":"04e3926c080e795713bff683e7dc9d3e","target_id":"fd3145047b9c813cc8e64b9322e531f9","source_type":"SOURCE_FILE","target_type":"CODE_SNIPPET","relationship_type":"CONTAINS","extra":"Source file contains code snippet: 219-327","gmt_create":"2026-04-23T20:33:57.629745+08:00","gmt_modified":"2026-04-23T20:33:57.629745+08:00"},{"id":915,"source_id":"74d3018f-4e23-4687-8bf4-7fb403f479f7","target_id":"b09a0f415030d91b25e6cabd8a0a93fc","source_type":"WIKI_ITEM","target_type":"CODE_SNIPPET","relationship_type":"CONTAINS","extra":"Wiki contains code snippet: backend/app/models/query_task.py#176-289","gmt_create":"2026-04-23T20:33:57.630458+08:00","gmt_modified":"2026-04-23T20:33:57.630458+08:00"},{"id":916,"source_id":"069738f21ac2da7349d22683e8c36929","target_id":"b09a0f415030d91b25e6cabd8a0a93fc","source_type":"SOURCE_FILE","target_type":"CODE_SNIPPET","relationship_type":"CONTAINS","extra":"Source file contains code snippet: 176-289","gmt_create":"2026-04-23T20:33:57.630748+08:00","gmt_modified":"2026-04-23T20:33:57.630748+08:00"},{"id":917,"source_id":"74d3018f-4e23-4687-8bf4-7fb403f479f7","target_id":"e2168959b26c386940370b5f1bf48d7d","source_type":"WIKI_ITEM","target_type":"CODE_SNIPPET","relationship_type":"CONTAINS","extra":"Wiki contains code snippet: backend/app/models/citation_record.py#194-204","gmt_create":"2026-04-23T20:33:57.631184+08:00","gmt_modified":"2026-04-23T20:33:57.631184+08:00"},{"id":918,"source_id":"b4a81ef789630d0af6a8d50859d01bf3","target_id":"e2168959b26c386940370b5f1bf48d7d","source_type":"SOURCE_FILE","target_type":"CODE_SNIPPET","relationship_type":"CONTAINS","extra":"Source file contains code snippet: 194-204","gmt_create":"2026-04-23T20:33:57.63147+08:00","gmt_modified":"2026-04-23T20:33:57.63147+08:00"},{"id":919,"source_id":"2126339b-b0f5-4152-924b-cbe028cd0c39","target_id":"8f973791233c698b3e64a4fb28a93d4b","source_type":"WIKI_ITEM","target_type":"SOURCE_FILE","relationship_type":"REFERENCED_BY","extra":"Wiki references source file: backend/app/workers/platforms/kimi.py","gmt_create":"2026-04-23T20:35:18.634061+08:00","gmt_modified":"2026-04-23T20:35:18.634062+08:00"},{"id":920,"source_id":"2126339b-b0f5-4152-924b-cbe028cd0c39","target_id":"a16cf42e9559523c4f96ca4c79f9488d","source_type":"WIKI_ITEM","target_type":"SOURCE_FILE","relationship_type":"REFERENCED_BY","extra":"Wiki references source file: backend/app/workers/platforms/base.py","gmt_create":"2026-04-23T20:35:18.634886+08:00","gmt_modified":"2026-04-23T20:35:18.634886+08:00"},{"id":921,"source_id":"2126339b-b0f5-4152-924b-cbe028cd0c39","target_id":"6a63f048c16c60c5d2d57012c810ee0e","source_type":"WIKI_ITEM","target_type":"SOURCE_FILE","relationship_type":"REFERENCED_BY","extra":"Wiki references source file: backend/app/workers/platforms/search_engine.py","gmt_create":"2026-04-23T20:35:18.635377+08:00","gmt_modified":"2026-04-23T20:35:18.635377+08:00"},{"id":922,"source_id":"2126339b-b0f5-4152-924b-cbe028cd0c39","target_id":"4a56ef5fca60bc63480b457cab3832f0","source_type":"WIKI_ITEM","target_type":"SOURCE_FILE","relationship_type":"REFERENCED_BY","extra":"Wiki references source file: backend/app/workers/platforms/__init__.py","gmt_create":"2026-04-23T20:35:18.63595+08:00","gmt_modified":"2026-04-23T20:35:18.63595+08:00"},{"id":923,"source_id":"2126339b-b0f5-4152-924b-cbe028cd0c39","target_id":"74040de652d5e57f548bb5c4adc3e1a0","source_type":"WIKI_ITEM","target_type":"SOURCE_FILE","relationship_type":"REFERENCED_BY","extra":"Wiki references source file: backend/app/workers/citation_engine.py","gmt_create":"2026-04-23T20:35:18.636363+08:00","gmt_modified":"2026-04-23T20:35:18.636363+08:00"},{"id":924,"source_id":"2126339b-b0f5-4152-924b-cbe028cd0c39","target_id":"5cbb1e3f112aeba62a14b0b8999fc0f5","source_type":"WIKI_ITEM","target_type":"SOURCE_FILE","relationship_type":"REFERENCED_BY","extra":"Wiki references source file: backend/app/workers/scheduler.py","gmt_create":"2026-04-23T20:35:18.636753+08:00","gmt_modified":"2026-04-23T20:35:18.636753+08:00"},{"id":925,"source_id":"2126339b-b0f5-4152-924b-cbe028cd0c39","target_id":"36dd0ad3ee6bc75a480ad8a62268e80e","source_type":"WIKI_ITEM","target_type":"SOURCE_FILE","relationship_type":"REFERENCED_BY","extra":"Wiki references source file: backend/app/workers/models/query.py","gmt_create":"2026-04-23T20:35:18.6372+08:00","gmt_modified":"2026-04-23T20:35:18.6372+08:00"},{"id":926,"source_id":"2126339b-b0f5-4152-924b-cbe028cd0c39","target_id":"b4a81ef789630d0af6a8d50859d01bf3","source_type":"WIKI_ITEM","target_type":"SOURCE_FILE","relationship_type":"REFERENCED_BY","extra":"Wiki references source file: backend/app/models/citation_record.py","gmt_create":"2026-04-23T20:35:18.637558+08:00","gmt_modified":"2026-04-23T20:35:18.637558+08:00"},{"id":927,"source_id":"2126339b-b0f5-4152-924b-cbe028cd0c39","target_id":"069738f21ac2da7349d22683e8c36929","source_type":"WIKI_ITEM","target_type":"SOURCE_FILE","relationship_type":"REFERENCED_BY","extra":"Wiki references source file: backend/app/models/query_task.py","gmt_create":"2026-04-23T20:35:18.637924+08:00","gmt_modified":"2026-04-23T20:35:18.637924+08:00"},{"id":928,"source_id":"2126339b-b0f5-4152-924b-cbe028cd0c39","target_id":"88d22de3b2a7419868e8ae19130d860c","source_type":"WIKI_ITEM","target_type":"SOURCE_FILE","relationship_type":"REFERENCED_BY","extra":"Wiki references source file: backend/app/services/query.py","gmt_create":"2026-04-23T20:35:18.638407+08:00","gmt_modified":"2026-04-23T20:35:18.638407+08:00"},{"id":929,"source_id":"2126339b-b0f5-4152-924b-cbe028cd0c39","target_id":"04e3926c080e795713bff683e7dc9d3e","source_type":"WIKI_ITEM","target_type":"SOURCE_FILE","relationship_type":"REFERENCED_BY","extra":"Wiki references source file: backend/app/services/citation.py","gmt_create":"2026-04-23T20:35:18.638942+08:00","gmt_modified":"2026-04-23T20:35:18.638942+08:00"},{"id":930,"source_id":"2126339b-b0f5-4152-924b-cbe028cd0c39","target_id":"6b3d903205941aa9391dd90016e1102c","source_type":"WIKI_ITEM","target_type":"SOURCE_FILE","relationship_type":"REFERENCED_BY","extra":"Wiki references source file: backend/app/api/queries.py","gmt_create":"2026-04-23T20:35:18.641162+08:00","gmt_modified":"2026-04-23T20:35:18.641162+08:00"},{"id":931,"source_id":"2126339b-b0f5-4152-924b-cbe028cd0c39","target_id":"7538ffe4902ab6041adb28b19844962a","source_type":"WIKI_ITEM","target_type":"SOURCE_FILE","relationship_type":"REFERENCED_BY","extra":"Wiki references source file: backend/app/api/citations.py","gmt_create":"2026-04-23T20:35:18.642251+08:00","gmt_modified":"2026-04-23T20:35:18.642251+08:00"},{"id":932,"source_id":"2126339b-b0f5-4152-924b-cbe028cd0c39","target_id":"9228ff67d4c757a85d9421b71f4b29f5","source_type":"WIKI_ITEM","target_type":"SOURCE_FILE","relationship_type":"REFERENCED_BY","extra":"Wiki references source file: backend/app/main.py","gmt_create":"2026-04-23T20:35:18.642925+08:00","gmt_modified":"2026-04-23T20:35:18.642925+08:00"},{"id":933,"source_id":"2126339b-b0f5-4152-924b-cbe028cd0c39","target_id":"ef72f0c3cedb9fd9a87352fe493053dc","source_type":"WIKI_ITEM","target_type":"SOURCE_FILE","relationship_type":"REFERENCED_BY","extra":"Wiki references source file: frontend/lib/platforms.ts","gmt_create":"2026-04-23T20:35:18.643414+08:00","gmt_modified":"2026-04-23T20:35:18.643415+08:00"},{"id":934,"source_id":"2126339b-b0f5-4152-924b-cbe028cd0c39","target_id":"096856da621e23e78422a15e2bfce1f1","source_type":"WIKI_ITEM","target_type":"CODE_SNIPPET","relationship_type":"CONTAINS","extra":"Wiki contains code snippet: backend/app/main.py#13-22","gmt_create":"2026-04-23T20:35:18.643912+08:00","gmt_modified":"2026-04-23T20:35:18.643912+08:00"},{"id":935,"source_id":"2126339b-b0f5-4152-924b-cbe028cd0c39","target_id":"129573d2bbcde48697ed0e75dea12396","source_type":"WIKI_ITEM","target_type":"CODE_SNIPPET","relationship_type":"CONTAINS","extra":"Wiki contains code snippet: backend/app/workers/scheduler.py#25-40","gmt_create":"2026-04-23T20:35:18.645078+08:00","gmt_modified":"2026-04-23T20:35:18.645078+08:00"},{"id":936,"source_id":"5cbb1e3f112aeba62a14b0b8999fc0f5","target_id":"129573d2bbcde48697ed0e75dea12396","source_type":"SOURCE_FILE","target_type":"CODE_SNIPPET","relationship_type":"CONTAINS","extra":"Source file contains code snippet: 25-40","gmt_create":"2026-04-23T20:35:18.646964+08:00","gmt_modified":"2026-04-23T20:35:18.646965+08:00"},{"id":937,"source_id":"2126339b-b0f5-4152-924b-cbe028cd0c39","target_id":"cf18c97a9be6c78aa43cc229ed3dad20","source_type":"WIKI_ITEM","target_type":"CODE_SNIPPET","relationship_type":"CONTAINS","extra":"Wiki contains code snippet: backend/app/workers/citation_engine.py#164-173","gmt_create":"2026-04-23T20:35:18.647598+08:00","gmt_modified":"2026-04-23T20:35:18.647598+08:00"},{"id":938,"source_id":"74040de652d5e57f548bb5c4adc3e1a0","target_id":"cf18c97a9be6c78aa43cc229ed3dad20","source_type":"SOURCE_FILE","target_type":"CODE_SNIPPET","relationship_type":"CONTAINS","extra":"Source file contains code snippet: 164-173","gmt_create":"2026-04-23T20:35:18.647972+08:00","gmt_modified":"2026-04-23T20:35:18.647972+08:00"},{"id":939,"source_id":"2126339b-b0f5-4152-924b-cbe028cd0c39","target_id":"3c7ca5d582dca31c2530b1ce9c058e95","source_type":"WIKI_ITEM","target_type":"CODE_SNIPPET","relationship_type":"CONTAINS","extra":"Wiki contains code snippet: backend/app/workers/platforms/kimi.py#10-37","gmt_create":"2026-04-23T20:35:18.648459+08:00","gmt_modified":"2026-04-23T20:35:18.64846+08:00"},{"id":940,"source_id":"8f973791233c698b3e64a4fb28a93d4b","target_id":"3c7ca5d582dca31c2530b1ce9c058e95","source_type":"SOURCE_FILE","target_type":"CODE_SNIPPET","relationship_type":"CONTAINS","extra":"Source file contains code snippet: 10-37","gmt_create":"2026-04-23T20:35:18.648785+08:00","gmt_modified":"2026-04-23T20:35:18.648785+08:00"},{"id":941,"source_id":"2126339b-b0f5-4152-924b-cbe028cd0c39","target_id":"9f82f6d82bf914a608d6afa3d9854abf","source_type":"WIKI_ITEM","target_type":"CODE_SNIPPET","relationship_type":"CONTAINS","extra":"Wiki contains code snippet: backend/app/workers/platforms/search_engine.py#1-174","gmt_create":"2026-04-23T20:35:18.649264+08:00","gmt_modified":"2026-04-23T20:35:18.649264+08:00"},{"id":942,"source_id":"2126339b-b0f5-4152-924b-cbe028cd0c39","target_id":"b74caccb06844efcdb14d8324cff65c2","source_type":"WIKI_ITEM","target_type":"SOURCE_FILE","relationship_type":"REFERENCED_BY","extra":"Wiki references source file: backend/app/models/query.py","gmt_create":"2026-04-23T20:35:18.650358+08:00","gmt_modified":"2026-04-23T20:35:18.650358+08:00"},{"id":943,"source_id":"2126339b-b0f5-4152-924b-cbe028cd0c39","target_id":"4fb8856be3a581fe8303d11b2284ca29","source_type":"WIKI_ITEM","target_type":"CODE_SNIPPET","relationship_type":"CONTAINS","extra":"Wiki contains code snippet: backend/app/models/query.py#11-55","gmt_create":"2026-04-23T20:35:18.650954+08:00","gmt_modified":"2026-04-23T20:35:18.650954+08:00"},{"id":944,"source_id":"2126339b-b0f5-4152-924b-cbe028cd0c39","target_id":"fd541971cebf8a7c167d717f5c5d1ff6","source_type":"WIKI_ITEM","target_type":"CODE_SNIPPET","relationship_type":"CONTAINS","extra":"Wiki contains code snippet: backend/app/models/citation_record.py#11-42","gmt_create":"2026-04-23T20:35:18.652232+08:00","gmt_modified":"2026-04-23T20:35:18.652232+08:00"},{"id":945,"source_id":"2126339b-b0f5-4152-924b-cbe028cd0c39","target_id":"b84f46f058847733347974841f613688","source_type":"WIKI_ITEM","target_type":"CODE_SNIPPET","relationship_type":"CONTAINS","extra":"Wiki contains code snippet: backend/app/models/query_task.py#11-39","gmt_create":"2026-04-23T20:35:18.653511+08:00","gmt_modified":"2026-04-23T20:35:18.653511+08:00"},{"id":946,"source_id":"2126339b-b0f5-4152-924b-cbe028cd0c39","target_id":"27047f868643e5457d4f242b4298a9f6","source_type":"WIKI_ITEM","target_type":"CODE_SNIPPET","relationship_type":"CONTAINS","extra":"Wiki contains code snippet: frontend/lib/platforms.ts#1-23","gmt_create":"2026-04-23T20:35:18.654994+08:00","gmt_modified":"2026-04-23T20:35:18.654994+08:00"},{"id":947,"source_id":"ef72f0c3cedb9fd9a87352fe493053dc","target_id":"27047f868643e5457d4f242b4298a9f6","source_type":"SOURCE_FILE","target_type":"CODE_SNIPPET","relationship_type":"CONTAINS","extra":"Source file contains code snippet: 1-23","gmt_create":"2026-04-23T20:35:18.6556+08:00","gmt_modified":"2026-04-23T20:35:18.6556+08:00"},{"id":948,"source_id":"2126339b-b0f5-4152-924b-cbe028cd0c39","target_id":"557ae34b57a5dd8e8fa3bb2a6ce178a7","source_type":"WIKI_ITEM","target_type":"CODE_SNIPPET","relationship_type":"CONTAINS","extra":"Wiki contains code snippet: backend/app/workers/platforms/search_engine.py#163-174","gmt_create":"2026-04-23T20:35:18.657485+08:00","gmt_modified":"2026-04-23T20:35:18.657486+08:00"},{"id":949,"source_id":"2126339b-b0f5-4152-924b-cbe028cd0c39","target_id":"1526e4e02133a48eac04befb74ec5bd1","source_type":"WIKI_ITEM","target_type":"CODE_SNIPPET","relationship_type":"CONTAINS","extra":"Wiki contains code snippet: backend/app/workers/citation_engine.py#161-173","gmt_create":"2026-04-23T20:35:18.65887+08:00","gmt_modified":"2026-04-23T20:35:18.65887+08:00"},{"id":950,"source_id":"74040de652d5e57f548bb5c4adc3e1a0","target_id":"1526e4e02133a48eac04befb74ec5bd1","source_type":"SOURCE_FILE","target_type":"CODE_SNIPPET","relationship_type":"CONTAINS","extra":"Source file contains code snippet: 161-173","gmt_create":"2026-04-23T20:35:18.659265+08:00","gmt_modified":"2026-04-23T20:35:18.659265+08:00"},{"id":951,"source_id":"2126339b-b0f5-4152-924b-cbe028cd0c39","target_id":"98c02d9bb7aa6e2b6be5f7381e64fd99","source_type":"WIKI_ITEM","target_type":"CODE_SNIPPET","relationship_type":"CONTAINS","extra":"Wiki contains code snippet: backend/app/api/queries.py#26-39","gmt_create":"2026-04-23T20:35:18.661103+08:00","gmt_modified":"2026-04-23T20:35:18.661103+08:00"},{"id":952,"source_id":"6b3d903205941aa9391dd90016e1102c","target_id":"98c02d9bb7aa6e2b6be5f7381e64fd99","source_type":"SOURCE_FILE","target_type":"CODE_SNIPPET","relationship_type":"CONTAINS","extra":"Source file contains code snippet: 26-39","gmt_create":"2026-04-23T20:35:18.661433+08:00","gmt_modified":"2026-04-23T20:35:18.661433+08:00"},{"id":953,"source_id":"2126339b-b0f5-4152-924b-cbe028cd0c39","target_id":"212d822d207a4c0bd7825bbf20e188e9","source_type":"WIKI_ITEM","target_type":"CODE_SNIPPET","relationship_type":"CONTAINS","extra":"Wiki contains code snippet: backend/app/api/citations.py#59-77","gmt_create":"2026-04-23T20:35:18.661922+08:00","gmt_modified":"2026-04-23T20:35:18.661922+08:00"},{"id":954,"source_id":"2126339b-b0f5-4152-924b-cbe028cd0c39","target_id":"9b10dac7dbbb1327afc8a525bf4bd0c3","source_type":"WIKI_ITEM","target_type":"CODE_SNIPPET","relationship_type":"CONTAINS","extra":"Wiki contains code snippet: backend/app/services/query.py#45-81","gmt_create":"2026-04-23T20:35:18.662781+08:00","gmt_modified":"2026-04-23T20:35:18.662781+08:00"},{"id":955,"source_id":"2126339b-b0f5-4152-924b-cbe028cd0c39","target_id":"4ded871d02b8119cdd985de8b220b084","source_type":"WIKI_ITEM","target_type":"CODE_SNIPPET","relationship_type":"CONTAINS","extra":"Wiki contains code snippet: backend/app/services/citation.py#204-234","gmt_create":"2026-04-23T20:35:18.680675+08:00","gmt_modified":"2026-04-23T20:35:18.680675+08:00"},{"id":956,"source_id":"2126339b-b0f5-4152-924b-cbe028cd0c39","target_id":"448970b02d89d5e1576f70bdb0063363","source_type":"WIKI_ITEM","target_type":"CODE_SNIPPET","relationship_type":"CONTAINS","extra":"Wiki contains code snippet: backend/app/workers/scheduler.py#51-84","gmt_create":"2026-04-23T20:35:18.68314+08:00","gmt_modified":"2026-04-23T20:35:18.68314+08:00"},{"id":957,"source_id":"2126339b-b0f5-4152-924b-cbe028cd0c39","target_id":"8565f299083b4dcba5a328c947f06fee","source_type":"WIKI_ITEM","target_type":"CODE_SNIPPET","relationship_type":"CONTAINS","extra":"Wiki contains code snippet: backend/app/workers/citation_engine.py#256-287","gmt_create":"2026-04-23T20:35:18.685341+08:00","gmt_modified":"2026-04-23T20:35:18.685341+08:00"},{"id":958,"source_id":"2126339b-b0f5-4152-924b-cbe028cd0c39","target_id":"52c01d7b9c17aa16944cbfcf8885be61","source_type":"WIKI_ITEM","target_type":"CODE_SNIPPET","relationship_type":"CONTAINS","extra":"Wiki contains code snippet: backend/app/workers/platforms/kimi.py#16-33","gmt_create":"2026-04-23T20:35:18.686894+08:00","gmt_modified":"2026-04-23T20:35:18.686894+08:00"},{"id":959,"source_id":"2126339b-b0f5-4152-924b-cbe028cd0c39","target_id":"2a971cb83924013902324eceeab22559","source_type":"WIKI_ITEM","target_type":"CODE_SNIPPET","relationship_type":"CONTAINS","extra":"Wiki contains code snippet: backend/app/workers/platforms/kimi.py#16-29","gmt_create":"2026-04-23T20:35:18.689849+08:00","gmt_modified":"2026-04-23T20:35:18.689849+08:00"},{"id":960,"source_id":"8f973791233c698b3e64a4fb28a93d4b","target_id":"2a971cb83924013902324eceeab22559","source_type":"SOURCE_FILE","target_type":"CODE_SNIPPET","relationship_type":"CONTAINS","extra":"Source file contains code snippet: 16-29","gmt_create":"2026-04-23T20:35:18.69154+08:00","gmt_modified":"2026-04-23T20:35:18.69154+08:00"},{"id":961,"source_id":"2126339b-b0f5-4152-924b-cbe028cd0c39","target_id":"99326fedad9275392719105b5b6782d6","source_type":"WIKI_ITEM","target_type":"CODE_SNIPPET","relationship_type":"CONTAINS","extra":"Wiki contains code snippet: backend/app/workers/platforms/kimi.py#31-33","gmt_create":"2026-04-23T20:35:18.692776+08:00","gmt_modified":"2026-04-23T20:35:18.692776+08:00"},{"id":962,"source_id":"8f973791233c698b3e64a4fb28a93d4b","target_id":"99326fedad9275392719105b5b6782d6","source_type":"SOURCE_FILE","target_type":"CODE_SNIPPET","relationship_type":"CONTAINS","extra":"Source file contains code snippet: 31-33","gmt_create":"2026-04-23T20:35:18.693945+08:00","gmt_modified":"2026-04-23T20:35:18.693945+08:00"},{"id":963,"source_id":"2126339b-b0f5-4152-924b-cbe028cd0c39","target_id":"102223dd13475177a1ade8b9be14fbd1","source_type":"WIKI_ITEM","target_type":"CODE_SNIPPET","relationship_type":"CONTAINS","extra":"Wiki contains code snippet: backend/app/workers/platforms/search_engine.py#79-144","gmt_create":"2026-04-23T20:35:18.695323+08:00","gmt_modified":"2026-04-23T20:35:18.695324+08:00"},{"id":964,"source_id":"2126339b-b0f5-4152-924b-cbe028cd0c39","target_id":"5e5dacc623918c0f1eba234154c99291","source_type":"WIKI_ITEM","target_type":"CODE_SNIPPET","relationship_type":"CONTAINS","extra":"Wiki contains code snippet: backend/app/workers/platforms/search_engine.py#16-76","gmt_create":"2026-04-23T20:35:18.696341+08:00","gmt_modified":"2026-04-23T20:35:18.696341+08:00"},{"id":965,"source_id":"6a63f048c16c60c5d2d57012c810ee0e","target_id":"5e5dacc623918c0f1eba234154c99291","source_type":"SOURCE_FILE","target_type":"CODE_SNIPPET","relationship_type":"CONTAINS","extra":"Source file contains code snippet: 16-76","gmt_create":"2026-04-23T20:35:18.697266+08:00","gmt_modified":"2026-04-23T20:35:18.697267+08:00"},{"id":966,"source_id":"2126339b-b0f5-4152-924b-cbe028cd0c39","target_id":"5be7e6cf82d6359efddaf131aaf92615","source_type":"WIKI_ITEM","target_type":"CODE_SNIPPET","relationship_type":"CONTAINS","extra":"Wiki contains code snippet: backend/app/workers/citation_engine.py#323-330","gmt_create":"2026-04-23T20:35:18.701473+08:00","gmt_modified":"2026-04-23T20:35:18.701473+08:00"},{"id":967,"source_id":"74040de652d5e57f548bb5c4adc3e1a0","target_id":"5be7e6cf82d6359efddaf131aaf92615","source_type":"SOURCE_FILE","target_type":"CODE_SNIPPET","relationship_type":"CONTAINS","extra":"Source file contains code snippet: 323-330","gmt_create":"2026-04-23T20:35:18.7021+08:00","gmt_modified":"2026-04-23T20:35:18.7021+08:00"},{"id":968,"source_id":"2126339b-b0f5-4152-924b-cbe028cd0c39","target_id":"129b746e71a9013ceb1b0fcc59942b39","source_type":"WIKI_ITEM","target_type":"CODE_SNIPPET","relationship_type":"CONTAINS","extra":"Wiki contains code snippet: backend/app/workers/scheduler.py#86-90","gmt_create":"2026-04-23T20:35:18.703871+08:00","gmt_modified":"2026-04-23T20:35:18.703871+08:00"},{"id":969,"source_id":"5cbb1e3f112aeba62a14b0b8999fc0f5","target_id":"129b746e71a9013ceb1b0fcc59942b39","source_type":"SOURCE_FILE","target_type":"CODE_SNIPPET","relationship_type":"CONTAINS","extra":"Source file contains code snippet: 86-90","gmt_create":"2026-04-23T20:35:18.709231+08:00","gmt_modified":"2026-04-23T20:35:18.709231+08:00"},{"id":970,"source_id":"2126339b-b0f5-4152-924b-cbe028cd0c39","target_id":"fe70b1fef9f36e73d26d84987e927c7a","source_type":"WIKI_ITEM","target_type":"CODE_SNIPPET","relationship_type":"CONTAINS","extra":"Wiki contains code snippet: backend/app/api/queries.py#15-86","gmt_create":"2026-04-23T20:35:18.712574+08:00","gmt_modified":"2026-04-23T20:35:18.712574+08:00"},{"id":971,"source_id":"2126339b-b0f5-4152-924b-cbe028cd0c39","target_id":"c066a8d4bffabed87a2e38ccad81c107","source_type":"WIKI_ITEM","target_type":"CODE_SNIPPET","relationship_type":"CONTAINS","extra":"Wiki contains code snippet: backend/app/api/citations.py#25-77","gmt_create":"2026-04-23T20:35:18.713529+08:00","gmt_modified":"2026-04-23T20:35:18.713529+08:00"},{"id":972,"source_id":"2126339b-b0f5-4152-924b-cbe028cd0c39","target_id":"d7c319a04abbc6704da53107e07dd8e7","source_type":"WIKI_ITEM","target_type":"CODE_SNIPPET","relationship_type":"CONTAINS","extra":"Wiki contains code snippet: backend/app/services/query.py#12-130","gmt_create":"2026-04-23T20:35:18.714412+08:00","gmt_modified":"2026-04-23T20:35:18.714412+08:00"},{"id":973,"source_id":"2126339b-b0f5-4152-924b-cbe028cd0c39","target_id":"d780e807ee751f39f331a658b47c4ed3","source_type":"WIKI_ITEM","target_type":"CODE_SNIPPET","relationship_type":"CONTAINS","extra":"Wiki contains code snippet: backend/app/services/citation.py#24-269","gmt_create":"2026-04-23T20:35:18.715261+08:00","gmt_modified":"2026-04-23T20:35:18.715261+08:00"},{"id":974,"source_id":"04e3926c080e795713bff683e7dc9d3e","target_id":"d780e807ee751f39f331a658b47c4ed3","source_type":"SOURCE_FILE","target_type":"CODE_SNIPPET","relationship_type":"CONTAINS","extra":"Source file contains code snippet: 24-269","gmt_create":"2026-04-23T20:35:18.716135+08:00","gmt_modified":"2026-04-23T20:35:18.716135+08:00"},{"id":975,"source_id":"2126339b-b0f5-4152-924b-cbe028cd0c39","target_id":"8eea43550951387ac740b5e3e64c7691","source_type":"WIKI_ITEM","target_type":"CODE_SNIPPET","relationship_type":"CONTAINS","extra":"Wiki contains code snippet: backend/app/workers/platforms/search_engine.py#94-96","gmt_create":"2026-04-23T20:35:18.720519+08:00","gmt_modified":"2026-04-23T20:35:18.720519+08:00"},{"id":976,"source_id":"6a63f048c16c60c5d2d57012c810ee0e","target_id":"8eea43550951387ac740b5e3e64c7691","source_type":"SOURCE_FILE","target_type":"CODE_SNIPPET","relationship_type":"CONTAINS","extra":"Source file contains code snippet: 94-96","gmt_create":"2026-04-23T20:35:18.72132+08:00","gmt_modified":"2026-04-23T20:35:18.72132+08:00"},{"id":977,"source_id":"2126339b-b0f5-4152-924b-cbe028cd0c39","target_id":"ed527c7a549ec333c2b30b59614343df","source_type":"WIKI_ITEM","target_type":"CODE_SNIPPET","relationship_type":"CONTAINS","extra":"Wiki contains code snippet: backend/app/models/query.py#50-54","gmt_create":"2026-04-23T20:35:18.72244+08:00","gmt_modified":"2026-04-23T20:35:18.72244+08:00"},{"id":978,"source_id":"2126339b-b0f5-4152-924b-cbe028cd0c39","target_id":"a2adbf02c71e4eb2cf1f120e1a2ff517","source_type":"WIKI_ITEM","target_type":"CODE_SNIPPET","relationship_type":"CONTAINS","extra":"Wiki contains code snippet: backend/app/models/citation_record.py#37-41","gmt_create":"2026-04-23T20:35:18.725156+08:00","gmt_modified":"2026-04-23T20:35:18.725157+08:00"},{"id":979,"source_id":"2126339b-b0f5-4152-924b-cbe028cd0c39","target_id":"b55cc5936c299f819b57b899858438e6","source_type":"WIKI_ITEM","target_type":"CODE_SNIPPET","relationship_type":"CONTAINS","extra":"Wiki contains code snippet: backend/app/workers/platforms/search_engine.py#139-144","gmt_create":"2026-04-23T20:35:18.727146+08:00","gmt_modified":"2026-04-23T20:35:18.727146+08:00"},{"id":980,"source_id":"2126339b-b0f5-4152-924b-cbe028cd0c39","target_id":"37769b7e6b5588be0065681dedf514ed","source_type":"WIKI_ITEM","target_type":"CODE_SNIPPET","relationship_type":"CONTAINS","extra":"Wiki contains code snippet: backend/app/workers/platforms/search_engine.py#140-144","gmt_create":"2026-04-23T20:35:18.728033+08:00","gmt_modified":"2026-04-23T20:35:18.728033+08:00"},{"id":981,"source_id":"6a63f048c16c60c5d2d57012c810ee0e","target_id":"37769b7e6b5588be0065681dedf514ed","source_type":"SOURCE_FILE","target_type":"CODE_SNIPPET","relationship_type":"CONTAINS","extra":"Source file contains code snippet: 140-144","gmt_create":"2026-04-23T20:35:18.728855+08:00","gmt_modified":"2026-04-23T20:35:18.728855+08:00"},{"id":982,"source_id":"2126339b-b0f5-4152-924b-cbe028cd0c39","target_id":"518d184988b97ebc7ef0c0bf5c10f42c","source_type":"WIKI_ITEM","target_type":"CODE_SNIPPET","relationship_type":"CONTAINS","extra":"Wiki contains code snippet: backend/app/workers/platforms/kimi.py#24-29","gmt_create":"2026-04-23T20:35:18.72968+08:00","gmt_modified":"2026-04-23T20:35:18.72968+08:00"},{"id":983,"source_id":"8f973791233c698b3e64a4fb28a93d4b","target_id":"518d184988b97ebc7ef0c0bf5c10f42c","source_type":"SOURCE_FILE","target_type":"CODE_SNIPPET","relationship_type":"CONTAINS","extra":"Source file contains code snippet: 24-29","gmt_create":"2026-04-23T20:35:18.730545+08:00","gmt_modified":"2026-04-23T20:35:18.730546+08:00"},{"id":984,"source_id":"2126339b-b0f5-4152-924b-cbe028cd0c39","target_id":"818504ee2e17d2f9cc8fe115ca321138","source_type":"WIKI_ITEM","target_type":"CODE_SNIPPET","relationship_type":"CONTAINS","extra":"Wiki contains code snippet: backend/app/api/queries.py#34-38","gmt_create":"2026-04-23T20:35:18.73162+08:00","gmt_modified":"2026-04-23T20:35:18.73162+08:00"},{"id":985,"source_id":"6b3d903205941aa9391dd90016e1102c","target_id":"818504ee2e17d2f9cc8fe115ca321138","source_type":"SOURCE_FILE","target_type":"CODE_SNIPPET","relationship_type":"CONTAINS","extra":"Source file contains code snippet: 34-38","gmt_create":"2026-04-23T20:35:18.732614+08:00","gmt_modified":"2026-04-23T20:35:18.732614+08:00"},{"id":986,"source_id":"2126339b-b0f5-4152-924b-cbe028cd0c39","target_id":"55f1628f1ab6f323710e367e12146b1a","source_type":"WIKI_ITEM","target_type":"CODE_SNIPPET","relationship_type":"CONTAINS","extra":"Wiki contains code snippet: backend/app/api/citations.py#67-71","gmt_create":"2026-04-23T20:35:18.733467+08:00","gmt_modified":"2026-04-23T20:35:18.733467+08:00"},{"id":987,"source_id":"2126339b-b0f5-4152-924b-cbe028cd0c39","target_id":"8a1a0ffd82ac6ff54d3410e4ce59a6b8","source_type":"WIKI_ITEM","target_type":"CODE_SNIPPET","relationship_type":"CONTAINS","extra":"Wiki contains code snippet: backend/app/api/citations.py#25-56","gmt_create":"2026-04-23T20:35:18.735579+08:00","gmt_modified":"2026-04-23T20:35:18.735579+08:00"},{"id":988,"source_id":"7538ffe4902ab6041adb28b19844962a","target_id":"8a1a0ffd82ac6ff54d3410e4ce59a6b8","source_type":"SOURCE_FILE","target_type":"CODE_SNIPPET","relationship_type":"CONTAINS","extra":"Source file contains code snippet: 25-56","gmt_create":"2026-04-23T20:35:18.73663+08:00","gmt_modified":"2026-04-23T20:35:18.73663+08:00"},{"id":1012,"source_id":"b4a81ef789630d0af6a8d50859d01bf3","target_id":"d4f99d3dd9fe489c354edf5fe2f8803d","source_type":"SOURCE_FILE","target_type":"CODE_SNIPPET","relationship_type":"CONTAINS","extra":"Source file contains code snippet: 1-44","gmt_create":"2026-04-23T20:35:45.713712+08:00","gmt_modified":"2026-04-23T20:35:45.713713+08:00"},{"id":1015,"source_id":"bceca00463fe55d3bcafda728f97f723","target_id":"86e37040be1aeb400fab9b529f5404c8","source_type":"SOURCE_FILE","target_type":"CODE_SNIPPET","relationship_type":"CONTAINS","extra":"Source file contains code snippet: 1-37","gmt_create":"2026-04-23T20:35:45.722046+08:00","gmt_modified":"2026-04-23T20:35:45.722047+08:00"},{"id":1017,"source_id":"a680d4819f5da57fe9fa0e6bc708f380","target_id":"211463f5b49610f09594c40c0a235943","source_type":"SOURCE_FILE","target_type":"CODE_SNIPPET","relationship_type":"CONTAINS","extra":"Source file contains code snippet: 1-89","gmt_create":"2026-04-23T20:35:45.736063+08:00","gmt_modified":"2026-04-23T20:35:45.736064+08:00"},{"id":1019,"source_id":"fc6242433ae9506bcc0bf4cb0dce1413","target_id":"48d22eaee09e364a293ad6c4750f5c5a","source_type":"SOURCE_FILE","target_type":"CODE_SNIPPET","relationship_type":"CONTAINS","extra":"Source file contains code snippet: 1-71","gmt_create":"2026-04-23T20:35:45.743112+08:00","gmt_modified":"2026-04-23T20:35:45.743112+08:00"},{"id":1022,"source_id":"d4f95fcf50683b5bf6167c7d2a6b126d","target_id":"98cc82f62b83678f06a33cf9231ecdf8","source_type":"SOURCE_FILE","target_type":"CODE_SNIPPET","relationship_type":"CONTAINS","extra":"Source file contains code snippet: 1-128","gmt_create":"2026-04-23T20:35:45.771158+08:00","gmt_modified":"2026-04-23T20:35:45.771158+08:00"},{"id":1024,"source_id":"f6e6948dd0cdd3894bd9928b21feb979","target_id":"e1aabd52989e47806fb997157381e1cf","source_type":"SOURCE_FILE","target_type":"CODE_SNIPPET","relationship_type":"CONTAINS","extra":"Source file contains code snippet: 1-37","gmt_create":"2026-04-23T20:35:45.782446+08:00","gmt_modified":"2026-04-23T20:35:45.782446+08:00"},{"id":1028,"source_id":"d4f95fcf50683b5bf6167c7d2a6b126d","target_id":"ac77e4875817616194b7b5997d4fb1ae","source_type":"SOURCE_FILE","target_type":"CODE_SNIPPET","relationship_type":"CONTAINS","extra":"Source file contains code snippet: 57-94","gmt_create":"2026-04-23T20:35:45.808076+08:00","gmt_modified":"2026-04-23T20:35:45.808076+08:00"},{"id":1030,"source_id":"f6e6948dd0cdd3894bd9928b21feb979","target_id":"0e57efd98dacc85da21f995980371ee4","source_type":"SOURCE_FILE","target_type":"CODE_SNIPPET","relationship_type":"CONTAINS","extra":"Source file contains code snippet: 21-37","gmt_create":"2026-04-23T20:35:45.81891+08:00","gmt_modified":"2026-04-23T20:35:45.81891+08:00"},{"id":1033,"source_id":"b4a81ef789630d0af6a8d50859d01bf3","target_id":"717eb27184726e4f78d694984d29420c","source_type":"SOURCE_FILE","target_type":"CODE_SNIPPET","relationship_type":"CONTAINS","extra":"Source file contains code snippet: 37-44","gmt_create":"2026-04-23T20:35:45.831123+08:00","gmt_modified":"2026-04-23T20:35:45.831123+08:00"},{"id":1037,"source_id":"b74caccb06844efcdb14d8324cff65c2","target_id":"bfdf3479f244dc6794628d9df10ab6d0","source_type":"SOURCE_FILE","target_type":"CODE_SNIPPET","relationship_type":"CONTAINS","extra":"Source file contains code snippet: 11-48","gmt_create":"2026-04-23T20:35:45.842187+08:00","gmt_modified":"2026-04-23T20:35:45.842187+08:00"},{"id":1039,"source_id":"b4a81ef789630d0af6a8d50859d01bf3","target_id":"f5f9f0d96263ae84631c7a8d7e9b3648","source_type":"SOURCE_FILE","target_type":"CODE_SNIPPET","relationship_type":"CONTAINS","extra":"Source file contains code snippet: 11-44","gmt_create":"2026-04-23T20:35:45.84404+08:00","gmt_modified":"2026-04-23T20:35:45.84404+08:00"},{"id":1041,"source_id":"069738f21ac2da7349d22683e8c36929","target_id":"818d1354dc0665798f3d91a2ca5153d6","source_type":"SOURCE_FILE","target_type":"CODE_SNIPPET","relationship_type":"CONTAINS","extra":"Source file contains code snippet: 11-34","gmt_create":"2026-04-23T20:35:45.845935+08:00","gmt_modified":"2026-04-23T20:35:45.845935+08:00"},{"id":1043,"source_id":"bceca00463fe55d3bcafda728f97f723","target_id":"24aade4c34609a8ab28e4643a3692201","source_type":"SOURCE_FILE","target_type":"CODE_SNIPPET","relationship_type":"CONTAINS","extra":"Source file contains code snippet: 11-36","gmt_create":"2026-04-23T20:35:45.853262+08:00","gmt_modified":"2026-04-23T20:35:45.853263+08:00"},{"id":1045,"source_id":"a680d4819f5da57fe9fa0e6bc708f380","target_id":"d34337b9ff77246979252d2fd8fb8018","source_type":"SOURCE_FILE","target_type":"CODE_SNIPPET","relationship_type":"CONTAINS","extra":"Source file contains code snippet: 33-88","gmt_create":"2026-04-23T20:35:45.866334+08:00","gmt_modified":"2026-04-23T20:35:45.866335+08:00"},{"id":1048,"source_id":"d4f95fcf50683b5bf6167c7d2a6b126d","target_id":"eb63042f04a22f9a67bd498df1684d20","source_type":"SOURCE_FILE","target_type":"CODE_SNIPPET","relationship_type":"CONTAINS","extra":"Source file contains code snippet: 36-111","gmt_create":"2026-04-23T20:35:45.883763+08:00","gmt_modified":"2026-04-23T20:35:45.883763+08:00"},{"id":1051,"source_id":"b0c428683c8a3e6922d90ca0d8c2736d","target_id":"c651c7ad6747a92ee96eabb2eb82afdd","source_type":"SOURCE_FILE","target_type":"CODE_SNIPPET","relationship_type":"CONTAINS","extra":"Source file contains code snippet: 12-18","gmt_create":"2026-04-23T20:35:45.891674+08:00","gmt_modified":"2026-04-23T20:35:45.891674+08:00"},{"id":1053,"source_id":"04e3926c080e795713bff683e7dc9d3e","target_id":"dd01eee487298a28e950f6345196f1d4","source_type":"SOURCE_FILE","target_type":"CODE_SNIPPET","relationship_type":"CONTAINS","extra":"Source file contains code snippet: 30-79","gmt_create":"2026-04-23T20:35:45.895814+08:00","gmt_modified":"2026-04-23T20:35:45.895814+08:00"},{"id":1055,"source_id":"88d22de3b2a7419868e8ae19130d860c","target_id":"7dae7237f11c5100bf7889c105193cf6","source_type":"SOURCE_FILE","target_type":"CODE_SNIPPET","relationship_type":"CONTAINS","extra":"Source file contains code snippet: 12-32","gmt_create":"2026-04-23T20:35:45.901349+08:00","gmt_modified":"2026-04-23T20:35:45.901349+08:00"},{"id":1057,"source_id":"04e3926c080e795713bff683e7dc9d3e","target_id":"cc64cf609f5ff218f618e0664ffa7cc7","source_type":"SOURCE_FILE","target_type":"CODE_SNIPPET","relationship_type":"CONTAINS","extra":"Source file contains code snippet: 298-308","gmt_create":"2026-04-23T20:35:45.904411+08:00","gmt_modified":"2026-04-23T20:35:45.904411+08:00"},{"id":1059,"source_id":"04e3926c080e795713bff683e7dc9d3e","target_id":"ce7e334595a4ce912e0d116314db9a35","source_type":"SOURCE_FILE","target_type":"CODE_SNIPPET","relationship_type":"CONTAINS","extra":"Source file contains code snippet: 342-429","gmt_create":"2026-04-23T20:35:45.906963+08:00","gmt_modified":"2026-04-23T20:35:45.906964+08:00"},{"id":1061,"source_id":"1a3336b4af8a39a055e912724338580c","target_id":"2f46f212597e3c245b9e5dcc5dbc863d","source_type":"SOURCE_FILE","target_type":"CODE_SNIPPET","relationship_type":"CONTAINS","extra":"Source file contains code snippet: 7-18","gmt_create":"2026-04-23T20:35:45.909475+08:00","gmt_modified":"2026-04-23T20:35:45.909476+08:00"},{"id":1063,"source_id":"04e3926c080e795713bff683e7dc9d3e","target_id":"dc40f1dd3e59ee7f046019201068bea1","source_type":"SOURCE_FILE","target_type":"CODE_SNIPPET","relationship_type":"CONTAINS","extra":"Source file contains code snippet: 14-22","gmt_create":"2026-04-23T20:35:45.920772+08:00","gmt_modified":"2026-04-23T20:35:45.920772+08:00"},{"id":1069,"source_id":"deb919cc-9541-4ed7-a581-ae2876ea67c2","target_id":"a1cc822d-5382-431c-8c49-cf398fb5eb3c","source_type":"WIKI_ITEM","target_type":"WIKI_ITEM","relationship_type":"PARENT_CHILD","extra":"Wiki parent-child relationship: deb919cc-9541-4ed7-a581-ae2876ea67c2 -\u003e a1cc822d-5382-431c-8c49-cf398fb5eb3c","gmt_create":"2026-04-23T20:35:46.950364+08:00","gmt_modified":"2026-04-23T20:35:46.950364+08:00"},{"id":1070,"source_id":"cfc48cde-e1c3-47f6-afe2-a6d7a8f4ab69","target_id":"37003fc0-1cf5-4264-996b-40807001875f","source_type":"WIKI_ITEM","target_type":"WIKI_ITEM","relationship_type":"PARENT_CHILD","extra":"Wiki parent-child relationship: cfc48cde-e1c3-47f6-afe2-a6d7a8f4ab69 -\u003e 37003fc0-1cf5-4264-996b-40807001875f","gmt_create":"2026-04-23T20:35:46.957122+08:00","gmt_modified":"2026-04-23T20:35:46.957122+08:00"},{"id":1071,"source_id":"cfc48cde-e1c3-47f6-afe2-a6d7a8f4ab69","target_id":"2126339b-b0f5-4152-924b-cbe028cd0c39","source_type":"WIKI_ITEM","target_type":"WIKI_ITEM","relationship_type":"PARENT_CHILD","extra":"Wiki parent-child relationship: cfc48cde-e1c3-47f6-afe2-a6d7a8f4ab69 -\u003e 2126339b-b0f5-4152-924b-cbe028cd0c39","gmt_create":"2026-04-23T20:35:46.959782+08:00","gmt_modified":"2026-04-23T20:35:46.959782+08:00"},{"id":1072,"source_id":"cfc48cde-e1c3-47f6-afe2-a6d7a8f4ab69","target_id":"fab60eaf-9652-4cb5-9f9e-0525caa62d63","source_type":"WIKI_ITEM","target_type":"WIKI_ITEM","relationship_type":"PARENT_CHILD","extra":"Wiki parent-child relationship: cfc48cde-e1c3-47f6-afe2-a6d7a8f4ab69 -\u003e fab60eaf-9652-4cb5-9f9e-0525caa62d63","gmt_create":"2026-04-23T20:35:46.965729+08:00","gmt_modified":"2026-04-23T20:35:46.965729+08:00"},{"id":1073,"source_id":"cfc48cde-e1c3-47f6-afe2-a6d7a8f4ab69","target_id":"00359e45-209d-4be3-8795-50dea52bdba1","source_type":"WIKI_ITEM","target_type":"WIKI_ITEM","relationship_type":"PARENT_CHILD","extra":"Wiki parent-child relationship: cfc48cde-e1c3-47f6-afe2-a6d7a8f4ab69 -\u003e 00359e45-209d-4be3-8795-50dea52bdba1","gmt_create":"2026-04-23T20:35:46.970985+08:00","gmt_modified":"2026-04-23T20:35:46.970985+08:00"},{"id":1074,"source_id":"cfc48cde-e1c3-47f6-afe2-a6d7a8f4ab69","target_id":"2632a6f9-774e-4a91-94da-a984bdb20758","source_type":"WIKI_ITEM","target_type":"WIKI_ITEM","relationship_type":"PARENT_CHILD","extra":"Wiki parent-child relationship: cfc48cde-e1c3-47f6-afe2-a6d7a8f4ab69 -\u003e 2632a6f9-774e-4a91-94da-a984bdb20758","gmt_create":"2026-04-23T20:35:46.974435+08:00","gmt_modified":"2026-04-23T20:35:46.974435+08:00"},{"id":1094,"source_id":"5e414f2ef9b69e55e00ab15f85b9291a","target_id":"01a0c4b40819965823b56e9da858c024","source_type":"SOURCE_FILE","target_type":"CODE_SNIPPET","relationship_type":"CONTAINS","extra":"Source file contains code snippet: 1-15","gmt_create":"2026-04-23T21:00:59.664546+08:00","gmt_modified":"2026-04-23T21:00:59.664546+08:00"},{"id":1101,"source_id":"50f2e6bdc4a79e69bd43ea8d6fec67fe","target_id":"13f6ca76349ef86ae756bb519f122bc5","source_type":"SOURCE_FILE","target_type":"CODE_SNIPPET","relationship_type":"CONTAINS","extra":"Source file contains code snippet: 1-150","gmt_create":"2026-04-23T21:00:59.691641+08:00","gmt_modified":"2026-04-23T21:00:59.691641+08:00"},{"id":1103,"source_id":"fb8af100a06778e1fbdac4790a3ed0a9","target_id":"74abd6612105c29b67178fa9dbd04b61","source_type":"SOURCE_FILE","target_type":"CODE_SNIPPET","relationship_type":"CONTAINS","extra":"Source file contains code snippet: 1-27","gmt_create":"2026-04-23T21:00:59.696535+08:00","gmt_modified":"2026-04-23T21:00:59.696535+08:00"},{"id":1105,"source_id":"4d9b59c294a0aac5e300b3de715eb226","target_id":"5bdaabf085a7c3eb6e87c5ad7479e25d","source_type":"SOURCE_FILE","target_type":"CODE_SNIPPET","relationship_type":"CONTAINS","extra":"Source file contains code snippet: 1-4","gmt_create":"2026-04-23T21:00:59.697778+08:00","gmt_modified":"2026-04-23T21:00:59.697778+08:00"},{"id":1108,"source_id":"50f2e6bdc4a79e69bd43ea8d6fec67fe","target_id":"9482f4f6279a4f636b77e69b8273b996","source_type":"SOURCE_FILE","target_type":"CODE_SNIPPET","relationship_type":"CONTAINS","extra":"Source file contains code snippet: 86-114","gmt_create":"2026-04-23T21:00:59.700939+08:00","gmt_modified":"2026-04-23T21:00:59.70094+08:00"},{"id":1110,"source_id":"0ef1efea889dba3e1f299626df479571","target_id":"397b266f19a1addebdf6c32db71ae77f","source_type":"SOURCE_FILE","target_type":"CODE_SNIPPET","relationship_type":"CONTAINS","extra":"Source file contains code snippet: 1-71","gmt_create":"2026-04-23T21:00:59.703412+08:00","gmt_modified":"2026-04-23T21:00:59.703413+08:00"},{"id":1113,"source_id":"9ff19022ef915615911280e3c49ed44b","target_id":"eb603ec2611957de67af00756f4b1efa","source_type":"SOURCE_FILE","target_type":"CODE_SNIPPET","relationship_type":"CONTAINS","extra":"Source file contains code snippet: 7-13","gmt_create":"2026-04-23T21:00:59.713128+08:00","gmt_modified":"2026-04-23T21:00:59.713128+08:00"},{"id":1115,"source_id":"e9b52adbec3c07cf021e488dd3f99ab4","target_id":"c25b39830f3b7734da975acc7f214666","source_type":"SOURCE_FILE","target_type":"CODE_SNIPPET","relationship_type":"CONTAINS","extra":"Source file contains code snippet: 31-33","gmt_create":"2026-04-23T21:00:59.71645+08:00","gmt_modified":"2026-04-23T21:00:59.71645+08:00"},{"id":1117,"source_id":"fc6242433ae9506bcc0bf4cb0dce1413","target_id":"4c9d362ecce8e796e6f14850def049b0","source_type":"SOURCE_FILE","target_type":"CODE_SNIPPET","relationship_type":"CONTAINS","extra":"Source file contains code snippet: 4-20","gmt_create":"2026-04-23T21:00:59.718148+08:00","gmt_modified":"2026-04-23T21:00:59.718148+08:00"},{"id":1119,"source_id":"fc6242433ae9506bcc0bf4cb0dce1413","target_id":"d5827be2cfbe41c8177660ae877e93a4","source_type":"SOURCE_FILE","target_type":"CODE_SNIPPET","relationship_type":"CONTAINS","extra":"Source file contains code snippet: 22-34","gmt_create":"2026-04-23T21:00:59.719965+08:00","gmt_modified":"2026-04-23T21:00:59.719965+08:00"},{"id":1121,"source_id":"9228ff67d4c757a85d9421b71f4b29f5","target_id":"03a65cdcfc173217d12ad8a417f8f033","source_type":"SOURCE_FILE","target_type":"CODE_SNIPPET","relationship_type":"CONTAINS","extra":"Source file contains code snippet: 13-21","gmt_create":"2026-04-23T21:00:59.721352+08:00","gmt_modified":"2026-04-23T21:00:59.721353+08:00"},{"id":1124,"source_id":"9228ff67d4c757a85d9421b71f4b29f5","target_id":"3365fa8db33d43bab1d0a614e8af3a70","source_type":"SOURCE_FILE","target_type":"CODE_SNIPPET","relationship_type":"CONTAINS","extra":"Source file contains code snippet: 45-47","gmt_create":"2026-04-23T21:00:59.724292+08:00","gmt_modified":"2026-04-23T21:00:59.724292+08:00"},{"id":1129,"source_id":"e0c0ca66b8b81cf66e078a7ab162c07f","target_id":"6f637c2b0796ec533aafb3b865c11cf0","source_type":"SOURCE_FILE","target_type":"CODE_SNIPPET","relationship_type":"CONTAINS","extra":"Source file contains code snippet: 1-34","gmt_create":"2026-04-23T21:00:59.728891+08:00","gmt_modified":"2026-04-23T21:00:59.728891+08:00"},{"id":1132,"source_id":"9ff19022ef915615911280e3c49ed44b","target_id":"a698e13bfada239280fc9354ff9e2331","source_type":"SOURCE_FILE","target_type":"CODE_SNIPPET","relationship_type":"CONTAINS","extra":"Source file contains code snippet: 7-8","gmt_create":"2026-04-23T21:00:59.731927+08:00","gmt_modified":"2026-04-23T21:00:59.731927+08:00"},{"id":1134,"source_id":"48a560c49d2b21da327c036ec2934b96","target_id":"37bbab6e4f16db7eac6eee9d05e80e46","source_type":"SOURCE_FILE","target_type":"CODE_SNIPPET","relationship_type":"CONTAINS","extra":"Source file contains code snippet: 1-3","gmt_create":"2026-04-23T21:00:59.737807+08:00","gmt_modified":"2026-04-23T21:00:59.737807+08:00"},{"id":1136,"source_id":"aaf5bce6be82d2f947bfa5c1806de452","target_id":"63ecbf5e72a0354028b84eb531a58977","source_type":"SOURCE_FILE","target_type":"CODE_SNIPPET","relationship_type":"CONTAINS","extra":"Source file contains code snippet: 11-38","gmt_create":"2026-04-23T21:00:59.738981+08:00","gmt_modified":"2026-04-23T21:00:59.738981+08:00"},{"id":1138,"source_id":"fc6242433ae9506bcc0bf4cb0dce1413","target_id":"bf363deac5ef38c8dc80c73b862e730b","source_type":"SOURCE_FILE","target_type":"CODE_SNIPPET","relationship_type":"CONTAINS","extra":"Source file contains code snippet: 4-34","gmt_create":"2026-04-23T21:00:59.740555+08:00","gmt_modified":"2026-04-23T21:00:59.740555+08:00"},{"id":1140,"source_id":"0ef1efea889dba3e1f299626df479571","target_id":"c6e94075e5f689bfa2fe16f8cf965203","source_type":"SOURCE_FILE","target_type":"CODE_SNIPPET","relationship_type":"CONTAINS","extra":"Source file contains code snippet: 19-50","gmt_create":"2026-04-23T21:00:59.742478+08:00","gmt_modified":"2026-04-23T21:00:59.742478+08:00"},{"id":1142,"source_id":"50f2e6bdc4a79e69bd43ea8d6fec67fe","target_id":"1a78f5574add6d07a1d7c947dba3f23d","source_type":"SOURCE_FILE","target_type":"CODE_SNIPPET","relationship_type":"CONTAINS","extra":"Source file contains code snippet: 115-150","gmt_create":"2026-04-23T21:00:59.743435+08:00","gmt_modified":"2026-04-23T21:00:59.743435+08:00"},{"id":1144,"source_id":"01056dad8851d3e9bd532eb4cab33792","target_id":"f6810849c947471a4b45d7ca01ec8c5f","source_type":"SOURCE_FILE","target_type":"CODE_SNIPPET","relationship_type":"CONTAINS","extra":"Source file contains code snippet: 5-9","gmt_create":"2026-04-23T21:00:59.744873+08:00","gmt_modified":"2026-04-23T21:00:59.744873+08:00"},{"id":1146,"source_id":"9228ff67d4c757a85d9421b71f4b29f5","target_id":"9f6d9941f3b93e29d714bfec7e83434c","source_type":"SOURCE_FILE","target_type":"CODE_SNIPPET","relationship_type":"CONTAINS","extra":"Source file contains code snippet: 30-36","gmt_create":"2026-04-23T21:00:59.745747+08:00","gmt_modified":"2026-04-23T21:00:59.745747+08:00"},{"id":1148,"source_id":"9ff19022ef915615911280e3c49ed44b","target_id":"669d67125dcddb0756f4ff50a43512c6","source_type":"SOURCE_FILE","target_type":"CODE_SNIPPET","relationship_type":"CONTAINS","extra":"Source file contains code snippet: 9-13","gmt_create":"2026-04-23T21:00:59.746456+08:00","gmt_modified":"2026-04-23T21:00:59.746456+08:00"},{"id":1168,"source_id":"9228ff67d4c757a85d9421b71f4b29f5","target_id":"85792f0b1e34b5b48b0300aa606ed6e6","source_type":"SOURCE_FILE","target_type":"CODE_SNIPPET","relationship_type":"CONTAINS","extra":"Source file contains code snippet: 1-56","gmt_create":"2026-04-23T21:02:44.193893+08:00","gmt_modified":"2026-04-23T21:02:44.193893+08:00"},{"id":1211,"source_id":"34e572eb-6fc8-4de7-8061-63783ef8be24","target_id":"ed630a36e81abafd12787d4095dfe8c2","source_type":"WIKI_ITEM","target_type":"SOURCE_FILE","relationship_type":"REFERENCED_BY","extra":"Wiki references source file: backend/README.md","gmt_create":"2026-04-24T10:58:35.359267+08:00","gmt_modified":"2026-04-24T10:58:35.359267+08:00"},{"id":1212,"source_id":"34e572eb-6fc8-4de7-8061-63783ef8be24","target_id":"1cafc02d1d722feb4692dab6ae85c09f","source_type":"WIKI_ITEM","target_type":"SOURCE_FILE","relationship_type":"REFERENCED_BY","extra":"Wiki references source file: frontend/README.md","gmt_create":"2026-04-24T10:58:35.360113+08:00","gmt_modified":"2026-04-24T10:58:35.360113+08:00"},{"id":1213,"source_id":"34e572eb-6fc8-4de7-8061-63783ef8be24","target_id":"9228ff67d4c757a85d9421b71f4b29f5","source_type":"WIKI_ITEM","target_type":"SOURCE_FILE","relationship_type":"REFERENCED_BY","extra":"Wiki references source file: backend/app/main.py","gmt_create":"2026-04-24T10:58:35.36047+08:00","gmt_modified":"2026-04-24T10:58:35.36047+08:00"},{"id":1214,"source_id":"34e572eb-6fc8-4de7-8061-63783ef8be24","target_id":"9ff19022ef915615911280e3c49ed44b","source_type":"WIKI_ITEM","target_type":"SOURCE_FILE","relationship_type":"REFERENCED_BY","extra":"Wiki references source file: backend/app/config.py","gmt_create":"2026-04-24T10:58:35.360788+08:00","gmt_modified":"2026-04-24T10:58:35.360788+08:00"},{"id":1215,"source_id":"34e572eb-6fc8-4de7-8061-63783ef8be24","target_id":"5cbb1e3f112aeba62a14b0b8999fc0f5","source_type":"WIKI_ITEM","target_type":"SOURCE_FILE","relationship_type":"REFERENCED_BY","extra":"Wiki references source file: backend/app/workers/scheduler.py","gmt_create":"2026-04-24T10:58:35.361116+08:00","gmt_modified":"2026-04-24T10:58:35.361116+08:00"},{"id":1216,"source_id":"34e572eb-6fc8-4de7-8061-63783ef8be24","target_id":"74040de652d5e57f548bb5c4adc3e1a0","source_type":"WIKI_ITEM","target_type":"SOURCE_FILE","relationship_type":"REFERENCED_BY","extra":"Wiki references source file: backend/app/workers/citation_engine.py","gmt_create":"2026-04-24T10:58:35.385327+08:00","gmt_modified":"2026-04-24T10:58:35.385328+08:00"},{"id":1217,"source_id":"34e572eb-6fc8-4de7-8061-63783ef8be24","target_id":"a16cf42e9559523c4f96ca4c79f9488d","source_type":"WIKI_ITEM","target_type":"SOURCE_FILE","relationship_type":"REFERENCED_BY","extra":"Wiki references source file: backend/app/workers/platforms/base.py","gmt_create":"2026-04-24T10:58:35.386483+08:00","gmt_modified":"2026-04-24T10:58:35.386484+08:00"},{"id":1218,"source_id":"34e572eb-6fc8-4de7-8061-63783ef8be24","target_id":"6b3d903205941aa9391dd90016e1102c","source_type":"WIKI_ITEM","target_type":"SOURCE_FILE","relationship_type":"REFERENCED_BY","extra":"Wiki references source file: backend/app/api/queries.py","gmt_create":"2026-04-24T10:58:35.386836+08:00","gmt_modified":"2026-04-24T10:58:35.386836+08:00"},{"id":1219,"source_id":"34e572eb-6fc8-4de7-8061-63783ef8be24","target_id":"b74caccb06844efcdb14d8324cff65c2","source_type":"WIKI_ITEM","target_type":"SOURCE_FILE","relationship_type":"REFERENCED_BY","extra":"Wiki references source file: backend/app/models/query.py","gmt_create":"2026-04-24T10:58:35.387135+08:00","gmt_modified":"2026-04-24T10:58:35.387135+08:00"},{"id":1220,"source_id":"34e572eb-6fc8-4de7-8061-63783ef8be24","target_id":"b4a81ef789630d0af6a8d50859d01bf3","source_type":"WIKI_ITEM","target_type":"SOURCE_FILE","relationship_type":"REFERENCED_BY","extra":"Wiki references source file: backend/app/models/citation_record.py","gmt_create":"2026-04-24T10:58:35.387467+08:00","gmt_modified":"2026-04-24T10:58:35.387467+08:00"},{"id":1221,"source_id":"34e572eb-6fc8-4de7-8061-63783ef8be24","target_id":"12e2c3d7b9a92dc44a6ee29b85e10df6","source_type":"WIKI_ITEM","target_type":"SOURCE_FILE","relationship_type":"REFERENCED_BY","extra":"Wiki references source file: frontend/app/layout.tsx","gmt_create":"2026-04-24T10:58:35.38776+08:00","gmt_modified":"2026-04-24T10:58:35.38776+08:00"},{"id":1222,"source_id":"34e572eb-6fc8-4de7-8061-63783ef8be24","target_id":"aaf5bce6be82d2f947bfa5c1806de452","source_type":"WIKI_ITEM","target_type":"SOURCE_FILE","relationship_type":"REFERENCED_BY","extra":"Wiki references source file: frontend/package.json","gmt_create":"2026-04-24T10:58:35.388086+08:00","gmt_modified":"2026-04-24T10:58:35.388086+08:00"},{"id":1223,"source_id":"34e572eb-6fc8-4de7-8061-63783ef8be24","target_id":"f1a7d61831cc0a45ac6220294f15c21d","source_type":"WIKI_ITEM","target_type":"SOURCE_FILE","relationship_type":"REFERENCED_BY","extra":"Wiki references source file: frontend/components/charts/platform-chart.tsx","gmt_create":"2026-04-24T10:58:35.388419+08:00","gmt_modified":"2026-04-24T10:58:35.388419+08:00"},{"id":1224,"source_id":"34e572eb-6fc8-4de7-8061-63783ef8be24","target_id":"ef72f0c3cedb9fd9a87352fe493053dc","source_type":"WIKI_ITEM","target_type":"SOURCE_FILE","relationship_type":"REFERENCED_BY","extra":"Wiki references source file: frontend/lib/platforms.ts","gmt_create":"2026-04-24T10:58:35.3887+08:00","gmt_modified":"2026-04-24T10:58:35.3887+08:00"},{"id":1225,"source_id":"34e572eb-6fc8-4de7-8061-63783ef8be24","target_id":"fc6242433ae9506bcc0bf4cb0dce1413","source_type":"WIKI_ITEM","target_type":"SOURCE_FILE","relationship_type":"REFERENCED_BY","extra":"Wiki references source file: docker-compose.yml","gmt_create":"2026-04-24T10:58:35.388982+08:00","gmt_modified":"2026-04-24T10:58:35.388982+08:00"},{"id":1226,"source_id":"34e572eb-6fc8-4de7-8061-63783ef8be24","target_id":"a26ee01cf41da3b956e1650448c156fa","source_type":"WIKI_ITEM","target_type":"SOURCE_FILE","relationship_type":"REFERENCED_BY","extra":"Wiki references source file: backend/requirements.txt","gmt_create":"2026-04-24T10:58:35.389271+08:00","gmt_modified":"2026-04-24T10:58:35.389271+08:00"},{"id":1227,"source_id":"34e572eb-6fc8-4de7-8061-63783ef8be24","target_id":"5d7886d0dc99f81073a578b8aefdd375","source_type":"WIKI_ITEM","target_type":"SOURCE_FILE","relationship_type":"REFERENCED_BY","extra":"Wiki references source file: frontend/lib/api.ts","gmt_create":"2026-04-24T10:58:35.389707+08:00","gmt_modified":"2026-04-24T10:58:35.389707+08:00"},{"id":1228,"source_id":"34e572eb-6fc8-4de7-8061-63783ef8be24","target_id":"d2c1984414de6856ed5b3873c661b712","source_type":"WIKI_ITEM","target_type":"SOURCE_FILE","relationship_type":"REFERENCED_BY","extra":"Wiki references source file: frontend/lib/auth.ts","gmt_create":"2026-04-24T10:58:35.390068+08:00","gmt_modified":"2026-04-24T10:58:35.390068+08:00"},{"id":1229,"source_id":"34e572eb-6fc8-4de7-8061-63783ef8be24","target_id":"0ef1efea889dba3e1f299626df479571","source_type":"WIKI_ITEM","target_type":"SOURCE_FILE","relationship_type":"REFERENCED_BY","extra":"Wiki references source file: tests/conftest.py","gmt_create":"2026-04-24T10:58:35.390413+08:00","gmt_modified":"2026-04-24T10:58:35.390413+08:00"},{"id":1230,"source_id":"34e572eb-6fc8-4de7-8061-63783ef8be24","target_id":"389d631bc6c7111ba411b0b79fca455e","source_type":"WIKI_ITEM","target_type":"SOURCE_FILE","relationship_type":"REFERENCED_BY","extra":"Wiki references source file: tests/test_auth.py","gmt_create":"2026-04-24T10:58:35.390888+08:00","gmt_modified":"2026-04-24T10:58:35.390888+08:00"},{"id":1231,"source_id":"34e572eb-6fc8-4de7-8061-63783ef8be24","target_id":"f240c1067c223a019ba05b0fbd718aa4","source_type":"WIKI_ITEM","target_type":"CODE_SNIPPET","relationship_type":"CONTAINS","extra":"Wiki contains code snippet: backend/app/main.py#1-84","gmt_create":"2026-04-24T10:58:35.39137+08:00","gmt_modified":"2026-04-24T10:58:35.39137+08:00"},{"id":1232,"source_id":"9228ff67d4c757a85d9421b71f4b29f5","target_id":"f240c1067c223a019ba05b0fbd718aa4","source_type":"SOURCE_FILE","target_type":"CODE_SNIPPET","relationship_type":"CONTAINS","extra":"Source file contains code snippet: 1-84","gmt_create":"2026-04-24T10:58:35.391735+08:00","gmt_modified":"2026-04-24T10:58:35.391735+08:00"},{"id":1233,"source_id":"34e572eb-6fc8-4de7-8061-63783ef8be24","target_id":"71f98c8993fb42b108e34a554247869b","source_type":"WIKI_ITEM","target_type":"CODE_SNIPPET","relationship_type":"CONTAINS","extra":"Wiki contains code snippet: backend/app/workers/scheduler.py#1-95","gmt_create":"2026-04-24T10:58:35.393449+08:00","gmt_modified":"2026-04-24T10:58:35.393449+08:00"},{"id":1234,"source_id":"34e572eb-6fc8-4de7-8061-63783ef8be24","target_id":"116584ea9162c1bc05911f39f9ef82b6","source_type":"WIKI_ITEM","target_type":"CODE_SNIPPET","relationship_type":"CONTAINS","extra":"Wiki contains code snippet: backend/app/workers/citation_engine.py#1-309","gmt_create":"2026-04-24T10:58:35.394311+08:00","gmt_modified":"2026-04-24T10:58:35.394312+08:00"},{"id":1235,"source_id":"34e572eb-6fc8-4de7-8061-63783ef8be24","target_id":"48d22eaee09e364a293ad6c4750f5c5a","source_type":"WIKI_ITEM","target_type":"CODE_SNIPPET","relationship_type":"CONTAINS","extra":"Wiki contains code snippet: docker-compose.yml#1-71","gmt_create":"2026-04-24T10:58:35.395171+08:00","gmt_modified":"2026-04-24T10:58:35.395171+08:00"},{"id":1236,"source_id":"34e572eb-6fc8-4de7-8061-63783ef8be24","target_id":"72a110dca58d8152758e2fdab4e94761","source_type":"WIKI_ITEM","target_type":"CODE_SNIPPET","relationship_type":"CONTAINS","extra":"Wiki contains code snippet: backend/app/workers/platforms/base.py#1-18","gmt_create":"2026-04-24T10:58:35.397907+08:00","gmt_modified":"2026-04-24T10:58:35.397907+08:00"},{"id":1237,"source_id":"34e572eb-6fc8-4de7-8061-63783ef8be24","target_id":"10d1e37bdc9f353c189b7a2fe79dc85e","source_type":"WIKI_ITEM","target_type":"CODE_SNIPPET","relationship_type":"CONTAINS","extra":"Wiki contains code snippet: backend/app/api/queries.py#1-86","gmt_create":"2026-04-24T10:58:35.399232+08:00","gmt_modified":"2026-04-24T10:58:35.399232+08:00"},{"id":1238,"source_id":"34e572eb-6fc8-4de7-8061-63783ef8be24","target_id":"6281fff17a86ec1895c64d87c2ae7fb1","source_type":"WIKI_ITEM","target_type":"CODE_SNIPPET","relationship_type":"CONTAINS","extra":"Wiki contains code snippet: backend/app/models/query.py#1-55","gmt_create":"2026-04-24T10:58:35.400157+08:00","gmt_modified":"2026-04-24T10:58:35.400157+08:00"},{"id":1239,"source_id":"34e572eb-6fc8-4de7-8061-63783ef8be24","target_id":"943c18db69a04b3137fba4cebcfea87e","source_type":"WIKI_ITEM","target_type":"CODE_SNIPPET","relationship_type":"CONTAINS","extra":"Wiki contains code snippet: backend/app/models/citation_record.py#1-42","gmt_create":"2026-04-24T10:58:35.400997+08:00","gmt_modified":"2026-04-24T10:58:35.400997+08:00"},{"id":1240,"source_id":"34e572eb-6fc8-4de7-8061-63783ef8be24","target_id":"8a466b0c6eac2ccb54c5da7e13854646","source_type":"WIKI_ITEM","target_type":"CODE_SNIPPET","relationship_type":"CONTAINS","extra":"Wiki contains code snippet: frontend/app/layout.tsx#1-37","gmt_create":"2026-04-24T10:58:35.401612+08:00","gmt_modified":"2026-04-24T10:58:35.401612+08:00"},{"id":1241,"source_id":"34e572eb-6fc8-4de7-8061-63783ef8be24","target_id":"6b9f52af0b6d78c17ff9bbc42d760ea2","source_type":"WIKI_ITEM","target_type":"CODE_SNIPPET","relationship_type":"CONTAINS","extra":"Wiki contains code snippet: frontend/components/charts/platform-chart.tsx#1-68","gmt_create":"2026-04-24T10:58:35.402427+08:00","gmt_modified":"2026-04-24T10:58:35.402427+08:00"},{"id":1242,"source_id":"34e572eb-6fc8-4de7-8061-63783ef8be24","target_id":"a829403082cc3460c01e0110229c53c4","source_type":"WIKI_ITEM","target_type":"CODE_SNIPPET","relationship_type":"CONTAINS","extra":"Wiki contains code snippet: frontend/lib/platforms.ts#1-18","gmt_create":"2026-04-24T10:58:35.409328+08:00","gmt_modified":"2026-04-24T10:58:35.409329+08:00"},{"id":1243,"source_id":"34e572eb-6fc8-4de7-8061-63783ef8be24","target_id":"a9fb75d1fdb833a11b36bc7b298f19be","source_type":"WIKI_ITEM","target_type":"CODE_SNIPPET","relationship_type":"CONTAINS","extra":"Wiki contains code snippet: frontend/lib/api.ts#1-154","gmt_create":"2026-04-24T10:58:35.410752+08:00","gmt_modified":"2026-04-24T10:58:35.410752+08:00"},{"id":1244,"source_id":"5d7886d0dc99f81073a578b8aefdd375","target_id":"a9fb75d1fdb833a11b36bc7b298f19be","source_type":"SOURCE_FILE","target_type":"CODE_SNIPPET","relationship_type":"CONTAINS","extra":"Source file contains code snippet: 1-154","gmt_create":"2026-04-24T10:58:35.411143+08:00","gmt_modified":"2026-04-24T10:58:35.411143+08:00"},{"id":1245,"source_id":"34e572eb-6fc8-4de7-8061-63783ef8be24","target_id":"40325db1cb621a9af027150a8c5cf8e9","source_type":"WIKI_ITEM","target_type":"CODE_SNIPPET","relationship_type":"CONTAINS","extra":"Wiki contains code snippet: frontend/lib/auth.ts#1-73","gmt_create":"2026-04-24T10:58:35.41196+08:00","gmt_modified":"2026-04-24T10:58:35.41196+08:00"},{"id":1246,"source_id":"d2c1984414de6856ed5b3873c661b712","target_id":"40325db1cb621a9af027150a8c5cf8e9","source_type":"SOURCE_FILE","target_type":"CODE_SNIPPET","relationship_type":"CONTAINS","extra":"Source file contains code snippet: 1-73","gmt_create":"2026-04-24T10:58:35.412876+08:00","gmt_modified":"2026-04-24T10:58:35.412876+08:00"},{"id":1247,"source_id":"34e572eb-6fc8-4de7-8061-63783ef8be24","target_id":"ea655c6d147bc98beb42955d437260cc","source_type":"WIKI_ITEM","target_type":"CODE_SNIPPET","relationship_type":"CONTAINS","extra":"Wiki contains code snippet: backend/app/config.py#1-23","gmt_create":"2026-04-24T10:58:35.414212+08:00","gmt_modified":"2026-04-24T10:58:35.414212+08:00"},{"id":1248,"source_id":"34e572eb-6fc8-4de7-8061-63783ef8be24","target_id":"93d8c6a312849c344b6a9713b671840f","source_type":"WIKI_ITEM","target_type":"CODE_SNIPPET","relationship_type":"CONTAINS","extra":"Wiki contains code snippet: backend/requirements.txt#1-39","gmt_create":"2026-04-24T10:58:35.4148+08:00","gmt_modified":"2026-04-24T10:58:35.4148+08:00"},{"id":1249,"source_id":"a26ee01cf41da3b956e1650448c156fa","target_id":"93d8c6a312849c344b6a9713b671840f","source_type":"SOURCE_FILE","target_type":"CODE_SNIPPET","relationship_type":"CONTAINS","extra":"Source file contains code snippet: 1-39","gmt_create":"2026-04-24T10:58:35.415254+08:00","gmt_modified":"2026-04-24T10:58:35.415254+08:00"},{"id":1250,"source_id":"34e572eb-6fc8-4de7-8061-63783ef8be24","target_id":"71a37a516437e94fd82a87efc70a3f16","source_type":"WIKI_ITEM","target_type":"CODE_SNIPPET","relationship_type":"CONTAINS","extra":"Wiki contains code snippet: frontend/package.json#1-40","gmt_create":"2026-04-24T10:58:35.416275+08:00","gmt_modified":"2026-04-24T10:58:35.416275+08:00"},{"id":1251,"source_id":"34e572eb-6fc8-4de7-8061-63783ef8be24","target_id":"844b21a35ae39ead76ff8831eb974e5a","source_type":"WIKI_ITEM","target_type":"CODE_SNIPPET","relationship_type":"CONTAINS","extra":"Wiki contains code snippet: backend/app/main.py#81-84","gmt_create":"2026-04-24T10:58:35.417932+08:00","gmt_modified":"2026-04-24T10:58:35.417932+08:00"},{"id":1252,"source_id":"9228ff67d4c757a85d9421b71f4b29f5","target_id":"844b21a35ae39ead76ff8831eb974e5a","source_type":"SOURCE_FILE","target_type":"CODE_SNIPPET","relationship_type":"CONTAINS","extra":"Source file contains code snippet: 81-84","gmt_create":"2026-04-24T10:58:35.418732+08:00","gmt_modified":"2026-04-24T10:58:35.418732+08:00"},{"id":1253,"source_id":"34e572eb-6fc8-4de7-8061-63783ef8be24","target_id":"3af33bd686ce3d418e31843cac66f58b","source_type":"WIKI_ITEM","target_type":"CODE_SNIPPET","relationship_type":"CONTAINS","extra":"Wiki contains code snippet: backend/README.md#12-67","gmt_create":"2026-04-24T10:58:35.422407+08:00","gmt_modified":"2026-04-24T10:58:35.422407+08:00"},{"id":1254,"source_id":"ed630a36e81abafd12787d4095dfe8c2","target_id":"3af33bd686ce3d418e31843cac66f58b","source_type":"SOURCE_FILE","target_type":"CODE_SNIPPET","relationship_type":"CONTAINS","extra":"Source file contains code snippet: 12-67","gmt_create":"2026-04-24T10:58:35.423436+08:00","gmt_modified":"2026-04-24T10:58:35.423436+08:00"},{"id":1255,"source_id":"34e572eb-6fc8-4de7-8061-63783ef8be24","target_id":"06c6dfcd66159d42fa9b9eafd1e36a04","source_type":"WIKI_ITEM","target_type":"CODE_SNIPPET","relationship_type":"CONTAINS","extra":"Wiki contains code snippet: frontend/README.md#11-34","gmt_create":"2026-04-24T10:58:35.424232+08:00","gmt_modified":"2026-04-24T10:58:35.424232+08:00"},{"id":1256,"source_id":"1cafc02d1d722feb4692dab6ae85c09f","target_id":"06c6dfcd66159d42fa9b9eafd1e36a04","source_type":"SOURCE_FILE","target_type":"CODE_SNIPPET","relationship_type":"CONTAINS","extra":"Source file contains code snippet: 11-34","gmt_create":"2026-04-24T10:58:35.424616+08:00","gmt_modified":"2026-04-24T10:58:35.424616+08:00"},{"id":1257,"source_id":"34e572eb-6fc8-4de7-8061-63783ef8be24","target_id":"903da86dc3fb26783f45f247d60e9534","source_type":"WIKI_ITEM","target_type":"CODE_SNIPPET","relationship_type":"CONTAINS","extra":"Wiki contains code snippet: backend/README.md#69-126","gmt_create":"2026-04-24T10:58:35.426243+08:00","gmt_modified":"2026-04-24T10:58:35.426243+08:00"},{"id":1258,"source_id":"ed630a36e81abafd12787d4095dfe8c2","target_id":"903da86dc3fb26783f45f247d60e9534","source_type":"SOURCE_FILE","target_type":"CODE_SNIPPET","relationship_type":"CONTAINS","extra":"Source file contains code snippet: 69-126","gmt_create":"2026-04-24T10:58:35.426634+08:00","gmt_modified":"2026-04-24T10:58:35.426634+08:00"},{"id":1259,"source_id":"34e572eb-6fc8-4de7-8061-63783ef8be24","target_id":"0ffe337a73c8fb7254f3e48932a8ae7f","source_type":"WIKI_ITEM","target_type":"CODE_SNIPPET","relationship_type":"CONTAINS","extra":"Wiki contains code snippet: backend/README.md#209-234","gmt_create":"2026-04-24T10:58:35.427155+08:00","gmt_modified":"2026-04-24T10:58:35.427155+08:00"},{"id":1260,"source_id":"ed630a36e81abafd12787d4095dfe8c2","target_id":"0ffe337a73c8fb7254f3e48932a8ae7f","source_type":"SOURCE_FILE","target_type":"CODE_SNIPPET","relationship_type":"CONTAINS","extra":"Source file contains code snippet: 209-234","gmt_create":"2026-04-24T10:58:35.427796+08:00","gmt_modified":"2026-04-24T10:58:35.427797+08:00"},{"id":1261,"source_id":"34e572eb-6fc8-4de7-8061-63783ef8be24","target_id":"290df8332b3d104e5ea8d71dc39315b5","source_type":"WIKI_ITEM","target_type":"CODE_SNIPPET","relationship_type":"CONTAINS","extra":"Wiki contains code snippet: tests/conftest.py#1-123","gmt_create":"2026-04-24T10:58:35.428393+08:00","gmt_modified":"2026-04-24T10:58:35.428393+08:00"},{"id":1262,"source_id":"34e572eb-6fc8-4de7-8061-63783ef8be24","target_id":"d820e2daf2ea133a7aa17cdc475e44a4","source_type":"WIKI_ITEM","target_type":"CODE_SNIPPET","relationship_type":"CONTAINS","extra":"Wiki contains code snippet: tests/test_auth.py#1-104","gmt_create":"2026-04-24T10:58:35.429142+08:00","gmt_modified":"2026-04-24T10:58:35.429142+08:00"},{"id":1263,"source_id":"34e572eb-6fc8-4de7-8061-63783ef8be24","target_id":"55369db351eb916a3210b22f3d672162","source_type":"WIKI_ITEM","target_type":"CODE_SNIPPET","relationship_type":"CONTAINS","extra":"Wiki contains code snippet: frontend/README.md#161-170","gmt_create":"2026-04-24T10:58:35.429799+08:00","gmt_modified":"2026-04-24T10:58:35.429799+08:00"},{"id":1264,"source_id":"1cafc02d1d722feb4692dab6ae85c09f","target_id":"55369db351eb916a3210b22f3d672162","source_type":"SOURCE_FILE","target_type":"CODE_SNIPPET","relationship_type":"CONTAINS","extra":"Source file contains code snippet: 161-170","gmt_create":"2026-04-24T10:58:35.430152+08:00","gmt_modified":"2026-04-24T10:58:35.430152+08:00"},{"id":1293,"source_id":"b44632a0f399b2fe2b4daf295a120ec7","target_id":"6c080aba7d0e611bd4e7f268835b630f","source_type":"SOURCE_FILE","target_type":"CODE_SNIPPET","relationship_type":"CONTAINS","extra":"Source file contains code snippet: 1-24","gmt_create":"2026-04-24T10:58:51.104849+08:00","gmt_modified":"2026-04-24T10:58:51.104849+08:00"},{"id":1295,"source_id":"5883a8ef4fc156d76b71ffdb5ecdf232","target_id":"a7bba55ddc4dd5d215e881e8432d83ea","source_type":"SOURCE_FILE","target_type":"CODE_SNIPPET","relationship_type":"CONTAINS","extra":"Source file contains code snippet: 1-83","gmt_create":"2026-04-24T10:58:51.105611+08:00","gmt_modified":"2026-04-24T10:58:51.105612+08:00"},{"id":1297,"source_id":"f26740f2a1532b38c816663a4f665dbf","target_id":"7c7425c51cc43b8840cefd9764b47204","source_type":"SOURCE_FILE","target_type":"CODE_SNIPPET","relationship_type":"CONTAINS","extra":"Source file contains code snippet: 1-108","gmt_create":"2026-04-24T10:58:51.106317+08:00","gmt_modified":"2026-04-24T10:58:51.106317+08:00"},{"id":1299,"source_id":"58901c94d975d87e652a4dc6c8dda656","target_id":"6e4a52820e780e4b42651a8214ad4493","source_type":"SOURCE_FILE","target_type":"CODE_SNIPPET","relationship_type":"CONTAINS","extra":"Source file contains code snippet: 1-75","gmt_create":"2026-04-24T10:58:51.10724+08:00","gmt_modified":"2026-04-24T10:58:51.10724+08:00"},{"id":1301,"source_id":"5386144bf3c668c6fa14481c0d85a214","target_id":"4247da3fc00a7e5f8b73775321eccf8e","source_type":"SOURCE_FILE","target_type":"CODE_SNIPPET","relationship_type":"CONTAINS","extra":"Source file contains code snippet: 1-77","gmt_create":"2026-04-24T10:58:51.108036+08:00","gmt_modified":"2026-04-24T10:58:51.108036+08:00"},{"id":1303,"source_id":"3809c5ab912511e0e093ba02a4fc918f","target_id":"9bdd2f6103cf3cc8b3914b9d6d8812fb","source_type":"SOURCE_FILE","target_type":"CODE_SNIPPET","relationship_type":"CONTAINS","extra":"Source file contains code snippet: 1-188","gmt_create":"2026-04-24T10:58:51.109999+08:00","gmt_modified":"2026-04-24T10:58:51.109999+08:00"},{"id":1305,"source_id":"b250fc6c32106a7f3e0c3ad152dfc097","target_id":"557281ca025f76d0dc2db67e56b44053","source_type":"SOURCE_FILE","target_type":"CODE_SNIPPET","relationship_type":"CONTAINS","extra":"Source file contains code snippet: 1-155","gmt_create":"2026-04-24T10:58:51.111471+08:00","gmt_modified":"2026-04-24T10:58:51.111472+08:00"},{"id":1307,"source_id":"9228ff67d4c757a85d9421b71f4b29f5","target_id":"e2d4838e58acc0eee236ef586abab64e","source_type":"SOURCE_FILE","target_type":"CODE_SNIPPET","relationship_type":"CONTAINS","extra":"Source file contains code snippet: 13-48","gmt_create":"2026-04-24T10:58:51.113574+08:00","gmt_modified":"2026-04-24T10:58:51.113574+08:00"},{"id":1309,"source_id":"b0c428683c8a3e6922d90ca0d8c2736d","target_id":"8aee7654d1f435ab53d8ddaabd269fed","source_type":"SOURCE_FILE","target_type":"CODE_SNIPPET","relationship_type":"CONTAINS","extra":"Source file contains code snippet: 6-29","gmt_create":"2026-04-24T10:58:51.114869+08:00","gmt_modified":"2026-04-24T10:58:51.114869+08:00"},{"id":1311,"source_id":"9d08667997a868fc07c9b4e328e44224","target_id":"acd9e6c32084e589d5aeb1665d918dfd","source_type":"SOURCE_FILE","target_type":"CODE_SNIPPET","relationship_type":"CONTAINS","extra":"Source file contains code snippet: 13-43","gmt_create":"2026-04-24T10:58:51.115783+08:00","gmt_modified":"2026-04-24T10:58:51.115783+08:00"},{"id":1313,"source_id":"9228ff67d4c757a85d9421b71f4b29f5","target_id":"33ec8bca51cb9f667bf91088dd6b6a70","source_type":"SOURCE_FILE","target_type":"CODE_SNIPPET","relationship_type":"CONTAINS","extra":"Source file contains code snippet: 24-48","gmt_create":"2026-04-24T10:58:51.116484+08:00","gmt_modified":"2026-04-24T10:58:51.116484+08:00"},{"id":1315,"source_id":"5883a8ef4fc156d76b71ffdb5ecdf232","target_id":"712424bd3bd3d5f39b1a0a72acc9952a","source_type":"SOURCE_FILE","target_type":"CODE_SNIPPET","relationship_type":"CONTAINS","extra":"Source file contains code snippet: 10-83","gmt_create":"2026-04-24T10:58:51.117511+08:00","gmt_modified":"2026-04-24T10:58:51.117511+08:00"},{"id":1317,"source_id":"b44632a0f399b2fe2b4daf295a120ec7","target_id":"9357a0fcca02068d428f4a191d08fdcd","source_type":"SOURCE_FILE","target_type":"CODE_SNIPPET","relationship_type":"CONTAINS","extra":"Source file contains code snippet: 8-24","gmt_create":"2026-04-24T10:58:51.118728+08:00","gmt_modified":"2026-04-24T10:58:51.118728+08:00"},{"id":1320,"source_id":"4d2f3847b7c10634733118b70a1aea0b","target_id":"8efcce12915471fe5b88fe058bcf238e","source_type":"SOURCE_FILE","target_type":"CODE_SNIPPET","relationship_type":"CONTAINS","extra":"Source file contains code snippet: 16-69","gmt_create":"2026-04-24T10:58:51.120028+08:00","gmt_modified":"2026-04-24T10:58:51.120028+08:00"},{"id":1322,"source_id":"3809c5ab912511e0e093ba02a4fc918f","target_id":"7f81ebbdde3496054e6f43f5eef366dc","source_type":"SOURCE_FILE","target_type":"CODE_SNIPPET","relationship_type":"CONTAINS","extra":"Source file contains code snippet: 14-188","gmt_create":"2026-04-24T10:58:51.124562+08:00","gmt_modified":"2026-04-24T10:58:51.124562+08:00"},{"id":1324,"source_id":"b250fc6c32106a7f3e0c3ad152dfc097","target_id":"f4d57f9a78585969a006b7451ea8ce84","source_type":"SOURCE_FILE","target_type":"CODE_SNIPPET","relationship_type":"CONTAINS","extra":"Source file contains code snippet: 69-155","gmt_create":"2026-04-24T10:58:51.125712+08:00","gmt_modified":"2026-04-24T10:58:51.125712+08:00"},{"id":1330,"source_id":"9ff19022ef915615911280e3c49ed44b","target_id":"608c00e1835ad72363ef08796961faca","source_type":"SOURCE_FILE","target_type":"CODE_SNIPPET","relationship_type":"CONTAINS","extra":"Source file contains code snippet: 4-17","gmt_create":"2026-04-24T10:58:51.129154+08:00","gmt_modified":"2026-04-24T10:58:51.129154+08:00"},{"id":1342,"source_id":"5cbb1e3f112aeba62a14b0b8999fc0f5","target_id":"ec4bf600a513dc2b014c85e141d7582d","source_type":"SOURCE_FILE","target_type":"CODE_SNIPPET","relationship_type":"CONTAINS","extra":"Source file contains code snippet: 51-85","gmt_create":"2026-04-24T10:58:51.139025+08:00","gmt_modified":"2026-04-24T10:58:51.139026+08:00"},{"id":1356,"source_id":"5883a8ef4fc156d76b71ffdb5ecdf232","target_id":"9606b8243736b4a6f5ecfe152b2ab6dd","source_type":"SOURCE_FILE","target_type":"CODE_SNIPPET","relationship_type":"CONTAINS","extra":"Source file contains code snippet: 34-83","gmt_create":"2026-04-24T10:58:51.158662+08:00","gmt_modified":"2026-04-24T10:58:51.158662+08:00"},{"id":1358,"source_id":"f26740f2a1532b38c816663a4f665dbf","target_id":"05664cbd35007caa5290760cc1ef1b99","source_type":"SOURCE_FILE","target_type":"CODE_SNIPPET","relationship_type":"CONTAINS","extra":"Source file contains code snippet: 29-108","gmt_create":"2026-04-24T10:58:51.160297+08:00","gmt_modified":"2026-04-24T10:58:51.160297+08:00"},{"id":1360,"source_id":"b250fc6c32106a7f3e0c3ad152dfc097","target_id":"3d85cad939ce858f9c6d153d425c19fb","source_type":"SOURCE_FILE","target_type":"CODE_SNIPPET","relationship_type":"CONTAINS","extra":"Source file contains code snippet: 25-155","gmt_create":"2026-04-24T10:58:51.163075+08:00","gmt_modified":"2026-04-24T10:58:51.163075+08:00"},{"id":1362,"source_id":"5013cbe89f1c6f03533eb218400cedb0","target_id":"36769bd305cd5f664fa6e28f82e4b3e7","source_type":"SOURCE_FILE","target_type":"CODE_SNIPPET","relationship_type":"CONTAINS","extra":"Source file contains code snippet: 1-41","gmt_create":"2026-04-24T10:58:51.164477+08:00","gmt_modified":"2026-04-24T10:58:51.164477+08:00"},{"id":1364,"source_id":"58901c94d975d87e652a4dc6c8dda656","target_id":"14c2d098319eeab16c64ff7d1447df6b","source_type":"SOURCE_FILE","target_type":"CODE_SNIPPET","relationship_type":"CONTAINS","extra":"Source file contains code snippet: 18-75","gmt_create":"2026-04-24T10:58:51.166362+08:00","gmt_modified":"2026-04-24T10:58:51.166363+08:00"},{"id":1392,"source_id":"c59f8c276697a070dffc581fe94d809c","target_id":"1f8d26b6a5da49d89d95bb13c7ace2c6","source_type":"SOURCE_FILE","target_type":"CODE_SNIPPET","relationship_type":"CONTAINS","extra":"Source file contains code snippet: 1-48","gmt_create":"2026-04-24T10:59:38.934235+08:00","gmt_modified":"2026-04-24T10:59:38.934235+08:00"},{"id":1403,"source_id":"b0cb6810919f64006be7aa66b2b76a61","target_id":"c8f2dbcb7475bd189a34c7061ea46c6d","source_type":"SOURCE_FILE","target_type":"CODE_SNIPPET","relationship_type":"CONTAINS","extra":"Source file contains code snippet: 1-41","gmt_create":"2026-04-24T10:59:38.943933+08:00","gmt_modified":"2026-04-24T10:59:38.943933+08:00"},{"id":1407,"source_id":"4d2f3847b7c10634733118b70a1aea0b","target_id":"08c1475254a5bc8877ff29a895de3b6a","source_type":"SOURCE_FILE","target_type":"CODE_SNIPPET","relationship_type":"CONTAINS","extra":"Source file contains code snippet: 1-175","gmt_create":"2026-04-24T10:59:38.9463+08:00","gmt_modified":"2026-04-24T10:59:38.9463+08:00"},{"id":1409,"source_id":"c59f8c276697a070dffc581fe94d809c","target_id":"f5978358d04c3c917d9ca5044c7f36fa","source_type":"SOURCE_FILE","target_type":"CODE_SNIPPET","relationship_type":"CONTAINS","extra":"Source file contains code snippet: 11-48","gmt_create":"2026-04-24T10:59:38.947981+08:00","gmt_modified":"2026-04-24T10:59:38.947981+08:00"},{"id":1417,"source_id":"b0cb6810919f64006be7aa66b2b76a61","target_id":"675ab6c1ae510ca753b5e966b7b6a10c","source_type":"SOURCE_FILE","target_type":"CODE_SNIPPET","relationship_type":"CONTAINS","extra":"Source file contains code snippet: 21-41","gmt_create":"2026-04-24T10:59:38.954222+08:00","gmt_modified":"2026-04-24T10:59:38.954223+08:00"},{"id":1427,"source_id":"4d2f3847b7c10634733118b70a1aea0b","target_id":"fe351bf59a46bec7f77ffe40a68a5993","source_type":"SOURCE_FILE","target_type":"CODE_SNIPPET","relationship_type":"CONTAINS","extra":"Source file contains code snippet: 40-56","gmt_create":"2026-04-24T10:59:38.965521+08:00","gmt_modified":"2026-04-24T10:59:38.965521+08:00"},{"id":1435,"source_id":"4d2f3847b7c10634733118b70a1aea0b","target_id":"46e69841e5c5dc62faa55c9f066586d6","source_type":"SOURCE_FILE","target_type":"CODE_SNIPPET","relationship_type":"CONTAINS","extra":"Source file contains code snippet: 74-107","gmt_create":"2026-04-24T10:59:38.971032+08:00","gmt_modified":"2026-04-24T10:59:38.971032+08:00"},{"id":1437,"source_id":"4d2f3847b7c10634733118b70a1aea0b","target_id":"cecc8857775f7928d465b68e429493d2","source_type":"SOURCE_FILE","target_type":"CODE_SNIPPET","relationship_type":"CONTAINS","extra":"Source file contains code snippet: 110-140","gmt_create":"2026-04-24T10:59:38.97203+08:00","gmt_modified":"2026-04-24T10:59:38.97203+08:00"},{"id":1439,"source_id":"e0c0ca66b8b81cf66e078a7ab162c07f","target_id":"1153d8a149a70bc79ca59a9dcba5945c","source_type":"SOURCE_FILE","target_type":"CODE_SNIPPET","relationship_type":"CONTAINS","extra":"Source file contains code snippet: 8-55","gmt_create":"2026-04-24T10:59:38.972843+08:00","gmt_modified":"2026-04-24T10:59:38.972843+08:00"},{"id":1441,"source_id":"93022c8938ce318f167277cfa65c29a7","target_id":"35dd08df9c7a562d9c7b8edf740eaf3c","source_type":"SOURCE_FILE","target_type":"CODE_SNIPPET","relationship_type":"CONTAINS","extra":"Source file contains code snippet: 33-115","gmt_create":"2026-04-24T10:59:38.973675+08:00","gmt_modified":"2026-04-24T10:59:38.973675+08:00"},{"id":1461,"source_id":"18a0651d895fba9bb4e0c0229459efdc","target_id":"dc735ee4a0f12140bcee122a67f4a13b","source_type":"SOURCE_FILE","target_type":"CODE_SNIPPET","relationship_type":"CONTAINS","extra":"Source file contains code snippet: 1-63","gmt_create":"2026-04-24T11:01:58.090246+08:00","gmt_modified":"2026-04-24T11:01:58.090246+08:00"},{"id":1465,"source_id":"955e1dfe57f0a9a8e900383eb7641ba1","target_id":"f990ecd63842b3ab82f5b8c8dcde2a6b","source_type":"SOURCE_FILE","target_type":"CODE_SNIPPET","relationship_type":"CONTAINS","extra":"Source file contains code snippet: 1-5","gmt_create":"2026-04-24T11:01:58.092029+08:00","gmt_modified":"2026-04-24T11:01:58.092029+08:00"},{"id":1468,"source_id":"b1d80d63eae8fd5e1bdfeee3c6bc9594","target_id":"d5efa0fbc545b778dd913854d860c502","source_type":"SOURCE_FILE","target_type":"CODE_SNIPPET","relationship_type":"CONTAINS","extra":"Source file contains code snippet: 1-29","gmt_create":"2026-04-24T11:01:58.095303+08:00","gmt_modified":"2026-04-24T11:01:58.095304+08:00"},{"id":1473,"source_id":"df661133-efbf-43fe-97c3-f581c81f47a7","target_id":"c59f8c276697a070dffc581fe94d809c","source_type":"WIKI_ITEM","target_type":"SOURCE_FILE","relationship_type":"REFERENCED_BY","extra":"Wiki references source file: backend/app/models/user.py","gmt_create":"2026-04-24T11:02:17.577219+08:00","gmt_modified":"2026-04-24T11:02:17.577219+08:00"},{"id":1474,"source_id":"df661133-efbf-43fe-97c3-f581c81f47a7","target_id":"e0c0ca66b8b81cf66e078a7ab162c07f","source_type":"WIKI_ITEM","target_type":"SOURCE_FILE","relationship_type":"REFERENCED_BY","extra":"Wiki references source file: backend/app/schemas/auth.py","gmt_create":"2026-04-24T11:02:17.578316+08:00","gmt_modified":"2026-04-24T11:02:17.578316+08:00"},{"id":1475,"source_id":"df661133-efbf-43fe-97c3-f581c81f47a7","target_id":"4d2f3847b7c10634733118b70a1aea0b","source_type":"WIKI_ITEM","target_type":"SOURCE_FILE","relationship_type":"REFERENCED_BY","extra":"Wiki references source file: backend/app/services/auth.py","gmt_create":"2026-04-24T11:02:17.579016+08:00","gmt_modified":"2026-04-24T11:02:17.579016+08:00"},{"id":1476,"source_id":"df661133-efbf-43fe-97c3-f581c81f47a7","target_id":"93022c8938ce318f167277cfa65c29a7","source_type":"WIKI_ITEM","target_type":"SOURCE_FILE","relationship_type":"REFERENCED_BY","extra":"Wiki references source file: backend/app/api/auth.py","gmt_create":"2026-04-24T11:02:17.579604+08:00","gmt_modified":"2026-04-24T11:02:17.579604+08:00"},{"id":1477,"source_id":"df661133-efbf-43fe-97c3-f581c81f47a7","target_id":"9d08667997a868fc07c9b4e328e44224","source_type":"WIKI_ITEM","target_type":"SOURCE_FILE","relationship_type":"REFERENCED_BY","extra":"Wiki references source file: backend/app/api/deps.py","gmt_create":"2026-04-24T11:02:17.580669+08:00","gmt_modified":"2026-04-24T11:02:17.580669+08:00"},{"id":1478,"source_id":"df661133-efbf-43fe-97c3-f581c81f47a7","target_id":"9ff19022ef915615911280e3c49ed44b","source_type":"WIKI_ITEM","target_type":"SOURCE_FILE","relationship_type":"REFERENCED_BY","extra":"Wiki references source file: backend/app/config.py","gmt_create":"2026-04-24T11:02:17.581765+08:00","gmt_modified":"2026-04-24T11:02:17.581765+08:00"},{"id":1479,"source_id":"df661133-efbf-43fe-97c3-f581c81f47a7","target_id":"b0c428683c8a3e6922d90ca0d8c2736d","source_type":"WIKI_ITEM","target_type":"SOURCE_FILE","relationship_type":"REFERENCED_BY","extra":"Wiki references source file: backend/app/database.py","gmt_create":"2026-04-24T11:02:17.582245+08:00","gmt_modified":"2026-04-24T11:02:17.582245+08:00"},{"id":1480,"source_id":"df661133-efbf-43fe-97c3-f581c81f47a7","target_id":"9228ff67d4c757a85d9421b71f4b29f5","source_type":"WIKI_ITEM","target_type":"SOURCE_FILE","relationship_type":"REFERENCED_BY","extra":"Wiki references source file: backend/app/main.py","gmt_create":"2026-04-24T11:02:17.582573+08:00","gmt_modified":"2026-04-24T11:02:17.582573+08:00"},{"id":1481,"source_id":"df661133-efbf-43fe-97c3-f581c81f47a7","target_id":"d4f95fcf50683b5bf6167c7d2a6b126d","source_type":"WIKI_ITEM","target_type":"SOURCE_FILE","relationship_type":"REFERENCED_BY","extra":"Wiki references source file: backend/alembic/versions/488d0bd5ab01_initial_migration.py","gmt_create":"2026-04-24T11:02:17.582943+08:00","gmt_modified":"2026-04-24T11:02:17.582943+08:00"},{"id":1482,"source_id":"df661133-efbf-43fe-97c3-f581c81f47a7","target_id":"b0cb6810919f64006be7aa66b2b76a61","source_type":"WIKI_ITEM","target_type":"SOURCE_FILE","relationship_type":"REFERENCED_BY","extra":"Wiki references source file: backend/alembic/versions/c3d5e7f9ab12_add_user_management_fields.py","gmt_create":"2026-04-24T11:02:17.58335+08:00","gmt_modified":"2026-04-24T11:02:17.58335+08:00"},{"id":1483,"source_id":"df661133-efbf-43fe-97c3-f581c81f47a7","target_id":"d2c1984414de6856ed5b3873c661b712","source_type":"WIKI_ITEM","target_type":"SOURCE_FILE","relationship_type":"REFERENCED_BY","extra":"Wiki references source file: frontend/lib/auth.ts","gmt_create":"2026-04-24T11:02:17.583672+08:00","gmt_modified":"2026-04-24T11:02:17.583673+08:00"},{"id":1484,"source_id":"df661133-efbf-43fe-97c3-f581c81f47a7","target_id":"5d7886d0dc99f81073a578b8aefdd375","source_type":"WIKI_ITEM","target_type":"SOURCE_FILE","relationship_type":"REFERENCED_BY","extra":"Wiki references source file: frontend/lib/api.ts","gmt_create":"2026-04-24T11:02:17.583973+08:00","gmt_modified":"2026-04-24T11:02:17.583973+08:00"},{"id":1485,"source_id":"df661133-efbf-43fe-97c3-f581c81f47a7","target_id":"5800a08224424ebced854d06365f6d44","source_type":"WIKI_ITEM","target_type":"SOURCE_FILE","relationship_type":"REFERENCED_BY","extra":"Wiki references source file: frontend/app/(auth","gmt_create":"2026-04-24T11:02:17.584307+08:00","gmt_modified":"2026-04-24T11:02:17.584307+08:00"},{"id":1486,"source_id":"df661133-efbf-43fe-97c3-f581c81f47a7","target_id":"37d7291b1373216dcf08f081a94ab1c8","source_type":"WIKI_ITEM","target_type":"SOURCE_FILE","relationship_type":"REFERENCED_BY","extra":"Wiki references source file: /Users/Chiguyong/Code/GEO#wiki#main#wiki#zh/[frontend/app/api/auth/[...nextauth]/route.ts](file:/frontend/app/api/auth/[...nextauth]/route.ts)","gmt_create":"2026-04-24T11:02:17.585037+08:00","gmt_modified":"2026-04-24T11:02:17.585037+08:00"},{"id":1487,"source_id":"df661133-efbf-43fe-97c3-f581c81f47a7","target_id":"389d631bc6c7111ba411b0b79fca455e","source_type":"WIKI_ITEM","target_type":"SOURCE_FILE","relationship_type":"REFERENCED_BY","extra":"Wiki references source file: tests/test_auth.py","gmt_create":"2026-04-24T11:02:17.585369+08:00","gmt_modified":"2026-04-24T11:02:17.585369+08:00"},{"id":1488,"source_id":"df661133-efbf-43fe-97c3-f581c81f47a7","target_id":"f5978358d04c3c917d9ca5044c7f36fa","source_type":"WIKI_ITEM","target_type":"CODE_SNIPPET","relationship_type":"CONTAINS","extra":"Wiki contains code snippet: backend/app/models/user.py#11-48","gmt_create":"2026-04-24T11:02:17.585874+08:00","gmt_modified":"2026-04-24T11:02:17.585874+08:00"},{"id":1489,"source_id":"df661133-efbf-43fe-97c3-f581c81f47a7","target_id":"46434c04e402674d97a6e2017a3a13c0","source_type":"WIKI_ITEM","target_type":"CODE_SNIPPET","relationship_type":"CONTAINS","extra":"Wiki contains code snippet: backend/app/schemas/auth.py#8-62","gmt_create":"2026-04-24T11:02:17.58637+08:00","gmt_modified":"2026-04-24T11:02:17.58637+08:00"},{"id":1490,"source_id":"e0c0ca66b8b81cf66e078a7ab162c07f","target_id":"46434c04e402674d97a6e2017a3a13c0","source_type":"SOURCE_FILE","target_type":"CODE_SNIPPET","relationship_type":"CONTAINS","extra":"Source file contains code snippet: 8-62","gmt_create":"2026-04-24T11:02:17.586722+08:00","gmt_modified":"2026-04-24T11:02:17.586723+08:00"},{"id":1491,"source_id":"df661133-efbf-43fe-97c3-f581c81f47a7","target_id":"3a0fd619768c80d413f8b02b3daec229","source_type":"WIKI_ITEM","target_type":"CODE_SNIPPET","relationship_type":"CONTAINS","extra":"Wiki contains code snippet: backend/app/services/auth.py#74-175","gmt_create":"2026-04-24T11:02:17.587241+08:00","gmt_modified":"2026-04-24T11:02:17.587241+08:00"},{"id":1492,"source_id":"4d2f3847b7c10634733118b70a1aea0b","target_id":"3a0fd619768c80d413f8b02b3daec229","source_type":"SOURCE_FILE","target_type":"CODE_SNIPPET","relationship_type":"CONTAINS","extra":"Source file contains code snippet: 74-175","gmt_create":"2026-04-24T11:02:17.587532+08:00","gmt_modified":"2026-04-24T11:02:17.587532+08:00"},{"id":1493,"source_id":"df661133-efbf-43fe-97c3-f581c81f47a7","target_id":"86af0295eebcd62f33207e158db86c81","source_type":"WIKI_ITEM","target_type":"CODE_SNIPPET","relationship_type":"CONTAINS","extra":"Wiki contains code snippet: backend/app/api/auth.py#65-115","gmt_create":"2026-04-24T11:02:17.58823+08:00","gmt_modified":"2026-04-24T11:02:17.58823+08:00"},{"id":1494,"source_id":"93022c8938ce318f167277cfa65c29a7","target_id":"86af0295eebcd62f33207e158db86c81","source_type":"SOURCE_FILE","target_type":"CODE_SNIPPET","relationship_type":"CONTAINS","extra":"Source file contains code snippet: 65-115","gmt_create":"2026-04-24T11:02:17.588592+08:00","gmt_modified":"2026-04-24T11:02:17.588592+08:00"},{"id":1495,"source_id":"df661133-efbf-43fe-97c3-f581c81f47a7","target_id":"675ab6c1ae510ca753b5e966b7b6a10c","source_type":"WIKI_ITEM","target_type":"CODE_SNIPPET","relationship_type":"CONTAINS","extra":"Wiki contains code snippet: backend/alembic/versions/c3d5e7f9ab12_add_user_management_fields.py#21-41","gmt_create":"2026-04-24T11:02:17.589011+08:00","gmt_modified":"2026-04-24T11:02:17.589011+08:00"},{"id":1496,"source_id":"df661133-efbf-43fe-97c3-f581c81f47a7","target_id":"809fc86e3ce390a1af1db1e0cd5ad787","source_type":"WIKI_ITEM","target_type":"CODE_SNIPPET","relationship_type":"CONTAINS","extra":"Wiki contains code snippet: frontend/lib/api.ts#55-84","gmt_create":"2026-04-24T11:02:17.589558+08:00","gmt_modified":"2026-04-24T11:02:17.589558+08:00"},{"id":1497,"source_id":"5d7886d0dc99f81073a578b8aefdd375","target_id":"809fc86e3ce390a1af1db1e0cd5ad787","source_type":"SOURCE_FILE","target_type":"CODE_SNIPPET","relationship_type":"CONTAINS","extra":"Source file contains code snippet: 55-84","gmt_create":"2026-04-24T11:02:17.589968+08:00","gmt_modified":"2026-04-24T11:02:17.589968+08:00"},{"id":1498,"source_id":"df661133-efbf-43fe-97c3-f581c81f47a7","target_id":"33ec8bca51cb9f667bf91088dd6b6a70","source_type":"WIKI_ITEM","target_type":"CODE_SNIPPET","relationship_type":"CONTAINS","extra":"Wiki contains code snippet: backend/app/main.py#24-48","gmt_create":"2026-04-24T11:02:17.590369+08:00","gmt_modified":"2026-04-24T11:02:17.590369+08:00"},{"id":1499,"source_id":"df661133-efbf-43fe-97c3-f581c81f47a7","target_id":"069243fafe60a85cf16a0ca40fa07180","source_type":"WIKI_ITEM","target_type":"CODE_SNIPPET","relationship_type":"CONTAINS","extra":"Wiki contains code snippet: backend/app/api/deps.py#16-43","gmt_create":"2026-04-24T11:02:17.591152+08:00","gmt_modified":"2026-04-24T11:02:17.591152+08:00"},{"id":1500,"source_id":"df661133-efbf-43fe-97c3-f581c81f47a7","target_id":"608c00e1835ad72363ef08796961faca","source_type":"WIKI_ITEM","target_type":"CODE_SNIPPET","relationship_type":"CONTAINS","extra":"Wiki contains code snippet: backend/app/config.py#4-17","gmt_create":"2026-04-24T11:02:17.59504+08:00","gmt_modified":"2026-04-24T11:02:17.59504+08:00"},{"id":1501,"source_id":"df661133-efbf-43fe-97c3-f581c81f47a7","target_id":"8aee7654d1f435ab53d8ddaabd269fed","source_type":"WIKI_ITEM","target_type":"CODE_SNIPPET","relationship_type":"CONTAINS","extra":"Wiki contains code snippet: backend/app/database.py#6-29","gmt_create":"2026-04-24T11:02:17.595846+08:00","gmt_modified":"2026-04-24T11:02:17.595846+08:00"},{"id":1502,"source_id":"df661133-efbf-43fe-97c3-f581c81f47a7","target_id":"29ee02d164db08d7b9bd4591195e191b","source_type":"WIKI_ITEM","target_type":"CODE_SNIPPET","relationship_type":"CONTAINS","extra":"Wiki contains code snippet: frontend/lib/auth.ts#5-56","gmt_create":"2026-04-24T11:02:17.596584+08:00","gmt_modified":"2026-04-24T11:02:17.596584+08:00"},{"id":1503,"source_id":"d2c1984414de6856ed5b3873c661b712","target_id":"29ee02d164db08d7b9bd4591195e191b","source_type":"SOURCE_FILE","target_type":"CODE_SNIPPET","relationship_type":"CONTAINS","extra":"Source file contains code snippet: 5-56","gmt_create":"2026-04-24T11:02:17.596923+08:00","gmt_modified":"2026-04-24T11:02:17.596923+08:00"},{"id":1504,"source_id":"df661133-efbf-43fe-97c3-f581c81f47a7","target_id":"73c4889fcacaea737921a568bf20383d","source_type":"WIKI_ITEM","target_type":"CODE_SNIPPET","relationship_type":"CONTAINS","extra":"Wiki contains code snippet: frontend/lib/auth.ts#13-32","gmt_create":"2026-04-24T11:02:17.598958+08:00","gmt_modified":"2026-04-24T11:02:17.598958+08:00"},{"id":1505,"source_id":"d2c1984414de6856ed5b3873c661b712","target_id":"73c4889fcacaea737921a568bf20383d","source_type":"SOURCE_FILE","target_type":"CODE_SNIPPET","relationship_type":"CONTAINS","extra":"Source file contains code snippet: 13-32","gmt_create":"2026-04-24T11:02:17.599388+08:00","gmt_modified":"2026-04-24T11:02:17.599389+08:00"},{"id":1506,"source_id":"df661133-efbf-43fe-97c3-f581c81f47a7","target_id":"11c2505e56ba9a48c50be4c915f22c9d","source_type":"WIKI_ITEM","target_type":"CODE_SNIPPET","relationship_type":"CONTAINS","extra":"Wiki contains code snippet: backend/app/services/auth.py#27-37","gmt_create":"2026-04-24T11:02:17.601161+08:00","gmt_modified":"2026-04-24T11:02:17.601161+08:00"},{"id":1507,"source_id":"4d2f3847b7c10634733118b70a1aea0b","target_id":"11c2505e56ba9a48c50be4c915f22c9d","source_type":"SOURCE_FILE","target_type":"CODE_SNIPPET","relationship_type":"CONTAINS","extra":"Source file contains code snippet: 27-37","gmt_create":"2026-04-24T11:02:17.601545+08:00","gmt_modified":"2026-04-24T11:02:17.601545+08:00"},{"id":1508,"source_id":"df661133-efbf-43fe-97c3-f581c81f47a7","target_id":"5f32b18b18cea3b2bdc9150366c24e5e","source_type":"WIKI_ITEM","target_type":"CODE_SNIPPET","relationship_type":"CONTAINS","extra":"Wiki contains code snippet: backend/app/api/deps.py#26-37","gmt_create":"2026-04-24T11:02:17.601968+08:00","gmt_modified":"2026-04-24T11:02:17.601968+08:00"},{"id":1509,"source_id":"9d08667997a868fc07c9b4e328e44224","target_id":"5f32b18b18cea3b2bdc9150366c24e5e","source_type":"SOURCE_FILE","target_type":"CODE_SNIPPET","relationship_type":"CONTAINS","extra":"Source file contains code snippet: 26-37","gmt_create":"2026-04-24T11:02:17.602636+08:00","gmt_modified":"2026-04-24T11:02:17.602636+08:00"},{"id":1510,"source_id":"df661133-efbf-43fe-97c3-f581c81f47a7","target_id":"c4abaa8a82ad75d09ee66f97fbad4b96","source_type":"WIKI_ITEM","target_type":"CODE_SNIPPET","relationship_type":"CONTAINS","extra":"Wiki contains code snippet: backend/app/config.py#9-10","gmt_create":"2026-04-24T11:02:17.603102+08:00","gmt_modified":"2026-04-24T11:02:17.603102+08:00"},{"id":1511,"source_id":"9ff19022ef915615911280e3c49ed44b","target_id":"c4abaa8a82ad75d09ee66f97fbad4b96","source_type":"SOURCE_FILE","target_type":"CODE_SNIPPET","relationship_type":"CONTAINS","extra":"Source file contains code snippet: 9-10","gmt_create":"2026-04-24T11:02:17.603401+08:00","gmt_modified":"2026-04-24T11:02:17.603402+08:00"},{"id":1512,"source_id":"df661133-efbf-43fe-97c3-f581c81f47a7","target_id":"08ac91fb508b386f0e6c66e53b03a471","source_type":"WIKI_ITEM","target_type":"CODE_SNIPPET","relationship_type":"CONTAINS","extra":"Wiki contains code snippet: backend/app/schemas/auth.py#8-11","gmt_create":"2026-04-24T11:02:17.604811+08:00","gmt_modified":"2026-04-24T11:02:17.604811+08:00"},{"id":1513,"source_id":"e0c0ca66b8b81cf66e078a7ab162c07f","target_id":"08ac91fb508b386f0e6c66e53b03a471","source_type":"SOURCE_FILE","target_type":"CODE_SNIPPET","relationship_type":"CONTAINS","extra":"Source file contains code snippet: 8-11","gmt_create":"2026-04-24T11:02:17.60518+08:00","gmt_modified":"2026-04-24T11:02:17.60518+08:00"},{"id":1514,"source_id":"df661133-efbf-43fe-97c3-f581c81f47a7","target_id":"d4ea500c0acb4ebf267a44908e23f787","source_type":"WIKI_ITEM","target_type":"CODE_SNIPPET","relationship_type":"CONTAINS","extra":"Wiki contains code snippet: backend/app/services/auth.py#40-55","gmt_create":"2026-04-24T11:02:17.605584+08:00","gmt_modified":"2026-04-24T11:02:17.605584+08:00"},{"id":1515,"source_id":"4d2f3847b7c10634733118b70a1aea0b","target_id":"d4ea500c0acb4ebf267a44908e23f787","source_type":"SOURCE_FILE","target_type":"CODE_SNIPPET","relationship_type":"CONTAINS","extra":"Source file contains code snippet: 40-55","gmt_create":"2026-04-24T11:02:17.605874+08:00","gmt_modified":"2026-04-24T11:02:17.605874+08:00"},{"id":1516,"source_id":"df661133-efbf-43fe-97c3-f581c81f47a7","target_id":"b4f0bea37f71296167571d8831ebe6d5","source_type":"WIKI_ITEM","target_type":"CODE_SNIPPET","relationship_type":"CONTAINS","extra":"Wiki contains code snippet: tests/test_auth.py#25-58","gmt_create":"2026-04-24T11:02:17.60772+08:00","gmt_modified":"2026-04-24T11:02:17.607721+08:00"},{"id":1517,"source_id":"389d631bc6c7111ba411b0b79fca455e","target_id":"b4f0bea37f71296167571d8831ebe6d5","source_type":"SOURCE_FILE","target_type":"CODE_SNIPPET","relationship_type":"CONTAINS","extra":"Source file contains code snippet: 25-58","gmt_create":"2026-04-24T11:02:17.608058+08:00","gmt_modified":"2026-04-24T11:02:17.608058+08:00"},{"id":1518,"source_id":"df661133-efbf-43fe-97c3-f581c81f47a7","target_id":"46f7431da5eb82bbd7686a71abaddf78","source_type":"WIKI_ITEM","target_type":"CODE_SNIPPET","relationship_type":"CONTAINS","extra":"Wiki contains code snippet: backend/app/api/auth.py#42-57","gmt_create":"2026-04-24T11:02:17.608532+08:00","gmt_modified":"2026-04-24T11:02:17.608532+08:00"},{"id":1519,"source_id":"93022c8938ce318f167277cfa65c29a7","target_id":"46f7431da5eb82bbd7686a71abaddf78","source_type":"SOURCE_FILE","target_type":"CODE_SNIPPET","relationship_type":"CONTAINS","extra":"Source file contains code snippet: 42-57","gmt_create":"2026-04-24T11:02:17.608872+08:00","gmt_modified":"2026-04-24T11:02:17.608872+08:00"},{"id":1520,"source_id":"df661133-efbf-43fe-97c3-f581c81f47a7","target_id":"0ba2ea54873608360c48c8b5aaeea20f","source_type":"WIKI_ITEM","target_type":"CODE_SNIPPET","relationship_type":"CONTAINS","extra":"Wiki contains code snippet: backend/app/services/auth.py#58-71","gmt_create":"2026-04-24T11:02:17.609376+08:00","gmt_modified":"2026-04-24T11:02:17.609376+08:00"},{"id":1521,"source_id":"4d2f3847b7c10634733118b70a1aea0b","target_id":"0ba2ea54873608360c48c8b5aaeea20f","source_type":"SOURCE_FILE","target_type":"CODE_SNIPPET","relationship_type":"CONTAINS","extra":"Source file contains code snippet: 58-71","gmt_create":"2026-04-24T11:02:17.609794+08:00","gmt_modified":"2026-04-24T11:02:17.609794+08:00"},{"id":1522,"source_id":"df661133-efbf-43fe-97c3-f581c81f47a7","target_id":"2d170933ae8c838199f6d68a2b9165c0","source_type":"WIKI_ITEM","target_type":"CODE_SNIPPET","relationship_type":"CONTAINS","extra":"Wiki contains code snippet: tests/test_auth.py#61-84","gmt_create":"2026-04-24T11:02:17.610895+08:00","gmt_modified":"2026-04-24T11:02:17.610895+08:00"},{"id":1523,"source_id":"389d631bc6c7111ba411b0b79fca455e","target_id":"2d170933ae8c838199f6d68a2b9165c0","source_type":"SOURCE_FILE","target_type":"CODE_SNIPPET","relationship_type":"CONTAINS","extra":"Source file contains code snippet: 61-84","gmt_create":"2026-04-24T11:02:17.6112+08:00","gmt_modified":"2026-04-24T11:02:17.6112+08:00"},{"id":1524,"source_id":"df661133-efbf-43fe-97c3-f581c81f47a7","target_id":"0ea85b56099b9087bd22eec96b7bb752","source_type":"WIKI_ITEM","target_type":"CODE_SNIPPET","relationship_type":"CONTAINS","extra":"Wiki contains code snippet: backend/app/services/auth.py#74-140","gmt_create":"2026-04-24T11:02:17.611696+08:00","gmt_modified":"2026-04-24T11:02:17.611696+08:00"},{"id":1525,"source_id":"4d2f3847b7c10634733118b70a1aea0b","target_id":"0ea85b56099b9087bd22eec96b7bb752","source_type":"SOURCE_FILE","target_type":"CODE_SNIPPET","relationship_type":"CONTAINS","extra":"Source file contains code snippet: 74-140","gmt_create":"2026-04-24T11:02:17.612307+08:00","gmt_modified":"2026-04-24T11:02:17.612307+08:00"},{"id":1526,"source_id":"df661133-efbf-43fe-97c3-f581c81f47a7","target_id":"2a4087b6941ca17dd651147f2f23451c","source_type":"WIKI_ITEM","target_type":"CODE_SNIPPET","relationship_type":"CONTAINS","extra":"Wiki contains code snippet: backend/app/api/auth.py#65-90","gmt_create":"2026-04-24T11:02:17.613704+08:00","gmt_modified":"2026-04-24T11:02:17.613704+08:00"},{"id":1527,"source_id":"93022c8938ce318f167277cfa65c29a7","target_id":"2a4087b6941ca17dd651147f2f23451c","source_type":"SOURCE_FILE","target_type":"CODE_SNIPPET","relationship_type":"CONTAINS","extra":"Source file contains code snippet: 65-90","gmt_create":"2026-04-24T11:02:17.614071+08:00","gmt_modified":"2026-04-24T11:02:17.614071+08:00"},{"id":1528,"source_id":"df661133-efbf-43fe-97c3-f581c81f47a7","target_id":"88c12e200d5c3ea53c695aa4209cecd9","source_type":"WIKI_ITEM","target_type":"CODE_SNIPPET","relationship_type":"CONTAINS","extra":"Wiki contains code snippet: backend/app/api/auth.py#65-76","gmt_create":"2026-04-24T11:02:17.614574+08:00","gmt_modified":"2026-04-24T11:02:17.614574+08:00"},{"id":1529,"source_id":"93022c8938ce318f167277cfa65c29a7","target_id":"88c12e200d5c3ea53c695aa4209cecd9","source_type":"SOURCE_FILE","target_type":"CODE_SNIPPET","relationship_type":"CONTAINS","extra":"Source file contains code snippet: 65-76","gmt_create":"2026-04-24T11:02:17.615017+08:00","gmt_modified":"2026-04-24T11:02:17.615017+08:00"},{"id":1530,"source_id":"df661133-efbf-43fe-97c3-f581c81f47a7","target_id":"cecc8857775f7928d465b68e429493d2","source_type":"WIKI_ITEM","target_type":"CODE_SNIPPET","relationship_type":"CONTAINS","extra":"Wiki contains code snippet: backend/app/services/auth.py#110-140","gmt_create":"2026-04-24T11:02:17.615713+08:00","gmt_modified":"2026-04-24T11:02:17.615713+08:00"},{"id":1531,"source_id":"df661133-efbf-43fe-97c3-f581c81f47a7","target_id":"42b92d878423a23067e9a6da104e3a5e","source_type":"WIKI_ITEM","target_type":"CODE_SNIPPET","relationship_type":"CONTAINS","extra":"Wiki contains code snippet: backend/app/api/auth.py#79-90","gmt_create":"2026-04-24T11:02:17.616887+08:00","gmt_modified":"2026-04-24T11:02:17.616888+08:00"},{"id":1532,"source_id":"93022c8938ce318f167277cfa65c29a7","target_id":"42b92d878423a23067e9a6da104e3a5e","source_type":"SOURCE_FILE","target_type":"CODE_SNIPPET","relationship_type":"CONTAINS","extra":"Source file contains code snippet: 79-90","gmt_create":"2026-04-24T11:02:17.617309+08:00","gmt_modified":"2026-04-24T11:02:17.617309+08:00"},{"id":1533,"source_id":"df661133-efbf-43fe-97c3-f581c81f47a7","target_id":"46e69841e5c5dc62faa55c9f066586d6","source_type":"WIKI_ITEM","target_type":"CODE_SNIPPET","relationship_type":"CONTAINS","extra":"Wiki contains code snippet: backend/app/services/auth.py#74-107","gmt_create":"2026-04-24T11:02:17.617785+08:00","gmt_modified":"2026-04-24T11:02:17.617785+08:00"},{"id":1534,"source_id":"df661133-efbf-43fe-97c3-f581c81f47a7","target_id":"abadc99952ad6e00ab4bfb66b84732bb","source_type":"WIKI_ITEM","target_type":"CODE_SNIPPET","relationship_type":"CONTAINS","extra":"Wiki contains code snippet: backend/app/schemas/auth.py#33-41","gmt_create":"2026-04-24T11:02:17.618924+08:00","gmt_modified":"2026-04-24T11:02:17.618925+08:00"},{"id":1535,"source_id":"e0c0ca66b8b81cf66e078a7ab162c07f","target_id":"abadc99952ad6e00ab4bfb66b84732bb","source_type":"SOURCE_FILE","target_type":"CODE_SNIPPET","relationship_type":"CONTAINS","extra":"Source file contains code snippet: 33-41","gmt_create":"2026-04-24T11:02:17.619333+08:00","gmt_modified":"2026-04-24T11:02:17.619333+08:00"},{"id":1536,"source_id":"df661133-efbf-43fe-97c3-f581c81f47a7","target_id":"f784a33e47128515d518555d99103f62","source_type":"WIKI_ITEM","target_type":"CODE_SNIPPET","relationship_type":"CONTAINS","extra":"Wiki contains code snippet: backend/app/services/auth.py#143-175","gmt_create":"2026-04-24T11:02:17.619742+08:00","gmt_modified":"2026-04-24T11:02:17.619742+08:00"},{"id":1537,"source_id":"4d2f3847b7c10634733118b70a1aea0b","target_id":"f784a33e47128515d518555d99103f62","source_type":"SOURCE_FILE","target_type":"CODE_SNIPPET","relationship_type":"CONTAINS","extra":"Source file contains code snippet: 143-175","gmt_create":"2026-04-24T11:02:17.620025+08:00","gmt_modified":"2026-04-24T11:02:17.620025+08:00"},{"id":1538,"source_id":"df661133-efbf-43fe-97c3-f581c81f47a7","target_id":"173f8de5896e18fc81cdd5d72e2a8c07","source_type":"WIKI_ITEM","target_type":"CODE_SNIPPET","relationship_type":"CONTAINS","extra":"Wiki contains code snippet: backend/app/api/auth.py#93-115","gmt_create":"2026-04-24T11:02:17.621068+08:00","gmt_modified":"2026-04-24T11:02:17.621068+08:00"},{"id":1539,"source_id":"93022c8938ce318f167277cfa65c29a7","target_id":"173f8de5896e18fc81cdd5d72e2a8c07","source_type":"SOURCE_FILE","target_type":"CODE_SNIPPET","relationship_type":"CONTAINS","extra":"Source file contains code snippet: 93-115","gmt_create":"2026-04-24T11:02:17.62207+08:00","gmt_modified":"2026-04-24T11:02:17.62207+08:00"},{"id":1540,"source_id":"df661133-efbf-43fe-97c3-f581c81f47a7","target_id":"3ab144009e705151f69698d2d8a81cea","source_type":"WIKI_ITEM","target_type":"CODE_SNIPPET","relationship_type":"CONTAINS","extra":"Wiki contains code snippet: backend/app/services/auth.py#35-37","gmt_create":"2026-04-24T11:02:17.622971+08:00","gmt_modified":"2026-04-24T11:02:17.622972+08:00"},{"id":1541,"source_id":"4d2f3847b7c10634733118b70a1aea0b","target_id":"3ab144009e705151f69698d2d8a81cea","source_type":"SOURCE_FILE","target_type":"CODE_SNIPPET","relationship_type":"CONTAINS","extra":"Source file contains code snippet: 35-37","gmt_create":"2026-04-24T11:02:17.623434+08:00","gmt_modified":"2026-04-24T11:02:17.623434+08:00"},{"id":1542,"source_id":"df661133-efbf-43fe-97c3-f581c81f47a7","target_id":"570a917d85850ab1208fce5823b110a3","source_type":"WIKI_ITEM","target_type":"CODE_SNIPPET","relationship_type":"CONTAINS","extra":"Wiki contains code snippet: backend/app/api/auth.py#60-62","gmt_create":"2026-04-24T11:02:17.62436+08:00","gmt_modified":"2026-04-24T11:02:17.62436+08:00"},{"id":1543,"source_id":"93022c8938ce318f167277cfa65c29a7","target_id":"570a917d85850ab1208fce5823b110a3","source_type":"SOURCE_FILE","target_type":"CODE_SNIPPET","relationship_type":"CONTAINS","extra":"Source file contains code snippet: 60-62","gmt_create":"2026-04-24T11:02:17.624694+08:00","gmt_modified":"2026-04-24T11:02:17.624694+08:00"},{"id":1544,"source_id":"df661133-efbf-43fe-97c3-f581c81f47a7","target_id":"f92c0c41197c488f04f994bf0f7ea465","source_type":"WIKI_ITEM","target_type":"CODE_SNIPPET","relationship_type":"CONTAINS","extra":"Wiki contains code snippet: tests/test_auth.py#87-104","gmt_create":"2026-04-24T11:02:17.625099+08:00","gmt_modified":"2026-04-24T11:02:17.625099+08:00"},{"id":1545,"source_id":"389d631bc6c7111ba411b0b79fca455e","target_id":"f92c0c41197c488f04f994bf0f7ea465","source_type":"SOURCE_FILE","target_type":"CODE_SNIPPET","relationship_type":"CONTAINS","extra":"Source file contains code snippet: 87-104","gmt_create":"2026-04-24T11:02:17.625385+08:00","gmt_modified":"2026-04-24T11:02:17.625385+08:00"},{"id":1546,"source_id":"df661133-efbf-43fe-97c3-f581c81f47a7","target_id":"5688471e2418628ac2a6409451708d06","source_type":"WIKI_ITEM","target_type":"CODE_SNIPPET","relationship_type":"CONTAINS","extra":"Wiki contains code snippet: backend/app/api/auth.py#1-115","gmt_create":"2026-04-24T11:02:17.626962+08:00","gmt_modified":"2026-04-24T11:02:17.626962+08:00"},{"id":1547,"source_id":"93022c8938ce318f167277cfa65c29a7","target_id":"5688471e2418628ac2a6409451708d06","source_type":"SOURCE_FILE","target_type":"CODE_SNIPPET","relationship_type":"CONTAINS","extra":"Source file contains code snippet: 1-115","gmt_create":"2026-04-24T11:02:17.627296+08:00","gmt_modified":"2026-04-24T11:02:17.627296+08:00"},{"id":1548,"source_id":"df661133-efbf-43fe-97c3-f581c81f47a7","target_id":"76e6c0abb49fec57cac4892837a143c9","source_type":"WIKI_ITEM","target_type":"CODE_SNIPPET","relationship_type":"CONTAINS","extra":"Wiki contains code snippet: backend/app/api/deps.py#1-43","gmt_create":"2026-04-24T11:02:17.62778+08:00","gmt_modified":"2026-04-24T11:02:17.62778+08:00"},{"id":1549,"source_id":"df661133-efbf-43fe-97c3-f581c81f47a7","target_id":"08c1475254a5bc8877ff29a895de3b6a","source_type":"WIKI_ITEM","target_type":"CODE_SNIPPET","relationship_type":"CONTAINS","extra":"Wiki contains code snippet: backend/app/services/auth.py#1-175","gmt_create":"2026-04-24T11:02:17.628417+08:00","gmt_modified":"2026-04-24T11:02:17.628417+08:00"},{"id":1550,"source_id":"df661133-efbf-43fe-97c3-f581c81f47a7","target_id":"9bfc041fe426da2eb78353827e8d9163","source_type":"WIKI_ITEM","target_type":"CODE_SNIPPET","relationship_type":"CONTAINS","extra":"Wiki contains code snippet: backend/app/database.py#1-29","gmt_create":"2026-04-24T11:02:17.629023+08:00","gmt_modified":"2026-04-24T11:02:17.629023+08:00"},{"id":1551,"source_id":"df661133-efbf-43fe-97c3-f581c81f47a7","target_id":"84fbed7d35f7752e2117a74fcaf5f0e9","source_type":"WIKI_ITEM","target_type":"CODE_SNIPPET","relationship_type":"CONTAINS","extra":"Wiki contains code snippet: backend/app/config.py#1-17","gmt_create":"2026-04-24T11:02:17.629535+08:00","gmt_modified":"2026-04-24T11:02:17.629535+08:00"},{"id":1552,"source_id":"df661133-efbf-43fe-97c3-f581c81f47a7","target_id":"c2747ca16b879bca0f68955534c3c4fc","source_type":"WIKI_ITEM","target_type":"CODE_SNIPPET","relationship_type":"CONTAINS","extra":"Wiki contains code snippet: backend/app/main.py#1-48","gmt_create":"2026-04-24T11:02:17.630073+08:00","gmt_modified":"2026-04-24T11:02:17.630073+08:00"},{"id":1553,"source_id":"df661133-efbf-43fe-97c3-f581c81f47a7","target_id":"1721defc3d6206478d3c0692cc821761","source_type":"WIKI_ITEM","target_type":"CODE_SNIPPET","relationship_type":"CONTAINS","extra":"Wiki contains code snippet: tests/test_auth.py#25-104","gmt_create":"2026-04-24T11:02:17.632419+08:00","gmt_modified":"2026-04-24T11:02:17.632419+08:00"},{"id":1554,"source_id":"df661133-efbf-43fe-97c3-f581c81f47a7","target_id":"7075cde1c771c46dbbd37b3c09dac53d","source_type":"WIKI_ITEM","target_type":"CODE_SNIPPET","relationship_type":"CONTAINS","extra":"Wiki contains code snippet: backend/app/api/deps.py#20-41","gmt_create":"2026-04-24T11:02:17.633252+08:00","gmt_modified":"2026-04-24T11:02:17.633252+08:00"},{"id":1555,"source_id":"9d08667997a868fc07c9b4e328e44224","target_id":"7075cde1c771c46dbbd37b3c09dac53d","source_type":"SOURCE_FILE","target_type":"CODE_SNIPPET","relationship_type":"CONTAINS","extra":"Source file contains code snippet: 20-41","gmt_create":"2026-04-24T11:02:17.636427+08:00","gmt_modified":"2026-04-24T11:02:17.636427+08:00"},{"id":1556,"source_id":"df661133-efbf-43fe-97c3-f581c81f47a7","target_id":"607e99e751640281d26516c772548b93","source_type":"WIKI_ITEM","target_type":"CODE_SNIPPET","relationship_type":"CONTAINS","extra":"Wiki contains code snippet: frontend/lib/api.ts#17-39","gmt_create":"2026-04-24T11:02:17.637267+08:00","gmt_modified":"2026-04-24T11:02:17.637267+08:00"},{"id":1557,"source_id":"5d7886d0dc99f81073a578b8aefdd375","target_id":"607e99e751640281d26516c772548b93","source_type":"SOURCE_FILE","target_type":"CODE_SNIPPET","relationship_type":"CONTAINS","extra":"Source file contains code snippet: 17-39","gmt_create":"2026-04-24T11:02:17.637632+08:00","gmt_modified":"2026-04-24T11:02:17.637632+08:00"},{"id":1583,"source_id":"9228ff67d4c757a85d9421b71f4b29f5","target_id":"0fcc0fe680a7ca8b8c7f4d579b77aeec","source_type":"SOURCE_FILE","target_type":"CODE_SNIPPET","relationship_type":"CONTAINS","extra":"Source file contains code snippet: 12-78","gmt_create":"2026-04-24T11:02:30.048441+08:00","gmt_modified":"2026-04-24T11:02:30.048441+08:00"},{"id":1585,"source_id":"93022c8938ce318f167277cfa65c29a7","target_id":"10d3948b1394ffa0110796edfa0bfc25","source_type":"SOURCE_FILE","target_type":"CODE_SNIPPET","relationship_type":"CONTAINS","extra":"Source file contains code snippet: 30","gmt_create":"2026-04-24T11:02:30.050019+08:00","gmt_modified":"2026-04-24T11:02:30.050019+08:00"},{"id":1589,"source_id":"58901c94d975d87e652a4dc6c8dda656","target_id":"3c41910bad9855635d1362efc314463a","source_type":"SOURCE_FILE","target_type":"CODE_SNIPPET","relationship_type":"CONTAINS","extra":"Source file contains code snippet: 15","gmt_create":"2026-04-24T11:02:30.051832+08:00","gmt_modified":"2026-04-24T11:02:30.051832+08:00"},{"id":1591,"source_id":"5386144bf3c668c6fa14481c0d85a214","target_id":"f32e078c985967af30d2c526290d9acb","source_type":"SOURCE_FILE","target_type":"CODE_SNIPPET","relationship_type":"CONTAINS","extra":"Source file contains code snippet: 23","gmt_create":"2026-04-24T11:02:30.052506+08:00","gmt_modified":"2026-04-24T11:02:30.052506+08:00"},{"id":1593,"source_id":"f26740f2a1532b38c816663a4f665dbf","target_id":"c10a89cdd47474f51664a239b82cc2e2","source_type":"SOURCE_FILE","target_type":"CODE_SNIPPET","relationship_type":"CONTAINS","extra":"Source file contains code snippet: 17","gmt_create":"2026-04-24T11:02:30.05328+08:00","gmt_modified":"2026-04-24T11:02:30.05328+08:00"},{"id":1596,"source_id":"9228ff67d4c757a85d9421b71f4b29f5","target_id":"d6ebce8c7d9e9de127486400670ebed0","source_type":"SOURCE_FILE","target_type":"CODE_SNIPPET","relationship_type":"CONTAINS","extra":"Source file contains code snippet: 39-84","gmt_create":"2026-04-24T11:02:30.054595+08:00","gmt_modified":"2026-04-24T11:02:30.054595+08:00"},{"id":1599,"source_id":"5386144bf3c668c6fa14481c0d85a214","target_id":"ec3ed02cad3cd8af4bacb5c978273092","source_type":"SOURCE_FILE","target_type":"CODE_SNIPPET","relationship_type":"CONTAINS","extra":"Source file contains code snippet: 26-77","gmt_create":"2026-04-24T11:02:30.056273+08:00","gmt_modified":"2026-04-24T11:02:30.056273+08:00"},{"id":1603,"source_id":"9228ff67d4c757a85d9421b71f4b29f5","target_id":"2db9940a42c91fc92f23595491ea93d1","source_type":"SOURCE_FILE","target_type":"CODE_SNIPPET","relationship_type":"CONTAINS","extra":"Source file contains code snippet: 67-78","gmt_create":"2026-04-24T11:02:30.058168+08:00","gmt_modified":"2026-04-24T11:02:30.058168+08:00"},{"id":1609,"source_id":"93022c8938ce318f167277cfa65c29a7","target_id":"68fbb2bd365f96a98ea187a9738c4460","source_type":"SOURCE_FILE","target_type":"CODE_SNIPPET","relationship_type":"CONTAINS","extra":"Source file contains code snippet: 33-57","gmt_create":"2026-04-24T11:02:30.061204+08:00","gmt_modified":"2026-04-24T11:02:30.061204+08:00"},{"id":1619,"source_id":"58901c94d975d87e652a4dc6c8dda656","target_id":"44f9c9f195e096efbd6c6a6f97880944","source_type":"SOURCE_FILE","target_type":"CODE_SNIPPET","relationship_type":"CONTAINS","extra":"Source file contains code snippet: 51-75","gmt_create":"2026-04-24T11:02:30.069323+08:00","gmt_modified":"2026-04-24T11:02:30.069323+08:00"},{"id":1621,"source_id":"04e3926c080e795713bff683e7dc9d3e","target_id":"cbe8ffc1cfb98ac79c7659e968191837","source_type":"SOURCE_FILE","target_type":"CODE_SNIPPET","relationship_type":"CONTAINS","extra":"Source file contains code snippet: 343-466","gmt_create":"2026-04-24T11:02:30.070073+08:00","gmt_modified":"2026-04-24T11:02:30.070073+08:00"},{"id":1624,"source_id":"b250fc6c32106a7f3e0c3ad152dfc097","target_id":"97f9b6149bd43feb0f69cf2582ab6305","source_type":"SOURCE_FILE","target_type":"CODE_SNIPPET","relationship_type":"CONTAINS","extra":"Source file contains code snippet: 85-117","gmt_create":"2026-04-24T11:02:30.071724+08:00","gmt_modified":"2026-04-24T11:02:30.071724+08:00"},{"id":1626,"source_id":"5013cbe89f1c6f03533eb218400cedb0","target_id":"ce4de96353f8f81ca825173ddbec1150","source_type":"SOURCE_FILE","target_type":"CODE_SNIPPET","relationship_type":"CONTAINS","extra":"Source file contains code snippet: 12-41","gmt_create":"2026-04-24T11:02:30.072769+08:00","gmt_modified":"2026-04-24T11:02:30.072769+08:00"},{"id":1628,"source_id":"b250fc6c32106a7f3e0c3ad152dfc097","target_id":"a87a1a7c1723518159d5818c197996cc","source_type":"SOURCE_FILE","target_type":"CODE_SNIPPET","relationship_type":"CONTAINS","extra":"Source file contains code snippet: 56-155","gmt_create":"2026-04-24T11:02:30.073474+08:00","gmt_modified":"2026-04-24T11:02:30.073474+08:00"},{"id":1630,"source_id":"f26740f2a1532b38c816663a4f665dbf","target_id":"0e4bc0a539e0ccc6832031bdaf1eb1ca","source_type":"SOURCE_FILE","target_type":"CODE_SNIPPET","relationship_type":"CONTAINS","extra":"Source file contains code snippet: 29-45","gmt_create":"2026-04-24T11:02:30.074211+08:00","gmt_modified":"2026-04-24T11:02:30.074211+08:00"},{"id":1632,"source_id":"3809c5ab912511e0e093ba02a4fc918f","target_id":"f7314a4515e822cba6f37d7a8f1970f3","source_type":"SOURCE_FILE","target_type":"CODE_SNIPPET","relationship_type":"CONTAINS","extra":"Source file contains code snippet: 14-46","gmt_create":"2026-04-24T11:02:30.074964+08:00","gmt_modified":"2026-04-24T11:02:30.074964+08:00"},{"id":1635,"source_id":"5883a8ef4fc156d76b71ffdb5ecdf232","target_id":"ef31f4aa4fbd1b6ff76eba467b757a04","source_type":"SOURCE_FILE","target_type":"CODE_SNIPPET","relationship_type":"CONTAINS","extra":"Source file contains code snippet: 34-69","gmt_create":"2026-04-24T11:02:30.076612+08:00","gmt_modified":"2026-04-24T11:02:30.076612+08:00"},{"id":1646,"source_id":"93022c8938ce318f167277cfa65c29a7","target_id":"3a7201f4564dbcf35c5771f1b5d58cb6","source_type":"SOURCE_FILE","target_type":"CODE_SNIPPET","relationship_type":"CONTAINS","extra":"Source file contains code snippet: 46-50","gmt_create":"2026-04-24T11:02:30.084522+08:00","gmt_modified":"2026-04-24T11:02:30.084522+08:00"},{"id":1650,"source_id":"58901c94d975d87e652a4dc6c8dda656","target_id":"39c3dbe67ab2ae74446fe6a118bd8738","source_type":"SOURCE_FILE","target_type":"CODE_SNIPPET","relationship_type":"CONTAINS","extra":"Source file contains code snippet: 25-29","gmt_create":"2026-04-24T11:02:30.086409+08:00","gmt_modified":"2026-04-24T11:02:30.08641+08:00"},{"id":1652,"source_id":"5386144bf3c668c6fa14481c0d85a214","target_id":"68d937267aab2509edc0c7b67e1b5ef6","source_type":"SOURCE_FILE","target_type":"CODE_SNIPPET","relationship_type":"CONTAINS","extra":"Source file contains code snippet: 53-57","gmt_create":"2026-04-24T11:02:30.087245+08:00","gmt_modified":"2026-04-24T11:02:30.087245+08:00"},{"id":1654,"source_id":"f26740f2a1532b38c816663a4f665dbf","target_id":"3d0bf5a05f6a7d2b8b12bb91e8f93642","source_type":"SOURCE_FILE","target_type":"CODE_SNIPPET","relationship_type":"CONTAINS","extra":"Source file contains code snippet: 22-25","gmt_create":"2026-04-24T11:02:30.08803+08:00","gmt_modified":"2026-04-24T11:02:30.08803+08:00"},{"id":1656,"source_id":"5883a8ef4fc156d76b71ffdb5ecdf232","target_id":"a9c1b0716ae36af22fce6148c2e40ce5","source_type":"SOURCE_FILE","target_type":"CODE_SNIPPET","relationship_type":"CONTAINS","extra":"Source file contains code snippet: 47-49","gmt_create":"2026-04-24T11:02:30.088761+08:00","gmt_modified":"2026-04-24T11:02:30.088762+08:00"},{"id":1657,"source_id":"34e572eb-6fc8-4de7-8061-63783ef8be24","target_id":"2793782c-91c8-4052-b9db-39513426c736","source_type":"WIKI_ITEM","target_type":"WIKI_ITEM","relationship_type":"PARENT_CHILD","extra":"Wiki parent-child relationship: 34e572eb-6fc8-4de7-8061-63783ef8be24 -\u003e 2793782c-91c8-4052-b9db-39513426c736","gmt_create":"2026-04-24T11:08:43.063241+08:00","gmt_modified":"2026-04-24T11:08:43.063241+08:00"},{"id":1658,"source_id":"34e572eb-6fc8-4de7-8061-63783ef8be24","target_id":"e23bd86e-b4ac-40eb-b1c1-38d929fd5419","source_type":"WIKI_ITEM","target_type":"WIKI_ITEM","relationship_type":"PARENT_CHILD","extra":"Wiki parent-child relationship: 34e572eb-6fc8-4de7-8061-63783ef8be24 -\u003e e23bd86e-b4ac-40eb-b1c1-38d929fd5419","gmt_create":"2026-04-24T11:08:43.063978+08:00","gmt_modified":"2026-04-24T11:08:43.063978+08:00"},{"id":1659,"source_id":"34e572eb-6fc8-4de7-8061-63783ef8be24","target_id":"70b3948e-f456-42d2-b7ad-a0097ad5ee5f","source_type":"WIKI_ITEM","target_type":"WIKI_ITEM","relationship_type":"PARENT_CHILD","extra":"Wiki parent-child relationship: 34e572eb-6fc8-4de7-8061-63783ef8be24 -\u003e 70b3948e-f456-42d2-b7ad-a0097ad5ee5f","gmt_create":"2026-04-24T11:08:43.064613+08:00","gmt_modified":"2026-04-24T11:08:43.064613+08:00"},{"id":1661,"source_id":"34e572eb-6fc8-4de7-8061-63783ef8be24","target_id":"7e679d62-c415-4d6a-a7e5-d41d00e0ed69","source_type":"WIKI_ITEM","target_type":"WIKI_ITEM","relationship_type":"PARENT_CHILD","extra":"Wiki parent-child relationship: 34e572eb-6fc8-4de7-8061-63783ef8be24 -\u003e 7e679d62-c415-4d6a-a7e5-d41d00e0ed69","gmt_create":"2026-04-24T11:08:43.065797+08:00","gmt_modified":"2026-04-24T11:08:43.065797+08:00"},{"id":1686,"source_id":"b0c36b2b-bb03-4624-933d-c1f6a320b7ca","target_id":"0ef1efea889dba3e1f299626df479571","source_type":"WIKI_ITEM","target_type":"SOURCE_FILE","relationship_type":"REFERENCED_BY","extra":"Wiki references source file: tests/conftest.py","gmt_create":"2026-05-23T15:16:36.206816+08:00","gmt_modified":"2026-05-23T15:16:36.206817+08:00"},{"id":1687,"source_id":"b0c36b2b-bb03-4624-933d-c1f6a320b7ca","target_id":"389d631bc6c7111ba411b0b79fca455e","source_type":"WIKI_ITEM","target_type":"SOURCE_FILE","relationship_type":"REFERENCED_BY","extra":"Wiki references source file: tests/test_auth.py","gmt_create":"2026-05-23T15:16:36.207764+08:00","gmt_modified":"2026-05-23T15:16:36.207764+08:00"},{"id":1688,"source_id":"b0c36b2b-bb03-4624-933d-c1f6a320b7ca","target_id":"80a0429cc47931de27ddb17a62b8dd9c","source_type":"WIKI_ITEM","target_type":"SOURCE_FILE","relationship_type":"REFERENCED_BY","extra":"Wiki references source file: tests/test_business_flow.py","gmt_create":"2026-05-23T15:16:36.210436+08:00","gmt_modified":"2026-05-23T15:16:36.210436+08:00"},{"id":1689,"source_id":"b0c36b2b-bb03-4624-933d-c1f6a320b7ca","target_id":"b07a4fb9cecbbd66a6910ccbc7651f19","source_type":"WIKI_ITEM","target_type":"SOURCE_FILE","relationship_type":"REFERENCED_BY","extra":"Wiki references source file: tests/test_citation_engine.py","gmt_create":"2026-05-23T15:16:36.211921+08:00","gmt_modified":"2026-05-23T15:16:36.211921+08:00"},{"id":1690,"source_id":"b0c36b2b-bb03-4624-933d-c1f6a320b7ca","target_id":"42ff5383133d176cec9eb88682483be3","source_type":"WIKI_ITEM","target_type":"SOURCE_FILE","relationship_type":"REFERENCED_BY","extra":"Wiki references source file: tests/test_citations.py","gmt_create":"2026-05-23T15:16:36.213087+08:00","gmt_modified":"2026-05-23T15:16:36.213087+08:00"},{"id":1691,"source_id":"b0c36b2b-bb03-4624-933d-c1f6a320b7ca","target_id":"1eb698126da2b6c95924e3ca32115e3a","source_type":"WIKI_ITEM","target_type":"SOURCE_FILE","relationship_type":"REFERENCED_BY","extra":"Wiki references source file: tests/test_content_agents.py","gmt_create":"2026-05-23T15:16:36.213756+08:00","gmt_modified":"2026-05-23T15:16:36.213756+08:00"},{"id":1692,"source_id":"b0c36b2b-bb03-4624-933d-c1f6a320b7ca","target_id":"ff5699698ead454bb1137030cf21c533","source_type":"WIKI_ITEM","target_type":"SOURCE_FILE","relationship_type":"REFERENCED_BY","extra":"Wiki references source file: tests/test_llm_provider.py","gmt_create":"2026-05-23T15:16:36.214345+08:00","gmt_modified":"2026-05-23T15:16:36.214345+08:00"},{"id":1693,"source_id":"b0c36b2b-bb03-4624-933d-c1f6a320b7ca","target_id":"a8bfbe8f5db65abf625c19edc3999a97","source_type":"WIKI_ITEM","target_type":"SOURCE_FILE","relationship_type":"REFERENCED_BY","extra":"Wiki references source file: tests/test_pipeline_engine.py","gmt_create":"2026-05-23T15:16:36.21477+08:00","gmt_modified":"2026-05-23T15:16:36.21477+08:00"},{"id":1694,"source_id":"b0c36b2b-bb03-4624-933d-c1f6a320b7ca","target_id":"0bfe423695374ece56313bb55e9d3e86","source_type":"WIKI_ITEM","target_type":"SOURCE_FILE","relationship_type":"REFERENCED_BY","extra":"Wiki references source file: tests/test_platform_rules.py","gmt_create":"2026-05-23T15:16:36.215178+08:00","gmt_modified":"2026-05-23T15:16:36.215178+08:00"},{"id":1695,"source_id":"b0c36b2b-bb03-4624-933d-c1f6a320b7ca","target_id":"bbcb3a67f564dd7c05d3f8684c9bf8c6","source_type":"WIKI_ITEM","target_type":"SOURCE_FILE","relationship_type":"REFERENCED_BY","extra":"Wiki references source file: tests/test_prompt_template.py","gmt_create":"2026-05-23T15:16:36.215561+08:00","gmt_modified":"2026-05-23T15:16:36.215561+08:00"},{"id":1696,"source_id":"b0c36b2b-bb03-4624-933d-c1f6a320b7ca","target_id":"0613e76b9679be7f998fb8fd8056e686","source_type":"WIKI_ITEM","target_type":"SOURCE_FILE","relationship_type":"REFERENCED_BY","extra":"Wiki references source file: tests/test_queries.py","gmt_create":"2026-05-23T15:16:36.215949+08:00","gmt_modified":"2026-05-23T15:16:36.215949+08:00"},{"id":1697,"source_id":"b0c36b2b-bb03-4624-933d-c1f6a320b7ca","target_id":"2aab65d07faab01583455277d363742f","source_type":"WIKI_ITEM","target_type":"SOURCE_FILE","relationship_type":"REFERENCED_BY","extra":"Wiki references source file: tests/test_rag_service.py","gmt_create":"2026-05-23T15:16:36.216332+08:00","gmt_modified":"2026-05-23T15:16:36.216332+08:00"},{"id":1698,"source_id":"b0c36b2b-bb03-4624-933d-c1f6a320b7ca","target_id":"b2f0d46a31a5441594f2e777365fc156","source_type":"WIKI_ITEM","target_type":"SOURCE_FILE","relationship_type":"REFERENCED_BY","extra":"Wiki references source file: tests/test_scheduler.py","gmt_create":"2026-05-23T15:16:36.216833+08:00","gmt_modified":"2026-05-23T15:16:36.216833+08:00"},{"id":1699,"source_id":"b0c36b2b-bb03-4624-933d-c1f6a320b7ca","target_id":"af7c8d3b4ba659f1bd8c4989b5ed7a62","source_type":"WIKI_ITEM","target_type":"SOURCE_FILE","relationship_type":"REFERENCED_BY","extra":"Wiki references source file: backend/tests/test_integration/test_full_flow.py","gmt_create":"2026-05-23T15:16:36.217275+08:00","gmt_modified":"2026-05-23T15:16:36.217275+08:00"},{"id":1700,"source_id":"b0c36b2b-bb03-4624-933d-c1f6a320b7ca","target_id":"9228ff67d4c757a85d9421b71f4b29f5","source_type":"WIKI_ITEM","target_type":"SOURCE_FILE","relationship_type":"REFERENCED_BY","extra":"Wiki references source file: backend/app/main.py","gmt_create":"2026-05-23T15:16:36.217851+08:00","gmt_modified":"2026-05-23T15:16:36.217851+08:00"},{"id":1701,"source_id":"b0c36b2b-bb03-4624-933d-c1f6a320b7ca","target_id":"9d08667997a868fc07c9b4e328e44224","source_type":"WIKI_ITEM","target_type":"SOURCE_FILE","relationship_type":"REFERENCED_BY","extra":"Wiki references source file: backend/app/api/deps.py","gmt_create":"2026-05-23T15:16:36.218458+08:00","gmt_modified":"2026-05-23T15:16:36.218458+08:00"},{"id":1702,"source_id":"b0c36b2b-bb03-4624-933d-c1f6a320b7ca","target_id":"4d2f3847b7c10634733118b70a1aea0b","source_type":"WIKI_ITEM","target_type":"SOURCE_FILE","relationship_type":"REFERENCED_BY","extra":"Wiki references source file: backend/app/services/auth.py","gmt_create":"2026-05-23T15:16:36.218906+08:00","gmt_modified":"2026-05-23T15:16:36.218906+08:00"},{"id":1703,"source_id":"b0c36b2b-bb03-4624-933d-c1f6a320b7ca","target_id":"74040de652d5e57f548bb5c4adc3e1a0","source_type":"WIKI_ITEM","target_type":"SOURCE_FILE","relationship_type":"REFERENCED_BY","extra":"Wiki references source file: backend/app/workers/citation_engine.py","gmt_create":"2026-05-23T15:16:36.2202+08:00","gmt_modified":"2026-05-23T15:16:36.2202+08:00"},{"id":1704,"source_id":"b0c36b2b-bb03-4624-933d-c1f6a320b7ca","target_id":"5cbb1e3f112aeba62a14b0b8999fc0f5","source_type":"WIKI_ITEM","target_type":"SOURCE_FILE","relationship_type":"REFERENCED_BY","extra":"Wiki references source file: backend/app/workers/scheduler.py","gmt_create":"2026-05-23T15:16:36.220695+08:00","gmt_modified":"2026-05-23T15:16:36.220695+08:00"},{"id":1705,"source_id":"b0c36b2b-bb03-4624-933d-c1f6a320b7ca","target_id":"93022c8938ce318f167277cfa65c29a7","source_type":"WIKI_ITEM","target_type":"SOURCE_FILE","relationship_type":"REFERENCED_BY","extra":"Wiki references source file: backend/app/api/auth.py","gmt_create":"2026-05-23T15:16:36.221198+08:00","gmt_modified":"2026-05-23T15:16:36.221198+08:00"},{"id":1706,"source_id":"b0c36b2b-bb03-4624-933d-c1f6a320b7ca","target_id":"7538ffe4902ab6041adb28b19844962a","source_type":"WIKI_ITEM","target_type":"SOURCE_FILE","relationship_type":"REFERENCED_BY","extra":"Wiki references source file: backend/app/api/citations.py","gmt_create":"2026-05-23T15:16:36.221874+08:00","gmt_modified":"2026-05-23T15:16:36.221874+08:00"},{"id":1707,"source_id":"b0c36b2b-bb03-4624-933d-c1f6a320b7ca","target_id":"6b3d903205941aa9391dd90016e1102c","source_type":"WIKI_ITEM","target_type":"SOURCE_FILE","relationship_type":"REFERENCED_BY","extra":"Wiki references source file: backend/app/api/queries.py","gmt_create":"2026-05-23T15:16:36.222439+08:00","gmt_modified":"2026-05-23T15:16:36.222439+08:00"},{"id":1708,"source_id":"b0c36b2b-bb03-4624-933d-c1f6a320b7ca","target_id":"b0c428683c8a3e6922d90ca0d8c2736d","source_type":"WIKI_ITEM","target_type":"SOURCE_FILE","relationship_type":"REFERENCED_BY","extra":"Wiki references source file: backend/app/database.py","gmt_create":"2026-05-23T15:16:36.222865+08:00","gmt_modified":"2026-05-23T15:16:36.222866+08:00"},{"id":1709,"source_id":"b0c36b2b-bb03-4624-933d-c1f6a320b7ca","target_id":"9ff19022ef915615911280e3c49ed44b","source_type":"WIKI_ITEM","target_type":"SOURCE_FILE","relationship_type":"REFERENCED_BY","extra":"Wiki references source file: backend/app/config.py","gmt_create":"2026-05-23T15:16:36.223258+08:00","gmt_modified":"2026-05-23T15:16:36.223258+08:00"},{"id":1710,"source_id":"b0c36b2b-bb03-4624-933d-c1f6a320b7ca","target_id":"13b8f594e7cace5c8a9255dc801dcad8","source_type":"WIKI_ITEM","target_type":"SOURCE_FILE","relationship_type":"REFERENCED_BY","extra":"Wiki references source file: backend/app/agent_framework/agents/content_generator_agent.py","gmt_create":"2026-05-23T15:16:36.223801+08:00","gmt_modified":"2026-05-23T15:16:36.223801+08:00"},{"id":1711,"source_id":"b0c36b2b-bb03-4624-933d-c1f6a320b7ca","target_id":"750f8d79d83ee910e9d18e8a4fe37e22","source_type":"WIKI_ITEM","target_type":"SOURCE_FILE","relationship_type":"REFERENCED_BY","extra":"Wiki references source file: backend/app/agent_framework/agents/deai_agent.py","gmt_create":"2026-05-23T15:16:36.224278+08:00","gmt_modified":"2026-05-23T15:16:36.224278+08:00"},{"id":1712,"source_id":"b0c36b2b-bb03-4624-933d-c1f6a320b7ca","target_id":"7f8c6e94ead45ad9bab8cea9a7be2123","source_type":"WIKI_ITEM","target_type":"SOURCE_FILE","relationship_type":"REFERENCED_BY","extra":"Wiki references source file: backend/app/agent_framework/agents/geo_optimizer_agent.py","gmt_create":"2026-05-23T15:16:36.224716+08:00","gmt_modified":"2026-05-23T15:16:36.224716+08:00"},{"id":1713,"source_id":"b0c36b2b-bb03-4624-933d-c1f6a320b7ca","target_id":"609a02c9e1ccc0311885a70578b86386","source_type":"WIKI_ITEM","target_type":"SOURCE_FILE","relationship_type":"REFERENCED_BY","extra":"Wiki references source file: backend/app/agent_framework/pipeline/engine.py","gmt_create":"2026-05-23T15:16:36.227597+08:00","gmt_modified":"2026-05-23T15:16:36.227597+08:00"},{"id":1714,"source_id":"b0c36b2b-bb03-4624-933d-c1f6a320b7ca","target_id":"43642bd7bedabd97ff2f0a902b783e4e","source_type":"WIKI_ITEM","target_type":"SOURCE_FILE","relationship_type":"REFERENCED_BY","extra":"Wiki references source file: backend/app/agent_framework/pipeline/loader.py","gmt_create":"2026-05-23T15:16:36.228586+08:00","gmt_modified":"2026-05-23T15:16:36.228586+08:00"},{"id":1715,"source_id":"b0c36b2b-bb03-4624-933d-c1f6a320b7ca","target_id":"1de27749fbccdfaf785545657f58d256","source_type":"WIKI_ITEM","target_type":"SOURCE_FILE","relationship_type":"REFERENCED_BY","extra":"Wiki references source file: backend/app/services/llm/factory.py","gmt_create":"2026-05-23T15:16:36.229492+08:00","gmt_modified":"2026-05-23T15:16:36.229492+08:00"},{"id":1716,"source_id":"b0c36b2b-bb03-4624-933d-c1f6a320b7ca","target_id":"290df8332b3d104e5ea8d71dc39315b5","source_type":"WIKI_ITEM","target_type":"CODE_SNIPPET","relationship_type":"CONTAINS","extra":"Wiki contains code snippet: tests/conftest.py#1-123","gmt_create":"2026-05-23T15:16:36.230309+08:00","gmt_modified":"2026-05-23T15:16:36.230309+08:00"},{"id":1717,"source_id":"b0c36b2b-bb03-4624-933d-c1f6a320b7ca","target_id":"85792f0b1e34b5b48b0300aa606ed6e6","source_type":"WIKI_ITEM","target_type":"CODE_SNIPPET","relationship_type":"CONTAINS","extra":"Wiki contains code snippet: backend/app/main.py#1-56","gmt_create":"2026-05-23T15:16:36.231411+08:00","gmt_modified":"2026-05-23T15:16:36.231411+08:00"},{"id":1718,"source_id":"b0c36b2b-bb03-4624-933d-c1f6a320b7ca","target_id":"76e6c0abb49fec57cac4892837a143c9","source_type":"WIKI_ITEM","target_type":"CODE_SNIPPET","relationship_type":"CONTAINS","extra":"Wiki contains code snippet: backend/app/api/deps.py#1-43","gmt_create":"2026-05-23T15:16:36.232293+08:00","gmt_modified":"2026-05-23T15:16:36.232293+08:00"},{"id":1719,"source_id":"b0c36b2b-bb03-4624-933d-c1f6a320b7ca","target_id":"f66d9907b467b110c638bd527efd95c5","source_type":"WIKI_ITEM","target_type":"CODE_SNIPPET","relationship_type":"CONTAINS","extra":"Wiki contains code snippet: backend/app/api/auth.py#1-43","gmt_create":"2026-05-23T15:16:36.233083+08:00","gmt_modified":"2026-05-23T15:16:36.233083+08:00"},{"id":1720,"source_id":"b0c36b2b-bb03-4624-933d-c1f6a320b7ca","target_id":"10d1e37bdc9f353c189b7a2fe79dc85e","source_type":"WIKI_ITEM","target_type":"CODE_SNIPPET","relationship_type":"CONTAINS","extra":"Wiki contains code snippet: backend/app/api/queries.py#1-86","gmt_create":"2026-05-23T15:16:36.233899+08:00","gmt_modified":"2026-05-23T15:16:36.233899+08:00"},{"id":1721,"source_id":"b0c36b2b-bb03-4624-933d-c1f6a320b7ca","target_id":"cbd0101fa84d957bcb1baaa623c6b31c","source_type":"WIKI_ITEM","target_type":"CODE_SNIPPET","relationship_type":"CONTAINS","extra":"Wiki contains code snippet: backend/app/api/citations.py#1-78","gmt_create":"2026-05-23T15:16:36.234893+08:00","gmt_modified":"2026-05-23T15:16:36.234893+08:00"},{"id":1722,"source_id":"b0c36b2b-bb03-4624-933d-c1f6a320b7ca","target_id":"116584ea9162c1bc05911f39f9ef82b6","source_type":"WIKI_ITEM","target_type":"CODE_SNIPPET","relationship_type":"CONTAINS","extra":"Wiki contains code snippet: backend/app/workers/citation_engine.py#1-309","gmt_create":"2026-05-23T15:16:36.235813+08:00","gmt_modified":"2026-05-23T15:16:36.235813+08:00"},{"id":1723,"source_id":"b0c36b2b-bb03-4624-933d-c1f6a320b7ca","target_id":"9630036e63fc15cb81b202cf79671aab","source_type":"WIKI_ITEM","target_type":"CODE_SNIPPET","relationship_type":"CONTAINS","extra":"Wiki contains code snippet: backend/app/workers/scheduler.py#1-182","gmt_create":"2026-05-23T15:16:36.236809+08:00","gmt_modified":"2026-05-23T15:16:36.236809+08:00"},{"id":1724,"source_id":"b0c36b2b-bb03-4624-933d-c1f6a320b7ca","target_id":"9bfc041fe426da2eb78353827e8d9163","source_type":"WIKI_ITEM","target_type":"CODE_SNIPPET","relationship_type":"CONTAINS","extra":"Wiki contains code snippet: backend/app/database.py#1-29","gmt_create":"2026-05-23T15:16:36.23771+08:00","gmt_modified":"2026-05-23T15:16:36.23771+08:00"},{"id":1725,"source_id":"b0c36b2b-bb03-4624-933d-c1f6a320b7ca","target_id":"ea655c6d147bc98beb42955d437260cc","source_type":"WIKI_ITEM","target_type":"CODE_SNIPPET","relationship_type":"CONTAINS","extra":"Wiki contains code snippet: backend/app/config.py#1-23","gmt_create":"2026-05-23T15:16:36.238575+08:00","gmt_modified":"2026-05-23T15:16:36.238575+08:00"},{"id":1726,"source_id":"b0c36b2b-bb03-4624-933d-c1f6a320b7ca","target_id":"461200c8ca02024dd32c214c679b9664","source_type":"WIKI_ITEM","target_type":"CODE_SNIPPET","relationship_type":"CONTAINS","extra":"Wiki contains code snippet: backend/app/agent_framework/agents/content_generator_agent.py#1-299","gmt_create":"2026-05-23T15:16:36.239366+08:00","gmt_modified":"2026-05-23T15:16:36.239366+08:00"},{"id":1727,"source_id":"13b8f594e7cace5c8a9255dc801dcad8","target_id":"461200c8ca02024dd32c214c679b9664","source_type":"SOURCE_FILE","target_type":"CODE_SNIPPET","relationship_type":"CONTAINS","extra":"Source file contains code snippet: 1-299","gmt_create":"2026-05-23T15:16:36.240866+08:00","gmt_modified":"2026-05-23T15:16:36.240866+08:00"},{"id":1728,"source_id":"b0c36b2b-bb03-4624-933d-c1f6a320b7ca","target_id":"7f44b646183e17098f8ce4d2be931d3e","source_type":"WIKI_ITEM","target_type":"CODE_SNIPPET","relationship_type":"CONTAINS","extra":"Wiki contains code snippet: backend/app/agent_framework/agents/deai_agent.py#1-156","gmt_create":"2026-05-23T15:16:36.245637+08:00","gmt_modified":"2026-05-23T15:16:36.245638+08:00"},{"id":1729,"source_id":"750f8d79d83ee910e9d18e8a4fe37e22","target_id":"7f44b646183e17098f8ce4d2be931d3e","source_type":"SOURCE_FILE","target_type":"CODE_SNIPPET","relationship_type":"CONTAINS","extra":"Source file contains code snippet: 1-156","gmt_create":"2026-05-23T15:16:36.24631+08:00","gmt_modified":"2026-05-23T15:16:36.24631+08:00"},{"id":1730,"source_id":"b0c36b2b-bb03-4624-933d-c1f6a320b7ca","target_id":"45778eaa35d92099677ba180f1067905","source_type":"WIKI_ITEM","target_type":"CODE_SNIPPET","relationship_type":"CONTAINS","extra":"Wiki contains code snippet: backend/app/agent_framework/agents/geo_optimizer_agent.py#1-198","gmt_create":"2026-05-23T15:16:36.248542+08:00","gmt_modified":"2026-05-23T15:16:36.248543+08:00"},{"id":1731,"source_id":"7f8c6e94ead45ad9bab8cea9a7be2123","target_id":"45778eaa35d92099677ba180f1067905","source_type":"SOURCE_FILE","target_type":"CODE_SNIPPET","relationship_type":"CONTAINS","extra":"Source file contains code snippet: 1-198","gmt_create":"2026-05-23T15:16:36.248957+08:00","gmt_modified":"2026-05-23T15:16:36.248957+08:00"},{"id":1732,"source_id":"b0c36b2b-bb03-4624-933d-c1f6a320b7ca","target_id":"74bf1d1b17dff651c44a2f4dc12d7bc7","source_type":"WIKI_ITEM","target_type":"CODE_SNIPPET","relationship_type":"CONTAINS","extra":"Wiki contains code snippet: backend/app/agent_framework/pipeline/engine.py#1-536","gmt_create":"2026-05-23T15:16:36.249504+08:00","gmt_modified":"2026-05-23T15:16:36.249504+08:00"},{"id":1733,"source_id":"609a02c9e1ccc0311885a70578b86386","target_id":"74bf1d1b17dff651c44a2f4dc12d7bc7","source_type":"SOURCE_FILE","target_type":"CODE_SNIPPET","relationship_type":"CONTAINS","extra":"Source file contains code snippet: 1-536","gmt_create":"2026-05-23T15:16:36.249909+08:00","gmt_modified":"2026-05-23T15:16:36.249909+08:00"},{"id":1734,"source_id":"b0c36b2b-bb03-4624-933d-c1f6a320b7ca","target_id":"d8a98dd989912e358f7dbd278e1c5353","source_type":"WIKI_ITEM","target_type":"CODE_SNIPPET","relationship_type":"CONTAINS","extra":"Wiki contains code snippet: backend/app/agent_framework/pipeline/loader.py#1-283","gmt_create":"2026-05-23T15:16:36.251045+08:00","gmt_modified":"2026-05-23T15:16:36.251045+08:00"},{"id":1735,"source_id":"43642bd7bedabd97ff2f0a902b783e4e","target_id":"d8a98dd989912e358f7dbd278e1c5353","source_type":"SOURCE_FILE","target_type":"CODE_SNIPPET","relationship_type":"CONTAINS","extra":"Source file contains code snippet: 1-283","gmt_create":"2026-05-23T15:16:36.251436+08:00","gmt_modified":"2026-05-23T15:16:36.251436+08:00"},{"id":1736,"source_id":"b0c36b2b-bb03-4624-933d-c1f6a320b7ca","target_id":"3d0cd79c03fc72299fb184947c5d0d6c","source_type":"WIKI_ITEM","target_type":"CODE_SNIPPET","relationship_type":"CONTAINS","extra":"Wiki contains code snippet: backend/app/services/llm/factory.py#1-66","gmt_create":"2026-05-23T15:16:36.252132+08:00","gmt_modified":"2026-05-23T15:16:36.252132+08:00"},{"id":1737,"source_id":"1de27749fbccdfaf785545657f58d256","target_id":"3d0cd79c03fc72299fb184947c5d0d6c","source_type":"SOURCE_FILE","target_type":"CODE_SNIPPET","relationship_type":"CONTAINS","extra":"Source file contains code snippet: 1-66","gmt_create":"2026-05-23T15:16:36.252601+08:00","gmt_modified":"2026-05-23T15:16:36.252601+08:00"},{"id":1738,"source_id":"b0c36b2b-bb03-4624-933d-c1f6a320b7ca","target_id":"5ddf0c8d7b38e4f6126a5d85da1dfeda","source_type":"WIKI_ITEM","target_type":"CODE_SNIPPET","relationship_type":"CONTAINS","extra":"Wiki contains code snippet: tests/conftest.py#19-123","gmt_create":"2026-05-23T15:16:36.254753+08:00","gmt_modified":"2026-05-23T15:16:36.254754+08:00"},{"id":1739,"source_id":"b0c36b2b-bb03-4624-933d-c1f6a320b7ca","target_id":"c43dadd2749edf2a89b29068d7644bb9","source_type":"WIKI_ITEM","target_type":"CODE_SNIPPET","relationship_type":"CONTAINS","extra":"Wiki contains code snippet: tests/test_content_agents.py#26-54","gmt_create":"2026-05-23T15:16:36.255759+08:00","gmt_modified":"2026-05-23T15:16:36.255759+08:00"},{"id":1740,"source_id":"1eb698126da2b6c95924e3ca32115e3a","target_id":"c43dadd2749edf2a89b29068d7644bb9","source_type":"SOURCE_FILE","target_type":"CODE_SNIPPET","relationship_type":"CONTAINS","extra":"Source file contains code snippet: 26-54","gmt_create":"2026-05-23T15:16:36.256483+08:00","gmt_modified":"2026-05-23T15:16:36.256483+08:00"},{"id":1741,"source_id":"b0c36b2b-bb03-4624-933d-c1f6a320b7ca","target_id":"3251d42aeb8cbe7f90d0e9827fbecdb8","source_type":"WIKI_ITEM","target_type":"CODE_SNIPPET","relationship_type":"CONTAINS","extra":"Wiki contains code snippet: tests/test_pipeline_engine.py#148-166","gmt_create":"2026-05-23T15:16:36.25719+08:00","gmt_modified":"2026-05-23T15:16:36.257191+08:00"},{"id":1742,"source_id":"a8bfbe8f5db65abf625c19edc3999a97","target_id":"3251d42aeb8cbe7f90d0e9827fbecdb8","source_type":"SOURCE_FILE","target_type":"CODE_SNIPPET","relationship_type":"CONTAINS","extra":"Source file contains code snippet: 148-166","gmt_create":"2026-05-23T15:16:36.257695+08:00","gmt_modified":"2026-05-23T15:16:36.257695+08:00"},{"id":1743,"source_id":"b0c36b2b-bb03-4624-933d-c1f6a320b7ca","target_id":"9df233ef1be4b95068ed91bf01083ae7","source_type":"WIKI_ITEM","target_type":"CODE_SNIPPET","relationship_type":"CONTAINS","extra":"Wiki contains code snippet: tests/conftest.py#117-123","gmt_create":"2026-05-23T15:16:36.258257+08:00","gmt_modified":"2026-05-23T15:16:36.258257+08:00"},{"id":1744,"source_id":"b0c36b2b-bb03-4624-933d-c1f6a320b7ca","target_id":"6286d4be455dc058c8be2ee4e0d1175a","source_type":"WIKI_ITEM","target_type":"CODE_SNIPPET","relationship_type":"CONTAINS","extra":"Wiki contains code snippet: backend/app/main.py#38-42","gmt_create":"2026-05-23T15:16:36.260104+08:00","gmt_modified":"2026-05-23T15:16:36.260104+08:00"},{"id":1745,"source_id":"b0c36b2b-bb03-4624-933d-c1f6a320b7ca","target_id":"069243fafe60a85cf16a0ca40fa07180","source_type":"WIKI_ITEM","target_type":"CODE_SNIPPET","relationship_type":"CONTAINS","extra":"Wiki contains code snippet: backend/app/api/deps.py#16-43","gmt_create":"2026-05-23T15:16:36.261365+08:00","gmt_modified":"2026-05-23T15:16:36.261365+08:00"},{"id":1746,"source_id":"b0c36b2b-bb03-4624-933d-c1f6a320b7ca","target_id":"d5a1fb0bd23ce9240fbf79529ef94a45","source_type":"WIKI_ITEM","target_type":"CODE_SNIPPET","relationship_type":"CONTAINS","extra":"Wiki contains code snippet: backend/app/api/auth.py#13-43","gmt_create":"2026-05-23T15:16:36.26246+08:00","gmt_modified":"2026-05-23T15:16:36.26246+08:00"},{"id":1747,"source_id":"b0c36b2b-bb03-4624-933d-c1f6a320b7ca","target_id":"fe70b1fef9f36e73d26d84987e927c7a","source_type":"WIKI_ITEM","target_type":"CODE_SNIPPET","relationship_type":"CONTAINS","extra":"Wiki contains code snippet: backend/app/api/queries.py#15-86","gmt_create":"2026-05-23T15:16:36.263185+08:00","gmt_modified":"2026-05-23T15:16:36.263186+08:00"},{"id":1748,"source_id":"b0c36b2b-bb03-4624-933d-c1f6a320b7ca","target_id":"735aef72b4fe6ca4f407e69b7dda8b43","source_type":"WIKI_ITEM","target_type":"CODE_SNIPPET","relationship_type":"CONTAINS","extra":"Wiki contains code snippet: backend/app/api/citations.py#25-78","gmt_create":"2026-05-23T15:16:36.264067+08:00","gmt_modified":"2026-05-23T15:16:36.264067+08:00"},{"id":1749,"source_id":"b0c36b2b-bb03-4624-933d-c1f6a320b7ca","target_id":"8128dd67cf376d2cadf7c2d3831c380a","source_type":"WIKI_ITEM","target_type":"CODE_SNIPPET","relationship_type":"CONTAINS","extra":"Wiki contains code snippet: backend/app/database.py#23-29","gmt_create":"2026-05-23T15:16:36.264979+08:00","gmt_modified":"2026-05-23T15:16:36.264979+08:00"},{"id":1750,"source_id":"b0c36b2b-bb03-4624-933d-c1f6a320b7ca","target_id":"1721defc3d6206478d3c0692cc821761","source_type":"WIKI_ITEM","target_type":"CODE_SNIPPET","relationship_type":"CONTAINS","extra":"Wiki contains code snippet: tests/test_auth.py#25-104","gmt_create":"2026-05-23T15:16:36.265802+08:00","gmt_modified":"2026-05-23T15:16:36.265802+08:00"},{"id":1751,"source_id":"b0c36b2b-bb03-4624-933d-c1f6a320b7ca","target_id":"753a437d837246ead62b0e16c6331284","source_type":"WIKI_ITEM","target_type":"CODE_SNIPPET","relationship_type":"CONTAINS","extra":"Wiki contains code snippet: backend/app/services/auth.py#37-69","gmt_create":"2026-05-23T15:16:36.267299+08:00","gmt_modified":"2026-05-23T15:16:36.267299+08:00"},{"id":1752,"source_id":"b0c36b2b-bb03-4624-933d-c1f6a320b7ca","target_id":"d820e2daf2ea133a7aa17cdc475e44a4","source_type":"WIKI_ITEM","target_type":"CODE_SNIPPET","relationship_type":"CONTAINS","extra":"Wiki contains code snippet: tests/test_auth.py#1-104","gmt_create":"2026-05-23T15:16:36.268402+08:00","gmt_modified":"2026-05-23T15:16:36.268402+08:00"},{"id":1753,"source_id":"b0c36b2b-bb03-4624-933d-c1f6a320b7ca","target_id":"1a439c5fed6cfd188c646e1614d56371","source_type":"WIKI_ITEM","target_type":"CODE_SNIPPET","relationship_type":"CONTAINS","extra":"Wiki contains code snippet: backend/app/services/auth.py#1-69","gmt_create":"2026-05-23T15:16:36.269648+08:00","gmt_modified":"2026-05-23T15:16:36.269648+08:00"},{"id":1754,"source_id":"b0c36b2b-bb03-4624-933d-c1f6a320b7ca","target_id":"b624be78e3bffd876e403cff2557b088","source_type":"WIKI_ITEM","target_type":"CODE_SNIPPET","relationship_type":"CONTAINS","extra":"Wiki contains code snippet: backend/app/workers/citation_engine.py#19-120","gmt_create":"2026-05-23T15:16:36.271032+08:00","gmt_modified":"2026-05-23T15:16:36.271032+08:00"},{"id":1755,"source_id":"b0c36b2b-bb03-4624-933d-c1f6a320b7ca","target_id":"5c67e2f70283956b2d29a3c1443eb514","source_type":"WIKI_ITEM","target_type":"CODE_SNIPPET","relationship_type":"CONTAINS","extra":"Wiki contains code snippet: backend/app/workers/citation_engine.py#122-146","gmt_create":"2026-05-23T15:16:36.272163+08:00","gmt_modified":"2026-05-23T15:16:36.272163+08:00"},{"id":1756,"source_id":"b0c36b2b-bb03-4624-933d-c1f6a320b7ca","target_id":"309607c54b12a6340edc086ffb4737c9","source_type":"WIKI_ITEM","target_type":"CODE_SNIPPET","relationship_type":"CONTAINS","extra":"Wiki contains code snippet: backend/app/workers/citation_engine.py#148-309","gmt_create":"2026-05-23T15:16:36.273278+08:00","gmt_modified":"2026-05-23T15:16:36.273279+08:00"},{"id":1757,"source_id":"b0c36b2b-bb03-4624-933d-c1f6a320b7ca","target_id":"a57acd9da5287c915ac823784a409292","source_type":"WIKI_ITEM","target_type":"CODE_SNIPPET","relationship_type":"CONTAINS","extra":"Wiki contains code snippet: tests/test_citation_engine.py#1-127","gmt_create":"2026-05-23T15:16:36.274585+08:00","gmt_modified":"2026-05-23T15:16:36.274586+08:00"},{"id":1758,"source_id":"b0c36b2b-bb03-4624-933d-c1f6a320b7ca","target_id":"2a4f741f31f62dce8ad63be2e831f520","source_type":"WIKI_ITEM","target_type":"CODE_SNIPPET","relationship_type":"CONTAINS","extra":"Wiki contains code snippet: tests/test_citations.py#23-93","gmt_create":"2026-05-23T15:16:36.279368+08:00","gmt_modified":"2026-05-23T15:16:36.279368+08:00"},{"id":1759,"source_id":"b0c36b2b-bb03-4624-933d-c1f6a320b7ca","target_id":"692ac240965eff7e66945aa3c4c270f7","source_type":"WIKI_ITEM","target_type":"CODE_SNIPPET","relationship_type":"CONTAINS","extra":"Wiki contains code snippet: tests/test_citations.py#1-93","gmt_create":"2026-05-23T15:16:36.281396+08:00","gmt_modified":"2026-05-23T15:16:36.281396+08:00"},{"id":1760,"source_id":"b0c36b2b-bb03-4624-933d-c1f6a320b7ca","target_id":"32a0a52faca2d8d488e49c63c86075b1","source_type":"WIKI_ITEM","target_type":"CODE_SNIPPET","relationship_type":"CONTAINS","extra":"Wiki contains code snippet: tests/test_queries.py#29-154","gmt_create":"2026-05-23T15:16:36.282984+08:00","gmt_modified":"2026-05-23T15:16:36.282984+08:00"},{"id":1761,"source_id":"b0c36b2b-bb03-4624-933d-c1f6a320b7ca","target_id":"7804331f5f8c1ba5a3b6d9c1ae1c78c1","source_type":"WIKI_ITEM","target_type":"CODE_SNIPPET","relationship_type":"CONTAINS","extra":"Wiki contains code snippet: tests/test_queries.py#1-154","gmt_create":"2026-05-23T15:16:36.316134+08:00","gmt_modified":"2026-05-23T15:16:36.316134+08:00"},{"id":1762,"source_id":"b0c36b2b-bb03-4624-933d-c1f6a320b7ca","target_id":"8cdfa09247c1ca69fa5581194d1dc998","source_type":"WIKI_ITEM","target_type":"CODE_SNIPPET","relationship_type":"CONTAINS","extra":"Wiki contains code snippet: tests/test_content_agents.py#75-116","gmt_create":"2026-05-23T15:16:36.317925+08:00","gmt_modified":"2026-05-23T15:16:36.317925+08:00"},{"id":1763,"source_id":"1eb698126da2b6c95924e3ca32115e3a","target_id":"8cdfa09247c1ca69fa5581194d1dc998","source_type":"SOURCE_FILE","target_type":"CODE_SNIPPET","relationship_type":"CONTAINS","extra":"Source file contains code snippet: 75-116","gmt_create":"2026-05-23T15:16:36.318326+08:00","gmt_modified":"2026-05-23T15:16:36.318326+08:00"},{"id":1764,"source_id":"b0c36b2b-bb03-4624-933d-c1f6a320b7ca","target_id":"4d43427ff0dc504c0665bd3e3f86d68c","source_type":"WIKI_ITEM","target_type":"CODE_SNIPPET","relationship_type":"CONTAINS","extra":"Wiki contains code snippet: tests/test_content_agents.py#200-236","gmt_create":"2026-05-23T15:16:36.319097+08:00","gmt_modified":"2026-05-23T15:16:36.319097+08:00"},{"id":1765,"source_id":"1eb698126da2b6c95924e3ca32115e3a","target_id":"4d43427ff0dc504c0665bd3e3f86d68c","source_type":"SOURCE_FILE","target_type":"CODE_SNIPPET","relationship_type":"CONTAINS","extra":"Source file contains code snippet: 200-236","gmt_create":"2026-05-23T15:16:36.319906+08:00","gmt_modified":"2026-05-23T15:16:36.319906+08:00"},{"id":1766,"source_id":"b0c36b2b-bb03-4624-933d-c1f6a320b7ca","target_id":"7ec53d0bb9dd7a59cedbd4d3865fddf8","source_type":"WIKI_ITEM","target_type":"CODE_SNIPPET","relationship_type":"CONTAINS","extra":"Wiki contains code snippet: tests/test_content_agents.py#268-320","gmt_create":"2026-05-23T15:16:36.320562+08:00","gmt_modified":"2026-05-23T15:16:36.320562+08:00"},{"id":1767,"source_id":"1eb698126da2b6c95924e3ca32115e3a","target_id":"7ec53d0bb9dd7a59cedbd4d3865fddf8","source_type":"SOURCE_FILE","target_type":"CODE_SNIPPET","relationship_type":"CONTAINS","extra":"Source file contains code snippet: 268-320","gmt_create":"2026-05-23T15:16:36.320984+08:00","gmt_modified":"2026-05-23T15:16:36.320984+08:00"},{"id":1768,"source_id":"b0c36b2b-bb03-4624-933d-c1f6a320b7ca","target_id":"67b04d8d66c36c9362f3c42260f08d77","source_type":"WIKI_ITEM","target_type":"CODE_SNIPPET","relationship_type":"CONTAINS","extra":"Wiki contains code snippet: tests/test_content_agents.py#1-358","gmt_create":"2026-05-23T15:16:36.321507+08:00","gmt_modified":"2026-05-23T15:16:36.321507+08:00"},{"id":1769,"source_id":"1eb698126da2b6c95924e3ca32115e3a","target_id":"67b04d8d66c36c9362f3c42260f08d77","source_type":"SOURCE_FILE","target_type":"CODE_SNIPPET","relationship_type":"CONTAINS","extra":"Source file contains code snippet: 1-358","gmt_create":"2026-05-23T15:16:36.321902+08:00","gmt_modified":"2026-05-23T15:16:36.321902+08:00"},{"id":1770,"source_id":"b0c36b2b-bb03-4624-933d-c1f6a320b7ca","target_id":"a29fa4c505649339b1a61e2bd730e05a","source_type":"WIKI_ITEM","target_type":"CODE_SNIPPET","relationship_type":"CONTAINS","extra":"Wiki contains code snippet: tests/test_llm_provider.py#24-67","gmt_create":"2026-05-23T15:16:36.32363+08:00","gmt_modified":"2026-05-23T15:16:36.32363+08:00"},{"id":1771,"source_id":"ff5699698ead454bb1137030cf21c533","target_id":"a29fa4c505649339b1a61e2bd730e05a","source_type":"SOURCE_FILE","target_type":"CODE_SNIPPET","relationship_type":"CONTAINS","extra":"Source file contains code snippet: 24-67","gmt_create":"2026-05-23T15:16:36.324115+08:00","gmt_modified":"2026-05-23T15:16:36.324115+08:00"},{"id":1772,"source_id":"b0c36b2b-bb03-4624-933d-c1f6a320b7ca","target_id":"892c4889ccac1ebb4f9871633c633fb0","source_type":"WIKI_ITEM","target_type":"CODE_SNIPPET","relationship_type":"CONTAINS","extra":"Wiki contains code snippet: tests/test_llm_provider.py#94-153","gmt_create":"2026-05-23T15:16:36.32487+08:00","gmt_modified":"2026-05-23T15:16:36.32487+08:00"},{"id":1773,"source_id":"ff5699698ead454bb1137030cf21c533","target_id":"892c4889ccac1ebb4f9871633c633fb0","source_type":"SOURCE_FILE","target_type":"CODE_SNIPPET","relationship_type":"CONTAINS","extra":"Source file contains code snippet: 94-153","gmt_create":"2026-05-23T15:16:36.326005+08:00","gmt_modified":"2026-05-23T15:16:36.326005+08:00"},{"id":1774,"source_id":"b0c36b2b-bb03-4624-933d-c1f6a320b7ca","target_id":"5a90244fc04639f59621ea190b395d53","source_type":"WIKI_ITEM","target_type":"CODE_SNIPPET","relationship_type":"CONTAINS","extra":"Wiki contains code snippet: tests/test_llm_provider.py#200-204","gmt_create":"2026-05-23T15:16:36.32715+08:00","gmt_modified":"2026-05-23T15:16:36.32715+08:00"},{"id":1775,"source_id":"ff5699698ead454bb1137030cf21c533","target_id":"5a90244fc04639f59621ea190b395d53","source_type":"SOURCE_FILE","target_type":"CODE_SNIPPET","relationship_type":"CONTAINS","extra":"Source file contains code snippet: 200-204","gmt_create":"2026-05-23T15:16:36.327777+08:00","gmt_modified":"2026-05-23T15:16:36.327777+08:00"},{"id":1776,"source_id":"b0c36b2b-bb03-4624-933d-c1f6a320b7ca","target_id":"7a5c445db631fd099bd752645fe46eeb","source_type":"WIKI_ITEM","target_type":"CODE_SNIPPET","relationship_type":"CONTAINS","extra":"Wiki contains code snippet: backend/app/services/llm/factory.py#8-66","gmt_create":"2026-05-23T15:16:36.328343+08:00","gmt_modified":"2026-05-23T15:16:36.328343+08:00"},{"id":1777,"source_id":"1de27749fbccdfaf785545657f58d256","target_id":"7a5c445db631fd099bd752645fe46eeb","source_type":"SOURCE_FILE","target_type":"CODE_SNIPPET","relationship_type":"CONTAINS","extra":"Source file contains code snippet: 8-66","gmt_create":"2026-05-23T15:16:36.328713+08:00","gmt_modified":"2026-05-23T15:16:36.328713+08:00"},{"id":1778,"source_id":"b0c36b2b-bb03-4624-933d-c1f6a320b7ca","target_id":"470e94b38cfbc9bfa40075043a5ff609","source_type":"WIKI_ITEM","target_type":"CODE_SNIPPET","relationship_type":"CONTAINS","extra":"Wiki contains code snippet: tests/test_llm_provider.py#1-205","gmt_create":"2026-05-23T15:16:36.329291+08:00","gmt_modified":"2026-05-23T15:16:36.329291+08:00"},{"id":1779,"source_id":"ff5699698ead454bb1137030cf21c533","target_id":"470e94b38cfbc9bfa40075043a5ff609","source_type":"SOURCE_FILE","target_type":"CODE_SNIPPET","relationship_type":"CONTAINS","extra":"Source file contains code snippet: 1-205","gmt_create":"2026-05-23T15:16:36.329648+08:00","gmt_modified":"2026-05-23T15:16:36.329648+08:00"},{"id":1780,"source_id":"b0c36b2b-bb03-4624-933d-c1f6a320b7ca","target_id":"e2014a3633197a028b389f084f136010","source_type":"WIKI_ITEM","target_type":"CODE_SNIPPET","relationship_type":"CONTAINS","extra":"Wiki contains code snippet: tests/test_pipeline_engine.py#55-98","gmt_create":"2026-05-23T15:16:36.330763+08:00","gmt_modified":"2026-05-23T15:16:36.330763+08:00"},{"id":1781,"source_id":"a8bfbe8f5db65abf625c19edc3999a97","target_id":"e2014a3633197a028b389f084f136010","source_type":"SOURCE_FILE","target_type":"CODE_SNIPPET","relationship_type":"CONTAINS","extra":"Source file contains code snippet: 55-98","gmt_create":"2026-05-23T15:16:36.331132+08:00","gmt_modified":"2026-05-23T15:16:36.331132+08:00"},{"id":1782,"source_id":"b0c36b2b-bb03-4624-933d-c1f6a320b7ca","target_id":"4d80ca6fa9f1355807471a059213113a","source_type":"WIKI_ITEM","target_type":"CODE_SNIPPET","relationship_type":"CONTAINS","extra":"Wiki contains code snippet: tests/test_pipeline_engine.py#148-223","gmt_create":"2026-05-23T15:16:36.331648+08:00","gmt_modified":"2026-05-23T15:16:36.331648+08:00"},{"id":1783,"source_id":"a8bfbe8f5db65abf625c19edc3999a97","target_id":"4d80ca6fa9f1355807471a059213113a","source_type":"SOURCE_FILE","target_type":"CODE_SNIPPET","relationship_type":"CONTAINS","extra":"Source file contains code snippet: 148-223","gmt_create":"2026-05-23T15:16:36.33201+08:00","gmt_modified":"2026-05-23T15:16:36.33201+08:00"},{"id":1784,"source_id":"b0c36b2b-bb03-4624-933d-c1f6a320b7ca","target_id":"1c16d98271c83e4d1bf7759d6eff90e7","source_type":"WIKI_ITEM","target_type":"CODE_SNIPPET","relationship_type":"CONTAINS","extra":"Wiki contains code snippet: backend/app/agent_framework/pipeline/loader.py#41-134","gmt_create":"2026-05-23T15:16:36.332547+08:00","gmt_modified":"2026-05-23T15:16:36.332547+08:00"},{"id":1785,"source_id":"43642bd7bedabd97ff2f0a902b783e4e","target_id":"1c16d98271c83e4d1bf7759d6eff90e7","source_type":"SOURCE_FILE","target_type":"CODE_SNIPPET","relationship_type":"CONTAINS","extra":"Source file contains code snippet: 41-134","gmt_create":"2026-05-23T15:16:36.332928+08:00","gmt_modified":"2026-05-23T15:16:36.332928+08:00"},{"id":1786,"source_id":"b0c36b2b-bb03-4624-933d-c1f6a320b7ca","target_id":"32e64c6a06a68a4c10f248296033c62e","source_type":"WIKI_ITEM","target_type":"CODE_SNIPPET","relationship_type":"CONTAINS","extra":"Wiki contains code snippet: backend/app/agent_framework/pipeline/engine.py#31-176","gmt_create":"2026-05-23T15:16:36.333572+08:00","gmt_modified":"2026-05-23T15:16:36.333572+08:00"},{"id":1787,"source_id":"609a02c9e1ccc0311885a70578b86386","target_id":"32e64c6a06a68a4c10f248296033c62e","source_type":"SOURCE_FILE","target_type":"CODE_SNIPPET","relationship_type":"CONTAINS","extra":"Source file contains code snippet: 31-176","gmt_create":"2026-05-23T15:16:36.334143+08:00","gmt_modified":"2026-05-23T15:16:36.334143+08:00"},{"id":1788,"source_id":"b0c36b2b-bb03-4624-933d-c1f6a320b7ca","target_id":"a593c13b0e0e255b16b161d69fcd4c09","source_type":"WIKI_ITEM","target_type":"CODE_SNIPPET","relationship_type":"CONTAINS","extra":"Wiki contains code snippet: tests/test_pipeline_engine.py#1-255","gmt_create":"2026-05-23T15:16:36.334754+08:00","gmt_modified":"2026-05-23T15:16:36.334754+08:00"},{"id":1789,"source_id":"a8bfbe8f5db65abf625c19edc3999a97","target_id":"a593c13b0e0e255b16b161d69fcd4c09","source_type":"SOURCE_FILE","target_type":"CODE_SNIPPET","relationship_type":"CONTAINS","extra":"Source file contains code snippet: 1-255","gmt_create":"2026-05-23T15:16:36.33547+08:00","gmt_modified":"2026-05-23T15:16:36.33547+08:00"},{"id":1790,"source_id":"b0c36b2b-bb03-4624-933d-c1f6a320b7ca","target_id":"7a0c4604142743b83dfb37f2ff1aa3e8","source_type":"WIKI_ITEM","target_type":"CODE_SNIPPET","relationship_type":"CONTAINS","extra":"Wiki contains code snippet: backend/tests/test_integration/test_full_flow.py#94-223","gmt_create":"2026-05-23T15:16:36.337164+08:00","gmt_modified":"2026-05-23T15:16:36.337164+08:00"},{"id":1791,"source_id":"af7c8d3b4ba659f1bd8c4989b5ed7a62","target_id":"7a0c4604142743b83dfb37f2ff1aa3e8","source_type":"SOURCE_FILE","target_type":"CODE_SNIPPET","relationship_type":"CONTAINS","extra":"Source file contains code snippet: 94-223","gmt_create":"2026-05-23T15:16:36.337647+08:00","gmt_modified":"2026-05-23T15:16:36.337647+08:00"},{"id":1792,"source_id":"b0c36b2b-bb03-4624-933d-c1f6a320b7ca","target_id":"3548385bba6b1c5a95d40191fbb95fc4","source_type":"WIKI_ITEM","target_type":"CODE_SNIPPET","relationship_type":"CONTAINS","extra":"Wiki contains code snippet: backend/tests/test_integration/test_full_flow.py#228-298","gmt_create":"2026-05-23T15:16:36.338255+08:00","gmt_modified":"2026-05-23T15:16:36.338255+08:00"},{"id":1793,"source_id":"af7c8d3b4ba659f1bd8c4989b5ed7a62","target_id":"3548385bba6b1c5a95d40191fbb95fc4","source_type":"SOURCE_FILE","target_type":"CODE_SNIPPET","relationship_type":"CONTAINS","extra":"Source file contains code snippet: 228-298","gmt_create":"2026-05-23T15:16:36.338678+08:00","gmt_modified":"2026-05-23T15:16:36.338678+08:00"},{"id":1794,"source_id":"b0c36b2b-bb03-4624-933d-c1f6a320b7ca","target_id":"4c439b670fff499e1277c271ed2e3598","source_type":"WIKI_ITEM","target_type":"CODE_SNIPPET","relationship_type":"CONTAINS","extra":"Wiki contains code snippet: backend/tests/test_integration/test_full_flow.py#1-322","gmt_create":"2026-05-23T15:16:36.339576+08:00","gmt_modified":"2026-05-23T15:16:36.339576+08:00"},{"id":1795,"source_id":"af7c8d3b4ba659f1bd8c4989b5ed7a62","target_id":"4c439b670fff499e1277c271ed2e3598","source_type":"SOURCE_FILE","target_type":"CODE_SNIPPET","relationship_type":"CONTAINS","extra":"Source file contains code snippet: 1-322","gmt_create":"2026-05-23T15:16:36.340019+08:00","gmt_modified":"2026-05-23T15:16:36.340019+08:00"},{"id":1796,"source_id":"b0c36b2b-bb03-4624-933d-c1f6a320b7ca","target_id":"3a6e1b738967bf8cc651e57f48e2e126","source_type":"WIKI_ITEM","target_type":"CODE_SNIPPET","relationship_type":"CONTAINS","extra":"Wiki contains code snippet: tests/test_business_flow.py#83-126","gmt_create":"2026-05-23T15:16:36.340705+08:00","gmt_modified":"2026-05-23T15:16:36.340705+08:00"},{"id":1797,"source_id":"b0c36b2b-bb03-4624-933d-c1f6a320b7ca","target_id":"b1afd377757f1d0e9bdf87edfff3ad88","source_type":"WIKI_ITEM","target_type":"CODE_SNIPPET","relationship_type":"CONTAINS","extra":"Wiki contains code snippet: tests/test_business_flow.py#131-186","gmt_create":"2026-05-23T15:16:36.341571+08:00","gmt_modified":"2026-05-23T15:16:36.341571+08:00"},{"id":1798,"source_id":"b0c36b2b-bb03-4624-933d-c1f6a320b7ca","target_id":"de05ec7eed033e432991e5a88e1b5a06","source_type":"WIKI_ITEM","target_type":"CODE_SNIPPET","relationship_type":"CONTAINS","extra":"Wiki contains code snippet: tests/test_business_flow.py#192-222","gmt_create":"2026-05-23T15:16:36.343423+08:00","gmt_modified":"2026-05-23T15:16:36.343423+08:00"},{"id":1799,"source_id":"b0c36b2b-bb03-4624-933d-c1f6a320b7ca","target_id":"7fd61a451248b6b129299d6246f711c7","source_type":"WIKI_ITEM","target_type":"CODE_SNIPPET","relationship_type":"CONTAINS","extra":"Wiki contains code snippet: tests/test_business_flow.py#228-296","gmt_create":"2026-05-23T15:16:36.344609+08:00","gmt_modified":"2026-05-23T15:16:36.344609+08:00"},{"id":1800,"source_id":"b0c36b2b-bb03-4624-933d-c1f6a320b7ca","target_id":"53eedffff456a566fa7b0cecc7169f56","source_type":"WIKI_ITEM","target_type":"CODE_SNIPPET","relationship_type":"CONTAINS","extra":"Wiki contains code snippet: tests/test_business_flow.py#1-441","gmt_create":"2026-05-23T15:16:36.345412+08:00","gmt_modified":"2026-05-23T15:16:36.345412+08:00"},{"id":1801,"source_id":"b0c36b2b-bb03-4624-933d-c1f6a320b7ca","target_id":"906f7a8288e38d4244211f3f538fe7b6","source_type":"WIKI_ITEM","target_type":"CODE_SNIPPET","relationship_type":"CONTAINS","extra":"Wiki contains code snippet: backend/app/workers/scheduler.py#27-182","gmt_create":"2026-05-23T15:16:36.346167+08:00","gmt_modified":"2026-05-23T15:16:36.346167+08:00"},{"id":1802,"source_id":"b0c36b2b-bb03-4624-933d-c1f6a320b7ca","target_id":"1647ee2066de2ae59ba8cf88e33c5e02","source_type":"WIKI_ITEM","target_type":"CODE_SNIPPET","relationship_type":"CONTAINS","extra":"Wiki contains code snippet: tests/test_scheduler.py#1-123","gmt_create":"2026-05-23T15:16:36.346937+08:00","gmt_modified":"2026-05-23T15:16:36.346937+08:00"},{"id":1803,"source_id":"49915365-e38e-43b5-beac-6aa7d5a74cbb","target_id":"9228ff67d4c757a85d9421b71f4b29f5","source_type":"WIKI_ITEM","target_type":"SOURCE_FILE","relationship_type":"REFERENCED_BY","extra":"Wiki references source file: backend/app/main.py","gmt_create":"2026-05-23T15:17:24.156756+08:00","gmt_modified":"2026-05-23T15:17:24.156756+08:00"},{"id":1804,"source_id":"49915365-e38e-43b5-beac-6aa7d5a74cbb","target_id":"93022c8938ce318f167277cfa65c29a7","source_type":"WIKI_ITEM","target_type":"SOURCE_FILE","relationship_type":"REFERENCED_BY","extra":"Wiki references source file: backend/app/api/auth.py","gmt_create":"2026-05-23T15:17:24.15738+08:00","gmt_modified":"2026-05-23T15:17:24.15738+08:00"},{"id":1805,"source_id":"49915365-e38e-43b5-beac-6aa7d5a74cbb","target_id":"6b3d903205941aa9391dd90016e1102c","source_type":"WIKI_ITEM","target_type":"SOURCE_FILE","relationship_type":"REFERENCED_BY","extra":"Wiki references source file: backend/app/api/queries.py","gmt_create":"2026-05-23T15:17:24.157856+08:00","gmt_modified":"2026-05-23T15:17:24.157856+08:00"},{"id":1806,"source_id":"49915365-e38e-43b5-beac-6aa7d5a74cbb","target_id":"7538ffe4902ab6041adb28b19844962a","source_type":"WIKI_ITEM","target_type":"SOURCE_FILE","relationship_type":"REFERENCED_BY","extra":"Wiki references source file: backend/app/api/citations.py","gmt_create":"2026-05-23T15:17:24.158305+08:00","gmt_modified":"2026-05-23T15:17:24.158305+08:00"},{"id":1807,"source_id":"49915365-e38e-43b5-beac-6aa7d5a74cbb","target_id":"58901c94d975d87e652a4dc6c8dda656","source_type":"WIKI_ITEM","target_type":"SOURCE_FILE","relationship_type":"REFERENCED_BY","extra":"Wiki references source file: backend/app/api/reports.py","gmt_create":"2026-05-23T15:17:24.158712+08:00","gmt_modified":"2026-05-23T15:17:24.158712+08:00"},{"id":1808,"source_id":"49915365-e38e-43b5-beac-6aa7d5a74cbb","target_id":"5386144bf3c668c6fa14481c0d85a214","source_type":"WIKI_ITEM","target_type":"SOURCE_FILE","relationship_type":"REFERENCED_BY","extra":"Wiki references source file: backend/app/api/subscriptions.py","gmt_create":"2026-05-23T15:17:24.159304+08:00","gmt_modified":"2026-05-23T15:17:24.159304+08:00"},{"id":1809,"source_id":"49915365-e38e-43b5-beac-6aa7d5a74cbb","target_id":"f26740f2a1532b38c816663a4f665dbf","source_type":"WIKI_ITEM","target_type":"SOURCE_FILE","relationship_type":"REFERENCED_BY","extra":"Wiki references source file: backend/app/api/admin.py","gmt_create":"2026-05-23T15:17:24.161122+08:00","gmt_modified":"2026-05-23T15:17:24.161123+08:00"},{"id":1810,"source_id":"49915365-e38e-43b5-beac-6aa7d5a74cbb","target_id":"6a9387dd3885cf4d27bce3db87fd61c7","source_type":"WIKI_ITEM","target_type":"SOURCE_FILE","relationship_type":"REFERENCED_BY","extra":"Wiki references source file: backend/app/api/agents.py","gmt_create":"2026-05-23T15:17:24.161871+08:00","gmt_modified":"2026-05-23T15:17:24.161871+08:00"},{"id":1811,"source_id":"49915365-e38e-43b5-beac-6aa7d5a74cbb","target_id":"9af41884bf42d6e175163e89f663a479","source_type":"WIKI_ITEM","target_type":"SOURCE_FILE","relationship_type":"REFERENCED_BY","extra":"Wiki references source file: backend/app/api/analytics.py","gmt_create":"2026-05-23T15:17:24.162493+08:00","gmt_modified":"2026-05-23T15:17:24.162493+08:00"},{"id":1812,"source_id":"49915365-e38e-43b5-beac-6aa7d5a74cbb","target_id":"9c224bb80474867f8ded674babaa6e11","source_type":"WIKI_ITEM","target_type":"SOURCE_FILE","relationship_type":"REFERENCED_BY","extra":"Wiki references source file: backend/app/api/lifecycle.py","gmt_create":"2026-05-23T15:17:24.163341+08:00","gmt_modified":"2026-05-23T15:17:24.163341+08:00"},{"id":1813,"source_id":"49915365-e38e-43b5-beac-6aa7d5a74cbb","target_id":"63953ee6b39f159a61963104ac06f283","source_type":"WIKI_ITEM","target_type":"SOURCE_FILE","relationship_type":"REFERENCED_BY","extra":"Wiki references source file: backend/app/api/knowledge.py","gmt_create":"2026-05-23T15:17:24.164229+08:00","gmt_modified":"2026-05-23T15:17:24.164229+08:00"},{"id":1814,"source_id":"49915365-e38e-43b5-beac-6aa7d5a74cbb","target_id":"9d08667997a868fc07c9b4e328e44224","source_type":"WIKI_ITEM","target_type":"SOURCE_FILE","relationship_type":"REFERENCED_BY","extra":"Wiki references source file: backend/app/api/deps.py","gmt_create":"2026-05-23T15:17:24.164778+08:00","gmt_modified":"2026-05-23T15:17:24.164778+08:00"},{"id":1815,"source_id":"49915365-e38e-43b5-beac-6aa7d5a74cbb","target_id":"5883a8ef4fc156d76b71ffdb5ecdf232","source_type":"WIKI_ITEM","target_type":"SOURCE_FILE","relationship_type":"REFERENCED_BY","extra":"Wiki references source file: backend/app/middleware/rate_limit.py","gmt_create":"2026-05-23T15:17:24.165716+08:00","gmt_modified":"2026-05-23T15:17:24.165716+08:00"},{"id":1816,"source_id":"49915365-e38e-43b5-beac-6aa7d5a74cbb","target_id":"e0c0ca66b8b81cf66e078a7ab162c07f","source_type":"WIKI_ITEM","target_type":"SOURCE_FILE","relationship_type":"REFERENCED_BY","extra":"Wiki references source file: backend/app/schemas/auth.py","gmt_create":"2026-05-23T15:17:24.166436+08:00","gmt_modified":"2026-05-23T15:17:24.166436+08:00"},{"id":1817,"source_id":"49915365-e38e-43b5-beac-6aa7d5a74cbb","target_id":"f301b79d833233ce39d350e82a71c938","source_type":"WIKI_ITEM","target_type":"SOURCE_FILE","relationship_type":"REFERENCED_BY","extra":"Wiki references source file: backend/app/schemas/query.py","gmt_create":"2026-05-23T15:17:24.166929+08:00","gmt_modified":"2026-05-23T15:17:24.166929+08:00"},{"id":1818,"source_id":"49915365-e38e-43b5-beac-6aa7d5a74cbb","target_id":"1a3336b4af8a39a055e912724338580c","source_type":"WIKI_ITEM","target_type":"SOURCE_FILE","relationship_type":"REFERENCED_BY","extra":"Wiki references source file: backend/app/schemas/citation.py","gmt_create":"2026-05-23T15:17:24.167341+08:00","gmt_modified":"2026-05-23T15:17:24.167341+08:00"},{"id":1819,"source_id":"49915365-e38e-43b5-beac-6aa7d5a74cbb","target_id":"5013cbe89f1c6f03533eb218400cedb0","source_type":"WIKI_ITEM","target_type":"SOURCE_FILE","relationship_type":"REFERENCED_BY","extra":"Wiki references source file: backend/app/schemas/subscription.py","gmt_create":"2026-05-23T15:17:24.167751+08:00","gmt_modified":"2026-05-23T15:17:24.167752+08:00"},{"id":1820,"source_id":"49915365-e38e-43b5-beac-6aa7d5a74cbb","target_id":"6940047dd4c29a8a219b1b50e358f7c1","source_type":"WIKI_ITEM","target_type":"SOURCE_FILE","relationship_type":"REFERENCED_BY","extra":"Wiki references source file: backend/app/schemas/analytics.py","gmt_create":"2026-05-23T15:17:24.168313+08:00","gmt_modified":"2026-05-23T15:17:24.168313+08:00"},{"id":1821,"source_id":"49915365-e38e-43b5-beac-6aa7d5a74cbb","target_id":"952c887faf6f91370b174bd4e1ad6e00","source_type":"WIKI_ITEM","target_type":"SOURCE_FILE","relationship_type":"REFERENCED_BY","extra":"Wiki references source file: backend/app/schemas/lifecycle.py","gmt_create":"2026-05-23T15:17:24.169203+08:00","gmt_modified":"2026-05-23T15:17:24.169203+08:00"},{"id":1822,"source_id":"49915365-e38e-43b5-beac-6aa7d5a74cbb","target_id":"ed4505205a22ba55c7d4a83b0b24eaa4","source_type":"WIKI_ITEM","target_type":"SOURCE_FILE","relationship_type":"REFERENCED_BY","extra":"Wiki references source file: backend/app/schemas/knowledge.py","gmt_create":"2026-05-23T15:17:24.170114+08:00","gmt_modified":"2026-05-23T15:17:24.170114+08:00"},{"id":1823,"source_id":"49915365-e38e-43b5-beac-6aa7d5a74cbb","target_id":"4d2f3847b7c10634733118b70a1aea0b","source_type":"WIKI_ITEM","target_type":"SOURCE_FILE","relationship_type":"REFERENCED_BY","extra":"Wiki references source file: backend/app/services/auth.py","gmt_create":"2026-05-23T15:17:24.171119+08:00","gmt_modified":"2026-05-23T15:17:24.171119+08:00"},{"id":1824,"source_id":"49915365-e38e-43b5-beac-6aa7d5a74cbb","target_id":"88d22de3b2a7419868e8ae19130d860c","source_type":"WIKI_ITEM","target_type":"SOURCE_FILE","relationship_type":"REFERENCED_BY","extra":"Wiki references source file: backend/app/services/query.py","gmt_create":"2026-05-23T15:17:24.172532+08:00","gmt_modified":"2026-05-23T15:17:24.172533+08:00"},{"id":1825,"source_id":"49915365-e38e-43b5-beac-6aa7d5a74cbb","target_id":"04e3926c080e795713bff683e7dc9d3e","source_type":"WIKI_ITEM","target_type":"SOURCE_FILE","relationship_type":"REFERENCED_BY","extra":"Wiki references source file: backend/app/services/citation.py","gmt_create":"2026-05-23T15:17:24.173154+08:00","gmt_modified":"2026-05-23T15:17:24.173154+08:00"},{"id":1826,"source_id":"49915365-e38e-43b5-beac-6aa7d5a74cbb","target_id":"b250fc6c32106a7f3e0c3ad152dfc097","source_type":"WIKI_ITEM","target_type":"SOURCE_FILE","relationship_type":"REFERENCED_BY","extra":"Wiki references source file: backend/app/services/subscription.py","gmt_create":"2026-05-23T15:17:24.173811+08:00","gmt_modified":"2026-05-23T15:17:24.173811+08:00"},{"id":1827,"source_id":"49915365-e38e-43b5-beac-6aa7d5a74cbb","target_id":"3809c5ab912511e0e093ba02a4fc918f","source_type":"WIKI_ITEM","target_type":"SOURCE_FILE","relationship_type":"REFERENCED_BY","extra":"Wiki references source file: backend/app/services/admin.py","gmt_create":"2026-05-23T15:17:24.174428+08:00","gmt_modified":"2026-05-23T15:17:24.174428+08:00"},{"id":1828,"source_id":"49915365-e38e-43b5-beac-6aa7d5a74cbb","target_id":"a0c569cd2355079f9f4045a198ddcadc","source_type":"WIKI_ITEM","target_type":"SOURCE_FILE","relationship_type":"REFERENCED_BY","extra":"Wiki references source file: backend/app/services/analytics/insights.py","gmt_create":"2026-05-23T15:17:24.175148+08:00","gmt_modified":"2026-05-23T15:17:24.175148+08:00"},{"id":1829,"source_id":"49915365-e38e-43b5-beac-6aa7d5a74cbb","target_id":"984d67382822ff587452a79f89e0d336","source_type":"WIKI_ITEM","target_type":"SOURCE_FILE","relationship_type":"REFERENCED_BY","extra":"Wiki references source file: backend/app/services/analytics/tracker.py","gmt_create":"2026-05-23T15:17:24.175886+08:00","gmt_modified":"2026-05-23T15:17:24.175886+08:00"},{"id":1830,"source_id":"49915365-e38e-43b5-beac-6aa7d5a74cbb","target_id":"45c9d96513947cae445aaaf8b58b4266","source_type":"WIKI_ITEM","target_type":"SOURCE_FILE","relationship_type":"REFERENCED_BY","extra":"Wiki references source file: backend/app/services/knowledge/rag_service.py","gmt_create":"2026-05-23T15:17:24.176407+08:00","gmt_modified":"2026-05-23T15:17:24.176407+08:00"},{"id":1831,"source_id":"49915365-e38e-43b5-beac-6aa7d5a74cbb","target_id":"3b13f3fa9b6316b23cfd01d740a85b81","source_type":"WIKI_ITEM","target_type":"SOURCE_FILE","relationship_type":"REFERENCED_BY","extra":"Wiki references source file: backend/app/services/knowledge/chunker.py","gmt_create":"2026-05-23T15:17:24.178905+08:00","gmt_modified":"2026-05-23T15:17:24.178905+08:00"},{"id":1832,"source_id":"49915365-e38e-43b5-beac-6aa7d5a74cbb","target_id":"aaa9ce5fdaad8eaa6887e8c079e0b7af","source_type":"WIKI_ITEM","target_type":"SOURCE_FILE","relationship_type":"REFERENCED_BY","extra":"Wiki references source file: backend/app/services/knowledge/embedder.py","gmt_create":"2026-05-23T15:17:24.17971+08:00","gmt_modified":"2026-05-23T15:17:24.17971+08:00"},{"id":1833,"source_id":"49915365-e38e-43b5-beac-6aa7d5a74cbb","target_id":"000702af850583bb79fec57f7fd1fcca","source_type":"WIKI_ITEM","target_type":"SOURCE_FILE","relationship_type":"REFERENCED_BY","extra":"Wiki references source file: backend/app/services/knowledge/retriever.py","gmt_create":"2026-05-23T15:17:24.180374+08:00","gmt_modified":"2026-05-23T15:17:24.180374+08:00"},{"id":1834,"source_id":"49915365-e38e-43b5-beac-6aa7d5a74cbb","target_id":"9ff19022ef915615911280e3c49ed44b","source_type":"WIKI_ITEM","target_type":"SOURCE_FILE","relationship_type":"REFERENCED_BY","extra":"Wiki references source file: backend/app/config.py","gmt_create":"2026-05-23T15:17:24.18144+08:00","gmt_modified":"2026-05-23T15:17:24.18144+08:00"},{"id":1835,"source_id":"49915365-e38e-43b5-beac-6aa7d5a74cbb","target_id":"c59f8c276697a070dffc581fe94d809c","source_type":"WIKI_ITEM","target_type":"SOURCE_FILE","relationship_type":"REFERENCED_BY","extra":"Wiki references source file: backend/app/models/user.py","gmt_create":"2026-05-23T15:17:24.182209+08:00","gmt_modified":"2026-05-23T15:17:24.18221+08:00"},{"id":1836,"source_id":"49915365-e38e-43b5-beac-6aa7d5a74cbb","target_id":"b74caccb06844efcdb14d8324cff65c2","source_type":"WIKI_ITEM","target_type":"SOURCE_FILE","relationship_type":"REFERENCED_BY","extra":"Wiki references source file: backend/app/models/query.py","gmt_create":"2026-05-23T15:17:24.183087+08:00","gmt_modified":"2026-05-23T15:17:24.183087+08:00"},{"id":1837,"source_id":"49915365-e38e-43b5-beac-6aa7d5a74cbb","target_id":"b4a81ef789630d0af6a8d50859d01bf3","source_type":"WIKI_ITEM","target_type":"SOURCE_FILE","relationship_type":"REFERENCED_BY","extra":"Wiki references source file: backend/app/models/citation_record.py","gmt_create":"2026-05-23T15:17:24.184037+08:00","gmt_modified":"2026-05-23T15:17:24.184037+08:00"},{"id":1838,"source_id":"49915365-e38e-43b5-beac-6aa7d5a74cbb","target_id":"069738f21ac2da7349d22683e8c36929","source_type":"WIKI_ITEM","target_type":"SOURCE_FILE","relationship_type":"REFERENCED_BY","extra":"Wiki references source file: backend/app/models/query_task.py","gmt_create":"2026-05-23T15:17:24.18506+08:00","gmt_modified":"2026-05-23T15:17:24.18506+08:00"},{"id":1839,"source_id":"49915365-e38e-43b5-beac-6aa7d5a74cbb","target_id":"bceca00463fe55d3bcafda728f97f723","source_type":"WIKI_ITEM","target_type":"SOURCE_FILE","relationship_type":"REFERENCED_BY","extra":"Wiki references source file: backend/app/models/subscription.py","gmt_create":"2026-05-23T15:17:24.185602+08:00","gmt_modified":"2026-05-23T15:17:24.185602+08:00"},{"id":1840,"source_id":"49915365-e38e-43b5-beac-6aa7d5a74cbb","target_id":"aa6cf63a65ebf46a29606af91112eb7b","source_type":"WIKI_ITEM","target_type":"SOURCE_FILE","relationship_type":"REFERENCED_BY","extra":"Wiki references source file: backend/app/models/agent.py","gmt_create":"2026-05-23T15:17:24.186064+08:00","gmt_modified":"2026-05-23T15:17:24.186064+08:00"},{"id":1841,"source_id":"49915365-e38e-43b5-beac-6aa7d5a74cbb","target_id":"97cfe961cb7386b4022a51706ae8f5dd","source_type":"WIKI_ITEM","target_type":"SOURCE_FILE","relationship_type":"REFERENCED_BY","extra":"Wiki references source file: backend/app/models/lifecycle.py","gmt_create":"2026-05-23T15:17:24.186929+08:00","gmt_modified":"2026-05-23T15:17:24.186929+08:00"},{"id":1842,"source_id":"49915365-e38e-43b5-beac-6aa7d5a74cbb","target_id":"4774aadaa8ace576601bdaa8d3e11f74","source_type":"WIKI_ITEM","target_type":"SOURCE_FILE","relationship_type":"REFERENCED_BY","extra":"Wiki references source file: backend/app/models/knowledge.py","gmt_create":"2026-05-23T15:17:24.187568+08:00","gmt_modified":"2026-05-23T15:17:24.187568+08:00"},{"id":1843,"source_id":"49915365-e38e-43b5-beac-6aa7d5a74cbb","target_id":"0fcc0fe680a7ca8b8c7f4d579b77aeec","source_type":"WIKI_ITEM","target_type":"CODE_SNIPPET","relationship_type":"CONTAINS","extra":"Wiki contains code snippet: backend/app/main.py#12-78","gmt_create":"2026-05-23T15:17:24.188555+08:00","gmt_modified":"2026-05-23T15:17:24.188555+08:00"},{"id":1844,"source_id":"49915365-e38e-43b5-beac-6aa7d5a74cbb","target_id":"10d3948b1394ffa0110796edfa0bfc25","source_type":"WIKI_ITEM","target_type":"CODE_SNIPPET","relationship_type":"CONTAINS","extra":"Wiki contains code snippet: backend/app/api/auth.py#30","gmt_create":"2026-05-23T15:17:24.204464+08:00","gmt_modified":"2026-05-23T15:17:24.204464+08:00"},{"id":1845,"source_id":"49915365-e38e-43b5-beac-6aa7d5a74cbb","target_id":"0a5c3d0a239107364b77b52d4ff33454","source_type":"WIKI_ITEM","target_type":"CODE_SNIPPET","relationship_type":"CONTAINS","extra":"Wiki contains code snippet: backend/app/api/agents.py#29","gmt_create":"2026-05-23T15:17:24.20616+08:00","gmt_modified":"2026-05-23T15:17:24.20616+08:00"},{"id":1846,"source_id":"6a9387dd3885cf4d27bce3db87fd61c7","target_id":"0a5c3d0a239107364b77b52d4ff33454","source_type":"SOURCE_FILE","target_type":"CODE_SNIPPET","relationship_type":"CONTAINS","extra":"Source file contains code snippet: 29","gmt_create":"2026-05-23T15:17:24.206732+08:00","gmt_modified":"2026-05-23T15:17:24.206732+08:00"},{"id":1847,"source_id":"49915365-e38e-43b5-beac-6aa7d5a74cbb","target_id":"6c9ecb8d32dfd5ce9b2dc95f1a110d97","source_type":"WIKI_ITEM","target_type":"CODE_SNIPPET","relationship_type":"CONTAINS","extra":"Wiki contains code snippet: backend/app/api/analytics.py#26","gmt_create":"2026-05-23T15:17:24.207346+08:00","gmt_modified":"2026-05-23T15:17:24.207346+08:00"},{"id":1848,"source_id":"9af41884bf42d6e175163e89f663a479","target_id":"6c9ecb8d32dfd5ce9b2dc95f1a110d97","source_type":"SOURCE_FILE","target_type":"CODE_SNIPPET","relationship_type":"CONTAINS","extra":"Source file contains code snippet: 26","gmt_create":"2026-05-23T15:17:24.207877+08:00","gmt_modified":"2026-05-23T15:17:24.207877+08:00"},{"id":1849,"source_id":"49915365-e38e-43b5-beac-6aa7d5a74cbb","target_id":"6242be39e66058ce4f2dd93974e98599","source_type":"WIKI_ITEM","target_type":"CODE_SNIPPET","relationship_type":"CONTAINS","extra":"Wiki contains code snippet: backend/app/api/lifecycle.py#24","gmt_create":"2026-05-23T15:17:24.208801+08:00","gmt_modified":"2026-05-23T15:17:24.208801+08:00"},{"id":1850,"source_id":"9c224bb80474867f8ded674babaa6e11","target_id":"6242be39e66058ce4f2dd93974e98599","source_type":"SOURCE_FILE","target_type":"CODE_SNIPPET","relationship_type":"CONTAINS","extra":"Source file contains code snippet: 24","gmt_create":"2026-05-23T15:17:24.210225+08:00","gmt_modified":"2026-05-23T15:17:24.210225+08:00"},{"id":1851,"source_id":"49915365-e38e-43b5-beac-6aa7d5a74cbb","target_id":"3dde6ad029645735cef7c4edf22b28c3","source_type":"WIKI_ITEM","target_type":"CODE_SNIPPET","relationship_type":"CONTAINS","extra":"Wiki contains code snippet: backend/app/api/knowledge.py#38","gmt_create":"2026-05-23T15:17:24.213173+08:00","gmt_modified":"2026-05-23T15:17:24.213173+08:00"},{"id":1852,"source_id":"63953ee6b39f159a61963104ac06f283","target_id":"3dde6ad029645735cef7c4edf22b28c3","source_type":"SOURCE_FILE","target_type":"CODE_SNIPPET","relationship_type":"CONTAINS","extra":"Source file contains code snippet: 38","gmt_create":"2026-05-23T15:17:24.2143+08:00","gmt_modified":"2026-05-23T15:17:24.214301+08:00"},{"id":1853,"source_id":"49915365-e38e-43b5-beac-6aa7d5a74cbb","target_id":"f240c1067c223a019ba05b0fbd718aa4","source_type":"WIKI_ITEM","target_type":"CODE_SNIPPET","relationship_type":"CONTAINS","extra":"Wiki contains code snippet: backend/app/main.py#1-84","gmt_create":"2026-05-23T15:17:24.215324+08:00","gmt_modified":"2026-05-23T15:17:24.215324+08:00"},{"id":1854,"source_id":"49915365-e38e-43b5-beac-6aa7d5a74cbb","target_id":"d6ebce8c7d9e9de127486400670ebed0","source_type":"WIKI_ITEM","target_type":"CODE_SNIPPET","relationship_type":"CONTAINS","extra":"Wiki contains code snippet: backend/app/main.py#39-84","gmt_create":"2026-05-23T15:17:24.216598+08:00","gmt_modified":"2026-05-23T15:17:24.216598+08:00"},{"id":1855,"source_id":"49915365-e38e-43b5-beac-6aa7d5a74cbb","target_id":"35dd08df9c7a562d9c7b8edf740eaf3c","source_type":"WIKI_ITEM","target_type":"CODE_SNIPPET","relationship_type":"CONTAINS","extra":"Wiki contains code snippet: backend/app/api/auth.py#33-115","gmt_create":"2026-05-23T15:17:24.21734+08:00","gmt_modified":"2026-05-23T15:17:24.21734+08:00"},{"id":1856,"source_id":"49915365-e38e-43b5-beac-6aa7d5a74cbb","target_id":"c7cbd948815aa81602e95e7e469a2b80","source_type":"WIKI_ITEM","target_type":"CODE_SNIPPET","relationship_type":"CONTAINS","extra":"Wiki contains code snippet: backend/app/api/agents.py#66-299","gmt_create":"2026-05-23T15:17:24.218834+08:00","gmt_modified":"2026-05-23T15:17:24.218834+08:00"},{"id":1857,"source_id":"6a9387dd3885cf4d27bce3db87fd61c7","target_id":"c7cbd948815aa81602e95e7e469a2b80","source_type":"SOURCE_FILE","target_type":"CODE_SNIPPET","relationship_type":"CONTAINS","extra":"Source file contains code snippet: 66-299","gmt_create":"2026-05-23T15:17:24.219687+08:00","gmt_modified":"2026-05-23T15:17:24.219687+08:00"},{"id":1858,"source_id":"49915365-e38e-43b5-beac-6aa7d5a74cbb","target_id":"c666a867c1b927bcc12241a45e84cd71","source_type":"WIKI_ITEM","target_type":"CODE_SNIPPET","relationship_type":"CONTAINS","extra":"Wiki contains code snippet: backend/app/api/analytics.py#47-243","gmt_create":"2026-05-23T15:17:24.22048+08:00","gmt_modified":"2026-05-23T15:17:24.220481+08:00"},{"id":1859,"source_id":"9af41884bf42d6e175163e89f663a479","target_id":"c666a867c1b927bcc12241a45e84cd71","source_type":"SOURCE_FILE","target_type":"CODE_SNIPPET","relationship_type":"CONTAINS","extra":"Source file contains code snippet: 47-243","gmt_create":"2026-05-23T15:17:24.221074+08:00","gmt_modified":"2026-05-23T15:17:24.221074+08:00"},{"id":1860,"source_id":"49915365-e38e-43b5-beac-6aa7d5a74cbb","target_id":"196c325b93526e566ba9f2560a82c2ac","source_type":"WIKI_ITEM","target_type":"CODE_SNIPPET","relationship_type":"CONTAINS","extra":"Wiki contains code snippet: backend/app/api/lifecycle.py#85-297","gmt_create":"2026-05-23T15:17:24.222051+08:00","gmt_modified":"2026-05-23T15:17:24.222051+08:00"},{"id":1861,"source_id":"9c224bb80474867f8ded674babaa6e11","target_id":"196c325b93526e566ba9f2560a82c2ac","source_type":"SOURCE_FILE","target_type":"CODE_SNIPPET","relationship_type":"CONTAINS","extra":"Source file contains code snippet: 85-297","gmt_create":"2026-05-23T15:17:24.222588+08:00","gmt_modified":"2026-05-23T15:17:24.222589+08:00"},{"id":1862,"source_id":"49915365-e38e-43b5-beac-6aa7d5a74cbb","target_id":"f617a59447265c18ad5d4c79e9db8e12","source_type":"WIKI_ITEM","target_type":"CODE_SNIPPET","relationship_type":"CONTAINS","extra":"Wiki contains code snippet: backend/app/api/knowledge.py#81-502","gmt_create":"2026-05-23T15:17:24.223422+08:00","gmt_modified":"2026-05-23T15:17:24.223422+08:00"},{"id":1863,"source_id":"63953ee6b39f159a61963104ac06f283","target_id":"f617a59447265c18ad5d4c79e9db8e12","source_type":"SOURCE_FILE","target_type":"CODE_SNIPPET","relationship_type":"CONTAINS","extra":"Source file contains code snippet: 81-502","gmt_create":"2026-05-23T15:17:24.224138+08:00","gmt_modified":"2026-05-23T15:17:24.224139+08:00"},{"id":1864,"source_id":"49915365-e38e-43b5-beac-6aa7d5a74cbb","target_id":"712424bd3bd3d5f39b1a0a72acc9952a","source_type":"WIKI_ITEM","target_type":"CODE_SNIPPET","relationship_type":"CONTAINS","extra":"Wiki contains code snippet: backend/app/middleware/rate_limit.py#10-83","gmt_create":"2026-05-23T15:17:24.224761+08:00","gmt_modified":"2026-05-23T15:17:24.224761+08:00"},{"id":1865,"source_id":"49915365-e38e-43b5-beac-6aa7d5a74cbb","target_id":"2db9940a42c91fc92f23595491ea93d1","source_type":"WIKI_ITEM","target_type":"CODE_SNIPPET","relationship_type":"CONTAINS","extra":"Wiki contains code snippet: backend/app/main.py#67-78","gmt_create":"2026-05-23T15:17:24.225488+08:00","gmt_modified":"2026-05-23T15:17:24.225488+08:00"},{"id":1866,"source_id":"49915365-e38e-43b5-beac-6aa7d5a74cbb","target_id":"bcdf50f6234651cb9863ab210e6473e5","source_type":"WIKI_ITEM","target_type":"CODE_SNIPPET","relationship_type":"CONTAINS","extra":"Wiki contains code snippet: backend/app/api/deps.py#16-42","gmt_create":"2026-05-23T15:17:24.230136+08:00","gmt_modified":"2026-05-23T15:17:24.230136+08:00"},{"id":1867,"source_id":"49915365-e38e-43b5-beac-6aa7d5a74cbb","target_id":"6df0277c2486b148fa26c2682dbdaa4c","source_type":"WIKI_ITEM","target_type":"CODE_SNIPPET","relationship_type":"CONTAINS","extra":"Wiki contains code snippet: backend/app/services/auth.py#37-68","gmt_create":"2026-05-23T15:17:24.231867+08:00","gmt_modified":"2026-05-23T15:17:24.231867+08:00"},{"id":1868,"source_id":"49915365-e38e-43b5-beac-6aa7d5a74cbb","target_id":"5ea5f192d580031ffe57e1582b70c67e","source_type":"WIKI_ITEM","target_type":"CODE_SNIPPET","relationship_type":"CONTAINS","extra":"Wiki contains code snippet: backend/app/services/query.py#12-123","gmt_create":"2026-05-23T15:17:24.232789+08:00","gmt_modified":"2026-05-23T15:17:24.23279+08:00"},{"id":1869,"source_id":"49915365-e38e-43b5-beac-6aa7d5a74cbb","target_id":"fe4a793f16cd4e12b56253c0a6d53ae0","source_type":"WIKI_ITEM","target_type":"CODE_SNIPPET","relationship_type":"CONTAINS","extra":"Wiki contains code snippet: backend/app/services/citation.py#24-359","gmt_create":"2026-05-23T15:17:24.234569+08:00","gmt_modified":"2026-05-23T15:17:24.234569+08:00"},{"id":1870,"source_id":"49915365-e38e-43b5-beac-6aa7d5a74cbb","target_id":"68fbb2bd365f96a98ea187a9738c4460","source_type":"WIKI_ITEM","target_type":"CODE_SNIPPET","relationship_type":"CONTAINS","extra":"Wiki contains code snippet: backend/app/api/auth.py#33-57","gmt_create":"2026-05-23T15:17:24.235656+08:00","gmt_modified":"2026-05-23T15:17:24.235656+08:00"},{"id":1871,"source_id":"49915365-e38e-43b5-beac-6aa7d5a74cbb","target_id":"4aad38dfc00a0877bd965c3d0b3c280c","source_type":"WIKI_ITEM","target_type":"CODE_SNIPPET","relationship_type":"CONTAINS","extra":"Wiki contains code snippet: backend/app/schemas/auth.py#7-34","gmt_create":"2026-05-23T15:17:24.239144+08:00","gmt_modified":"2026-05-23T15:17:24.239144+08:00"},{"id":1872,"source_id":"49915365-e38e-43b5-beac-6aa7d5a74cbb","target_id":"9b10dac7dbbb1327afc8a525bf4bd0c3","source_type":"WIKI_ITEM","target_type":"CODE_SNIPPET","relationship_type":"CONTAINS","extra":"Wiki contains code snippet: backend/app/services/query.py#45-81","gmt_create":"2026-05-23T15:17:24.241451+08:00","gmt_modified":"2026-05-23T15:17:24.241451+08:00"},{"id":1873,"source_id":"49915365-e38e-43b5-beac-6aa7d5a74cbb","target_id":"ae9de874df4a46f4197b6c157c25ec6e","source_type":"WIKI_ITEM","target_type":"CODE_SNIPPET","relationship_type":"CONTAINS","extra":"Wiki contains code snippet: backend/app/api/queries.py#15-85","gmt_create":"2026-05-23T15:17:24.242206+08:00","gmt_modified":"2026-05-23T15:17:24.242206+08:00"},{"id":1874,"source_id":"49915365-e38e-43b5-beac-6aa7d5a74cbb","target_id":"69118807690ef351a9de910414d5e676","source_type":"WIKI_ITEM","target_type":"CODE_SNIPPET","relationship_type":"CONTAINS","extra":"Wiki contains code snippet: backend/app/schemas/query.py#11-94","gmt_create":"2026-05-23T15:17:24.247111+08:00","gmt_modified":"2026-05-23T15:17:24.247111+08:00"},{"id":1875,"source_id":"49915365-e38e-43b5-beac-6aa7d5a74cbb","target_id":"212d822d207a4c0bd7825bbf20e188e9","source_type":"WIKI_ITEM","target_type":"CODE_SNIPPET","relationship_type":"CONTAINS","extra":"Wiki contains code snippet: backend/app/api/citations.py#59-77","gmt_create":"2026-05-23T15:17:24.249091+08:00","gmt_modified":"2026-05-23T15:17:24.249092+08:00"},{"id":1876,"source_id":"49915365-e38e-43b5-beac-6aa7d5a74cbb","target_id":"b0777c7da17be89abb333c81c0dcf349","source_type":"WIKI_ITEM","target_type":"CODE_SNIPPET","relationship_type":"CONTAINS","extra":"Wiki contains code snippet: backend/app/services/citation.py#204-261","gmt_create":"2026-05-23T15:17:24.250307+08:00","gmt_modified":"2026-05-23T15:17:24.250307+08:00"},{"id":1877,"source_id":"49915365-e38e-43b5-beac-6aa7d5a74cbb","target_id":"c066a8d4bffabed87a2e38ccad81c107","source_type":"WIKI_ITEM","target_type":"CODE_SNIPPET","relationship_type":"CONTAINS","extra":"Wiki contains code snippet: backend/app/api/citations.py#25-77","gmt_create":"2026-05-23T15:17:24.251358+08:00","gmt_modified":"2026-05-23T15:17:24.251358+08:00"},{"id":1878,"source_id":"49915365-e38e-43b5-beac-6aa7d5a74cbb","target_id":"26288877e8e1f6c4ff5aca12610b0218","source_type":"WIKI_ITEM","target_type":"CODE_SNIPPET","relationship_type":"CONTAINS","extra":"Wiki contains code snippet: backend/app/schemas/citation.py#7-50","gmt_create":"2026-05-23T15:17:24.252188+08:00","gmt_modified":"2026-05-23T15:17:24.252188+08:00"},{"id":1879,"source_id":"49915365-e38e-43b5-beac-6aa7d5a74cbb","target_id":"44f9c9f195e096efbd6c6a6f97880944","source_type":"WIKI_ITEM","target_type":"CODE_SNIPPET","relationship_type":"CONTAINS","extra":"Wiki contains code snippet: backend/app/api/reports.py#51-75","gmt_create":"2026-05-23T15:17:24.253763+08:00","gmt_modified":"2026-05-23T15:17:24.253763+08:00"},{"id":1880,"source_id":"49915365-e38e-43b5-beac-6aa7d5a74cbb","target_id":"cbe8ffc1cfb98ac79c7659e968191837","source_type":"WIKI_ITEM","target_type":"CODE_SNIPPET","relationship_type":"CONTAINS","extra":"Wiki contains code snippet: backend/app/services/citation.py#343-466","gmt_create":"2026-05-23T15:17:24.255124+08:00","gmt_modified":"2026-05-23T15:17:24.255124+08:00"},{"id":1881,"source_id":"49915365-e38e-43b5-beac-6aa7d5a74cbb","target_id":"14c2d098319eeab16c64ff7d1447df6b","source_type":"WIKI_ITEM","target_type":"CODE_SNIPPET","relationship_type":"CONTAINS","extra":"Wiki contains code snippet: backend/app/api/reports.py#18-75","gmt_create":"2026-05-23T15:17:24.256276+08:00","gmt_modified":"2026-05-23T15:17:24.256276+08:00"},{"id":1882,"source_id":"49915365-e38e-43b5-beac-6aa7d5a74cbb","target_id":"97f9b6149bd43feb0f69cf2582ab6305","source_type":"WIKI_ITEM","target_type":"CODE_SNIPPET","relationship_type":"CONTAINS","extra":"Wiki contains code snippet: backend/app/services/subscription.py#85-117","gmt_create":"2026-05-23T15:17:24.25803+08:00","gmt_modified":"2026-05-23T15:17:24.25803+08:00"},{"id":1883,"source_id":"49915365-e38e-43b5-beac-6aa7d5a74cbb","target_id":"ec3ed02cad3cd8af4bacb5c978273092","source_type":"WIKI_ITEM","target_type":"CODE_SNIPPET","relationship_type":"CONTAINS","extra":"Wiki contains code snippet: backend/app/api/subscriptions.py#26-77","gmt_create":"2026-05-23T15:17:24.259391+08:00","gmt_modified":"2026-05-23T15:17:24.259391+08:00"},{"id":1884,"source_id":"49915365-e38e-43b5-beac-6aa7d5a74cbb","target_id":"ce4de96353f8f81ca825173ddbec1150","source_type":"WIKI_ITEM","target_type":"CODE_SNIPPET","relationship_type":"CONTAINS","extra":"Wiki contains code snippet: backend/app/schemas/subscription.py#12-41","gmt_create":"2026-05-23T15:17:24.262322+08:00","gmt_modified":"2026-05-23T15:17:24.262323+08:00"},{"id":1885,"source_id":"49915365-e38e-43b5-beac-6aa7d5a74cbb","target_id":"a87a1a7c1723518159d5818c197996cc","source_type":"WIKI_ITEM","target_type":"CODE_SNIPPET","relationship_type":"CONTAINS","extra":"Wiki contains code snippet: backend/app/services/subscription.py#56-155","gmt_create":"2026-05-23T15:17:24.263733+08:00","gmt_modified":"2026-05-23T15:17:24.263733+08:00"},{"id":1886,"source_id":"49915365-e38e-43b5-beac-6aa7d5a74cbb","target_id":"0e4bc0a539e0ccc6832031bdaf1eb1ca","source_type":"WIKI_ITEM","target_type":"CODE_SNIPPET","relationship_type":"CONTAINS","extra":"Wiki contains code snippet: backend/app/api/admin.py#29-45","gmt_create":"2026-05-23T15:17:24.265191+08:00","gmt_modified":"2026-05-23T15:17:24.265191+08:00"},{"id":1887,"source_id":"49915365-e38e-43b5-beac-6aa7d5a74cbb","target_id":"f7314a4515e822cba6f37d7a8f1970f3","source_type":"WIKI_ITEM","target_type":"CODE_SNIPPET","relationship_type":"CONTAINS","extra":"Wiki contains code snippet: backend/app/services/admin.py#14-46","gmt_create":"2026-05-23T15:17:24.266934+08:00","gmt_modified":"2026-05-23T15:17:24.266934+08:00"},{"id":1888,"source_id":"49915365-e38e-43b5-beac-6aa7d5a74cbb","target_id":"05664cbd35007caa5290760cc1ef1b99","source_type":"WIKI_ITEM","target_type":"CODE_SNIPPET","relationship_type":"CONTAINS","extra":"Wiki contains code snippet: backend/app/api/admin.py#29-108","gmt_create":"2026-05-23T15:17:24.268355+08:00","gmt_modified":"2026-05-23T15:17:24.268355+08:00"},{"id":1889,"source_id":"49915365-e38e-43b5-beac-6aa7d5a74cbb","target_id":"7f81ebbdde3496054e6f43f5eef366dc","source_type":"WIKI_ITEM","target_type":"CODE_SNIPPET","relationship_type":"CONTAINS","extra":"Wiki contains code snippet: backend/app/services/admin.py#14-188","gmt_create":"2026-05-23T15:17:24.269431+08:00","gmt_modified":"2026-05-23T15:17:24.269431+08:00"},{"id":1890,"source_id":"49915365-e38e-43b5-beac-6aa7d5a74cbb","target_id":"ffb5c89d546d3895e7ac0ed320a6ed90","source_type":"WIKI_ITEM","target_type":"CODE_SNIPPET","relationship_type":"CONTAINS","extra":"Wiki contains code snippet: backend/app/api/agents.py#186-222","gmt_create":"2026-05-23T15:17:24.270579+08:00","gmt_modified":"2026-05-23T15:17:24.270579+08:00"},{"id":1891,"source_id":"6a9387dd3885cf4d27bce3db87fd61c7","target_id":"ffb5c89d546d3895e7ac0ed320a6ed90","source_type":"SOURCE_FILE","target_type":"CODE_SNIPPET","relationship_type":"CONTAINS","extra":"Source file contains code snippet: 186-222","gmt_create":"2026-05-23T15:17:24.271154+08:00","gmt_modified":"2026-05-23T15:17:24.271154+08:00"},{"id":1892,"source_id":"49915365-e38e-43b5-beac-6aa7d5a74cbb","target_id":"e6fe884abc694714e2eb8bf1be27d72b","source_type":"WIKI_ITEM","target_type":"CODE_SNIPPET","relationship_type":"CONTAINS","extra":"Wiki contains code snippet: backend/app/models/agent.py#98-155","gmt_create":"2026-05-23T15:17:24.27219+08:00","gmt_modified":"2026-05-23T15:17:24.27219+08:00"},{"id":1893,"source_id":"aa6cf63a65ebf46a29606af91112eb7b","target_id":"e6fe884abc694714e2eb8bf1be27d72b","source_type":"SOURCE_FILE","target_type":"CODE_SNIPPET","relationship_type":"CONTAINS","extra":"Source file contains code snippet: 98-155","gmt_create":"2026-05-23T15:17:24.272858+08:00","gmt_modified":"2026-05-23T15:17:24.272859+08:00"},{"id":1894,"source_id":"49915365-e38e-43b5-beac-6aa7d5a74cbb","target_id":"ebc123c07512c5d5aeb1011d228a895c","source_type":"WIKI_ITEM","target_type":"CODE_SNIPPET","relationship_type":"CONTAINS","extra":"Wiki contains code snippet: backend/app/models/agent.py#12-206","gmt_create":"2026-05-23T15:17:24.274033+08:00","gmt_modified":"2026-05-23T15:17:24.274034+08:00"},{"id":1895,"source_id":"aa6cf63a65ebf46a29606af91112eb7b","target_id":"ebc123c07512c5d5aeb1011d228a895c","source_type":"SOURCE_FILE","target_type":"CODE_SNIPPET","relationship_type":"CONTAINS","extra":"Source file contains code snippet: 12-206","gmt_create":"2026-05-23T15:17:24.274595+08:00","gmt_modified":"2026-05-23T15:17:24.274595+08:00"},{"id":1896,"source_id":"49915365-e38e-43b5-beac-6aa7d5a74cbb","target_id":"9cbf60c1b6ff2f8c74be2f168f4f44eb","source_type":"WIKI_ITEM","target_type":"CODE_SNIPPET","relationship_type":"CONTAINS","extra":"Wiki contains code snippet: backend/app/api/analytics.py#47-60","gmt_create":"2026-05-23T15:17:24.275162+08:00","gmt_modified":"2026-05-23T15:17:24.275162+08:00"},{"id":1897,"source_id":"9af41884bf42d6e175163e89f663a479","target_id":"9cbf60c1b6ff2f8c74be2f168f4f44eb","source_type":"SOURCE_FILE","target_type":"CODE_SNIPPET","relationship_type":"CONTAINS","extra":"Source file contains code snippet: 47-60","gmt_create":"2026-05-23T15:17:24.275621+08:00","gmt_modified":"2026-05-23T15:17:24.275621+08:00"},{"id":1898,"source_id":"49915365-e38e-43b5-beac-6aa7d5a74cbb","target_id":"eb865aa7324cbb6c6ec83cf884c36b98","source_type":"WIKI_ITEM","target_type":"CODE_SNIPPET","relationship_type":"CONTAINS","extra":"Wiki contains code snippet: backend/app/api/analytics.py#206-212","gmt_create":"2026-05-23T15:17:24.277851+08:00","gmt_modified":"2026-05-23T15:17:24.277851+08:00"},{"id":1899,"source_id":"9af41884bf42d6e175163e89f663a479","target_id":"eb865aa7324cbb6c6ec83cf884c36b98","source_type":"SOURCE_FILE","target_type":"CODE_SNIPPET","relationship_type":"CONTAINS","extra":"Source file contains code snippet: 206-212","gmt_create":"2026-05-23T15:17:24.278515+08:00","gmt_modified":"2026-05-23T15:17:24.278515+08:00"},{"id":1900,"source_id":"49915365-e38e-43b5-beac-6aa7d5a74cbb","target_id":"68580333c31256edc20b45d90197222c","source_type":"WIKI_ITEM","target_type":"CODE_SNIPPET","relationship_type":"CONTAINS","extra":"Wiki contains code snippet: backend/app/schemas/analytics.py#14-145","gmt_create":"2026-05-23T15:17:24.280338+08:00","gmt_modified":"2026-05-23T15:17:24.280338+08:00"},{"id":1901,"source_id":"6940047dd4c29a8a219b1b50e358f7c1","target_id":"68580333c31256edc20b45d90197222c","source_type":"SOURCE_FILE","target_type":"CODE_SNIPPET","relationship_type":"CONTAINS","extra":"Source file contains code snippet: 14-145","gmt_create":"2026-05-23T15:17:24.280921+08:00","gmt_modified":"2026-05-23T15:17:24.280922+08:00"},{"id":1902,"source_id":"49915365-e38e-43b5-beac-6aa7d5a74cbb","target_id":"98d6d7fe81309b5f48907ff2c96bd9e9","source_type":"WIKI_ITEM","target_type":"CODE_SNIPPET","relationship_type":"CONTAINS","extra":"Wiki contains code snippet: backend/app/api/lifecycle.py#190-230","gmt_create":"2026-05-23T15:17:24.281728+08:00","gmt_modified":"2026-05-23T15:17:24.281728+08:00"},{"id":1903,"source_id":"9c224bb80474867f8ded674babaa6e11","target_id":"98d6d7fe81309b5f48907ff2c96bd9e9","source_type":"SOURCE_FILE","target_type":"CODE_SNIPPET","relationship_type":"CONTAINS","extra":"Source file contains code snippet: 190-230","gmt_create":"2026-05-23T15:17:24.282759+08:00","gmt_modified":"2026-05-23T15:17:24.282759+08:00"},{"id":1904,"source_id":"49915365-e38e-43b5-beac-6aa7d5a74cbb","target_id":"4d98c570e47fa5aa35c93cc23d9a9531","source_type":"WIKI_ITEM","target_type":"CODE_SNIPPET","relationship_type":"CONTAINS","extra":"Wiki contains code snippet: backend/app/schemas/lifecycle.py#9-68","gmt_create":"2026-05-23T15:17:24.284357+08:00","gmt_modified":"2026-05-23T15:17:24.284357+08:00"},{"id":1905,"source_id":"952c887faf6f91370b174bd4e1ad6e00","target_id":"4d98c570e47fa5aa35c93cc23d9a9531","source_type":"SOURCE_FILE","target_type":"CODE_SNIPPET","relationship_type":"CONTAINS","extra":"Source file contains code snippet: 9-68","gmt_create":"2026-05-23T15:17:24.284879+08:00","gmt_modified":"2026-05-23T15:17:24.284879+08:00"},{"id":1906,"source_id":"49915365-e38e-43b5-beac-6aa7d5a74cbb","target_id":"6a2a5a7cb69cc0e72c2e90e1d9e48037","source_type":"WIKI_ITEM","target_type":"CODE_SNIPPET","relationship_type":"CONTAINS","extra":"Wiki contains code snippet: backend/app/models/lifecycle.py#12-92","gmt_create":"2026-05-23T15:17:24.285676+08:00","gmt_modified":"2026-05-23T15:17:24.285676+08:00"},{"id":1907,"source_id":"97cfe961cb7386b4022a51706ae8f5dd","target_id":"6a2a5a7cb69cc0e72c2e90e1d9e48037","source_type":"SOURCE_FILE","target_type":"CODE_SNIPPET","relationship_type":"CONTAINS","extra":"Source file contains code snippet: 12-92","gmt_create":"2026-05-23T15:17:24.286407+08:00","gmt_modified":"2026-05-23T15:17:24.286408+08:00"},{"id":1908,"source_id":"49915365-e38e-43b5-beac-6aa7d5a74cbb","target_id":"f38b21f300a72d77625c203e8d9e5916","source_type":"WIKI_ITEM","target_type":"CODE_SNIPPET","relationship_type":"CONTAINS","extra":"Wiki contains code snippet: backend/app/api/knowledge.py#424-501","gmt_create":"2026-05-23T15:17:24.288543+08:00","gmt_modified":"2026-05-23T15:17:24.288543+08:00"},{"id":1909,"source_id":"63953ee6b39f159a61963104ac06f283","target_id":"f38b21f300a72d77625c203e8d9e5916","source_type":"SOURCE_FILE","target_type":"CODE_SNIPPET","relationship_type":"CONTAINS","extra":"Source file contains code snippet: 424-501","gmt_create":"2026-05-23T15:17:24.289121+08:00","gmt_modified":"2026-05-23T15:17:24.289121+08:00"},{"id":1910,"source_id":"49915365-e38e-43b5-beac-6aa7d5a74cbb","target_id":"02ee224326bf5a0307c63b44ccb270ac","source_type":"WIKI_ITEM","target_type":"CODE_SNIPPET","relationship_type":"CONTAINS","extra":"Wiki contains code snippet: backend/app/schemas/knowledge.py#9-77","gmt_create":"2026-05-23T15:17:24.290606+08:00","gmt_modified":"2026-05-23T15:17:24.290606+08:00"},{"id":1911,"source_id":"ed4505205a22ba55c7d4a83b0b24eaa4","target_id":"02ee224326bf5a0307c63b44ccb270ac","source_type":"SOURCE_FILE","target_type":"CODE_SNIPPET","relationship_type":"CONTAINS","extra":"Source file contains code snippet: 9-77","gmt_create":"2026-05-23T15:17:24.291254+08:00","gmt_modified":"2026-05-23T15:17:24.291254+08:00"},{"id":1912,"source_id":"49915365-e38e-43b5-beac-6aa7d5a74cbb","target_id":"f043b2767c713f94381e9f7154cd904a","source_type":"WIKI_ITEM","target_type":"CODE_SNIPPET","relationship_type":"CONTAINS","extra":"Wiki contains code snippet: backend/app/models/knowledge.py#22-213","gmt_create":"2026-05-23T15:17:24.292253+08:00","gmt_modified":"2026-05-23T15:17:24.292253+08:00"},{"id":1913,"source_id":"4774aadaa8ace576601bdaa8d3e11f74","target_id":"f043b2767c713f94381e9f7154cd904a","source_type":"SOURCE_FILE","target_type":"CODE_SNIPPET","relationship_type":"CONTAINS","extra":"Source file contains code snippet: 22-213","gmt_create":"2026-05-23T15:17:24.292799+08:00","gmt_modified":"2026-05-23T15:17:24.292799+08:00"},{"id":1914,"source_id":"49915365-e38e-43b5-beac-6aa7d5a74cbb","target_id":"ef31f4aa4fbd1b6ff76eba467b757a04","source_type":"WIKI_ITEM","target_type":"CODE_SNIPPET","relationship_type":"CONTAINS","extra":"Wiki contains code snippet: backend/app/middleware/rate_limit.py#34-69","gmt_create":"2026-05-23T15:17:24.295615+08:00","gmt_modified":"2026-05-23T15:17:24.295616+08:00"},{"id":1915,"source_id":"49915365-e38e-43b5-beac-6aa7d5a74cbb","target_id":"f5978358d04c3c917d9ca5044c7f36fa","source_type":"WIKI_ITEM","target_type":"CODE_SNIPPET","relationship_type":"CONTAINS","extra":"Wiki contains code snippet: backend/app/models/user.py#11-48","gmt_create":"2026-05-23T15:17:24.297824+08:00","gmt_modified":"2026-05-23T15:17:24.297824+08:00"},{"id":1916,"source_id":"49915365-e38e-43b5-beac-6aa7d5a74cbb","target_id":"4fb8856be3a581fe8303d11b2284ca29","source_type":"WIKI_ITEM","target_type":"CODE_SNIPPET","relationship_type":"CONTAINS","extra":"Wiki contains code snippet: backend/app/models/query.py#11-55","gmt_create":"2026-05-23T15:17:24.299265+08:00","gmt_modified":"2026-05-23T15:17:24.299265+08:00"},{"id":1917,"source_id":"49915365-e38e-43b5-beac-6aa7d5a74cbb","target_id":"fd541971cebf8a7c167d717f5c5d1ff6","source_type":"WIKI_ITEM","target_type":"CODE_SNIPPET","relationship_type":"CONTAINS","extra":"Wiki contains code snippet: backend/app/models/citation_record.py#11-42","gmt_create":"2026-05-23T15:17:24.300537+08:00","gmt_modified":"2026-05-23T15:17:24.300537+08:00"},{"id":1918,"source_id":"49915365-e38e-43b5-beac-6aa7d5a74cbb","target_id":"b84f46f058847733347974841f613688","source_type":"WIKI_ITEM","target_type":"CODE_SNIPPET","relationship_type":"CONTAINS","extra":"Wiki contains code snippet: backend/app/models/query_task.py#11-39","gmt_create":"2026-05-23T15:17:24.301612+08:00","gmt_modified":"2026-05-23T15:17:24.301612+08:00"},{"id":1919,"source_id":"49915365-e38e-43b5-beac-6aa7d5a74cbb","target_id":"4d323bf0aaf4078f09726dc0890e5955","source_type":"WIKI_ITEM","target_type":"CODE_SNIPPET","relationship_type":"CONTAINS","extra":"Wiki contains code snippet: backend/app/models/subscription.py#11-37","gmt_create":"2026-05-23T15:17:24.3024+08:00","gmt_modified":"2026-05-23T15:17:24.3024+08:00"},{"id":1920,"source_id":"49915365-e38e-43b5-beac-6aa7d5a74cbb","target_id":"1a2657244414b5681afded9565a86422","source_type":"WIKI_ITEM","target_type":"CODE_SNIPPET","relationship_type":"CONTAINS","extra":"Wiki contains code snippet: backend/app/models/user.py#35-40","gmt_create":"2026-05-23T15:17:24.305671+08:00","gmt_modified":"2026-05-23T15:17:24.305671+08:00"},{"id":1921,"source_id":"49915365-e38e-43b5-beac-6aa7d5a74cbb","target_id":"acd5a29be2bdd4ae251e10ca266ffe13","source_type":"WIKI_ITEM","target_type":"CODE_SNIPPET","relationship_type":"CONTAINS","extra":"Wiki contains code snippet: backend/app/models/query.py#43-48","gmt_create":"2026-05-23T15:17:24.306445+08:00","gmt_modified":"2026-05-23T15:17:24.306446+08:00"},{"id":1922,"source_id":"49915365-e38e-43b5-beac-6aa7d5a74cbb","target_id":"27a5e2dd1d197b2e3a45be41c57a6183","source_type":"WIKI_ITEM","target_type":"CODE_SNIPPET","relationship_type":"CONTAINS","extra":"Wiki contains code snippet: backend/app/models/citation_record.py#35","gmt_create":"2026-05-23T15:17:24.30719+08:00","gmt_modified":"2026-05-23T15:17:24.307191+08:00"},{"id":1923,"source_id":"49915365-e38e-43b5-beac-6aa7d5a74cbb","target_id":"c43e8fc0c04c5ed2db7798d99c8c77b8","source_type":"WIKI_ITEM","target_type":"CODE_SNIPPET","relationship_type":"CONTAINS","extra":"Wiki contains code snippet: backend/app/models/query_task.py#34","gmt_create":"2026-05-23T15:17:24.308001+08:00","gmt_modified":"2026-05-23T15:17:24.308002+08:00"},{"id":1924,"source_id":"49915365-e38e-43b5-beac-6aa7d5a74cbb","target_id":"3a7201f4564dbcf35c5771f1b5d58cb6","source_type":"WIKI_ITEM","target_type":"CODE_SNIPPET","relationship_type":"CONTAINS","extra":"Wiki contains code snippet: backend/app/api/auth.py#46-50","gmt_create":"2026-05-23T15:17:24.308792+08:00","gmt_modified":"2026-05-23T15:17:24.308792+08:00"},{"id":1925,"source_id":"49915365-e38e-43b5-beac-6aa7d5a74cbb","target_id":"a50f983ec39bac67dff5df80f6dad837","source_type":"WIKI_ITEM","target_type":"CODE_SNIPPET","relationship_type":"CONTAINS","extra":"Wiki contains code snippet: backend/app/services/query.py#59-60","gmt_create":"2026-05-23T15:17:24.312167+08:00","gmt_modified":"2026-05-23T15:17:24.312167+08:00"},{"id":1926,"source_id":"49915365-e38e-43b5-beac-6aa7d5a74cbb","target_id":"55f1628f1ab6f323710e367e12146b1a","source_type":"WIKI_ITEM","target_type":"CODE_SNIPPET","relationship_type":"CONTAINS","extra":"Wiki contains code snippet: backend/app/api/citations.py#67-71","gmt_create":"2026-05-23T15:17:24.313833+08:00","gmt_modified":"2026-05-23T15:17:24.313833+08:00"},{"id":1927,"source_id":"49915365-e38e-43b5-beac-6aa7d5a74cbb","target_id":"39c3dbe67ab2ae74446fe6a118bd8738","source_type":"WIKI_ITEM","target_type":"CODE_SNIPPET","relationship_type":"CONTAINS","extra":"Wiki contains code snippet: backend/app/api/reports.py#25-29","gmt_create":"2026-05-23T15:17:24.315656+08:00","gmt_modified":"2026-05-23T15:17:24.315656+08:00"},{"id":1928,"source_id":"49915365-e38e-43b5-beac-6aa7d5a74cbb","target_id":"68d937267aab2509edc0c7b67e1b5ef6","source_type":"WIKI_ITEM","target_type":"CODE_SNIPPET","relationship_type":"CONTAINS","extra":"Wiki contains code snippet: backend/app/api/subscriptions.py#53-57","gmt_create":"2026-05-23T15:17:24.316691+08:00","gmt_modified":"2026-05-23T15:17:24.316691+08:00"},{"id":1929,"source_id":"49915365-e38e-43b5-beac-6aa7d5a74cbb","target_id":"3d0bf5a05f6a7d2b8b12bb91e8f93642","source_type":"WIKI_ITEM","target_type":"CODE_SNIPPET","relationship_type":"CONTAINS","extra":"Wiki contains code snippet: backend/app/api/admin.py#22-25","gmt_create":"2026-05-23T15:17:24.317568+08:00","gmt_modified":"2026-05-23T15:17:24.317568+08:00"},{"id":1930,"source_id":"49915365-e38e-43b5-beac-6aa7d5a74cbb","target_id":"934240d46ff47296dae2c8aef650b86f","source_type":"WIKI_ITEM","target_type":"CODE_SNIPPET","relationship_type":"CONTAINS","extra":"Wiki contains code snippet: backend/app/api/agents.py#84-88","gmt_create":"2026-05-23T15:17:24.318329+08:00","gmt_modified":"2026-05-23T15:17:24.31833+08:00"},{"id":1931,"source_id":"6a9387dd3885cf4d27bce3db87fd61c7","target_id":"934240d46ff47296dae2c8aef650b86f","source_type":"SOURCE_FILE","target_type":"CODE_SNIPPET","relationship_type":"CONTAINS","extra":"Source file contains code snippet: 84-88","gmt_create":"2026-05-23T15:17:24.320157+08:00","gmt_modified":"2026-05-23T15:17:24.320157+08:00"},{"id":1932,"source_id":"49915365-e38e-43b5-beac-6aa7d5a74cbb","target_id":"be2989f88e1e49d5282ec7353c9c4e89","source_type":"WIKI_ITEM","target_type":"CODE_SNIPPET","relationship_type":"CONTAINS","extra":"Wiki contains code snippet: backend/app/api/analytics.py#36-40","gmt_create":"2026-05-23T15:17:24.321292+08:00","gmt_modified":"2026-05-23T15:17:24.321292+08:00"},{"id":1933,"source_id":"9af41884bf42d6e175163e89f663a479","target_id":"be2989f88e1e49d5282ec7353c9c4e89","source_type":"SOURCE_FILE","target_type":"CODE_SNIPPET","relationship_type":"CONTAINS","extra":"Source file contains code snippet: 36-40","gmt_create":"2026-05-23T15:17:24.322188+08:00","gmt_modified":"2026-05-23T15:17:24.322188+08:00"},{"id":1934,"source_id":"49915365-e38e-43b5-beac-6aa7d5a74cbb","target_id":"3b33430ff6a3ac8b10af49dc35af8231","source_type":"WIKI_ITEM","target_type":"CODE_SNIPPET","relationship_type":"CONTAINS","extra":"Wiki contains code snippet: backend/app/api/lifecycle.py#146","gmt_create":"2026-05-23T15:17:24.323054+08:00","gmt_modified":"2026-05-23T15:17:24.323054+08:00"},{"id":1935,"source_id":"9c224bb80474867f8ded674babaa6e11","target_id":"3b33430ff6a3ac8b10af49dc35af8231","source_type":"SOURCE_FILE","target_type":"CODE_SNIPPET","relationship_type":"CONTAINS","extra":"Source file contains code snippet: 146","gmt_create":"2026-05-23T15:17:24.323656+08:00","gmt_modified":"2026-05-23T15:17:24.323656+08:00"},{"id":1936,"source_id":"49915365-e38e-43b5-beac-6aa7d5a74cbb","target_id":"59b4deade567af54c91f1a162e57b5be","source_type":"WIKI_ITEM","target_type":"CODE_SNIPPET","relationship_type":"CONTAINS","extra":"Wiki contains code snippet: backend/app/api/knowledge.py#92-96","gmt_create":"2026-05-23T15:17:24.324417+08:00","gmt_modified":"2026-05-23T15:17:24.324417+08:00"},{"id":1937,"source_id":"63953ee6b39f159a61963104ac06f283","target_id":"59b4deade567af54c91f1a162e57b5be","source_type":"SOURCE_FILE","target_type":"CODE_SNIPPET","relationship_type":"CONTAINS","extra":"Source file contains code snippet: 92-96","gmt_create":"2026-05-23T15:17:24.324896+08:00","gmt_modified":"2026-05-23T15:17:24.324896+08:00"},{"id":1938,"source_id":"49915365-e38e-43b5-beac-6aa7d5a74cbb","target_id":"a9c1b0716ae36af22fce6148c2e40ce5","source_type":"WIKI_ITEM","target_type":"CODE_SNIPPET","relationship_type":"CONTAINS","extra":"Wiki contains code snippet: backend/app/middleware/rate_limit.py#47-49","gmt_create":"2026-05-23T15:17:24.327641+08:00","gmt_modified":"2026-05-23T15:17:24.327641+08:00"},{"id":1939,"source_id":"643984fc-5a57-498b-8f25-68cc318d9d82","target_id":"a26ee01cf41da3b956e1650448c156fa","source_type":"WIKI_ITEM","target_type":"SOURCE_FILE","relationship_type":"REFERENCED_BY","extra":"Wiki references source file: backend/requirements.txt","gmt_create":"2026-05-23T15:18:41.125269+08:00","gmt_modified":"2026-05-23T15:18:41.12527+08:00"},{"id":1940,"source_id":"643984fc-5a57-498b-8f25-68cc318d9d82","target_id":"aaf5bce6be82d2f947bfa5c1806de452","source_type":"WIKI_ITEM","target_type":"SOURCE_FILE","relationship_type":"REFERENCED_BY","extra":"Wiki references source file: frontend/package.json","gmt_create":"2026-05-23T15:18:41.126121+08:00","gmt_modified":"2026-05-23T15:18:41.126122+08:00"},{"id":1941,"source_id":"643984fc-5a57-498b-8f25-68cc318d9d82","target_id":"9228ff67d4c757a85d9421b71f4b29f5","source_type":"WIKI_ITEM","target_type":"SOURCE_FILE","relationship_type":"REFERENCED_BY","extra":"Wiki references source file: backend/app/main.py","gmt_create":"2026-05-23T15:18:41.126809+08:00","gmt_modified":"2026-05-23T15:18:41.126809+08:00"},{"id":1942,"source_id":"643984fc-5a57-498b-8f25-68cc318d9d82","target_id":"e9b52adbec3c07cf021e488dd3f99ab4","source_type":"WIKI_ITEM","target_type":"SOURCE_FILE","relationship_type":"REFERENCED_BY","extra":"Wiki references source file: backend/Dockerfile","gmt_create":"2026-05-23T15:18:41.128865+08:00","gmt_modified":"2026-05-23T15:18:41.128866+08:00"},{"id":1943,"source_id":"643984fc-5a57-498b-8f25-68cc318d9d82","target_id":"5e414f2ef9b69e55e00ab15f85b9291a","source_type":"WIKI_ITEM","target_type":"SOURCE_FILE","relationship_type":"REFERENCED_BY","extra":"Wiki references source file: frontend/Dockerfile","gmt_create":"2026-05-23T15:18:41.13011+08:00","gmt_modified":"2026-05-23T15:18:41.13011+08:00"},{"id":1944,"source_id":"643984fc-5a57-498b-8f25-68cc318d9d82","target_id":"fc6242433ae9506bcc0bf4cb0dce1413","source_type":"WIKI_ITEM","target_type":"SOURCE_FILE","relationship_type":"REFERENCED_BY","extra":"Wiki references source file: docker-compose.yml","gmt_create":"2026-05-23T15:18:41.131281+08:00","gmt_modified":"2026-05-23T15:18:41.131281+08:00"},{"id":1945,"source_id":"643984fc-5a57-498b-8f25-68cc318d9d82","target_id":"50f2e6bdc4a79e69bd43ea8d6fec67fe","source_type":"WIKI_ITEM","target_type":"SOURCE_FILE","relationship_type":"REFERENCED_BY","extra":"Wiki references source file: backend/alembic.ini","gmt_create":"2026-05-23T15:18:41.132282+08:00","gmt_modified":"2026-05-23T15:18:41.132282+08:00"},{"id":1946,"source_id":"643984fc-5a57-498b-8f25-68cc318d9d82","target_id":"9ff19022ef915615911280e3c49ed44b","source_type":"WIKI_ITEM","target_type":"SOURCE_FILE","relationship_type":"REFERENCED_BY","extra":"Wiki references source file: backend/app/config.py","gmt_create":"2026-05-23T15:18:41.133446+08:00","gmt_modified":"2026-05-23T15:18:41.133447+08:00"},{"id":1947,"source_id":"643984fc-5a57-498b-8f25-68cc318d9d82","target_id":"fb8af100a06778e1fbdac4790a3ed0a9","source_type":"WIKI_ITEM","target_type":"SOURCE_FILE","relationship_type":"REFERENCED_BY","extra":"Wiki references source file: frontend/tsconfig.json","gmt_create":"2026-05-23T15:18:41.134065+08:00","gmt_modified":"2026-05-23T15:18:41.134066+08:00"},{"id":1948,"source_id":"643984fc-5a57-498b-8f25-68cc318d9d82","target_id":"01056dad8851d3e9bd532eb4cab33792","source_type":"WIKI_ITEM","target_type":"SOURCE_FILE","relationship_type":"REFERENCED_BY","extra":"Wiki references source file: frontend/tailwind.config.ts","gmt_create":"2026-05-23T15:18:41.134649+08:00","gmt_modified":"2026-05-23T15:18:41.134649+08:00"},{"id":1949,"source_id":"643984fc-5a57-498b-8f25-68cc318d9d82","target_id":"4d9b59c294a0aac5e300b3de715eb226","source_type":"WIKI_ITEM","target_type":"SOURCE_FILE","relationship_type":"REFERENCED_BY","extra":"Wiki references source file: frontend/.eslintrc.json","gmt_create":"2026-05-23T15:18:41.135265+08:00","gmt_modified":"2026-05-23T15:18:41.135265+08:00"},{"id":1950,"source_id":"643984fc-5a57-498b-8f25-68cc318d9d82","target_id":"0ef1efea889dba3e1f299626df479571","source_type":"WIKI_ITEM","target_type":"SOURCE_FILE","relationship_type":"REFERENCED_BY","extra":"Wiki references source file: tests/conftest.py","gmt_create":"2026-05-23T15:18:41.136046+08:00","gmt_modified":"2026-05-23T15:18:41.136046+08:00"},{"id":1951,"source_id":"643984fc-5a57-498b-8f25-68cc318d9d82","target_id":"93022c8938ce318f167277cfa65c29a7","source_type":"WIKI_ITEM","target_type":"SOURCE_FILE","relationship_type":"REFERENCED_BY","extra":"Wiki references source file: backend/app/api/auth.py","gmt_create":"2026-05-23T15:18:41.136696+08:00","gmt_modified":"2026-05-23T15:18:41.136697+08:00"},{"id":1952,"source_id":"643984fc-5a57-498b-8f25-68cc318d9d82","target_id":"e0c0ca66b8b81cf66e078a7ab162c07f","source_type":"WIKI_ITEM","target_type":"SOURCE_FILE","relationship_type":"REFERENCED_BY","extra":"Wiki references source file: backend/app/schemas/auth.py","gmt_create":"2026-05-23T15:18:41.137419+08:00","gmt_modified":"2026-05-23T15:18:41.13742+08:00"},{"id":1953,"source_id":"643984fc-5a57-498b-8f25-68cc318d9d82","target_id":"c59f8c276697a070dffc581fe94d809c","source_type":"WIKI_ITEM","target_type":"SOURCE_FILE","relationship_type":"REFERENCED_BY","extra":"Wiki references source file: backend/app/models/user.py","gmt_create":"2026-05-23T15:18:41.138044+08:00","gmt_modified":"2026-05-23T15:18:41.138044+08:00"},{"id":1954,"source_id":"643984fc-5a57-498b-8f25-68cc318d9d82","target_id":"48a560c49d2b21da327c036ec2934b96","source_type":"WIKI_ITEM","target_type":"SOURCE_FILE","relationship_type":"REFERENCED_BY","extra":"Wiki references source file: README.md","gmt_create":"2026-05-23T15:18:41.138715+08:00","gmt_modified":"2026-05-23T15:18:41.138715+08:00"},{"id":1955,"source_id":"643984fc-5a57-498b-8f25-68cc318d9d82","target_id":"3a1e34b542590c287768482d964dc7d5","source_type":"WIKI_ITEM","target_type":"SOURCE_FILE","relationship_type":"REFERENCED_BY","extra":"Wiki references source file: docs/03-development/coding-standards.md","gmt_create":"2026-05-23T15:18:41.139302+08:00","gmt_modified":"2026-05-23T15:18:41.139302+08:00"},{"id":1956,"source_id":"643984fc-5a57-498b-8f25-68cc318d9d82","target_id":"53d01851ef76ade6cb41a3cbe140676f","source_type":"WIKI_ITEM","target_type":"SOURCE_FILE","relationship_type":"REFERENCED_BY","extra":"Wiki references source file: docs/03-development/dev-guide.md","gmt_create":"2026-05-23T15:18:41.139886+08:00","gmt_modified":"2026-05-23T15:18:41.139887+08:00"},{"id":1957,"source_id":"643984fc-5a57-498b-8f25-68cc318d9d82","target_id":"21e6700955fa049df458cee6020cf073","source_type":"WIKI_ITEM","target_type":"SOURCE_FILE","relationship_type":"REFERENCED_BY","extra":"Wiki references source file: docs/05-deployment/deployment-guide.md","gmt_create":"2026-05-23T15:18:41.140569+08:00","gmt_modified":"2026-05-23T15:18:41.140569+08:00"},{"id":1958,"source_id":"643984fc-5a57-498b-8f25-68cc318d9d82","target_id":"b0db309ae449a2a435fc77103ca76955","source_type":"WIKI_ITEM","target_type":"SOURCE_FILE","relationship_type":"REFERENCED_BY","extra":"Wiki references source file: docs/04-testing/test-strategy.md","gmt_create":"2026-05-23T15:18:41.14129+08:00","gmt_modified":"2026-05-23T15:18:41.141291+08:00"},{"id":1959,"source_id":"643984fc-5a57-498b-8f25-68cc318d9d82","target_id":"974abe01413cc7a8a4898621e0b0779e","source_type":"WIKI_ITEM","target_type":"SOURCE_FILE","relationship_type":"REFERENCED_BY","extra":"Wiki references source file: docs/03-development/tdd-workflow.md","gmt_create":"2026-05-23T15:18:41.141882+08:00","gmt_modified":"2026-05-23T15:18:41.141883+08:00"},{"id":1960,"source_id":"643984fc-5a57-498b-8f25-68cc318d9d82","target_id":"01a3a8e0d02ddfa2e64837790ba231fa","source_type":"WIKI_ITEM","target_type":"SOURCE_FILE","relationship_type":"REFERENCED_BY","extra":"Wiki references source file: docs/00-project/tech-stack.md","gmt_create":"2026-05-23T15:18:41.142482+08:00","gmt_modified":"2026-05-23T15:18:41.142482+08:00"},{"id":1961,"source_id":"643984fc-5a57-498b-8f25-68cc318d9d82","target_id":"48d22eaee09e364a293ad6c4750f5c5a","source_type":"WIKI_ITEM","target_type":"CODE_SNIPPET","relationship_type":"CONTAINS","extra":"Wiki contains code snippet: docker-compose.yml#1-71","gmt_create":"2026-05-23T15:18:41.14327+08:00","gmt_modified":"2026-05-23T15:18:41.14327+08:00"},{"id":1962,"source_id":"643984fc-5a57-498b-8f25-68cc318d9d82","target_id":"01a0c4b40819965823b56e9da858c024","source_type":"WIKI_ITEM","target_type":"CODE_SNIPPET","relationship_type":"CONTAINS","extra":"Wiki contains code snippet: frontend/Dockerfile#1-15","gmt_create":"2026-05-23T15:18:41.14466+08:00","gmt_modified":"2026-05-23T15:18:41.144661+08:00"},{"id":1963,"source_id":"643984fc-5a57-498b-8f25-68cc318d9d82","target_id":"412695e5de2014514a8f62f98c573656","source_type":"WIKI_ITEM","target_type":"CODE_SNIPPET","relationship_type":"CONTAINS","extra":"Wiki contains code snippet: backend/Dockerfile#1-41","gmt_create":"2026-05-23T15:18:41.146114+08:00","gmt_modified":"2026-05-23T15:18:41.146114+08:00"},{"id":1964,"source_id":"643984fc-5a57-498b-8f25-68cc318d9d82","target_id":"6171fd1748ad5189394ba670000e7e75","source_type":"WIKI_ITEM","target_type":"CODE_SNIPPET","relationship_type":"CONTAINS","extra":"Wiki contains code snippet: frontend/package.json#1-45","gmt_create":"2026-05-23T15:18:41.147542+08:00","gmt_modified":"2026-05-23T15:18:41.147543+08:00"},{"id":1965,"source_id":"aaf5bce6be82d2f947bfa5c1806de452","target_id":"6171fd1748ad5189394ba670000e7e75","source_type":"SOURCE_FILE","target_type":"CODE_SNIPPET","relationship_type":"CONTAINS","extra":"Source file contains code snippet: 1-45","gmt_create":"2026-05-23T15:18:41.148436+08:00","gmt_modified":"2026-05-23T15:18:41.148436+08:00"},{"id":1966,"source_id":"643984fc-5a57-498b-8f25-68cc318d9d82","target_id":"00502fc9ffc15147665f96f056735d74","source_type":"WIKI_ITEM","target_type":"CODE_SNIPPET","relationship_type":"CONTAINS","extra":"Wiki contains code snippet: backend/requirements.txt#1-42","gmt_create":"2026-05-23T15:18:41.150097+08:00","gmt_modified":"2026-05-23T15:18:41.150097+08:00"},{"id":1967,"source_id":"a26ee01cf41da3b956e1650448c156fa","target_id":"00502fc9ffc15147665f96f056735d74","source_type":"SOURCE_FILE","target_type":"CODE_SNIPPET","relationship_type":"CONTAINS","extra":"Source file contains code snippet: 1-42","gmt_create":"2026-05-23T15:18:41.150919+08:00","gmt_modified":"2026-05-23T15:18:41.150919+08:00"},{"id":1968,"source_id":"643984fc-5a57-498b-8f25-68cc318d9d82","target_id":"c2747ca16b879bca0f68955534c3c4fc","source_type":"WIKI_ITEM","target_type":"CODE_SNIPPET","relationship_type":"CONTAINS","extra":"Wiki contains code snippet: backend/app/main.py#1-48","gmt_create":"2026-05-23T15:18:41.15193+08:00","gmt_modified":"2026-05-23T15:18:41.15193+08:00"},{"id":1969,"source_id":"643984fc-5a57-498b-8f25-68cc318d9d82","target_id":"dd36901ce62b8cc1d66667dcdc45e637","source_type":"WIKI_ITEM","target_type":"CODE_SNIPPET","relationship_type":"CONTAINS","extra":"Wiki contains code snippet: backend/app/config.py#1-46","gmt_create":"2026-05-23T15:18:41.15309+08:00","gmt_modified":"2026-05-23T15:18:41.15309+08:00"},{"id":1970,"source_id":"9ff19022ef915615911280e3c49ed44b","target_id":"dd36901ce62b8cc1d66667dcdc45e637","source_type":"SOURCE_FILE","target_type":"CODE_SNIPPET","relationship_type":"CONTAINS","extra":"Source file contains code snippet: 1-46","gmt_create":"2026-05-23T15:18:41.153678+08:00","gmt_modified":"2026-05-23T15:18:41.153678+08:00"},{"id":1971,"source_id":"643984fc-5a57-498b-8f25-68cc318d9d82","target_id":"13f6ca76349ef86ae756bb519f122bc5","source_type":"WIKI_ITEM","target_type":"CODE_SNIPPET","relationship_type":"CONTAINS","extra":"Wiki contains code snippet: backend/alembic.ini#1-150","gmt_create":"2026-05-23T15:18:41.15511+08:00","gmt_modified":"2026-05-23T15:18:41.15511+08:00"},{"id":1972,"source_id":"643984fc-5a57-498b-8f25-68cc318d9d82","target_id":"74abd6612105c29b67178fa9dbd04b61","source_type":"WIKI_ITEM","target_type":"CODE_SNIPPET","relationship_type":"CONTAINS","extra":"Wiki contains code snippet: frontend/tsconfig.json#1-27","gmt_create":"2026-05-23T15:18:41.165191+08:00","gmt_modified":"2026-05-23T15:18:41.165191+08:00"},{"id":1973,"source_id":"643984fc-5a57-498b-8f25-68cc318d9d82","target_id":"36ca3ba8293eaed314a7628b0272e957","source_type":"WIKI_ITEM","target_type":"CODE_SNIPPET","relationship_type":"CONTAINS","extra":"Wiki contains code snippet: frontend/.eslintrc.json#1-14","gmt_create":"2026-05-23T15:18:41.167086+08:00","gmt_modified":"2026-05-23T15:18:41.167086+08:00"},{"id":1974,"source_id":"4d9b59c294a0aac5e300b3de715eb226","target_id":"36ca3ba8293eaed314a7628b0272e957","source_type":"SOURCE_FILE","target_type":"CODE_SNIPPET","relationship_type":"CONTAINS","extra":"Source file contains code snippet: 1-14","gmt_create":"2026-05-23T15:18:41.167599+08:00","gmt_modified":"2026-05-23T15:18:41.167599+08:00"},{"id":1975,"source_id":"643984fc-5a57-498b-8f25-68cc318d9d82","target_id":"89d70e5f89be23a229e3ee59982b8e6e","source_type":"WIKI_ITEM","target_type":"CODE_SNIPPET","relationship_type":"CONTAINS","extra":"Wiki contains code snippet: frontend/tailwind.config.ts#1-57","gmt_create":"2026-05-23T15:18:41.168439+08:00","gmt_modified":"2026-05-23T15:18:41.168439+08:00"},{"id":1976,"source_id":"643984fc-5a57-498b-8f25-68cc318d9d82","target_id":"9482f4f6279a4f636b77e69b8273b996","source_type":"WIKI_ITEM","target_type":"CODE_SNIPPET","relationship_type":"CONTAINS","extra":"Wiki contains code snippet: backend/alembic.ini#86-114","gmt_create":"2026-05-23T15:18:41.169649+08:00","gmt_modified":"2026-05-23T15:18:41.169649+08:00"},{"id":1977,"source_id":"643984fc-5a57-498b-8f25-68cc318d9d82","target_id":"397b266f19a1addebdf6c32db71ae77f","source_type":"WIKI_ITEM","target_type":"CODE_SNIPPET","relationship_type":"CONTAINS","extra":"Wiki contains code snippet: tests/conftest.py#1-71","gmt_create":"2026-05-23T15:18:41.170634+08:00","gmt_modified":"2026-05-23T15:18:41.170635+08:00"},{"id":1978,"source_id":"643984fc-5a57-498b-8f25-68cc318d9d82","target_id":"b55a164add5a8fec2ef0e489f7234829","source_type":"WIKI_ITEM","target_type":"CODE_SNIPPET","relationship_type":"CONTAINS","extra":"Wiki contains code snippet: backend/app/main.py#24-47","gmt_create":"2026-05-23T15:18:41.171613+08:00","gmt_modified":"2026-05-23T15:18:41.171613+08:00"},{"id":1979,"source_id":"643984fc-5a57-498b-8f25-68cc318d9d82","target_id":"03b024618527c930185a98873f353b45","source_type":"WIKI_ITEM","target_type":"CODE_SNIPPET","relationship_type":"CONTAINS","extra":"Wiki contains code snippet: backend/app/config.py#12-18","gmt_create":"2026-05-23T15:18:41.17271+08:00","gmt_modified":"2026-05-23T15:18:41.172711+08:00"},{"id":1980,"source_id":"9ff19022ef915615911280e3c49ed44b","target_id":"03b024618527c930185a98873f353b45","source_type":"SOURCE_FILE","target_type":"CODE_SNIPPET","relationship_type":"CONTAINS","extra":"Source file contains code snippet: 12-18","gmt_create":"2026-05-23T15:18:41.173408+08:00","gmt_modified":"2026-05-23T15:18:41.173408+08:00"},{"id":1981,"source_id":"643984fc-5a57-498b-8f25-68cc318d9d82","target_id":"c25b39830f3b7734da975acc7f214666","source_type":"WIKI_ITEM","target_type":"CODE_SNIPPET","relationship_type":"CONTAINS","extra":"Wiki contains code snippet: backend/Dockerfile#31-33","gmt_create":"2026-05-23T15:18:41.174222+08:00","gmt_modified":"2026-05-23T15:18:41.174222+08:00"},{"id":1982,"source_id":"643984fc-5a57-498b-8f25-68cc318d9d82","target_id":"4c9d362ecce8e796e6f14850def049b0","source_type":"WIKI_ITEM","target_type":"CODE_SNIPPET","relationship_type":"CONTAINS","extra":"Wiki contains code snippet: docker-compose.yml#4-20","gmt_create":"2026-05-23T15:18:41.175392+08:00","gmt_modified":"2026-05-23T15:18:41.175392+08:00"},{"id":1983,"source_id":"643984fc-5a57-498b-8f25-68cc318d9d82","target_id":"d5827be2cfbe41c8177660ae877e93a4","source_type":"WIKI_ITEM","target_type":"CODE_SNIPPET","relationship_type":"CONTAINS","extra":"Wiki contains code snippet: docker-compose.yml#22-34","gmt_create":"2026-05-23T15:18:41.176895+08:00","gmt_modified":"2026-05-23T15:18:41.176895+08:00"},{"id":1984,"source_id":"643984fc-5a57-498b-8f25-68cc318d9d82","target_id":"03a65cdcfc173217d12ad8a417f8f033","source_type":"WIKI_ITEM","target_type":"CODE_SNIPPET","relationship_type":"CONTAINS","extra":"Wiki contains code snippet: backend/app/main.py#13-21","gmt_create":"2026-05-23T15:18:41.17848+08:00","gmt_modified":"2026-05-23T15:18:41.17848+08:00"},{"id":1985,"source_id":"643984fc-5a57-498b-8f25-68cc318d9d82","target_id":"6286d4be455dc058c8be2ee4e0d1175a","source_type":"WIKI_ITEM","target_type":"CODE_SNIPPET","relationship_type":"CONTAINS","extra":"Wiki contains code snippet: backend/app/main.py#38-42","gmt_create":"2026-05-23T15:18:41.180294+08:00","gmt_modified":"2026-05-23T15:18:41.180294+08:00"},{"id":1986,"source_id":"643984fc-5a57-498b-8f25-68cc318d9d82","target_id":"3365fa8db33d43bab1d0a614e8af3a70","source_type":"WIKI_ITEM","target_type":"CODE_SNIPPET","relationship_type":"CONTAINS","extra":"Wiki contains code snippet: backend/app/main.py#45-47","gmt_create":"2026-05-23T15:18:41.18154+08:00","gmt_modified":"2026-05-23T15:18:41.18154+08:00"},{"id":1987,"source_id":"643984fc-5a57-498b-8f25-68cc318d9d82","target_id":"4aad38dfc00a0877bd965c3d0b3c280c","source_type":"WIKI_ITEM","target_type":"CODE_SNIPPET","relationship_type":"CONTAINS","extra":"Wiki contains code snippet: backend/app/schemas/auth.py#7-34","gmt_create":"2026-05-23T15:18:41.18289+08:00","gmt_modified":"2026-05-23T15:18:41.18289+08:00"},{"id":1988,"source_id":"643984fc-5a57-498b-8f25-68cc318d9d82","target_id":"56e46969bdb790a5e8f333184b878d6d","source_type":"WIKI_ITEM","target_type":"CODE_SNIPPET","relationship_type":"CONTAINS","extra":"Wiki contains code snippet: backend/app/models/user.py#11-41","gmt_create":"2026-05-23T15:18:41.183973+08:00","gmt_modified":"2026-05-23T15:18:41.183973+08:00"},{"id":1989,"source_id":"643984fc-5a57-498b-8f25-68cc318d9d82","target_id":"f66d9907b467b110c638bd527efd95c5","source_type":"WIKI_ITEM","target_type":"CODE_SNIPPET","relationship_type":"CONTAINS","extra":"Wiki contains code snippet: backend/app/api/auth.py#1-43","gmt_create":"2026-05-23T15:18:41.185191+08:00","gmt_modified":"2026-05-23T15:18:41.185191+08:00"},{"id":1990,"source_id":"643984fc-5a57-498b-8f25-68cc318d9d82","target_id":"6f637c2b0796ec533aafb3b865c11cf0","source_type":"WIKI_ITEM","target_type":"CODE_SNIPPET","relationship_type":"CONTAINS","extra":"Wiki contains code snippet: backend/app/schemas/auth.py#1-34","gmt_create":"2026-05-23T15:18:41.186137+08:00","gmt_modified":"2026-05-23T15:18:41.186138+08:00"},{"id":1991,"source_id":"643984fc-5a57-498b-8f25-68cc318d9d82","target_id":"136f172c732d0cc130532a4f0df475a4","source_type":"WIKI_ITEM","target_type":"CODE_SNIPPET","relationship_type":"CONTAINS","extra":"Wiki contains code snippet: backend/app/models/user.py#1-41","gmt_create":"2026-05-23T15:18:41.187004+08:00","gmt_modified":"2026-05-23T15:18:41.187004+08:00"},{"id":1992,"source_id":"643984fc-5a57-498b-8f25-68cc318d9d82","target_id":"1693d293c428ed4a66bd90519a1bbad5","source_type":"WIKI_ITEM","target_type":"CODE_SNIPPET","relationship_type":"CONTAINS","extra":"Wiki contains code snippet: backend/app/config.py#12-13","gmt_create":"2026-05-23T15:18:41.188741+08:00","gmt_modified":"2026-05-23T15:18:41.188741+08:00"},{"id":1993,"source_id":"9ff19022ef915615911280e3c49ed44b","target_id":"1693d293c428ed4a66bd90519a1bbad5","source_type":"SOURCE_FILE","target_type":"CODE_SNIPPET","relationship_type":"CONTAINS","extra":"Source file contains code snippet: 12-13","gmt_create":"2026-05-23T15:18:41.189245+08:00","gmt_modified":"2026-05-23T15:18:41.189245+08:00"},{"id":1994,"source_id":"643984fc-5a57-498b-8f25-68cc318d9d82","target_id":"37bbab6e4f16db7eac6eee9d05e80e46","source_type":"WIKI_ITEM","target_type":"CODE_SNIPPET","relationship_type":"CONTAINS","extra":"Wiki contains code snippet: README.md#1-3","gmt_create":"2026-05-23T15:18:41.192525+08:00","gmt_modified":"2026-05-23T15:18:41.192525+08:00"},{"id":1995,"source_id":"643984fc-5a57-498b-8f25-68cc318d9d82","target_id":"c4f552eaa67bc052a06af7e5399d954c","source_type":"WIKI_ITEM","target_type":"CODE_SNIPPET","relationship_type":"CONTAINS","extra":"Wiki contains code snippet: backend/app/config.py#9-46","gmt_create":"2026-05-23T15:18:41.193775+08:00","gmt_modified":"2026-05-23T15:18:41.193775+08:00"},{"id":1996,"source_id":"9ff19022ef915615911280e3c49ed44b","target_id":"c4f552eaa67bc052a06af7e5399d954c","source_type":"SOURCE_FILE","target_type":"CODE_SNIPPET","relationship_type":"CONTAINS","extra":"Source file contains code snippet: 9-46","gmt_create":"2026-05-23T15:18:41.195066+08:00","gmt_modified":"2026-05-23T15:18:41.195066+08:00"},{"id":1997,"source_id":"643984fc-5a57-498b-8f25-68cc318d9d82","target_id":"db1c839ece4f3899017126c9b5b36016","source_type":"WIKI_ITEM","target_type":"CODE_SNIPPET","relationship_type":"CONTAINS","extra":"Wiki contains code snippet: docs/03-development/coding-standards.md#1-29","gmt_create":"2026-05-23T15:18:41.200058+08:00","gmt_modified":"2026-05-23T15:18:41.200058+08:00"},{"id":1998,"source_id":"3a1e34b542590c287768482d964dc7d5","target_id":"db1c839ece4f3899017126c9b5b36016","source_type":"SOURCE_FILE","target_type":"CODE_SNIPPET","relationship_type":"CONTAINS","extra":"Source file contains code snippet: 1-29","gmt_create":"2026-05-23T15:18:41.2015+08:00","gmt_modified":"2026-05-23T15:18:41.2015+08:00"},{"id":1999,"source_id":"643984fc-5a57-498b-8f25-68cc318d9d82","target_id":"9efa352ff057d696763b5eca047c0ca1","source_type":"WIKI_ITEM","target_type":"CODE_SNIPPET","relationship_type":"CONTAINS","extra":"Wiki contains code snippet: docs/03-development/dev-guide.md#1-32","gmt_create":"2026-05-23T15:18:41.204125+08:00","gmt_modified":"2026-05-23T15:18:41.204125+08:00"},{"id":2000,"source_id":"53d01851ef76ade6cb41a3cbe140676f","target_id":"9efa352ff057d696763b5eca047c0ca1","source_type":"SOURCE_FILE","target_type":"CODE_SNIPPET","relationship_type":"CONTAINS","extra":"Source file contains code snippet: 1-32","gmt_create":"2026-05-23T15:18:41.20481+08:00","gmt_modified":"2026-05-23T15:18:41.204811+08:00"},{"id":2001,"source_id":"643984fc-5a57-498b-8f25-68cc318d9d82","target_id":"10a5c824715b3c199eb40e1531c64150","source_type":"WIKI_ITEM","target_type":"CODE_SNIPPET","relationship_type":"CONTAINS","extra":"Wiki contains code snippet: docs/03-development/tdd-workflow.md#1-583","gmt_create":"2026-05-23T15:18:41.207218+08:00","gmt_modified":"2026-05-23T15:18:41.207218+08:00"},{"id":2002,"source_id":"974abe01413cc7a8a4898621e0b0779e","target_id":"10a5c824715b3c199eb40e1531c64150","source_type":"SOURCE_FILE","target_type":"CODE_SNIPPET","relationship_type":"CONTAINS","extra":"Source file contains code snippet: 1-583","gmt_create":"2026-05-23T15:18:41.208007+08:00","gmt_modified":"2026-05-23T15:18:41.208008+08:00"},{"id":2003,"source_id":"643984fc-5a57-498b-8f25-68cc318d9d82","target_id":"a47a364b551a984436d38cc17a272ef5","source_type":"WIKI_ITEM","target_type":"CODE_SNIPPET","relationship_type":"CONTAINS","extra":"Wiki contains code snippet: docs/04-testing/test-strategy.md#1-33","gmt_create":"2026-05-23T15:18:41.209182+08:00","gmt_modified":"2026-05-23T15:18:41.209183+08:00"},{"id":2004,"source_id":"b0db309ae449a2a435fc77103ca76955","target_id":"a47a364b551a984436d38cc17a272ef5","source_type":"SOURCE_FILE","target_type":"CODE_SNIPPET","relationship_type":"CONTAINS","extra":"Source file contains code snippet: 1-33","gmt_create":"2026-05-23T15:18:41.21001+08:00","gmt_modified":"2026-05-23T15:18:41.21001+08:00"},{"id":2005,"source_id":"643984fc-5a57-498b-8f25-68cc318d9d82","target_id":"6d2bbc04de724a57683b6d1af6f76e5b","source_type":"WIKI_ITEM","target_type":"CODE_SNIPPET","relationship_type":"CONTAINS","extra":"Wiki contains code snippet: docs/05-deployment/deployment-guide.md#1-32","gmt_create":"2026-05-23T15:18:41.210974+08:00","gmt_modified":"2026-05-23T15:18:41.210974+08:00"},{"id":2006,"source_id":"21e6700955fa049df458cee6020cf073","target_id":"6d2bbc04de724a57683b6d1af6f76e5b","source_type":"SOURCE_FILE","target_type":"CODE_SNIPPET","relationship_type":"CONTAINS","extra":"Source file contains code snippet: 1-32","gmt_create":"2026-05-23T15:18:41.214582+08:00","gmt_modified":"2026-05-23T15:18:41.214582+08:00"},{"id":2007,"source_id":"643984fc-5a57-498b-8f25-68cc318d9d82","target_id":"bf363deac5ef38c8dc80c73b862e730b","source_type":"WIKI_ITEM","target_type":"CODE_SNIPPET","relationship_type":"CONTAINS","extra":"Wiki contains code snippet: docker-compose.yml#4-34","gmt_create":"2026-05-23T15:18:41.216958+08:00","gmt_modified":"2026-05-23T15:18:41.216958+08:00"},{"id":2008,"source_id":"643984fc-5a57-498b-8f25-68cc318d9d82","target_id":"c6e94075e5f689bfa2fe16f8cf965203","source_type":"WIKI_ITEM","target_type":"CODE_SNIPPET","relationship_type":"CONTAINS","extra":"Wiki contains code snippet: tests/conftest.py#19-50","gmt_create":"2026-05-23T15:18:41.218379+08:00","gmt_modified":"2026-05-23T15:18:41.218379+08:00"},{"id":2009,"source_id":"643984fc-5a57-498b-8f25-68cc318d9d82","target_id":"1a78f5574add6d07a1d7c947dba3f23d","source_type":"WIKI_ITEM","target_type":"CODE_SNIPPET","relationship_type":"CONTAINS","extra":"Wiki contains code snippet: backend/alembic.ini#115-150","gmt_create":"2026-05-23T15:18:41.219483+08:00","gmt_modified":"2026-05-23T15:18:41.219484+08:00"},{"id":2010,"source_id":"643984fc-5a57-498b-8f25-68cc318d9d82","target_id":"f6810849c947471a4b45d7ca01ec8c5f","source_type":"WIKI_ITEM","target_type":"CODE_SNIPPET","relationship_type":"CONTAINS","extra":"Wiki contains code snippet: frontend/tailwind.config.ts#5-9","gmt_create":"2026-05-23T15:18:41.220597+08:00","gmt_modified":"2026-05-23T15:18:41.220597+08:00"},{"id":2011,"source_id":"643984fc-5a57-498b-8f25-68cc318d9d82","target_id":"67f5802e0fa695697eb6eeb1d1071448","source_type":"WIKI_ITEM","target_type":"CODE_SNIPPET","relationship_type":"CONTAINS","extra":"Wiki contains code snippet: docs/00-project/tech-stack.md#1-71","gmt_create":"2026-05-23T15:18:41.221486+08:00","gmt_modified":"2026-05-23T15:18:41.221486+08:00"},{"id":2012,"source_id":"01a3a8e0d02ddfa2e64837790ba231fa","target_id":"67f5802e0fa695697eb6eeb1d1071448","source_type":"SOURCE_FILE","target_type":"CODE_SNIPPET","relationship_type":"CONTAINS","extra":"Source file contains code snippet: 1-71","gmt_create":"2026-05-23T15:18:41.22238+08:00","gmt_modified":"2026-05-23T15:18:41.22238+08:00"},{"id":2013,"source_id":"ffbb970e-56e0-40ad-bd88-1a1e55482d96","target_id":"b0c428683c8a3e6922d90ca0d8c2736d","source_type":"WIKI_ITEM","target_type":"SOURCE_FILE","relationship_type":"REFERENCED_BY","extra":"Wiki references source file: backend/app/database.py","gmt_create":"2026-05-23T15:19:23.554788+08:00","gmt_modified":"2026-05-23T15:19:23.554788+08:00"},{"id":2014,"source_id":"ffbb970e-56e0-40ad-bd88-1a1e55482d96","target_id":"c59f8c276697a070dffc581fe94d809c","source_type":"WIKI_ITEM","target_type":"SOURCE_FILE","relationship_type":"REFERENCED_BY","extra":"Wiki references source file: backend/app/models/user.py","gmt_create":"2026-05-23T15:19:23.555831+08:00","gmt_modified":"2026-05-23T15:19:23.555831+08:00"},{"id":2015,"source_id":"ffbb970e-56e0-40ad-bd88-1a1e55482d96","target_id":"b74caccb06844efcdb14d8324cff65c2","source_type":"WIKI_ITEM","target_type":"SOURCE_FILE","relationship_type":"REFERENCED_BY","extra":"Wiki references source file: backend/app/models/query.py","gmt_create":"2026-05-23T15:19:23.556658+08:00","gmt_modified":"2026-05-23T15:19:23.556658+08:00"},{"id":2016,"source_id":"ffbb970e-56e0-40ad-bd88-1a1e55482d96","target_id":"b4a81ef789630d0af6a8d50859d01bf3","source_type":"WIKI_ITEM","target_type":"SOURCE_FILE","relationship_type":"REFERENCED_BY","extra":"Wiki references source file: backend/app/models/citation_record.py","gmt_create":"2026-05-23T15:19:23.572491+08:00","gmt_modified":"2026-05-23T15:19:23.572491+08:00"},{"id":2017,"source_id":"ffbb970e-56e0-40ad-bd88-1a1e55482d96","target_id":"069738f21ac2da7349d22683e8c36929","source_type":"WIKI_ITEM","target_type":"SOURCE_FILE","relationship_type":"REFERENCED_BY","extra":"Wiki references source file: backend/app/models/query_task.py","gmt_create":"2026-05-23T15:19:23.573626+08:00","gmt_modified":"2026-05-23T15:19:23.573626+08:00"},{"id":2018,"source_id":"ffbb970e-56e0-40ad-bd88-1a1e55482d96","target_id":"bceca00463fe55d3bcafda728f97f723","source_type":"WIKI_ITEM","target_type":"SOURCE_FILE","relationship_type":"REFERENCED_BY","extra":"Wiki references source file: backend/app/models/subscription.py","gmt_create":"2026-05-23T15:19:23.574254+08:00","gmt_modified":"2026-05-23T15:19:23.574254+08:00"},{"id":2019,"source_id":"ffbb970e-56e0-40ad-bd88-1a1e55482d96","target_id":"97cfe961cb7386b4022a51706ae8f5dd","source_type":"WIKI_ITEM","target_type":"SOURCE_FILE","relationship_type":"REFERENCED_BY","extra":"Wiki references source file: backend/app/models/lifecycle.py","gmt_create":"2026-05-23T15:19:23.57478+08:00","gmt_modified":"2026-05-23T15:19:23.57478+08:00"},{"id":2020,"source_id":"ffbb970e-56e0-40ad-bd88-1a1e55482d96","target_id":"68688ca664c7df5d64153200455dd7f6","source_type":"WIKI_ITEM","target_type":"SOURCE_FILE","relationship_type":"REFERENCED_BY","extra":"Wiki references source file: backend/app/models/analytics.py","gmt_create":"2026-05-23T15:19:23.577281+08:00","gmt_modified":"2026-05-23T15:19:23.577282+08:00"},{"id":2021,"source_id":"ffbb970e-56e0-40ad-bd88-1a1e55482d96","target_id":"9bad7097cce919cde648d435f673bac1","source_type":"WIKI_ITEM","target_type":"SOURCE_FILE","relationship_type":"REFERENCED_BY","extra":"Wiki references source file: backend/app/models/alert.py","gmt_create":"2026-05-23T15:19:23.578795+08:00","gmt_modified":"2026-05-23T15:19:23.578795+08:00"},{"id":2022,"source_id":"ffbb970e-56e0-40ad-bd88-1a1e55482d96","target_id":"4774aadaa8ace576601bdaa8d3e11f74","source_type":"WIKI_ITEM","target_type":"SOURCE_FILE","relationship_type":"REFERENCED_BY","extra":"Wiki references source file: backend/app/models/knowledge.py","gmt_create":"2026-05-23T15:19:23.579569+08:00","gmt_modified":"2026-05-23T15:19:23.579569+08:00"},{"id":2023,"source_id":"ffbb970e-56e0-40ad-bd88-1a1e55482d96","target_id":"99fe1b288fd41daa86c2dfbab819abf0","source_type":"WIKI_ITEM","target_type":"SOURCE_FILE","relationship_type":"REFERENCED_BY","extra":"Wiki references source file: backend/app/models/__init__.py","gmt_create":"2026-05-23T15:19:23.580288+08:00","gmt_modified":"2026-05-23T15:19:23.580289+08:00"},{"id":2024,"source_id":"ffbb970e-56e0-40ad-bd88-1a1e55482d96","target_id":"a680d4819f5da57fe9fa0e6bc708f380","source_type":"WIKI_ITEM","target_type":"SOURCE_FILE","relationship_type":"REFERENCED_BY","extra":"Wiki references source file: backend/alembic/env.py","gmt_create":"2026-05-23T15:19:23.580755+08:00","gmt_modified":"2026-05-23T15:19:23.580755+08:00"},{"id":2025,"source_id":"ffbb970e-56e0-40ad-bd88-1a1e55482d96","target_id":"d4f95fcf50683b5bf6167c7d2a6b126d","source_type":"WIKI_ITEM","target_type":"SOURCE_FILE","relationship_type":"REFERENCED_BY","extra":"Wiki references source file: backend/alembic/versions/488d0bd5ab01_initial_migration.py","gmt_create":"2026-05-23T15:19:23.581175+08:00","gmt_modified":"2026-05-23T15:19:23.581175+08:00"},{"id":2026,"source_id":"ffbb970e-56e0-40ad-bd88-1a1e55482d96","target_id":"f6e6948dd0cdd3894bd9928b21feb979","source_type":"WIKI_ITEM","target_type":"SOURCE_FILE","relationship_type":"REFERENCED_BY","extra":"Wiki references source file: backend/alembic/versions/b2c4d6e8fa10_add_confidence_match_type_to_citation_records.py","gmt_create":"2026-05-23T15:19:23.581588+08:00","gmt_modified":"2026-05-23T15:19:23.581588+08:00"},{"id":2027,"source_id":"ffbb970e-56e0-40ad-bd88-1a1e55482d96","target_id":"b0cb6810919f64006be7aa66b2b76a61","source_type":"WIKI_ITEM","target_type":"SOURCE_FILE","relationship_type":"REFERENCED_BY","extra":"Wiki references source file: backend/alembic/versions/c3d5e7f9ab12_add_user_management_fields.py","gmt_create":"2026-05-23T15:19:23.582209+08:00","gmt_modified":"2026-05-23T15:19:23.58221+08:00"},{"id":2028,"source_id":"ffbb970e-56e0-40ad-bd88-1a1e55482d96","target_id":"daab5d62bc9559915da6c4bd52dcec91","source_type":"WIKI_ITEM","target_type":"SOURCE_FILE","relationship_type":"REFERENCED_BY","extra":"Wiki references source file: backend/alembic/versions/d4f6g8h0ab23_add_geo_lifecycle_tables.py","gmt_create":"2026-05-23T15:19:23.582692+08:00","gmt_modified":"2026-05-23T15:19:23.582692+08:00"},{"id":2029,"source_id":"ffbb970e-56e0-40ad-bd88-1a1e55482d96","target_id":"22a884dd0b02fa904cd2808646d4aeca","source_type":"WIKI_ITEM","target_type":"SOURCE_FILE","relationship_type":"REFERENCED_BY","extra":"Wiki references source file: backend/alembic/versions/e5f7a9b1cd34_add_alerts_and_alert_settings_tables.py","gmt_create":"2026-05-23T15:19:23.583198+08:00","gmt_modified":"2026-05-23T15:19:23.583198+08:00"},{"id":2030,"source_id":"ffbb970e-56e0-40ad-bd88-1a1e55482d96","target_id":"e029becbf7babac61765f6a1790e1d48","source_type":"WIKI_ITEM","target_type":"SOURCE_FILE","relationship_type":"REFERENCED_BY","extra":"Wiki references source file: backend/alembic/versions/e5f7g9h1cd45_add_knowledge_base_tables.py","gmt_create":"2026-05-23T15:19:23.583893+08:00","gmt_modified":"2026-05-23T15:19:23.583894+08:00"},{"id":2031,"source_id":"ffbb970e-56e0-40ad-bd88-1a1e55482d96","target_id":"0c2c0c0ef594628c812c0adda8b914ea","source_type":"WIKI_ITEM","target_type":"SOURCE_FILE","relationship_type":"REFERENCED_BY","extra":"Wiki references source file: backend/alembic/versions/f6g8h0i2de56_add_analytics_tables.py","gmt_create":"2026-05-23T15:19:23.584455+08:00","gmt_modified":"2026-05-23T15:19:23.584455+08:00"},{"id":2032,"source_id":"ffbb970e-56e0-40ad-bd88-1a1e55482d96","target_id":"50f2e6bdc4a79e69bd43ea8d6fec67fe","source_type":"WIKI_ITEM","target_type":"SOURCE_FILE","relationship_type":"REFERENCED_BY","extra":"Wiki references source file: backend/alembic.ini","gmt_create":"2026-05-23T15:19:23.585197+08:00","gmt_modified":"2026-05-23T15:19:23.585197+08:00"},{"id":2033,"source_id":"ffbb970e-56e0-40ad-bd88-1a1e55482d96","target_id":"9ff19022ef915615911280e3c49ed44b","source_type":"WIKI_ITEM","target_type":"SOURCE_FILE","relationship_type":"REFERENCED_BY","extra":"Wiki references source file: backend/app/config.py","gmt_create":"2026-05-23T15:19:23.585749+08:00","gmt_modified":"2026-05-23T15:19:23.585749+08:00"},{"id":2034,"source_id":"ffbb970e-56e0-40ad-bd88-1a1e55482d96","target_id":"fc6242433ae9506bcc0bf4cb0dce1413","source_type":"WIKI_ITEM","target_type":"SOURCE_FILE","relationship_type":"REFERENCED_BY","extra":"Wiki references source file: docker-compose.yml","gmt_create":"2026-05-23T15:19:23.586422+08:00","gmt_modified":"2026-05-23T15:19:23.586422+08:00"},{"id":2035,"source_id":"ffbb970e-56e0-40ad-bd88-1a1e55482d96","target_id":"88d22de3b2a7419868e8ae19130d860c","source_type":"WIKI_ITEM","target_type":"SOURCE_FILE","relationship_type":"REFERENCED_BY","extra":"Wiki references source file: backend/app/services/query.py","gmt_create":"2026-05-23T15:19:23.587606+08:00","gmt_modified":"2026-05-23T15:19:23.587606+08:00"},{"id":2036,"source_id":"ffbb970e-56e0-40ad-bd88-1a1e55482d96","target_id":"04e3926c080e795713bff683e7dc9d3e","source_type":"WIKI_ITEM","target_type":"SOURCE_FILE","relationship_type":"REFERENCED_BY","extra":"Wiki references source file: backend/app/services/citation.py","gmt_create":"2026-05-23T15:19:23.588128+08:00","gmt_modified":"2026-05-23T15:19:23.588128+08:00"},{"id":2037,"source_id":"ffbb970e-56e0-40ad-bd88-1a1e55482d96","target_id":"4d2f3847b7c10634733118b70a1aea0b","source_type":"WIKI_ITEM","target_type":"SOURCE_FILE","relationship_type":"REFERENCED_BY","extra":"Wiki references source file: backend/app/services/auth.py","gmt_create":"2026-05-23T15:19:23.588692+08:00","gmt_modified":"2026-05-23T15:19:23.588692+08:00"},{"id":2038,"source_id":"ffbb970e-56e0-40ad-bd88-1a1e55482d96","target_id":"e0c0ca66b8b81cf66e078a7ab162c07f","source_type":"WIKI_ITEM","target_type":"SOURCE_FILE","relationship_type":"REFERENCED_BY","extra":"Wiki references source file: backend/app/schemas/auth.py","gmt_create":"2026-05-23T15:19:23.589291+08:00","gmt_modified":"2026-05-23T15:19:23.589291+08:00"},{"id":2039,"source_id":"ffbb970e-56e0-40ad-bd88-1a1e55482d96","target_id":"93022c8938ce318f167277cfa65c29a7","source_type":"WIKI_ITEM","target_type":"SOURCE_FILE","relationship_type":"REFERENCED_BY","extra":"Wiki references source file: backend/app/api/auth.py","gmt_create":"2026-05-23T15:19:23.59001+08:00","gmt_modified":"2026-05-23T15:19:23.59001+08:00"},{"id":2040,"source_id":"ffbb970e-56e0-40ad-bd88-1a1e55482d96","target_id":"7538ffe4902ab6041adb28b19844962a","source_type":"WIKI_ITEM","target_type":"SOURCE_FILE","relationship_type":"REFERENCED_BY","extra":"Wiki references source file: backend/app/api/citations.py","gmt_create":"2026-05-23T15:19:23.590586+08:00","gmt_modified":"2026-05-23T15:19:23.590586+08:00"},{"id":2041,"source_id":"ffbb970e-56e0-40ad-bd88-1a1e55482d96","target_id":"58901c94d975d87e652a4dc6c8dda656","source_type":"WIKI_ITEM","target_type":"SOURCE_FILE","relationship_type":"REFERENCED_BY","extra":"Wiki references source file: backend/app/api/reports.py","gmt_create":"2026-05-23T15:19:23.591167+08:00","gmt_modified":"2026-05-23T15:19:23.591167+08:00"},{"id":2042,"source_id":"ffbb970e-56e0-40ad-bd88-1a1e55482d96","target_id":"9c224bb80474867f8ded674babaa6e11","source_type":"WIKI_ITEM","target_type":"SOURCE_FILE","relationship_type":"REFERENCED_BY","extra":"Wiki references source file: backend/app/api/lifecycle.py","gmt_create":"2026-05-23T15:19:23.591703+08:00","gmt_modified":"2026-05-23T15:19:23.591704+08:00"},{"id":2043,"source_id":"ffbb970e-56e0-40ad-bd88-1a1e55482d96","target_id":"9af41884bf42d6e175163e89f663a479","source_type":"WIKI_ITEM","target_type":"SOURCE_FILE","relationship_type":"REFERENCED_BY","extra":"Wiki references source file: backend/app/api/analytics.py","gmt_create":"2026-05-23T15:19:23.59225+08:00","gmt_modified":"2026-05-23T15:19:23.59225+08:00"},{"id":2044,"source_id":"ffbb970e-56e0-40ad-bd88-1a1e55482d96","target_id":"80f3f2a6213e0002803247e1c51233be","source_type":"WIKI_ITEM","target_type":"SOURCE_FILE","relationship_type":"REFERENCED_BY","extra":"Wiki references source file: backend/app/api/alerts.py","gmt_create":"2026-05-23T15:19:23.595593+08:00","gmt_modified":"2026-05-23T15:19:23.595594+08:00"},{"id":2045,"source_id":"ffbb970e-56e0-40ad-bd88-1a1e55482d96","target_id":"63953ee6b39f159a61963104ac06f283","source_type":"WIKI_ITEM","target_type":"SOURCE_FILE","relationship_type":"REFERENCED_BY","extra":"Wiki references source file: backend/app/api/knowledge.py","gmt_create":"2026-05-23T15:19:23.596908+08:00","gmt_modified":"2026-05-23T15:19:23.596908+08:00"},{"id":2046,"source_id":"ffbb970e-56e0-40ad-bd88-1a1e55482d96","target_id":"ea655c6d147bc98beb42955d437260cc","source_type":"WIKI_ITEM","target_type":"CODE_SNIPPET","relationship_type":"CONTAINS","extra":"Wiki contains code snippet: backend/app/config.py#1-23","gmt_create":"2026-05-23T15:19:23.599053+08:00","gmt_modified":"2026-05-23T15:19:23.599053+08:00"},{"id":2047,"source_id":"ffbb970e-56e0-40ad-bd88-1a1e55482d96","target_id":"9bfc041fe426da2eb78353827e8d9163","source_type":"WIKI_ITEM","target_type":"CODE_SNIPPET","relationship_type":"CONTAINS","extra":"Wiki contains code snippet: backend/app/database.py#1-29","gmt_create":"2026-05-23T15:19:23.600626+08:00","gmt_modified":"2026-05-23T15:19:23.600627+08:00"},{"id":2048,"source_id":"ffbb970e-56e0-40ad-bd88-1a1e55482d96","target_id":"1f8d26b6a5da49d89d95bb13c7ace2c6","source_type":"WIKI_ITEM","target_type":"CODE_SNIPPET","relationship_type":"CONTAINS","extra":"Wiki contains code snippet: backend/app/models/user.py#1-48","gmt_create":"2026-05-23T15:19:23.601368+08:00","gmt_modified":"2026-05-23T15:19:23.601368+08:00"},{"id":2049,"source_id":"ffbb970e-56e0-40ad-bd88-1a1e55482d96","target_id":"87eaeed0bc611204a7529b148ae846e2","source_type":"WIKI_ITEM","target_type":"CODE_SNIPPET","relationship_type":"CONTAINS","extra":"Wiki contains code snippet: backend/app/models/lifecycle.py#1-92","gmt_create":"2026-05-23T15:19:23.602071+08:00","gmt_modified":"2026-05-23T15:19:23.602071+08:00"},{"id":2050,"source_id":"97cfe961cb7386b4022a51706ae8f5dd","target_id":"87eaeed0bc611204a7529b148ae846e2","source_type":"SOURCE_FILE","target_type":"CODE_SNIPPET","relationship_type":"CONTAINS","extra":"Source file contains code snippet: 1-92","gmt_create":"2026-05-23T15:19:23.602675+08:00","gmt_modified":"2026-05-23T15:19:23.602675+08:00"},{"id":2051,"source_id":"ffbb970e-56e0-40ad-bd88-1a1e55482d96","target_id":"790fb08a04a977bb97a81ea19d785777","source_type":"WIKI_ITEM","target_type":"CODE_SNIPPET","relationship_type":"CONTAINS","extra":"Wiki contains code snippet: backend/app/models/analytics.py#1-64","gmt_create":"2026-05-23T15:19:23.603748+08:00","gmt_modified":"2026-05-23T15:19:23.603748+08:00"},{"id":2052,"source_id":"68688ca664c7df5d64153200455dd7f6","target_id":"790fb08a04a977bb97a81ea19d785777","source_type":"SOURCE_FILE","target_type":"CODE_SNIPPET","relationship_type":"CONTAINS","extra":"Source file contains code snippet: 1-64","gmt_create":"2026-05-23T15:19:23.6044+08:00","gmt_modified":"2026-05-23T15:19:23.604401+08:00"},{"id":2053,"source_id":"ffbb970e-56e0-40ad-bd88-1a1e55482d96","target_id":"7bf4a8a5aa73c1704f76f4947a1a327a","source_type":"WIKI_ITEM","target_type":"CODE_SNIPPET","relationship_type":"CONTAINS","extra":"Wiki contains code snippet: backend/app/models/alert.py#1-75","gmt_create":"2026-05-23T15:19:23.605762+08:00","gmt_modified":"2026-05-23T15:19:23.605762+08:00"},{"id":2054,"source_id":"9bad7097cce919cde648d435f673bac1","target_id":"7bf4a8a5aa73c1704f76f4947a1a327a","source_type":"SOURCE_FILE","target_type":"CODE_SNIPPET","relationship_type":"CONTAINS","extra":"Source file contains code snippet: 1-75","gmt_create":"2026-05-23T15:19:23.606279+08:00","gmt_modified":"2026-05-23T15:19:23.606279+08:00"},{"id":2055,"source_id":"ffbb970e-56e0-40ad-bd88-1a1e55482d96","target_id":"9b03c2a2c7f00f40338248fa6d6f5c8b","source_type":"WIKI_ITEM","target_type":"CODE_SNIPPET","relationship_type":"CONTAINS","extra":"Wiki contains code snippet: backend/app/models/knowledge.py#1-213","gmt_create":"2026-05-23T15:19:23.607048+08:00","gmt_modified":"2026-05-23T15:19:23.607048+08:00"},{"id":2056,"source_id":"4774aadaa8ace576601bdaa8d3e11f74","target_id":"9b03c2a2c7f00f40338248fa6d6f5c8b","source_type":"SOURCE_FILE","target_type":"CODE_SNIPPET","relationship_type":"CONTAINS","extra":"Source file contains code snippet: 1-213","gmt_create":"2026-05-23T15:19:23.607557+08:00","gmt_modified":"2026-05-23T15:19:23.607557+08:00"},{"id":2057,"source_id":"ffbb970e-56e0-40ad-bd88-1a1e55482d96","target_id":"211463f5b49610f09594c40c0a235943","source_type":"WIKI_ITEM","target_type":"CODE_SNIPPET","relationship_type":"CONTAINS","extra":"Wiki contains code snippet: backend/alembic/env.py#1-89","gmt_create":"2026-05-23T15:19:23.609634+08:00","gmt_modified":"2026-05-23T15:19:23.609634+08:00"},{"id":2058,"source_id":"ffbb970e-56e0-40ad-bd88-1a1e55482d96","target_id":"48d22eaee09e364a293ad6c4750f5c5a","source_type":"WIKI_ITEM","target_type":"CODE_SNIPPET","relationship_type":"CONTAINS","extra":"Wiki contains code snippet: docker-compose.yml#1-71","gmt_create":"2026-05-23T15:19:23.611743+08:00","gmt_modified":"2026-05-23T15:19:23.611743+08:00"},{"id":2059,"source_id":"ffbb970e-56e0-40ad-bd88-1a1e55482d96","target_id":"afe4138895492c26aac5c0120ef46cd8","source_type":"WIKI_ITEM","target_type":"CODE_SNIPPET","relationship_type":"CONTAINS","extra":"Wiki contains code snippet: backend/app/models/__init__.py#1-14","gmt_create":"2026-05-23T15:19:23.616111+08:00","gmt_modified":"2026-05-23T15:19:23.616111+08:00"},{"id":2060,"source_id":"ffbb970e-56e0-40ad-bd88-1a1e55482d96","target_id":"98cc82f62b83678f06a33cf9231ecdf8","source_type":"WIKI_ITEM","target_type":"CODE_SNIPPET","relationship_type":"CONTAINS","extra":"Wiki contains code snippet: backend/alembic/versions/488d0bd5ab01_initial_migration.py#1-128","gmt_create":"2026-05-23T15:19:23.617406+08:00","gmt_modified":"2026-05-23T15:19:23.617406+08:00"},{"id":2061,"source_id":"ffbb970e-56e0-40ad-bd88-1a1e55482d96","target_id":"e1aabd52989e47806fb997157381e1cf","source_type":"WIKI_ITEM","target_type":"CODE_SNIPPET","relationship_type":"CONTAINS","extra":"Wiki contains code snippet: backend/alembic/versions/b2c4d6e8fa10_add_confidence_match_type_to_citation_records.py#1-37","gmt_create":"2026-05-23T15:19:23.61884+08:00","gmt_modified":"2026-05-23T15:19:23.61884+08:00"},{"id":2062,"source_id":"ffbb970e-56e0-40ad-bd88-1a1e55482d96","target_id":"c8f2dbcb7475bd189a34c7061ea46c6d","source_type":"WIKI_ITEM","target_type":"CODE_SNIPPET","relationship_type":"CONTAINS","extra":"Wiki contains code snippet: backend/alembic/versions/c3d5e7f9ab12_add_user_management_fields.py#1-41","gmt_create":"2026-05-23T15:19:23.619785+08:00","gmt_modified":"2026-05-23T15:19:23.619785+08:00"},{"id":2063,"source_id":"ffbb970e-56e0-40ad-bd88-1a1e55482d96","target_id":"d15e1f6c18afa7505178062959fe7333","source_type":"WIKI_ITEM","target_type":"CODE_SNIPPET","relationship_type":"CONTAINS","extra":"Wiki contains code snippet: backend/alembic/versions/d4f6g8h0ab23_add_geo_lifecycle_tables.py#1-398","gmt_create":"2026-05-23T15:19:23.620822+08:00","gmt_modified":"2026-05-23T15:19:23.620822+08:00"},{"id":2064,"source_id":"daab5d62bc9559915da6c4bd52dcec91","target_id":"d15e1f6c18afa7505178062959fe7333","source_type":"SOURCE_FILE","target_type":"CODE_SNIPPET","relationship_type":"CONTAINS","extra":"Source file contains code snippet: 1-398","gmt_create":"2026-05-23T15:19:23.621339+08:00","gmt_modified":"2026-05-23T15:19:23.621339+08:00"},{"id":2065,"source_id":"ffbb970e-56e0-40ad-bd88-1a1e55482d96","target_id":"762a2f675ceac5ab98af9a601f886b64","source_type":"WIKI_ITEM","target_type":"CODE_SNIPPET","relationship_type":"CONTAINS","extra":"Wiki contains code snippet: backend/alembic/versions/f6g8h0i2de56_add_analytics_tables.py#1-125","gmt_create":"2026-05-23T15:19:23.623307+08:00","gmt_modified":"2026-05-23T15:19:23.623307+08:00"},{"id":2066,"source_id":"0c2c0c0ef594628c812c0adda8b914ea","target_id":"762a2f675ceac5ab98af9a601f886b64","source_type":"SOURCE_FILE","target_type":"CODE_SNIPPET","relationship_type":"CONTAINS","extra":"Source file contains code snippet: 1-125","gmt_create":"2026-05-23T15:19:23.623741+08:00","gmt_modified":"2026-05-23T15:19:23.623741+08:00"},{"id":2067,"source_id":"ffbb970e-56e0-40ad-bd88-1a1e55482d96","target_id":"2df394b949344fe9ab2c77227b91a836","source_type":"WIKI_ITEM","target_type":"CODE_SNIPPET","relationship_type":"CONTAINS","extra":"Wiki contains code snippet: backend/alembic/versions/e5f7a9b1cd34_add_alerts_and_alert_settings_tables.py#1-86","gmt_create":"2026-05-23T15:19:23.624366+08:00","gmt_modified":"2026-05-23T15:19:23.624366+08:00"},{"id":2068,"source_id":"22a884dd0b02fa904cd2808646d4aeca","target_id":"2df394b949344fe9ab2c77227b91a836","source_type":"SOURCE_FILE","target_type":"CODE_SNIPPET","relationship_type":"CONTAINS","extra":"Source file contains code snippet: 1-86","gmt_create":"2026-05-23T15:19:23.626309+08:00","gmt_modified":"2026-05-23T15:19:23.626309+08:00"},{"id":2069,"source_id":"ffbb970e-56e0-40ad-bd88-1a1e55482d96","target_id":"0dc739a646e968be4ef81f8d6f73172f","source_type":"WIKI_ITEM","target_type":"CODE_SNIPPET","relationship_type":"CONTAINS","extra":"Wiki contains code snippet: backend/alembic/versions/e5f7g9h1cd45_add_knowledge_base_tables.py#1-224","gmt_create":"2026-05-23T15:19:23.627322+08:00","gmt_modified":"2026-05-23T15:19:23.627322+08:00"},{"id":2070,"source_id":"e029becbf7babac61765f6a1790e1d48","target_id":"0dc739a646e968be4ef81f8d6f73172f","source_type":"SOURCE_FILE","target_type":"CODE_SNIPPET","relationship_type":"CONTAINS","extra":"Source file contains code snippet: 1-224","gmt_create":"2026-05-23T15:19:23.62795+08:00","gmt_modified":"2026-05-23T15:19:23.627951+08:00"},{"id":2071,"source_id":"ffbb970e-56e0-40ad-bd88-1a1e55482d96","target_id":"916551131bd9ac8c9f9c8bb762af1fa4","source_type":"WIKI_ITEM","target_type":"CODE_SNIPPET","relationship_type":"CONTAINS","extra":"Wiki contains code snippet: backend/app/services/query.py#1-130","gmt_create":"2026-05-23T15:19:23.628703+08:00","gmt_modified":"2026-05-23T15:19:23.628703+08:00"},{"id":2072,"source_id":"ffbb970e-56e0-40ad-bd88-1a1e55482d96","target_id":"5d2836286eb7d4eb6039b004a9744d26","source_type":"WIKI_ITEM","target_type":"CODE_SNIPPET","relationship_type":"CONTAINS","extra":"Wiki contains code snippet: backend/app/services/citation.py#1-429","gmt_create":"2026-05-23T15:19:23.629487+08:00","gmt_modified":"2026-05-23T15:19:23.629487+08:00"},{"id":2073,"source_id":"ffbb970e-56e0-40ad-bd88-1a1e55482d96","target_id":"08c1475254a5bc8877ff29a895de3b6a","source_type":"WIKI_ITEM","target_type":"CODE_SNIPPET","relationship_type":"CONTAINS","extra":"Wiki contains code snippet: backend/app/services/auth.py#1-175","gmt_create":"2026-05-23T15:19:23.630346+08:00","gmt_modified":"2026-05-23T15:19:23.630346+08:00"},{"id":2074,"source_id":"ffbb970e-56e0-40ad-bd88-1a1e55482d96","target_id":"f5978358d04c3c917d9ca5044c7f36fa","source_type":"WIKI_ITEM","target_type":"CODE_SNIPPET","relationship_type":"CONTAINS","extra":"Wiki contains code snippet: backend/app/models/user.py#11-48","gmt_create":"2026-05-23T15:19:23.63281+08:00","gmt_modified":"2026-05-23T15:19:23.63281+08:00"},{"id":2075,"source_id":"ffbb970e-56e0-40ad-bd88-1a1e55482d96","target_id":"6a2a5a7cb69cc0e72c2e90e1d9e48037","source_type":"WIKI_ITEM","target_type":"CODE_SNIPPET","relationship_type":"CONTAINS","extra":"Wiki contains code snippet: backend/app/models/lifecycle.py#12-92","gmt_create":"2026-05-23T15:19:23.633688+08:00","gmt_modified":"2026-05-23T15:19:23.633688+08:00"},{"id":2076,"source_id":"ffbb970e-56e0-40ad-bd88-1a1e55482d96","target_id":"867308b1867163b86fcf5da125bff7bd","source_type":"WIKI_ITEM","target_type":"CODE_SNIPPET","relationship_type":"CONTAINS","extra":"Wiki contains code snippet: backend/app/models/analytics.py#9-64","gmt_create":"2026-05-23T15:19:23.634567+08:00","gmt_modified":"2026-05-23T15:19:23.634567+08:00"},{"id":2077,"source_id":"68688ca664c7df5d64153200455dd7f6","target_id":"867308b1867163b86fcf5da125bff7bd","source_type":"SOURCE_FILE","target_type":"CODE_SNIPPET","relationship_type":"CONTAINS","extra":"Source file contains code snippet: 9-64","gmt_create":"2026-05-23T15:19:23.635182+08:00","gmt_modified":"2026-05-23T15:19:23.635183+08:00"},{"id":2078,"source_id":"ffbb970e-56e0-40ad-bd88-1a1e55482d96","target_id":"7bb1fe5eea543a455c000decbf835a87","source_type":"WIKI_ITEM","target_type":"CODE_SNIPPET","relationship_type":"CONTAINS","extra":"Wiki contains code snippet: backend/app/models/alert.py#24-75","gmt_create":"2026-05-23T15:19:23.636116+08:00","gmt_modified":"2026-05-23T15:19:23.636117+08:00"},{"id":2079,"source_id":"9bad7097cce919cde648d435f673bac1","target_id":"7bb1fe5eea543a455c000decbf835a87","source_type":"SOURCE_FILE","target_type":"CODE_SNIPPET","relationship_type":"CONTAINS","extra":"Source file contains code snippet: 24-75","gmt_create":"2026-05-23T15:19:23.636556+08:00","gmt_modified":"2026-05-23T15:19:23.636556+08:00"},{"id":2080,"source_id":"ffbb970e-56e0-40ad-bd88-1a1e55482d96","target_id":"f043b2767c713f94381e9f7154cd904a","source_type":"WIKI_ITEM","target_type":"CODE_SNIPPET","relationship_type":"CONTAINS","extra":"Wiki contains code snippet: backend/app/models/knowledge.py#22-213","gmt_create":"2026-05-23T15:19:23.637182+08:00","gmt_modified":"2026-05-23T15:19:23.637182+08:00"},{"id":2081,"source_id":"ffbb970e-56e0-40ad-bd88-1a1e55482d96","target_id":"ac77e4875817616194b7b5997d4fb1ae","source_type":"WIKI_ITEM","target_type":"CODE_SNIPPET","relationship_type":"CONTAINS","extra":"Wiki contains code snippet: backend/alembic/versions/488d0bd5ab01_initial_migration.py#57-94","gmt_create":"2026-05-23T15:19:23.64098+08:00","gmt_modified":"2026-05-23T15:19:23.64098+08:00"},{"id":2082,"source_id":"ffbb970e-56e0-40ad-bd88-1a1e55482d96","target_id":"0e57efd98dacc85da21f995980371ee4","source_type":"WIKI_ITEM","target_type":"CODE_SNIPPET","relationship_type":"CONTAINS","extra":"Wiki contains code snippet: backend/alembic/versions/b2c4d6e8fa10_add_confidence_match_type_to_citation_records.py#21-37","gmt_create":"2026-05-23T15:19:23.643443+08:00","gmt_modified":"2026-05-23T15:19:23.643443+08:00"},{"id":2083,"source_id":"ffbb970e-56e0-40ad-bd88-1a1e55482d96","target_id":"675ab6c1ae510ca753b5e966b7b6a10c","source_type":"WIKI_ITEM","target_type":"CODE_SNIPPET","relationship_type":"CONTAINS","extra":"Wiki contains code snippet: backend/alembic/versions/c3d5e7f9ab12_add_user_management_fields.py#21-41","gmt_create":"2026-05-23T15:19:23.645994+08:00","gmt_modified":"2026-05-23T15:19:23.645994+08:00"},{"id":2084,"source_id":"ffbb970e-56e0-40ad-bd88-1a1e55482d96","target_id":"14d45085df87325a1a8a05e5a7306ea9","source_type":"WIKI_ITEM","target_type":"CODE_SNIPPET","relationship_type":"CONTAINS","extra":"Wiki contains code snippet: backend/alembic/versions/d4f6g8h0ab23_add_geo_lifecycle_tables.py#24-398","gmt_create":"2026-05-23T15:19:23.647263+08:00","gmt_modified":"2026-05-23T15:19:23.647263+08:00"},{"id":2085,"source_id":"daab5d62bc9559915da6c4bd52dcec91","target_id":"14d45085df87325a1a8a05e5a7306ea9","source_type":"SOURCE_FILE","target_type":"CODE_SNIPPET","relationship_type":"CONTAINS","extra":"Source file contains code snippet: 24-398","gmt_create":"2026-05-23T15:19:23.647719+08:00","gmt_modified":"2026-05-23T15:19:23.647719+08:00"},{"id":2086,"source_id":"ffbb970e-56e0-40ad-bd88-1a1e55482d96","target_id":"ab4062f7b12bddc89c8a6ecb5716ec22","source_type":"WIKI_ITEM","target_type":"CODE_SNIPPET","relationship_type":"CONTAINS","extra":"Wiki contains code snippet: backend/alembic/versions/f6g8h0i2de56_add_analytics_tables.py#24-125","gmt_create":"2026-05-23T15:19:23.648321+08:00","gmt_modified":"2026-05-23T15:19:23.648321+08:00"},{"id":2087,"source_id":"0c2c0c0ef594628c812c0adda8b914ea","target_id":"ab4062f7b12bddc89c8a6ecb5716ec22","source_type":"SOURCE_FILE","target_type":"CODE_SNIPPET","relationship_type":"CONTAINS","extra":"Source file contains code snippet: 24-125","gmt_create":"2026-05-23T15:19:23.6488+08:00","gmt_modified":"2026-05-23T15:19:23.6488+08:00"},{"id":2088,"source_id":"ffbb970e-56e0-40ad-bd88-1a1e55482d96","target_id":"d8c1ac7c70dcfce3893bb34ccad2ea86","source_type":"WIKI_ITEM","target_type":"CODE_SNIPPET","relationship_type":"CONTAINS","extra":"Wiki contains code snippet: backend/alembic/versions/e5f7a9b1cd34_add_alerts_and_alert_settings_tables.py#24-86","gmt_create":"2026-05-23T15:19:23.649406+08:00","gmt_modified":"2026-05-23T15:19:23.649406+08:00"},{"id":2089,"source_id":"22a884dd0b02fa904cd2808646d4aeca","target_id":"d8c1ac7c70dcfce3893bb34ccad2ea86","source_type":"SOURCE_FILE","target_type":"CODE_SNIPPET","relationship_type":"CONTAINS","extra":"Source file contains code snippet: 24-86","gmt_create":"2026-05-23T15:19:23.650058+08:00","gmt_modified":"2026-05-23T15:19:23.650058+08:00"},{"id":2090,"source_id":"ffbb970e-56e0-40ad-bd88-1a1e55482d96","target_id":"3f54e06cbaf0717d01fb0f4cb7294795","source_type":"WIKI_ITEM","target_type":"CODE_SNIPPET","relationship_type":"CONTAINS","extra":"Wiki contains code snippet: backend/alembic/versions/e5f7g9h1cd45_add_knowledge_base_tables.py#30-224","gmt_create":"2026-05-23T15:19:23.651039+08:00","gmt_modified":"2026-05-23T15:19:23.65104+08:00"},{"id":2091,"source_id":"e029becbf7babac61765f6a1790e1d48","target_id":"3f54e06cbaf0717d01fb0f4cb7294795","source_type":"SOURCE_FILE","target_type":"CODE_SNIPPET","relationship_type":"CONTAINS","extra":"Source file contains code snippet: 30-224","gmt_create":"2026-05-23T15:19:23.651691+08:00","gmt_modified":"2026-05-23T15:19:23.651691+08:00"},{"id":2092,"source_id":"ffbb970e-56e0-40ad-bd88-1a1e55482d96","target_id":"d34337b9ff77246979252d2fd8fb8018","source_type":"WIKI_ITEM","target_type":"CODE_SNIPPET","relationship_type":"CONTAINS","extra":"Wiki contains code snippet: backend/alembic/env.py#33-88","gmt_create":"2026-05-23T15:19:23.662049+08:00","gmt_modified":"2026-05-23T15:19:23.662049+08:00"},{"id":2093,"source_id":"ffbb970e-56e0-40ad-bd88-1a1e55482d96","target_id":"4d11ddf7abb8076d81b30c4315786f9a","source_type":"WIKI_ITEM","target_type":"CODE_SNIPPET","relationship_type":"CONTAINS","extra":"Wiki contains code snippet: backend/alembic/versions/488d0bd5ab01_initial_migration.py#21-128","gmt_create":"2026-05-23T15:19:23.664087+08:00","gmt_modified":"2026-05-23T15:19:23.664087+08:00"},{"id":2094,"source_id":"ffbb970e-56e0-40ad-bd88-1a1e55482d96","target_id":"948aa417b68df80b5de0cfdb37e5455e","source_type":"WIKI_ITEM","target_type":"CODE_SNIPPET","relationship_type":"CONTAINS","extra":"Wiki contains code snippet: backend/alembic/versions/d4f6g8h0ab23_add_geo_lifecycle_tables.py#21-398","gmt_create":"2026-05-23T15:19:23.665869+08:00","gmt_modified":"2026-05-23T15:19:23.665869+08:00"},{"id":2095,"source_id":"daab5d62bc9559915da6c4bd52dcec91","target_id":"948aa417b68df80b5de0cfdb37e5455e","source_type":"SOURCE_FILE","target_type":"CODE_SNIPPET","relationship_type":"CONTAINS","extra":"Source file contains code snippet: 21-398","gmt_create":"2026-05-23T15:19:23.666599+08:00","gmt_modified":"2026-05-23T15:19:23.666599+08:00"},{"id":2096,"source_id":"ffbb970e-56e0-40ad-bd88-1a1e55482d96","target_id":"96de5ca994afbb0cc75f2b0d419d69f7","source_type":"WIKI_ITEM","target_type":"CODE_SNIPPET","relationship_type":"CONTAINS","extra":"Wiki contains code snippet: backend/alembic/versions/e5f7a9b1cd34_add_alerts_and_alert_settings_tables.py#21-86","gmt_create":"2026-05-23T15:19:23.667775+08:00","gmt_modified":"2026-05-23T15:19:23.66778+08:00"},{"id":2097,"source_id":"22a884dd0b02fa904cd2808646d4aeca","target_id":"96de5ca994afbb0cc75f2b0d419d69f7","source_type":"SOURCE_FILE","target_type":"CODE_SNIPPET","relationship_type":"CONTAINS","extra":"Source file contains code snippet: 21-86","gmt_create":"2026-05-23T15:19:23.669265+08:00","gmt_modified":"2026-05-23T15:19:23.669265+08:00"},{"id":2098,"source_id":"ffbb970e-56e0-40ad-bd88-1a1e55482d96","target_id":"5f830240a0d18e5b3718cd8cabebed6e","source_type":"WIKI_ITEM","target_type":"CODE_SNIPPET","relationship_type":"CONTAINS","extra":"Wiki contains code snippet: backend/alembic/versions/e5f7g9h1cd45_add_knowledge_base_tables.py#21-224","gmt_create":"2026-05-23T15:19:23.669953+08:00","gmt_modified":"2026-05-23T15:19:23.669953+08:00"},{"id":2099,"source_id":"e029becbf7babac61765f6a1790e1d48","target_id":"5f830240a0d18e5b3718cd8cabebed6e","source_type":"SOURCE_FILE","target_type":"CODE_SNIPPET","relationship_type":"CONTAINS","extra":"Source file contains code snippet: 21-224","gmt_create":"2026-05-23T15:19:23.670664+08:00","gmt_modified":"2026-05-23T15:19:23.670665+08:00"},{"id":2100,"source_id":"ffbb970e-56e0-40ad-bd88-1a1e55482d96","target_id":"4a7611bf0d84c8d44518673bbe5af6ad","source_type":"WIKI_ITEM","target_type":"CODE_SNIPPET","relationship_type":"CONTAINS","extra":"Wiki contains code snippet: backend/alembic/versions/f6g8h0i2de56_add_analytics_tables.py#20-125","gmt_create":"2026-05-23T15:19:23.671643+08:00","gmt_modified":"2026-05-23T15:19:23.671643+08:00"},{"id":2101,"source_id":"0c2c0c0ef594628c812c0adda8b914ea","target_id":"4a7611bf0d84c8d44518673bbe5af6ad","source_type":"SOURCE_FILE","target_type":"CODE_SNIPPET","relationship_type":"CONTAINS","extra":"Source file contains code snippet: 20-125","gmt_create":"2026-05-23T15:19:23.672211+08:00","gmt_modified":"2026-05-23T15:19:23.672211+08:00"},{"id":2102,"source_id":"ffbb970e-56e0-40ad-bd88-1a1e55482d96","target_id":"eb63042f04a22f9a67bd498df1684d20","source_type":"WIKI_ITEM","target_type":"CODE_SNIPPET","relationship_type":"CONTAINS","extra":"Wiki contains code snippet: backend/alembic/versions/488d0bd5ab01_initial_migration.py#36-111","gmt_create":"2026-05-23T15:19:23.680639+08:00","gmt_modified":"2026-05-23T15:19:23.680639+08:00"},{"id":2103,"source_id":"ffbb970e-56e0-40ad-bd88-1a1e55482d96","target_id":"9b10dac7dbbb1327afc8a525bf4bd0c3","source_type":"WIKI_ITEM","target_type":"CODE_SNIPPET","relationship_type":"CONTAINS","extra":"Wiki contains code snippet: backend/app/services/query.py#45-81","gmt_create":"2026-05-23T15:19:23.68471+08:00","gmt_modified":"2026-05-23T15:19:23.684711+08:00"},{"id":2104,"source_id":"ffbb970e-56e0-40ad-bd88-1a1e55482d96","target_id":"c651c7ad6747a92ee96eabb2eb82afdd","source_type":"WIKI_ITEM","target_type":"CODE_SNIPPET","relationship_type":"CONTAINS","extra":"Wiki contains code snippet: backend/app/database.py#12-18","gmt_create":"2026-05-23T15:19:23.686051+08:00","gmt_modified":"2026-05-23T15:19:23.686051+08:00"},{"id":2105,"source_id":"ffbb970e-56e0-40ad-bd88-1a1e55482d96","target_id":"7dae7237f11c5100bf7889c105193cf6","source_type":"WIKI_ITEM","target_type":"CODE_SNIPPET","relationship_type":"CONTAINS","extra":"Wiki contains code snippet: backend/app/services/query.py#12-32","gmt_create":"2026-05-23T15:19:23.687784+08:00","gmt_modified":"2026-05-23T15:19:23.687784+08:00"},{"id":2106,"source_id":"ffbb970e-56e0-40ad-bd88-1a1e55482d96","target_id":"dd01eee487298a28e950f6345196f1d4","source_type":"WIKI_ITEM","target_type":"CODE_SNIPPET","relationship_type":"CONTAINS","extra":"Wiki contains code snippet: backend/app/services/citation.py#30-79","gmt_create":"2026-05-23T15:19:23.688917+08:00","gmt_modified":"2026-05-23T15:19:23.688917+08:00"},{"id":2107,"source_id":"ffbb970e-56e0-40ad-bd88-1a1e55482d96","target_id":"fe351bf59a46bec7f77ffe40a68a5993","source_type":"WIKI_ITEM","target_type":"CODE_SNIPPET","relationship_type":"CONTAINS","extra":"Wiki contains code snippet: backend/app/services/auth.py#40-56","gmt_create":"2026-05-23T15:19:23.690208+08:00","gmt_modified":"2026-05-23T15:19:23.690208+08:00"},{"id":2108,"source_id":"ffbb970e-56e0-40ad-bd88-1a1e55482d96","target_id":"cc64cf609f5ff218f618e0664ffa7cc7","source_type":"WIKI_ITEM","target_type":"CODE_SNIPPET","relationship_type":"CONTAINS","extra":"Wiki contains code snippet: backend/app/services/citation.py#298-308","gmt_create":"2026-05-23T15:19:23.691133+08:00","gmt_modified":"2026-05-23T15:19:23.691133+08:00"},{"id":2109,"source_id":"ffbb970e-56e0-40ad-bd88-1a1e55482d96","target_id":"ce7e334595a4ce912e0d116314db9a35","source_type":"WIKI_ITEM","target_type":"CODE_SNIPPET","relationship_type":"CONTAINS","extra":"Wiki contains code snippet: backend/app/services/citation.py#342-429","gmt_create":"2026-05-23T15:19:23.693626+08:00","gmt_modified":"2026-05-23T15:19:23.693627+08:00"},{"id":2110,"source_id":"ffbb970e-56e0-40ad-bd88-1a1e55482d96","target_id":"1a3336b4af8a39a055e912724338580c","source_type":"WIKI_ITEM","target_type":"SOURCE_FILE","relationship_type":"REFERENCED_BY","extra":"Wiki references source file: backend/app/schemas/citation.py","gmt_create":"2026-05-23T15:19:23.694541+08:00","gmt_modified":"2026-05-23T15:19:23.694541+08:00"},{"id":2111,"source_id":"ffbb970e-56e0-40ad-bd88-1a1e55482d96","target_id":"2f46f212597e3c245b9e5dcc5dbc863d","source_type":"WIKI_ITEM","target_type":"CODE_SNIPPET","relationship_type":"CONTAINS","extra":"Wiki contains code snippet: backend/app/schemas/citation.py#7-18","gmt_create":"2026-05-23T15:19:23.694986+08:00","gmt_modified":"2026-05-23T15:19:23.694986+08:00"},{"id":2112,"source_id":"ffbb970e-56e0-40ad-bd88-1a1e55482d96","target_id":"46e69841e5c5dc62faa55c9f066586d6","source_type":"WIKI_ITEM","target_type":"CODE_SNIPPET","relationship_type":"CONTAINS","extra":"Wiki contains code snippet: backend/app/services/auth.py#74-107","gmt_create":"2026-05-23T15:19:23.696249+08:00","gmt_modified":"2026-05-23T15:19:23.696249+08:00"},{"id":2113,"source_id":"ffbb970e-56e0-40ad-bd88-1a1e55482d96","target_id":"cecc8857775f7928d465b68e429493d2","source_type":"WIKI_ITEM","target_type":"CODE_SNIPPET","relationship_type":"CONTAINS","extra":"Wiki contains code snippet: backend/app/services/auth.py#110-140","gmt_create":"2026-05-23T15:19:23.697419+08:00","gmt_modified":"2026-05-23T15:19:23.697419+08:00"},{"id":2114,"source_id":"ffbb970e-56e0-40ad-bd88-1a1e55482d96","target_id":"1153d8a149a70bc79ca59a9dcba5945c","source_type":"WIKI_ITEM","target_type":"CODE_SNIPPET","relationship_type":"CONTAINS","extra":"Wiki contains code snippet: backend/app/schemas/auth.py#8-55","gmt_create":"2026-05-23T15:19:23.698372+08:00","gmt_modified":"2026-05-23T15:19:23.698372+08:00"},{"id":2115,"source_id":"ffbb970e-56e0-40ad-bd88-1a1e55482d96","target_id":"35dd08df9c7a562d9c7b8edf740eaf3c","source_type":"WIKI_ITEM","target_type":"CODE_SNIPPET","relationship_type":"CONTAINS","extra":"Wiki contains code snippet: backend/app/api/auth.py#33-115","gmt_create":"2026-05-23T15:19:23.699524+08:00","gmt_modified":"2026-05-23T15:19:23.699525+08:00"},{"id":2116,"source_id":"ffbb970e-56e0-40ad-bd88-1a1e55482d96","target_id":"dc40f1dd3e59ee7f046019201068bea1","source_type":"WIKI_ITEM","target_type":"CODE_SNIPPET","relationship_type":"CONTAINS","extra":"Wiki contains code snippet: backend/app/services/citation.py#14-22","gmt_create":"2026-05-23T15:19:23.713232+08:00","gmt_modified":"2026-05-23T15:19:23.713233+08:00"},{"id":2117,"source_id":"98909ecc-fceb-4ab7-a26f-741838eb2e50","target_id":"fc6242433ae9506bcc0bf4cb0dce1413","source_type":"WIKI_ITEM","target_type":"SOURCE_FILE","relationship_type":"REFERENCED_BY","extra":"Wiki references source file: docker-compose.yml","gmt_create":"2026-05-23T15:19:55.78259+08:00","gmt_modified":"2026-05-23T15:19:55.78259+08:00"},{"id":2118,"source_id":"98909ecc-fceb-4ab7-a26f-741838eb2e50","target_id":"e9b52adbec3c07cf021e488dd3f99ab4","source_type":"WIKI_ITEM","target_type":"SOURCE_FILE","relationship_type":"REFERENCED_BY","extra":"Wiki references source file: backend/Dockerfile","gmt_create":"2026-05-23T15:19:55.783376+08:00","gmt_modified":"2026-05-23T15:19:55.783376+08:00"},{"id":2119,"source_id":"98909ecc-fceb-4ab7-a26f-741838eb2e50","target_id":"5e414f2ef9b69e55e00ab15f85b9291a","source_type":"WIKI_ITEM","target_type":"SOURCE_FILE","relationship_type":"REFERENCED_BY","extra":"Wiki references source file: frontend/Dockerfile","gmt_create":"2026-05-23T15:19:55.784159+08:00","gmt_modified":"2026-05-23T15:19:55.78416+08:00"},{"id":2120,"source_id":"98909ecc-fceb-4ab7-a26f-741838eb2e50","target_id":"9228ff67d4c757a85d9421b71f4b29f5","source_type":"WIKI_ITEM","target_type":"SOURCE_FILE","relationship_type":"REFERENCED_BY","extra":"Wiki references source file: backend/app/main.py","gmt_create":"2026-05-23T15:19:55.784671+08:00","gmt_modified":"2026-05-23T15:19:55.784672+08:00"},{"id":2121,"source_id":"98909ecc-fceb-4ab7-a26f-741838eb2e50","target_id":"9ff19022ef915615911280e3c49ed44b","source_type":"WIKI_ITEM","target_type":"SOURCE_FILE","relationship_type":"REFERENCED_BY","extra":"Wiki references source file: backend/app/config.py","gmt_create":"2026-05-23T15:19:55.785266+08:00","gmt_modified":"2026-05-23T15:19:55.785266+08:00"},{"id":2122,"source_id":"98909ecc-fceb-4ab7-a26f-741838eb2e50","target_id":"a26ee01cf41da3b956e1650448c156fa","source_type":"WIKI_ITEM","target_type":"SOURCE_FILE","relationship_type":"REFERENCED_BY","extra":"Wiki references source file: backend/requirements.txt","gmt_create":"2026-05-23T15:19:55.785962+08:00","gmt_modified":"2026-05-23T15:19:55.785962+08:00"},{"id":2123,"source_id":"98909ecc-fceb-4ab7-a26f-741838eb2e50","target_id":"aaf5bce6be82d2f947bfa5c1806de452","source_type":"WIKI_ITEM","target_type":"SOURCE_FILE","relationship_type":"REFERENCED_BY","extra":"Wiki references source file: frontend/package.json","gmt_create":"2026-05-23T15:19:55.823839+08:00","gmt_modified":"2026-05-23T15:19:55.82384+08:00"},{"id":2124,"source_id":"98909ecc-fceb-4ab7-a26f-741838eb2e50","target_id":"5cbb1e3f112aeba62a14b0b8999fc0f5","source_type":"WIKI_ITEM","target_type":"SOURCE_FILE","relationship_type":"REFERENCED_BY","extra":"Wiki references source file: backend/app/workers/scheduler.py","gmt_create":"2026-05-23T15:19:55.825129+08:00","gmt_modified":"2026-05-23T15:19:55.825129+08:00"},{"id":2125,"source_id":"98909ecc-fceb-4ab7-a26f-741838eb2e50","target_id":"93022c8938ce318f167277cfa65c29a7","source_type":"WIKI_ITEM","target_type":"SOURCE_FILE","relationship_type":"REFERENCED_BY","extra":"Wiki references source file: backend/app/api/auth.py","gmt_create":"2026-05-23T15:19:55.827216+08:00","gmt_modified":"2026-05-23T15:19:55.827216+08:00"},{"id":2126,"source_id":"98909ecc-fceb-4ab7-a26f-741838eb2e50","target_id":"b0c428683c8a3e6922d90ca0d8c2736d","source_type":"WIKI_ITEM","target_type":"SOURCE_FILE","relationship_type":"REFERENCED_BY","extra":"Wiki references source file: backend/app/database.py","gmt_create":"2026-05-23T15:19:55.828339+08:00","gmt_modified":"2026-05-23T15:19:55.828339+08:00"},{"id":2127,"source_id":"98909ecc-fceb-4ab7-a26f-741838eb2e50","target_id":"b74caccb06844efcdb14d8324cff65c2","source_type":"WIKI_ITEM","target_type":"SOURCE_FILE","relationship_type":"REFERENCED_BY","extra":"Wiki references source file: backend/app/models/query.py","gmt_create":"2026-05-23T15:19:55.829074+08:00","gmt_modified":"2026-05-23T15:19:55.829075+08:00"},{"id":2128,"source_id":"98909ecc-fceb-4ab7-a26f-741838eb2e50","target_id":"50f2e6bdc4a79e69bd43ea8d6fec67fe","source_type":"WIKI_ITEM","target_type":"SOURCE_FILE","relationship_type":"REFERENCED_BY","extra":"Wiki references source file: backend/alembic.ini","gmt_create":"2026-05-23T15:19:55.829568+08:00","gmt_modified":"2026-05-23T15:19:55.829569+08:00"},{"id":2129,"source_id":"98909ecc-fceb-4ab7-a26f-741838eb2e50","target_id":"a680d4819f5da57fe9fa0e6bc708f380","source_type":"WIKI_ITEM","target_type":"SOURCE_FILE","relationship_type":"REFERENCED_BY","extra":"Wiki references source file: backend/alembic/env.py","gmt_create":"2026-05-23T15:19:55.830029+08:00","gmt_modified":"2026-05-23T15:19:55.830029+08:00"},{"id":2130,"source_id":"98909ecc-fceb-4ab7-a26f-741838eb2e50","target_id":"b44632a0f399b2fe2b4daf295a120ec7","source_type":"WIKI_ITEM","target_type":"SOURCE_FILE","relationship_type":"REFERENCED_BY","extra":"Wiki references source file: backend/app/middleware/logging_middleware.py","gmt_create":"2026-05-23T15:19:55.830487+08:00","gmt_modified":"2026-05-23T15:19:55.830488+08:00"},{"id":2131,"source_id":"98909ecc-fceb-4ab7-a26f-741838eb2e50","target_id":"5883a8ef4fc156d76b71ffdb5ecdf232","source_type":"WIKI_ITEM","target_type":"SOURCE_FILE","relationship_type":"REFERENCED_BY","extra":"Wiki references source file: backend/app/middleware/rate_limit.py","gmt_create":"2026-05-23T15:19:55.830935+08:00","gmt_modified":"2026-05-23T15:19:55.830936+08:00"},{"id":2132,"source_id":"98909ecc-fceb-4ab7-a26f-741838eb2e50","target_id":"389d631bc6c7111ba411b0b79fca455e","source_type":"WIKI_ITEM","target_type":"SOURCE_FILE","relationship_type":"REFERENCED_BY","extra":"Wiki references source file: tests/test_auth.py","gmt_create":"2026-05-23T15:19:55.831468+08:00","gmt_modified":"2026-05-23T15:19:55.831468+08:00"},{"id":2133,"source_id":"98909ecc-fceb-4ab7-a26f-741838eb2e50","target_id":"48d22eaee09e364a293ad6c4750f5c5a","source_type":"WIKI_ITEM","target_type":"CODE_SNIPPET","relationship_type":"CONTAINS","extra":"Wiki contains code snippet: docker-compose.yml#1-71","gmt_create":"2026-05-23T15:19:55.832153+08:00","gmt_modified":"2026-05-23T15:19:55.832153+08:00"},{"id":2134,"source_id":"98909ecc-fceb-4ab7-a26f-741838eb2e50","target_id":"412695e5de2014514a8f62f98c573656","source_type":"WIKI_ITEM","target_type":"CODE_SNIPPET","relationship_type":"CONTAINS","extra":"Wiki contains code snippet: backend/Dockerfile#1-41","gmt_create":"2026-05-23T15:19:55.833115+08:00","gmt_modified":"2026-05-23T15:19:55.833116+08:00"},{"id":2135,"source_id":"98909ecc-fceb-4ab7-a26f-741838eb2e50","target_id":"01a0c4b40819965823b56e9da858c024","source_type":"WIKI_ITEM","target_type":"CODE_SNIPPET","relationship_type":"CONTAINS","extra":"Wiki contains code snippet: frontend/Dockerfile#1-15","gmt_create":"2026-05-23T15:19:55.833968+08:00","gmt_modified":"2026-05-23T15:19:55.833968+08:00"},{"id":2136,"source_id":"98909ecc-fceb-4ab7-a26f-741838eb2e50","target_id":"cb292fb9d8227e14f98eed613b793a74","source_type":"WIKI_ITEM","target_type":"CODE_SNIPPET","relationship_type":"CONTAINS","extra":"Wiki contains code snippet: backend/app/main.py#1-100","gmt_create":"2026-05-23T15:19:55.834812+08:00","gmt_modified":"2026-05-23T15:19:55.834812+08:00"},{"id":2137,"source_id":"9228ff67d4c757a85d9421b71f4b29f5","target_id":"cb292fb9d8227e14f98eed613b793a74","source_type":"SOURCE_FILE","target_type":"CODE_SNIPPET","relationship_type":"CONTAINS","extra":"Source file contains code snippet: 1-100","gmt_create":"2026-05-23T15:19:55.835384+08:00","gmt_modified":"2026-05-23T15:19:55.835384+08:00"},{"id":2138,"source_id":"98909ecc-fceb-4ab7-a26f-741838eb2e50","target_id":"dd36901ce62b8cc1d66667dcdc45e637","source_type":"WIKI_ITEM","target_type":"CODE_SNIPPET","relationship_type":"CONTAINS","extra":"Wiki contains code snippet: backend/app/config.py#1-46","gmt_create":"2026-05-23T15:19:55.836049+08:00","gmt_modified":"2026-05-23T15:19:55.836049+08:00"},{"id":2139,"source_id":"98909ecc-fceb-4ab7-a26f-741838eb2e50","target_id":"9bfc041fe426da2eb78353827e8d9163","source_type":"WIKI_ITEM","target_type":"CODE_SNIPPET","relationship_type":"CONTAINS","extra":"Wiki contains code snippet: backend/app/database.py#1-29","gmt_create":"2026-05-23T15:19:55.837204+08:00","gmt_modified":"2026-05-23T15:19:55.837205+08:00"},{"id":2140,"source_id":"98909ecc-fceb-4ab7-a26f-741838eb2e50","target_id":"1aa2eb624a63acddcd9638630606b2e9","source_type":"WIKI_ITEM","target_type":"CODE_SNIPPET","relationship_type":"CONTAINS","extra":"Wiki contains code snippet: backend/app/workers/scheduler.py#1-189","gmt_create":"2026-05-23T15:19:55.838143+08:00","gmt_modified":"2026-05-23T15:19:55.838143+08:00"},{"id":2141,"source_id":"5cbb1e3f112aeba62a14b0b8999fc0f5","target_id":"1aa2eb624a63acddcd9638630606b2e9","source_type":"SOURCE_FILE","target_type":"CODE_SNIPPET","relationship_type":"CONTAINS","extra":"Source file contains code snippet: 1-189","gmt_create":"2026-05-23T15:19:55.838668+08:00","gmt_modified":"2026-05-23T15:19:55.838668+08:00"},{"id":2142,"source_id":"98909ecc-fceb-4ab7-a26f-741838eb2e50","target_id":"13f6ca76349ef86ae756bb519f122bc5","source_type":"WIKI_ITEM","target_type":"CODE_SNIPPET","relationship_type":"CONTAINS","extra":"Wiki contains code snippet: backend/alembic.ini#1-150","gmt_create":"2026-05-23T15:19:55.839524+08:00","gmt_modified":"2026-05-23T15:19:55.839524+08:00"},{"id":2143,"source_id":"98909ecc-fceb-4ab7-a26f-741838eb2e50","target_id":"211463f5b49610f09594c40c0a235943","source_type":"WIKI_ITEM","target_type":"CODE_SNIPPET","relationship_type":"CONTAINS","extra":"Wiki contains code snippet: backend/alembic/env.py#1-89","gmt_create":"2026-05-23T15:19:55.840322+08:00","gmt_modified":"2026-05-23T15:19:55.840322+08:00"},{"id":2144,"source_id":"98909ecc-fceb-4ab7-a26f-741838eb2e50","target_id":"a03d722c5d84b49db41742b78679a2f8","source_type":"WIKI_ITEM","target_type":"CODE_SNIPPET","relationship_type":"CONTAINS","extra":"Wiki contains code snippet: docker-compose.yml#36-66","gmt_create":"2026-05-23T15:19:55.848078+08:00","gmt_modified":"2026-05-23T15:19:55.848078+08:00"},{"id":2145,"source_id":"fc6242433ae9506bcc0bf4cb0dce1413","target_id":"a03d722c5d84b49db41742b78679a2f8","source_type":"SOURCE_FILE","target_type":"CODE_SNIPPET","relationship_type":"CONTAINS","extra":"Source file contains code snippet: 36-66","gmt_create":"2026-05-23T15:19:55.848739+08:00","gmt_modified":"2026-05-23T15:19:55.848739+08:00"},{"id":2146,"source_id":"98909ecc-fceb-4ab7-a26f-741838eb2e50","target_id":"f7e662afe370f458b73886fe90709a23","source_type":"WIKI_ITEM","target_type":"CODE_SNIPPET","relationship_type":"CONTAINS","extra":"Wiki contains code snippet: backend/app/main.py#97-100","gmt_create":"2026-05-23T15:19:55.849586+08:00","gmt_modified":"2026-05-23T15:19:55.849586+08:00"},{"id":2147,"source_id":"9228ff67d4c757a85d9421b71f4b29f5","target_id":"f7e662afe370f458b73886fe90709a23","source_type":"SOURCE_FILE","target_type":"CODE_SNIPPET","relationship_type":"CONTAINS","extra":"Source file contains code snippet: 97-100","gmt_create":"2026-05-23T15:19:55.850238+08:00","gmt_modified":"2026-05-23T15:19:55.850238+08:00"},{"id":2148,"source_id":"98909ecc-fceb-4ab7-a26f-741838eb2e50","target_id":"50925c15ef4105b22c55cd16d44103a1","source_type":"WIKI_ITEM","target_type":"CODE_SNIPPET","relationship_type":"CONTAINS","extra":"Wiki contains code snippet: backend/app/main.py#33-45","gmt_create":"2026-05-23T15:19:55.851594+08:00","gmt_modified":"2026-05-23T15:19:55.851594+08:00"},{"id":2149,"source_id":"9228ff67d4c757a85d9421b71f4b29f5","target_id":"50925c15ef4105b22c55cd16d44103a1","source_type":"SOURCE_FILE","target_type":"CODE_SNIPPET","relationship_type":"CONTAINS","extra":"Source file contains code snippet: 33-45","gmt_create":"2026-05-23T15:19:55.852082+08:00","gmt_modified":"2026-05-23T15:19:55.852083+08:00"},{"id":2150,"source_id":"98909ecc-fceb-4ab7-a26f-741838eb2e50","target_id":"6d4024210922cde4cb5f7944996640c5","source_type":"WIKI_ITEM","target_type":"CODE_SNIPPET","relationship_type":"CONTAINS","extra":"Wiki contains code snippet: backend/app/config.py#12-14","gmt_create":"2026-05-23T15:19:55.852831+08:00","gmt_modified":"2026-05-23T15:19:55.852832+08:00"},{"id":2151,"source_id":"9ff19022ef915615911280e3c49ed44b","target_id":"6d4024210922cde4cb5f7944996640c5","source_type":"SOURCE_FILE","target_type":"CODE_SNIPPET","relationship_type":"CONTAINS","extra":"Source file contains code snippet: 12-14","gmt_create":"2026-05-23T15:19:55.853566+08:00","gmt_modified":"2026-05-23T15:19:55.853566+08:00"},{"id":2152,"source_id":"98909ecc-fceb-4ab7-a26f-741838eb2e50","target_id":"b32f57d9055ac4c655dfc976b1fd51a4","source_type":"WIKI_ITEM","target_type":"CODE_SNIPPET","relationship_type":"CONTAINS","extra":"Wiki contains code snippet: backend/app/workers/scheduler.py#33-51","gmt_create":"2026-05-23T15:19:55.855342+08:00","gmt_modified":"2026-05-23T15:19:55.855342+08:00"},{"id":2153,"source_id":"5cbb1e3f112aeba62a14b0b8999fc0f5","target_id":"b32f57d9055ac4c655dfc976b1fd51a4","source_type":"SOURCE_FILE","target_type":"CODE_SNIPPET","relationship_type":"CONTAINS","extra":"Source file contains code snippet: 33-51","gmt_create":"2026-05-23T15:19:55.855957+08:00","gmt_modified":"2026-05-23T15:19:55.855957+08:00"},{"id":2154,"source_id":"98909ecc-fceb-4ab7-a26f-741838eb2e50","target_id":"6171fd1748ad5189394ba670000e7e75","source_type":"WIKI_ITEM","target_type":"CODE_SNIPPET","relationship_type":"CONTAINS","extra":"Wiki contains code snippet: frontend/package.json#1-45","gmt_create":"2026-05-23T15:19:55.864842+08:00","gmt_modified":"2026-05-23T15:19:55.864842+08:00"},{"id":2155,"source_id":"98909ecc-fceb-4ab7-a26f-741838eb2e50","target_id":"60f56d5de44cd7f96dbf71d74290910d","source_type":"WIKI_ITEM","target_type":"CODE_SNIPPET","relationship_type":"CONTAINS","extra":"Wiki contains code snippet: backend/app/main.py#53-63","gmt_create":"2026-05-23T15:19:55.865757+08:00","gmt_modified":"2026-05-23T15:19:55.865758+08:00"},{"id":2156,"source_id":"9228ff67d4c757a85d9421b71f4b29f5","target_id":"60f56d5de44cd7f96dbf71d74290910d","source_type":"SOURCE_FILE","target_type":"CODE_SNIPPET","relationship_type":"CONTAINS","extra":"Source file contains code snippet: 53-63","gmt_create":"2026-05-23T15:19:55.866492+08:00","gmt_modified":"2026-05-23T15:19:55.866493+08:00"},{"id":2157,"source_id":"98909ecc-fceb-4ab7-a26f-741838eb2e50","target_id":"6281fff17a86ec1895c64d87c2ae7fb1","source_type":"WIKI_ITEM","target_type":"CODE_SNIPPET","relationship_type":"CONTAINS","extra":"Wiki contains code snippet: backend/app/models/query.py#1-55","gmt_create":"2026-05-23T15:19:55.867761+08:00","gmt_modified":"2026-05-23T15:19:55.867762+08:00"},{"id":2158,"source_id":"98909ecc-fceb-4ab7-a26f-741838eb2e50","target_id":"0d92cb154d0e27b75793e9a25e3211c4","source_type":"WIKI_ITEM","target_type":"CODE_SNIPPET","relationship_type":"CONTAINS","extra":"Wiki contains code snippet: backend/alembic.ini#86-89","gmt_create":"2026-05-23T15:19:55.869696+08:00","gmt_modified":"2026-05-23T15:19:55.869696+08:00"},{"id":2159,"source_id":"50f2e6bdc4a79e69bd43ea8d6fec67fe","target_id":"0d92cb154d0e27b75793e9a25e3211c4","source_type":"SOURCE_FILE","target_type":"CODE_SNIPPET","relationship_type":"CONTAINS","extra":"Source file contains code snippet: 86-89","gmt_create":"2026-05-23T15:19:55.870233+08:00","gmt_modified":"2026-05-23T15:19:55.870233+08:00"},{"id":2160,"source_id":"98909ecc-fceb-4ab7-a26f-741838eb2e50","target_id":"5688471e2418628ac2a6409451708d06","source_type":"WIKI_ITEM","target_type":"CODE_SNIPPET","relationship_type":"CONTAINS","extra":"Wiki contains code snippet: backend/app/api/auth.py#1-115","gmt_create":"2026-05-23T15:19:55.873845+08:00","gmt_modified":"2026-05-23T15:19:55.873845+08:00"},{"id":2161,"source_id":"98909ecc-fceb-4ab7-a26f-741838eb2e50","target_id":"13b13aa0fd51de34b0cfb27187df0eb0","source_type":"WIKI_ITEM","target_type":"CODE_SNIPPET","relationship_type":"CONTAINS","extra":"Wiki contains code snippet: backend/app/config.py#14","gmt_create":"2026-05-23T15:19:55.877176+08:00","gmt_modified":"2026-05-23T15:19:55.877176+08:00"},{"id":2162,"source_id":"9ff19022ef915615911280e3c49ed44b","target_id":"13b13aa0fd51de34b0cfb27187df0eb0","source_type":"SOURCE_FILE","target_type":"CODE_SNIPPET","relationship_type":"CONTAINS","extra":"Source file contains code snippet: 14","gmt_create":"2026-05-23T15:19:55.878341+08:00","gmt_modified":"2026-05-23T15:19:55.878341+08:00"},{"id":2163,"source_id":"98909ecc-fceb-4ab7-a26f-741838eb2e50","target_id":"00502fc9ffc15147665f96f056735d74","source_type":"WIKI_ITEM","target_type":"CODE_SNIPPET","relationship_type":"CONTAINS","extra":"Wiki contains code snippet: backend/requirements.txt#1-42","gmt_create":"2026-05-23T15:19:55.882118+08:00","gmt_modified":"2026-05-23T15:19:55.882118+08:00"},{"id":2164,"source_id":"98909ecc-fceb-4ab7-a26f-741838eb2e50","target_id":"6c080aba7d0e611bd4e7f268835b630f","source_type":"WIKI_ITEM","target_type":"CODE_SNIPPET","relationship_type":"CONTAINS","extra":"Wiki contains code snippet: backend/app/middleware/logging_middleware.py#1-24","gmt_create":"2026-05-23T15:19:55.885798+08:00","gmt_modified":"2026-05-23T15:19:55.885798+08:00"},{"id":2165,"source_id":"98909ecc-fceb-4ab7-a26f-741838eb2e50","target_id":"a7bba55ddc4dd5d215e881e8432d83ea","source_type":"WIKI_ITEM","target_type":"CODE_SNIPPET","relationship_type":"CONTAINS","extra":"Wiki contains code snippet: backend/app/middleware/rate_limit.py#1-83","gmt_create":"2026-05-23T15:19:55.887374+08:00","gmt_modified":"2026-05-23T15:19:55.887374+08:00"},{"id":2166,"source_id":"98909ecc-fceb-4ab7-a26f-741838eb2e50","target_id":"ef31f4aa4fbd1b6ff76eba467b757a04","source_type":"WIKI_ITEM","target_type":"CODE_SNIPPET","relationship_type":"CONTAINS","extra":"Wiki contains code snippet: backend/app/middleware/rate_limit.py#34-69","gmt_create":"2026-05-23T15:19:55.889039+08:00","gmt_modified":"2026-05-23T15:19:55.889039+08:00"},{"id":2167,"source_id":"98909ecc-fceb-4ab7-a26f-741838eb2e50","target_id":"dfaa01739b500883c182fe0ee7b38f02","source_type":"WIKI_ITEM","target_type":"CODE_SNIPPET","relationship_type":"CONTAINS","extra":"Wiki contains code snippet: backend/requirements.txt#35-42","gmt_create":"2026-05-23T15:19:55.889934+08:00","gmt_modified":"2026-05-23T15:19:55.889934+08:00"},{"id":2168,"source_id":"a26ee01cf41da3b956e1650448c156fa","target_id":"dfaa01739b500883c182fe0ee7b38f02","source_type":"SOURCE_FILE","target_type":"CODE_SNIPPET","relationship_type":"CONTAINS","extra":"Source file contains code snippet: 35-42","gmt_create":"2026-05-23T15:19:55.890525+08:00","gmt_modified":"2026-05-23T15:19:55.890525+08:00"},{"id":2169,"source_id":"98909ecc-fceb-4ab7-a26f-741838eb2e50","target_id":"1a78f5574add6d07a1d7c947dba3f23d","source_type":"WIKI_ITEM","target_type":"CODE_SNIPPET","relationship_type":"CONTAINS","extra":"Wiki contains code snippet: backend/alembic.ini#115-150","gmt_create":"2026-05-23T15:19:55.899548+08:00","gmt_modified":"2026-05-23T15:19:55.899548+08:00"},{"id":2170,"source_id":"98909ecc-fceb-4ab7-a26f-741838eb2e50","target_id":"ffb7b526b388c92bf932d701fee71671","source_type":"WIKI_ITEM","target_type":"CODE_SNIPPET","relationship_type":"CONTAINS","extra":"Wiki contains code snippet: backend/alembic/env.py#64-89","gmt_create":"2026-05-23T15:19:55.90053+08:00","gmt_modified":"2026-05-23T15:19:55.90053+08:00"},{"id":2171,"source_id":"a680d4819f5da57fe9fa0e6bc708f380","target_id":"ffb7b526b388c92bf932d701fee71671","source_type":"SOURCE_FILE","target_type":"CODE_SNIPPET","relationship_type":"CONTAINS","extra":"Source file contains code snippet: 64-89","gmt_create":"2026-05-23T15:19:55.901127+08:00","gmt_modified":"2026-05-23T15:19:55.901128+08:00"},{"id":2172,"source_id":"98909ecc-fceb-4ab7-a26f-741838eb2e50","target_id":"d820e2daf2ea133a7aa17cdc475e44a4","source_type":"WIKI_ITEM","target_type":"CODE_SNIPPET","relationship_type":"CONTAINS","extra":"Wiki contains code snippet: tests/test_auth.py#1-104","gmt_create":"2026-05-23T15:19:55.902141+08:00","gmt_modified":"2026-05-23T15:19:55.902141+08:00"},{"id":2173,"source_id":"3af3bb9e-4d99-4dc3-b1ed-2686db385c26","target_id":"aaf5bce6be82d2f947bfa5c1806de452","source_type":"WIKI_ITEM","target_type":"SOURCE_FILE","relationship_type":"REFERENCED_BY","extra":"Wiki references source file: frontend/package.json","gmt_create":"2026-05-23T15:22:58.410448+08:00","gmt_modified":"2026-05-23T15:22:58.410448+08:00"},{"id":2174,"source_id":"3af3bb9e-4d99-4dc3-b1ed-2686db385c26","target_id":"955e1dfe57f0a9a8e900383eb7641ba1","source_type":"WIKI_ITEM","target_type":"SOURCE_FILE","relationship_type":"REFERENCED_BY","extra":"Wiki references source file: frontend/next.config.mjs","gmt_create":"2026-05-23T15:22:58.416474+08:00","gmt_modified":"2026-05-23T15:22:58.416474+08:00"},{"id":2175,"source_id":"3af3bb9e-4d99-4dc3-b1ed-2686db385c26","target_id":"01056dad8851d3e9bd532eb4cab33792","source_type":"WIKI_ITEM","target_type":"SOURCE_FILE","relationship_type":"REFERENCED_BY","extra":"Wiki references source file: frontend/tailwind.config.ts","gmt_create":"2026-05-23T15:22:58.417787+08:00","gmt_modified":"2026-05-23T15:22:58.417788+08:00"},{"id":2176,"source_id":"3af3bb9e-4d99-4dc3-b1ed-2686db385c26","target_id":"12e2c3d7b9a92dc44a6ee29b85e10df6","source_type":"WIKI_ITEM","target_type":"SOURCE_FILE","relationship_type":"REFERENCED_BY","extra":"Wiki references source file: frontend/app/layout.tsx","gmt_create":"2026-05-23T15:22:58.419844+08:00","gmt_modified":"2026-05-23T15:22:58.419845+08:00"},{"id":2177,"source_id":"3af3bb9e-4d99-4dc3-b1ed-2686db385c26","target_id":"546e01c5f73aaf5140eee922f4b9a441","source_type":"WIKI_ITEM","target_type":"SOURCE_FILE","relationship_type":"REFERENCED_BY","extra":"Wiki references source file: frontend/components/providers.tsx","gmt_create":"2026-05-23T15:22:58.42185+08:00","gmt_modified":"2026-05-23T15:22:58.42185+08:00"},{"id":2178,"source_id":"3af3bb9e-4d99-4dc3-b1ed-2686db385c26","target_id":"5800a08224424ebced854d06365f6d44","source_type":"WIKI_ITEM","target_type":"SOURCE_FILE","relationship_type":"REFERENCED_BY","extra":"Wiki references source file: frontend/app/(auth","gmt_create":"2026-05-23T15:22:58.422703+08:00","gmt_modified":"2026-05-23T15:22:58.422703+08:00"},{"id":2179,"source_id":"3af3bb9e-4d99-4dc3-b1ed-2686db385c26","target_id":"2a1c745c7b3fb7f600596be3d979bba1","source_type":"WIKI_ITEM","target_type":"SOURCE_FILE","relationship_type":"REFERENCED_BY","extra":"Wiki references source file: frontend/app/(dashboard","gmt_create":"2026-05-23T15:22:58.423387+08:00","gmt_modified":"2026-05-23T15:22:58.423387+08:00"},{"id":2180,"source_id":"3af3bb9e-4d99-4dc3-b1ed-2686db385c26","target_id":"d2c1984414de6856ed5b3873c661b712","source_type":"WIKI_ITEM","target_type":"SOURCE_FILE","relationship_type":"REFERENCED_BY","extra":"Wiki references source file: frontend/lib/auth.ts","gmt_create":"2026-05-23T15:22:58.424103+08:00","gmt_modified":"2026-05-23T15:22:58.424103+08:00"},{"id":2181,"source_id":"3af3bb9e-4d99-4dc3-b1ed-2686db385c26","target_id":"b1d80d63eae8fd5e1bdfeee3c6bc9594","source_type":"WIKI_ITEM","target_type":"SOURCE_FILE","relationship_type":"REFERENCED_BY","extra":"Wiki references source file: frontend/types/next-auth.d.ts","gmt_create":"2026-05-23T15:22:58.424779+08:00","gmt_modified":"2026-05-23T15:22:58.42478+08:00"},{"id":2182,"source_id":"3af3bb9e-4d99-4dc3-b1ed-2686db385c26","target_id":"5d7886d0dc99f81073a578b8aefdd375","source_type":"WIKI_ITEM","target_type":"SOURCE_FILE","relationship_type":"REFERENCED_BY","extra":"Wiki references source file: frontend/lib/api.ts","gmt_create":"2026-05-23T15:22:58.426166+08:00","gmt_modified":"2026-05-23T15:22:58.426166+08:00"},{"id":2183,"source_id":"3af3bb9e-4d99-4dc3-b1ed-2686db385c26","target_id":"ac1acbc54c49ee1de13369f6c6827568","source_type":"WIKI_ITEM","target_type":"SOURCE_FILE","relationship_type":"REFERENCED_BY","extra":"Wiki references source file: frontend/components/ui/button.tsx","gmt_create":"2026-05-23T15:22:58.434863+08:00","gmt_modified":"2026-05-23T15:22:58.434864+08:00"},{"id":2184,"source_id":"3af3bb9e-4d99-4dc3-b1ed-2686db385c26","target_id":"eca13a610badfc5ffc6210827fb96991","source_type":"WIKI_ITEM","target_type":"SOURCE_FILE","relationship_type":"REFERENCED_BY","extra":"Wiki references source file: frontend/components/layout/header.tsx","gmt_create":"2026-05-23T15:22:58.435989+08:00","gmt_modified":"2026-05-23T15:22:58.435989+08:00"},{"id":2185,"source_id":"3af3bb9e-4d99-4dc3-b1ed-2686db385c26","target_id":"18a0651d895fba9bb4e0c0229459efdc","source_type":"WIKI_ITEM","target_type":"SOURCE_FILE","relationship_type":"REFERENCED_BY","extra":"Wiki references source file: frontend/components/layout/sidebar.tsx","gmt_create":"2026-05-23T15:22:58.437626+08:00","gmt_modified":"2026-05-23T15:22:58.437626+08:00"},{"id":2186,"source_id":"3af3bb9e-4d99-4dc3-b1ed-2686db385c26","target_id":"beb87ab5aad9532647e9dbd2db7ef587","source_type":"WIKI_ITEM","target_type":"SOURCE_FILE","relationship_type":"REFERENCED_BY","extra":"Wiki references source file: frontend/components/ui/tabs.tsx","gmt_create":"2026-05-23T15:22:58.438536+08:00","gmt_modified":"2026-05-23T15:22:58.438537+08:00"},{"id":2187,"source_id":"3af3bb9e-4d99-4dc3-b1ed-2686db385c26","target_id":"facea1f00ec72e00f774d0839fee7131","source_type":"WIKI_ITEM","target_type":"SOURCE_FILE","relationship_type":"REFERENCED_BY","extra":"Wiki references source file: /Users/Chiguyong/Code/GEO#wiki#main#wiki#zh/[app/api/auth/[...nextauth]/route.ts](file:/frontend/app/api/auth/[...nextauth]/route.ts)","gmt_create":"2026-05-23T15:22:58.439449+08:00","gmt_modified":"2026-05-23T15:22:58.439449+08:00"},{"id":2188,"source_id":"3af3bb9e-4d99-4dc3-b1ed-2686db385c26","target_id":"9ea18740e615a926960e829e8c583175","source_type":"WIKI_ITEM","target_type":"SOURCE_FILE","relationship_type":"REFERENCED_BY","extra":"Wiki references source file: frontend/playwright.config.ts","gmt_create":"2026-05-23T15:22:58.440921+08:00","gmt_modified":"2026-05-23T15:22:58.440921+08:00"},{"id":2189,"source_id":"3af3bb9e-4d99-4dc3-b1ed-2686db385c26","target_id":"6f639c813a6c2a20c0c05939222f7475","source_type":"WIKI_ITEM","target_type":"SOURCE_FILE","relationship_type":"REFERENCED_BY","extra":"Wiki references source file: frontend/e2e/tests/dashboard-health.spec.ts","gmt_create":"2026-05-23T15:22:58.442234+08:00","gmt_modified":"2026-05-23T15:22:58.442234+08:00"},{"id":2190,"source_id":"3af3bb9e-4d99-4dc3-b1ed-2686db385c26","target_id":"a3a308292fda7895bf49445c417df345","source_type":"WIKI_ITEM","target_type":"SOURCE_FILE","relationship_type":"REFERENCED_BY","extra":"Wiki references source file: frontend/e2e/tests/login.spec.ts","gmt_create":"2026-05-23T15:22:58.443488+08:00","gmt_modified":"2026-05-23T15:22:58.443488+08:00"},{"id":2191,"source_id":"3af3bb9e-4d99-4dc3-b1ed-2686db385c26","target_id":"4edcf9364f826cf2a7b686447777cc07","source_type":"WIKI_ITEM","target_type":"SOURCE_FILE","relationship_type":"REFERENCED_BY","extra":"Wiki references source file: frontend/e2e/pages/dashboard.page.ts","gmt_create":"2026-05-23T15:22:58.446367+08:00","gmt_modified":"2026-05-23T15:22:58.446368+08:00"},{"id":2192,"source_id":"3af3bb9e-4d99-4dc3-b1ed-2686db385c26","target_id":"f6784e54bb91b7daa9c76653ba1b2c75","source_type":"WIKI_ITEM","target_type":"SOURCE_FILE","relationship_type":"REFERENCED_BY","extra":"Wiki references source file: frontend/e2e/pages/login.page.ts","gmt_create":"2026-05-23T15:22:58.450857+08:00","gmt_modified":"2026-05-23T15:22:58.450858+08:00"},{"id":2193,"source_id":"3af3bb9e-4d99-4dc3-b1ed-2686db385c26","target_id":"1fa69729b52f34bc96b687a395501734","source_type":"WIKI_ITEM","target_type":"SOURCE_FILE","relationship_type":"REFERENCED_BY","extra":"Wiki references source file: frontend/components/business/index.ts","gmt_create":"2026-05-23T15:22:58.452085+08:00","gmt_modified":"2026-05-23T15:22:58.452086+08:00"},{"id":2194,"source_id":"3af3bb9e-4d99-4dc3-b1ed-2686db385c26","target_id":"ebcf5e1a8abb3ccc9196e5749461f46b","source_type":"WIKI_ITEM","target_type":"SOURCE_FILE","relationship_type":"REFERENCED_BY","extra":"Wiki references source file: frontend/components/business/agent-status-card.tsx","gmt_create":"2026-05-23T15:22:58.45352+08:00","gmt_modified":"2026-05-23T15:22:58.453521+08:00"},{"id":2195,"source_id":"3af3bb9e-4d99-4dc3-b1ed-2686db385c26","target_id":"0da5aaee978edabdfebab3a8e67d803f","source_type":"WIKI_ITEM","target_type":"SOURCE_FILE","relationship_type":"REFERENCED_BY","extra":"Wiki references source file: frontend/components/business/alert-card.tsx","gmt_create":"2026-05-23T15:22:58.454283+08:00","gmt_modified":"2026-05-23T15:22:58.454284+08:00"},{"id":2196,"source_id":"3af3bb9e-4d99-4dc3-b1ed-2686db385c26","target_id":"0130bb8ebb0800faff59f36c5625b7f7","source_type":"WIKI_ITEM","target_type":"SOURCE_FILE","relationship_type":"REFERENCED_BY","extra":"Wiki references source file: frontend/components/dashboard/index.ts","gmt_create":"2026-05-23T15:22:58.45504+08:00","gmt_modified":"2026-05-23T15:22:58.455041+08:00"},{"id":2197,"source_id":"3af3bb9e-4d99-4dc3-b1ed-2686db385c26","target_id":"8a466b0c6eac2ccb54c5da7e13854646","source_type":"WIKI_ITEM","target_type":"CODE_SNIPPET","relationship_type":"CONTAINS","extra":"Wiki contains code snippet: frontend/app/layout.tsx#1-37","gmt_create":"2026-05-23T15:22:58.456055+08:00","gmt_modified":"2026-05-23T15:22:58.456055+08:00"},{"id":2198,"source_id":"3af3bb9e-4d99-4dc3-b1ed-2686db385c26","target_id":"fd18328b6582e68c30b130b912891992","source_type":"WIKI_ITEM","target_type":"CODE_SNIPPET","relationship_type":"CONTAINS","extra":"Wiki contains code snippet: frontend/components/providers.tsx#1-9","gmt_create":"2026-05-23T15:22:58.457635+08:00","gmt_modified":"2026-05-23T15:22:58.457635+08:00"},{"id":2199,"source_id":"3af3bb9e-4d99-4dc3-b1ed-2686db385c26","target_id":"dc735ee4a0f12140bcee122a67f4a13b","source_type":"WIKI_ITEM","target_type":"CODE_SNIPPET","relationship_type":"CONTAINS","extra":"Wiki contains code snippet: frontend/components/layout/sidebar.tsx#1-63","gmt_create":"2026-05-23T15:22:58.459345+08:00","gmt_modified":"2026-05-23T15:22:58.459345+08:00"},{"id":2200,"source_id":"3af3bb9e-4d99-4dc3-b1ed-2686db385c26","target_id":"bd3042a8d9b602334720b0d7b4e8ab3d","source_type":"WIKI_ITEM","target_type":"CODE_SNIPPET","relationship_type":"CONTAINS","extra":"Wiki contains code snippet: frontend/components/ui/tabs.tsx#1-56","gmt_create":"2026-05-23T15:22:58.464575+08:00","gmt_modified":"2026-05-23T15:22:58.464575+08:00"},{"id":2201,"source_id":"3af3bb9e-4d99-4dc3-b1ed-2686db385c26","target_id":"8b7ecdb77bf7d73f30b64d82972bf1f5","source_type":"WIKI_ITEM","target_type":"CODE_SNIPPET","relationship_type":"CONTAINS","extra":"Wiki contains code snippet: frontend/tailwind.config.ts#1-121","gmt_create":"2026-05-23T15:22:58.490873+08:00","gmt_modified":"2026-05-23T15:22:58.490873+08:00"},{"id":2202,"source_id":"01056dad8851d3e9bd532eb4cab33792","target_id":"8b7ecdb77bf7d73f30b64d82972bf1f5","source_type":"SOURCE_FILE","target_type":"CODE_SNIPPET","relationship_type":"CONTAINS","extra":"Source file contains code snippet: 1-121","gmt_create":"2026-05-23T15:22:58.491953+08:00","gmt_modified":"2026-05-23T15:22:58.491954+08:00"},{"id":2203,"source_id":"3af3bb9e-4d99-4dc3-b1ed-2686db385c26","target_id":"f990ecd63842b3ab82f5b8c8dcde2a6b","source_type":"WIKI_ITEM","target_type":"CODE_SNIPPET","relationship_type":"CONTAINS","extra":"Wiki contains code snippet: frontend/next.config.mjs#1-5","gmt_create":"2026-05-23T15:22:58.493007+08:00","gmt_modified":"2026-05-23T15:22:58.493007+08:00"},{"id":2204,"source_id":"3af3bb9e-4d99-4dc3-b1ed-2686db385c26","target_id":"a8bbf13a4b60cc33fd76c99c6bd6b36f","source_type":"WIKI_ITEM","target_type":"CODE_SNIPPET","relationship_type":"CONTAINS","extra":"Wiki contains code snippet: frontend/playwright.config.ts#1-39","gmt_create":"2026-05-23T15:22:58.494166+08:00","gmt_modified":"2026-05-23T15:22:58.494166+08:00"},{"id":2205,"source_id":"9ea18740e615a926960e829e8c583175","target_id":"a8bbf13a4b60cc33fd76c99c6bd6b36f","source_type":"SOURCE_FILE","target_type":"CODE_SNIPPET","relationship_type":"CONTAINS","extra":"Source file contains code snippet: 1-39","gmt_create":"2026-05-23T15:22:58.496502+08:00","gmt_modified":"2026-05-23T15:22:58.496503+08:00"},{"id":2206,"source_id":"3af3bb9e-4d99-4dc3-b1ed-2686db385c26","target_id":"8ca9b37cfe665abc053e0258b0d036d4","source_type":"WIKI_ITEM","target_type":"CODE_SNIPPET","relationship_type":"CONTAINS","extra":"Wiki contains code snippet: frontend/components/business/index.ts#1-29","gmt_create":"2026-05-23T15:22:58.498251+08:00","gmt_modified":"2026-05-23T15:22:58.498251+08:00"},{"id":2207,"source_id":"1fa69729b52f34bc96b687a395501734","target_id":"8ca9b37cfe665abc053e0258b0d036d4","source_type":"SOURCE_FILE","target_type":"CODE_SNIPPET","relationship_type":"CONTAINS","extra":"Source file contains code snippet: 1-29","gmt_create":"2026-05-23T15:22:58.499086+08:00","gmt_modified":"2026-05-23T15:22:58.499086+08:00"},{"id":2208,"source_id":"3af3bb9e-4d99-4dc3-b1ed-2686db385c26","target_id":"40325db1cb621a9af027150a8c5cf8e9","source_type":"WIKI_ITEM","target_type":"CODE_SNIPPET","relationship_type":"CONTAINS","extra":"Wiki contains code snippet: frontend/lib/auth.ts#1-73","gmt_create":"2026-05-23T15:22:58.504658+08:00","gmt_modified":"2026-05-23T15:22:58.504658+08:00"},{"id":2209,"source_id":"3af3bb9e-4d99-4dc3-b1ed-2686db385c26","target_id":"d5efa0fbc545b778dd913854d860c502","source_type":"WIKI_ITEM","target_type":"CODE_SNIPPET","relationship_type":"CONTAINS","extra":"Wiki contains code snippet: frontend/types/next-auth.d.ts#1-29","gmt_create":"2026-05-23T15:22:58.506489+08:00","gmt_modified":"2026-05-23T15:22:58.506489+08:00"},{"id":2210,"source_id":"3af3bb9e-4d99-4dc3-b1ed-2686db385c26","target_id":"a9fb75d1fdb833a11b36bc7b298f19be","source_type":"WIKI_ITEM","target_type":"CODE_SNIPPET","relationship_type":"CONTAINS","extra":"Wiki contains code snippet: frontend/lib/api.ts#1-154","gmt_create":"2026-05-23T15:22:58.507878+08:00","gmt_modified":"2026-05-23T15:22:58.507878+08:00"},{"id":2211,"source_id":"3af3bb9e-4d99-4dc3-b1ed-2686db385c26","target_id":"95be577a89fbeb02578e4c3718c6ec86","source_type":"WIKI_ITEM","target_type":"CODE_SNIPPET","relationship_type":"CONTAINS","extra":"Wiki contains code snippet: frontend/components/ui/button.tsx#1-57","gmt_create":"2026-05-23T15:22:58.509084+08:00","gmt_modified":"2026-05-23T15:22:58.509084+08:00"},{"id":2212,"source_id":"3af3bb9e-4d99-4dc3-b1ed-2686db385c26","target_id":"0d903468b55bdc63cc7e25a87a89c522","source_type":"WIKI_ITEM","target_type":"CODE_SNIPPET","relationship_type":"CONTAINS","extra":"Wiki contains code snippet: frontend/components/layout/header.tsx#1-30","gmt_create":"2026-05-23T15:22:58.510622+08:00","gmt_modified":"2026-05-23T15:22:58.510622+08:00"},{"id":2213,"source_id":"3af3bb9e-4d99-4dc3-b1ed-2686db385c26","target_id":"76edaefb3ec9610b238b448a797795a1","source_type":"WIKI_ITEM","target_type":"CODE_SNIPPET","relationship_type":"CONTAINS","extra":"Wiki contains code snippet: frontend/e2e/tests/dashboard-health.spec.ts#1-264","gmt_create":"2026-05-23T15:22:58.525186+08:00","gmt_modified":"2026-05-23T15:22:58.525186+08:00"},{"id":2214,"source_id":"6f639c813a6c2a20c0c05939222f7475","target_id":"76edaefb3ec9610b238b448a797795a1","source_type":"SOURCE_FILE","target_type":"CODE_SNIPPET","relationship_type":"CONTAINS","extra":"Source file contains code snippet: 1-264","gmt_create":"2026-05-23T15:22:58.526562+08:00","gmt_modified":"2026-05-23T15:22:58.526562+08:00"},{"id":2215,"source_id":"3af3bb9e-4d99-4dc3-b1ed-2686db385c26","target_id":"c413ca9685496f180a8e469f24ed082f","source_type":"WIKI_ITEM","target_type":"CODE_SNIPPET","relationship_type":"CONTAINS","extra":"Wiki contains code snippet: frontend/e2e/tests/login.spec.ts#1-126","gmt_create":"2026-05-23T15:22:58.531057+08:00","gmt_modified":"2026-05-23T15:22:58.531057+08:00"},{"id":2216,"source_id":"a3a308292fda7895bf49445c417df345","target_id":"c413ca9685496f180a8e469f24ed082f","source_type":"SOURCE_FILE","target_type":"CODE_SNIPPET","relationship_type":"CONTAINS","extra":"Source file contains code snippet: 1-126","gmt_create":"2026-05-23T15:22:58.533317+08:00","gmt_modified":"2026-05-23T15:22:58.533318+08:00"},{"id":2217,"source_id":"3af3bb9e-4d99-4dc3-b1ed-2686db385c26","target_id":"912411178607f349a732c3e67dccf631","source_type":"WIKI_ITEM","target_type":"CODE_SNIPPET","relationship_type":"CONTAINS","extra":"Wiki contains code snippet: frontend/e2e/pages/login.page.ts#1-36","gmt_create":"2026-05-23T15:22:58.566683+08:00","gmt_modified":"2026-05-23T15:22:58.566683+08:00"},{"id":2218,"source_id":"f6784e54bb91b7daa9c76653ba1b2c75","target_id":"912411178607f349a732c3e67dccf631","source_type":"SOURCE_FILE","target_type":"CODE_SNIPPET","relationship_type":"CONTAINS","extra":"Source file contains code snippet: 1-36","gmt_create":"2026-05-23T15:22:58.567563+08:00","gmt_modified":"2026-05-23T15:22:58.567563+08:00"},{"id":2219,"source_id":"3af3bb9e-4d99-4dc3-b1ed-2686db385c26","target_id":"4f2c0f1deb411b6b716e7cd04f42a519","source_type":"WIKI_ITEM","target_type":"CODE_SNIPPET","relationship_type":"CONTAINS","extra":"Wiki contains code snippet: frontend/e2e/pages/dashboard.page.ts#1-74","gmt_create":"2026-05-23T15:22:58.568454+08:00","gmt_modified":"2026-05-23T15:22:58.568454+08:00"},{"id":2220,"source_id":"4edcf9364f826cf2a7b686447777cc07","target_id":"4f2c0f1deb411b6b716e7cd04f42a519","source_type":"SOURCE_FILE","target_type":"CODE_SNIPPET","relationship_type":"CONTAINS","extra":"Source file contains code snippet: 1-74","gmt_create":"2026-05-23T15:22:58.569119+08:00","gmt_modified":"2026-05-23T15:22:58.569119+08:00"},{"id":2221,"source_id":"3af3bb9e-4d99-4dc3-b1ed-2686db385c26","target_id":"05a55dacbbd018dc394fa656f4e06a62","source_type":"WIKI_ITEM","target_type":"CODE_SNIPPET","relationship_type":"CONTAINS","extra":"Wiki contains code snippet: frontend/components/business/agent-status-card.tsx#1-134","gmt_create":"2026-05-23T15:22:58.572525+08:00","gmt_modified":"2026-05-23T15:22:58.572525+08:00"},{"id":2222,"source_id":"ebcf5e1a8abb3ccc9196e5749461f46b","target_id":"05a55dacbbd018dc394fa656f4e06a62","source_type":"SOURCE_FILE","target_type":"CODE_SNIPPET","relationship_type":"CONTAINS","extra":"Source file contains code snippet: 1-134","gmt_create":"2026-05-23T15:22:58.573613+08:00","gmt_modified":"2026-05-23T15:22:58.573613+08:00"},{"id":2223,"source_id":"3af3bb9e-4d99-4dc3-b1ed-2686db385c26","target_id":"554c0874b68d357f426fe79db129ea9f","source_type":"WIKI_ITEM","target_type":"CODE_SNIPPET","relationship_type":"CONTAINS","extra":"Wiki contains code snippet: frontend/components/business/alert-card.tsx#1-203","gmt_create":"2026-05-23T15:22:58.574892+08:00","gmt_modified":"2026-05-23T15:22:58.574893+08:00"},{"id":2224,"source_id":"0da5aaee978edabdfebab3a8e67d803f","target_id":"554c0874b68d357f426fe79db129ea9f","source_type":"SOURCE_FILE","target_type":"CODE_SNIPPET","relationship_type":"CONTAINS","extra":"Source file contains code snippet: 1-203","gmt_create":"2026-05-23T15:22:58.576063+08:00","gmt_modified":"2026-05-23T15:22:58.576063+08:00"},{"id":2225,"source_id":"3af3bb9e-4d99-4dc3-b1ed-2686db385c26","target_id":"6171fd1748ad5189394ba670000e7e75","source_type":"WIKI_ITEM","target_type":"CODE_SNIPPET","relationship_type":"CONTAINS","extra":"Wiki contains code snippet: frontend/package.json#1-45","gmt_create":"2026-05-23T15:22:58.58128+08:00","gmt_modified":"2026-05-23T15:22:58.58128+08:00"},{"id":2226,"source_id":"1c4316a1-f1d7-46da-bcfc-ea2fa0c56110","target_id":"9228ff67d4c757a85d9421b71f4b29f5","source_type":"WIKI_ITEM","target_type":"SOURCE_FILE","relationship_type":"REFERENCED_BY","extra":"Wiki references source file: backend/app/main.py","gmt_create":"2026-05-23T15:23:21.604254+08:00","gmt_modified":"2026-05-23T15:23:21.604255+08:00"},{"id":2227,"source_id":"1c4316a1-f1d7-46da-bcfc-ea2fa0c56110","target_id":"93022c8938ce318f167277cfa65c29a7","source_type":"WIKI_ITEM","target_type":"SOURCE_FILE","relationship_type":"REFERENCED_BY","extra":"Wiki references source file: backend/app/api/auth.py","gmt_create":"2026-05-23T15:23:21.607464+08:00","gmt_modified":"2026-05-23T15:23:21.607465+08:00"},{"id":2228,"source_id":"1c4316a1-f1d7-46da-bcfc-ea2fa0c56110","target_id":"6b3d903205941aa9391dd90016e1102c","source_type":"WIKI_ITEM","target_type":"SOURCE_FILE","relationship_type":"REFERENCED_BY","extra":"Wiki references source file: backend/app/api/queries.py","gmt_create":"2026-05-23T15:23:21.609277+08:00","gmt_modified":"2026-05-23T15:23:21.609278+08:00"},{"id":2229,"source_id":"1c4316a1-f1d7-46da-bcfc-ea2fa0c56110","target_id":"7538ffe4902ab6041adb28b19844962a","source_type":"WIKI_ITEM","target_type":"SOURCE_FILE","relationship_type":"REFERENCED_BY","extra":"Wiki references source file: backend/app/api/citations.py","gmt_create":"2026-05-23T15:23:21.610461+08:00","gmt_modified":"2026-05-23T15:23:21.610461+08:00"},{"id":2230,"source_id":"1c4316a1-f1d7-46da-bcfc-ea2fa0c56110","target_id":"58901c94d975d87e652a4dc6c8dda656","source_type":"WIKI_ITEM","target_type":"SOURCE_FILE","relationship_type":"REFERENCED_BY","extra":"Wiki references source file: backend/app/api/reports.py","gmt_create":"2026-05-23T15:23:21.612527+08:00","gmt_modified":"2026-05-23T15:23:21.612528+08:00"},{"id":2231,"source_id":"1c4316a1-f1d7-46da-bcfc-ea2fa0c56110","target_id":"9c224bb80474867f8ded674babaa6e11","source_type":"WIKI_ITEM","target_type":"SOURCE_FILE","relationship_type":"REFERENCED_BY","extra":"Wiki references source file: backend/app/api/lifecycle.py","gmt_create":"2026-05-23T15:23:21.614986+08:00","gmt_modified":"2026-05-23T15:23:21.614986+08:00"},{"id":2232,"source_id":"1c4316a1-f1d7-46da-bcfc-ea2fa0c56110","target_id":"63953ee6b39f159a61963104ac06f283","source_type":"WIKI_ITEM","target_type":"SOURCE_FILE","relationship_type":"REFERENCED_BY","extra":"Wiki references source file: backend/app/api/knowledge.py","gmt_create":"2026-05-23T15:23:21.617203+08:00","gmt_modified":"2026-05-23T15:23:21.617204+08:00"},{"id":2233,"source_id":"1c4316a1-f1d7-46da-bcfc-ea2fa0c56110","target_id":"4d2f3847b7c10634733118b70a1aea0b","source_type":"WIKI_ITEM","target_type":"SOURCE_FILE","relationship_type":"REFERENCED_BY","extra":"Wiki references source file: backend/app/services/auth.py","gmt_create":"2026-05-23T15:23:21.619516+08:00","gmt_modified":"2026-05-23T15:23:21.619516+08:00"},{"id":2234,"source_id":"1c4316a1-f1d7-46da-bcfc-ea2fa0c56110","target_id":"88d22de3b2a7419868e8ae19130d860c","source_type":"WIKI_ITEM","target_type":"SOURCE_FILE","relationship_type":"REFERENCED_BY","extra":"Wiki references source file: backend/app/services/query.py","gmt_create":"2026-05-23T15:23:21.621439+08:00","gmt_modified":"2026-05-23T15:23:21.62144+08:00"},{"id":2235,"source_id":"1c4316a1-f1d7-46da-bcfc-ea2fa0c56110","target_id":"04e3926c080e795713bff683e7dc9d3e","source_type":"WIKI_ITEM","target_type":"SOURCE_FILE","relationship_type":"REFERENCED_BY","extra":"Wiki references source file: backend/app/services/citation.py","gmt_create":"2026-05-23T15:23:21.622573+08:00","gmt_modified":"2026-05-23T15:23:21.622573+08:00"},{"id":2236,"source_id":"1c4316a1-f1d7-46da-bcfc-ea2fa0c56110","target_id":"984d67382822ff587452a79f89e0d336","source_type":"WIKI_ITEM","target_type":"SOURCE_FILE","relationship_type":"REFERENCED_BY","extra":"Wiki references source file: backend/app/services/analytics/tracker.py","gmt_create":"2026-05-23T15:23:21.623927+08:00","gmt_modified":"2026-05-23T15:23:21.623928+08:00"},{"id":2237,"source_id":"1c4316a1-f1d7-46da-bcfc-ea2fa0c56110","target_id":"a0c569cd2355079f9f4045a198ddcadc","source_type":"WIKI_ITEM","target_type":"SOURCE_FILE","relationship_type":"REFERENCED_BY","extra":"Wiki references source file: backend/app/services/analytics/insights.py","gmt_create":"2026-05-23T15:23:21.625824+08:00","gmt_modified":"2026-05-23T15:23:21.625825+08:00"},{"id":2238,"source_id":"1c4316a1-f1d7-46da-bcfc-ea2fa0c56110","target_id":"45c9d96513947cae445aaaf8b58b4266","source_type":"WIKI_ITEM","target_type":"SOURCE_FILE","relationship_type":"REFERENCED_BY","extra":"Wiki references source file: backend/app/services/knowledge/rag_service.py","gmt_create":"2026-05-23T15:23:21.627901+08:00","gmt_modified":"2026-05-23T15:23:21.627902+08:00"},{"id":2239,"source_id":"1c4316a1-f1d7-46da-bcfc-ea2fa0c56110","target_id":"d9f509d2a91b503397e98066751ead0c","source_type":"WIKI_ITEM","target_type":"SOURCE_FILE","relationship_type":"REFERENCED_BY","extra":"Wiki references source file: backend/app/agent_framework/agents/__init__.py","gmt_create":"2026-05-23T15:23:21.629466+08:00","gmt_modified":"2026-05-23T15:23:21.629467+08:00"},{"id":2240,"source_id":"1c4316a1-f1d7-46da-bcfc-ea2fa0c56110","target_id":"58a2f69ec5607ac5e4ab93266534ac01","source_type":"WIKI_ITEM","target_type":"SOURCE_FILE","relationship_type":"REFERENCED_BY","extra":"Wiki references source file: backend/app/agent_framework/agents/citation_detector.py","gmt_create":"2026-05-23T15:23:21.637054+08:00","gmt_modified":"2026-05-23T15:23:21.637054+08:00"},{"id":2241,"source_id":"1c4316a1-f1d7-46da-bcfc-ea2fa0c56110","target_id":"13b8f594e7cace5c8a9255dc801dcad8","source_type":"WIKI_ITEM","target_type":"SOURCE_FILE","relationship_type":"REFERENCED_BY","extra":"Wiki references source file: backend/app/agent_framework/agents/content_generator_agent.py","gmt_create":"2026-05-23T15:23:21.63889+08:00","gmt_modified":"2026-05-23T15:23:21.63889+08:00"},{"id":2242,"source_id":"1c4316a1-f1d7-46da-bcfc-ea2fa0c56110","target_id":"750f8d79d83ee910e9d18e8a4fe37e22","source_type":"WIKI_ITEM","target_type":"SOURCE_FILE","relationship_type":"REFERENCED_BY","extra":"Wiki references source file: backend/app/agent_framework/agents/deai_agent.py","gmt_create":"2026-05-23T15:23:21.640265+08:00","gmt_modified":"2026-05-23T15:23:21.640265+08:00"},{"id":2243,"source_id":"1c4316a1-f1d7-46da-bcfc-ea2fa0c56110","target_id":"7f8c6e94ead45ad9bab8cea9a7be2123","source_type":"WIKI_ITEM","target_type":"SOURCE_FILE","relationship_type":"REFERENCED_BY","extra":"Wiki references source file: backend/app/agent_framework/agents/geo_optimizer_agent.py","gmt_create":"2026-05-23T15:23:21.642401+08:00","gmt_modified":"2026-05-23T15:23:21.642401+08:00"},{"id":2244,"source_id":"1c4316a1-f1d7-46da-bcfc-ea2fa0c56110","target_id":"609a02c9e1ccc0311885a70578b86386","source_type":"WIKI_ITEM","target_type":"SOURCE_FILE","relationship_type":"REFERENCED_BY","extra":"Wiki references source file: backend/app/agent_framework/pipeline/engine.py","gmt_create":"2026-05-23T15:23:21.643826+08:00","gmt_modified":"2026-05-23T15:23:21.643826+08:00"},{"id":2245,"source_id":"1c4316a1-f1d7-46da-bcfc-ea2fa0c56110","target_id":"43642bd7bedabd97ff2f0a902b783e4e","source_type":"WIKI_ITEM","target_type":"SOURCE_FILE","relationship_type":"REFERENCED_BY","extra":"Wiki references source file: backend/app/agent_framework/pipeline/loader.py","gmt_create":"2026-05-23T15:23:21.645751+08:00","gmt_modified":"2026-05-23T15:23:21.645752+08:00"},{"id":2246,"source_id":"1c4316a1-f1d7-46da-bcfc-ea2fa0c56110","target_id":"fcde401daccbe6de50f3829f021ecf55","source_type":"WIKI_ITEM","target_type":"SOURCE_FILE","relationship_type":"REFERENCED_BY","extra":"Wiki references source file: backend/app/agent_framework/dispatcher.py","gmt_create":"2026-05-23T15:23:21.651152+08:00","gmt_modified":"2026-05-23T15:23:21.651153+08:00"},{"id":2247,"source_id":"1c4316a1-f1d7-46da-bcfc-ea2fa0c56110","target_id":"b74caccb06844efcdb14d8324cff65c2","source_type":"WIKI_ITEM","target_type":"SOURCE_FILE","relationship_type":"REFERENCED_BY","extra":"Wiki references source file: backend/app/models/query.py","gmt_create":"2026-05-23T15:23:21.652382+08:00","gmt_modified":"2026-05-23T15:23:21.652383+08:00"},{"id":2248,"source_id":"1c4316a1-f1d7-46da-bcfc-ea2fa0c56110","target_id":"b4a81ef789630d0af6a8d50859d01bf3","source_type":"WIKI_ITEM","target_type":"SOURCE_FILE","relationship_type":"REFERENCED_BY","extra":"Wiki references source file: backend/app/models/citation_record.py","gmt_create":"2026-05-23T15:23:21.654729+08:00","gmt_modified":"2026-05-23T15:23:21.654729+08:00"},{"id":2249,"source_id":"1c4316a1-f1d7-46da-bcfc-ea2fa0c56110","target_id":"97cfe961cb7386b4022a51706ae8f5dd","source_type":"WIKI_ITEM","target_type":"SOURCE_FILE","relationship_type":"REFERENCED_BY","extra":"Wiki references source file: backend/app/models/lifecycle.py","gmt_create":"2026-05-23T15:23:21.656617+08:00","gmt_modified":"2026-05-23T15:23:21.656618+08:00"},{"id":2250,"source_id":"1c4316a1-f1d7-46da-bcfc-ea2fa0c56110","target_id":"4774aadaa8ace576601bdaa8d3e11f74","source_type":"WIKI_ITEM","target_type":"SOURCE_FILE","relationship_type":"REFERENCED_BY","extra":"Wiki references source file: backend/app/models/knowledge.py","gmt_create":"2026-05-23T15:23:21.658596+08:00","gmt_modified":"2026-05-23T15:23:21.658596+08:00"},{"id":2251,"source_id":"1c4316a1-f1d7-46da-bcfc-ea2fa0c56110","target_id":"daab5d62bc9559915da6c4bd52dcec91","source_type":"WIKI_ITEM","target_type":"SOURCE_FILE","relationship_type":"REFERENCED_BY","extra":"Wiki references source file: backend/alembic/versions/d4f6g8h0ab23_add_geo_lifecycle_tables.py","gmt_create":"2026-05-23T15:23:21.659729+08:00","gmt_modified":"2026-05-23T15:23:21.65973+08:00"},{"id":2252,"source_id":"1c4316a1-f1d7-46da-bcfc-ea2fa0c56110","target_id":"5b011956f30d4ac51420444cca8c7f08","source_type":"WIKI_ITEM","target_type":"SOURCE_FILE","relationship_type":"REFERENCED_BY","extra":"Wiki references source file: backend/workers/scheduler.py","gmt_create":"2026-05-23T15:23:21.660713+08:00","gmt_modified":"2026-05-23T15:23:21.660713+08:00"},{"id":2253,"source_id":"1c4316a1-f1d7-46da-bcfc-ea2fa0c56110","target_id":"4d4403d720ed0580f3ed57503b584eff","source_type":"WIKI_ITEM","target_type":"SOURCE_FILE","relationship_type":"REFERENCED_BY","extra":"Wiki references source file: backend/workers/citation_engine.py","gmt_create":"2026-05-23T15:23:21.663032+08:00","gmt_modified":"2026-05-23T15:23:21.663032+08:00"},{"id":2254,"source_id":"1c4316a1-f1d7-46da-bcfc-ea2fa0c56110","target_id":"8aa6b45626f9eb93a3f4fbf1d3206a38","source_type":"WIKI_ITEM","target_type":"SOURCE_FILE","relationship_type":"REFERENCED_BY","extra":"Wiki references source file: backend/workers/platforms/base.py","gmt_create":"2026-05-23T15:23:21.667901+08:00","gmt_modified":"2026-05-23T15:23:21.667901+08:00"},{"id":2255,"source_id":"1c4316a1-f1d7-46da-bcfc-ea2fa0c56110","target_id":"2a1c745c7b3fb7f600596be3d979bba1","source_type":"WIKI_ITEM","target_type":"SOURCE_FILE","relationship_type":"REFERENCED_BY","extra":"Wiki references source file: frontend/app/(dashboard","gmt_create":"2026-05-23T15:23:21.669728+08:00","gmt_modified":"2026-05-23T15:23:21.669729+08:00"},{"id":2256,"source_id":"1c4316a1-f1d7-46da-bcfc-ea2fa0c56110","target_id":"d5f2266643d2011c66e86af088ec637f","source_type":"WIKI_ITEM","target_type":"SOURCE_FILE","relationship_type":"REFERENCED_BY","extra":"Wiki references source file: frontend/components/charts/trend-chart.tsx","gmt_create":"2026-05-23T15:23:21.672962+08:00","gmt_modified":"2026-05-23T15:23:21.672963+08:00"},{"id":2257,"source_id":"1c4316a1-f1d7-46da-bcfc-ea2fa0c56110","target_id":"21ab29cd896c5703dfa3461a055c0f54","source_type":"WIKI_ITEM","target_type":"SOURCE_FILE","relationship_type":"REFERENCED_BY","extra":"Wiki references source file: frontend/lib/api/lifecycle.ts","gmt_create":"2026-05-23T15:23:21.673897+08:00","gmt_modified":"2026-05-23T15:23:21.673898+08:00"},{"id":2258,"source_id":"1c4316a1-f1d7-46da-bcfc-ea2fa0c56110","target_id":"c2747ca16b879bca0f68955534c3c4fc","source_type":"WIKI_ITEM","target_type":"CODE_SNIPPET","relationship_type":"CONTAINS","extra":"Wiki contains code snippet: backend/app/main.py#1-48","gmt_create":"2026-05-23T15:23:21.675204+08:00","gmt_modified":"2026-05-23T15:23:21.675205+08:00"},{"id":2259,"source_id":"1c4316a1-f1d7-46da-bcfc-ea2fa0c56110","target_id":"f66d9907b467b110c638bd527efd95c5","source_type":"WIKI_ITEM","target_type":"CODE_SNIPPET","relationship_type":"CONTAINS","extra":"Wiki contains code snippet: backend/app/api/auth.py#1-43","gmt_create":"2026-05-23T15:23:21.67705+08:00","gmt_modified":"2026-05-23T15:23:21.67705+08:00"},{"id":2260,"source_id":"1c4316a1-f1d7-46da-bcfc-ea2fa0c56110","target_id":"10d1e37bdc9f353c189b7a2fe79dc85e","source_type":"WIKI_ITEM","target_type":"CODE_SNIPPET","relationship_type":"CONTAINS","extra":"Wiki contains code snippet: backend/app/api/queries.py#1-86","gmt_create":"2026-05-23T15:23:21.681965+08:00","gmt_modified":"2026-05-23T15:23:21.681965+08:00"},{"id":2261,"source_id":"1c4316a1-f1d7-46da-bcfc-ea2fa0c56110","target_id":"cbd0101fa84d957bcb1baaa623c6b31c","source_type":"WIKI_ITEM","target_type":"CODE_SNIPPET","relationship_type":"CONTAINS","extra":"Wiki contains code snippet: backend/app/api/citations.py#1-78","gmt_create":"2026-05-23T15:23:21.68563+08:00","gmt_modified":"2026-05-23T15:23:21.68563+08:00"},{"id":2262,"source_id":"1c4316a1-f1d7-46da-bcfc-ea2fa0c56110","target_id":"d592b986bbd1c67a5932c77ea0341bed","source_type":"WIKI_ITEM","target_type":"CODE_SNIPPET","relationship_type":"CONTAINS","extra":"Wiki contains code snippet: backend/app/api/reports.py#1-47","gmt_create":"2026-05-23T15:23:21.688324+08:00","gmt_modified":"2026-05-23T15:23:21.688324+08:00"},{"id":2263,"source_id":"58901c94d975d87e652a4dc6c8dda656","target_id":"d592b986bbd1c67a5932c77ea0341bed","source_type":"SOURCE_FILE","target_type":"CODE_SNIPPET","relationship_type":"CONTAINS","extra":"Source file contains code snippet: 1-47","gmt_create":"2026-05-23T15:23:21.688921+08:00","gmt_modified":"2026-05-23T15:23:21.688921+08:00"},{"id":2264,"source_id":"1c4316a1-f1d7-46da-bcfc-ea2fa0c56110","target_id":"d2a5fdb4be830adefb3b04de2c90f204","source_type":"WIKI_ITEM","target_type":"CODE_SNIPPET","relationship_type":"CONTAINS","extra":"Wiki contains code snippet: backend/app/api/lifecycle.py#1-297","gmt_create":"2026-05-23T15:23:21.69046+08:00","gmt_modified":"2026-05-23T15:23:21.690461+08:00"},{"id":2265,"source_id":"9c224bb80474867f8ded674babaa6e11","target_id":"d2a5fdb4be830adefb3b04de2c90f204","source_type":"SOURCE_FILE","target_type":"CODE_SNIPPET","relationship_type":"CONTAINS","extra":"Source file contains code snippet: 1-297","gmt_create":"2026-05-23T15:23:21.691541+08:00","gmt_modified":"2026-05-23T15:23:21.691541+08:00"},{"id":2266,"source_id":"1c4316a1-f1d7-46da-bcfc-ea2fa0c56110","target_id":"23914bed50c54bb11234aa5819aec0df","source_type":"WIKI_ITEM","target_type":"CODE_SNIPPET","relationship_type":"CONTAINS","extra":"Wiki contains code snippet: backend/app/api/knowledge.py#1-502","gmt_create":"2026-05-23T15:23:21.69317+08:00","gmt_modified":"2026-05-23T15:23:21.69317+08:00"},{"id":2267,"source_id":"63953ee6b39f159a61963104ac06f283","target_id":"23914bed50c54bb11234aa5819aec0df","source_type":"SOURCE_FILE","target_type":"CODE_SNIPPET","relationship_type":"CONTAINS","extra":"Source file contains code snippet: 1-502","gmt_create":"2026-05-23T15:23:21.694345+08:00","gmt_modified":"2026-05-23T15:23:21.694345+08:00"},{"id":2268,"source_id":"1c4316a1-f1d7-46da-bcfc-ea2fa0c56110","target_id":"1a439c5fed6cfd188c646e1614d56371","source_type":"WIKI_ITEM","target_type":"CODE_SNIPPET","relationship_type":"CONTAINS","extra":"Wiki contains code snippet: backend/app/services/auth.py#1-69","gmt_create":"2026-05-23T15:23:21.698547+08:00","gmt_modified":"2026-05-23T15:23:21.698547+08:00"},{"id":2269,"source_id":"1c4316a1-f1d7-46da-bcfc-ea2fa0c56110","target_id":"916551131bd9ac8c9f9c8bb762af1fa4","source_type":"WIKI_ITEM","target_type":"CODE_SNIPPET","relationship_type":"CONTAINS","extra":"Wiki contains code snippet: backend/app/services/query.py#1-130","gmt_create":"2026-05-23T15:23:21.701218+08:00","gmt_modified":"2026-05-23T15:23:21.701218+08:00"},{"id":2270,"source_id":"1c4316a1-f1d7-46da-bcfc-ea2fa0c56110","target_id":"7c0831c17e8c65eaed9511e17ed2a2ef","source_type":"WIKI_ITEM","target_type":"CODE_SNIPPET","relationship_type":"CONTAINS","extra":"Wiki contains code snippet: backend/app/services/citation.py#1-269","gmt_create":"2026-05-23T15:23:21.703222+08:00","gmt_modified":"2026-05-23T15:23:21.703222+08:00"},{"id":2271,"source_id":"1c4316a1-f1d7-46da-bcfc-ea2fa0c56110","target_id":"2014cd6665b187d6dccb007539278ae7","source_type":"WIKI_ITEM","target_type":"CODE_SNIPPET","relationship_type":"CONTAINS","extra":"Wiki contains code snippet: backend/app/services/analytics/tracker.py#1-230","gmt_create":"2026-05-23T15:23:21.706953+08:00","gmt_modified":"2026-05-23T15:23:21.706953+08:00"},{"id":2272,"source_id":"984d67382822ff587452a79f89e0d336","target_id":"2014cd6665b187d6dccb007539278ae7","source_type":"SOURCE_FILE","target_type":"CODE_SNIPPET","relationship_type":"CONTAINS","extra":"Source file contains code snippet: 1-230","gmt_create":"2026-05-23T15:23:21.708307+08:00","gmt_modified":"2026-05-23T15:23:21.708307+08:00"},{"id":2273,"source_id":"1c4316a1-f1d7-46da-bcfc-ea2fa0c56110","target_id":"451a0398486fbfcc669dc4e50c9ad6e2","source_type":"WIKI_ITEM","target_type":"CODE_SNIPPET","relationship_type":"CONTAINS","extra":"Wiki contains code snippet: backend/app/services/analytics/insights.py#1-313","gmt_create":"2026-05-23T15:23:21.709291+08:00","gmt_modified":"2026-05-23T15:23:21.709291+08:00"},{"id":2274,"source_id":"a0c569cd2355079f9f4045a198ddcadc","target_id":"451a0398486fbfcc669dc4e50c9ad6e2","source_type":"SOURCE_FILE","target_type":"CODE_SNIPPET","relationship_type":"CONTAINS","extra":"Source file contains code snippet: 1-313","gmt_create":"2026-05-23T15:23:21.710004+08:00","gmt_modified":"2026-05-23T15:23:21.710004+08:00"},{"id":2275,"source_id":"1c4316a1-f1d7-46da-bcfc-ea2fa0c56110","target_id":"897891ede0baa5b92d1b9f030a781753","source_type":"WIKI_ITEM","target_type":"CODE_SNIPPET","relationship_type":"CONTAINS","extra":"Wiki contains code snippet: backend/app/services/knowledge/rag_service.py#1-43","gmt_create":"2026-05-23T15:23:21.711734+08:00","gmt_modified":"2026-05-23T15:23:21.711734+08:00"},{"id":2276,"source_id":"45c9d96513947cae445aaaf8b58b4266","target_id":"897891ede0baa5b92d1b9f030a781753","source_type":"SOURCE_FILE","target_type":"CODE_SNIPPET","relationship_type":"CONTAINS","extra":"Source file contains code snippet: 1-43","gmt_create":"2026-05-23T15:23:21.712955+08:00","gmt_modified":"2026-05-23T15:23:21.712955+08:00"},{"id":2277,"source_id":"1c4316a1-f1d7-46da-bcfc-ea2fa0c56110","target_id":"ba54afe1867c2fa2046f8f62ad1caf3c","source_type":"WIKI_ITEM","target_type":"CODE_SNIPPET","relationship_type":"CONTAINS","extra":"Wiki contains code snippet: backend/app/agent_framework/agents/__init__.py#1-14","gmt_create":"2026-05-23T15:23:21.715215+08:00","gmt_modified":"2026-05-23T15:23:21.715215+08:00"},{"id":2278,"source_id":"d9f509d2a91b503397e98066751ead0c","target_id":"ba54afe1867c2fa2046f8f62ad1caf3c","source_type":"SOURCE_FILE","target_type":"CODE_SNIPPET","relationship_type":"CONTAINS","extra":"Source file contains code snippet: 1-14","gmt_create":"2026-05-23T15:23:21.716251+08:00","gmt_modified":"2026-05-23T15:23:21.716251+08:00"},{"id":2279,"source_id":"1c4316a1-f1d7-46da-bcfc-ea2fa0c56110","target_id":"74bf1d1b17dff651c44a2f4dc12d7bc7","source_type":"WIKI_ITEM","target_type":"CODE_SNIPPET","relationship_type":"CONTAINS","extra":"Wiki contains code snippet: backend/app/agent_framework/pipeline/engine.py#1-536","gmt_create":"2026-05-23T15:23:21.718018+08:00","gmt_modified":"2026-05-23T15:23:21.718019+08:00"},{"id":2280,"source_id":"1c4316a1-f1d7-46da-bcfc-ea2fa0c56110","target_id":"5dd1642d800053635d9827e12e6ea120","source_type":"WIKI_ITEM","target_type":"CODE_SNIPPET","relationship_type":"CONTAINS","extra":"Wiki contains code snippet: backend/app/agent_framework/dispatcher.py#1-367","gmt_create":"2026-05-23T15:23:21.72001+08:00","gmt_modified":"2026-05-23T15:23:21.72001+08:00"},{"id":2281,"source_id":"fcde401daccbe6de50f3829f021ecf55","target_id":"5dd1642d800053635d9827e12e6ea120","source_type":"SOURCE_FILE","target_type":"CODE_SNIPPET","relationship_type":"CONTAINS","extra":"Source file contains code snippet: 1-367","gmt_create":"2026-05-23T15:23:21.721447+08:00","gmt_modified":"2026-05-23T15:23:21.721448+08:00"},{"id":2282,"source_id":"1c4316a1-f1d7-46da-bcfc-ea2fa0c56110","target_id":"6281fff17a86ec1895c64d87c2ae7fb1","source_type":"WIKI_ITEM","target_type":"CODE_SNIPPET","relationship_type":"CONTAINS","extra":"Wiki contains code snippet: backend/app/models/query.py#1-55","gmt_create":"2026-05-23T15:23:21.725223+08:00","gmt_modified":"2026-05-23T15:23:21.725224+08:00"},{"id":2283,"source_id":"1c4316a1-f1d7-46da-bcfc-ea2fa0c56110","target_id":"943c18db69a04b3137fba4cebcfea87e","source_type":"WIKI_ITEM","target_type":"CODE_SNIPPET","relationship_type":"CONTAINS","extra":"Wiki contains code snippet: backend/app/models/citation_record.py#1-42","gmt_create":"2026-05-23T15:23:21.728082+08:00","gmt_modified":"2026-05-23T15:23:21.728082+08:00"},{"id":2284,"source_id":"1c4316a1-f1d7-46da-bcfc-ea2fa0c56110","target_id":"fa6144407f88a3c04dfcbac3b39bf8b1","source_type":"WIKI_ITEM","target_type":"CODE_SNIPPET","relationship_type":"CONTAINS","extra":"Wiki contains code snippet: backend/app/models/lifecycle.py#1-91","gmt_create":"2026-05-23T15:23:21.733468+08:00","gmt_modified":"2026-05-23T15:23:21.733468+08:00"},{"id":2285,"source_id":"97cfe961cb7386b4022a51706ae8f5dd","target_id":"fa6144407f88a3c04dfcbac3b39bf8b1","source_type":"SOURCE_FILE","target_type":"CODE_SNIPPET","relationship_type":"CONTAINS","extra":"Source file contains code snippet: 1-91","gmt_create":"2026-05-23T15:23:21.734434+08:00","gmt_modified":"2026-05-23T15:23:21.734434+08:00"},{"id":2286,"source_id":"1c4316a1-f1d7-46da-bcfc-ea2fa0c56110","target_id":"78d92049eebb9a8ceb231e7d2308aa78","source_type":"WIKI_ITEM","target_type":"CODE_SNIPPET","relationship_type":"CONTAINS","extra":"Wiki contains code snippet: backend/app/models/knowledge.py#1-43","gmt_create":"2026-05-23T15:23:21.736023+08:00","gmt_modified":"2026-05-23T15:23:21.736023+08:00"},{"id":2287,"source_id":"4774aadaa8ace576601bdaa8d3e11f74","target_id":"78d92049eebb9a8ceb231e7d2308aa78","source_type":"SOURCE_FILE","target_type":"CODE_SNIPPET","relationship_type":"CONTAINS","extra":"Source file contains code snippet: 1-43","gmt_create":"2026-05-23T15:23:21.736893+08:00","gmt_modified":"2026-05-23T15:23:21.736893+08:00"},{"id":2288,"source_id":"1c4316a1-f1d7-46da-bcfc-ea2fa0c56110","target_id":"9aac0f12a7ab3ebafd07a8bc408dbdcd","source_type":"WIKI_ITEM","target_type":"CODE_SNIPPET","relationship_type":"CONTAINS","extra":"Wiki contains code snippet: backend/workers/scheduler.py#1-95","gmt_create":"2026-05-23T15:23:21.738508+08:00","gmt_modified":"2026-05-23T15:23:21.738508+08:00"},{"id":2289,"source_id":"5b011956f30d4ac51420444cca8c7f08","target_id":"9aac0f12a7ab3ebafd07a8bc408dbdcd","source_type":"SOURCE_FILE","target_type":"CODE_SNIPPET","relationship_type":"CONTAINS","extra":"Source file contains code snippet: 1-95","gmt_create":"2026-05-23T15:23:21.739615+08:00","gmt_modified":"2026-05-23T15:23:21.739615+08:00"},{"id":2290,"source_id":"1c4316a1-f1d7-46da-bcfc-ea2fa0c56110","target_id":"00a305280b8ae4fb67df733a6d4c0c89","source_type":"WIKI_ITEM","target_type":"CODE_SNIPPET","relationship_type":"CONTAINS","extra":"Wiki contains code snippet: backend/workers/citation_engine.py#1-309","gmt_create":"2026-05-23T15:23:21.741089+08:00","gmt_modified":"2026-05-23T15:23:21.74109+08:00"},{"id":2291,"source_id":"4d4403d720ed0580f3ed57503b584eff","target_id":"00a305280b8ae4fb67df733a6d4c0c89","source_type":"SOURCE_FILE","target_type":"CODE_SNIPPET","relationship_type":"CONTAINS","extra":"Source file contains code snippet: 1-309","gmt_create":"2026-05-23T15:23:21.742661+08:00","gmt_modified":"2026-05-23T15:23:21.742661+08:00"},{"id":2292,"source_id":"1c4316a1-f1d7-46da-bcfc-ea2fa0c56110","target_id":"b7796fc6197ecce5beb461b9466e54a0","source_type":"WIKI_ITEM","target_type":"CODE_SNIPPET","relationship_type":"CONTAINS","extra":"Wiki contains code snippet: frontend/components/charts/trend-chart.tsx#1-60","gmt_create":"2026-05-23T15:23:21.752339+08:00","gmt_modified":"2026-05-23T15:23:21.752339+08:00"},{"id":2293,"source_id":"1c4316a1-f1d7-46da-bcfc-ea2fa0c56110","target_id":"74040de652d5e57f548bb5c4adc3e1a0","source_type":"WIKI_ITEM","target_type":"SOURCE_FILE","relationship_type":"REFERENCED_BY","extra":"Wiki references source file: backend/app/workers/citation_engine.py","gmt_create":"2026-05-23T15:23:21.761339+08:00","gmt_modified":"2026-05-23T15:23:21.76134+08:00"},{"id":2294,"source_id":"1c4316a1-f1d7-46da-bcfc-ea2fa0c56110","target_id":"309607c54b12a6340edc086ffb4737c9","source_type":"WIKI_ITEM","target_type":"CODE_SNIPPET","relationship_type":"CONTAINS","extra":"Wiki contains code snippet: backend/app/workers/citation_engine.py#148-309","gmt_create":"2026-05-23T15:23:21.766909+08:00","gmt_modified":"2026-05-23T15:23:21.76691+08:00"},{"id":2295,"source_id":"1c4316a1-f1d7-46da-bcfc-ea2fa0c56110","target_id":"a16cf42e9559523c4f96ca4c79f9488d","source_type":"WIKI_ITEM","target_type":"SOURCE_FILE","relationship_type":"REFERENCED_BY","extra":"Wiki references source file: backend/app/workers/platforms/base.py","gmt_create":"2026-05-23T15:23:21.768831+08:00","gmt_modified":"2026-05-23T15:23:21.768831+08:00"},{"id":2296,"source_id":"1c4316a1-f1d7-46da-bcfc-ea2fa0c56110","target_id":"72a110dca58d8152758e2fdab4e94761","source_type":"WIKI_ITEM","target_type":"CODE_SNIPPET","relationship_type":"CONTAINS","extra":"Wiki contains code snippet: backend/app/workers/platforms/base.py#1-18","gmt_create":"2026-05-23T15:23:21.771021+08:00","gmt_modified":"2026-05-23T15:23:21.771021+08:00"},{"id":2297,"source_id":"1c4316a1-f1d7-46da-bcfc-ea2fa0c56110","target_id":"03a65cdcfc173217d12ad8a417f8f033","source_type":"WIKI_ITEM","target_type":"CODE_SNIPPET","relationship_type":"CONTAINS","extra":"Wiki contains code snippet: backend/app/main.py#13-21","gmt_create":"2026-05-23T15:23:21.788068+08:00","gmt_modified":"2026-05-23T15:23:21.788068+08:00"},{"id":2298,"source_id":"1c4316a1-f1d7-46da-bcfc-ea2fa0c56110","target_id":"212d822d207a4c0bd7825bbf20e188e9","source_type":"WIKI_ITEM","target_type":"CODE_SNIPPET","relationship_type":"CONTAINS","extra":"Wiki contains code snippet: backend/app/api/citations.py#59-77","gmt_create":"2026-05-23T15:23:21.80864+08:00","gmt_modified":"2026-05-23T15:23:21.808641+08:00"},{"id":2299,"source_id":"1c4316a1-f1d7-46da-bcfc-ea2fa0c56110","target_id":"68338b3901163c41ed55d1ce10ea219a","source_type":"WIKI_ITEM","target_type":"CODE_SNIPPET","relationship_type":"CONTAINS","extra":"Wiki contains code snippet: backend/workers/scheduler.py#51-84","gmt_create":"2026-05-23T15:23:21.810776+08:00","gmt_modified":"2026-05-23T15:23:21.810776+08:00"},{"id":2300,"source_id":"5b011956f30d4ac51420444cca8c7f08","target_id":"68338b3901163c41ed55d1ce10ea219a","source_type":"SOURCE_FILE","target_type":"CODE_SNIPPET","relationship_type":"CONTAINS","extra":"Source file contains code snippet: 51-84","gmt_create":"2026-05-23T15:23:21.812508+08:00","gmt_modified":"2026-05-23T15:23:21.812509+08:00"},{"id":2301,"source_id":"1c4316a1-f1d7-46da-bcfc-ea2fa0c56110","target_id":"0bc629b80b2505420d45840e98a2b92d","source_type":"WIKI_ITEM","target_type":"CODE_SNIPPET","relationship_type":"CONTAINS","extra":"Wiki contains code snippet: backend/workers/citation_engine.py#159-234","gmt_create":"2026-05-23T15:23:21.81509+08:00","gmt_modified":"2026-05-23T15:23:21.815091+08:00"},{"id":2302,"source_id":"4d4403d720ed0580f3ed57503b584eff","target_id":"0bc629b80b2505420d45840e98a2b92d","source_type":"SOURCE_FILE","target_type":"CODE_SNIPPET","relationship_type":"CONTAINS","extra":"Source file contains code snippet: 159-234","gmt_create":"2026-05-23T15:23:21.816686+08:00","gmt_modified":"2026-05-23T15:23:21.816686+08:00"},{"id":2303,"source_id":"1c4316a1-f1d7-46da-bcfc-ea2fa0c56110","target_id":"4ded871d02b8119cdd985de8b220b084","source_type":"WIKI_ITEM","target_type":"CODE_SNIPPET","relationship_type":"CONTAINS","extra":"Wiki contains code snippet: backend/app/services/citation.py#204-234","gmt_create":"2026-05-23T15:23:21.819308+08:00","gmt_modified":"2026-05-23T15:23:21.819309+08:00"},{"id":2304,"source_id":"1c4316a1-f1d7-46da-bcfc-ea2fa0c56110","target_id":"f90f382f226eeca8bb1c111d10941fa0","source_type":"WIKI_ITEM","target_type":"CODE_SNIPPET","relationship_type":"CONTAINS","extra":"Wiki contains code snippet: backend/app/agent_framework/dispatcher.py#54-117","gmt_create":"2026-05-23T15:23:21.822083+08:00","gmt_modified":"2026-05-23T15:23:21.822084+08:00"},{"id":2305,"source_id":"fcde401daccbe6de50f3829f021ecf55","target_id":"f90f382f226eeca8bb1c111d10941fa0","source_type":"SOURCE_FILE","target_type":"CODE_SNIPPET","relationship_type":"CONTAINS","extra":"Source file contains code snippet: 54-117","gmt_create":"2026-05-23T15:23:21.823036+08:00","gmt_modified":"2026-05-23T15:23:21.823036+08:00"},{"id":2306,"source_id":"1c4316a1-f1d7-46da-bcfc-ea2fa0c56110","target_id":"8ece81c4077ec3e9c702e5e1092119a2","source_type":"WIKI_ITEM","target_type":"CODE_SNIPPET","relationship_type":"CONTAINS","extra":"Wiki contains code snippet: backend/app/agent_framework/pipeline/engine.py#51-176","gmt_create":"2026-05-23T15:23:21.82507+08:00","gmt_modified":"2026-05-23T15:23:21.825071+08:00"},{"id":2307,"source_id":"609a02c9e1ccc0311885a70578b86386","target_id":"8ece81c4077ec3e9c702e5e1092119a2","source_type":"SOURCE_FILE","target_type":"CODE_SNIPPET","relationship_type":"CONTAINS","extra":"Source file contains code snippet: 51-176","gmt_create":"2026-05-23T15:23:21.826138+08:00","gmt_modified":"2026-05-23T15:23:21.826138+08:00"},{"id":2308,"source_id":"1c4316a1-f1d7-46da-bcfc-ea2fa0c56110","target_id":"9552bd8a528207f18e4f3a1696f26a55","source_type":"WIKI_ITEM","target_type":"CODE_SNIPPET","relationship_type":"CONTAINS","extra":"Wiki contains code snippet: backend/app/api/auth.py#13-37","gmt_create":"2026-05-23T15:23:21.827167+08:00","gmt_modified":"2026-05-23T15:23:21.827167+08:00"},{"id":2309,"source_id":"1c4316a1-f1d7-46da-bcfc-ea2fa0c56110","target_id":"753a437d837246ead62b0e16c6331284","source_type":"WIKI_ITEM","target_type":"CODE_SNIPPET","relationship_type":"CONTAINS","extra":"Wiki contains code snippet: backend/app/services/auth.py#37-69","gmt_create":"2026-05-23T15:23:21.828241+08:00","gmt_modified":"2026-05-23T15:23:21.828242+08:00"},{"id":2310,"source_id":"1c4316a1-f1d7-46da-bcfc-ea2fa0c56110","target_id":"9b10dac7dbbb1327afc8a525bf4bd0c3","source_type":"WIKI_ITEM","target_type":"CODE_SNIPPET","relationship_type":"CONTAINS","extra":"Wiki contains code snippet: backend/app/services/query.py#45-81","gmt_create":"2026-05-23T15:23:21.833657+08:00","gmt_modified":"2026-05-23T15:23:21.833658+08:00"},{"id":2311,"source_id":"1c4316a1-f1d7-46da-bcfc-ea2fa0c56110","target_id":"168f54bd5cbe07c656ec3905e567862c","source_type":"WIKI_ITEM","target_type":"CODE_SNIPPET","relationship_type":"CONTAINS","extra":"Wiki contains code snippet: backend/app/workers/citation_engine.py#291-300","gmt_create":"2026-05-23T15:23:21.837553+08:00","gmt_modified":"2026-05-23T15:23:21.837553+08:00"},{"id":2312,"source_id":"74040de652d5e57f548bb5c4adc3e1a0","target_id":"168f54bd5cbe07c656ec3905e567862c","source_type":"SOURCE_FILE","target_type":"CODE_SNIPPET","relationship_type":"CONTAINS","extra":"Source file contains code snippet: 291-300","gmt_create":"2026-05-23T15:23:21.839019+08:00","gmt_modified":"2026-05-23T15:23:21.83902+08:00"},{"id":2313,"source_id":"1c4316a1-f1d7-46da-bcfc-ea2fa0c56110","target_id":"b624be78e3bffd876e403cff2557b088","source_type":"WIKI_ITEM","target_type":"CODE_SNIPPET","relationship_type":"CONTAINS","extra":"Wiki contains code snippet: backend/app/workers/citation_engine.py#19-120","gmt_create":"2026-05-23T15:23:21.847363+08:00","gmt_modified":"2026-05-23T15:23:21.847363+08:00"},{"id":2314,"source_id":"1c4316a1-f1d7-46da-bcfc-ea2fa0c56110","target_id":"5c67e2f70283956b2d29a3c1443eb514","source_type":"WIKI_ITEM","target_type":"CODE_SNIPPET","relationship_type":"CONTAINS","extra":"Wiki contains code snippet: backend/app/workers/citation_engine.py#122-146","gmt_create":"2026-05-23T15:23:21.848539+08:00","gmt_modified":"2026-05-23T15:23:21.84854+08:00"},{"id":2315,"source_id":"1c4316a1-f1d7-46da-bcfc-ea2fa0c56110","target_id":"160b5326537d25444c40a459a01e79c6","source_type":"WIKI_ITEM","target_type":"CODE_SNIPPET","relationship_type":"CONTAINS","extra":"Wiki contains code snippet: backend/app/workers/citation_engine.py#159-234","gmt_create":"2026-05-23T15:23:21.851603+08:00","gmt_modified":"2026-05-23T15:23:21.851603+08:00"},{"id":2316,"source_id":"1c4316a1-f1d7-46da-bcfc-ea2fa0c56110","target_id":"d3e817d678735f63b277894d26626924","source_type":"WIKI_ITEM","target_type":"CODE_SNIPPET","relationship_type":"CONTAINS","extra":"Wiki contains code snippet: backend/app/workers/platforms/base.py#10-17","gmt_create":"2026-05-23T15:23:21.853387+08:00","gmt_modified":"2026-05-23T15:23:21.853387+08:00"},{"id":2317,"source_id":"a16cf42e9559523c4f96ca4c79f9488d","target_id":"d3e817d678735f63b277894d26626924","source_type":"SOURCE_FILE","target_type":"CODE_SNIPPET","relationship_type":"CONTAINS","extra":"Source file contains code snippet: 10-17","gmt_create":"2026-05-23T15:23:21.854596+08:00","gmt_modified":"2026-05-23T15:23:21.854597+08:00"},{"id":2318,"source_id":"1c4316a1-f1d7-46da-bcfc-ea2fa0c56110","target_id":"f0421deca067a246711e95817e1f1b1a","source_type":"WIKI_ITEM","target_type":"CODE_SNIPPET","relationship_type":"CONTAINS","extra":"Wiki contains code snippet: backend/app/workers/citation_engine.py#151-157","gmt_create":"2026-05-23T15:23:21.859784+08:00","gmt_modified":"2026-05-23T15:23:21.859784+08:00"},{"id":2319,"source_id":"74040de652d5e57f548bb5c4adc3e1a0","target_id":"f0421deca067a246711e95817e1f1b1a","source_type":"SOURCE_FILE","target_type":"CODE_SNIPPET","relationship_type":"CONTAINS","extra":"Source file contains code snippet: 151-157","gmt_create":"2026-05-23T15:23:21.861671+08:00","gmt_modified":"2026-05-23T15:23:21.861671+08:00"},{"id":2320,"source_id":"1c4316a1-f1d7-46da-bcfc-ea2fa0c56110","target_id":"6a21ee5392ba55b57659d404ebf5355e","source_type":"WIKI_ITEM","target_type":"CODE_SNIPPET","relationship_type":"CONTAINS","extra":"Wiki contains code snippet: backend/app/agent_framework/agents/citation_detector.py#24-218","gmt_create":"2026-05-23T15:23:21.865655+08:00","gmt_modified":"2026-05-23T15:23:21.865656+08:00"},{"id":2321,"source_id":"58a2f69ec5607ac5e4ab93266534ac01","target_id":"6a21ee5392ba55b57659d404ebf5355e","source_type":"SOURCE_FILE","target_type":"CODE_SNIPPET","relationship_type":"CONTAINS","extra":"Source file contains code snippet: 24-218","gmt_create":"2026-05-23T15:23:21.866773+08:00","gmt_modified":"2026-05-23T15:23:21.866773+08:00"},{"id":2322,"source_id":"1c4316a1-f1d7-46da-bcfc-ea2fa0c56110","target_id":"76381105cd13daa99ac6376cfdab39f0","source_type":"WIKI_ITEM","target_type":"CODE_SNIPPET","relationship_type":"CONTAINS","extra":"Wiki contains code snippet: backend/app/agent_framework/agents/content_generator_agent.py#23-299","gmt_create":"2026-05-23T15:23:21.868274+08:00","gmt_modified":"2026-05-23T15:23:21.868274+08:00"},{"id":2323,"source_id":"13b8f594e7cace5c8a9255dc801dcad8","target_id":"76381105cd13daa99ac6376cfdab39f0","source_type":"SOURCE_FILE","target_type":"CODE_SNIPPET","relationship_type":"CONTAINS","extra":"Source file contains code snippet: 23-299","gmt_create":"2026-05-23T15:23:21.869317+08:00","gmt_modified":"2026-05-23T15:23:21.869317+08:00"},{"id":2324,"source_id":"1c4316a1-f1d7-46da-bcfc-ea2fa0c56110","target_id":"ff0389ece7f710d431371a409553989c","source_type":"WIKI_ITEM","target_type":"CODE_SNIPPET","relationship_type":"CONTAINS","extra":"Wiki contains code snippet: backend/app/agent_framework/agents/deai_agent.py#21-156","gmt_create":"2026-05-23T15:23:21.870814+08:00","gmt_modified":"2026-05-23T15:23:21.870814+08:00"},{"id":2325,"source_id":"750f8d79d83ee910e9d18e8a4fe37e22","target_id":"ff0389ece7f710d431371a409553989c","source_type":"SOURCE_FILE","target_type":"CODE_SNIPPET","relationship_type":"CONTAINS","extra":"Source file contains code snippet: 21-156","gmt_create":"2026-05-23T15:23:21.871975+08:00","gmt_modified":"2026-05-23T15:23:21.871975+08:00"},{"id":2326,"source_id":"1c4316a1-f1d7-46da-bcfc-ea2fa0c56110","target_id":"f30316a028f81ac1c0e2f77568ba64f5","source_type":"WIKI_ITEM","target_type":"CODE_SNIPPET","relationship_type":"CONTAINS","extra":"Wiki contains code snippet: backend/app/agent_framework/agents/geo_optimizer_agent.py#23-198","gmt_create":"2026-05-23T15:23:21.873473+08:00","gmt_modified":"2026-05-23T15:23:21.873473+08:00"},{"id":2327,"source_id":"7f8c6e94ead45ad9bab8cea9a7be2123","target_id":"f30316a028f81ac1c0e2f77568ba64f5","source_type":"SOURCE_FILE","target_type":"CODE_SNIPPET","relationship_type":"CONTAINS","extra":"Source file contains code snippet: 23-198","gmt_create":"2026-05-23T15:23:21.874184+08:00","gmt_modified":"2026-05-23T15:23:21.874184+08:00"},{"id":2328,"source_id":"1c4316a1-f1d7-46da-bcfc-ea2fa0c56110","target_id":"72c6b8f0be1248c2ce6e84247e81416d","source_type":"WIKI_ITEM","target_type":"CODE_SNIPPET","relationship_type":"CONTAINS","extra":"Wiki contains code snippet: backend/app/agent_framework/pipeline/engine.py#31-536","gmt_create":"2026-05-23T15:23:21.875709+08:00","gmt_modified":"2026-05-23T15:23:21.875709+08:00"},{"id":2329,"source_id":"609a02c9e1ccc0311885a70578b86386","target_id":"72c6b8f0be1248c2ce6e84247e81416d","source_type":"SOURCE_FILE","target_type":"CODE_SNIPPET","relationship_type":"CONTAINS","extra":"Source file contains code snippet: 31-536","gmt_create":"2026-05-23T15:23:21.877669+08:00","gmt_modified":"2026-05-23T15:23:21.877669+08:00"},{"id":2330,"source_id":"1c4316a1-f1d7-46da-bcfc-ea2fa0c56110","target_id":"af5a9cdc724669f93a0f9f1dd790717b","source_type":"WIKI_ITEM","target_type":"CODE_SNIPPET","relationship_type":"CONTAINS","extra":"Wiki contains code snippet: backend/app/agent_framework/dispatcher.py#32-367","gmt_create":"2026-05-23T15:23:21.87872+08:00","gmt_modified":"2026-05-23T15:23:21.87872+08:00"},{"id":2331,"source_id":"fcde401daccbe6de50f3829f021ecf55","target_id":"af5a9cdc724669f93a0f9f1dd790717b","source_type":"SOURCE_FILE","target_type":"CODE_SNIPPET","relationship_type":"CONTAINS","extra":"Source file contains code snippet: 32-367","gmt_create":"2026-05-23T15:23:21.880036+08:00","gmt_modified":"2026-05-23T15:23:21.880036+08:00"},{"id":2332,"source_id":"1c4316a1-f1d7-46da-bcfc-ea2fa0c56110","target_id":"8e264e08029549dd5af31f4238522cc1","source_type":"WIKI_ITEM","target_type":"CODE_SNIPPET","relationship_type":"CONTAINS","extra":"Wiki contains code snippet: backend/app/agent_framework/agents/citation_detector.py#1-218","gmt_create":"2026-05-23T15:23:21.884933+08:00","gmt_modified":"2026-05-23T15:23:21.884933+08:00"},{"id":2333,"source_id":"58a2f69ec5607ac5e4ab93266534ac01","target_id":"8e264e08029549dd5af31f4238522cc1","source_type":"SOURCE_FILE","target_type":"CODE_SNIPPET","relationship_type":"CONTAINS","extra":"Source file contains code snippet: 1-218","gmt_create":"2026-05-23T15:23:21.886083+08:00","gmt_modified":"2026-05-23T15:23:21.886113+08:00"},{"id":2334,"source_id":"1c4316a1-f1d7-46da-bcfc-ea2fa0c56110","target_id":"461200c8ca02024dd32c214c679b9664","source_type":"WIKI_ITEM","target_type":"CODE_SNIPPET","relationship_type":"CONTAINS","extra":"Wiki contains code snippet: backend/app/agent_framework/agents/content_generator_agent.py#1-299","gmt_create":"2026-05-23T15:23:21.888308+08:00","gmt_modified":"2026-05-23T15:23:21.888309+08:00"},{"id":2335,"source_id":"1c4316a1-f1d7-46da-bcfc-ea2fa0c56110","target_id":"7f44b646183e17098f8ce4d2be931d3e","source_type":"WIKI_ITEM","target_type":"CODE_SNIPPET","relationship_type":"CONTAINS","extra":"Wiki contains code snippet: backend/app/agent_framework/agents/deai_agent.py#1-156","gmt_create":"2026-05-23T15:23:21.889964+08:00","gmt_modified":"2026-05-23T15:23:21.889965+08:00"},{"id":2336,"source_id":"1c4316a1-f1d7-46da-bcfc-ea2fa0c56110","target_id":"45778eaa35d92099677ba180f1067905","source_type":"WIKI_ITEM","target_type":"CODE_SNIPPET","relationship_type":"CONTAINS","extra":"Wiki contains code snippet: backend/app/agent_framework/agents/geo_optimizer_agent.py#1-198","gmt_create":"2026-05-23T15:23:21.892479+08:00","gmt_modified":"2026-05-23T15:23:21.89248+08:00"},{"id":2337,"source_id":"1c4316a1-f1d7-46da-bcfc-ea2fa0c56110","target_id":"98d6d7fe81309b5f48907ff2c96bd9e9","source_type":"WIKI_ITEM","target_type":"CODE_SNIPPET","relationship_type":"CONTAINS","extra":"Wiki contains code snippet: backend/app/api/lifecycle.py#190-230","gmt_create":"2026-05-23T15:23:21.898853+08:00","gmt_modified":"2026-05-23T15:23:21.898853+08:00"},{"id":2338,"source_id":"1c4316a1-f1d7-46da-bcfc-ea2fa0c56110","target_id":"12b7988890a9e461cbccd36564a6cc82","source_type":"WIKI_ITEM","target_type":"CODE_SNIPPET","relationship_type":"CONTAINS","extra":"Wiki contains code snippet: backend/app/api/lifecycle.py#138-187","gmt_create":"2026-05-23T15:23:21.901727+08:00","gmt_modified":"2026-05-23T15:23:21.901727+08:00"},{"id":2339,"source_id":"9c224bb80474867f8ded674babaa6e11","target_id":"12b7988890a9e461cbccd36564a6cc82","source_type":"SOURCE_FILE","target_type":"CODE_SNIPPET","relationship_type":"CONTAINS","extra":"Source file contains code snippet: 138-187","gmt_create":"2026-05-23T15:23:21.903183+08:00","gmt_modified":"2026-05-23T15:23:21.903183+08:00"},{"id":2340,"source_id":"1c4316a1-f1d7-46da-bcfc-ea2fa0c56110","target_id":"5c9cde497ea1c98e6fe63e808f1d8ca5","source_type":"WIKI_ITEM","target_type":"CODE_SNIPPET","relationship_type":"CONTAINS","extra":"Wiki contains code snippet: backend/app/models/lifecycle.py#12-91","gmt_create":"2026-05-23T15:23:21.904798+08:00","gmt_modified":"2026-05-23T15:23:21.904798+08:00"},{"id":2341,"source_id":"97cfe961cb7386b4022a51706ae8f5dd","target_id":"5c9cde497ea1c98e6fe63e808f1d8ca5","source_type":"SOURCE_FILE","target_type":"CODE_SNIPPET","relationship_type":"CONTAINS","extra":"Source file contains code snippet: 12-91","gmt_create":"2026-05-23T15:23:21.905691+08:00","gmt_modified":"2026-05-23T15:23:21.905691+08:00"},{"id":2342,"source_id":"1c4316a1-f1d7-46da-bcfc-ea2fa0c56110","target_id":"058be4ad1752d83067d65bf59f958461","source_type":"WIKI_ITEM","target_type":"CODE_SNIPPET","relationship_type":"CONTAINS","extra":"Wiki contains code snippet: frontend/lib/api/lifecycle.ts#53-95","gmt_create":"2026-05-23T15:23:21.90988+08:00","gmt_modified":"2026-05-23T15:23:21.909881+08:00"},{"id":2343,"source_id":"21ab29cd896c5703dfa3461a055c0f54","target_id":"058be4ad1752d83067d65bf59f958461","source_type":"SOURCE_FILE","target_type":"CODE_SNIPPET","relationship_type":"CONTAINS","extra":"Source file contains code snippet: 53-95","gmt_create":"2026-05-23T15:23:21.911073+08:00","gmt_modified":"2026-05-23T15:23:21.911073+08:00"},{"id":2344,"source_id":"1c4316a1-f1d7-46da-bcfc-ea2fa0c56110","target_id":"c549a2efc417d5646c81a100701cf72a","source_type":"WIKI_ITEM","target_type":"CODE_SNIPPET","relationship_type":"CONTAINS","extra":"Wiki contains code snippet: backend/app/services/analytics/tracker.py#16-51","gmt_create":"2026-05-23T15:23:21.917374+08:00","gmt_modified":"2026-05-23T15:23:21.917374+08:00"},{"id":2345,"source_id":"984d67382822ff587452a79f89e0d336","target_id":"c549a2efc417d5646c81a100701cf72a","source_type":"SOURCE_FILE","target_type":"CODE_SNIPPET","relationship_type":"CONTAINS","extra":"Source file contains code snippet: 16-51","gmt_create":"2026-05-23T15:23:21.918843+08:00","gmt_modified":"2026-05-23T15:23:21.918843+08:00"},{"id":2346,"source_id":"1c4316a1-f1d7-46da-bcfc-ea2fa0c56110","target_id":"33c1014641412422e2687463885aef5f","source_type":"WIKI_ITEM","target_type":"CODE_SNIPPET","relationship_type":"CONTAINS","extra":"Wiki contains code snippet: backend/app/services/analytics/insights.py#40-103","gmt_create":"2026-05-23T15:23:21.920605+08:00","gmt_modified":"2026-05-23T15:23:21.920605+08:00"},{"id":2347,"source_id":"a0c569cd2355079f9f4045a198ddcadc","target_id":"33c1014641412422e2687463885aef5f","source_type":"SOURCE_FILE","target_type":"CODE_SNIPPET","relationship_type":"CONTAINS","extra":"Source file contains code snippet: 40-103","gmt_create":"2026-05-23T15:23:21.921664+08:00","gmt_modified":"2026-05-23T15:23:21.921664+08:00"},{"id":2348,"source_id":"1c4316a1-f1d7-46da-bcfc-ea2fa0c56110","target_id":"befab5441502d9e867d85550072130fa","source_type":"WIKI_ITEM","target_type":"CODE_SNIPPET","relationship_type":"CONTAINS","extra":"Wiki contains code snippet: backend/app/services/analytics/tracker.py#53-128","gmt_create":"2026-05-23T15:23:21.922803+08:00","gmt_modified":"2026-05-23T15:23:21.922804+08:00"},{"id":2349,"source_id":"984d67382822ff587452a79f89e0d336","target_id":"befab5441502d9e867d85550072130fa","source_type":"SOURCE_FILE","target_type":"CODE_SNIPPET","relationship_type":"CONTAINS","extra":"Source file contains code snippet: 53-128","gmt_create":"2026-05-23T15:23:21.924282+08:00","gmt_modified":"2026-05-23T15:23:21.924282+08:00"},{"id":2350,"source_id":"1c4316a1-f1d7-46da-bcfc-ea2fa0c56110","target_id":"1d1a90f9679ff5937c688d465591a0ab","source_type":"WIKI_ITEM","target_type":"CODE_SNIPPET","relationship_type":"CONTAINS","extra":"Wiki contains code snippet: backend/app/api/knowledge.py#217-293","gmt_create":"2026-05-23T15:23:21.92941+08:00","gmt_modified":"2026-05-23T15:23:21.929411+08:00"},{"id":2351,"source_id":"63953ee6b39f159a61963104ac06f283","target_id":"1d1a90f9679ff5937c688d465591a0ab","source_type":"SOURCE_FILE","target_type":"CODE_SNIPPET","relationship_type":"CONTAINS","extra":"Source file contains code snippet: 217-293","gmt_create":"2026-05-23T15:23:21.931252+08:00","gmt_modified":"2026-05-23T15:23:21.931252+08:00"},{"id":2352,"source_id":"1c4316a1-f1d7-46da-bcfc-ea2fa0c56110","target_id":"f38b21f300a72d77625c203e8d9e5916","source_type":"WIKI_ITEM","target_type":"CODE_SNIPPET","relationship_type":"CONTAINS","extra":"Wiki contains code snippet: backend/app/api/knowledge.py#424-501","gmt_create":"2026-05-23T15:23:21.933587+08:00","gmt_modified":"2026-05-23T15:23:21.933588+08:00"},{"id":2353,"source_id":"1c4316a1-f1d7-46da-bcfc-ea2fa0c56110","target_id":"7f9b9025f56d8baba8136ab1b8ed49b3","source_type":"WIKI_ITEM","target_type":"CODE_SNIPPET","relationship_type":"CONTAINS","extra":"Wiki contains code snippet: backend/app/services/knowledge/rag_service.py#33-43","gmt_create":"2026-05-23T15:23:21.935311+08:00","gmt_modified":"2026-05-23T15:23:21.935311+08:00"},{"id":2354,"source_id":"45c9d96513947cae445aaaf8b58b4266","target_id":"7f9b9025f56d8baba8136ab1b8ed49b3","source_type":"SOURCE_FILE","target_type":"CODE_SNIPPET","relationship_type":"CONTAINS","extra":"Source file contains code snippet: 33-43","gmt_create":"2026-05-23T15:23:21.936548+08:00","gmt_modified":"2026-05-23T15:23:21.936549+08:00"},{"id":2355,"source_id":"1c4316a1-f1d7-46da-bcfc-ea2fa0c56110","target_id":"16f20ee7078a57c6910a20d49deb646f","source_type":"WIKI_ITEM","target_type":"CODE_SNIPPET","relationship_type":"CONTAINS","extra":"Wiki contains code snippet: frontend/components/charts/trend-chart.tsx#22-59","gmt_create":"2026-05-23T15:23:21.941432+08:00","gmt_modified":"2026-05-23T15:23:21.941432+08:00"},{"id":2356,"source_id":"d5f2266643d2011c66e86af088ec637f","target_id":"16f20ee7078a57c6910a20d49deb646f","source_type":"SOURCE_FILE","target_type":"CODE_SNIPPET","relationship_type":"CONTAINS","extra":"Source file contains code snippet: 22-59","gmt_create":"2026-05-23T15:23:21.942627+08:00","gmt_modified":"2026-05-23T15:23:21.942628+08:00"},{"id":2357,"source_id":"1c4316a1-f1d7-46da-bcfc-ea2fa0c56110","target_id":"f457c5ae12bb63dcd5d83e4ede8efb15","source_type":"WIKI_ITEM","target_type":"CODE_SNIPPET","relationship_type":"CONTAINS","extra":"Wiki contains code snippet: backend/app/api/citations.py#49-56","gmt_create":"2026-05-23T15:23:21.944425+08:00","gmt_modified":"2026-05-23T15:23:21.944425+08:00"},{"id":2358,"source_id":"7538ffe4902ab6041adb28b19844962a","target_id":"f457c5ae12bb63dcd5d83e4ede8efb15","source_type":"SOURCE_FILE","target_type":"CODE_SNIPPET","relationship_type":"CONTAINS","extra":"Source file contains code snippet: 49-56","gmt_create":"2026-05-23T15:23:21.94554+08:00","gmt_modified":"2026-05-23T15:23:21.945541+08:00"},{"id":2359,"source_id":"1c4316a1-f1d7-46da-bcfc-ea2fa0c56110","target_id":"cb57298d603df7c5572310807b629516","source_type":"WIKI_ITEM","target_type":"CODE_SNIPPET","relationship_type":"CONTAINS","extra":"Wiki contains code snippet: backend/app/services/citation.py#76-201","gmt_create":"2026-05-23T15:23:21.94905+08:00","gmt_modified":"2026-05-23T15:23:21.94905+08:00"},{"id":2360,"source_id":"04e3926c080e795713bff683e7dc9d3e","target_id":"cb57298d603df7c5572310807b629516","source_type":"SOURCE_FILE","target_type":"CODE_SNIPPET","relationship_type":"CONTAINS","extra":"Source file contains code snippet: 76-201","gmt_create":"2026-05-23T15:23:21.950572+08:00","gmt_modified":"2026-05-23T15:23:21.950572+08:00"},{"id":2361,"source_id":"1c4316a1-f1d7-46da-bcfc-ea2fa0c56110","target_id":"177c73dc4e71186d9eaa1157fc0fe97f","source_type":"WIKI_ITEM","target_type":"CODE_SNIPPET","relationship_type":"CONTAINS","extra":"Wiki contains code snippet: backend/app/api/reports.py#16-46","gmt_create":"2026-05-23T15:23:21.957479+08:00","gmt_modified":"2026-05-23T15:23:21.957479+08:00"},{"id":2362,"source_id":"1c4316a1-f1d7-46da-bcfc-ea2fa0c56110","target_id":"84d5ec753cc381b480dfd2cc2f4228a0","source_type":"WIKI_ITEM","target_type":"CODE_SNIPPET","relationship_type":"CONTAINS","extra":"Wiki contains code snippet: backend/app/services/citation.py#237-268","gmt_create":"2026-05-23T15:23:21.959295+08:00","gmt_modified":"2026-05-23T15:23:21.959295+08:00"},{"id":2363,"source_id":"04e3926c080e795713bff683e7dc9d3e","target_id":"84d5ec753cc381b480dfd2cc2f4228a0","source_type":"SOURCE_FILE","target_type":"CODE_SNIPPET","relationship_type":"CONTAINS","extra":"Source file contains code snippet: 237-268","gmt_create":"2026-05-23T15:23:21.960008+08:00","gmt_modified":"2026-05-23T15:23:21.960008+08:00"},{"id":2364,"source_id":"1c4316a1-f1d7-46da-bcfc-ea2fa0c56110","target_id":"6286d4be455dc058c8be2ee4e0d1175a","source_type":"WIKI_ITEM","target_type":"CODE_SNIPPET","relationship_type":"CONTAINS","extra":"Wiki contains code snippet: backend/app/main.py#38-42","gmt_create":"2026-05-23T15:23:21.966343+08:00","gmt_modified":"2026-05-23T15:23:21.966343+08:00"},{"id":2365,"source_id":"1c4316a1-f1d7-46da-bcfc-ea2fa0c56110","target_id":"d49ddf2ff36cff1ba6702d9fe3bd253d","source_type":"WIKI_ITEM","target_type":"CODE_SNIPPET","relationship_type":"CONTAINS","extra":"Wiki contains code snippet: backend/app/agent_framework/dispatcher.py#35-46","gmt_create":"2026-05-23T15:23:21.97134+08:00","gmt_modified":"2026-05-23T15:23:21.971341+08:00"},{"id":2366,"source_id":"fcde401daccbe6de50f3829f021ecf55","target_id":"d49ddf2ff36cff1ba6702d9fe3bd253d","source_type":"SOURCE_FILE","target_type":"CODE_SNIPPET","relationship_type":"CONTAINS","extra":"Source file contains code snippet: 35-46","gmt_create":"2026-05-23T15:23:21.972595+08:00","gmt_modified":"2026-05-23T15:23:21.972596+08:00"},{"id":2367,"source_id":"1c4316a1-f1d7-46da-bcfc-ea2fa0c56110","target_id":"5cbb1e3f112aeba62a14b0b8999fc0f5","source_type":"WIKI_ITEM","target_type":"SOURCE_FILE","relationship_type":"REFERENCED_BY","extra":"Wiki references source file: backend/app/workers/scheduler.py","gmt_create":"2026-05-23T15:23:21.983031+08:00","gmt_modified":"2026-05-23T15:23:21.983031+08:00"},{"id":2368,"source_id":"1c4316a1-f1d7-46da-bcfc-ea2fa0c56110","target_id":"89c74d1f6c264e3b6b0232f7c2385cc7","source_type":"WIKI_ITEM","target_type":"CODE_SNIPPET","relationship_type":"CONTAINS","extra":"Wiki contains code snippet: backend/app/workers/scheduler.py#30-40","gmt_create":"2026-05-23T15:23:21.984142+08:00","gmt_modified":"2026-05-23T15:23:21.984142+08:00"},{"id":2369,"source_id":"5cbb1e3f112aeba62a14b0b8999fc0f5","target_id":"89c74d1f6c264e3b6b0232f7c2385cc7","source_type":"SOURCE_FILE","target_type":"CODE_SNIPPET","relationship_type":"CONTAINS","extra":"Source file contains code snippet: 30-40","gmt_create":"2026-05-23T15:23:21.985389+08:00","gmt_modified":"2026-05-23T15:23:21.98539+08:00"},{"id":2370,"source_id":"1c4316a1-f1d7-46da-bcfc-ea2fa0c56110","target_id":"d51485da00706b78a1bc7eb4290c8044","source_type":"WIKI_ITEM","target_type":"CODE_SNIPPET","relationship_type":"CONTAINS","extra":"Wiki contains code snippet: backend/app/agent_framework/dispatcher.py#118-154","gmt_create":"2026-05-23T15:23:21.986846+08:00","gmt_modified":"2026-05-23T15:23:21.986846+08:00"},{"id":2371,"source_id":"fcde401daccbe6de50f3829f021ecf55","target_id":"d51485da00706b78a1bc7eb4290c8044","source_type":"SOURCE_FILE","target_type":"CODE_SNIPPET","relationship_type":"CONTAINS","extra":"Source file contains code snippet: 118-154","gmt_create":"2026-05-23T15:23:21.987898+08:00","gmt_modified":"2026-05-23T15:23:21.987899+08:00"},{"id":2372,"source_id":"c7eb113b-b503-4d83-be7f-9ccf3350c9d9","target_id":"9228ff67d4c757a85d9421b71f4b29f5","source_type":"WIKI_ITEM","target_type":"SOURCE_FILE","relationship_type":"REFERENCED_BY","extra":"Wiki references source file: backend/app/main.py","gmt_create":"2026-05-23T15:24:01.88966+08:00","gmt_modified":"2026-05-23T15:24:01.88966+08:00"},{"id":2373,"source_id":"c7eb113b-b503-4d83-be7f-9ccf3350c9d9","target_id":"9ff19022ef915615911280e3c49ed44b","source_type":"WIKI_ITEM","target_type":"SOURCE_FILE","relationship_type":"REFERENCED_BY","extra":"Wiki references source file: backend/app/config.py","gmt_create":"2026-05-23T15:24:01.890714+08:00","gmt_modified":"2026-05-23T15:24:01.890714+08:00"},{"id":2374,"source_id":"c7eb113b-b503-4d83-be7f-9ccf3350c9d9","target_id":"b0c428683c8a3e6922d90ca0d8c2736d","source_type":"WIKI_ITEM","target_type":"SOURCE_FILE","relationship_type":"REFERENCED_BY","extra":"Wiki references source file: backend/app/database.py","gmt_create":"2026-05-23T15:24:01.891767+08:00","gmt_modified":"2026-05-23T15:24:01.891768+08:00"},{"id":2375,"source_id":"c7eb113b-b503-4d83-be7f-9ccf3350c9d9","target_id":"93022c8938ce318f167277cfa65c29a7","source_type":"WIKI_ITEM","target_type":"SOURCE_FILE","relationship_type":"REFERENCED_BY","extra":"Wiki references source file: backend/app/api/auth.py","gmt_create":"2026-05-23T15:24:01.893771+08:00","gmt_modified":"2026-05-23T15:24:01.893771+08:00"},{"id":2376,"source_id":"c7eb113b-b503-4d83-be7f-9ccf3350c9d9","target_id":"6b3d903205941aa9391dd90016e1102c","source_type":"WIKI_ITEM","target_type":"SOURCE_FILE","relationship_type":"REFERENCED_BY","extra":"Wiki references source file: backend/app/api/queries.py","gmt_create":"2026-05-23T15:24:01.895137+08:00","gmt_modified":"2026-05-23T15:24:01.895137+08:00"},{"id":2377,"source_id":"c7eb113b-b503-4d83-be7f-9ccf3350c9d9","target_id":"7538ffe4902ab6041adb28b19844962a","source_type":"WIKI_ITEM","target_type":"SOURCE_FILE","relationship_type":"REFERENCED_BY","extra":"Wiki references source file: backend/app/api/citations.py","gmt_create":"2026-05-23T15:24:01.899331+08:00","gmt_modified":"2026-05-23T15:24:01.899331+08:00"},{"id":2378,"source_id":"c7eb113b-b503-4d83-be7f-9ccf3350c9d9","target_id":"9d08667997a868fc07c9b4e328e44224","source_type":"WIKI_ITEM","target_type":"SOURCE_FILE","relationship_type":"REFERENCED_BY","extra":"Wiki references source file: backend/app/api/deps.py","gmt_create":"2026-05-23T15:24:01.901077+08:00","gmt_modified":"2026-05-23T15:24:01.901077+08:00"},{"id":2379,"source_id":"c7eb113b-b503-4d83-be7f-9ccf3350c9d9","target_id":"f26740f2a1532b38c816663a4f665dbf","source_type":"WIKI_ITEM","target_type":"SOURCE_FILE","relationship_type":"REFERENCED_BY","extra":"Wiki references source file: backend/app/api/admin.py","gmt_create":"2026-05-23T15:24:01.902215+08:00","gmt_modified":"2026-05-23T15:24:01.902215+08:00"},{"id":2380,"source_id":"c7eb113b-b503-4d83-be7f-9ccf3350c9d9","target_id":"58901c94d975d87e652a4dc6c8dda656","source_type":"WIKI_ITEM","target_type":"SOURCE_FILE","relationship_type":"REFERENCED_BY","extra":"Wiki references source file: backend/app/api/reports.py","gmt_create":"2026-05-23T15:24:01.903191+08:00","gmt_modified":"2026-05-23T15:24:01.903192+08:00"},{"id":2381,"source_id":"c7eb113b-b503-4d83-be7f-9ccf3350c9d9","target_id":"5386144bf3c668c6fa14481c0d85a214","source_type":"WIKI_ITEM","target_type":"SOURCE_FILE","relationship_type":"REFERENCED_BY","extra":"Wiki references source file: backend/app/api/subscriptions.py","gmt_create":"2026-05-23T15:24:01.904559+08:00","gmt_modified":"2026-05-23T15:24:01.904559+08:00"},{"id":2382,"source_id":"c7eb113b-b503-4d83-be7f-9ccf3350c9d9","target_id":"b44632a0f399b2fe2b4daf295a120ec7","source_type":"WIKI_ITEM","target_type":"SOURCE_FILE","relationship_type":"REFERENCED_BY","extra":"Wiki references source file: backend/app/middleware/logging_middleware.py","gmt_create":"2026-05-23T15:24:01.905631+08:00","gmt_modified":"2026-05-23T15:24:01.905631+08:00"},{"id":2383,"source_id":"c7eb113b-b503-4d83-be7f-9ccf3350c9d9","target_id":"5883a8ef4fc156d76b71ffdb5ecdf232","source_type":"WIKI_ITEM","target_type":"SOURCE_FILE","relationship_type":"REFERENCED_BY","extra":"Wiki references source file: backend/app/middleware/rate_limit.py","gmt_create":"2026-05-23T15:24:01.906674+08:00","gmt_modified":"2026-05-23T15:24:01.906675+08:00"},{"id":2384,"source_id":"c7eb113b-b503-4d83-be7f-9ccf3350c9d9","target_id":"e0c0ca66b8b81cf66e078a7ab162c07f","source_type":"WIKI_ITEM","target_type":"SOURCE_FILE","relationship_type":"REFERENCED_BY","extra":"Wiki references source file: backend/app/schemas/auth.py","gmt_create":"2026-05-23T15:24:01.907695+08:00","gmt_modified":"2026-05-23T15:24:01.907695+08:00"},{"id":2385,"source_id":"c7eb113b-b503-4d83-be7f-9ccf3350c9d9","target_id":"5013cbe89f1c6f03533eb218400cedb0","source_type":"WIKI_ITEM","target_type":"SOURCE_FILE","relationship_type":"REFERENCED_BY","extra":"Wiki references source file: backend/app/schemas/subscription.py","gmt_create":"2026-05-23T15:24:01.908564+08:00","gmt_modified":"2026-05-23T15:24:01.908564+08:00"},{"id":2386,"source_id":"c7eb113b-b503-4d83-be7f-9ccf3350c9d9","target_id":"c59f8c276697a070dffc581fe94d809c","source_type":"WIKI_ITEM","target_type":"SOURCE_FILE","relationship_type":"REFERENCED_BY","extra":"Wiki references source file: backend/app/models/user.py","gmt_create":"2026-05-23T15:24:01.909612+08:00","gmt_modified":"2026-05-23T15:24:01.909613+08:00"},{"id":2387,"source_id":"c7eb113b-b503-4d83-be7f-9ccf3350c9d9","target_id":"b74caccb06844efcdb14d8324cff65c2","source_type":"WIKI_ITEM","target_type":"SOURCE_FILE","relationship_type":"REFERENCED_BY","extra":"Wiki references source file: backend/app/models/query.py","gmt_create":"2026-05-23T15:24:01.910653+08:00","gmt_modified":"2026-05-23T15:24:01.910653+08:00"},{"id":2388,"source_id":"c7eb113b-b503-4d83-be7f-9ccf3350c9d9","target_id":"b4a81ef789630d0af6a8d50859d01bf3","source_type":"WIKI_ITEM","target_type":"SOURCE_FILE","relationship_type":"REFERENCED_BY","extra":"Wiki references source file: backend/app/models/citation_record.py","gmt_create":"2026-05-23T15:24:01.911648+08:00","gmt_modified":"2026-05-23T15:24:01.911648+08:00"},{"id":2389,"source_id":"c7eb113b-b503-4d83-be7f-9ccf3350c9d9","target_id":"bceca00463fe55d3bcafda728f97f723","source_type":"WIKI_ITEM","target_type":"SOURCE_FILE","relationship_type":"REFERENCED_BY","extra":"Wiki references source file: backend/app/models/subscription.py","gmt_create":"2026-05-23T15:24:01.91297+08:00","gmt_modified":"2026-05-23T15:24:01.912971+08:00"},{"id":2390,"source_id":"c7eb113b-b503-4d83-be7f-9ccf3350c9d9","target_id":"069738f21ac2da7349d22683e8c36929","source_type":"WIKI_ITEM","target_type":"SOURCE_FILE","relationship_type":"REFERENCED_BY","extra":"Wiki references source file: backend/app/models/query_task.py","gmt_create":"2026-05-23T15:24:01.914556+08:00","gmt_modified":"2026-05-23T15:24:01.914556+08:00"},{"id":2391,"source_id":"c7eb113b-b503-4d83-be7f-9ccf3350c9d9","target_id":"4d2f3847b7c10634733118b70a1aea0b","source_type":"WIKI_ITEM","target_type":"SOURCE_FILE","relationship_type":"REFERENCED_BY","extra":"Wiki references source file: backend/app/services/auth.py","gmt_create":"2026-05-23T15:24:01.916029+08:00","gmt_modified":"2026-05-23T15:24:01.916029+08:00"},{"id":2392,"source_id":"c7eb113b-b503-4d83-be7f-9ccf3350c9d9","target_id":"3809c5ab912511e0e093ba02a4fc918f","source_type":"WIKI_ITEM","target_type":"SOURCE_FILE","relationship_type":"REFERENCED_BY","extra":"Wiki references source file: backend/app/services/admin.py","gmt_create":"2026-05-23T15:24:01.917356+08:00","gmt_modified":"2026-05-23T15:24:01.917356+08:00"},{"id":2393,"source_id":"c7eb113b-b503-4d83-be7f-9ccf3350c9d9","target_id":"b250fc6c32106a7f3e0c3ad152dfc097","source_type":"WIKI_ITEM","target_type":"SOURCE_FILE","relationship_type":"REFERENCED_BY","extra":"Wiki references source file: backend/app/services/subscription.py","gmt_create":"2026-05-23T15:24:01.918488+08:00","gmt_modified":"2026-05-23T15:24:01.918488+08:00"},{"id":2394,"source_id":"c7eb113b-b503-4d83-be7f-9ccf3350c9d9","target_id":"5cbb1e3f112aeba62a14b0b8999fc0f5","source_type":"WIKI_ITEM","target_type":"SOURCE_FILE","relationship_type":"REFERENCED_BY","extra":"Wiki references source file: backend/app/workers/scheduler.py","gmt_create":"2026-05-23T15:24:01.920149+08:00","gmt_modified":"2026-05-23T15:24:01.920149+08:00"},{"id":2395,"source_id":"c7eb113b-b503-4d83-be7f-9ccf3350c9d9","target_id":"74040de652d5e57f548bb5c4adc3e1a0","source_type":"WIKI_ITEM","target_type":"SOURCE_FILE","relationship_type":"REFERENCED_BY","extra":"Wiki references source file: backend/app/workers/citation_engine.py","gmt_create":"2026-05-23T15:24:01.921207+08:00","gmt_modified":"2026-05-23T15:24:01.921207+08:00"},{"id":2396,"source_id":"c7eb113b-b503-4d83-be7f-9ccf3350c9d9","target_id":"ca1e69e3279cea977bb7f660d417b4d8","source_type":"WIKI_ITEM","target_type":"SOURCE_FILE","relationship_type":"REFERENCED_BY","extra":"Wiki references source file: backend/app/workers/llm_adapter.py","gmt_create":"2026-05-23T15:24:01.922119+08:00","gmt_modified":"2026-05-23T15:24:01.922119+08:00"},{"id":2397,"source_id":"c7eb113b-b503-4d83-be7f-9ccf3350c9d9","target_id":"249d68c4ba50c523b617a8c82e7afdae","source_type":"WIKI_ITEM","target_type":"SOURCE_FILE","relationship_type":"REFERENCED_BY","extra":"Wiki references source file: backend/app/agent_framework/base.py","gmt_create":"2026-05-23T15:24:01.923776+08:00","gmt_modified":"2026-05-23T15:24:01.923777+08:00"},{"id":2398,"source_id":"c7eb113b-b503-4d83-be7f-9ccf3350c9d9","target_id":"fcde401daccbe6de50f3829f021ecf55","source_type":"WIKI_ITEM","target_type":"SOURCE_FILE","relationship_type":"REFERENCED_BY","extra":"Wiki references source file: backend/app/agent_framework/dispatcher.py","gmt_create":"2026-05-23T15:24:01.926306+08:00","gmt_modified":"2026-05-23T15:24:01.926307+08:00"},{"id":2399,"source_id":"c7eb113b-b503-4d83-be7f-9ccf3350c9d9","target_id":"5d2b9655ba99a14a3accb1878bb5681a","source_type":"WIKI_ITEM","target_type":"SOURCE_FILE","relationship_type":"REFERENCED_BY","extra":"Wiki references source file: backend/app/agent_framework/registry.py","gmt_create":"2026-05-23T15:24:01.92773+08:00","gmt_modified":"2026-05-23T15:24:01.92773+08:00"},{"id":2400,"source_id":"c7eb113b-b503-4d83-be7f-9ccf3350c9d9","target_id":"609a02c9e1ccc0311885a70578b86386","source_type":"WIKI_ITEM","target_type":"SOURCE_FILE","relationship_type":"REFERENCED_BY","extra":"Wiki references source file: backend/app/agent_framework/pipeline/engine.py","gmt_create":"2026-05-23T15:24:01.929101+08:00","gmt_modified":"2026-05-23T15:24:01.929101+08:00"},{"id":2401,"source_id":"c7eb113b-b503-4d83-be7f-9ccf3350c9d9","target_id":"43642bd7bedabd97ff2f0a902b783e4e","source_type":"WIKI_ITEM","target_type":"SOURCE_FILE","relationship_type":"REFERENCED_BY","extra":"Wiki references source file: backend/app/agent_framework/pipeline/loader.py","gmt_create":"2026-05-23T15:24:01.934695+08:00","gmt_modified":"2026-05-23T15:24:01.934695+08:00"},{"id":2402,"source_id":"c7eb113b-b503-4d83-be7f-9ccf3350c9d9","target_id":"022c381f121cc2a65834024ca2c9b8c1","source_type":"WIKI_ITEM","target_type":"SOURCE_FILE","relationship_type":"REFERENCED_BY","extra":"Wiki references source file: backend/app/agent_framework/pipeline/schema.py","gmt_create":"2026-05-23T15:24:01.937634+08:00","gmt_modified":"2026-05-23T15:24:01.937634+08:00"},{"id":2403,"source_id":"c7eb113b-b503-4d83-be7f-9ccf3350c9d9","target_id":"3a2a43dd94c9405ea91934c43cdecced","source_type":"WIKI_ITEM","target_type":"SOURCE_FILE","relationship_type":"REFERENCED_BY","extra":"Wiki references source file: backend/app/agent_framework/protocol.py","gmt_create":"2026-05-23T15:24:01.939352+08:00","gmt_modified":"2026-05-23T15:24:01.939352+08:00"},{"id":2404,"source_id":"c7eb113b-b503-4d83-be7f-9ccf3350c9d9","target_id":"13b8f594e7cace5c8a9255dc801dcad8","source_type":"WIKI_ITEM","target_type":"SOURCE_FILE","relationship_type":"REFERENCED_BY","extra":"Wiki references source file: backend/app/agent_framework/agents/content_generator_agent.py","gmt_create":"2026-05-23T15:24:01.940783+08:00","gmt_modified":"2026-05-23T15:24:01.940784+08:00"},{"id":2405,"source_id":"c7eb113b-b503-4d83-be7f-9ccf3350c9d9","target_id":"7f8c6e94ead45ad9bab8cea9a7be2123","source_type":"WIKI_ITEM","target_type":"SOURCE_FILE","relationship_type":"REFERENCED_BY","extra":"Wiki references source file: backend/app/agent_framework/agents/geo_optimizer_agent.py","gmt_create":"2026-05-23T15:24:01.943003+08:00","gmt_modified":"2026-05-23T15:24:01.943003+08:00"},{"id":2406,"source_id":"c7eb113b-b503-4d83-be7f-9ccf3350c9d9","target_id":"1de27749fbccdfaf785545657f58d256","source_type":"WIKI_ITEM","target_type":"SOURCE_FILE","relationship_type":"REFERENCED_BY","extra":"Wiki references source file: backend/app/services/llm/factory.py","gmt_create":"2026-05-23T15:24:01.966133+08:00","gmt_modified":"2026-05-23T15:24:01.966133+08:00"},{"id":2407,"source_id":"c7eb113b-b503-4d83-be7f-9ccf3350c9d9","target_id":"aa6cf63a65ebf46a29606af91112eb7b","source_type":"WIKI_ITEM","target_type":"SOURCE_FILE","relationship_type":"REFERENCED_BY","extra":"Wiki references source file: backend/app/models/agent.py","gmt_create":"2026-05-23T15:24:01.969813+08:00","gmt_modified":"2026-05-23T15:24:01.969813+08:00"},{"id":2408,"source_id":"c7eb113b-b503-4d83-be7f-9ccf3350c9d9","target_id":"fffc152ed28771e8a42e5bb2e33650cd","source_type":"WIKI_ITEM","target_type":"SOURCE_FILE","relationship_type":"REFERENCED_BY","extra":"Wiki references source file: backend/pipelines/content_production.yaml","gmt_create":"2026-05-23T15:24:01.971665+08:00","gmt_modified":"2026-05-23T15:24:01.971665+08:00"},{"id":2409,"source_id":"c7eb113b-b503-4d83-be7f-9ccf3350c9d9","target_id":"856c9e5eddcb40682e653dbd1a4bfc4b","source_type":"WIKI_ITEM","target_type":"SOURCE_FILE","relationship_type":"REFERENCED_BY","extra":"Wiki references source file: backend/pipelines/diagnosis.yaml","gmt_create":"2026-05-23T15:24:01.972907+08:00","gmt_modified":"2026-05-23T15:24:01.972907+08:00"},{"id":2410,"source_id":"c7eb113b-b503-4d83-be7f-9ccf3350c9d9","target_id":"c2747ca16b879bca0f68955534c3c4fc","source_type":"WIKI_ITEM","target_type":"CODE_SNIPPET","relationship_type":"CONTAINS","extra":"Wiki contains code snippet: backend/app/main.py#1-48","gmt_create":"2026-05-23T15:24:01.975078+08:00","gmt_modified":"2026-05-23T15:24:01.975078+08:00"},{"id":2411,"source_id":"c7eb113b-b503-4d83-be7f-9ccf3350c9d9","target_id":"84fbed7d35f7752e2117a74fcaf5f0e9","source_type":"WIKI_ITEM","target_type":"CODE_SNIPPET","relationship_type":"CONTAINS","extra":"Wiki contains code snippet: backend/app/config.py#1-17","gmt_create":"2026-05-23T15:24:01.976777+08:00","gmt_modified":"2026-05-23T15:24:01.976777+08:00"},{"id":2412,"source_id":"c7eb113b-b503-4d83-be7f-9ccf3350c9d9","target_id":"9bfc041fe426da2eb78353827e8d9163","source_type":"WIKI_ITEM","target_type":"CODE_SNIPPET","relationship_type":"CONTAINS","extra":"Wiki contains code snippet: backend/app/database.py#1-29","gmt_create":"2026-05-23T15:24:01.978153+08:00","gmt_modified":"2026-05-23T15:24:01.978153+08:00"},{"id":2413,"source_id":"c7eb113b-b503-4d83-be7f-9ccf3350c9d9","target_id":"6c080aba7d0e611bd4e7f268835b630f","source_type":"WIKI_ITEM","target_type":"CODE_SNIPPET","relationship_type":"CONTAINS","extra":"Wiki contains code snippet: backend/app/middleware/logging_middleware.py#1-24","gmt_create":"2026-05-23T15:24:01.981529+08:00","gmt_modified":"2026-05-23T15:24:01.981529+08:00"},{"id":2414,"source_id":"c7eb113b-b503-4d83-be7f-9ccf3350c9d9","target_id":"a7bba55ddc4dd5d215e881e8432d83ea","source_type":"WIKI_ITEM","target_type":"CODE_SNIPPET","relationship_type":"CONTAINS","extra":"Wiki contains code snippet: backend/app/middleware/rate_limit.py#1-83","gmt_create":"2026-05-23T15:24:01.983855+08:00","gmt_modified":"2026-05-23T15:24:01.983855+08:00"},{"id":2415,"source_id":"c7eb113b-b503-4d83-be7f-9ccf3350c9d9","target_id":"041b88dd888e1118b1b0be80f9ec4904","source_type":"WIKI_ITEM","target_type":"CODE_SNIPPET","relationship_type":"CONTAINS","extra":"Wiki contains code snippet: backend/app/agent_framework/base.py#1-223","gmt_create":"2026-05-23T15:24:01.987813+08:00","gmt_modified":"2026-05-23T15:24:01.987813+08:00"},{"id":2416,"source_id":"249d68c4ba50c523b617a8c82e7afdae","target_id":"041b88dd888e1118b1b0be80f9ec4904","source_type":"SOURCE_FILE","target_type":"CODE_SNIPPET","relationship_type":"CONTAINS","extra":"Source file contains code snippet: 1-223","gmt_create":"2026-05-23T15:24:01.988985+08:00","gmt_modified":"2026-05-23T15:24:01.988986+08:00"},{"id":2417,"source_id":"c7eb113b-b503-4d83-be7f-9ccf3350c9d9","target_id":"aba7dcba1181acae0e810fe447807010","source_type":"WIKI_ITEM","target_type":"CODE_SNIPPET","relationship_type":"CONTAINS","extra":"Wiki contains code snippet: backend/app/agent_framework/registry.py#1-219","gmt_create":"2026-05-23T15:24:01.990499+08:00","gmt_modified":"2026-05-23T15:24:01.990499+08:00"},{"id":2418,"source_id":"5d2b9655ba99a14a3accb1878bb5681a","target_id":"aba7dcba1181acae0e810fe447807010","source_type":"SOURCE_FILE","target_type":"CODE_SNIPPET","relationship_type":"CONTAINS","extra":"Source file contains code snippet: 1-219","gmt_create":"2026-05-23T15:24:01.992162+08:00","gmt_modified":"2026-05-23T15:24:01.992162+08:00"},{"id":2419,"source_id":"c7eb113b-b503-4d83-be7f-9ccf3350c9d9","target_id":"5dd1642d800053635d9827e12e6ea120","source_type":"WIKI_ITEM","target_type":"CODE_SNIPPET","relationship_type":"CONTAINS","extra":"Wiki contains code snippet: backend/app/agent_framework/dispatcher.py#1-367","gmt_create":"2026-05-23T15:24:01.993803+08:00","gmt_modified":"2026-05-23T15:24:01.993803+08:00"},{"id":2420,"source_id":"c7eb113b-b503-4d83-be7f-9ccf3350c9d9","target_id":"74bf1d1b17dff651c44a2f4dc12d7bc7","source_type":"WIKI_ITEM","target_type":"CODE_SNIPPET","relationship_type":"CONTAINS","extra":"Wiki contains code snippet: backend/app/agent_framework/pipeline/engine.py#1-536","gmt_create":"2026-05-23T15:24:01.996583+08:00","gmt_modified":"2026-05-23T15:24:01.996583+08:00"},{"id":2421,"source_id":"c7eb113b-b503-4d83-be7f-9ccf3350c9d9","target_id":"3d0cd79c03fc72299fb184947c5d0d6c","source_type":"WIKI_ITEM","target_type":"CODE_SNIPPET","relationship_type":"CONTAINS","extra":"Wiki contains code snippet: backend/app/services/llm/factory.py#1-66","gmt_create":"2026-05-23T15:24:01.999333+08:00","gmt_modified":"2026-05-23T15:24:01.999334+08:00"},{"id":2422,"source_id":"c7eb113b-b503-4d83-be7f-9ccf3350c9d9","target_id":"4a0f6c5332f954161992df9247e63a97","source_type":"WIKI_ITEM","target_type":"CODE_SNIPPET","relationship_type":"CONTAINS","extra":"Wiki contains code snippet: backend/app/workers/llm_adapter.py#1-281","gmt_create":"2026-05-23T15:24:02.002496+08:00","gmt_modified":"2026-05-23T15:24:02.002496+08:00"},{"id":2423,"source_id":"ca1e69e3279cea977bb7f660d417b4d8","target_id":"4a0f6c5332f954161992df9247e63a97","source_type":"SOURCE_FILE","target_type":"CODE_SNIPPET","relationship_type":"CONTAINS","extra":"Source file contains code snippet: 1-281","gmt_create":"2026-05-23T15:24:02.003816+08:00","gmt_modified":"2026-05-23T15:24:02.003816+08:00"},{"id":2424,"source_id":"c7eb113b-b503-4d83-be7f-9ccf3350c9d9","target_id":"d432677dc357ec0518cc70701962e6bd","source_type":"WIKI_ITEM","target_type":"CODE_SNIPPET","relationship_type":"CONTAINS","extra":"Wiki contains code snippet: backend/pipelines/content_production.yaml#1-65","gmt_create":"2026-05-23T15:24:02.005942+08:00","gmt_modified":"2026-05-23T15:24:02.005943+08:00"},{"id":2425,"source_id":"fffc152ed28771e8a42e5bb2e33650cd","target_id":"d432677dc357ec0518cc70701962e6bd","source_type":"SOURCE_FILE","target_type":"CODE_SNIPPET","relationship_type":"CONTAINS","extra":"Source file contains code snippet: 1-65","gmt_create":"2026-05-23T15:24:02.008305+08:00","gmt_modified":"2026-05-23T15:24:02.008305+08:00"},{"id":2426,"source_id":"c7eb113b-b503-4d83-be7f-9ccf3350c9d9","target_id":"3d50a008bc36ea9fed48168c2597933d","source_type":"WIKI_ITEM","target_type":"CODE_SNIPPET","relationship_type":"CONTAINS","extra":"Wiki contains code snippet: backend/pipelines/diagnosis.yaml#1-30","gmt_create":"2026-05-23T15:24:02.010478+08:00","gmt_modified":"2026-05-23T15:24:02.010478+08:00"},{"id":2427,"source_id":"856c9e5eddcb40682e653dbd1a4bfc4b","target_id":"3d50a008bc36ea9fed48168c2597933d","source_type":"SOURCE_FILE","target_type":"CODE_SNIPPET","relationship_type":"CONTAINS","extra":"Source file contains code snippet: 1-30","gmt_create":"2026-05-23T15:24:02.011439+08:00","gmt_modified":"2026-05-23T15:24:02.01144+08:00"},{"id":2428,"source_id":"c7eb113b-b503-4d83-be7f-9ccf3350c9d9","target_id":"e2d4838e58acc0eee236ef586abab64e","source_type":"WIKI_ITEM","target_type":"CODE_SNIPPET","relationship_type":"CONTAINS","extra":"Wiki contains code snippet: backend/app/main.py#13-48","gmt_create":"2026-05-23T15:24:02.017686+08:00","gmt_modified":"2026-05-23T15:24:02.017686+08:00"},{"id":2429,"source_id":"c7eb113b-b503-4d83-be7f-9ccf3350c9d9","target_id":"8aee7654d1f435ab53d8ddaabd269fed","source_type":"WIKI_ITEM","target_type":"CODE_SNIPPET","relationship_type":"CONTAINS","extra":"Wiki contains code snippet: backend/app/database.py#6-29","gmt_create":"2026-05-23T15:24:02.019679+08:00","gmt_modified":"2026-05-23T15:24:02.019679+08:00"},{"id":2430,"source_id":"c7eb113b-b503-4d83-be7f-9ccf3350c9d9","target_id":"acd9e6c32084e589d5aeb1665d918dfd","source_type":"WIKI_ITEM","target_type":"CODE_SNIPPET","relationship_type":"CONTAINS","extra":"Wiki contains code snippet: backend/app/api/deps.py#13-43","gmt_create":"2026-05-23T15:24:02.021548+08:00","gmt_modified":"2026-05-23T15:24:02.021548+08:00"},{"id":2431,"source_id":"c7eb113b-b503-4d83-be7f-9ccf3350c9d9","target_id":"33ec8bca51cb9f667bf91088dd6b6a70","source_type":"WIKI_ITEM","target_type":"CODE_SNIPPET","relationship_type":"CONTAINS","extra":"Wiki contains code snippet: backend/app/main.py#24-48","gmt_create":"2026-05-23T15:24:02.023714+08:00","gmt_modified":"2026-05-23T15:24:02.023715+08:00"},{"id":2432,"source_id":"c7eb113b-b503-4d83-be7f-9ccf3350c9d9","target_id":"712424bd3bd3d5f39b1a0a72acc9952a","source_type":"WIKI_ITEM","target_type":"CODE_SNIPPET","relationship_type":"CONTAINS","extra":"Wiki contains code snippet: backend/app/middleware/rate_limit.py#10-83","gmt_create":"2026-05-23T15:24:02.026139+08:00","gmt_modified":"2026-05-23T15:24:02.02614+08:00"},{"id":2433,"source_id":"c7eb113b-b503-4d83-be7f-9ccf3350c9d9","target_id":"9357a0fcca02068d428f4a191d08fdcd","source_type":"WIKI_ITEM","target_type":"CODE_SNIPPET","relationship_type":"CONTAINS","extra":"Wiki contains code snippet: backend/app/middleware/logging_middleware.py#8-24","gmt_create":"2026-05-23T15:24:02.03014+08:00","gmt_modified":"2026-05-23T15:24:02.030141+08:00"},{"id":2434,"source_id":"c7eb113b-b503-4d83-be7f-9ccf3350c9d9","target_id":"069243fafe60a85cf16a0ca40fa07180","source_type":"WIKI_ITEM","target_type":"CODE_SNIPPET","relationship_type":"CONTAINS","extra":"Wiki contains code snippet: backend/app/api/deps.py#16-43","gmt_create":"2026-05-23T15:24:02.03315+08:00","gmt_modified":"2026-05-23T15:24:02.03315+08:00"},{"id":2435,"source_id":"c7eb113b-b503-4d83-be7f-9ccf3350c9d9","target_id":"8efcce12915471fe5b88fe058bcf238e","source_type":"WIKI_ITEM","target_type":"CODE_SNIPPET","relationship_type":"CONTAINS","extra":"Wiki contains code snippet: backend/app/services/auth.py#16-69","gmt_create":"2026-05-23T15:24:02.03673+08:00","gmt_modified":"2026-05-23T15:24:02.03673+08:00"},{"id":2436,"source_id":"c7eb113b-b503-4d83-be7f-9ccf3350c9d9","target_id":"7f81ebbdde3496054e6f43f5eef366dc","source_type":"WIKI_ITEM","target_type":"CODE_SNIPPET","relationship_type":"CONTAINS","extra":"Wiki contains code snippet: backend/app/services/admin.py#14-188","gmt_create":"2026-05-23T15:24:02.03863+08:00","gmt_modified":"2026-05-23T15:24:02.03863+08:00"},{"id":2437,"source_id":"c7eb113b-b503-4d83-be7f-9ccf3350c9d9","target_id":"f4d57f9a78585969a006b7451ea8ce84","source_type":"WIKI_ITEM","target_type":"CODE_SNIPPET","relationship_type":"CONTAINS","extra":"Wiki contains code snippet: backend/app/services/subscription.py#69-155","gmt_create":"2026-05-23T15:24:02.040327+08:00","gmt_modified":"2026-05-23T15:24:02.040327+08:00"},{"id":2438,"source_id":"c7eb113b-b503-4d83-be7f-9ccf3350c9d9","target_id":"e230904202fcf7a861c6f49b84f9f863","source_type":"WIKI_ITEM","target_type":"CODE_SNIPPET","relationship_type":"CONTAINS","extra":"Wiki contains code snippet: backend/app/workers/scheduler.py#25-95","gmt_create":"2026-05-23T15:24:02.042114+08:00","gmt_modified":"2026-05-23T15:24:02.042114+08:00"},{"id":2439,"source_id":"c7eb113b-b503-4d83-be7f-9ccf3350c9d9","target_id":"309607c54b12a6340edc086ffb4737c9","source_type":"WIKI_ITEM","target_type":"CODE_SNIPPET","relationship_type":"CONTAINS","extra":"Wiki contains code snippet: backend/app/workers/citation_engine.py#148-309","gmt_create":"2026-05-23T15:24:02.044717+08:00","gmt_modified":"2026-05-23T15:24:02.044717+08:00"},{"id":2440,"source_id":"c7eb113b-b503-4d83-be7f-9ccf3350c9d9","target_id":"096856da621e23e78422a15e2bfce1f1","source_type":"WIKI_ITEM","target_type":"CODE_SNIPPET","relationship_type":"CONTAINS","extra":"Wiki contains code snippet: backend/app/main.py#13-22","gmt_create":"2026-05-23T15:24:02.056222+08:00","gmt_modified":"2026-05-23T15:24:02.056223+08:00"},{"id":2441,"source_id":"c7eb113b-b503-4d83-be7f-9ccf3350c9d9","target_id":"129b746e71a9013ceb1b0fcc59942b39","source_type":"WIKI_ITEM","target_type":"CODE_SNIPPET","relationship_type":"CONTAINS","extra":"Wiki contains code snippet: backend/app/workers/scheduler.py#86-90","gmt_create":"2026-05-23T15:24:02.057668+08:00","gmt_modified":"2026-05-23T15:24:02.057668+08:00"},{"id":2442,"source_id":"c7eb113b-b503-4d83-be7f-9ccf3350c9d9","target_id":"608c00e1835ad72363ef08796961faca","source_type":"WIKI_ITEM","target_type":"CODE_SNIPPET","relationship_type":"CONTAINS","extra":"Wiki contains code snippet: backend/app/config.py#4-17","gmt_create":"2026-05-23T15:24:02.061919+08:00","gmt_modified":"2026-05-23T15:24:02.061919+08:00"},{"id":2443,"source_id":"c7eb113b-b503-4d83-be7f-9ccf3350c9d9","target_id":"d5a1fb0bd23ce9240fbf79529ef94a45","source_type":"WIKI_ITEM","target_type":"CODE_SNIPPET","relationship_type":"CONTAINS","extra":"Wiki contains code snippet: backend/app/api/auth.py#13-43","gmt_create":"2026-05-23T15:24:02.073361+08:00","gmt_modified":"2026-05-23T15:24:02.073361+08:00"},{"id":2444,"source_id":"c7eb113b-b503-4d83-be7f-9ccf3350c9d9","target_id":"753a437d837246ead62b0e16c6331284","source_type":"WIKI_ITEM","target_type":"CODE_SNIPPET","relationship_type":"CONTAINS","extra":"Wiki contains code snippet: backend/app/services/auth.py#37-69","gmt_create":"2026-05-23T15:24:02.07737+08:00","gmt_modified":"2026-05-23T15:24:02.07737+08:00"},{"id":2445,"source_id":"c7eb113b-b503-4d83-be7f-9ccf3350c9d9","target_id":"f66d9907b467b110c638bd527efd95c5","source_type":"WIKI_ITEM","target_type":"CODE_SNIPPET","relationship_type":"CONTAINS","extra":"Wiki contains code snippet: backend/app/api/auth.py#1-43","gmt_create":"2026-05-23T15:24:02.082052+08:00","gmt_modified":"2026-05-23T15:24:02.082052+08:00"},{"id":2446,"source_id":"c7eb113b-b503-4d83-be7f-9ccf3350c9d9","target_id":"6f637c2b0796ec533aafb3b865c11cf0","source_type":"WIKI_ITEM","target_type":"CODE_SNIPPET","relationship_type":"CONTAINS","extra":"Wiki contains code snippet: backend/app/schemas/auth.py#1-34","gmt_create":"2026-05-23T15:24:02.084374+08:00","gmt_modified":"2026-05-23T15:24:02.084374+08:00"},{"id":2447,"source_id":"c7eb113b-b503-4d83-be7f-9ccf3350c9d9","target_id":"56e46969bdb790a5e8f333184b878d6d","source_type":"WIKI_ITEM","target_type":"CODE_SNIPPET","relationship_type":"CONTAINS","extra":"Wiki contains code snippet: backend/app/models/user.py#11-41","gmt_create":"2026-05-23T15:24:02.086491+08:00","gmt_modified":"2026-05-23T15:24:02.086491+08:00"},{"id":2448,"source_id":"c7eb113b-b503-4d83-be7f-9ccf3350c9d9","target_id":"1a439c5fed6cfd188c646e1614d56371","source_type":"WIKI_ITEM","target_type":"CODE_SNIPPET","relationship_type":"CONTAINS","extra":"Wiki contains code snippet: backend/app/services/auth.py#1-69","gmt_create":"2026-05-23T15:24:02.088247+08:00","gmt_modified":"2026-05-23T15:24:02.088248+08:00"},{"id":2449,"source_id":"c7eb113b-b503-4d83-be7f-9ccf3350c9d9","target_id":"76e6c0abb49fec57cac4892837a143c9","source_type":"WIKI_ITEM","target_type":"CODE_SNIPPET","relationship_type":"CONTAINS","extra":"Wiki contains code snippet: backend/app/api/deps.py#1-43","gmt_create":"2026-05-23T15:24:02.090104+08:00","gmt_modified":"2026-05-23T15:24:02.090104+08:00"},{"id":2450,"source_id":"c7eb113b-b503-4d83-be7f-9ccf3350c9d9","target_id":"98c02d9bb7aa6e2b6be5f7381e64fd99","source_type":"WIKI_ITEM","target_type":"CODE_SNIPPET","relationship_type":"CONTAINS","extra":"Wiki contains code snippet: backend/app/api/queries.py#26-39","gmt_create":"2026-05-23T15:24:02.092831+08:00","gmt_modified":"2026-05-23T15:24:02.092831+08:00"},{"id":2451,"source_id":"c7eb113b-b503-4d83-be7f-9ccf3350c9d9","target_id":"10d1e37bdc9f353c189b7a2fe79dc85e","source_type":"WIKI_ITEM","target_type":"CODE_SNIPPET","relationship_type":"CONTAINS","extra":"Wiki contains code snippet: backend/app/api/queries.py#1-86","gmt_create":"2026-05-23T15:24:02.096743+08:00","gmt_modified":"2026-05-23T15:24:02.096744+08:00"},{"id":2452,"source_id":"c7eb113b-b503-4d83-be7f-9ccf3350c9d9","target_id":"cbd0101fa84d957bcb1baaa623c6b31c","source_type":"WIKI_ITEM","target_type":"CODE_SNIPPET","relationship_type":"CONTAINS","extra":"Wiki contains code snippet: backend/app/api/citations.py#1-78","gmt_create":"2026-05-23T15:24:02.099354+08:00","gmt_modified":"2026-05-23T15:24:02.099355+08:00"},{"id":2453,"source_id":"c7eb113b-b503-4d83-be7f-9ccf3350c9d9","target_id":"ec4bf600a513dc2b014c85e141d7582d","source_type":"WIKI_ITEM","target_type":"CODE_SNIPPET","relationship_type":"CONTAINS","extra":"Wiki contains code snippet: backend/app/workers/scheduler.py#51-85","gmt_create":"2026-05-23T15:24:02.102067+08:00","gmt_modified":"2026-05-23T15:24:02.102067+08:00"},{"id":2454,"source_id":"c7eb113b-b503-4d83-be7f-9ccf3350c9d9","target_id":"160b5326537d25444c40a459a01e79c6","source_type":"WIKI_ITEM","target_type":"CODE_SNIPPET","relationship_type":"CONTAINS","extra":"Wiki contains code snippet: backend/app/workers/citation_engine.py#159-234","gmt_create":"2026-05-23T15:24:02.103972+08:00","gmt_modified":"2026-05-23T15:24:02.103973+08:00"},{"id":2455,"source_id":"c7eb113b-b503-4d83-be7f-9ccf3350c9d9","target_id":"71f98c8993fb42b108e34a554247869b","source_type":"WIKI_ITEM","target_type":"CODE_SNIPPET","relationship_type":"CONTAINS","extra":"Wiki contains code snippet: backend/app/workers/scheduler.py#1-95","gmt_create":"2026-05-23T15:24:02.106422+08:00","gmt_modified":"2026-05-23T15:24:02.106422+08:00"},{"id":2456,"source_id":"c7eb113b-b503-4d83-be7f-9ccf3350c9d9","target_id":"116584ea9162c1bc05911f39f9ef82b6","source_type":"WIKI_ITEM","target_type":"CODE_SNIPPET","relationship_type":"CONTAINS","extra":"Wiki contains code snippet: backend/app/workers/citation_engine.py#1-309","gmt_create":"2026-05-23T15:24:02.1083+08:00","gmt_modified":"2026-05-23T15:24:02.1083+08:00"},{"id":2457,"source_id":"c7eb113b-b503-4d83-be7f-9ccf3350c9d9","target_id":"4fb8856be3a581fe8303d11b2284ca29","source_type":"WIKI_ITEM","target_type":"CODE_SNIPPET","relationship_type":"CONTAINS","extra":"Wiki contains code snippet: backend/app/models/query.py#11-55","gmt_create":"2026-05-23T15:24:02.111934+08:00","gmt_modified":"2026-05-23T15:24:02.111934+08:00"},{"id":2458,"source_id":"c7eb113b-b503-4d83-be7f-9ccf3350c9d9","target_id":"fd541971cebf8a7c167d717f5c5d1ff6","source_type":"WIKI_ITEM","target_type":"CODE_SNIPPET","relationship_type":"CONTAINS","extra":"Wiki contains code snippet: backend/app/models/citation_record.py#11-42","gmt_create":"2026-05-23T15:24:02.115038+08:00","gmt_modified":"2026-05-23T15:24:02.115038+08:00"},{"id":2459,"source_id":"c7eb113b-b503-4d83-be7f-9ccf3350c9d9","target_id":"4d323bf0aaf4078f09726dc0890e5955","source_type":"WIKI_ITEM","target_type":"CODE_SNIPPET","relationship_type":"CONTAINS","extra":"Wiki contains code snippet: backend/app/models/subscription.py#11-37","gmt_create":"2026-05-23T15:24:02.116997+08:00","gmt_modified":"2026-05-23T15:24:02.116997+08:00"},{"id":2460,"source_id":"c7eb113b-b503-4d83-be7f-9ccf3350c9d9","target_id":"b84f46f058847733347974841f613688","source_type":"WIKI_ITEM","target_type":"CODE_SNIPPET","relationship_type":"CONTAINS","extra":"Wiki contains code snippet: backend/app/models/query_task.py#11-39","gmt_create":"2026-05-23T15:24:02.119131+08:00","gmt_modified":"2026-05-23T15:24:02.119131+08:00"},{"id":2461,"source_id":"c7eb113b-b503-4d83-be7f-9ccf3350c9d9","target_id":"ebc123c07512c5d5aeb1011d228a895c","source_type":"WIKI_ITEM","target_type":"CODE_SNIPPET","relationship_type":"CONTAINS","extra":"Wiki contains code snippet: backend/app/models/agent.py#12-206","gmt_create":"2026-05-23T15:24:02.120709+08:00","gmt_modified":"2026-05-23T15:24:02.120709+08:00"},{"id":2462,"source_id":"c7eb113b-b503-4d83-be7f-9ccf3350c9d9","target_id":"136f172c732d0cc130532a4f0df475a4","source_type":"WIKI_ITEM","target_type":"CODE_SNIPPET","relationship_type":"CONTAINS","extra":"Wiki contains code snippet: backend/app/models/user.py#1-41","gmt_create":"2026-05-23T15:24:02.122577+08:00","gmt_modified":"2026-05-23T15:24:02.122578+08:00"},{"id":2463,"source_id":"c7eb113b-b503-4d83-be7f-9ccf3350c9d9","target_id":"6281fff17a86ec1895c64d87c2ae7fb1","source_type":"WIKI_ITEM","target_type":"CODE_SNIPPET","relationship_type":"CONTAINS","extra":"Wiki contains code snippet: backend/app/models/query.py#1-55","gmt_create":"2026-05-23T15:24:02.124444+08:00","gmt_modified":"2026-05-23T15:24:02.124444+08:00"},{"id":2464,"source_id":"c7eb113b-b503-4d83-be7f-9ccf3350c9d9","target_id":"943c18db69a04b3137fba4cebcfea87e","source_type":"WIKI_ITEM","target_type":"CODE_SNIPPET","relationship_type":"CONTAINS","extra":"Wiki contains code snippet: backend/app/models/citation_record.py#1-42","gmt_create":"2026-05-23T15:24:02.126471+08:00","gmt_modified":"2026-05-23T15:24:02.126471+08:00"},{"id":2465,"source_id":"c7eb113b-b503-4d83-be7f-9ccf3350c9d9","target_id":"86e37040be1aeb400fab9b529f5404c8","source_type":"WIKI_ITEM","target_type":"CODE_SNIPPET","relationship_type":"CONTAINS","extra":"Wiki contains code snippet: backend/app/models/subscription.py#1-37","gmt_create":"2026-05-23T15:24:02.128513+08:00","gmt_modified":"2026-05-23T15:24:02.128513+08:00"},{"id":2466,"source_id":"c7eb113b-b503-4d83-be7f-9ccf3350c9d9","target_id":"6628e006b8e5ca16160743528b6b0506","source_type":"WIKI_ITEM","target_type":"CODE_SNIPPET","relationship_type":"CONTAINS","extra":"Wiki contains code snippet: backend/app/models/query_task.py#1-39","gmt_create":"2026-05-23T15:24:02.130666+08:00","gmt_modified":"2026-05-23T15:24:02.130666+08:00"},{"id":2467,"source_id":"c7eb113b-b503-4d83-be7f-9ccf3350c9d9","target_id":"bf0d60f20f3ea5a2f2458ba86d3f9173","source_type":"WIKI_ITEM","target_type":"CODE_SNIPPET","relationship_type":"CONTAINS","extra":"Wiki contains code snippet: backend/app/models/agent.py#1-206","gmt_create":"2026-05-23T15:24:02.133058+08:00","gmt_modified":"2026-05-23T15:24:02.133058+08:00"},{"id":2468,"source_id":"aa6cf63a65ebf46a29606af91112eb7b","target_id":"bf0d60f20f3ea5a2f2458ba86d3f9173","source_type":"SOURCE_FILE","target_type":"CODE_SNIPPET","relationship_type":"CONTAINS","extra":"Source file contains code snippet: 1-206","gmt_create":"2026-05-23T15:24:02.13419+08:00","gmt_modified":"2026-05-23T15:24:02.13419+08:00"},{"id":2469,"source_id":"c7eb113b-b503-4d83-be7f-9ccf3350c9d9","target_id":"81d750ebce1c6f458a3499de79002778","source_type":"WIKI_ITEM","target_type":"CODE_SNIPPET","relationship_type":"CONTAINS","extra":"Wiki contains code snippet: backend/app/agent_framework/base.py#52-114","gmt_create":"2026-05-23T15:24:02.135532+08:00","gmt_modified":"2026-05-23T15:24:02.135532+08:00"},{"id":2470,"source_id":"249d68c4ba50c523b617a8c82e7afdae","target_id":"81d750ebce1c6f458a3499de79002778","source_type":"SOURCE_FILE","target_type":"CODE_SNIPPET","relationship_type":"CONTAINS","extra":"Source file contains code snippet: 52-114","gmt_create":"2026-05-23T15:24:02.136549+08:00","gmt_modified":"2026-05-23T15:24:02.13655+08:00"},{"id":2471,"source_id":"c7eb113b-b503-4d83-be7f-9ccf3350c9d9","target_id":"07fd98ac292cc72700ce97168ed58d9a","source_type":"WIKI_ITEM","target_type":"CODE_SNIPPET","relationship_type":"CONTAINS","extra":"Wiki contains code snippet: backend/app/agent_framework/base.py#148-182","gmt_create":"2026-05-23T15:24:02.13822+08:00","gmt_modified":"2026-05-23T15:24:02.13822+08:00"},{"id":2472,"source_id":"249d68c4ba50c523b617a8c82e7afdae","target_id":"07fd98ac292cc72700ce97168ed58d9a","source_type":"SOURCE_FILE","target_type":"CODE_SNIPPET","relationship_type":"CONTAINS","extra":"Source file contains code snippet: 148-182","gmt_create":"2026-05-23T15:24:02.139464+08:00","gmt_modified":"2026-05-23T15:24:02.139464+08:00"},{"id":2473,"source_id":"c7eb113b-b503-4d83-be7f-9ccf3350c9d9","target_id":"ff27531ef3cacd097bc66aa7e982158d","source_type":"WIKI_ITEM","target_type":"CODE_SNIPPET","relationship_type":"CONTAINS","extra":"Wiki contains code snippet: backend/app/agent_framework/registry.py#29-80","gmt_create":"2026-05-23T15:24:02.140959+08:00","gmt_modified":"2026-05-23T15:24:02.140959+08:00"},{"id":2474,"source_id":"5d2b9655ba99a14a3accb1878bb5681a","target_id":"ff27531ef3cacd097bc66aa7e982158d","source_type":"SOURCE_FILE","target_type":"CODE_SNIPPET","relationship_type":"CONTAINS","extra":"Source file contains code snippet: 29-80","gmt_create":"2026-05-23T15:24:02.142015+08:00","gmt_modified":"2026-05-23T15:24:02.142015+08:00"},{"id":2475,"source_id":"c7eb113b-b503-4d83-be7f-9ccf3350c9d9","target_id":"27a49e5089cfba7405dc53418c54dd37","source_type":"WIKI_ITEM","target_type":"CODE_SNIPPET","relationship_type":"CONTAINS","extra":"Wiki contains code snippet: backend/app/agent_framework/registry.py#156-172","gmt_create":"2026-05-23T15:24:02.143356+08:00","gmt_modified":"2026-05-23T15:24:02.143357+08:00"},{"id":2476,"source_id":"5d2b9655ba99a14a3accb1878bb5681a","target_id":"27a49e5089cfba7405dc53418c54dd37","source_type":"SOURCE_FILE","target_type":"CODE_SNIPPET","relationship_type":"CONTAINS","extra":"Source file contains code snippet: 156-172","gmt_create":"2026-05-23T15:24:02.144831+08:00","gmt_modified":"2026-05-23T15:24:02.144832+08:00"},{"id":2477,"source_id":"c7eb113b-b503-4d83-be7f-9ccf3350c9d9","target_id":"c0d940dbb4ac9ef819aad6c16edc0d60","source_type":"WIKI_ITEM","target_type":"CODE_SNIPPET","relationship_type":"CONTAINS","extra":"Wiki contains code snippet: backend/app/agent_framework/registry.py#174-201","gmt_create":"2026-05-23T15:24:02.14687+08:00","gmt_modified":"2026-05-23T15:24:02.146871+08:00"},{"id":2478,"source_id":"5d2b9655ba99a14a3accb1878bb5681a","target_id":"c0d940dbb4ac9ef819aad6c16edc0d60","source_type":"SOURCE_FILE","target_type":"CODE_SNIPPET","relationship_type":"CONTAINS","extra":"Source file contains code snippet: 174-201","gmt_create":"2026-05-23T15:24:02.148253+08:00","gmt_modified":"2026-05-23T15:24:02.148253+08:00"},{"id":2479,"source_id":"c7eb113b-b503-4d83-be7f-9ccf3350c9d9","target_id":"f90f382f226eeca8bb1c111d10941fa0","source_type":"WIKI_ITEM","target_type":"CODE_SNIPPET","relationship_type":"CONTAINS","extra":"Wiki contains code snippet: backend/app/agent_framework/dispatcher.py#54-117","gmt_create":"2026-05-23T15:24:02.150151+08:00","gmt_modified":"2026-05-23T15:24:02.150152+08:00"},{"id":2480,"source_id":"c7eb113b-b503-4d83-be7f-9ccf3350c9d9","target_id":"7a66c4fd8249f7d534ebe9092faa1124","source_type":"WIKI_ITEM","target_type":"CODE_SNIPPET","relationship_type":"CONTAINS","extra":"Wiki contains code snippet: backend/app/agent_framework/dispatcher.py#169-218","gmt_create":"2026-05-23T15:24:02.151932+08:00","gmt_modified":"2026-05-23T15:24:02.151933+08:00"},{"id":2481,"source_id":"fcde401daccbe6de50f3829f021ecf55","target_id":"7a66c4fd8249f7d534ebe9092faa1124","source_type":"SOURCE_FILE","target_type":"CODE_SNIPPET","relationship_type":"CONTAINS","extra":"Source file contains code snippet: 169-218","gmt_create":"2026-05-23T15:24:02.153277+08:00","gmt_modified":"2026-05-23T15:24:02.153278+08:00"},{"id":2482,"source_id":"c7eb113b-b503-4d83-be7f-9ccf3350c9d9","target_id":"7a5c445db631fd099bd752645fe46eeb","source_type":"WIKI_ITEM","target_type":"CODE_SNIPPET","relationship_type":"CONTAINS","extra":"Wiki contains code snippet: backend/app/services/llm/factory.py#8-66","gmt_create":"2026-05-23T15:24:02.157921+08:00","gmt_modified":"2026-05-23T15:24:02.157921+08:00"},{"id":2483,"source_id":"c7eb113b-b503-4d83-be7f-9ccf3350c9d9","target_id":"962888e682bf9d3ceaa4d5bd5e75bb2c","source_type":"WIKI_ITEM","target_type":"CODE_SNIPPET","relationship_type":"CONTAINS","extra":"Wiki contains code snippet: backend/app/services/llm/factory.py#25-50","gmt_create":"2026-05-23T15:24:02.160559+08:00","gmt_modified":"2026-05-23T15:24:02.160559+08:00"},{"id":2484,"source_id":"1de27749fbccdfaf785545657f58d256","target_id":"962888e682bf9d3ceaa4d5bd5e75bb2c","source_type":"SOURCE_FILE","target_type":"CODE_SNIPPET","relationship_type":"CONTAINS","extra":"Source file contains code snippet: 25-50","gmt_create":"2026-05-23T15:24:02.161428+08:00","gmt_modified":"2026-05-23T15:24:02.161428+08:00"},{"id":2485,"source_id":"c7eb113b-b503-4d83-be7f-9ccf3350c9d9","target_id":"ea929f7dbed5834bb5b3e24ebb32a0bc","source_type":"WIKI_ITEM","target_type":"CODE_SNIPPET","relationship_type":"CONTAINS","extra":"Wiki contains code snippet: backend/app/workers/llm_adapter.py#71-110","gmt_create":"2026-05-23T15:24:02.162864+08:00","gmt_modified":"2026-05-23T15:24:02.162864+08:00"},{"id":2486,"source_id":"ca1e69e3279cea977bb7f660d417b4d8","target_id":"ea929f7dbed5834bb5b3e24ebb32a0bc","source_type":"SOURCE_FILE","target_type":"CODE_SNIPPET","relationship_type":"CONTAINS","extra":"Source file contains code snippet: 71-110","gmt_create":"2026-05-23T15:24:02.164264+08:00","gmt_modified":"2026-05-23T15:24:02.164265+08:00"},{"id":2487,"source_id":"c7eb113b-b503-4d83-be7f-9ccf3350c9d9","target_id":"ef16244eb1b5c1ab8774199c05bf0151","source_type":"WIKI_ITEM","target_type":"CODE_SNIPPET","relationship_type":"CONTAINS","extra":"Wiki contains code snippet: backend/app/workers/llm_adapter.py#220-270","gmt_create":"2026-05-23T15:24:02.16581+08:00","gmt_modified":"2026-05-23T15:24:02.16581+08:00"},{"id":2488,"source_id":"ca1e69e3279cea977bb7f660d417b4d8","target_id":"ef16244eb1b5c1ab8774199c05bf0151","source_type":"SOURCE_FILE","target_type":"CODE_SNIPPET","relationship_type":"CONTAINS","extra":"Source file contains code snippet: 220-270","gmt_create":"2026-05-23T15:24:02.166559+08:00","gmt_modified":"2026-05-23T15:24:02.166559+08:00"},{"id":2489,"source_id":"c7eb113b-b503-4d83-be7f-9ccf3350c9d9","target_id":"678dbba75fa1ffc2d9230f9e3ef7cc6f","source_type":"WIKI_ITEM","target_type":"CODE_SNIPPET","relationship_type":"CONTAINS","extra":"Wiki contains code snippet: backend/app/agent_framework/agents/content_generator_agent.py#111-182","gmt_create":"2026-05-23T15:24:02.169096+08:00","gmt_modified":"2026-05-23T15:24:02.169096+08:00"},{"id":2490,"source_id":"13b8f594e7cace5c8a9255dc801dcad8","target_id":"678dbba75fa1ffc2d9230f9e3ef7cc6f","source_type":"SOURCE_FILE","target_type":"CODE_SNIPPET","relationship_type":"CONTAINS","extra":"Source file contains code snippet: 111-182","gmt_create":"2026-05-23T15:24:02.169914+08:00","gmt_modified":"2026-05-23T15:24:02.169914+08:00"},{"id":2491,"source_id":"c7eb113b-b503-4d83-be7f-9ccf3350c9d9","target_id":"c32c02777f644d164c73710bcdd9c25c","source_type":"WIKI_ITEM","target_type":"CODE_SNIPPET","relationship_type":"CONTAINS","extra":"Wiki contains code snippet: backend/app/agent_framework/agents/content_generator_agent.py#184-252","gmt_create":"2026-05-23T15:24:02.171318+08:00","gmt_modified":"2026-05-23T15:24:02.171318+08:00"},{"id":2492,"source_id":"13b8f594e7cace5c8a9255dc801dcad8","target_id":"c32c02777f644d164c73710bcdd9c25c","source_type":"SOURCE_FILE","target_type":"CODE_SNIPPET","relationship_type":"CONTAINS","extra":"Source file contains code snippet: 184-252","gmt_create":"2026-05-23T15:24:02.17202+08:00","gmt_modified":"2026-05-23T15:24:02.17202+08:00"},{"id":2493,"source_id":"c7eb113b-b503-4d83-be7f-9ccf3350c9d9","target_id":"860a2f84ff90988124545bb7386f7e45","source_type":"WIKI_ITEM","target_type":"CODE_SNIPPET","relationship_type":"CONTAINS","extra":"Wiki contains code snippet: backend/app/agent_framework/agents/geo_optimizer_agent.py#104-180","gmt_create":"2026-05-23T15:24:02.173662+08:00","gmt_modified":"2026-05-23T15:24:02.173662+08:00"},{"id":2494,"source_id":"7f8c6e94ead45ad9bab8cea9a7be2123","target_id":"860a2f84ff90988124545bb7386f7e45","source_type":"SOURCE_FILE","target_type":"CODE_SNIPPET","relationship_type":"CONTAINS","extra":"Source file contains code snippet: 104-180","gmt_create":"2026-05-23T15:24:02.174936+08:00","gmt_modified":"2026-05-23T15:24:02.174937+08:00"},{"id":2495,"source_id":"c7eb113b-b503-4d83-be7f-9ccf3350c9d9","target_id":"461200c8ca02024dd32c214c679b9664","source_type":"WIKI_ITEM","target_type":"CODE_SNIPPET","relationship_type":"CONTAINS","extra":"Wiki contains code snippet: backend/app/agent_framework/agents/content_generator_agent.py#1-299","gmt_create":"2026-05-23T15:24:02.183488+08:00","gmt_modified":"2026-05-23T15:24:02.183488+08:00"},{"id":2496,"source_id":"c7eb113b-b503-4d83-be7f-9ccf3350c9d9","target_id":"45778eaa35d92099677ba180f1067905","source_type":"WIKI_ITEM","target_type":"CODE_SNIPPET","relationship_type":"CONTAINS","extra":"Wiki contains code snippet: backend/app/agent_framework/agents/geo_optimizer_agent.py#1-198","gmt_create":"2026-05-23T15:24:02.186913+08:00","gmt_modified":"2026-05-23T15:24:02.186913+08:00"},{"id":2497,"source_id":"c7eb113b-b503-4d83-be7f-9ccf3350c9d9","target_id":"ccbe69d125e99e73a7907f2c94c59cc3","source_type":"WIKI_ITEM","target_type":"CODE_SNIPPET","relationship_type":"CONTAINS","extra":"Wiki contains code snippet: backend/pipelines/content_production.yaml#9-65","gmt_create":"2026-05-23T15:24:02.191108+08:00","gmt_modified":"2026-05-23T15:24:02.191109+08:00"},{"id":2498,"source_id":"fffc152ed28771e8a42e5bb2e33650cd","target_id":"ccbe69d125e99e73a7907f2c94c59cc3","source_type":"SOURCE_FILE","target_type":"CODE_SNIPPET","relationship_type":"CONTAINS","extra":"Source file contains code snippet: 9-65","gmt_create":"2026-05-23T15:24:02.192794+08:00","gmt_modified":"2026-05-23T15:24:02.192795+08:00"},{"id":2499,"source_id":"c7eb113b-b503-4d83-be7f-9ccf3350c9d9","target_id":"63b5e7a6a9a5545b70747bcbcae293f9","source_type":"WIKI_ITEM","target_type":"CODE_SNIPPET","relationship_type":"CONTAINS","extra":"Wiki contains code snippet: backend/pipelines/diagnosis.yaml#8-30","gmt_create":"2026-05-23T15:24:02.194778+08:00","gmt_modified":"2026-05-23T15:24:02.194778+08:00"},{"id":2500,"source_id":"856c9e5eddcb40682e653dbd1a4bfc4b","target_id":"63b5e7a6a9a5545b70747bcbcae293f9","source_type":"SOURCE_FILE","target_type":"CODE_SNIPPET","relationship_type":"CONTAINS","extra":"Source file contains code snippet: 8-30","gmt_create":"2026-05-23T15:24:02.196037+08:00","gmt_modified":"2026-05-23T15:24:02.196037+08:00"},{"id":2501,"source_id":"c7eb113b-b503-4d83-be7f-9ccf3350c9d9","target_id":"8ece81c4077ec3e9c702e5e1092119a2","source_type":"WIKI_ITEM","target_type":"CODE_SNIPPET","relationship_type":"CONTAINS","extra":"Wiki contains code snippet: backend/app/agent_framework/pipeline/engine.py#51-176","gmt_create":"2026-05-23T15:24:02.199542+08:00","gmt_modified":"2026-05-23T15:24:02.199543+08:00"},{"id":2502,"source_id":"c7eb113b-b503-4d83-be7f-9ccf3350c9d9","target_id":"cdcf6ce33785e1c04e59e8244ca38ec8","source_type":"WIKI_ITEM","target_type":"CODE_SNIPPET","relationship_type":"CONTAINS","extra":"Wiki contains code snippet: backend/app/agent_framework/pipeline/engine.py#256-327","gmt_create":"2026-05-23T15:24:02.204302+08:00","gmt_modified":"2026-05-23T15:24:02.204302+08:00"},{"id":2503,"source_id":"609a02c9e1ccc0311885a70578b86386","target_id":"cdcf6ce33785e1c04e59e8244ca38ec8","source_type":"SOURCE_FILE","target_type":"CODE_SNIPPET","relationship_type":"CONTAINS","extra":"Source file contains code snippet: 256-327","gmt_create":"2026-05-23T15:24:02.206689+08:00","gmt_modified":"2026-05-23T15:24:02.20669+08:00"},{"id":2504,"source_id":"c7eb113b-b503-4d83-be7f-9ccf3350c9d9","target_id":"d8a98dd989912e358f7dbd278e1c5353","source_type":"WIKI_ITEM","target_type":"CODE_SNIPPET","relationship_type":"CONTAINS","extra":"Wiki contains code snippet: backend/app/agent_framework/pipeline/loader.py#1-283","gmt_create":"2026-05-23T15:24:02.209677+08:00","gmt_modified":"2026-05-23T15:24:02.209677+08:00"},{"id":2505,"source_id":"c7eb113b-b503-4d83-be7f-9ccf3350c9d9","target_id":"8d044a978198d9cd54d1b3d8e41194c0","source_type":"WIKI_ITEM","target_type":"CODE_SNIPPET","relationship_type":"CONTAINS","extra":"Wiki contains code snippet: backend/app/agent_framework/pipeline/schema.py#1-102","gmt_create":"2026-05-23T15:24:02.212021+08:00","gmt_modified":"2026-05-23T15:24:02.212021+08:00"},{"id":2506,"source_id":"022c381f121cc2a65834024ca2c9b8c1","target_id":"8d044a978198d9cd54d1b3d8e41194c0","source_type":"SOURCE_FILE","target_type":"CODE_SNIPPET","relationship_type":"CONTAINS","extra":"Source file contains code snippet: 1-102","gmt_create":"2026-05-23T15:24:02.214191+08:00","gmt_modified":"2026-05-23T15:24:02.214192+08:00"},{"id":2507,"source_id":"c7eb113b-b503-4d83-be7f-9ccf3350c9d9","target_id":"9606b8243736b4a6f5ecfe152b2ab6dd","source_type":"WIKI_ITEM","target_type":"CODE_SNIPPET","relationship_type":"CONTAINS","extra":"Wiki contains code snippet: backend/app/middleware/rate_limit.py#34-83","gmt_create":"2026-05-23T15:24:02.222101+08:00","gmt_modified":"2026-05-23T15:24:02.222101+08:00"},{"id":2508,"source_id":"c7eb113b-b503-4d83-be7f-9ccf3350c9d9","target_id":"05664cbd35007caa5290760cc1ef1b99","source_type":"WIKI_ITEM","target_type":"CODE_SNIPPET","relationship_type":"CONTAINS","extra":"Wiki contains code snippet: backend/app/api/admin.py#29-108","gmt_create":"2026-05-23T15:24:02.229058+08:00","gmt_modified":"2026-05-23T15:24:02.229058+08:00"},{"id":2509,"source_id":"c7eb113b-b503-4d83-be7f-9ccf3350c9d9","target_id":"7c7425c51cc43b8840cefd9764b47204","source_type":"WIKI_ITEM","target_type":"CODE_SNIPPET","relationship_type":"CONTAINS","extra":"Wiki contains code snippet: backend/app/api/admin.py#1-108","gmt_create":"2026-05-23T15:24:02.234822+08:00","gmt_modified":"2026-05-23T15:24:02.234823+08:00"},{"id":2510,"source_id":"c7eb113b-b503-4d83-be7f-9ccf3350c9d9","target_id":"9bdd2f6103cf3cc8b3914b9d6d8812fb","source_type":"WIKI_ITEM","target_type":"CODE_SNIPPET","relationship_type":"CONTAINS","extra":"Wiki contains code snippet: backend/app/services/admin.py#1-188","gmt_create":"2026-05-23T15:24:02.237145+08:00","gmt_modified":"2026-05-23T15:24:02.237145+08:00"},{"id":2511,"source_id":"c7eb113b-b503-4d83-be7f-9ccf3350c9d9","target_id":"3d85cad939ce858f9c6d153d425c19fb","source_type":"WIKI_ITEM","target_type":"CODE_SNIPPET","relationship_type":"CONTAINS","extra":"Wiki contains code snippet: backend/app/services/subscription.py#25-155","gmt_create":"2026-05-23T15:24:02.239313+08:00","gmt_modified":"2026-05-23T15:24:02.239313+08:00"},{"id":2512,"source_id":"c7eb113b-b503-4d83-be7f-9ccf3350c9d9","target_id":"4247da3fc00a7e5f8b73775321eccf8e","source_type":"WIKI_ITEM","target_type":"CODE_SNIPPET","relationship_type":"CONTAINS","extra":"Wiki contains code snippet: backend/app/api/subscriptions.py#1-77","gmt_create":"2026-05-23T15:24:02.242793+08:00","gmt_modified":"2026-05-23T15:24:02.242793+08:00"},{"id":2513,"source_id":"c7eb113b-b503-4d83-be7f-9ccf3350c9d9","target_id":"36769bd305cd5f664fa6e28f82e4b3e7","source_type":"WIKI_ITEM","target_type":"CODE_SNIPPET","relationship_type":"CONTAINS","extra":"Wiki contains code snippet: backend/app/schemas/subscription.py#1-41","gmt_create":"2026-05-23T15:24:02.244875+08:00","gmt_modified":"2026-05-23T15:24:02.244875+08:00"},{"id":2514,"source_id":"c7eb113b-b503-4d83-be7f-9ccf3350c9d9","target_id":"557281ca025f76d0dc2db67e56b44053","source_type":"WIKI_ITEM","target_type":"CODE_SNIPPET","relationship_type":"CONTAINS","extra":"Wiki contains code snippet: backend/app/services/subscription.py#1-155","gmt_create":"2026-05-23T15:24:02.25128+08:00","gmt_modified":"2026-05-23T15:24:02.25128+08:00"},{"id":2515,"source_id":"c7eb113b-b503-4d83-be7f-9ccf3350c9d9","target_id":"14c2d098319eeab16c64ff7d1447df6b","source_type":"WIKI_ITEM","target_type":"CODE_SNIPPET","relationship_type":"CONTAINS","extra":"Wiki contains code snippet: backend/app/api/reports.py#18-75","gmt_create":"2026-05-23T15:24:02.25351+08:00","gmt_modified":"2026-05-23T15:24:02.25351+08:00"},{"id":2516,"source_id":"c7eb113b-b503-4d83-be7f-9ccf3350c9d9","target_id":"6e4a52820e780e4b42651a8214ad4493","source_type":"WIKI_ITEM","target_type":"CODE_SNIPPET","relationship_type":"CONTAINS","extra":"Wiki contains code snippet: backend/app/api/reports.py#1-75","gmt_create":"2026-05-23T15:24:02.255272+08:00","gmt_modified":"2026-05-23T15:24:02.255272+08:00"},{"id":2517,"source_id":"c7eb113b-b503-4d83-be7f-9ccf3350c9d9","target_id":"eb603ec2611957de67af00756f4b1efa","source_type":"WIKI_ITEM","target_type":"CODE_SNIPPET","relationship_type":"CONTAINS","extra":"Wiki contains code snippet: backend/app/config.py#7-13","gmt_create":"2026-05-23T15:24:02.3019+08:00","gmt_modified":"2026-05-23T15:24:02.3019+08:00"},{"id":2518,"source_id":"c7eb113b-b503-4d83-be7f-9ccf3350c9d9","target_id":"e1d2b027678118df4d0a50ce9269271d","source_type":"WIKI_ITEM","target_type":"CODE_SNIPPET","relationship_type":"CONTAINS","extra":"Wiki contains code snippet: backend/app/workers/scheduler.py#42-90","gmt_create":"2026-05-23T15:24:02.306153+08:00","gmt_modified":"2026-05-23T15:24:02.306154+08:00"},{"id":2519,"source_id":"c7eb113b-b503-4d83-be7f-9ccf3350c9d9","target_id":"38142b7d7016c5590e638fafcdcb1a19","source_type":"WIKI_ITEM","target_type":"CODE_SNIPPET","relationship_type":"CONTAINS","extra":"Wiki contains code snippet: backend/app/workers/citation_engine.py#211-227","gmt_create":"2026-05-23T15:24:02.307777+08:00","gmt_modified":"2026-05-23T15:24:02.307777+08:00"},{"id":2520,"source_id":"c7eb113b-b503-4d83-be7f-9ccf3350c9d9","target_id":"960edc307c80a05c1d234e641a795b35","source_type":"WIKI_ITEM","target_type":"CODE_SNIPPET","relationship_type":"CONTAINS","extra":"Wiki contains code snippet: backend/app/workers/llm_adapter.py#141-218","gmt_create":"2026-05-23T15:24:02.318511+08:00","gmt_modified":"2026-05-23T15:24:02.318511+08:00"},{"id":2521,"source_id":"ca1e69e3279cea977bb7f660d417b4d8","target_id":"960edc307c80a05c1d234e641a795b35","source_type":"SOURCE_FILE","target_type":"CODE_SNIPPET","relationship_type":"CONTAINS","extra":"Source file contains code snippet: 141-218","gmt_create":"2026-05-23T15:24:02.324725+08:00","gmt_modified":"2026-05-23T15:24:02.324726+08:00"},{"id":2522,"source_id":"c7eb113b-b503-4d83-be7f-9ccf3350c9d9","target_id":"8bf01ba5b11502e9f6f9802c9735f370","source_type":"WIKI_ITEM","target_type":"CODE_SNIPPET","relationship_type":"CONTAINS","extra":"Wiki contains code snippet: backend/app/agent_framework/pipeline/loader.py#124-134","gmt_create":"2026-05-23T15:24:02.330086+08:00","gmt_modified":"2026-05-23T15:24:02.330086+08:00"},{"id":2523,"source_id":"43642bd7bedabd97ff2f0a902b783e4e","target_id":"8bf01ba5b11502e9f6f9802c9735f370","source_type":"SOURCE_FILE","target_type":"CODE_SNIPPET","relationship_type":"CONTAINS","extra":"Source file contains code snippet: 124-134","gmt_create":"2026-05-23T15:24:02.33248+08:00","gmt_modified":"2026-05-23T15:24:02.332481+08:00"},{"id":2524,"source_id":"c5849940-e223-4222-be17-aa0a6cb36bc8","target_id":"9228ff67d4c757a85d9421b71f4b29f5","source_type":"WIKI_ITEM","target_type":"SOURCE_FILE","relationship_type":"REFERENCED_BY","extra":"Wiki references source file: backend/app/main.py","gmt_create":"2026-05-23T15:26:09.959877+08:00","gmt_modified":"2026-05-23T15:26:09.959878+08:00"},{"id":2525,"source_id":"c5849940-e223-4222-be17-aa0a6cb36bc8","target_id":"9ff19022ef915615911280e3c49ed44b","source_type":"WIKI_ITEM","target_type":"SOURCE_FILE","relationship_type":"REFERENCED_BY","extra":"Wiki references source file: backend/app/config.py","gmt_create":"2026-05-23T15:26:09.96188+08:00","gmt_modified":"2026-05-23T15:26:09.961881+08:00"},{"id":2526,"source_id":"c5849940-e223-4222-be17-aa0a6cb36bc8","target_id":"93022c8938ce318f167277cfa65c29a7","source_type":"WIKI_ITEM","target_type":"SOURCE_FILE","relationship_type":"REFERENCED_BY","extra":"Wiki references source file: backend/app/api/auth.py","gmt_create":"2026-05-23T15:26:09.963003+08:00","gmt_modified":"2026-05-23T15:26:09.963004+08:00"},{"id":2527,"source_id":"c5849940-e223-4222-be17-aa0a6cb36bc8","target_id":"6b3d903205941aa9391dd90016e1102c","source_type":"WIKI_ITEM","target_type":"SOURCE_FILE","relationship_type":"REFERENCED_BY","extra":"Wiki references source file: backend/app/api/queries.py","gmt_create":"2026-05-23T15:26:09.964609+08:00","gmt_modified":"2026-05-23T15:26:09.964609+08:00"},{"id":2528,"source_id":"c5849940-e223-4222-be17-aa0a6cb36bc8","target_id":"58901c94d975d87e652a4dc6c8dda656","source_type":"WIKI_ITEM","target_type":"SOURCE_FILE","relationship_type":"REFERENCED_BY","extra":"Wiki references source file: backend/app/api/reports.py","gmt_create":"2026-05-23T15:26:09.966371+08:00","gmt_modified":"2026-05-23T15:26:09.966372+08:00"},{"id":2529,"source_id":"c5849940-e223-4222-be17-aa0a6cb36bc8","target_id":"7538ffe4902ab6041adb28b19844962a","source_type":"WIKI_ITEM","target_type":"SOURCE_FILE","relationship_type":"REFERENCED_BY","extra":"Wiki references source file: backend/app/api/citations.py","gmt_create":"2026-05-23T15:26:09.967943+08:00","gmt_modified":"2026-05-23T15:26:09.967944+08:00"},{"id":2530,"source_id":"c5849940-e223-4222-be17-aa0a6cb36bc8","target_id":"6a9387dd3885cf4d27bce3db87fd61c7","source_type":"WIKI_ITEM","target_type":"SOURCE_FILE","relationship_type":"REFERENCED_BY","extra":"Wiki references source file: backend/app/api/agents.py","gmt_create":"2026-05-23T15:26:09.968693+08:00","gmt_modified":"2026-05-23T15:26:09.968693+08:00"},{"id":2531,"source_id":"c5849940-e223-4222-be17-aa0a6cb36bc8","target_id":"b74caccb06844efcdb14d8324cff65c2","source_type":"WIKI_ITEM","target_type":"SOURCE_FILE","relationship_type":"REFERENCED_BY","extra":"Wiki references source file: backend/app/models/query.py","gmt_create":"2026-05-23T15:26:09.969487+08:00","gmt_modified":"2026-05-23T15:26:09.969487+08:00"},{"id":2532,"source_id":"c5849940-e223-4222-be17-aa0a6cb36bc8","target_id":"f301b79d833233ce39d350e82a71c938","source_type":"WIKI_ITEM","target_type":"SOURCE_FILE","relationship_type":"REFERENCED_BY","extra":"Wiki references source file: backend/app/schemas/query.py","gmt_create":"2026-05-23T15:26:09.970813+08:00","gmt_modified":"2026-05-23T15:26:09.970813+08:00"},{"id":2533,"source_id":"c5849940-e223-4222-be17-aa0a6cb36bc8","target_id":"5cbb1e3f112aeba62a14b0b8999fc0f5","source_type":"WIKI_ITEM","target_type":"SOURCE_FILE","relationship_type":"REFERENCED_BY","extra":"Wiki references source file: backend/app/workers/scheduler.py","gmt_create":"2026-05-23T15:26:09.972359+08:00","gmt_modified":"2026-05-23T15:26:09.972359+08:00"},{"id":2534,"source_id":"c5849940-e223-4222-be17-aa0a6cb36bc8","target_id":"a16cf42e9559523c4f96ca4c79f9488d","source_type":"WIKI_ITEM","target_type":"SOURCE_FILE","relationship_type":"REFERENCED_BY","extra":"Wiki references source file: backend/app/workers/platforms/base.py","gmt_create":"2026-05-23T15:26:09.973803+08:00","gmt_modified":"2026-05-23T15:26:09.973803+08:00"},{"id":2535,"source_id":"c5849940-e223-4222-be17-aa0a6cb36bc8","target_id":"8f973791233c698b3e64a4fb28a93d4b","source_type":"WIKI_ITEM","target_type":"SOURCE_FILE","relationship_type":"REFERENCED_BY","extra":"Wiki references source file: backend/app/workers/platforms/kimi.py","gmt_create":"2026-05-23T15:26:09.97491+08:00","gmt_modified":"2026-05-23T15:26:09.97491+08:00"},{"id":2536,"source_id":"c5849940-e223-4222-be17-aa0a6cb36bc8","target_id":"f642fc1c2f34e15572d9d98aa6c18813","source_type":"WIKI_ITEM","target_type":"SOURCE_FILE","relationship_type":"REFERENCED_BY","extra":"Wiki references source file: backend/app/workers/platforms/wenxin.py","gmt_create":"2026-05-23T15:26:09.97652+08:00","gmt_modified":"2026-05-23T15:26:09.97652+08:00"},{"id":2537,"source_id":"c5849940-e223-4222-be17-aa0a6cb36bc8","target_id":"74040de652d5e57f548bb5c4adc3e1a0","source_type":"WIKI_ITEM","target_type":"SOURCE_FILE","relationship_type":"REFERENCED_BY","extra":"Wiki references source file: backend/app/workers/citation_engine.py","gmt_create":"2026-05-23T15:26:09.977692+08:00","gmt_modified":"2026-05-23T15:26:09.977692+08:00"},{"id":2538,"source_id":"c5849940-e223-4222-be17-aa0a6cb36bc8","target_id":"4d2f3847b7c10634733118b70a1aea0b","source_type":"WIKI_ITEM","target_type":"SOURCE_FILE","relationship_type":"REFERENCED_BY","extra":"Wiki references source file: backend/app/services/auth.py","gmt_create":"2026-05-23T15:26:09.978675+08:00","gmt_modified":"2026-05-23T15:26:09.978675+08:00"},{"id":2539,"source_id":"c5849940-e223-4222-be17-aa0a6cb36bc8","target_id":"88d22de3b2a7419868e8ae19130d860c","source_type":"WIKI_ITEM","target_type":"SOURCE_FILE","relationship_type":"REFERENCED_BY","extra":"Wiki references source file: backend/app/services/query.py","gmt_create":"2026-05-23T15:26:09.979339+08:00","gmt_modified":"2026-05-23T15:26:09.979339+08:00"},{"id":2540,"source_id":"c5849940-e223-4222-be17-aa0a6cb36bc8","target_id":"04e3926c080e795713bff683e7dc9d3e","source_type":"WIKI_ITEM","target_type":"SOURCE_FILE","relationship_type":"REFERENCED_BY","extra":"Wiki references source file: backend/app/services/citation.py","gmt_create":"2026-05-23T15:26:09.980266+08:00","gmt_modified":"2026-05-23T15:26:09.980266+08:00"},{"id":2541,"source_id":"c5849940-e223-4222-be17-aa0a6cb36bc8","target_id":"b0c428683c8a3e6922d90ca0d8c2736d","source_type":"WIKI_ITEM","target_type":"SOURCE_FILE","relationship_type":"REFERENCED_BY","extra":"Wiki references source file: backend/app/database.py","gmt_create":"2026-05-23T15:26:09.981705+08:00","gmt_modified":"2026-05-23T15:26:09.981706+08:00"},{"id":2542,"source_id":"c5849940-e223-4222-be17-aa0a6cb36bc8","target_id":"9d08667997a868fc07c9b4e328e44224","source_type":"WIKI_ITEM","target_type":"SOURCE_FILE","relationship_type":"REFERENCED_BY","extra":"Wiki references source file: backend/app/api/deps.py","gmt_create":"2026-05-23T15:26:09.984465+08:00","gmt_modified":"2026-05-23T15:26:09.984465+08:00"},{"id":2543,"source_id":"c5849940-e223-4222-be17-aa0a6cb36bc8","target_id":"c59f8c276697a070dffc581fe94d809c","source_type":"WIKI_ITEM","target_type":"SOURCE_FILE","relationship_type":"REFERENCED_BY","extra":"Wiki references source file: backend/app/models/user.py","gmt_create":"2026-05-23T15:26:09.98624+08:00","gmt_modified":"2026-05-23T15:26:09.986241+08:00"},{"id":2544,"source_id":"c5849940-e223-4222-be17-aa0a6cb36bc8","target_id":"e0c0ca66b8b81cf66e078a7ab162c07f","source_type":"WIKI_ITEM","target_type":"SOURCE_FILE","relationship_type":"REFERENCED_BY","extra":"Wiki references source file: backend/app/schemas/auth.py","gmt_create":"2026-05-23T15:26:09.987271+08:00","gmt_modified":"2026-05-23T15:26:09.987271+08:00"},{"id":2545,"source_id":"c5849940-e223-4222-be17-aa0a6cb36bc8","target_id":"1a3336b4af8a39a055e912724338580c","source_type":"WIKI_ITEM","target_type":"SOURCE_FILE","relationship_type":"REFERENCED_BY","extra":"Wiki references source file: backend/app/schemas/citation.py","gmt_create":"2026-05-23T15:26:09.98798+08:00","gmt_modified":"2026-05-23T15:26:09.98798+08:00"},{"id":2546,"source_id":"c5849940-e223-4222-be17-aa0a6cb36bc8","target_id":"a26ee01cf41da3b956e1650448c156fa","source_type":"WIKI_ITEM","target_type":"SOURCE_FILE","relationship_type":"REFERENCED_BY","extra":"Wiki references source file: backend/requirements.txt","gmt_create":"2026-05-23T15:26:09.988952+08:00","gmt_modified":"2026-05-23T15:26:09.988952+08:00"},{"id":2547,"source_id":"c5849940-e223-4222-be17-aa0a6cb36bc8","target_id":"12e2c3d7b9a92dc44a6ee29b85e10df6","source_type":"WIKI_ITEM","target_type":"SOURCE_FILE","relationship_type":"REFERENCED_BY","extra":"Wiki references source file: frontend/app/layout.tsx","gmt_create":"2026-05-23T15:26:09.989956+08:00","gmt_modified":"2026-05-23T15:26:09.989956+08:00"},{"id":2548,"source_id":"c5849940-e223-4222-be17-aa0a6cb36bc8","target_id":"546e01c5f73aaf5140eee922f4b9a441","source_type":"WIKI_ITEM","target_type":"SOURCE_FILE","relationship_type":"REFERENCED_BY","extra":"Wiki references source file: frontend/components/providers.tsx","gmt_create":"2026-05-23T15:26:09.991346+08:00","gmt_modified":"2026-05-23T15:26:09.991346+08:00"},{"id":2549,"source_id":"c5849940-e223-4222-be17-aa0a6cb36bc8","target_id":"5d7886d0dc99f81073a578b8aefdd375","source_type":"WIKI_ITEM","target_type":"SOURCE_FILE","relationship_type":"REFERENCED_BY","extra":"Wiki references source file: frontend/lib/api.ts","gmt_create":"2026-05-23T15:26:09.99246+08:00","gmt_modified":"2026-05-23T15:26:09.992461+08:00"},{"id":2550,"source_id":"c5849940-e223-4222-be17-aa0a6cb36bc8","target_id":"aa21995469cad3e13897d5dbe268533f","source_type":"WIKI_ITEM","target_type":"SOURCE_FILE","relationship_type":"REFERENCED_BY","extra":"Wiki references source file: frontend/lib/api/agents.ts","gmt_create":"2026-05-23T15:26:09.993452+08:00","gmt_modified":"2026-05-23T15:26:09.993452+08:00"},{"id":2551,"source_id":"c5849940-e223-4222-be17-aa0a6cb36bc8","target_id":"aaf5bce6be82d2f947bfa5c1806de452","source_type":"WIKI_ITEM","target_type":"SOURCE_FILE","relationship_type":"REFERENCED_BY","extra":"Wiki references source file: frontend/package.json","gmt_create":"2026-05-23T15:26:09.99453+08:00","gmt_modified":"2026-05-23T15:26:09.994531+08:00"},{"id":2552,"source_id":"c5849940-e223-4222-be17-aa0a6cb36bc8","target_id":"fc6242433ae9506bcc0bf4cb0dce1413","source_type":"WIKI_ITEM","target_type":"SOURCE_FILE","relationship_type":"REFERENCED_BY","extra":"Wiki references source file: docker-compose.yml","gmt_create":"2026-05-23T15:26:09.997075+08:00","gmt_modified":"2026-05-23T15:26:09.997076+08:00"},{"id":2553,"source_id":"c5849940-e223-4222-be17-aa0a6cb36bc8","target_id":"e9b52adbec3c07cf021e488dd3f99ab4","source_type":"WIKI_ITEM","target_type":"SOURCE_FILE","relationship_type":"REFERENCED_BY","extra":"Wiki references source file: backend/Dockerfile","gmt_create":"2026-05-23T15:26:09.998723+08:00","gmt_modified":"2026-05-23T15:26:09.998723+08:00"},{"id":2554,"source_id":"c5849940-e223-4222-be17-aa0a6cb36bc8","target_id":"5e414f2ef9b69e55e00ab15f85b9291a","source_type":"WIKI_ITEM","target_type":"SOURCE_FILE","relationship_type":"REFERENCED_BY","extra":"Wiki references source file: frontend/Dockerfile","gmt_create":"2026-05-23T15:26:10.001175+08:00","gmt_modified":"2026-05-23T15:26:10.001175+08:00"},{"id":2555,"source_id":"c5849940-e223-4222-be17-aa0a6cb36bc8","target_id":"d4f95fcf50683b5bf6167c7d2a6b126d","source_type":"WIKI_ITEM","target_type":"SOURCE_FILE","relationship_type":"REFERENCED_BY","extra":"Wiki references source file: backend/alembic/versions/488d0bd5ab01_initial_migration.py","gmt_create":"2026-05-23T15:26:10.002952+08:00","gmt_modified":"2026-05-23T15:26:10.002953+08:00"},{"id":2556,"source_id":"c5849940-e223-4222-be17-aa0a6cb36bc8","target_id":"5d2b9655ba99a14a3accb1878bb5681a","source_type":"WIKI_ITEM","target_type":"SOURCE_FILE","relationship_type":"REFERENCED_BY","extra":"Wiki references source file: backend/app/agent_framework/registry.py","gmt_create":"2026-05-23T15:26:10.005018+08:00","gmt_modified":"2026-05-23T15:26:10.005019+08:00"},{"id":2557,"source_id":"c5849940-e223-4222-be17-aa0a6cb36bc8","target_id":"6b50314c917457b8b70ade390573c3cb","source_type":"WIKI_ITEM","target_type":"SOURCE_FILE","relationship_type":"REFERENCED_BY","extra":"Wiki references source file: backend/app/agent_framework/config_manager.py","gmt_create":"2026-05-23T15:26:10.00594+08:00","gmt_modified":"2026-05-23T15:26:10.00594+08:00"},{"id":2558,"source_id":"c5849940-e223-4222-be17-aa0a6cb36bc8","target_id":"fcde401daccbe6de50f3829f021ecf55","source_type":"WIKI_ITEM","target_type":"SOURCE_FILE","relationship_type":"REFERENCED_BY","extra":"Wiki references source file: backend/app/agent_framework/dispatcher.py","gmt_create":"2026-05-23T15:26:10.007122+08:00","gmt_modified":"2026-05-23T15:26:10.007122+08:00"},{"id":2559,"source_id":"c5849940-e223-4222-be17-aa0a6cb36bc8","target_id":"3a2a43dd94c9405ea91934c43cdecced","source_type":"WIKI_ITEM","target_type":"SOURCE_FILE","relationship_type":"REFERENCED_BY","extra":"Wiki references source file: backend/app/agent_framework/protocol.py","gmt_create":"2026-05-23T15:26:10.008461+08:00","gmt_modified":"2026-05-23T15:26:10.008461+08:00"},{"id":2560,"source_id":"c5849940-e223-4222-be17-aa0a6cb36bc8","target_id":"609a02c9e1ccc0311885a70578b86386","source_type":"WIKI_ITEM","target_type":"SOURCE_FILE","relationship_type":"REFERENCED_BY","extra":"Wiki references source file: backend/app/agent_framework/pipeline/engine.py","gmt_create":"2026-05-23T15:26:10.009222+08:00","gmt_modified":"2026-05-23T15:26:10.009223+08:00"},{"id":2561,"source_id":"c5849940-e223-4222-be17-aa0a6cb36bc8","target_id":"aa6cf63a65ebf46a29606af91112eb7b","source_type":"WIKI_ITEM","target_type":"SOURCE_FILE","relationship_type":"REFERENCED_BY","extra":"Wiki references source file: backend/app/models/agent.py","gmt_create":"2026-05-23T15:26:10.010633+08:00","gmt_modified":"2026-05-23T15:26:10.010633+08:00"},{"id":2562,"source_id":"c5849940-e223-4222-be17-aa0a6cb36bc8","target_id":"c2036406c4a0ae8b1e671ef1f1601826","source_type":"WIKI_ITEM","target_type":"SOURCE_FILE","relationship_type":"REFERENCED_BY","extra":"Wiki references source file: .env.example","gmt_create":"2026-05-23T15:26:10.012593+08:00","gmt_modified":"2026-05-23T15:26:10.012594+08:00"},{"id":2563,"source_id":"c5849940-e223-4222-be17-aa0a6cb36bc8","target_id":"c2747ca16b879bca0f68955534c3c4fc","source_type":"WIKI_ITEM","target_type":"CODE_SNIPPET","relationship_type":"CONTAINS","extra":"Wiki contains code snippet: backend/app/main.py#1-48","gmt_create":"2026-05-23T15:26:10.014439+08:00","gmt_modified":"2026-05-23T15:26:10.014439+08:00"},{"id":2564,"source_id":"c5849940-e223-4222-be17-aa0a6cb36bc8","target_id":"70985e6be46865e7b0a26fdaab7ce0d2","source_type":"WIKI_ITEM","target_type":"CODE_SNIPPET","relationship_type":"CONTAINS","extra":"Wiki contains code snippet: frontend/lib/api.ts#1-58","gmt_create":"2026-05-23T15:26:10.019115+08:00","gmt_modified":"2026-05-23T15:26:10.019115+08:00"},{"id":2565,"source_id":"5d7886d0dc99f81073a578b8aefdd375","target_id":"70985e6be46865e7b0a26fdaab7ce0d2","source_type":"SOURCE_FILE","target_type":"CODE_SNIPPET","relationship_type":"CONTAINS","extra":"Source file contains code snippet: 1-58","gmt_create":"2026-05-23T15:26:10.020704+08:00","gmt_modified":"2026-05-23T15:26:10.020705+08:00"},{"id":2566,"source_id":"c5849940-e223-4222-be17-aa0a6cb36bc8","target_id":"42315d289241195bda33f7251dff0396","source_type":"WIKI_ITEM","target_type":"CODE_SNIPPET","relationship_type":"CONTAINS","extra":"Wiki contains code snippet: frontend/lib/api/agents.ts#1-57","gmt_create":"2026-05-23T15:26:10.022448+08:00","gmt_modified":"2026-05-23T15:26:10.022448+08:00"},{"id":2567,"source_id":"aa21995469cad3e13897d5dbe268533f","target_id":"42315d289241195bda33f7251dff0396","source_type":"SOURCE_FILE","target_type":"CODE_SNIPPET","relationship_type":"CONTAINS","extra":"Source file contains code snippet: 1-57","gmt_create":"2026-05-23T15:26:10.023777+08:00","gmt_modified":"2026-05-23T15:26:10.023777+08:00"},{"id":2568,"source_id":"c5849940-e223-4222-be17-aa0a6cb36bc8","target_id":"71f98c8993fb42b108e34a554247869b","source_type":"WIKI_ITEM","target_type":"CODE_SNIPPET","relationship_type":"CONTAINS","extra":"Wiki contains code snippet: backend/app/workers/scheduler.py#1-95","gmt_create":"2026-05-23T15:26:10.025151+08:00","gmt_modified":"2026-05-23T15:26:10.025151+08:00"},{"id":2569,"source_id":"c5849940-e223-4222-be17-aa0a6cb36bc8","target_id":"72a110dca58d8152758e2fdab4e94761","source_type":"WIKI_ITEM","target_type":"CODE_SNIPPET","relationship_type":"CONTAINS","extra":"Wiki contains code snippet: backend/app/workers/platforms/base.py#1-18","gmt_create":"2026-05-23T15:26:10.026269+08:00","gmt_modified":"2026-05-23T15:26:10.026269+08:00"},{"id":2570,"source_id":"c5849940-e223-4222-be17-aa0a6cb36bc8","target_id":"39a3b2d9301fa4eff7bef0fda3352790","source_type":"WIKI_ITEM","target_type":"CODE_SNIPPET","relationship_type":"CONTAINS","extra":"Wiki contains code snippet: backend/app/workers/platforms/kimi.py#1-206","gmt_create":"2026-05-23T15:26:10.027803+08:00","gmt_modified":"2026-05-23T15:26:10.027803+08:00"},{"id":2571,"source_id":"c5849940-e223-4222-be17-aa0a6cb36bc8","target_id":"fbcfae3b1238b3da5329ebafe4294861","source_type":"WIKI_ITEM","target_type":"CODE_SNIPPET","relationship_type":"CONTAINS","extra":"Wiki contains code snippet: backend/app/workers/platforms/wenxin.py#1-205","gmt_create":"2026-05-23T15:26:10.029396+08:00","gmt_modified":"2026-05-23T15:26:10.029397+08:00"},{"id":2572,"source_id":"c5849940-e223-4222-be17-aa0a6cb36bc8","target_id":"aba7dcba1181acae0e810fe447807010","source_type":"WIKI_ITEM","target_type":"CODE_SNIPPET","relationship_type":"CONTAINS","extra":"Wiki contains code snippet: backend/app/agent_framework/registry.py#1-219","gmt_create":"2026-05-23T15:26:10.031015+08:00","gmt_modified":"2026-05-23T15:26:10.031015+08:00"},{"id":2573,"source_id":"c5849940-e223-4222-be17-aa0a6cb36bc8","target_id":"370e7d15bc2a240ba54af22c704f8192","source_type":"WIKI_ITEM","target_type":"CODE_SNIPPET","relationship_type":"CONTAINS","extra":"Wiki contains code snippet: backend/app/agent_framework/config_manager.py#1-191","gmt_create":"2026-05-23T15:26:10.034543+08:00","gmt_modified":"2026-05-23T15:26:10.034543+08:00"},{"id":2574,"source_id":"6b50314c917457b8b70ade390573c3cb","target_id":"370e7d15bc2a240ba54af22c704f8192","source_type":"SOURCE_FILE","target_type":"CODE_SNIPPET","relationship_type":"CONTAINS","extra":"Source file contains code snippet: 1-191","gmt_create":"2026-05-23T15:26:10.035987+08:00","gmt_modified":"2026-05-23T15:26:10.035987+08:00"},{"id":2575,"source_id":"c5849940-e223-4222-be17-aa0a6cb36bc8","target_id":"5dd1642d800053635d9827e12e6ea120","source_type":"WIKI_ITEM","target_type":"CODE_SNIPPET","relationship_type":"CONTAINS","extra":"Wiki contains code snippet: backend/app/agent_framework/dispatcher.py#1-367","gmt_create":"2026-05-23T15:26:10.03743+08:00","gmt_modified":"2026-05-23T15:26:10.037431+08:00"},{"id":2576,"source_id":"c5849940-e223-4222-be17-aa0a6cb36bc8","target_id":"db3ad017a4a81f38a1e6008d01fb07fb","source_type":"WIKI_ITEM","target_type":"CODE_SNIPPET","relationship_type":"CONTAINS","extra":"Wiki contains code snippet: backend/app/agent_framework/pipeline/engine.py#1-376","gmt_create":"2026-05-23T15:26:10.038939+08:00","gmt_modified":"2026-05-23T15:26:10.03894+08:00"},{"id":2577,"source_id":"609a02c9e1ccc0311885a70578b86386","target_id":"db3ad017a4a81f38a1e6008d01fb07fb","source_type":"SOURCE_FILE","target_type":"CODE_SNIPPET","relationship_type":"CONTAINS","extra":"Source file contains code snippet: 1-376","gmt_create":"2026-05-23T15:26:10.040091+08:00","gmt_modified":"2026-05-23T15:26:10.040092+08:00"},{"id":2578,"source_id":"c5849940-e223-4222-be17-aa0a6cb36bc8","target_id":"8a466b0c6eac2ccb54c5da7e13854646","source_type":"WIKI_ITEM","target_type":"CODE_SNIPPET","relationship_type":"CONTAINS","extra":"Wiki contains code snippet: frontend/app/layout.tsx#1-37","gmt_create":"2026-05-23T15:26:10.042941+08:00","gmt_modified":"2026-05-23T15:26:10.042941+08:00"},{"id":2579,"source_id":"c5849940-e223-4222-be17-aa0a6cb36bc8","target_id":"fd18328b6582e68c30b130b912891992","source_type":"WIKI_ITEM","target_type":"CODE_SNIPPET","relationship_type":"CONTAINS","extra":"Wiki contains code snippet: frontend/components/providers.tsx#1-9","gmt_create":"2026-05-23T15:26:10.044621+08:00","gmt_modified":"2026-05-23T15:26:10.044622+08:00"},{"id":2580,"source_id":"c5849940-e223-4222-be17-aa0a6cb36bc8","target_id":"f66d9907b467b110c638bd527efd95c5","source_type":"WIKI_ITEM","target_type":"CODE_SNIPPET","relationship_type":"CONTAINS","extra":"Wiki contains code snippet: backend/app/api/auth.py#1-43","gmt_create":"2026-05-23T15:26:10.046386+08:00","gmt_modified":"2026-05-23T15:26:10.046387+08:00"},{"id":2581,"source_id":"c5849940-e223-4222-be17-aa0a6cb36bc8","target_id":"10d1e37bdc9f353c189b7a2fe79dc85e","source_type":"WIKI_ITEM","target_type":"CODE_SNIPPET","relationship_type":"CONTAINS","extra":"Wiki contains code snippet: backend/app/api/queries.py#1-86","gmt_create":"2026-05-23T15:26:10.047692+08:00","gmt_modified":"2026-05-23T15:26:10.047692+08:00"},{"id":2582,"source_id":"c5849940-e223-4222-be17-aa0a6cb36bc8","target_id":"41c1962c6c680f23f0fde4efc0edc618","source_type":"WIKI_ITEM","target_type":"CODE_SNIPPET","relationship_type":"CONTAINS","extra":"Wiki contains code snippet: backend/app/api/agents.py#1-299","gmt_create":"2026-05-23T15:26:10.052723+08:00","gmt_modified":"2026-05-23T15:26:10.052724+08:00"},{"id":2583,"source_id":"6a9387dd3885cf4d27bce3db87fd61c7","target_id":"41c1962c6c680f23f0fde4efc0edc618","source_type":"SOURCE_FILE","target_type":"CODE_SNIPPET","relationship_type":"CONTAINS","extra":"Source file contains code snippet: 1-299","gmt_create":"2026-05-23T15:26:10.054022+08:00","gmt_modified":"2026-05-23T15:26:10.054023+08:00"},{"id":2584,"source_id":"c5849940-e223-4222-be17-aa0a6cb36bc8","target_id":"6281fff17a86ec1895c64d87c2ae7fb1","source_type":"WIKI_ITEM","target_type":"CODE_SNIPPET","relationship_type":"CONTAINS","extra":"Wiki contains code snippet: backend/app/models/query.py#1-55","gmt_create":"2026-05-23T15:26:10.056182+08:00","gmt_modified":"2026-05-23T15:26:10.056182+08:00"},{"id":2585,"source_id":"c5849940-e223-4222-be17-aa0a6cb36bc8","target_id":"a0eac56d622a2fff529bc2b796064bcd","source_type":"WIKI_ITEM","target_type":"CODE_SNIPPET","relationship_type":"CONTAINS","extra":"Wiki contains code snippet: backend/app/schemas/query.py#1-94","gmt_create":"2026-05-23T15:26:10.058098+08:00","gmt_modified":"2026-05-23T15:26:10.058099+08:00"},{"id":2586,"source_id":"c5849940-e223-4222-be17-aa0a6cb36bc8","target_id":"6286d4be455dc058c8be2ee4e0d1175a","source_type":"WIKI_ITEM","target_type":"CODE_SNIPPET","relationship_type":"CONTAINS","extra":"Wiki contains code snippet: backend/app/main.py#38-42","gmt_create":"2026-05-23T15:26:10.078591+08:00","gmt_modified":"2026-05-23T15:26:10.078592+08:00"},{"id":2587,"source_id":"c5849940-e223-4222-be17-aa0a6cb36bc8","target_id":"bf0d60f20f3ea5a2f2458ba86d3f9173","source_type":"WIKI_ITEM","target_type":"CODE_SNIPPET","relationship_type":"CONTAINS","extra":"Wiki contains code snippet: backend/app/models/agent.py#1-206","gmt_create":"2026-05-23T15:26:10.096602+08:00","gmt_modified":"2026-05-23T15:26:10.096603+08:00"},{"id":2588,"source_id":"c5849940-e223-4222-be17-aa0a6cb36bc8","target_id":"dd36901ce62b8cc1d66667dcdc45e637","source_type":"WIKI_ITEM","target_type":"CODE_SNIPPET","relationship_type":"CONTAINS","extra":"Wiki contains code snippet: backend/app/config.py#1-46","gmt_create":"2026-05-23T15:26:10.135722+08:00","gmt_modified":"2026-05-23T15:26:10.135722+08:00"},{"id":2589,"source_id":"c5849940-e223-4222-be17-aa0a6cb36bc8","target_id":"08d06b8b6e8c01974ec66e0a5b10795f","source_type":"WIKI_ITEM","target_type":"CODE_SNIPPET","relationship_type":"CONTAINS","extra":"Wiki contains code snippet: backend/app/schemas/query.py#6-8","gmt_create":"2026-05-23T15:26:10.138241+08:00","gmt_modified":"2026-05-23T15:26:10.138241+08:00"},{"id":2590,"source_id":"f301b79d833233ce39d350e82a71c938","target_id":"08d06b8b6e8c01974ec66e0a5b10795f","source_type":"SOURCE_FILE","target_type":"CODE_SNIPPET","relationship_type":"CONTAINS","extra":"Source file contains code snippet: 6-8","gmt_create":"2026-05-23T15:26:10.139566+08:00","gmt_modified":"2026-05-23T15:26:10.139567+08:00"},{"id":2591,"source_id":"c5849940-e223-4222-be17-aa0a6cb36bc8","target_id":"1ee5153c867fc6e9d277a3067963a1fc","source_type":"WIKI_ITEM","target_type":"CODE_SNIPPET","relationship_type":"CONTAINS","extra":"Wiki contains code snippet: backend/app/workers/scheduler.py#32-38","gmt_create":"2026-05-23T15:26:10.145894+08:00","gmt_modified":"2026-05-23T15:26:10.145895+08:00"},{"id":2592,"source_id":"c5849940-e223-4222-be17-aa0a6cb36bc8","target_id":"a6811a3e7a5e0874867a1839912ac150","source_type":"WIKI_ITEM","target_type":"CODE_SNIPPET","relationship_type":"CONTAINS","extra":"Wiki contains code snippet: frontend/lib/api.ts#1","gmt_create":"2026-05-23T15:26:10.164126+08:00","gmt_modified":"2026-05-23T15:26:10.164126+08:00"},{"id":2593,"source_id":"5d7886d0dc99f81073a578b8aefdd375","target_id":"a6811a3e7a5e0874867a1839912ac150","source_type":"SOURCE_FILE","target_type":"CODE_SNIPPET","relationship_type":"CONTAINS","extra":"Source file contains code snippet: 1","gmt_create":"2026-05-23T15:26:10.167766+08:00","gmt_modified":"2026-05-23T15:26:10.167771+08:00"},{"id":2594,"source_id":"c5849940-e223-4222-be17-aa0a6cb36bc8","target_id":"7480204ff8e76e1fedc3c82967acbddf","source_type":"WIKI_ITEM","target_type":"CODE_SNIPPET","relationship_type":"CONTAINS","extra":"Wiki contains code snippet: .env.example#1-35","gmt_create":"2026-05-23T15:26:10.175436+08:00","gmt_modified":"2026-05-23T15:26:10.175437+08:00"},{"id":2595,"source_id":"c2036406c4a0ae8b1e671ef1f1601826","target_id":"7480204ff8e76e1fedc3c82967acbddf","source_type":"SOURCE_FILE","target_type":"CODE_SNIPPET","relationship_type":"CONTAINS","extra":"Source file contains code snippet: 1-35","gmt_create":"2026-05-23T15:26:10.18136+08:00","gmt_modified":"2026-05-23T15:26:10.18136+08:00"},{"id":2596,"source_id":"c5849940-e223-4222-be17-aa0a6cb36bc8","target_id":"b41c589b6a7e0c0addb0aa1d78666cf7","source_type":"WIKI_ITEM","target_type":"CODE_SNIPPET","relationship_type":"CONTAINS","extra":"Wiki contains code snippet: backend/app/schemas/query.py#6","gmt_create":"2026-05-23T15:26:10.194836+08:00","gmt_modified":"2026-05-23T15:26:10.194836+08:00"},{"id":2597,"source_id":"f301b79d833233ce39d350e82a71c938","target_id":"b41c589b6a7e0c0addb0aa1d78666cf7","source_type":"SOURCE_FILE","target_type":"CODE_SNIPPET","relationship_type":"CONTAINS","extra":"Source file contains code snippet: 6","gmt_create":"2026-05-23T15:26:10.195771+08:00","gmt_modified":"2026-05-23T15:26:10.195771+08:00"},{"id":2598,"source_id":"c5849940-e223-4222-be17-aa0a6cb36bc8","target_id":"d20fc729a5d3986b1c077f9e07ece9c4","source_type":"WIKI_ITEM","target_type":"CODE_SNIPPET","relationship_type":"CONTAINS","extra":"Wiki contains code snippet: backend/app/config.py#7","gmt_create":"2026-05-23T15:26:10.197696+08:00","gmt_modified":"2026-05-23T15:26:10.197696+08:00"},{"id":2599,"source_id":"c5849940-e223-4222-be17-aa0a6cb36bc8","target_id":"05089063cd933e72db9ddd32806194bb","source_type":"WIKI_ITEM","target_type":"CODE_SNIPPET","relationship_type":"CONTAINS","extra":"Wiki contains code snippet: backend/requirements.txt#5-8","gmt_create":"2026-05-23T15:26:10.201339+08:00","gmt_modified":"2026-05-23T15:26:10.201339+08:00"},{"id":2600,"source_id":"a26ee01cf41da3b956e1650448c156fa","target_id":"05089063cd933e72db9ddd32806194bb","source_type":"SOURCE_FILE","target_type":"CODE_SNIPPET","relationship_type":"CONTAINS","extra":"Source file contains code snippet: 5-8","gmt_create":"2026-05-23T15:26:10.20309+08:00","gmt_modified":"2026-05-23T15:26:10.203091+08:00"},{"id":2601,"source_id":"c5849940-e223-4222-be17-aa0a6cb36bc8","target_id":"0a7f1ad960e7961b21073bdd1dbef2cb","source_type":"WIKI_ITEM","target_type":"CODE_SNIPPET","relationship_type":"CONTAINS","extra":"Wiki contains code snippet: frontend/lib/api.ts#3-21","gmt_create":"2026-05-23T15:26:10.20642+08:00","gmt_modified":"2026-05-23T15:26:10.20642+08:00"},{"id":2602,"source_id":"5d7886d0dc99f81073a578b8aefdd375","target_id":"0a7f1ad960e7961b21073bdd1dbef2cb","source_type":"SOURCE_FILE","target_type":"CODE_SNIPPET","relationship_type":"CONTAINS","extra":"Source file contains code snippet: 3-21","gmt_create":"2026-05-23T15:26:10.207549+08:00","gmt_modified":"2026-05-23T15:26:10.207549+08:00"},{"id":2603,"source_id":"c5849940-e223-4222-be17-aa0a6cb36bc8","target_id":"c099b506f31f17751b7e08f64b2b1cbe","source_type":"WIKI_ITEM","target_type":"CODE_SNIPPET","relationship_type":"CONTAINS","extra":"Wiki contains code snippet: frontend/lib/api.ts#16-21","gmt_create":"2026-05-23T15:26:10.227241+08:00","gmt_modified":"2026-05-23T15:26:10.227242+08:00"},{"id":2604,"source_id":"5d7886d0dc99f81073a578b8aefdd375","target_id":"c099b506f31f17751b7e08f64b2b1cbe","source_type":"SOURCE_FILE","target_type":"CODE_SNIPPET","relationship_type":"CONTAINS","extra":"Source file contains code snippet: 16-21","gmt_create":"2026-05-23T15:26:10.228953+08:00","gmt_modified":"2026-05-23T15:26:10.228953+08:00"},{"id":2605,"source_id":"c5849940-e223-4222-be17-aa0a6cb36bc8","target_id":"7289a3568c137c8a671fc8c963bb8d28","source_type":"WIKI_ITEM","target_type":"CODE_SNIPPET","relationship_type":"CONTAINS","extra":"Wiki contains code snippet: backend/requirements.txt#1-35","gmt_create":"2026-05-23T15:26:10.234133+08:00","gmt_modified":"2026-05-23T15:26:10.234133+08:00"},{"id":2606,"source_id":"c5849940-e223-4222-be17-aa0a6cb36bc8","target_id":"c45dbdda70a8b9f02b52af4991644d0b","source_type":"WIKI_ITEM","target_type":"CODE_SNIPPET","relationship_type":"CONTAINS","extra":"Wiki contains code snippet: frontend/package.json#11-27","gmt_create":"2026-05-23T15:26:10.235735+08:00","gmt_modified":"2026-05-23T15:26:10.235735+08:00"},{"id":2607,"source_id":"c5849940-e223-4222-be17-aa0a6cb36bc8","target_id":"3365fa8db33d43bab1d0a614e8af3a70","source_type":"WIKI_ITEM","target_type":"CODE_SNIPPET","relationship_type":"CONTAINS","extra":"Wiki contains code snippet: backend/app/main.py#45-47","gmt_create":"2026-05-23T15:26:10.240933+08:00","gmt_modified":"2026-05-23T15:26:10.240933+08:00"},{"id":2608,"source_id":"c5849940-e223-4222-be17-aa0a6cb36bc8","target_id":"9f6d9941f3b93e29d714bfec7e83434c","source_type":"WIKI_ITEM","target_type":"CODE_SNIPPET","relationship_type":"CONTAINS","extra":"Wiki contains code snippet: backend/app/main.py#30-36","gmt_create":"2026-05-23T15:26:10.243025+08:00","gmt_modified":"2026-05-23T15:26:10.243026+08:00"},{"id":2609,"source_id":"c5849940-e223-4222-be17-aa0a6cb36bc8","target_id":"6997483bdbba1455b9454fe4cccbba45","source_type":"WIKI_ITEM","target_type":"CODE_SNIPPET","relationship_type":"CONTAINS","extra":"Wiki contains code snippet: backend/app/workers/platforms/kimi.py#23-32","gmt_create":"2026-05-23T15:26:10.246518+08:00","gmt_modified":"2026-05-23T15:26:10.246519+08:00"},{"id":2610,"source_id":"8f973791233c698b3e64a4fb28a93d4b","target_id":"6997483bdbba1455b9454fe4cccbba45","source_type":"SOURCE_FILE","target_type":"CODE_SNIPPET","relationship_type":"CONTAINS","extra":"Source file contains code snippet: 23-32","gmt_create":"2026-05-23T15:26:10.248783+08:00","gmt_modified":"2026-05-23T15:26:10.248783+08:00"},{"id":2611,"source_id":"34e572eb-6fc8-4de7-8061-63783ef8be24","target_id":"1c4316a1-f1d7-46da-bcfc-ea2fa0c56110","source_type":"WIKI_ITEM","target_type":"WIKI_ITEM","relationship_type":"PARENT_CHILD","extra":"Wiki parent-child relationship: 34e572eb-6fc8-4de7-8061-63783ef8be24 -\u003e 1c4316a1-f1d7-46da-bcfc-ea2fa0c56110","gmt_create":"2026-05-23T15:26:11.42441+08:00","gmt_modified":"2026-05-23T15:26:11.424411+08:00"},{"id":2612,"source_id":"c7eb113b-b503-4d83-be7f-9ccf3350c9d9","target_id":"f94da0b4-8a07-4de1-b0b3-d3b32a12c3c1","source_type":"WIKI_ITEM","target_type":"WIKI_ITEM","relationship_type":"PARENT_CHILD","extra":"Wiki parent-child relationship: c7eb113b-b503-4d83-be7f-9ccf3350c9d9 -\u003e f94da0b4-8a07-4de1-b0b3-d3b32a12c3c1","gmt_create":"2026-05-23T15:26:11.426597+08:00","gmt_modified":"2026-05-23T15:26:11.426597+08:00"},{"id":2613,"source_id":"c7eb113b-b503-4d83-be7f-9ccf3350c9d9","target_id":"df661133-efbf-43fe-97c3-f581c81f47a7","source_type":"WIKI_ITEM","target_type":"WIKI_ITEM","relationship_type":"PARENT_CHILD","extra":"Wiki parent-child relationship: c7eb113b-b503-4d83-be7f-9ccf3350c9d9 -\u003e df661133-efbf-43fe-97c3-f581c81f47a7","gmt_create":"2026-05-23T15:26:11.42852+08:00","gmt_modified":"2026-05-23T15:26:11.428521+08:00"},{"id":2614,"source_id":"c7eb113b-b503-4d83-be7f-9ccf3350c9d9","target_id":"11936bb5-374f-40f4-bb53-b75264fc4b9d","source_type":"WIKI_ITEM","target_type":"WIKI_ITEM","relationship_type":"PARENT_CHILD","extra":"Wiki parent-child relationship: c7eb113b-b503-4d83-be7f-9ccf3350c9d9 -\u003e 11936bb5-374f-40f4-bb53-b75264fc4b9d","gmt_create":"2026-05-23T15:26:11.430157+08:00","gmt_modified":"2026-05-23T15:26:11.430158+08:00"},{"id":2615,"source_id":"c7eb113b-b503-4d83-be7f-9ccf3350c9d9","target_id":"23ad3419-5473-4e2c-ac87-d9715090279d","source_type":"WIKI_ITEM","target_type":"WIKI_ITEM","relationship_type":"PARENT_CHILD","extra":"Wiki parent-child relationship: c7eb113b-b503-4d83-be7f-9ccf3350c9d9 -\u003e 23ad3419-5473-4e2c-ac87-d9715090279d","gmt_create":"2026-05-23T15:26:11.432268+08:00","gmt_modified":"2026-05-23T15:26:11.432268+08:00"},{"id":2616,"source_id":"c7eb113b-b503-4d83-be7f-9ccf3350c9d9","target_id":"19e75845-5147-4aeb-90be-16f3aa270465","source_type":"WIKI_ITEM","target_type":"WIKI_ITEM","relationship_type":"PARENT_CHILD","extra":"Wiki parent-child relationship: c7eb113b-b503-4d83-be7f-9ccf3350c9d9 -\u003e 19e75845-5147-4aeb-90be-16f3aa270465","gmt_create":"2026-05-23T15:26:11.434024+08:00","gmt_modified":"2026-05-23T15:26:11.434024+08:00"},{"id":2617,"source_id":"c7eb113b-b503-4d83-be7f-9ccf3350c9d9","target_id":"83fe6837-7874-4467-8114-103062f15f58","source_type":"WIKI_ITEM","target_type":"WIKI_ITEM","relationship_type":"PARENT_CHILD","extra":"Wiki parent-child relationship: c7eb113b-b503-4d83-be7f-9ccf3350c9d9 -\u003e 83fe6837-7874-4467-8114-103062f15f58","gmt_create":"2026-05-23T15:26:11.435215+08:00","gmt_modified":"2026-05-23T15:26:11.435215+08:00"},{"id":2618,"source_id":"3af3bb9e-4d99-4dc3-b1ed-2686db385c26","target_id":"c112a3f4-b0a1-4c4a-a325-e3ede8c90be6","source_type":"WIKI_ITEM","target_type":"WIKI_ITEM","relationship_type":"PARENT_CHILD","extra":"Wiki parent-child relationship: 3af3bb9e-4d99-4dc3-b1ed-2686db385c26 -\u003e c112a3f4-b0a1-4c4a-a325-e3ede8c90be6","gmt_create":"2026-05-23T15:26:11.43808+08:00","gmt_modified":"2026-05-23T15:26:11.43808+08:00"},{"id":2619,"source_id":"3af3bb9e-4d99-4dc3-b1ed-2686db385c26","target_id":"2b32ec11-d228-42c0-9232-103ba7e44f71","source_type":"WIKI_ITEM","target_type":"WIKI_ITEM","relationship_type":"PARENT_CHILD","extra":"Wiki parent-child relationship: 3af3bb9e-4d99-4dc3-b1ed-2686db385c26 -\u003e 2b32ec11-d228-42c0-9232-103ba7e44f71","gmt_create":"2026-05-23T15:26:11.440929+08:00","gmt_modified":"2026-05-23T15:26:11.440929+08:00"},{"id":2620,"source_id":"3af3bb9e-4d99-4dc3-b1ed-2686db385c26","target_id":"ba0390b3-c249-4e92-a3c8-6820343aeda9","source_type":"WIKI_ITEM","target_type":"WIKI_ITEM","relationship_type":"PARENT_CHILD","extra":"Wiki parent-child relationship: 3af3bb9e-4d99-4dc3-b1ed-2686db385c26 -\u003e ba0390b3-c249-4e92-a3c8-6820343aeda9","gmt_create":"2026-05-23T15:26:11.442379+08:00","gmt_modified":"2026-05-23T15:26:11.442379+08:00"},{"id":2621,"source_id":"3af3bb9e-4d99-4dc3-b1ed-2686db385c26","target_id":"760610d4-dff6-4c6d-831f-7c9078db86a6","source_type":"WIKI_ITEM","target_type":"WIKI_ITEM","relationship_type":"PARENT_CHILD","extra":"Wiki parent-child relationship: 3af3bb9e-4d99-4dc3-b1ed-2686db385c26 -\u003e 760610d4-dff6-4c6d-831f-7c9078db86a6","gmt_create":"2026-05-23T15:26:11.44359+08:00","gmt_modified":"2026-05-23T15:26:11.44359+08:00"},{"id":2622,"source_id":"3af3bb9e-4d99-4dc3-b1ed-2686db385c26","target_id":"a40267bc-925a-4364-a01f-b96d3df60aea","source_type":"WIKI_ITEM","target_type":"WIKI_ITEM","relationship_type":"PARENT_CHILD","extra":"Wiki parent-child relationship: 3af3bb9e-4d99-4dc3-b1ed-2686db385c26 -\u003e a40267bc-925a-4364-a01f-b96d3df60aea","gmt_create":"2026-05-23T15:26:11.445284+08:00","gmt_modified":"2026-05-23T15:26:11.445284+08:00"},{"id":2623,"source_id":"3af3bb9e-4d99-4dc3-b1ed-2686db385c26","target_id":"7bd2c461-81b0-48e8-8cb3-b4b14305806d","source_type":"WIKI_ITEM","target_type":"WIKI_ITEM","relationship_type":"PARENT_CHILD","extra":"Wiki parent-child relationship: 3af3bb9e-4d99-4dc3-b1ed-2686db385c26 -\u003e 7bd2c461-81b0-48e8-8cb3-b4b14305806d","gmt_create":"2026-05-23T15:26:11.446751+08:00","gmt_modified":"2026-05-23T15:26:11.446752+08:00"},{"id":2624,"source_id":"ffbb970e-56e0-40ad-bd88-1a1e55482d96","target_id":"d5c75004-b01b-416f-850a-4791c5489a32","source_type":"WIKI_ITEM","target_type":"WIKI_ITEM","relationship_type":"PARENT_CHILD","extra":"Wiki parent-child relationship: ffbb970e-56e0-40ad-bd88-1a1e55482d96 -\u003e d5c75004-b01b-416f-850a-4791c5489a32","gmt_create":"2026-05-23T15:26:11.468281+08:00","gmt_modified":"2026-05-23T15:26:11.468281+08:00"},{"id":2625,"source_id":"ffbb970e-56e0-40ad-bd88-1a1e55482d96","target_id":"c3fa653f-8dd7-41fe-8c2e-8b60adbf70f4","source_type":"WIKI_ITEM","target_type":"WIKI_ITEM","relationship_type":"PARENT_CHILD","extra":"Wiki parent-child relationship: ffbb970e-56e0-40ad-bd88-1a1e55482d96 -\u003e c3fa653f-8dd7-41fe-8c2e-8b60adbf70f4","gmt_create":"2026-05-23T15:26:11.470185+08:00","gmt_modified":"2026-05-23T15:26:11.470185+08:00"},{"id":2626,"source_id":"ffbb970e-56e0-40ad-bd88-1a1e55482d96","target_id":"262a3941-fdc6-46b0-b767-be40aa9d5761","source_type":"WIKI_ITEM","target_type":"WIKI_ITEM","relationship_type":"PARENT_CHILD","extra":"Wiki parent-child relationship: ffbb970e-56e0-40ad-bd88-1a1e55482d96 -\u003e 262a3941-fdc6-46b0-b767-be40aa9d5761","gmt_create":"2026-05-23T15:26:11.471306+08:00","gmt_modified":"2026-05-23T15:26:11.471306+08:00"},{"id":2627,"source_id":"ffbb970e-56e0-40ad-bd88-1a1e55482d96","target_id":"7c0201f7-9e02-4cba-9ee1-81c3477f049a","source_type":"WIKI_ITEM","target_type":"WIKI_ITEM","relationship_type":"PARENT_CHILD","extra":"Wiki parent-child relationship: ffbb970e-56e0-40ad-bd88-1a1e55482d96 -\u003e 7c0201f7-9e02-4cba-9ee1-81c3477f049a","gmt_create":"2026-05-23T15:26:11.472613+08:00","gmt_modified":"2026-05-23T15:26:11.472613+08:00"},{"id":2628,"source_id":"49915365-e38e-43b5-beac-6aa7d5a74cbb","target_id":"7c7564ee-7fe2-4555-8ff0-4ec1b757997a","source_type":"WIKI_ITEM","target_type":"WIKI_ITEM","relationship_type":"PARENT_CHILD","extra":"Wiki parent-child relationship: 49915365-e38e-43b5-beac-6aa7d5a74cbb -\u003e 7c7564ee-7fe2-4555-8ff0-4ec1b757997a","gmt_create":"2026-05-23T15:26:11.478176+08:00","gmt_modified":"2026-05-23T15:26:11.478177+08:00"},{"id":2629,"source_id":"49915365-e38e-43b5-beac-6aa7d5a74cbb","target_id":"74d3018f-4e23-4687-8bf4-7fb403f479f7","source_type":"WIKI_ITEM","target_type":"WIKI_ITEM","relationship_type":"PARENT_CHILD","extra":"Wiki parent-child relationship: 49915365-e38e-43b5-beac-6aa7d5a74cbb -\u003e 74d3018f-4e23-4687-8bf4-7fb403f479f7","gmt_create":"2026-05-23T15:26:11.479896+08:00","gmt_modified":"2026-05-23T15:26:11.479896+08:00"},{"id":2630,"source_id":"49915365-e38e-43b5-beac-6aa7d5a74cbb","target_id":"737f8d6c-bd8f-4c11-b142-71a400423323","source_type":"WIKI_ITEM","target_type":"WIKI_ITEM","relationship_type":"PARENT_CHILD","extra":"Wiki parent-child relationship: 49915365-e38e-43b5-beac-6aa7d5a74cbb -\u003e 737f8d6c-bd8f-4c11-b142-71a400423323","gmt_create":"2026-05-23T15:26:11.481543+08:00","gmt_modified":"2026-05-23T15:26:11.481543+08:00"},{"id":2631,"source_id":"49915365-e38e-43b5-beac-6aa7d5a74cbb","target_id":"ae62f4a8-8840-4c8e-9a42-3373370299ff","source_type":"WIKI_ITEM","target_type":"WIKI_ITEM","relationship_type":"PARENT_CHILD","extra":"Wiki parent-child relationship: 49915365-e38e-43b5-beac-6aa7d5a74cbb -\u003e ae62f4a8-8840-4c8e-9a42-3373370299ff","gmt_create":"2026-05-23T15:26:11.483862+08:00","gmt_modified":"2026-05-23T15:26:11.483862+08:00"},{"id":2632,"source_id":"98909ecc-fceb-4ab7-a26f-741838eb2e50","target_id":"1ed0b482-3d6a-4bfd-af40-47a5d1f3e802","source_type":"WIKI_ITEM","target_type":"WIKI_ITEM","relationship_type":"PARENT_CHILD","extra":"Wiki parent-child relationship: 98909ecc-fceb-4ab7-a26f-741838eb2e50 -\u003e 1ed0b482-3d6a-4bfd-af40-47a5d1f3e802","gmt_create":"2026-05-23T15:26:11.485457+08:00","gmt_modified":"2026-05-23T15:26:11.485458+08:00"},{"id":2633,"source_id":"98909ecc-fceb-4ab7-a26f-741838eb2e50","target_id":"26f80935-eac2-44ee-bcdb-d6a79c537750","source_type":"WIKI_ITEM","target_type":"WIKI_ITEM","relationship_type":"PARENT_CHILD","extra":"Wiki parent-child relationship: 98909ecc-fceb-4ab7-a26f-741838eb2e50 -\u003e 26f80935-eac2-44ee-bcdb-d6a79c537750","gmt_create":"2026-05-23T15:26:11.486443+08:00","gmt_modified":"2026-05-23T15:26:11.486443+08:00"},{"id":2634,"source_id":"98909ecc-fceb-4ab7-a26f-741838eb2e50","target_id":"eb1288f7-5ea1-413a-8f54-4f870306d14d","source_type":"WIKI_ITEM","target_type":"WIKI_ITEM","relationship_type":"PARENT_CHILD","extra":"Wiki parent-child relationship: 98909ecc-fceb-4ab7-a26f-741838eb2e50 -\u003e eb1288f7-5ea1-413a-8f54-4f870306d14d","gmt_create":"2026-05-23T15:26:11.487483+08:00","gmt_modified":"2026-05-23T15:26:11.487483+08:00"},{"id":2635,"source_id":"98909ecc-fceb-4ab7-a26f-741838eb2e50","target_id":"aa6db9b6-71e1-4497-a0e2-f3ff25358d3a","source_type":"WIKI_ITEM","target_type":"WIKI_ITEM","relationship_type":"PARENT_CHILD","extra":"Wiki parent-child relationship: 98909ecc-fceb-4ab7-a26f-741838eb2e50 -\u003e aa6db9b6-71e1-4497-a0e2-f3ff25358d3a","gmt_create":"2026-05-23T15:26:11.48887+08:00","gmt_modified":"2026-05-23T15:26:11.48887+08:00"},{"id":2636,"source_id":"643984fc-5a57-498b-8f25-68cc318d9d82","target_id":"13c568d2-dfa7-4d1b-81c0-dfef247cbb67","source_type":"WIKI_ITEM","target_type":"WIKI_ITEM","relationship_type":"PARENT_CHILD","extra":"Wiki parent-child relationship: 643984fc-5a57-498b-8f25-68cc318d9d82 -\u003e 13c568d2-dfa7-4d1b-81c0-dfef247cbb67","gmt_create":"2026-05-23T15:26:11.490522+08:00","gmt_modified":"2026-05-23T15:26:11.490522+08:00"},{"id":2637,"source_id":"643984fc-5a57-498b-8f25-68cc318d9d82","target_id":"222a9371-45c1-4e0d-b1da-e8ada1c501c2","source_type":"WIKI_ITEM","target_type":"WIKI_ITEM","relationship_type":"PARENT_CHILD","extra":"Wiki parent-child relationship: 643984fc-5a57-498b-8f25-68cc318d9d82 -\u003e 222a9371-45c1-4e0d-b1da-e8ada1c501c2","gmt_create":"2026-05-23T15:26:11.492226+08:00","gmt_modified":"2026-05-23T15:26:11.492226+08:00"},{"id":2638,"source_id":"643984fc-5a57-498b-8f25-68cc318d9d82","target_id":"979be617-a83d-4db9-b73e-38581348f8c1","source_type":"WIKI_ITEM","target_type":"WIKI_ITEM","relationship_type":"PARENT_CHILD","extra":"Wiki parent-child relationship: 643984fc-5a57-498b-8f25-68cc318d9d82 -\u003e 979be617-a83d-4db9-b73e-38581348f8c1","gmt_create":"2026-05-23T15:26:11.493178+08:00","gmt_modified":"2026-05-23T15:26:11.493178+08:00"},{"id":2639,"source_id":"643984fc-5a57-498b-8f25-68cc318d9d82","target_id":"422c46b3-e69c-4023-a878-411a48ae182f","source_type":"WIKI_ITEM","target_type":"WIKI_ITEM","relationship_type":"PARENT_CHILD","extra":"Wiki parent-child relationship: 643984fc-5a57-498b-8f25-68cc318d9d82 -\u003e 422c46b3-e69c-4023-a878-411a48ae182f","gmt_create":"2026-05-23T15:26:11.494227+08:00","gmt_modified":"2026-05-23T15:26:11.494227+08:00"},{"id":2640,"source_id":"b0c36b2b-bb03-4624-933d-c1f6a320b7ca","target_id":"8150ddbb-7aa9-48d0-9953-2ef55e4bcfd5","source_type":"WIKI_ITEM","target_type":"WIKI_ITEM","relationship_type":"PARENT_CHILD","extra":"Wiki parent-child relationship: b0c36b2b-bb03-4624-933d-c1f6a320b7ca -\u003e 8150ddbb-7aa9-48d0-9953-2ef55e4bcfd5","gmt_create":"2026-05-23T15:26:11.495508+08:00","gmt_modified":"2026-05-23T15:26:11.495508+08:00"},{"id":2641,"source_id":"b0c36b2b-bb03-4624-933d-c1f6a320b7ca","target_id":"8c17b44f-1586-459b-a83d-c9b961cd2142","source_type":"WIKI_ITEM","target_type":"WIKI_ITEM","relationship_type":"PARENT_CHILD","extra":"Wiki parent-child relationship: b0c36b2b-bb03-4624-933d-c1f6a320b7ca -\u003e 8c17b44f-1586-459b-a83d-c9b961cd2142","gmt_create":"2026-05-23T15:26:11.49656+08:00","gmt_modified":"2026-05-23T15:26:11.49656+08:00"},{"id":2642,"source_id":"b0c36b2b-bb03-4624-933d-c1f6a320b7ca","target_id":"05e59a75-d52f-42e1-a924-f6a32f06f2fe","source_type":"WIKI_ITEM","target_type":"WIKI_ITEM","relationship_type":"PARENT_CHILD","extra":"Wiki parent-child relationship: b0c36b2b-bb03-4624-933d-c1f6a320b7ca -\u003e 05e59a75-d52f-42e1-a924-f6a32f06f2fe","gmt_create":"2026-05-23T15:26:11.497857+08:00","gmt_modified":"2026-05-23T15:26:11.497857+08:00"},{"id":2643,"source_id":"c5849940-e223-4222-be17-aa0a6cb36bc8","target_id":"d2c7157d-157f-4990-8f76-11f3ea5435f7","source_type":"WIKI_ITEM","target_type":"WIKI_ITEM","relationship_type":"PARENT_CHILD","extra":"Wiki parent-child relationship: c5849940-e223-4222-be17-aa0a6cb36bc8 -\u003e d2c7157d-157f-4990-8f76-11f3ea5435f7","gmt_create":"2026-05-23T15:26:11.499867+08:00","gmt_modified":"2026-05-23T15:26:11.499867+08:00"},{"id":2644,"source_id":"c5849940-e223-4222-be17-aa0a6cb36bc8","target_id":"e1e0bd0e-01b3-4543-9781-d9beb32b9a57","source_type":"WIKI_ITEM","target_type":"WIKI_ITEM","relationship_type":"PARENT_CHILD","extra":"Wiki parent-child relationship: c5849940-e223-4222-be17-aa0a6cb36bc8 -\u003e e1e0bd0e-01b3-4543-9781-d9beb32b9a57","gmt_create":"2026-05-23T15:26:11.501613+08:00","gmt_modified":"2026-05-23T15:26:11.501613+08:00"},{"id":2645,"source_id":"c5849940-e223-4222-be17-aa0a6cb36bc8","target_id":"e9a02c86-236b-49cb-bbed-9462ee123c04","source_type":"WIKI_ITEM","target_type":"WIKI_ITEM","relationship_type":"PARENT_CHILD","extra":"Wiki parent-child relationship: c5849940-e223-4222-be17-aa0a6cb36bc8 -\u003e e9a02c86-236b-49cb-bbed-9462ee123c04","gmt_create":"2026-05-23T15:26:11.502659+08:00","gmt_modified":"2026-05-23T15:26:11.502659+08:00"},{"id":2646,"source_id":"1c4316a1-f1d7-46da-bcfc-ea2fa0c56110","target_id":"ec2f1708-d31e-42bb-8959-fa405db7d6da","source_type":"WIKI_ITEM","target_type":"WIKI_ITEM","relationship_type":"PARENT_CHILD","extra":"Wiki parent-child relationship: 1c4316a1-f1d7-46da-bcfc-ea2fa0c56110 -\u003e ec2f1708-d31e-42bb-8959-fa405db7d6da","gmt_create":"2026-05-23T15:26:11.525084+08:00","gmt_modified":"2026-05-23T15:26:11.525084+08:00"},{"id":2647,"source_id":"1c4316a1-f1d7-46da-bcfc-ea2fa0c56110","target_id":"2059d1cd-98a3-4b7f-b29b-69acf8a0d751","source_type":"WIKI_ITEM","target_type":"WIKI_ITEM","relationship_type":"PARENT_CHILD","extra":"Wiki parent-child relationship: 1c4316a1-f1d7-46da-bcfc-ea2fa0c56110 -\u003e 2059d1cd-98a3-4b7f-b29b-69acf8a0d751","gmt_create":"2026-05-23T15:26:11.526803+08:00","gmt_modified":"2026-05-23T15:26:11.526803+08:00"},{"id":2648,"source_id":"1c4316a1-f1d7-46da-bcfc-ea2fa0c56110","target_id":"d474a7a6-e056-4456-ba79-4aedbb7add58","source_type":"WIKI_ITEM","target_type":"WIKI_ITEM","relationship_type":"PARENT_CHILD","extra":"Wiki parent-child relationship: 1c4316a1-f1d7-46da-bcfc-ea2fa0c56110 -\u003e d474a7a6-e056-4456-ba79-4aedbb7add58","gmt_create":"2026-05-23T15:26:11.528146+08:00","gmt_modified":"2026-05-23T15:26:11.528146+08:00"},{"id":2649,"source_id":"1c4316a1-f1d7-46da-bcfc-ea2fa0c56110","target_id":"2d7c030d-7b82-418c-9a16-67b067cac93c","source_type":"WIKI_ITEM","target_type":"WIKI_ITEM","relationship_type":"PARENT_CHILD","extra":"Wiki parent-child relationship: 1c4316a1-f1d7-46da-bcfc-ea2fa0c56110 -\u003e 2d7c030d-7b82-418c-9a16-67b067cac93c","gmt_create":"2026-05-23T15:26:11.529536+08:00","gmt_modified":"2026-05-23T15:26:11.529537+08:00"}],"source_files":[{"id":"12e2c3d7b9a92dc44a6ee29b85e10df6","path":"frontend/app/layout.tsx","filename":"layout.tsx","gmt_create":"2026-04-23T15:19:43.754128+08:00","gmt_modified":"2026-04-23T15:19:43.754129+08:00"},{"id":"2a1c745c7b3fb7f600596be3d979bba1","path":"frontend/app/(dashboard","filename":"(dashboard","gmt_create":"2026-04-23T15:19:43.756075+08:00","gmt_modified":"2026-04-23T15:19:43.756075+08:00"},{"id":"eca13a610badfc5ffc6210827fb96991","path":"frontend/components/layout/header.tsx","filename":"header.tsx","gmt_create":"2026-04-23T15:19:43.756308+08:00","gmt_modified":"2026-04-23T15:19:43.756308+08:00"},{"id":"18a0651d895fba9bb4e0c0229459efdc","path":"frontend/components/layout/sidebar.tsx","filename":"sidebar.tsx","gmt_create":"2026-04-23T15:19:43.756496+08:00","gmt_modified":"2026-04-23T15:19:43.756496+08:00"},{"id":"5d7886d0dc99f81073a578b8aefdd375","path":"frontend/lib/api.ts","filename":"api.ts","gmt_create":"2026-04-23T15:19:43.756648+08:00","gmt_modified":"2026-04-23T15:19:43.756648+08:00"},{"id":"0c0b0f4e2cf44facd9d5b57de0d0bf0c","path":"frontend/components/ui/table.tsx","filename":"table.tsx","gmt_create":"2026-04-23T15:19:43.758184+08:00","gmt_modified":"2026-04-23T15:19:43.758184+08:00"},{"id":"108b0c4b4dcfb6aa39a5eb138225c148","path":"frontend/components/ui/dialog.tsx","filename":"dialog.tsx","gmt_create":"2026-04-23T15:19:43.75905+08:00","gmt_modified":"2026-04-23T15:19:43.75905+08:00"},{"id":"ef72f0c3cedb9fd9a87352fe493053dc","path":"frontend/lib/platforms.ts","filename":"platforms.ts","gmt_create":"2026-04-23T15:19:43.759223+08:00","gmt_modified":"2026-04-23T15:19:43.759223+08:00"},{"id":"f93ae024fe0a2e69698037dff6df205f","path":"frontend/lib/utils.ts","filename":"utils.ts","gmt_create":"2026-04-23T15:19:43.759351+08:00","gmt_modified":"2026-04-23T15:19:43.759351+08:00"},{"id":"d5f2266643d2011c66e86af088ec637f","path":"frontend/components/charts/trend-chart.tsx","filename":"trend-chart.tsx","gmt_create":"2026-04-23T15:19:43.759489+08:00","gmt_modified":"2026-04-23T15:19:43.759489+08:00"},{"id":"f1a7d61831cc0a45ac6220294f15c21d","path":"frontend/components/charts/platform-chart.tsx","filename":"platform-chart.tsx","gmt_create":"2026-04-23T15:19:43.759606+08:00","gmt_modified":"2026-04-23T15:19:43.759606+08:00"},{"id":"9228ff67d4c757a85d9421b71f4b29f5","path":"backend/app/main.py","filename":"main.py","gmt_create":"2026-04-23T15:19:45.5873+08:00","gmt_modified":"2026-04-23T15:19:45.5873+08:00"},{"id":"93022c8938ce318f167277cfa65c29a7","path":"backend/app/api/auth.py","filename":"auth.py","gmt_create":"2026-04-23T15:19:45.587785+08:00","gmt_modified":"2026-04-23T15:19:45.587786+08:00"},{"id":"6b3d903205941aa9391dd90016e1102c","path":"backend/app/api/queries.py","filename":"queries.py","gmt_create":"2026-04-23T15:19:45.588167+08:00","gmt_modified":"2026-04-23T15:19:45.588167+08:00"},{"id":"7538ffe4902ab6041adb28b19844962a","path":"backend/app/api/citations.py","filename":"citations.py","gmt_create":"2026-04-23T15:19:45.588473+08:00","gmt_modified":"2026-04-23T15:19:45.588473+08:00"},{"id":"58901c94d975d87e652a4dc6c8dda656","path":"backend/app/api/reports.py","filename":"reports.py","gmt_create":"2026-04-23T15:19:45.588695+08:00","gmt_modified":"2026-04-23T15:19:45.588695+08:00"},{"id":"9d08667997a868fc07c9b4e328e44224","path":"backend/app/api/deps.py","filename":"deps.py","gmt_create":"2026-04-23T15:19:45.588857+08:00","gmt_modified":"2026-04-23T15:19:45.588857+08:00"},{"id":"e0c0ca66b8b81cf66e078a7ab162c07f","path":"backend/app/schemas/auth.py","filename":"auth.py","gmt_create":"2026-04-23T15:19:45.589011+08:00","gmt_modified":"2026-04-23T15:19:45.589011+08:00"},{"id":"f301b79d833233ce39d350e82a71c938","path":"backend/app/schemas/query.py","filename":"query.py","gmt_create":"2026-04-23T15:19:45.589202+08:00","gmt_modified":"2026-04-23T15:19:45.589202+08:00"},{"id":"1a3336b4af8a39a055e912724338580c","path":"backend/app/schemas/citation.py","filename":"citation.py","gmt_create":"2026-04-23T15:19:45.589399+08:00","gmt_modified":"2026-04-23T15:19:45.589399+08:00"},{"id":"4d2f3847b7c10634733118b70a1aea0b","path":"backend/app/services/auth.py","filename":"auth.py","gmt_create":"2026-04-23T15:19:45.589591+08:00","gmt_modified":"2026-04-23T15:19:45.589591+08:00"},{"id":"88d22de3b2a7419868e8ae19130d860c","path":"backend/app/services/query.py","filename":"query.py","gmt_create":"2026-04-23T15:19:45.589732+08:00","gmt_modified":"2026-04-23T15:19:45.589732+08:00"},{"id":"04e3926c080e795713bff683e7dc9d3e","path":"backend/app/services/citation.py","filename":"citation.py","gmt_create":"2026-04-23T15:19:45.589852+08:00","gmt_modified":"2026-04-23T15:19:45.589852+08:00"},{"id":"9ff19022ef915615911280e3c49ed44b","path":"backend/app/config.py","filename":"config.py","gmt_create":"2026-04-23T15:19:45.589987+08:00","gmt_modified":"2026-04-23T15:19:45.589987+08:00"},{"id":"c59f8c276697a070dffc581fe94d809c","path":"backend/app/models/user.py","filename":"user.py","gmt_create":"2026-04-23T15:19:45.590197+08:00","gmt_modified":"2026-04-23T15:19:45.590198+08:00"},{"id":"b74caccb06844efcdb14d8324cff65c2","path":"backend/app/models/query.py","filename":"query.py","gmt_create":"2026-04-23T15:19:45.590343+08:00","gmt_modified":"2026-04-23T15:19:45.590344+08:00"},{"id":"b4a81ef789630d0af6a8d50859d01bf3","path":"backend/app/models/citation_record.py","filename":"citation_record.py","gmt_create":"2026-04-23T15:19:45.590489+08:00","gmt_modified":"2026-04-23T15:19:45.590489+08:00"},{"id":"069738f21ac2da7349d22683e8c36929","path":"backend/app/models/query_task.py","filename":"query_task.py","gmt_create":"2026-04-23T15:19:45.59062+08:00","gmt_modified":"2026-04-23T15:19:45.59062+08:00"},{"id":"5cbb1e3f112aeba62a14b0b8999fc0f5","path":"backend/app/workers/scheduler.py","filename":"scheduler.py","gmt_create":"2026-04-23T15:20:08.953491+08:00","gmt_modified":"2026-04-23T15:20:08.953491+08:00"},{"id":"74040de652d5e57f548bb5c4adc3e1a0","path":"backend/app/workers/citation_engine.py","filename":"citation_engine.py","gmt_create":"2026-04-23T15:20:08.953836+08:00","gmt_modified":"2026-04-23T15:20:08.953837+08:00"},{"id":"8f973791233c698b3e64a4fb28a93d4b","path":"backend/app/workers/platforms/kimi.py","filename":"kimi.py","gmt_create":"2026-04-23T15:20:08.954103+08:00","gmt_modified":"2026-04-23T15:20:08.954103+08:00"},{"id":"f642fc1c2f34e15572d9d98aa6c18813","path":"backend/app/workers/platforms/wenxin.py","filename":"wenxin.py","gmt_create":"2026-04-23T15:20:08.954273+08:00","gmt_modified":"2026-04-23T15:20:08.954273+08:00"},{"id":"a16cf42e9559523c4f96ca4c79f9488d","path":"backend/app/workers/platforms/base.py","filename":"base.py","gmt_create":"2026-04-23T15:20:08.954406+08:00","gmt_modified":"2026-04-23T15:20:08.954406+08:00"},{"id":"b0c428683c8a3e6922d90ca0d8c2736d","path":"backend/app/database.py","filename":"database.py","gmt_create":"2026-04-23T15:20:08.955702+08:00","gmt_modified":"2026-04-23T15:20:08.955702+08:00"},{"id":"b2f0d46a31a5441594f2e777365fc156","path":"tests/test_scheduler.py","filename":"test_scheduler.py","gmt_create":"2026-04-23T15:20:08.95621+08:00","gmt_modified":"2026-04-23T15:20:08.95621+08:00"},{"id":"0613e76b9679be7f998fb8fd8056e686","path":"tests/test_queries.py","filename":"test_queries.py","gmt_create":"2026-04-23T15:20:08.956336+08:00","gmt_modified":"2026-04-23T15:20:08.956336+08:00"},{"id":"99fe1b288fd41daa86c2dfbab819abf0","path":"backend/app/models/__init__.py","filename":"__init__.py","gmt_create":"2026-04-23T15:21:46.682639+08:00","gmt_modified":"2026-04-23T15:21:46.682639+08:00"},{"id":"bceca00463fe55d3bcafda728f97f723","path":"backend/app/models/subscription.py","filename":"subscription.py","gmt_create":"2026-04-23T15:21:46.684259+08:00","gmt_modified":"2026-04-23T15:21:46.684259+08:00"},{"id":"d4f95fcf50683b5bf6167c7d2a6b126d","path":"backend/alembic/versions/488d0bd5ab01_initial_migration.py","filename":"488d0bd5ab01_initial_migration.py","gmt_create":"2026-04-23T15:21:46.684619+08:00","gmt_modified":"2026-04-23T15:21:46.684619+08:00"},{"id":"0ef1efea889dba3e1f299626df479571","path":"tests/conftest.py","filename":"conftest.py","gmt_create":"2026-04-23T15:22:15.981194+08:00","gmt_modified":"2026-04-23T15:22:15.981194+08:00"},{"id":"389d631bc6c7111ba411b0b79fca455e","path":"tests/test_auth.py","filename":"test_auth.py","gmt_create":"2026-04-23T15:22:15.98141+08:00","gmt_modified":"2026-04-23T15:22:15.98141+08:00"},{"id":"80a0429cc47931de27ddb17a62b8dd9c","path":"tests/test_business_flow.py","filename":"test_business_flow.py","gmt_create":"2026-04-23T15:22:15.981566+08:00","gmt_modified":"2026-04-23T15:22:15.981567+08:00"},{"id":"b07a4fb9cecbbd66a6910ccbc7651f19","path":"tests/test_citation_engine.py","filename":"test_citation_engine.py","gmt_create":"2026-04-23T15:22:15.981715+08:00","gmt_modified":"2026-04-23T15:22:15.981715+08:00"},{"id":"42ff5383133d176cec9eb88682483be3","path":"tests/test_citations.py","filename":"test_citations.py","gmt_create":"2026-04-23T15:22:15.981831+08:00","gmt_modified":"2026-04-23T15:22:15.981831+08:00"},{"id":"aaf5bce6be82d2f947bfa5c1806de452","path":"frontend/package.json","filename":"package.json","gmt_create":"2026-04-23T15:22:23.492837+08:00","gmt_modified":"2026-04-23T15:22:23.492837+08:00"},{"id":"01056dad8851d3e9bd532eb4cab33792","path":"frontend/tailwind.config.ts","filename":"tailwind.config.ts","gmt_create":"2026-04-23T15:22:23.495792+08:00","gmt_modified":"2026-04-23T15:22:23.495792+08:00"},{"id":"ac1acbc54c49ee1de13369f6c6827568","path":"frontend/components/ui/button.tsx","filename":"button.tsx","gmt_create":"2026-04-23T15:22:23.496353+08:00","gmt_modified":"2026-04-23T15:22:23.496353+08:00"},{"id":"0186dc8a89340139a84e1e3c5571a57f","path":"frontend/components/ui/dropdown-menu.tsx","filename":"dropdown-menu.tsx","gmt_create":"2026-04-23T15:22:23.496869+08:00","gmt_modified":"2026-04-23T15:22:23.496869+08:00"},{"id":"3cf787fa77a15b2b1783560c6d83ed21","path":"frontend/components/ui/input.tsx","filename":"input.tsx","gmt_create":"2026-04-23T15:22:23.497127+08:00","gmt_modified":"2026-04-23T15:22:23.497128+08:00"},{"id":"3c56e1c079959bfcc985183805e5874f","path":"frontend/components/ui/select.tsx","filename":"select.tsx","gmt_create":"2026-04-23T15:22:23.497457+08:00","gmt_modified":"2026-04-23T15:22:23.497457+08:00"},{"id":"0d5ef537f7c0b8c390f8b31d7cf47b56","path":"frontend/components/ui/card.tsx","filename":"card.tsx","gmt_create":"2026-04-23T15:22:23.497745+08:00","gmt_modified":"2026-04-23T15:22:23.497745+08:00"},{"id":"51821ca9ec2a1c972f3c9d111e19db8a","path":"frontend/components/ui/badge.tsx","filename":"badge.tsx","gmt_create":"2026-04-23T15:22:23.498034+08:00","gmt_modified":"2026-04-23T15:22:23.498034+08:00"},{"id":"beb87ab5aad9532647e9dbd2db7ef587","path":"frontend/components/ui/tabs.tsx","filename":"tabs.tsx","gmt_create":"2026-04-23T15:22:23.498711+08:00","gmt_modified":"2026-04-23T15:22:23.498711+08:00"},{"id":"792b8e2c16c9ff2095d83b8972313be4","path":"frontend/components/ui/label.tsx","filename":"label.tsx","gmt_create":"2026-04-23T15:22:23.499031+08:00","gmt_modified":"2026-04-23T15:22:23.499031+08:00"},{"id":"546e01c5f73aaf5140eee922f4b9a441","path":"frontend/components/providers.tsx","filename":"providers.tsx","gmt_create":"2026-04-23T15:22:23.499298+08:00","gmt_modified":"2026-04-23T15:22:23.499298+08:00"},{"id":"e68ad5186f1e47610ab3d9f14a794393","path":"backend/app/workers/platforms/tongyi.py","filename":"tongyi.py","gmt_create":"2026-04-23T20:31:36.476814+08:00","gmt_modified":"2026-04-23T20:31:36.476814+08:00"},{"id":"404f6d0765a8c6e77e33b7fc21b377a4","path":"backend/app/workers/platforms/doubao.py","filename":"doubao.py","gmt_create":"2026-04-23T20:31:36.477414+08:00","gmt_modified":"2026-04-23T20:31:36.477414+08:00"},{"id":"303e80519e946904d1cb3ac32cbb0814","path":"backend/app/workers/platforms/qingyan.py","filename":"qingyan.py","gmt_create":"2026-04-23T20:31:36.477731+08:00","gmt_modified":"2026-04-23T20:31:36.477731+08:00"},{"id":"5af7301fe056fc3d10820d820e8ad777","path":"backend/app/workers/platforms/tiangong.py","filename":"tiangong.py","gmt_create":"2026-04-23T20:31:36.477969+08:00","gmt_modified":"2026-04-23T20:31:36.477969+08:00"},{"id":"0e38ad5d2d3daaad08c9302df8805b15","path":"backend/app/workers/platforms/xinghuo.py","filename":"xinghuo.py","gmt_create":"2026-04-23T20:31:36.47825+08:00","gmt_modified":"2026-04-23T20:31:36.47825+08:00"},{"id":"6a63f048c16c60c5d2d57012c810ee0e","path":"backend/app/workers/platforms/search_engine.py","filename":"search_engine.py","gmt_create":"2026-04-23T20:31:36.478564+08:00","gmt_modified":"2026-04-23T20:31:36.478564+08:00"},{"id":"a26ee01cf41da3b956e1650448c156fa","path":"backend/requirements.txt","filename":"requirements.txt","gmt_create":"2026-04-23T20:31:36.48051+08:00","gmt_modified":"2026-04-23T20:31:36.48051+08:00"},{"id":"e9b52adbec3c07cf021e488dd3f99ab4","path":"backend/Dockerfile","filename":"Dockerfile","gmt_create":"2026-04-23T20:31:50.452043+08:00","gmt_modified":"2026-04-23T20:31:50.452043+08:00"},{"id":"4a56ef5fca60bc63480b457cab3832f0","path":"backend/app/workers/platforms/__init__.py","filename":"__init__.py","gmt_create":"2026-04-23T20:35:18.583102+08:00","gmt_modified":"2026-04-23T20:35:18.583102+08:00"},{"id":"36dd0ad3ee6bc75a480ad8a62268e80e","path":"backend/app/workers/models/query.py","filename":"query.py","gmt_create":"2026-04-23T20:35:18.58383+08:00","gmt_modified":"2026-04-23T20:35:18.58383+08:00"},{"id":"a680d4819f5da57fe9fa0e6bc708f380","path":"backend/alembic/env.py","filename":"env.py","gmt_create":"2026-04-23T20:35:45.568869+08:00","gmt_modified":"2026-04-23T20:35:45.56887+08:00"},{"id":"f6e6948dd0cdd3894bd9928b21feb979","path":"backend/alembic/versions/b2c4d6e8fa10_add_confidence_match_type_to_citation_records.py","filename":"b2c4d6e8fa10_add_confidence_match_type_to_citation_records.py","gmt_create":"2026-04-23T20:35:45.569946+08:00","gmt_modified":"2026-04-23T20:35:45.569946+08:00"},{"id":"50f2e6bdc4a79e69bd43ea8d6fec67fe","path":"backend/alembic.ini","filename":"alembic.ini","gmt_create":"2026-04-23T20:35:45.570621+08:00","gmt_modified":"2026-04-23T20:35:45.570621+08:00"},{"id":"fc6242433ae9506bcc0bf4cb0dce1413","path":"docker-compose.yml","filename":"docker-compose.yml","gmt_create":"2026-04-23T20:35:45.574312+08:00","gmt_modified":"2026-04-23T20:35:45.574314+08:00"},{"id":"5e414f2ef9b69e55e00ab15f85b9291a","path":"frontend/Dockerfile","filename":"Dockerfile","gmt_create":"2026-04-23T21:00:59.630269+08:00","gmt_modified":"2026-04-23T21:00:59.630269+08:00"},{"id":"fb8af100a06778e1fbdac4790a3ed0a9","path":"frontend/tsconfig.json","filename":"tsconfig.json","gmt_create":"2026-04-23T21:00:59.630887+08:00","gmt_modified":"2026-04-23T21:00:59.630888+08:00"},{"id":"4d9b59c294a0aac5e300b3de715eb226","path":"frontend/.eslintrc.json","filename":".eslintrc.json","gmt_create":"2026-04-23T21:00:59.631396+08:00","gmt_modified":"2026-04-23T21:00:59.631396+08:00"},{"id":"48a560c49d2b21da327c036ec2934b96","path":"README.md","filename":"README.md","gmt_create":"2026-04-23T21:00:59.633061+08:00","gmt_modified":"2026-04-23T21:00:59.633061+08:00"},{"id":"ed630a36e81abafd12787d4095dfe8c2","path":"backend/README.md","filename":"README.md","gmt_create":"2026-04-24T10:58:35.330288+08:00","gmt_modified":"2026-04-24T10:58:35.330289+08:00"},{"id":"1cafc02d1d722feb4692dab6ae85c09f","path":"frontend/README.md","filename":"README.md","gmt_create":"2026-04-24T10:58:35.331593+08:00","gmt_modified":"2026-04-24T10:58:35.331593+08:00"},{"id":"d2c1984414de6856ed5b3873c661b712","path":"frontend/lib/auth.ts","filename":"auth.ts","gmt_create":"2026-04-24T10:58:35.334476+08:00","gmt_modified":"2026-04-24T10:58:35.334477+08:00"},{"id":"f26740f2a1532b38c816663a4f665dbf","path":"backend/app/api/admin.py","filename":"admin.py","gmt_create":"2026-04-24T10:58:51.055493+08:00","gmt_modified":"2026-04-24T10:58:51.055493+08:00"},{"id":"5386144bf3c668c6fa14481c0d85a214","path":"backend/app/api/subscriptions.py","filename":"subscriptions.py","gmt_create":"2026-04-24T10:58:51.055792+08:00","gmt_modified":"2026-04-24T10:58:51.055792+08:00"},{"id":"b44632a0f399b2fe2b4daf295a120ec7","path":"backend/app/middleware/logging_middleware.py","filename":"logging_middleware.py","gmt_create":"2026-04-24T10:58:51.05617+08:00","gmt_modified":"2026-04-24T10:58:51.056171+08:00"},{"id":"5883a8ef4fc156d76b71ffdb5ecdf232","path":"backend/app/middleware/rate_limit.py","filename":"rate_limit.py","gmt_create":"2026-04-24T10:58:51.056416+08:00","gmt_modified":"2026-04-24T10:58:51.056416+08:00"},{"id":"5013cbe89f1c6f03533eb218400cedb0","path":"backend/app/schemas/subscription.py","filename":"subscription.py","gmt_create":"2026-04-24T10:58:51.056765+08:00","gmt_modified":"2026-04-24T10:58:51.056765+08:00"},{"id":"3809c5ab912511e0e093ba02a4fc918f","path":"backend/app/services/admin.py","filename":"admin.py","gmt_create":"2026-04-24T10:58:51.058083+08:00","gmt_modified":"2026-04-24T10:58:51.058083+08:00"},{"id":"b250fc6c32106a7f3e0c3ad152dfc097","path":"backend/app/services/subscription.py","filename":"subscription.py","gmt_create":"2026-04-24T10:58:51.058233+08:00","gmt_modified":"2026-04-24T10:58:51.058233+08:00"},{"id":"b0cb6810919f64006be7aa66b2b76a61","path":"backend/alembic/versions/c3d5e7f9ab12_add_user_management_fields.py","filename":"c3d5e7f9ab12_add_user_management_fields.py","gmt_create":"2026-04-24T10:59:38.893705+08:00","gmt_modified":"2026-04-24T10:59:38.893705+08:00"},{"id":"955e1dfe57f0a9a8e900383eb7641ba1","path":"frontend/next.config.mjs","filename":"next.config.mjs","gmt_create":"2026-04-24T11:01:58.061252+08:00","gmt_modified":"2026-04-24T11:01:58.061252+08:00"},{"id":"5800a08224424ebced854d06365f6d44","path":"frontend/app/(auth","filename":"(auth","gmt_create":"2026-04-24T11:01:58.062019+08:00","gmt_modified":"2026-04-24T11:01:58.062019+08:00"},{"id":"b1d80d63eae8fd5e1bdfeee3c6bc9594","path":"frontend/types/next-auth.d.ts","filename":"next-auth.d.ts","gmt_create":"2026-04-24T11:01:58.062472+08:00","gmt_modified":"2026-04-24T11:01:58.062472+08:00"},{"id":"facea1f00ec72e00f774d0839fee7131","path":"#wiki#main#wiki#zh/[app/api/auth/[...nextauth]/route.ts](file:/frontend/app/api/auth/[...nextauth]/route.ts)","filename":"route.ts)","gmt_create":"2026-04-24T11:01:58.064844+08:00","gmt_modified":"2026-04-24T11:01:58.064845+08:00"},{"id":"37d7291b1373216dcf08f081a94ab1c8","path":"#wiki#main#wiki#zh/[frontend/app/api/auth/[...nextauth]/route.ts](file:/frontend/app/api/auth/[...nextauth]/route.ts)","filename":"route.ts)","gmt_create":"2026-04-24T11:02:17.54199+08:00","gmt_modified":"2026-04-24T11:02:17.54199+08:00"},{"id":"1eb698126da2b6c95924e3ca32115e3a","path":"tests/test_content_agents.py","filename":"test_content_agents.py","gmt_create":"2026-05-23T15:16:36.136354+08:00","gmt_modified":"2026-05-23T15:16:36.136354+08:00"},{"id":"ff5699698ead454bb1137030cf21c533","path":"tests/test_llm_provider.py","filename":"test_llm_provider.py","gmt_create":"2026-05-23T15:16:36.136596+08:00","gmt_modified":"2026-05-23T15:16:36.136596+08:00"},{"id":"a8bfbe8f5db65abf625c19edc3999a97","path":"tests/test_pipeline_engine.py","filename":"test_pipeline_engine.py","gmt_create":"2026-05-23T15:16:36.136778+08:00","gmt_modified":"2026-05-23T15:16:36.136779+08:00"},{"id":"0bfe423695374ece56313bb55e9d3e86","path":"tests/test_platform_rules.py","filename":"test_platform_rules.py","gmt_create":"2026-05-23T15:16:36.136934+08:00","gmt_modified":"2026-05-23T15:16:36.136934+08:00"},{"id":"bbcb3a67f564dd7c05d3f8684c9bf8c6","path":"tests/test_prompt_template.py","filename":"test_prompt_template.py","gmt_create":"2026-05-23T15:16:36.137095+08:00","gmt_modified":"2026-05-23T15:16:36.137095+08:00"},{"id":"2aab65d07faab01583455277d363742f","path":"tests/test_rag_service.py","filename":"test_rag_service.py","gmt_create":"2026-05-23T15:16:36.137516+08:00","gmt_modified":"2026-05-23T15:16:36.137516+08:00"},{"id":"af7c8d3b4ba659f1bd8c4989b5ed7a62","path":"backend/tests/test_integration/test_full_flow.py","filename":"test_full_flow.py","gmt_create":"2026-05-23T15:16:36.138034+08:00","gmt_modified":"2026-05-23T15:16:36.138034+08:00"},{"id":"13b8f594e7cace5c8a9255dc801dcad8","path":"backend/app/agent_framework/agents/content_generator_agent.py","filename":"content_generator_agent.py","gmt_create":"2026-05-23T15:16:36.140513+08:00","gmt_modified":"2026-05-23T15:16:36.140513+08:00"},{"id":"750f8d79d83ee910e9d18e8a4fe37e22","path":"backend/app/agent_framework/agents/deai_agent.py","filename":"deai_agent.py","gmt_create":"2026-05-23T15:16:36.1407+08:00","gmt_modified":"2026-05-23T15:16:36.1407+08:00"},{"id":"7f8c6e94ead45ad9bab8cea9a7be2123","path":"backend/app/agent_framework/agents/geo_optimizer_agent.py","filename":"geo_optimizer_agent.py","gmt_create":"2026-05-23T15:16:36.140854+08:00","gmt_modified":"2026-05-23T15:16:36.140854+08:00"},{"id":"609a02c9e1ccc0311885a70578b86386","path":"backend/app/agent_framework/pipeline/engine.py","filename":"engine.py","gmt_create":"2026-05-23T15:16:36.141011+08:00","gmt_modified":"2026-05-23T15:16:36.141011+08:00"},{"id":"43642bd7bedabd97ff2f0a902b783e4e","path":"backend/app/agent_framework/pipeline/loader.py","filename":"loader.py","gmt_create":"2026-05-23T15:16:36.141161+08:00","gmt_modified":"2026-05-23T15:16:36.141161+08:00"},{"id":"1de27749fbccdfaf785545657f58d256","path":"backend/app/services/llm/factory.py","filename":"factory.py","gmt_create":"2026-05-23T15:16:36.141304+08:00","gmt_modified":"2026-05-23T15:16:36.141304+08:00"},{"id":"6a9387dd3885cf4d27bce3db87fd61c7","path":"backend/app/api/agents.py","filename":"agents.py","gmt_create":"2026-05-23T15:17:24.081191+08:00","gmt_modified":"2026-05-23T15:17:24.081192+08:00"},{"id":"9af41884bf42d6e175163e89f663a479","path":"backend/app/api/analytics.py","filename":"analytics.py","gmt_create":"2026-05-23T15:17:24.081515+08:00","gmt_modified":"2026-05-23T15:17:24.081515+08:00"},{"id":"9c224bb80474867f8ded674babaa6e11","path":"backend/app/api/lifecycle.py","filename":"lifecycle.py","gmt_create":"2026-05-23T15:17:24.081772+08:00","gmt_modified":"2026-05-23T15:17:24.081772+08:00"},{"id":"63953ee6b39f159a61963104ac06f283","path":"backend/app/api/knowledge.py","filename":"knowledge.py","gmt_create":"2026-05-23T15:17:24.082157+08:00","gmt_modified":"2026-05-23T15:17:24.082157+08:00"},{"id":"6940047dd4c29a8a219b1b50e358f7c1","path":"backend/app/schemas/analytics.py","filename":"analytics.py","gmt_create":"2026-05-23T15:17:24.084817+08:00","gmt_modified":"2026-05-23T15:17:24.084817+08:00"},{"id":"952c887faf6f91370b174bd4e1ad6e00","path":"backend/app/schemas/lifecycle.py","filename":"lifecycle.py","gmt_create":"2026-05-23T15:17:24.085312+08:00","gmt_modified":"2026-05-23T15:17:24.085312+08:00"},{"id":"ed4505205a22ba55c7d4a83b0b24eaa4","path":"backend/app/schemas/knowledge.py","filename":"knowledge.py","gmt_create":"2026-05-23T15:17:24.085541+08:00","gmt_modified":"2026-05-23T15:17:24.085541+08:00"},{"id":"a0c569cd2355079f9f4045a198ddcadc","path":"backend/app/services/analytics/insights.py","filename":"insights.py","gmt_create":"2026-05-23T15:17:24.087528+08:00","gmt_modified":"2026-05-23T15:17:24.087528+08:00"},{"id":"984d67382822ff587452a79f89e0d336","path":"backend/app/services/analytics/tracker.py","filename":"tracker.py","gmt_create":"2026-05-23T15:17:24.087949+08:00","gmt_modified":"2026-05-23T15:17:24.087949+08:00"},{"id":"45c9d96513947cae445aaaf8b58b4266","path":"backend/app/services/knowledge/rag_service.py","filename":"rag_service.py","gmt_create":"2026-05-23T15:17:24.088178+08:00","gmt_modified":"2026-05-23T15:17:24.088178+08:00"},{"id":"3b13f3fa9b6316b23cfd01d740a85b81","path":"backend/app/services/knowledge/chunker.py","filename":"chunker.py","gmt_create":"2026-05-23T15:17:24.088359+08:00","gmt_modified":"2026-05-23T15:17:24.088359+08:00"},{"id":"aaa9ce5fdaad8eaa6887e8c079e0b7af","path":"backend/app/services/knowledge/embedder.py","filename":"embedder.py","gmt_create":"2026-05-23T15:17:24.088522+08:00","gmt_modified":"2026-05-23T15:17:24.088522+08:00"},{"id":"000702af850583bb79fec57f7fd1fcca","path":"backend/app/services/knowledge/retriever.py","filename":"retriever.py","gmt_create":"2026-05-23T15:17:24.088674+08:00","gmt_modified":"2026-05-23T15:17:24.088674+08:00"},{"id":"aa6cf63a65ebf46a29606af91112eb7b","path":"backend/app/models/agent.py","filename":"agent.py","gmt_create":"2026-05-23T15:17:24.090372+08:00","gmt_modified":"2026-05-23T15:17:24.090373+08:00"},{"id":"97cfe961cb7386b4022a51706ae8f5dd","path":"backend/app/models/lifecycle.py","filename":"lifecycle.py","gmt_create":"2026-05-23T15:17:24.090637+08:00","gmt_modified":"2026-05-23T15:17:24.090638+08:00"},{"id":"4774aadaa8ace576601bdaa8d3e11f74","path":"backend/app/models/knowledge.py","filename":"knowledge.py","gmt_create":"2026-05-23T15:17:24.090925+08:00","gmt_modified":"2026-05-23T15:17:24.090925+08:00"},{"id":"3a1e34b542590c287768482d964dc7d5","path":"docs/03-development/coding-standards.md","filename":"coding-standards.md","gmt_create":"2026-05-23T15:18:41.055279+08:00","gmt_modified":"2026-05-23T15:18:41.055279+08:00"},{"id":"53d01851ef76ade6cb41a3cbe140676f","path":"docs/03-development/dev-guide.md","filename":"dev-guide.md","gmt_create":"2026-05-23T15:18:41.055638+08:00","gmt_modified":"2026-05-23T15:18:41.055638+08:00"},{"id":"21e6700955fa049df458cee6020cf073","path":"docs/05-deployment/deployment-guide.md","filename":"deployment-guide.md","gmt_create":"2026-05-23T15:18:41.055945+08:00","gmt_modified":"2026-05-23T15:18:41.055945+08:00"},{"id":"b0db309ae449a2a435fc77103ca76955","path":"docs/04-testing/test-strategy.md","filename":"test-strategy.md","gmt_create":"2026-05-23T15:18:41.056328+08:00","gmt_modified":"2026-05-23T15:18:41.056328+08:00"},{"id":"974abe01413cc7a8a4898621e0b0779e","path":"docs/03-development/tdd-workflow.md","filename":"tdd-workflow.md","gmt_create":"2026-05-23T15:18:41.056789+08:00","gmt_modified":"2026-05-23T15:18:41.056789+08:00"},{"id":"01a3a8e0d02ddfa2e64837790ba231fa","path":"docs/00-project/tech-stack.md","filename":"tech-stack.md","gmt_create":"2026-05-23T15:18:41.057096+08:00","gmt_modified":"2026-05-23T15:18:41.057096+08:00"},{"id":"68688ca664c7df5d64153200455dd7f6","path":"backend/app/models/analytics.py","filename":"analytics.py","gmt_create":"2026-05-23T15:19:23.472665+08:00","gmt_modified":"2026-05-23T15:19:23.472665+08:00"},{"id":"9bad7097cce919cde648d435f673bac1","path":"backend/app/models/alert.py","filename":"alert.py","gmt_create":"2026-05-23T15:19:23.472906+08:00","gmt_modified":"2026-05-23T15:19:23.472906+08:00"},{"id":"daab5d62bc9559915da6c4bd52dcec91","path":"backend/alembic/versions/d4f6g8h0ab23_add_geo_lifecycle_tables.py","filename":"d4f6g8h0ab23_add_geo_lifecycle_tables.py","gmt_create":"2026-05-23T15:19:23.474868+08:00","gmt_modified":"2026-05-23T15:19:23.474868+08:00"},{"id":"22a884dd0b02fa904cd2808646d4aeca","path":"backend/alembic/versions/e5f7a9b1cd34_add_alerts_and_alert_settings_tables.py","filename":"e5f7a9b1cd34_add_alerts_and_alert_settings_tables.py","gmt_create":"2026-05-23T15:19:23.476036+08:00","gmt_modified":"2026-05-23T15:19:23.476036+08:00"},{"id":"e029becbf7babac61765f6a1790e1d48","path":"backend/alembic/versions/e5f7g9h1cd45_add_knowledge_base_tables.py","filename":"e5f7g9h1cd45_add_knowledge_base_tables.py","gmt_create":"2026-05-23T15:19:23.476457+08:00","gmt_modified":"2026-05-23T15:19:23.476457+08:00"},{"id":"0c2c0c0ef594628c812c0adda8b914ea","path":"backend/alembic/versions/f6g8h0i2de56_add_analytics_tables.py","filename":"f6g8h0i2de56_add_analytics_tables.py","gmt_create":"2026-05-23T15:19:23.477615+08:00","gmt_modified":"2026-05-23T15:19:23.477615+08:00"},{"id":"80f3f2a6213e0002803247e1c51233be","path":"backend/app/api/alerts.py","filename":"alerts.py","gmt_create":"2026-05-23T15:19:23.481478+08:00","gmt_modified":"2026-05-23T15:19:23.481478+08:00"},{"id":"9ea18740e615a926960e829e8c583175","path":"frontend/playwright.config.ts","filename":"playwright.config.ts","gmt_create":"2026-05-23T15:22:58.299607+08:00","gmt_modified":"2026-05-23T15:22:58.299607+08:00"},{"id":"6f639c813a6c2a20c0c05939222f7475","path":"frontend/e2e/tests/dashboard-health.spec.ts","filename":"dashboard-health.spec.ts","gmt_create":"2026-05-23T15:22:58.299977+08:00","gmt_modified":"2026-05-23T15:22:58.299977+08:00"},{"id":"a3a308292fda7895bf49445c417df345","path":"frontend/e2e/tests/login.spec.ts","filename":"login.spec.ts","gmt_create":"2026-05-23T15:22:58.300354+08:00","gmt_modified":"2026-05-23T15:22:58.300354+08:00"},{"id":"4edcf9364f826cf2a7b686447777cc07","path":"frontend/e2e/pages/dashboard.page.ts","filename":"dashboard.page.ts","gmt_create":"2026-05-23T15:22:58.300735+08:00","gmt_modified":"2026-05-23T15:22:58.300736+08:00"},{"id":"f6784e54bb91b7daa9c76653ba1b2c75","path":"frontend/e2e/pages/login.page.ts","filename":"login.page.ts","gmt_create":"2026-05-23T15:22:58.30103+08:00","gmt_modified":"2026-05-23T15:22:58.30103+08:00"},{"id":"1fa69729b52f34bc96b687a395501734","path":"frontend/components/business/index.ts","filename":"index.ts","gmt_create":"2026-05-23T15:22:58.301363+08:00","gmt_modified":"2026-05-23T15:22:58.301363+08:00"},{"id":"ebcf5e1a8abb3ccc9196e5749461f46b","path":"frontend/components/business/agent-status-card.tsx","filename":"agent-status-card.tsx","gmt_create":"2026-05-23T15:22:58.301788+08:00","gmt_modified":"2026-05-23T15:22:58.301789+08:00"},{"id":"0da5aaee978edabdfebab3a8e67d803f","path":"frontend/components/business/alert-card.tsx","filename":"alert-card.tsx","gmt_create":"2026-05-23T15:22:58.302198+08:00","gmt_modified":"2026-05-23T15:22:58.302198+08:00"},{"id":"0130bb8ebb0800faff59f36c5625b7f7","path":"frontend/components/dashboard/index.ts","filename":"index.ts","gmt_create":"2026-05-23T15:22:58.302547+08:00","gmt_modified":"2026-05-23T15:22:58.302547+08:00"},{"id":"d9f509d2a91b503397e98066751ead0c","path":"backend/app/agent_framework/agents/__init__.py","filename":"__init__.py","gmt_create":"2026-05-23T15:23:21.347893+08:00","gmt_modified":"2026-05-23T15:23:21.347894+08:00"},{"id":"58a2f69ec5607ac5e4ab93266534ac01","path":"backend/app/agent_framework/agents/citation_detector.py","filename":"citation_detector.py","gmt_create":"2026-05-23T15:23:21.349766+08:00","gmt_modified":"2026-05-23T15:23:21.349766+08:00"},{"id":"fcde401daccbe6de50f3829f021ecf55","path":"backend/app/agent_framework/dispatcher.py","filename":"dispatcher.py","gmt_create":"2026-05-23T15:23:21.355483+08:00","gmt_modified":"2026-05-23T15:23:21.355483+08:00"},{"id":"5b011956f30d4ac51420444cca8c7f08","path":"backend/workers/scheduler.py","filename":"scheduler.py","gmt_create":"2026-05-23T15:23:21.360698+08:00","gmt_modified":"2026-05-23T15:23:21.360699+08:00"},{"id":"4d4403d720ed0580f3ed57503b584eff","path":"backend/workers/citation_engine.py","filename":"citation_engine.py","gmt_create":"2026-05-23T15:23:21.36113+08:00","gmt_modified":"2026-05-23T15:23:21.36113+08:00"},{"id":"8aa6b45626f9eb93a3f4fbf1d3206a38","path":"backend/workers/platforms/base.py","filename":"base.py","gmt_create":"2026-05-23T15:23:21.362039+08:00","gmt_modified":"2026-05-23T15:23:21.36204+08:00"},{"id":"21ab29cd896c5703dfa3461a055c0f54","path":"frontend/lib/api/lifecycle.ts","filename":"lifecycle.ts","gmt_create":"2026-05-23T15:23:21.375132+08:00","gmt_modified":"2026-05-23T15:23:21.375132+08:00"},{"id":"ca1e69e3279cea977bb7f660d417b4d8","path":"backend/app/workers/llm_adapter.py","filename":"llm_adapter.py","gmt_create":"2026-05-23T15:24:01.680615+08:00","gmt_modified":"2026-05-23T15:24:01.680616+08:00"},{"id":"249d68c4ba50c523b617a8c82e7afdae","path":"backend/app/agent_framework/base.py","filename":"base.py","gmt_create":"2026-05-23T15:24:01.681072+08:00","gmt_modified":"2026-05-23T15:24:01.681072+08:00"},{"id":"5d2b9655ba99a14a3accb1878bb5681a","path":"backend/app/agent_framework/registry.py","filename":"registry.py","gmt_create":"2026-05-23T15:24:01.682376+08:00","gmt_modified":"2026-05-23T15:24:01.682376+08:00"},{"id":"022c381f121cc2a65834024ca2c9b8c1","path":"backend/app/agent_framework/pipeline/schema.py","filename":"schema.py","gmt_create":"2026-05-23T15:24:01.684475+08:00","gmt_modified":"2026-05-23T15:24:01.684475+08:00"},{"id":"3a2a43dd94c9405ea91934c43cdecced","path":"backend/app/agent_framework/protocol.py","filename":"protocol.py","gmt_create":"2026-05-23T15:24:01.685073+08:00","gmt_modified":"2026-05-23T15:24:01.685073+08:00"},{"id":"fffc152ed28771e8a42e5bb2e33650cd","path":"backend/pipelines/content_production.yaml","filename":"content_production.yaml","gmt_create":"2026-05-23T15:24:01.688276+08:00","gmt_modified":"2026-05-23T15:24:01.688276+08:00"},{"id":"856c9e5eddcb40682e653dbd1a4bfc4b","path":"backend/pipelines/diagnosis.yaml","filename":"diagnosis.yaml","gmt_create":"2026-05-23T15:24:01.688961+08:00","gmt_modified":"2026-05-23T15:24:01.688961+08:00"},{"id":"aa21995469cad3e13897d5dbe268533f","path":"frontend/lib/api/agents.ts","filename":"agents.ts","gmt_create":"2026-05-23T15:26:09.814653+08:00","gmt_modified":"2026-05-23T15:26:09.814654+08:00"},{"id":"6b50314c917457b8b70ade390573c3cb","path":"backend/app/agent_framework/config_manager.py","filename":"config_manager.py","gmt_create":"2026-05-23T15:26:09.824114+08:00","gmt_modified":"2026-05-23T15:26:09.824114+08:00"},{"id":"c2036406c4a0ae8b1e671ef1f1601826","path":".env.example","filename":".env.example","gmt_create":"2026-05-23T15:26:09.827338+08:00","gmt_modified":"2026-05-23T15:26:09.827339+08:00"}],"wiki_catalogs":[{"id":"1bb55e12-24c4-42cb-8f59-ddc303460d45","repo_id":"1095f823-f6f5-4e66-9aad-9f0b5b6b99d1","name":"项目概述","description":"project-overview","prompt":"为GEO项目创建全面的项目概述内容。详细介绍GEO平台的核心目标、主要功能特性和技术架构。解释项目作为智能学术查询与引用管理系统的设计理念,包括多AI平台集成、定时查询任务调度、数据可视化展示等核心功能。说明前后端技术栈的选择原因和整体架构设计思路。提供项目背景、应用场景和价值主张。包含系统边界、核心组件关系图和数据流向说明。面向初学者提供概念性理解,同时为经验丰富的开发者提供技术决策的背景信息。","progress_status":"completed","dependent_files":"backend/README.md,frontend/README.md,backend/app/main.py,backend/app/config.py,docker-compose.yml,README.md","gmt_create":"2026-04-22T18:56:47.080895+08:00","gmt_modified":"2026-04-24T10:58:35.431076+08:00","raw_data":"WikiEncrypted:nzQO5jvliy8ncyK0FT40s3j/+jLrEduTcrc/mlxpgSLdYjBwtNztvkbMoPPMFNEMDes7QSOWotr7g4sRG3hN1QC5esoYS3BvN6Y/T/6GOvnwo5Ww+L13yRESwkAhTxZ0bDtqMqBMDJjp0MKl68qbq7B2U5OjVB5vyO1G7qlX+bY4a+E+zpn1E17PQvN9P7VlQgVDqa1nwz8U0c4YkUjlvSLoRXqMUPWbTTo8enr8varFiB9kZhlIveqWyQg70c2so+mmgK5tu58aGpglpVdjphh9cbkx8+rqqdDcytUZT7S8pKc4MGkZe3rCbq6nyT0QAyu8WwZ0h9/zER3M3mecpY0QwlpWFcQiEekYeGeusO+eNSbtIN9Tohtik8zfV/pV0TaGc/LbnkcMtj8m0T83c8wKIfYs/liR225bzfnhLIqsoF6rOnXNLIoTpE8Z6Ks8+5swWOqw0Oa1WUgNMnH79HbG7z2uBctEg3Kb/3wmXweL49APkVOhhX9rJu18yc8nR26giaoFIlCpKme7nOHGBbxVcV8/JH1uRvSJLspnk9+gwQcK6n07+/KN5SIq/dFPZUVljWill5+4lQiNxtX+bZcGsWdNjyiate8dGLZoiydoxbt8zaaOQ/sE/vzpNhUqORGkQ8zSh8rLkJEdzSYUCb95gUWs+6vCBogO7GSPqHQcoYZi5WnndLvZiktMpSEJFxGL8OBQQmyD6Z6bOiznhTf01DdqjQOJBP1sIfkt1trL9OQOr20Ak7fnYetRoaFaSlNhpQQ/hgidyWqYv/uEjDqbh6r8sMdfkOJfWVQwoTFcSfwD2/Ezujp/A0M27lE6NNRroam4tql49iIRkSJ8j5Mqpc4aSg/1LGSCtGFO7lgwS9gOqERvjimyvLJqWq3dZ0cOYXDKpKLA0X7nDR9XyX2YWJS4KaXUr5+S2sxJzO7sAlTKSz6PH6BQ/b2JlcDCx+56VN8QMP+RCcbydnghzXKe6RgzxbAnDpW0JuxjjZ4MX8K34hI8qs2i0yxuU9+Mf/FjPgDApnz61m6zpE7ytZaS5gDZPTG3wIPktdrLMdemyyufsG9Lw++TxZ0idt/BkMk5EUrehRV+xT+AOX78k10N+lSt8JqDE3IeHtwqfFd0is91jzyBsgYPlipjXY6xSsJlNTYZ8aU/1mQMFLZvcMTTF703Kx6yRYTe1s9QIB3LdfeaNqDov7ouvZRgU5fNwWTcIt9sUTJn5/2mwjZpBmntggvmpmp5wC7dpNB6kBNb8jJrmRLMepO0ocqPbXE6JhTb8/yOhegEy3fJ1RNTeTZIEpBt4+sCZtc5TA3aJSYPZ51wEGmqMbiVCl1DnxLKmBc0O0JH97VCXcyhIKj4aOGsfQbqM3cyeIWuRNds3/do3Z8vOc9AQfcOnwFZU1H3df4iLKZ9pDyMVGCNqEeKew=="},{"id":"7c3e3c0b-5d1f-4d64-99be-668041c6cd9d","repo_id":"1095f823-f6f5-4e66-9aad-9f0b5b6b99d1","name":"核心框架配置","description":"core-framework","prompt":"为GEO后端核心框架创建详细的配置文档。深入解释FastAPI应用实例的初始化过程,包括应用名称、版本管理和生命周期管理。详细说明CORS中间件配置、路由注册机制和健康检查端点。文档化配置管理系统的实现,包括环境变量读取、配置验证和默认值设置。解释数据库连接池配置、异步会话管理和连接超时设置。包含应用启动和关闭流程的详细说明,以及资源清理机制。提供配置最佳实践和常见问题解决方案。","parent_id":"7c2ac186-ec90-400a-ac1d-b3b7ca2f01d5","progress_status":"completed","dependent_files":"backend/app/main.py,backend/app/config.py,backend/app/database.py","gmt_create":"2026-04-22T18:57:02.316945+08:00","gmt_modified":"2026-04-22T19:03:21.69307+08:00","raw_data":"WikiEncrypted:luoNp8LvFa7zGThvIT9T4rhp6COPRJpm3tT/kftARqFq4dg1cG/8M10NcCrCelp/LC8SV6McSk0Sx9xEgJV/YmEmjfMmlukALh9v7ZKLxT8XDDYkBCrff2Ia9KfGFRdlfVmmQUGfhQARTeykGZh6O8/4GECBHUYLS0F6NXI7fSS3R+/I5c/HIjI7F17mVNpZDQZcc2HmM4zhdyIinOGyErSf3vIPcfVVobPB4D/wCUvMWxl+jpvktykHTIgH9ze7f4fTCC02xK5vRnt1RlMdAQ3d1Km7OOGjAga30OGvRdp9UtT48gdhzPQH5FEbfzn7K6TnuPzqQRf4GuS2kVTRSUFbSnmj5d5HqHmgx7D9iQYR/XxRRVbv+GeFwINvVa+UX9cnanYU19zazOGWG2rcdDk8jqu5MwAhVZsT28hykyuLfKeTf7xuM6Li86T1mZ18SROCJHe4LXYEaH94K6CHjZLCyEl10xBk02/CkW4aTW29TIgrponrmnrvV6bShQ+ZitR1TcivPsNN5t6TCaHMnlaLlOpznSGNpMyf4S51cRPxl2cwZrqJbrdFxehIoPrUyOvtRvtEsLhpo30456ihrInvbVXgJMwZIcDaKHSu0Bf7ma8y+UCWH61+VBIqW44KzA9zmKcXU9hiiwL+gjwiNcV7JDcgg43Un4qvjEzeJiBRBMGGzc8Oc05dWgRs1K6QUdS1kZTjI/JKiGS8zFYKz0mvQqLwc6/xe1/MDhMyU1QUXSqpcNNU6aFmY7te5kENN2aSPZqigqID+RwvIV8k8JETdmHaxJUzCSrNEpbpUukFuVQKz419athf4kMeQH2fKsLMZABn10WnnmY9HGGqBx+gpNOTU9AiSz1l4b0Ej8XoQcwIn1lqw49qdJ6+PRuuFBv6OcjxgJSMNSQzm4c/eyl7yv6J4vXceT7Ul+ySMAGRnSpDUehmOuw1DT4dV0n05Rcrx5gBjuztOAexxUhLwMUK/v+8qdn/0OcciISCZ/U1GhzhWFYiVKRBfNuNkuRjwmc4zg5Zc97TPRBXYs2q2e0/3cT+Dr7lqeGnXWL3X4iTjTygXMekhDQBjc0NbF6cdDOJcPAUnOg6jDkreBiEkTJ7hZg3J9ho2RYDaHuPvyMlkW4YWTpGRODtXIs4aLG0KFbNr6uOG31hOPZsgnHmoNwcPwRUO4G89Nkl2M6ZTMiNHWtsSwES+gLmCLPunm7R2zQNtdei+K3lzSg0bQgUvg==","layer_level":1},{"id":"bcaa04da-04e3-427f-ba01-847ad657e78a","repo_id":"1095f823-f6f5-4e66-9aad-9f0b5b6b99d1","name":"Next.js应用配置","description":"nextjs-app-config","prompt":"创建Next.js 14应用配置的详细文档。说明App Router的页面组织结构,包括路由规则、嵌套路由和页面布局设计。文档化全局样式配置、字体系统和主题定制。解释Tailwind CSS的配置选项、自定义样式和响应式设计原则。说明TypeScript配置、类型定义和开发工具设置。包含性能优化配置、构建优化和生产环境部署设置。提供配置最佳实践和常见问题解决方案。","parent_id":"d907a8eb-795c-4060-9cdd-50d31cf39be3","progress_status":"completed","dependent_files":"frontend/app/layout.tsx,frontend/app/globals.css,frontend/next.config.mjs,frontend/tailwind.config.ts,frontend/tsconfig.json","gmt_create":"2026-04-22T18:57:04.216045+08:00","gmt_modified":"2026-04-22T19:04:47.361369+08:00","raw_data":"WikiEncrypted:MoQ9U2rERvJfHcC2U9f5yo5PrhAUeAY0OH9kgPk99cOGQSyTenUDM+krr5XcMxqj+FSA7CYnuq8hz8eS8Pvzc8yZuRRHbRPExvPpdrOEr8fRtUXkjnECv8NVvFPloo2fonxY9Q2vmL0x2O1UsV1O6L6tkraG28x1o504hsBitow5XMWkk8uSk+sDbyHo/y9/SBDWpcEOXVqeU4nwD/UU+7N90n5i5T89nz6b4M+31tkvffIuZRigZ+1+IJqlsqFgRt9PNrxL9ZUsD2D/Yvh8EJ0sCr9z7AI+D3z+JYM2kgFT/3ugS/EnEzwByGZk/e2EsOY4D+NkRBas836JX++o61ZH5GPQBXTHnVa8h5B1LAVlbA5zBuJHHY3V2XS4X1cTo9Hj76mg9Ha+jWvX2A9fv4vnscE6cVxnM+WjWnSfN8N7Vtla2YRDrNXZRAL50+PNfhUKpb48d0hKFyzf1Av1T4WBKgaYEo2znphEy99ViuG+oOFS6D5pVQ/w5yoPe5MpZCDk4aNsO/owrJkILcGc3+qHfld4Yd4HtYM6madWmmOvHIIuCy5CPGojBzKDcTTSPP6ZjuY1EC/RG3lBkYCQtQj889+80GZpaSbrqWjTmMI1DX1KLNXJkoI3dFk5Tx+w4TqiKICJ8q9KJhOX+mEVk+ECXqrc2Qz787D34zY5UlwsaA44ziBvWDZuwfPWmtelAq4KjqfWTFWYqdY6D0fUvetLh3/VEqH/o5Nh4HrlGvy/faZbU9FKOBZPkAy8c0J24rW5p2pKmRq6+2IicNTgufRROtiY87GKfbfmqpDYBEn3Dogv/Q3i5beVavuD1tJWhRsewhAZAUi1jWdiK3LyS0QI7dMFXVJw3cm2FnegeXA8CNlWnjUVSOY/OfLFqJJqYrfcj57f3nAU4a88w4h10+iFBLh0yZkX50llRxgUjV0fnjyEFUDoinC1xDA9ip9IOosTI+avZPhLTC0Yn4ZGnJi4NCD5cD88+KIdRUnVZJ5Sqf4ZcCCQamtYBT8NJ+PlByYxpqJpGtLyV9BuexYC86YnD3PJau0oXazcytuXMYh/TTaEo89ZzW4jpsqDM1G/gBUq7R+QDzLElNZfw3Ov0E0+Pvfm89W+v2iSsJ2JI2Yq7wrml7FiTN0KoP5KVEBCEzDLwebnJFqa7GBaghwADYcgoZ2VX2Xtin82a3oqlX2WNfur2DIr4YURiSmE8g8O","layer_level":1},{"id":"9e3d703f-f424-47f4-84df-b99873b93e5a","repo_id":"1095f823-f6f5-4e66-9aad-9f0b5b6b99d1","name":"项目介绍","description":"project-introduction","prompt":"为GEO项目创建详细的项目介绍内容。解释GEO平台作为智能学术查询与引用管理系统的核心使命和价值主张。详细描述项目解决的实际问题,包括传统学术研究中品牌引用检测的痛点、多平台数据整合的需求等。说明项目的目标用户群体和应用场景,如研究人员、市场分析师、品牌监测团队等。介绍项目的发展历程、设计理念和创新点。提供系统的功能概览,包括智能引用检测、多AI平台集成、定时查询调度等核心能力。面向初学者解释项目的基本概念和使用价值,为后续技术文档奠定基础。","parent_id":"1bb55e12-24c4-42cb-8f59-ddc303460d45","progress_status":"completed","dependent_files":"backend/app/main.py,backend/app/config.py,README.md","gmt_create":"2026-04-22T18:57:13.329466+08:00","gmt_modified":"2026-04-22T19:05:00.376007+08:00","raw_data":"WikiEncrypted:0MI1/XkBoMl0lTbK6t0CnyIiRc/FeBluVaO5vMjpi7GJDj6RYPJBK8z3pvJGG/q2Umz028dfdXdKirGdHRY2lrn0erk9nv1ZHCzuughhzuFHwcxdCPIpZdrZtQpPh6bsxkWiwYzSScq7WGo0sBeTvyoiisiPXNkFNbSjUGQOu0M9zOwZAcknYWqtf16nUcOV3lRfAFHfNSt77Nc0IUQGl1zM4BWFjitEsa6cq/jjGIh7XC2gcTvm2eWRaWDDr5n6IcJZtD0ODJYzhH9IJVk4uIXlKksbQcuIrmEWEkZBxeh+DAIp0tmgXr52zuL9uRxapFuSlOq3BlU5N3I+Iu8Fg/rBAnNcvKEwSk/71gIbFlwaxLvik5gposBrfcD4U1+MJLRTPhgg/HJwljnpTC13NERk70aJg2/SCvFZcO+86xWuLwvNjWRxc2K8yOeJggfWG6S/Dt0dGaFl5F44u6XDbQV0GKiDfNOzo5CtzO7CrkSRJ+zErGQOEEoF6UhVmmpA6ONf2YDr/z3Z5bIP5z605qNZZWUDPVLjU5elINOMi4fsEw3OYaerNp6aoSHA1eXnOJoJIMsU0KM3eGAO9QNhHE2PlkwXulCEX5l1tkohbwthcv94cBVsn64CtaMMgjrgUkflNYnfEM1djmP2iJFEG/MjNMntZCrVRGXdjjqR4Q+lRe3ELhXuHjqeU5RS+KdYLASsYBDzti2T8foSfBxxXcpMIz/lS8+Qx3pTLW3ktH5AaEtSdclWCF2HLc1/03O/gdv070KOck/8TXbyZsJ6g3fzThY7xASttVsW1IITTaX9XE52YkNOe7KOrjJwkSbUgOU1Rv3Aa7x3VJ/ac9nDL4AgS+TlYNxfYBlGkbesL+sqDgWrL268y38MyK0DRqEQVjCxV9+7aAkxLvaUXVMYIwxqAM9Id66zRb0pJB3uwgpOAIRzOCskNEghjp17p4BK3lgehkRcM9RAGb7WqgeNfl/+ox2b25Pj+nvbWN3XghNZwNzoTW+kBZxXhOTRvIyAne7IPRpmtD1XD6ZBx/C6ucQ7kTUL/7LqFXE66g3Zey3hiaiQihueSMCFVer6F+BIMSBpV+9cmAczdqYvXRnKIjQg15zwVGz7mKE4D7caiDjkAQeMUSqziw+i/S26Ont/JBHIsLpYISQJErTAl2rGwC+7ADw+H6jg0rn+nE5s5u9fxUPMsWodcWi5oGIFRRTyGeIZYSTNveEwN8h0LGwXhUlHR6RxBAIpbiwKVUcOFOKc7mojhJEN36mXsQdRyCUjV3YdNzj2Tw5tG4exPzStsjDxSn98XK42QisGde126iI=","layer_level":1},{"id":"a06436ee-1678-4a51-bbf8-b0d0ac3456b9","repo_id":"1095f823-f6f5-4e66-9aad-9f0b5b6b99d1","name":"数据库架构","description":"database-architecture","prompt":"创建GEO项目数据库架构文档。详细说明基于PostgreSQL的异步数据库连接配置,包括SQLAlchemy异步引擎设置、连接池管理和会话生命周期。文档化数据库连接字符串配置、环境变量管理和安全考虑。解释异步数据库操作的优势、性能特点和最佳实践。包含数据库连接监控、错误处理和故障恢复机制。提供生产环境配置建议和性能调优指南。","parent_id":"243a1a45-d31f-405e-a3b9-694d2fe617d5","progress_status":"completed","dependent_files":"backend/app/database.py,backend/app/config.py,backend/alembic.ini","gmt_create":"2026-04-22T18:57:14.160162+08:00","gmt_modified":"2026-04-22T19:05:13.623934+08:00","raw_data":"WikiEncrypted:veTYwq2y4io5qXerCTrkkJxdCaPVm76qYvPs0DmFrBYr++cWSoBpsZCop64XjnmZv6vHv8URIJAqohtlaw1HFotKc3mK0aD3tk5jmFWmTjGEd9iSTEcB45Yccg7p5eggZzqexWRLP1afxRQPau2t5uy1dZIlExyu+lyiNQI9/hXf1UppgfCjo4u6akBIZtYhzgcUSoYY4jCjv0naBAT/PyevZQctOpKPIBwMdeB86h71UT0hKB1hXxbyQoljBYZmATJaRjmlQzZf/Ka1gnDj1s1WVsGMpSoA7jyNRPH+Ra6hR+5N8Ba5vkjxM/HcRFq282Jnr/TnidF4MF5HpD5Piye73QZ3zAvIbu8+iOSvpQee/FTzkrUQBy0xOA5lsfFOy5OFOKtQh0mHybuNqe6H5squ2Tge+K4+RKXbDCt0wptrSV+BVQ+OkAJJEtLNRpJElsQ5bw1UU6CuzbgnnEYrMXB5TMBI5N2/J6hmlqt978t04N3zVI9JnnFKK0H2og6TVu1Hrxq/xEB8RFWTf/WNN1p4Akee5r1uOuUry6hsO2yQUTlmHq74QnJz4o4YJodWkhwAmcyzPIlMeSFg/Kr/EvsQJN4UprhudCTvNitnPaBesVkucYDYQiVAhxyNSAqCzZUYXbyuLD4r5DKxKzvHjkhRugm73yBM7wzbxB2lABMiGM9p90FASIxS0SfzIl4qrFbO/oQGRIFaYfUCnQF8h0YDi40UX4/LVmnlT/L8y/d+hU00P5j5PI0qOyoRDqsfQZFaze+qtibkMnJ//iy0Awl0wqQ47SxaB0jhTc07lPFBLSHFSoVUaKDs1DPGiwKjpWZRzAw7rbv9NFuV+irKc0l8qDNCaK6Rk0rRd0ukFuszcaE9n92URbvv0Fk8XTHLr8sFAh/xMm63r5hUAuqEYN6z/Si5Isq52UmJ1/TvnLYIUK58JHTuDsVn3MKJ2fTgUw/U3g+N61WpDIgGvaHO75crgWZbS9qQyDoSSj4wNdxWR+wtmKjwZdRK44kWRBS1QebMTLNYDBgHD5hPnmOa5W/Rx4Y0QBw6UFjCy/GOmDI=","layer_level":1},{"id":"7fea5a24-e6de-4003-bc70-9dae6d8fdb25","repo_id":"1095f823-f6f5-4e66-9aad-9f0b5b6b99d1","name":"适配器架构设计","description":"adapter-architecture","prompt":"创建适配器架构设计的详细文档。详细解释BasePlatformAdapter抽象基类的设计理念和实现细节,包括平台名称、平台URL等核心属性的定义。说明抽象方法query()的设计目的和参数规范,以及close()方法的资源清理机制。文档化适配器模式在AI平台集成中的应用价值,包括如何通过统一接口实现不同平台的无缝切换。提供适配器扩展的最佳实践和代码示例,帮助开发者理解如何为新平台创建适配器。","parent_id":"7e66719b-4a8a-484d-889d-10fdc76788bb","progress_status":"completed","dependent_files":"backend/app/workers/platforms/base.py","gmt_create":"2026-04-22T18:57:14.592407+08:00","gmt_modified":"2026-04-22T19:06:14.01609+08:00","raw_data":"WikiEncrypted:mEeeU1uNqYKn4jkG2zPtuGBVTFJMKL8+aALSFPkyoEYifQL2Z+klmgmPGyzF3YlP0xw/C/hG8jzgXcVjqaWbA8lOQYPPvd4qFK8fszqAYs/fYEHXvWBVaOTbFhjNiT5k+li1MqVRx7SiaRze/N6NV4j39o5dfNAouxnCXgLyBZdG5QXj6JAfhJ1mTHsYQFDmrIU+nOtrQvRh3bruUOURVd64c13kwbBISJKHVwByRrfqWLRTsCLXPYfsgZF4rkL+Iz9x27Nl0VXvNcIIoMXj9B7hg2PPcQlmup4U8y2LhUHmKrdiKpW1t+XZ8rpO2aPKpzr47rn+3n2axWoQIDjWKlHAwi5AhxgPysB/i5EGv0pvgo/mNNIfsZlmSYgXASM6bgCzH5W4O4oJVqOi+gaLuI5+i7N8/+s+FKb63H9ZNvwClw5jXJe2Xm1YUwVGLG8KX5beKRTmBgnyDPmOW17/OXwsWMWQSQKrgpiv+2C7VQqI8X/agBVWawLJAc8VloY281S3ZH5LTa/6ajeGUVXiwpWSD/YWzo9sxLdws1ZXCInzLYy5vX7YflgBOlw+pn6Z901TBktq5jxrG3CFTbRLGxaeG1aJ06sLEFoPzLSXIIiEIuAROC6lPr6XpYAKESgWGOG0GdM3BinxdkriGn21ZZjENIJ436aZjsOiE5M20/kJAnjWIBPEJ/sv3nsi7u5iLfYFvkus4GfnKXJyto9LWiTgqrwHoEUQy4+pnVW+ce//iLlM/t0ZknimuBfzgYSWx/jPc8o9ZU5OIserDAYGaE4sDZIDQas1jOq8HGN/q4wJR7sW7Fw1jKyl4suQZE6QSfYx6molnJ1cSVKcsGrf7AHDKM5x+uGRmLWXqMMUZXXtbbCw0mwqfxAUPiRLUdVyzot8dh/NIWX6B1KABd/kKs+L+vVuCmMen1XVfP72Uy91fYOkBj/xPkA6GYrempnrB6zh6INdvGw5dEKlvNARMnZZLCA64Xw4h2TBjbkIjsBawvJtT+wEGkfkPk5z99jbaaGS65e/JDF/g5WNnKSX0B1Xo+frM1AFwnKR4dIJXZ8=","layer_level":1},{"id":"78288302-33bd-44f7-8b29-24f516c8b6bb","repo_id":"1095f823-f6f5-4e66-9aad-9f0b5b6b99d1","name":"调度器设计","description":"scheduler-design","prompt":"创建调度器设计的详细文档。解释基于APScheduler的AsyncIOScheduler架构选择和配置,包括调度器初始化、触发器设置和任务注册机制。详细说明调度器的核心组件,包括QueryScheduler类的设计模式、事件循环管理和异步任务包装。文档化调度器的启动和关闭流程,包括资源清理和优雅停机机制。提供调度器配置参数、性能调优选项和扩展方法。包含实际代码示例展示调度器的使用模式和最佳实践。","parent_id":"7416db23-312f-478d-8883-2fc3c41ac2e8","progress_status":"completed","dependent_files":"backend/app/workers/scheduler.py","gmt_create":"2026-04-22T18:57:25.383156+08:00","gmt_modified":"2026-04-23T20:33:30.132403+08:00","raw_data":"WikiEncrypted:z5m818jdZZHs9QqQTrTafQ5BuN3hUq8ojqzL8SUBUvazzYVUu4EVEqQ8I56QCaxYSTvxoxfSrvjJk5zRU5X7dcnw4Xa3OBhn3OLehoT3E+tyMxhlJSbJpOfp1afGCLyH7k587Ud4I355IvboUvSoBViL1WL1yQq+6Tus1CsKPq1yHjNiWT35OfV9g7bRu5xE+1nSxjPu58jZpFKuN1x9oqF5OJmckHxf5sVFqKlGPU2yyeGdpzKRagbQGUkBdw72yxzSyevTXJ4y+UPCQLh2FLZ8RgYP0OD705z2xIGb7KSeQocLcW5FoxR79ySiibc+AmzE0OBKZqbcm/aw8K5lAK1GP31LdhjrndMTmXrsf9CYBNRIir1QOJsuCh6zPtpsvQVmrX7DpqXiWsaqnK2GVOkKPtnYAJnGsEQhaoX24/64eSYeSnJ7KIsQxP0MHUrRG85VVGF2ADUGh6L8qzexe7uE+lnaqgC8HBQ7CnQ3Ugnj5hcO7vnwQl67NHMOQ5yaL1SpfURVWAx3jjUBU4xjHfmUNcBC2VM6ie9C6Ulelai8Pg0+gFL0A+pfN/Mkzzh05wcgnmFbWfjabZ4Ofv/w+UlG5qhMsEJQAgag4tXHgP/86pheTsfyefYhWEkow983vJf6mYl4lgRaFHeOZ/JBTmM0sxmg1PMZ8wgClMSC0a9SKcsAyWOh0yMuBn/Ckhx4HqGoPAP1rx/k9TkBiHFEoEAXeTNoeg/Wn7tVimdgZvAjW79z7lbcRV1cvlKMSjhRyO2s6n6N3Z6xTlKtLrqHBbXZcrjNQqJVgW91Xk78+a1haDNngswufhJkTJcH8hp3hSUCJeU/Cpx3RYRRf7E3bGmj4sV/+yXAybUvCOhs1s89mYVFThdpDifMbvN5C8a9xrjKJNfjzijlVZwx+cGy5aj+ZQFSDCRCBHvCCIBd76w8uxi+VR8VhbsIryP2KUNpudqIY4V56Jx3DB+dznNJMasPFZZ2ZttlKIAV7oqWrreoweIqeEIugrIM4TdE4EWmokDP5wr0tBdyerPnkaCgJLQj3X2K/xjY6ony3F4svfG1pk2jd5JwTLnudwS4dnGY/1b//vEDGI668cQtR5fW7+APXXb8qjOLlzM4Enze4mw=","layer_level":1},{"id":"b027f234-4ac5-4d6d-9b38-afc8054325f5","repo_id":"1095f823-f6f5-4e66-9aad-9f0b5b6b99d1","name":"单元测试","description":"unit-testing","prompt":"创建GEO项目单元测试的详细文档。说明各个模块的单元测试实现,包括认证模块测试、引用引擎测试、查询处理测试和引用数据测试的具体用例设计。文档化测试夹具的使用方法,包括mock_user、auth_token、auth_headers等测试辅助对象的创建和配置。详细说明测试断言的编写方法和测试覆盖率要求。提供具体的测试代码示例,展示如何测试异步函数、依赖注入和错误处理。包含测试数据准备和清理的最佳实践。","parent_id":"fc6f24c3-594e-4153-854f-19250834eeb1","progress_status":"completed","dependent_files":"tests/test_auth.py,tests/test_citation_engine.py,tests/test_citations.py,tests/test_queries.py","gmt_create":"2026-04-22T18:57:25.616384+08:00","gmt_modified":"2026-04-22T19:06:55.090058+08:00","raw_data":"WikiEncrypted:oQ7VNoYBl3ApU4O5/TGa/YEO9ObmRNw6knddpSF6M+qfBokxpt9FAn5Oh9wXkjVweu6TpLk0XawcRFRcQ09Zi+YnQyN8+4Ep9fANKzHyAxzcnhkI4VZF35j3DwTbhekUFTKQ+71fms4SP6LGrVw+8IP/eqJC2TH96LJR1oxckQk//yfvKqFHsMLgziXy6zrXuQO8PIu5U/WbkKUkJHWSkLkoTtPteU+WKljSMapCS60e0RUDWZEPuFD2uupr2PJxT8AoOXx358C9XEj8tQ+OwHpsBiR7NdmO0D3GmcgVUcuU7WWxnToWu1UM1d/t4u+x7bIQvHQIDjLWR40nTrvBZJBSSiui0he3T03jLkIB7r9kxCpm9mFUx0fkmUSWp7FRfs7MfJkuoQYVU0YHf6/FF6g/PoQ8ieyqr4YaNjM3kk8GirHkmKjfdQt9YmQtuzMWnzUQ6COtN+BG3STyOvO+12YQAYi5LWe7u7oP4D7TJRReg7FeLDQ60Y8KEoKBJKM051F7pgHlorthWz42brF5tF7oa0tjB4AtWaEwXdCvH278kzwHNEW9E5zeERzX3hlHYL+mKpTbemJlfuHuRugCRy4EKFRP0RYiIUecBK82Pi4Vi9MGjB7cQxIEutHQ/3D0JNLGwEo5TCsk4W3isoF+mJDFy6/IDwgW/+5FIo7V/G18dTg9YbFRwMecdvBfJU5QZV4R993bdx+kH6qB5IoJrA0AzBOCn99YQ/xgAd3w/82Z5vR8syeNZjHYmcx8P/XrYDk4UZTwaacEHfn7tcq+tL5qJDbxdY95wjaWRo9giFE8woDfoLWstvKA1/q+YOyDsIHC/uHjNP1L0ELPZ9ssFuHcwLVrqDwlcblya4+oXlPEOH2ar22uXNRmFyd8Mf8MmEWVZklodBHSKiGUlj8eSWqtR+Cw5Am1gmeUcOxqan5YwzpyXet6g5ll12dnu6ItLby6qm+kjET3rsjaJag7UBlMXWV9xn9Vj4QDK8USPTTWkRUEAj4WH9QqECQzUtYJ6+GsIE7LGx/5tzApMdX3BThIiG8C2k5ry3z310nAMX/pTSrGFGjy8tWFf+KH95sJ6aG4CDyxSPHT/3ivhXAnKDesNYTVgSIKNmAUcj5hRjTfJeGyljB7NEs6Gxz0tf5k+GQLwvRX6PxSnMGkm+q0yx0MNDRBYJNlPCFKUR74ZAU=","layer_level":1},{"id":"940e5918-1689-4001-a284-44f2de75b8ee","repo_id":"1095f823-f6f5-4e66-9aad-9f0b5b6b99d1","name":"认证接口","description":"authentication-api","prompt":"创建认证系统的完整API文档。详细记录用户注册接口(/api/v1/auth/register)的请求参数、响应格式和错误处理。说明用户登录接口(/api/v1/auth/login)的JWT令牌生成机制、认证流程和安全考虑。文档化用户信息接口(/api/v1/auth/me)的权限验证和当前用户获取功能。包含完整的请求示例、响应示例、状态码说明和常见错误处理。提供认证中间件的使用指南和最佳实践。","parent_id":"dd12cc44-0c95-45d5-a726-e7b8bcf2531b","progress_status":"completed","dependent_files":"backend/app/api/auth.py,backend/app/schemas/auth.py,backend/app/services/auth.py","gmt_create":"2026-04-22T18:57:37.836287+08:00","gmt_modified":"2026-04-22T19:07:12.356456+08:00","raw_data":"WikiEncrypted:uxAckj1IXK2TQH//kEdeBPmScopsydAsQUjZb8Fs6jI7ezX3WnM5wMv74LMiw55tL2+YKxETbMgwkBQYqIg1VTja5IjBYqljlAzD5l6SrkKU835vZQoOKlYgIFEEXj5PMURu9+2Om7SDVgjbSQ05vLa2aVIBV6PiVswRGc5EGTGtYnV+DJs4BxHzYpH0Ac7KkyHUCGgH6w5QDaOxWt6c5gftFmsRwr8WVKANmqlNU9uhDjmWzjTtSqZ39EVbLd++OjVbpLbTtijQ6gOF0KBBS4B0N5k+Xm2/gDv+HNK9kZ0BphZE1Si3NfV0+cu27HLJ2XV9w357rte4pplU0wYG5oC6cuO7eBFxQdCR6e+ejXIvKGahQOce8d/jWexjfdWnUzvQ18PU4+bUZmiP+YD1dJVBFgxggbCIHG8VFTQBqMaYwc3NLWogjXnczII+Z3sLLneLkVAQEdQ381GeRKdaD4PrtAWp1Ss2QpGHWUKDdaNSLcfm5NXEe6GeECxXH96p6BvyegD3twPfZmY9WKG8YOhXqbpzae/+DXnUTfldYKnMfbonSav0nUBYt8JA0L3oceaNs03211fvlSgE8L9vtUDtNF5lHkhOLMLbu000pe/VWc8WVQRbCKd8KPd4TUxMkB61vQNIcvlRKLMJLNSnE1VftRTpdEpWKhm5qkLfOfikgsp2qp1iSw5Idpu/TLQPIGN/sYpTJ1eACeXt/A3qrlITHFV8by4utTXDT1gRQQ7j7n51fQHHEIbpU+6CRhSBBQfa5IlWAqkarenBmr5RY74jeX7tlhDhvFojQGHYyMaDsZO8G/H93/20YG/li4iihHLIYmsN+2YRP/KWCNaopBGp7tRyZi//RKVXdHGteWxP7vse7URwPhfmHDUB6dMExCT5PwgsYoDwD32k19Eauv4c6OogAMMUN3I9rhSo3V0cde7/xSOhJ34SUY3w9VpPAu1I4zTqhY649YmBnNEjtGLZGTnEJWSdneSPsudvl1HJKg6faq1dMy0dVkMqbHaqMCooFDhiYVS1AM1cG07y9rQisvQP8Ic3NTPAA7BhH0nrPnLc615Jg+XEAjs3brkNXEVZlxNvX5ZqMCoMqsiZrA==","layer_level":1},{"id":"6406f42a-e10b-4a2b-84a5-0a21c1c759ea","repo_id":"1095f823-f6f5-4e66-9aad-9f0b5b6b99d1","name":"代码规范","description":"code-standards","prompt":"创建GEO项目的代码规范文档。详细说明Python代码风格指南,包括PEP8标准、命名约定、导入顺序和注释规范。文档化TypeScript/JavaScript代码规范,包括类型定义、接口设计、模块组织和错误处理模式。说明前后端代码风格差异和一致性要求。提供具体的代码示例展示正确和错误的编码方式。包含自动化代码检查工具的配置和使用方法。","parent_id":"2148d7d6-25c4-497f-8894-c4eb7a0d2bd7","progress_status":"completed","dependent_files":"backend/requirements.txt,frontend/tsconfig.json,frontend/.eslintrc.json,backend/app/__init__.py","gmt_create":"2026-04-22T18:57:39.373374+08:00","gmt_modified":"2026-04-22T19:07:51.274139+08:00","raw_data":"WikiEncrypted:Gw00+yNdsAXvNpUHE0sZ2+QbHW33I6XBnIRt1QjI/FW/5OIgpgiMvU/f+bhXrxoZK5Mgo6YrGuAKhtZ2BPutU1EdQeDFUnQQxxqSupe1WUkFgEECvCkbZOAHimRWBeUutq2qKCfVhu1+US1y8n87OZXUUvVSAksZOa8lbb2AHyiKTMdzzPThS0D+8uOalkBg1mvJCS9fqVoZzY5BYYpuH5eZJBglHbA4uMbdFVTSKVFfHaJ8nlm6uYjaY0sJCSg+dhEAIiMfOTXP5Bh59kxWfLSdZU6b8oPvLV0btsiS22/oEJZI4rWjJ0YTxfQ4jRv348P+GQ6oi1pvwveiJyOxLq8QcVKSiDxO55Ovd76PhOgpOp2WJcUsKoKBoxs817utm+Ld0htpPBS3V90Rw+suMSPCU0mCa80FTrBNn6PnXemH7lH1ozQIu3Y/AGNYBN93acBxtiZ09sGFh2sO9mbbCU0iRuNe9nwWa4MsA5rJMLGdRbyv6jk03+sAvuKwZHXyTWxqeXvMatOUKXzTNfmhXsE+Bexe1vaukG22SWhsXu7FhIaH4Rt7CdpMW0jjbZOf4CwKY36ucVBRwft6ymuED4ihzikPz7pJ5IEuxLGtCyt5QDqT7kbv5ITx4NM/Q2IMMTRZf9bAZyN64PV2TJVCNK11yU+cE7y8HFBNFSzPfDBGFmxijKjTL9MvlElogPp0+qckxGclnip/IOFc6/WAbPNK0qXq98Jq5DsZwLsx4//8yOyRyaQGmOVaOWxb3Aum4RIf933X/hzoTFpV2uSLSznRyCwLpKqjp2zMS7lCj9aDhWLcx5J9NxXfdxFVxBsapMeDDl5xR5nfTFJcOFylsdPxEdxf5J8ULB77F3OmE8Hff/40adNMxJHMyBmju99HNnMZkGLjC68HEPNMZ/6T0+m/Sq1yHOrakYMiw6vnQvmLW4cBIhsTFbhbgpkazGFTk8xsKH3pGySrLXL4xmadfs/g2X/lRrLbSonWaQehTqHYrhz4HIxrTUDn4kdxaPPDhH4fHdEu/69Dri0DSzmSF2m8W3hh1gbAbUO/mbHob1eJg0yKGzyh8AmvUlwXIRGrOwQA5dUZNPSo+oCcv1qlrQ==","layer_level":1},{"id":"e8ec6ac6-ad1a-4332-a7be-727b47d71233","repo_id":"1095f823-f6f5-4e66-9aad-9f0b5b6b99d1","name":"Docker容器化部署","description":"docker-containerization","prompt":"创建GEO项目Docker容器化部署的详细文档。说明Docker Compose配置文件的结构和各个服务的配置参数,包括数据库(PostgreSQL)、Redis缓存、后端(FastAPI)和前端(Next.js)服务的容器设置。详细解释容器间的依赖关系、网络配置和数据卷挂载。文档化Dockerfile的构建过程,包括多阶段构建策略、依赖安装和运行时配置。提供完整的容器编排流程,从镜像构建到服务启动的完整步骤。包含环境变量配置、健康检查设置和故障排查方法。","parent_id":"803bfef4-3985-477e-a61c-915a246d0061","progress_status":"completed","dependent_files":"docker-compose.yml,backend/Dockerfile,frontend/Dockerfile,.env","gmt_create":"2026-04-22T18:57:40.354835+08:00","gmt_modified":"2026-04-22T19:08:34.084609+08:00","raw_data":"WikiEncrypted:h7ADvj4WLJHyulzCl+z7kNgZWY+r5P000yRKX1NQnlv1Xv3Dqgu5Ve8V72HxPVQrbKK8WU/ipQ1PAqV6SDrNgrc1Neea6KoTKr95imYAh3dYgIt/lZ1sndBbQCFqOF87dQsUIEKQgwrsicAeQ0zdudUWh6EW2nyIF0NGa50xffbgEr1mm/MThBZjOua+YnCRogCbgtirEO/6HGlC+I33w/bfFI+rREYKdumqUEia0kUP0pWSpwWjOQp06I7cUoSrx/LuJJ4in5YsZetdjzxdbA3ZvGMjeyI/VVF6UC/QUOgE2csP9z42v6XdOOngM/coBHI3DiUrroBGTPa6BVxJdngItCJ9XcNvXPbo0xMAkAoUKnNPA72B2pRuk4F1sTiOaSCQ1jaMiCTFvbj7+VleaodRFLDFsYa8f1w2FkiW7cEBhFpFgB7Qfru+Yi11rpkjnM2def+Sqq2PSHQ+Ji83jPoQXFl935rDQbNUy28wOIE3BdWN5jjM3nyoXcqKjPVjLf3cxGvg/sbdWk1FYPMIsbK/DUWayyTHt6L/fYkDQYjY5h0H6Q0jBxlhNQ34GG8kEcvrZ6Dy/jtCtE149pi/ToeMbpPq21c5KUhs9OHcEHgMjxWMaEVjQXMjFCpKyJIPfC984tfoZhAHi9WupzyEi37/igcgVJnvIdtadpX7uRxW2JCdfoHn1H87nGQj4eAeI3kMhtJ3EIPd/D6STxUcgtyLdTIZu9kgvnBIN4OyZeI1ygNZfawwQMmbDxHZ1pPcyZDHFlz1HZ0NFX+7VnN2b25TJP2hxMCZ/5OdYeSLozIbM/azA8QMHofESSdxDX9ZDdhvENDlngxUBmxM8+yCAWHENGYqWDL0gZMMDwe89n48Xy9qnKNLX0ROfG4FAtoXsEgLlPQM3AWFETnzr7Kvuma+8sY1iaMVIXJ/MWoy1zLwuY/oOZhVqGLX+DOEupKhk1oQmiqzciCeV8my5Q6LQeriSBww4jA3r6VQMPzBVzKJYz+TLizB6Esf//9+ilsgUVUc6GjD41Ml4fb1GZO3PzxGWrcX1RUE6RKllUBVNffxzE2WCirEX4e4YprntsHu6SAb9TLIInCx7aZnlVnaDQE5BCiHLjIQJnsHHJzlBm+8jtzE4zi7ljHLfbJwhtZ9W6S9KGUqjjNryjTVnVyYQlumOT8HCAkz3fSM6MpXwQr1qz/gHyDrQanmM1O9B/0ox5O2NWcOm5qtsteiyxwKACdyxrsUx0X9BaU8xygDL75XcTfcaOTcICRwaRZF3/UQW+zhbJo9LnHxq30JzTbxU7wEdjpWZQHZ+tu5BMrIqi4=","layer_level":1},{"id":"a91fff3d-ec5e-43df-8176-22f0084109ef","repo_id":"1095f823-f6f5-4e66-9aad-9f0b5b6b99d1","name":"功能扩展","description":"feature-extension","prompt":"创建GEO项目功能扩展的详细文档。说明如何新增API接口,包括后端路由添加、数据模型扩展和业务逻辑实现的具体步骤。详细介绍前端页面扩展方法,包括Next.js页面路由添加、组件开发和状态管理集成。文档化引用检测引擎的扩展机制,包括新品牌匹配策略添加和竞争品牌识别算法的实现。提供UI组件库的扩展指南,包括新组件开发、样式定制和响应式设计。包含完整的代码示例和最佳实践建议。","parent_id":"b2bb2e3c-5661-497c-97dd-15bf6ee8b7d4","progress_status":"completed","dependent_files":"backend/app/api/,frontend/app/(dashboard)/,backend/app/workers/citation_engine.py,frontend/components/ui/","gmt_create":"2026-04-22T18:57:48.684421+08:00","gmt_modified":"2026-04-22T19:08:25.140739+08:00","raw_data":"WikiEncrypted:5RlNBsIi2/3o8ATlHuzaYD9/6k0SjLB2nW/cTN9Sp7ydYLe7mauzXPQFm5pYVoY1D1K/aULghB4g32vyxSUIsHV6NsxwYA/5+FQ8w/4xsQc3urcx9OEKeSC0hGU52WXucdAGjiEq/f4wJ2c9FdJEeALD6eX7MltcooFsxAVRWIKzHsMdBiy0RQN6s7vv4sb8vpV3b1ET27D9QlTUiTPU7RgtJLMui8iYiwJIirfL1TgdGRSx0Rr3tY/JvS3/6/L6VU/69BKglW8DnLwDkWKuthI/2sfWQa+lb+uTuixXL/VbltWQnzwjMVYghhTizEEC0xTpFGcDY/ajvLcjy5+wSleNEr9AFy/ytJKkpqEO8Zt5qyVJ4eANJMSXYcoKrZEskjVpnrPEHGdOzaEaCqcl2sQYkXde8LWM29fWmwlMjwJzucGwhudoQLXgkIwJnD+jb1r2SdjjafTI76MM53AnSfD4aj8K26yrOkVtoD6nWG1A1fG6F22pPBhJdezNJCYuKBaSDxJDES5486L5Gm5RvjYDq4r6RZ5CheGPgxl29XjCimgWuxXKVX0jPLUawteo/Vo5D7AHzucx2dX4mKr4rSSSHpD4HGdbwnxZ717DkRG01vTOnue6gSQ7pceMjSZ6TnB7dvtwwarHBKQMKwJXrpqxc83aZQjW4sRTAJs2Gc9+11c7qT9fQnGK54JJjEARaQZVaDmTpKmme4SKKxCB7V8yUqR+D+swVuSjIpYdL1m7THJtbWSSLaKkWmYiom1C6qb4GIgO4CT/IiFSyQ0Sz8MUIJi/dK0l/vVmpp5p3IF5K1m6NHDX94yEPWEHsWIS8eC2B74AyX6PG1fWSt7HpiBAzq8nu8n+IrXPqDege5sXbjfNrbvkRot94AvLF2aqMbteOUGOZxMLASQYyfRQBlaEEFMiKEVNTRSaHqiS8mS3pG6XLcV7TkWJIyMzhcT93hKXrSB2+jLa/rrxxrZwfp6lddgEcV+XZzQU3KsJf8blNUd+UkA4TcwFugu0um1Kr6Hro8EHAR34+FGMbPskEPPX2yd42YXx6qfmcFrI1xvHIQfnc7QuxZwO6GHR0G5LiPtuV4ZSxklXCwgnGWy1lpC13xANNvM1UKqAuhpuV2qU+xayK5IQv7kQaDOJpnMzFj/dSxtRgL2Xm20nH4BA2lhBCQMqeM5OxJ5vzwVlgVMZxDbhwrRaDU6cudgNfRJDFh2lGQqE2flEkvSF7g87Hc5H3qDQxUv56qpdOPJcgugKJtT3Jz4dNt3+eojvEwrTUc7d2Kq4KDTFUa5jDr5uo9PZhNR2TDJazpNIdl1x/64=","layer_level":1},{"id":"e3ae8925-4862-4280-b85a-0b376841b15e","repo_id":"1095f823-f6f5-4e66-9aad-9f0b5b6b99d1","name":"快速开始","description":"getting-started","prompt":"创建GEO项目的快速开始指南。提供详细的环境要求、依赖安装步骤和本地开发环境配置说明。包含Docker容器化部署的完整流程,从环境准备到应用启动的每一步操作。提供基本的使用示例,包括用户注册登录、创建查询任务、查看引用数据等核心功能演示。说明开发环境的调试方法和常见问题解决方案。确保新开发者能够在最短时间内成功运行项目并理解基本使用流程。","order":1,"progress_status":"completed","dependent_files":"docker-compose.yml,backend/requirements.txt,frontend/package.json,.env.example","gmt_create":"2026-04-22T18:56:47.081987+08:00","gmt_modified":"2026-04-22T18:58:54.237875+08:00","raw_data":"WikiEncrypted:qfgbutC7oyxR6nMxrwk1ODnNMBEQ3/sG78fQT1yXWju83LC7H/jAM8CEAvWT8huE5OClmQiIfNYNxHQ9s7RRS/GGSwI5DTgXTPiPdxvdU9tU52Y4wj4FfVrOtqmH0nMPa+EBKH1Wo4HibSewimTkeCuJVAAjyygiPePcftR4ud09LKmopy1NSgZrtHMoDFDwUOcNJQad4OVgxMnOi6B6z6s2Oh2aPWNJX5EvE5xGkLAc6XvhE2T7MU40VJ4lUOoKlCNZNdI06grEqwyizBqt13Hg20wonqeQ1uPs49UbF84IJecH3DmE6KW3oqmqvQY6tztk79eE1bKZmBtQKXz8WhEMWZwALTsVk+hkk4dH/fcDoLteR1iuO4FaxDwAOaD71KF79AaYxDZiM/8RER9YsajjGSI+sfpJALuiQbqqfKbYFSgliiUcf4gTM20Ey5rtfBkcvBY6yOBPpqdKg7/ls7jdggNEWDJfN+DPVzV4SGAYRD4g/kDzPa5vaNZ6USRa7hVIR0SJufX0DGSdzX5BMh5DQEEyd9svxV+bs4KPZphBIeqAOzvo6zyF9l9LjPPdEook/uTIBHjGgx+8Ck1NQEeNOs61Zqr5EfISope1Au8dYCrzwpr02s4XAb/6bYsMSkfVqETlSSUkipDodGoLJU8QiYr5Pjv63Bb9Qb7SZ+i7NrGp6UJNVT0etywEMKSQn+73I8e9AYrAxlN5ST6K5b3W7cOPzFQMCVRfzvdd/FbuN30u7JXlFCnm6Ee8LDHW6nteOxBP1D6JxbrQirCQE0cSuk+d8OR5tR/DJiRDcjbsG38KVBEqWnIek8KlMGxEt6N3oq2ceUCCLe4jVURPc/2G/6gNiyVq0dPPAVwjaNKNwtiyaDhhBu4T21k9NUfhdQNz9DJWD0wXuaZc89RoqLNlCHJ6TtxEHJ/Sv4cgvm3QUierIBIqUawkCMEDn3ZEo7L2fUS4fMlzfpHSgTvxB43ta+H1m6syFUmAyh1yqfXVxKZY0f4JtmBbQpNzpT+aRHMKKQ9UVvtjvNcpupzO5aNkyclJVWis66DMtfA1H4am2gseXSfgHHtXiLfOnGoELSM1fLS+T9oPt48v+RPafJQpahtNeKtZc4dbTcsc4qlS1krenNSBbkKac4Zsosjv8xHuD1aqYvAS476XT3gjLfV7YUCF/+i3PiovD9NGzhA="},{"id":"c19260e2-5163-43d4-b35a-b48aae995f4a","repo_id":"1095f823-f6f5-4e66-9aad-9f0b5b6b99d1","name":"认证系统","description":"authentication-system","prompt":"为GEO认证系统创建全面的实现文档。详细解释用户模型设计,包括字段定义、数据类型和约束条件。文档化JWT令牌生成和验证机制,包括令牌签名算法、过期时间和刷新策略。说明用户注册流程,包括密码加密、邮箱验证和用户激活。解释登录认证过程,包括凭据验证、会话管理和权限分配。详细描述依赖注入系统在认证中的应用,包括当前用户获取和权限检查。包含安全最佳实践、令牌存储策略和会话管理。提供认证错误处理和调试指南。","parent_id":"7c2ac186-ec90-400a-ac1d-b3b7ca2f01d5","order":1,"progress_status":"completed","dependent_files":"backend/app/schemas/auth.py,backend/app/services/auth.py,backend/app/api/auth.py,frontend/app/(auth)/forgot-password/page.tsx,frontend/app/(auth)/reset-password/page.tsx,frontend/app/(auth)/verify-email/page.tsx,frontend/app/(dashboard)/dashboard/settings/page.tsx,backend/app/api/deps.py,backend/app/models/user.py","gmt_create":"2026-04-22T18:57:02.317252+08:00","gmt_modified":"2026-04-24T11:02:17.638164+08:00","raw_data":"WikiEncrypted:1O68LCvyq1zgacF3KZk5YThbR7ok3g75/gwtsJvdh2o83INCVjstQiF01tda6hFb+2JTqgZSefMRniabd6NWxIcxLGQkPzKVW/Hd8nBmAPUj7rQun7N62bOjGs7Vdy4RhltwZryBPaspbuAyl910fhwCIzZMGRfD+PXCWNv/v434hWViOvWnjpYaMrt2sX9Ljy71CYMLz0NLL55ClE3+kRm2WBxbzfWvpabmDbKCJIjHUouLtLTqa8nO2ZD/mpn8P/USYy3J+ucCQEsu8jbkFecDJgSCRkNzfeLi54eh7hIPt3cwY3k1GwBPcK28HnOkNGaLuFV5qSbDgUwDBoJ1ZTehKeXMMxAuPFJ+1q+Cushre7O1bOmgO+I80GEecYAmWGgpx7U8Xu3tI2XaqjSkfRQHdUEezEWtGlEdBOV5pTVVkz/k7SvMCf0IQSaeAV4CB0uPNlyH37JexzmbUl6SbJQzlmX5BcDo56/DmhFUZ+iz591eZevVGaIdCDU9scQfmskMZZfkf9d+T9heLb3IonhkwGtoofl1NWkyMZ4LRfpoWpOQVz5rwZczDy6DzPtcmJMGgjGoJF5qad8II9wEjnSfCikdIKBXQM/KBIZKZDvEsRH7Kf28A8nCpNpf9eKymJ9xUlUDXB7chWBw+J9WK5EQplTeI52vg2TWVsMNSe/gBLV0GDzzFNuAIAOAh+BEGM65LlZrL89p9j3rI7YORJ+qtC/f7HdtqWPMDToAOV2WH9ykII3qnNarPzMf6QbGtA9+XEJw1P3fie457QflUMrUyuW1QAW9RXj3CdpyA0XWl7v69GhCW+ABebIpbYBRusC1DkAL1U16hWKVHHgqUV4gf8Fe9Chq1RalQUnIusIyrILaH9a4GAwAAclwJrHhLdDwcGeZYBVyM2BngvsRb/O3ChVyFYnpcM8mdwPauc5jvaBBKrdeyK61TlB6N6oOmNMsnvd+MbQGK9PFBrRFUzkC0+NgBC/hMn84JKFb9bM9QByG7MpRGn3SXDA8p06GgAXdN4la5zg9hm5Zf0B4pryWfgd4FuhV3KvyBM2w4YHORaKYN9xZtxAbX+IOODdualJ0330kxPW6dvHj7fPGxFcUQQb+/tR7E2nO8orJBmwWZh0YchjYeDSg1cD1y+YJUGjn6kBo2UeP1OKt09nDiSlHMp8EuHnvFBQpBxP6HevfwlW1Fg5bwtkTOlgAmJBltJgnn2qJpcbfTminqL9HbR7qWWabkMULUXBRWUSvixoKdphNXY++/I84oDc81EJBNgQz8ZglrU2lOzuPY1D/NDPfzU2MAwNrhMKGcVz2fQj6T4Ritr4wQmQEVRTdma8ST30CO5COXFne2c+0Jtnl/ASeYQcC8/87vsgSXxLQApyJARvqN14s+M1RDKVFG095u2ZXOboEbwN9cTPaDY72E387diTUEL8SKiX2kjnHME/eldUwbnuXM0raDbPpoUSzIunVEWrB21l/8hx823tGkHNjc20MuSe7gaDnYWxj9CZI07jHTk7KM+fVncOW8XC39kS/z+F7PcJbV+22DtWJkoi4U40aX/PuLYs8oyTC6NjvAaj0mgd0QVWF2vvW2R4XGpEIyIZ4Tx+CRzKGE8X9v7ysizR/XX5nLdr42F25yZM=","layer_level":1},{"id":"9b71fe02-5927-4a19-8db8-66eb129ecd9a","repo_id":"1095f823-f6f5-4e66-9aad-9f0b5b6b99d1","name":"认证系统前端实现","description":"auth-system-frontend","prompt":"创建前端认证系统的详细实现文档。说明NextAuth.js的集成配置、会话管理和用户状态同步机制。文档化认证提供者配置、OAuth流程和JWT令牌处理。解释路由保护机制、权限验证和用户状态持久化。说明API客户端的认证头设置、请求拦截和错误处理。包含用户登录状态管理、会话过期处理和安全最佳实践。提供认证流程的调试方法和常见问题排查指南。","parent_id":"d907a8eb-795c-4060-9cdd-50d31cf39be3","order":1,"progress_status":"completed","dependent_files":"frontend/components/providers.tsx,frontend/lib/auth.ts,frontend/lib/api.ts,frontend/types/next-auth.d.ts","gmt_create":"2026-04-22T18:57:04.21635+08:00","gmt_modified":"2026-04-22T19:09:48.747579+08:00","raw_data":"WikiEncrypted:BenkIlLPgjbiADCpekIm2LnLFWkzmPKE+C+tunEqC7EVMaC4hkq7YX8EJXa9qt893SobX5KrGOKV9QEeDplCQkFx4neCRj4kZkvt/lObxAfDgMBruR7HQAasniGfUhUjW5KYXC16w7brsqCWR8CWKDQGEZiduwEsaDjAZy9TEu7PlK6Cp8RhkPZ9jhN/YjqaxTAq5i4xHmQz4VuuV2SO1LedFcTlV12iJH/vTW0vFyXgJqY/Ql6+bTZO2yMaEWan9rB7e+IsErvp40JaC2xqL7fRnfroIwQssGEvaqckwf2qyNjjNCcewd62C6FVDnxJOLjQbizlBKmbb8XVzuRLkECZVB1edGJKnDV6FkOkP9y2Al2Qtpbx/1Uhx1Lo92eRd57kA0Icc/KGcHKRjNsW0HfYWAtLctTH3fNIwtmND/J/6zKK4UdDJ8sXiTnjiU4JhX/fqW8bl4FVo8F+kJYUIhbJCQkl+qlYh/MkTCmyG8XukvSZGbvWMPUxyU1gMjDxUnyVdcJmFFt15oXI+X1CL6ukGEn1cRRDiB4yRAq2GR4/iUPUFC0d3aqeRj+ryjr6Cp8YqrHfONdwZyWd4hS8RPEP7NeRuD64yNRSDFTju1oPvBfROcmunn1GaAmw8dV6KtXSJnM9SaiqnYutX51ah9psTgX+UxTu7EU/ijnQYUnDLg26m2/bX4Rhm4MRyE/fAwzxOKEI3uIaqyun0W3lgdaF4bWTwTblet2a9rBOwbVP1xtJ5M095JzboruOAhl29fAT9iO2jeqpZBoO7zBim2s8cpkCt/Zf2Edu2CeUkS180PzKCBtnq0FpPLD9hjXPsn0GjtTEbwO6lSl9JdJ1+J03tiLVJjRTZffLUlA2gM3tucbJOfyGdAom4yffwP8hjrhTBeEyLwKmLISNARiKuE2Cm671yMn1pmt85Vu1rajq9L/GeJdoPPL+4pw0dk8/Oydx0+kOg8/Jyb/8D+XobOK98UfLB6gCaeqZV/2EBEumn1xdhcDpP8cx/kijjzPmOg+tlXa5VzG6SpcY1zw1kYgyEbLZMts5EHUFYp+UCNixZleiG2HvEN5v2iuXOdcZiguCFkQLt9TkzO1v99jj08p64LxUkxY7ovJoeanwleMMBEAI0vWrt1+8nf065/WLA+s6zQWMP7nlMloMXAfMybSF/he7s2xGsrnFXqR0XBU9qRnrLY/9IcroEnKTvicyEUylh+wG8KUQcIJj+fOEVqPGITla0i+36wx46XgzdRw=","layer_level":1},{"id":"b80dc237-1a6a-401f-9f4d-14190edebcdd","repo_id":"1095f823-f6f5-4e66-9aad-9f0b5b6b99d1","name":"技术栈","description":"technology-stack","prompt":"为GEO项目创建全面的技术栈文档。详细介绍前后端采用的核心技术和框架选择,包括后端的FastAPI + Python 3.9+、前端的Next.js 14 + TypeScript、数据库的PostgreSQL、Redis缓存等。解释每个技术选型的原因和优势,如FastAPI的高性能异步特性、Next.js的App Router架构、SQLAlchemy的异步ORM支持等。说明容器化部署方案,包括Docker镜像构建和多阶段部署策略。介绍开发工具链,如TypeScript配置、Tailwind CSS样式框架、ESLint代码规范等。提供技术兼容性信息和版本要求,帮助开发者快速了解项目的技术基础。","parent_id":"1bb55e12-24c4-42cb-8f59-ddc303460d45","order":1,"progress_status":"completed","dependent_files":"backend/requirements.txt,frontend/package.json,backend/Dockerfile,frontend/Dockerfile","gmt_create":"2026-04-22T18:57:13.329718+08:00","gmt_modified":"2026-04-22T19:09:54.216074+08:00","raw_data":"WikiEncrypted:w0CkdCdnXCcvlN5xOpiEhEX3U68GI0Ngj6azFMJo9xRSxuOblJXg8Gncvj5vankATp2aJeXH/Zz4LVKH2Ep+cABEA0J7OIJMnt/ZJc7uvMtWJKS6+i5aGsUhX9BZcr1SC4TqdgwXb2je+DFK+fLZJVkri1Ne9BkEqmtSaV5CijFytJ/VSKFHzj8+7gC5Jd3CbEASojclHovCufD4dAVhlK2qcIuY3RBxMsvfRAlLyMLZEWg/gD7LEj0JaChWWR8vRaEtX0LtMoYIgSfbY/nUjR+3xHFig+m0qclK8Q01S5GJH99paLVqVkmt12iwMMiqNZypY1W2gRvZNsT8eanIKu0tq5HqvmbN0y9+nnuwnz/Tg6nUBlKIIS40jp2oYca9ak9bIwBm0TqkMe+M3Ara03+x9PgGRUuYwCt9d0PwpPG5/vOAkZtP8talqqwhn7Qom1nVkhmExMfsXTYsM+Fn2bQFXKIT/rAyT5rY6hwokrvghKwOb9pH7V8+4XckeKWV6L1rNcccOb6Inp4WcVBTcTvGbdy4Wj5Z1VETFwMnDdpOGFWc0jZRJpjrRSGgDuEW8IXpMvVYk3FV5ZyUXZcNyEWZ0Fp/s84guMC21/RYF67/9jD7eJYMeCsU92nWm6QkdVB13XQBOvYGFSu1QejQCgDMWpPz4kkt4yz9mgOtH7HsH8ZUDIml7Vci6pCcEIzS2Sy+BoXxSxcOzrqxD+PbGcH8A/BafN1771WuNzprCCTqbZd5MVXBKiY+qrlRCD1ug+pKS075xfWh/Y2Sjz4p1aJuyVplvOfNUKTlbZVBzQu5DBO+yhXj4b8Amf7OLydq0Avaf0gJhYhX3HpFNqi6aqT9OzPBIPohOUi9RWffBwHMJii2/NZj4GbgeXsWU5+EKE6sGFRGtUiBZGzf8FnB6rW16EA6in7Vd7Ls3pJrra3z6b/k9gqlh8eAVDoZhCPuxtA6yNlXm+RYWLDYeWiRDZoavKVj13rXtaqtX3j1/e1zFPMBZlDPVHyBqCZRiZjlKnty9cj2ASgpu7idyh8jDQSALGu814Wb55H1q08bvFxJf6pxn0JfbRJZMHqCEgInivdDUTcCCPOteDT0O2pwMmyHuq3mI3VzFPnYLM3aYzgJQsNIVztV/dIEJu2UGF/cyjIeROHaxvWYLNXRJZ05iMp8oelEwNe58eAvWt2KOuahqQl6xKUctm90QLv8QR9hr7PjiNAMVH3WsMxkqLcIUPuboMElVq3ErUqd4qE7W5l5Uxi2I9bVcnq4qiRtbCnRY32uC43wILTgq6KrBaO6dehB3eW4drPWqtmcU8rP1DJEatUWEvhpDNrI7T7wG6F+","layer_level":1},{"id":"7e5c3b8e-5aa3-448d-ae52-d5a96a413b0b","repo_id":"1095f823-f6f5-4e66-9aad-9f0b5b6b99d1","name":"表结构设计","description":"table-schema-design","prompt":"创建GEO项目表结构设计文档。详细描述所有数据库表的设计,包括users、queries、citation_records、query_tasks和subscriptions表的字段定义、数据类型和约束条件。说明主键、外键关系和索引策略。文档化表之间的关联关系,包括一对一、一对多和多对多关系。解释业务规则在数据库层面的实现,如数据完整性约束和业务逻辑验证。提供表结构图和ER关系图,帮助理解数据模型的整体架构。","parent_id":"243a1a45-d31f-405e-a3b9-694d2fe617d5","order":1,"progress_status":"completed","dependent_files":"backend/app/models/user.py,backend/app/models/query.py,backend/app/models/citation_record.py,backend/app/models/query_task.py,backend/app/models/subscription.py","gmt_create":"2026-04-22T18:57:14.160671+08:00","gmt_modified":"2026-04-22T19:10:23.576798+08:00","raw_data":"WikiEncrypted:TWtD9cYU/QQHU+vD+ojNNl24L1Ao0zI5Y2mk07u9ZlXGce4CUXsGNCSRaLrvDZHw4OUpuZEJrmJBXEQX8GmxRc1IXLTgRlqUGmpzfcUAx8VrQijBe+unqg1mWTkYnMlYOqKWSJdISHyD5K3kBL2cL5pXF+f+lPHzSbWtqMnNnMKbqnSl/TkKh6cr7PM1YBR4IYmE21gHSR5XoQjbtYmg5qNyKF1kMdcAd0LHw6p7zHBaF9cNt++5GyFKLK0zjN2L8YiFsuFBSrn/M48QW3WyTrvDvqdOuR/Slfv+gUsKgbkt6+NEpuY9HPcRdvVJHvG9FZedomH4DrKuI0fUXgICXotXbrcEe5dOkLKgfn+gXmS6sPSZ1XgrSNO5gy2QNJaW+oKBuEPzfuKsNr3X19FZTz+x620YmL1Ccv/5uvf0Zxl6fyQb3qP+lsh2kaMdhWVKyoBv37oNKF7MO+fy+TWHFEwlVnxgmQREyQva5qxLyYzu1GtDpGp79IemnumltTAAzQ7LRs/RsaNcU3BZdYfQspjnhukylPJpNZtmKNN//XWvj023bGiaLyy805c71DcyqZNUs+EdlXmRTABeq9QkVU5wq/gkO4RFSgsWao/8f2i9FLeEZolKQXzoLnX7GxaY3BMcynG+DlwKFEolVOw07cpddYEWzmVKgJUokX/eiMbrokbcv9bLXJpHl2aP27B2FXy5Q2Ot11b2WbuT532RndBI+S9HQpfMmZ2z2Fc3VrWAbk03DwChHEbNHpmQvJpjKtLweVEpClahV8iTSwCkwd43jJdW+tR00iSdjt5vbl1cU7Dciah/B/9B7CDr9sUyZMjly7kzyWZqTkdXde3tO6tu6tWhTigIMXmZVqhW/pgVifH0R72VuM+sdMw57m7Z89ibQ7o2LewlMzJ4GsV90DdDhHQtUr++aRhcZp/669o8mijOQKj8MPHY+xjhZ2oiS6RHiCYxpibVfauiaXA3swWKIQrVCVE1x+jB07pieI3wHrmZf875mdp9rhfrz96+y4zJ464iINUdTQinm/zI4CnhXE3inFBgr8bD3pop0oYr2X5f8Gn2iKyvByc+w5r8HKV/7dd4GrdAosqVWpQweVEYR+MHRZ3AxiW+TCpRWz/PsHgunD4m+AQv5lxwoHVqF0Tqw7fmmxTqA/zC+dxlIJVD/R2WF4sFpA6femHOwqniwaowQerg8bGe7mz3BCSqiobqGSZQ5jQdh34TRP7qUg6PGkJx2NJ6AVIZVYBg9JNOQI67+2PN5AKq6WiT7Rojgo1r8lEx8SORaVptbL4YEEeD8Ec4g2l7Aqkhdxd43uw=","layer_level":1},{"id":"9fe32b83-3697-4939-8b10-524f5ed3e65e","repo_id":"1095f823-f6f5-4e66-9aad-9f0b5b6b99d1","name":"Kimi平台集成","description":"kimi-platform-integration","prompt":"创建Kimi平台集成的详细文档。详细说明Kimi平台适配器的实现,包括Playwright浏览器自动化配置和初始化过程。文档化页面交互逻辑,包括搜索框定位、输入处理、搜索按钮点击和结果页面解析。解释错误重试机制的实现,包括网络异常处理、页面加载超时和重试策略。说明浏览器会话管理和资源清理机制。提供Kimi平台API调用的具体示例和常见问题解决方案。包含性能优化建议和调试技巧。","parent_id":"7e66719b-4a8a-484d-889d-10fdc76788bb","order":1,"progress_status":"completed","dependent_files":"backend/app/workers/platforms/kimi.py","gmt_create":"2026-04-22T18:57:14.59267+08:00","gmt_modified":"2026-04-23T20:35:18.737652+08:00","raw_data":"WikiEncrypted:0zvMywNpoUVtx5LPNkwYYfwlM/Ie9jv+tKyKKcv1AxRC9mVBYjtaMmDbjB4bi6R3DoFVGOgv6ErdxCywJprEc4/FOXSuinoLipOBEjS1SoLvIuIvglY6l/IjgeQW61Rm7d1YcswwpmQZIzWMvqp6xJswdQOA6I4OCWZyyoaPa/2lETrzZcBW9ssD16KyXFVp96WbqY4mZhPFxSQEDiT4cUJ/clUzKx+oT4S+pSOYSGl6/5YsuAOA3Rc1HhY9Ow5FK9FlKsVMaFmxyJU/KLHcwZslXi8yzFzIWcnJQnRmMQlz6Zzz6mhJvkfg/s1TIOTiz3ZX906YG6DBXgZ66UywONJCeYpSAmTL6PJmP5z+lNRhuD0CzfmDGhErgZhLtvoyUfFoVruQmx/x9Rgy1lFnhKmvH60xIEg1eXiVjrQ/yktlr5ioCPigx1TWbcHspNlPAbDuKqqBhQtNOIgnlpoGgyEogad7Il1hkawUxt/TaiS3Lh0SN+zWs028ewgjO9gdWMB7xsAiB1+L5jMFCCJP/mhbPEfqnGC/VyxfevmgulrRD5A2EPR0QF4D/XNbc/vqSGqnIgkBngdxV4ibQlp1HO+Av79lh88FpVteFuEf6bsCL5SSHLDhJ8seJm0aoD1e6f+DtutdT3mVHaMcrEbMYz3AaNJhbNq0bEuElJ/ANz3eN0m5PPDjjnZto+CQ9o7K0C3DeRqKx2P0uRlrzhuBWIwJMzcC944SPjxYEUXHfT4C4vryztUifweDRw3eil4eFCrCBpGf/6gsdtqLoTPs1uBBVkxVh2UFoypvq5jwW2g9IkwMSHN/sAbNIITH2bRVDR7Z/pJay1eQSTjF1pz3NWcM6kQpB22XVAiOhiWPjJRQuWDtpRh+kOxWUSLaNkXSsf98tkydtHAPkMfUhalyLYFO/66PWyHJDWdFPECqtsOy5mpoJdYD0O/20+xc08z7liVDDgIlSocFXHWG35upSCjW6JWCIiphXqsI3He/dWHuwvTBamA9XB7Q44hTbQY3lKiTRjkbjuNfX8cmxcX7Hq21kTW6OBbxTVR55HSW1znrOe12b0sUz6V4Sk1zI5OB","layer_level":1},{"id":"cc7a1f1b-c70e-4c61-bfbc-6dc408a12ff2","repo_id":"1095f823-f6f5-4e66-9aad-9f0b5b6b99d1","name":"查询执行流程","description":"query-execution-flow","prompt":"创建查询执行流程的详细文档。解释从任务检查到执行完成的完整生命周期,包括查询状态检查、数据库事务处理和异常处理机制。详细说明check_and_execute_queries方法的工作原理,包括查询条件筛选、批量执行策略和错误隔离机制。文档化单个查询执行过程,包括CitationEngine的集成、异步调用模式和状态更新流程。提供执行流程的时序图、状态转换图和错误处理策略。包含性能监控指标和调试技巧。","parent_id":"7416db23-312f-478d-8883-2fc3c41ac2e8","order":1,"progress_status":"completed","dependent_files":"backend/app/workers/scheduler.py,backend/app/workers/citation_engine.py","gmt_create":"2026-04-22T18:57:25.383473+08:00","gmt_modified":"2026-04-22T19:11:29.353795+08:00","raw_data":"WikiEncrypted:l9Ho0Yh0r5bYH9QEePEhka2UMFH582eHsB+P+EaGE/r7Zj5gVUJmL6923rRlAt7h2uvHOVtef4s71D/S/eYpYYgI+wRFyPq+fQZYOCmVnMBRyypO5m8WqfyrsSGvviugw2fw2oH6ruNX2ul1LjPKkntbj4o015R9XwHG0oDdyJlipxqNUbh66IV2c2DO1besCA/q2yTeLh6EiHD+vYeG3HO5H+y8kykMbBuh9eydnmoXBTCsTlNBHH8gzmZWEBBSL7DETM0lYCiNr6WpRCoeZEo9ewLagGq1ammmMjcMg+7fO/xo+ZkkACRTnG2vnKh3if5fBjzo9tY4tGmtF7Fevx+yjLRfhpPsg8vSRZeaggRPgub5zBIulo/4qZhAvIVsyYuAQCqrwq6mBxAEjgWWrWjOThUEQOntbugUY0DitRui7XGp7tDjAIWw570xWzTTUWe0CMoHIPghfvhItcnYfjKK+fapnQTnz159jVJarLbBdjZT5JJfw9a+jlkVyF5RIKu3J03cjGFJeBf74DiMxFIMQkKzgL8jg5YiLQTisI4X0BBQrKHQvHzsD5+VzHGwCsz7IIfcdZuhkg3PIA4z4V7eZP9tOBUJdh7iE4fjhOk6fVDG5iZME72OxpBtFkmfrhwM52swaToCosj1eQ5m6V2GjsYY/+ZvaNf2aWn8vBJHI4IEO+Ua1mLHkPRT9bhDGS+Td2r1R2fmSEEvNQ+PTuhnRAyzRASTsjfWljzNWGNmcbCtClwcIuTSwPWLAoL+ANl303UlvxObHa9udiJcH3pZ86+A7iBLoCg6JxZQuCSqD0W6bPR/vozpiCvGs1TvMR5tx6AtfZGWw4JYl9wN5iPPaP8sPsz40D4PWkYIb4fIYY/X3r2iAnbjpV+/8+h3DQCWEdqRNnkZ4Do+XZGOi1yH7QaPOf/RN00+bcNtR36PnzENY47tg8VfPkbt47YTWHf+qvWfMFPwco2hLzXvNFmYN4dVMld5V+9mzCPJSIb+JOcDoVkoGuNq7aXnOVFdERnypgzvjryBt3W2LgPNlD3k6jR7pJAE1gKKrl00VSdDN9npu4QXyT49p+YMv9m8Jbf9xo1Jn2dqM/cJiKZi1FLR0clZHZ7nh7/7WxoEqbKnLWbboi/qyuTABO07nyQfmyXR/24bRp3AIRiM+7Bq8KL9ZFZs05JmFBtaRCAzWdBdM3TElVkfFOyZRZeKaBlk","layer_level":1},{"id":"fec685a0-c9bb-4048-baf4-40b56b2aa29c","repo_id":"1095f823-f6f5-4e66-9aad-9f0b5b6b99d1","name":"集成测试","description":"integration-testing","prompt":"创建GEO项目集成测试的综合文档。详细说明API端到端测试的实现方法,包括FastAPI应用测试、数据库连接测试和外部服务集成测试。文档化测试环境的配置,包括测试数据库设置、异步客户端配置和依赖注入覆盖。说明如何测试完整的用户工作流,从认证到查询执行再到结果返回的端到端流程。提供数据库事务管理和测试数据隔离的策略。包含性能测试和负载测试的方法。","parent_id":"fc6f24c3-594e-4153-854f-19250834eeb1","order":1,"progress_status":"completed","dependent_files":"tests/conftest.py,backend/app/main.py,backend/app/database.py","gmt_create":"2026-04-22T18:57:25.616681+08:00","gmt_modified":"2026-04-22T19:12:37.820526+08:00","raw_data":"WikiEncrypted:0j4RRfWJQdenLQLpT+DwLTyjMVG5sQffpuJQoSG8tbOVCukW9eq2bqobYYACR3zRn/N/FP6n0t+ZzbrLBFIDPbiPv5CjhNbth11wsRap1Da2YyKifcvwg7uyuWtSILKRIkP8wIVHX2/TkxRFQi9/m+9Qz3xVjYcNeOD0G8UWxzsSDqYGS90xX9MVwW3N24hbwwcJUE/TAMETdbhwrekpr33ej8R6IT6aBvn7m0Y93BRItueF5HJcUtKCizqJqcsG+BIQ1fodLPAsUiqvYW5dwymM89ASYiZXVbCOJq19yL9K4p1ZW1LsAc2J+6D8SR9RJ//D4gGwBmMTqxyP9bgn5eNt3ILeVMXWLXI9oxaDrdVs2Y4dXNC4AK1j0pegZkiNREUo54kWHFqCuQ6dG8dZB7BmnFEIYjwEeU29KdF6i0dyUH3/h5QjdLfc0OV75zuHQPaMs1p5fn3vo6ubXz/uWtxEF/IoVhph+AyY0Gci8TxdouTw4RZOm9I6mo5m4Y+TBsxUb9RO0WCrD/U7tRgIZcrxFfkORsKadNWm60Q4SRJeImUzxIVCUGBjr4km9AMwVsl94KSXmkBCNOFppeijE4N4Dl0n+RekVA2NBOau2woOIr/GwJ7b2h0jV/5/3x5hihxUSqZJ/q4RJmV/8aP30XRdYwZ6qiLcaF6Ic8kwpaS+9cvzGsPMcUF4GCS6ZSZoq4tuGj1ZY/iFI0w6Wj7rJHWbeBhsF/fHqFm2ijbrvn2nz+lH8Gxb3FM+re81hKNVU3BaZ3fxOAldPPvUxDw9tttWR+oH3F/gRkqefOIsw95LNYf2vIq/HXfNygn6mUw4aYidP1SY8flPcCMl0mDm7y7W6l+DKUJuok11v6h2AM09f0VV9JnGBMgwCic1FjQmfF2FWdqlsEaB0X4+aPne0DgPyIivgCLEq1dyneDm4TxA3CEVODVKHIu4fxPjmDtwbXUvPQe5sWkG7AEkp1Vuul8T/GLjJc/DHgUFe51MPFk3+8i0FCKo0x0fS8Mqm3spHB5W1tKYAIyexOgSkHzqgRdgERCTqUW461c4lKbFO2WIJqWgt/seMgxHr02Yk/pvMU08AaMRC974SfB7kP0lEQ==","layer_level":1},{"id":"b10c2334-a850-471a-9851-a1c698e3a485","repo_id":"1095f823-f6f5-4e66-9aad-9f0b5b6b99d1","name":"查询管理接口","description":"queries-api","prompt":"创建查询管理系统的详细API文档。记录查询任务的创建、读取、更新、删除和执行操作的完整流程。详细说明查询任务的数据模型、字段定义和验证规则。文档化查询任务的状态管理、调度机制和执行监控功能。包含查询参数配置、定时任务设置和批量操作接口。提供查询任务生命周期管理的最佳实践和错误处理策略。","parent_id":"dd12cc44-0c95-45d5-a726-e7b8bcf2531b","order":1,"progress_status":"completed","dependent_files":"backend/app/api/queries.py,backend/app/schemas/query.py,backend/app/models/query.py","gmt_create":"2026-04-22T18:57:37.836674+08:00","gmt_modified":"2026-04-23T20:33:57.631967+08:00","raw_data":"WikiEncrypted:pNRlLcrWPaMbqj3wxGubppFNc0/AzaZuAQDxEKkb9fgIpRlV367n+a2PWiIY8g+kSLtBeyylocxMvW4jGcb79BLGGixlb4O6TPBIJc7v8GgK1UB+nLdmTHx/nT1JfKtrcPOkDjQ/yPHvw+ykuXomGaA2hiHzzBxAe+PbZILYbxYpQjnTqh7v4SGaGQ9U1E2EOXJ0RFpwna+s0NYfvBk+YvwkzRYPMiKcr+F4pcD5xTUWKMHZO3NuijnbDIE02fzYXvZ/xDBLubLxQ9Byx2dgdWxmi+xwo+gspb4v/DcrNll6qDWKwDnHGuyOQzDJJ1vXg3AaxwF5c2JyyQLNPUM7YV2kwxweQA08sFkJHAJ2yA0z4XM/DvAPZRdQf54LPlDB1zuFh8c3Ih5WaEO7+aTJM4YSmIYUbqjIjbqsMea3+cY2bIHXq2kdRT7uLikCktC9Lakrz0fFKLoJLovY3S1UBP3i7tCt6cmtMlN5g5hyHGqIVTT/fqAVUAc7wSZumMs4rr4uyEizs6t12KohwD2SqiCePMC+kbUpHV0fEBuzGlnYqPbW0yjiiVQlmIe8wTDNiNNa88JmcXkQB1pYhkAYrBUvBUN4Nrdf7lGBTIbQkQwvVoHuFah0MmoLuRQtoBqISkKJ9PMN0EOofu4pUNKyxmmcY87ZVbUNrwkgbvahp01NhzlsOLdxEa7d/74gFI+6MOrPY/6TcJqttksCQEkme4HWeJgRl5S2bCy3hlU9qcZyk6WAGPjVZg4JXdq2UbvBokHzB7KA7421mWkKGQALuZcUApNvwsvF1ZHjVau13wxP02WvaOzt+udwhgw2PXdNi26RDqwLhRL+GIjkpNfVngOcLfk1ULiMS87NXS9kHRTdXxu5W6PqAzyrgByrL3G+nPHL+XmMw6ntgsJdmtYmNWV0VijOOQGxSJGQHtaif6ZhBP+ckr+OXJ4GlkTF3jvGcfRkfx/eox+BaoxWI06xuXbFfImPuNqqa6odgzQzWv4CkvAnjcFq7umhE9Iri8xw/PDlUzBnr4HGnUPnAVvdomeMasz/oiPVTaI0O6tO3+I=","layer_level":1},{"id":"0c1d3542-92cf-4796-8dba-82caf2f7b361","repo_id":"1095f823-f6f5-4e66-9aad-9f0b5b6b99d1","name":"开发流程","description":"development-workflow","prompt":"创建GEO项目的开发流程文档。详细说明Git分支策略和工作流,包括feature分支、develop分支和release分支的管理。文档化代码审查流程,包括Pull Request模板、审查标准和合并要求。说明版本发布管理,包括语义化版本控制、变更日志维护和发布标签。提供持续集成/持续部署(CI/CD)配置说明。包含开发环境搭建和团队协作的最佳实践。","parent_id":"2148d7d6-25c4-497f-8894-c4eb7a0d2bd7","order":1,"progress_status":"completed","dependent_files":"docker-compose.yml,backend/Dockerfile,frontend/Dockerfile,backend/requirements.txt,frontend/package.json","gmt_create":"2026-04-22T18:57:39.374243+08:00","gmt_modified":"2026-04-22T19:13:23.08237+08:00","raw_data":"WikiEncrypted:F3QgleoEfoy16cQggYe9Czfqaqo1gAmvHQcnSrNK3eg3bg6SLp6Qtm0Hd5JwzGY3jDj+dSShAoxbjZ6YvxA0ahjJ7+4npTrro/p0OlyQfTnVZ5PYAZZMMXhJM063eUYiuQW88+rNBbc3mKbsAdZboYndBnd6/wybElFnP7TORa5qWxWMveWf6U7O01ocA+ZnrQqoPWB5xrRfSzD1p3yGFA3fzKobYoxAAA3xE1ALEY0vjLN7vajgFVllC2Z6uKZOE4Q6v+W+r18Pr7pLXGDJM7b6pEfFCqcEMw2fWzUAFYSUOjSyg7j9TjP6Lae0AWOmmxIDmJIIiaY0BCv/iOXgg4F6QSChC8bZFyWJATWTNhfmHAMU6tYpDXqDsfLmRpczznZ5nzTtcX+87Ndpqchh+NWU4y5OYvzEeMRCh3HcCUDs5KrOoCJgRneV8BzAxfk4gCwSo2t2D/FYg1XWGfb6hPdmWzePBCYhhIGeDQRyAdApe2Js8UhXUOD3TM7yzFPMX9q5U9ZBfejCp8TyW2thbRzOL4s5Fto9PpXg38HbnE59l0BmptA7z5bTKTp4DHA8d4NhgCeDbfNLfSJXbyYaD3RqsQt8szzbxB2Q8mvEi8iUZUARZR0lyq0oEw3cYkZRo7Dcb1n5az2OJRZwHmvRYAm7KceVqa92aKeBUlVrfA7nOuwsVH+cEXyzE8ApglbJiQfTJshljzVBvYPkz0BxhBcYrnRIjy9TlqfTs67adZyWc0wqEVZeZhuYHwwN5yID2imZ/nq7cqiZCbV1dtBUUM6ayhVX2h/cBSLpHKAwVHAg9bb9V+RxXgtSYWYKCHsAD0ymmu/Fzk3/QBvrrFiVqL4b/5CKqk6Qi2dh4pN4tZg3zJZDuyx6xzWSrsHeYGnLunZQWtHn2lr2vR6+RqzRTDiOC8SizuAjeZP72IbQf5Xyyf65hS6yls8xztLA9oDCNnSDgJ/RiNDOspfgUyj2xemyoNqf2eJ/kCDdo4/VXxMiKVfg3MHY+Vi4dVlRcSEJYLU4AYuGqtqVhTIi2ESpnPXgDPAIT+ZZPqg0hLIIPx+HNqo5qz0qqxvliLlcAhizNT4MG3p3dBRI2IkylW4gHg==","layer_level":1},{"id":"109a8fb1-6619-4bc7-8481-e28cc2127d24","repo_id":"1095f823-f6f5-4e66-9aad-9f0b5b6b99d1","name":"生产环境部署","description":"production-deployment","prompt":"创建GEO项目生产环境部署的综合指南。详细说明生产环境的部署架构,包括Nginx反向代理配置、SSL证书管理和负载均衡设置。文档化环境变量的安全配置,包括数据库连接、Redis配置和API密钥管理。说明生产环境的性能优化策略,包括静态资源缓存、Gzip压缩和CDN集成。提供安全加固措施,包括防火墙配置、访问控制和数据加密。包含域名配置、DNS设置和HTTPS证书申请流程。提供部署后的验证步骤和性能基准测试方法。","parent_id":"803bfef4-3985-477e-a61c-915a246d0061","order":1,"progress_status":"completed","dependent_files":"docker-compose.yml,backend/Dockerfile,frontend/Dockerfile,backend/requirements.txt,frontend/package.json","gmt_create":"2026-04-22T18:57:40.355193+08:00","gmt_modified":"2026-04-22T19:13:58.697418+08:00","raw_data":"WikiEncrypted:1PcQ+NupkgQiLQ506NXlaizhNZeqS8C1INCZPnjb6ozpR9JAOMhzbAgtECu8k4VbH9zFlJ7iHctHtUva/hpzUaHUxVuG/rnK2RrcCUGVfbG0WKRpjG+EsQheC10ihbe51Rb+uXm+ciY+/SOxWBmrtK9m9jwSBQZQx2vXLOPvachfZTksEB+Ak0/Y5DF+vjL4WN+ym2SAYi7dW98iM9YCG0AepSeRm5DxENKRvtPR7m+w+vL7F2oISKi67pFiAATpFXSSgbkKjENZIgPfqc+pJfUREOrnHANiCx/oVaX2aOb68pluM8RGtAgyOfMp097D2Nt4PR/HN691JphbIyyeHPc82yGTjeuFPfg5XqFkhM4gvd9EdBLE3/6bh/MJhYjEwmN2RRhz7EYgLjSss8gEdDu+YLIEbHIaIC5fFS7gss/cJULC0/i3v4nnobE2Iqh3WdeIMAmynsin0sjO60LhvRmXlecODQ7+1EeQpMWju5LwTuVyX3dnr4CO4rJJxEBNYA4gaJuef2xo/ZXoun6cEIHjUq7qVNVOBZw2QtqBD2CyY3NULBP+nDD/NwjH/Gh98gl2Q0am/gLAHHoKcZfkSub1o1m1ZWTFgYn6MqyYv95NuqxR5+MSPb9C6/rwkYduPmovFsS2Alznry8TjsLdD5iSNz9MdRTR9iNV/A/TIIovgVogXlgCwnIz6EXZUgDnTeBTfTHxC+gwTrSKXUigRlIxEGksBJkzktpQA8y9mwnIfHgRDI4c8WEQRGEcKm2N3/ZPVOyBHSOHNpXK/BX8MCQqGoj0x6jusO9pJehw7KRprktlMbB0LmAuc5i0RYf9SnhsGs23W7ktzhS+uTjRB4kviSWZdHs+hgh1Pu0HsyBZxX7pemalNElQsWbvLwFNsJY1L1yjHNbBDYyXC7gZZqdb2l9GqKVgozQuK+qUUA0Vj2o6Cr4CxL01vBYMFpHALv8KnmAI2CuprX0c6PmsXV20FAFF8tIxoGfh7qcvquq/d4ONxZ5FZ1hJPYzi2xeCU0p8gFYEYYlbGMXdLCk0L5Tu0aDmTVkkrZlOHSIneYJDGZ1W/q+U6W18i48iBLvFBHD19jGHBgdzRuX551rbt4axStOcEGuyFrivbWK9R2zdcffHbiRtxe9wSFXxthLGe23JR42EF5PmZmMtlUhpV6alxUZNxguf+q/ouSz7Xn8+o6amnO60N57RyJjJO7O6+TgfHeroxL7CpABxkru/vXEJ5XTLqZBiECMMi4keQOqUbNZX8Ioct03e1YG7OgHtDSayZFtZf3kwN2ToVkxIRpLHTUHxSWLZu0YiAI2MONU=","layer_level":1},{"id":"4d5ac6d7-8812-414b-b8df-68574cc36d7d","repo_id":"1095f823-f6f5-4e66-9aad-9f0b5b6b99d1","name":"配置定制","description":"configuration-customization","prompt":"创建GEO项目配置定制的综合文档。详细说明环境变量配置管理,包括数据库连接配置、AI平台API密钥管理和Redis缓存配置。文档化功能开关的实现机制,包括动态配置加载、运行时功能启用/禁用和配置热更新。说明性能调优参数的配置方法,包括数据库连接池大小、异步任务并发数和缓存策略参数。提供前端主题定制指南,包括Tailwind CSS配置、颜色方案定制和响应式断点调整。包含生产环境配置最佳实践和安全配置建议。","parent_id":"b2bb2e3c-5661-497c-97dd-15bf6ee8b7d4","order":1,"progress_status":"completed","dependent_files":"backend/app/config.py,backend/alembic.ini,frontend/tailwind.config.ts,frontend/next.config.mjs","gmt_create":"2026-04-22T18:57:48.684725+08:00","gmt_modified":"2026-04-22T19:14:17.843426+08:00","raw_data":"WikiEncrypted:aC5ZtUyEKPSxjzg//aVllKOp167MIMMk/Juev/hVoGY4+Uz0exYT+x+CbyScHHV/Mh1WUG25XsdoZThZQEtO0sLOn9+hGddmRIK1DWfKa/hxxPvnViNvXvltvNYiLNOIbKgkBxtXovEsADGNyhZh4ndOp+a/upcB9NJ4f0miwJacx2Kc2MyCkDCgUM/gJEjyoB9tRPRJVPFRvprzmaiPXJ1K8jd+KuXwrM12ogUA9iPZOtJJQTeEXQVIItOZYzY5bzAZ/mnRyVIB11vegQ+E6Lzm7D1Nza2QOZ2893Bzu61StECZsNlfecc+xEh82aNHrbFip7Fg2I3E3fqBs5EgoNXO5Wnvkcd9fHCw9vI9kMJucTIPcthOyWAFiP56zu6Hzknqy5N0o2gSAJQdhzzEvIUUKeeGDZKSY2EjFsH531gWa+Q9m0FsYWFcErqBlQXG8K06rnNNeMwR71GloOifAK0ySuik/7BjJ7xIR7HF8FOfSaOhI011z3GaEBxZsMfPc13v0joKHld4p4PRBXAfExWLlfuM6cmB/77U4xdBrHVyMcS8NPKuT+TQCTzjr2uUKzxUcjbz+yGbjVFGKMaVzKH0UQfLKeSDUnb1JNBrQWR0PFAuZsPZt730dAHdElNx9MenV8/GY+XPklTXdGMUtflT6CKf3fLy6ppMVbMDph2Ov+1Xh3z35Y5Mz3rufJasyOE0rZQMNsUu3wHtnjYprxfzvmpP9En5z4KoGEa/282c8xoLp+n3+etuGCN2aor1BSrro/ZpPTduyQtqj2WdfXDnZo1In/RRAh0TwqPze8Cd244OFfKDDAEICSSoZl0S/2l15QyTbqDNVnRzLndJswfAi2yfaVOEkBHvZuDQZXmmlf4VGsJYihVUwG8Y8bvegjLxgcD3LFGNKjzuKP1eAYLcotF84HRaFwNG3hz8Mv8puFMKyrHVKIC3UxzBVaialQqdO3oFRcrLdcSIx1JlY2qhK3BsrUtj0OLURUs0dBnCQS4ndq4NTLSQECFIifA9l7GSPXyOkGkp0+H5QCfjOl7L/3EJ2o+lTisAZggIZSZ57Ig3WxOGp4tgBh18ubr0TRNi0u/VccTbFyT97irQVq+9KNBKwPZZazaWvJEuqNSsdX3WGjh17VTbbZgmTkAwLyuCf+nyKkGUkq6MtRYwX17XkQuhceFpBmYkoxlfSWr4odGaspQ3c/AJ5zFNMigymGGpxOynWRWD5Abo/3R67eqZ9rZbmCqQbF0fkFPxdi1prJr87dubXtG1Zkj8AE/ZGXYjwas/l8NeDYxLFeir/ic+yR2tcU34lFAY/B86IHf+EBSbBYigErIEadb9gw81","layer_level":1},{"id":"a232faa5-28b0-4235-8ad4-b082fd226e69","repo_id":"1095f823-f6f5-4e66-9aad-9f0b5b6b99d1","name":"订阅管理系统","description":"subscription-management-system","parent_id":"178b681f-d013-44b7-aef8-dee7ca8c22a9","order":1,"progress_status":"completed","dependent_files":"backend/app/api/subscriptions.py,backend/app/services/subscription.py,backend/app/schemas/subscription.py,backend/app/models/subscription.py,frontend/app/(dashboard)/dashboard/settings/page.tsx","gmt_create":"2026-04-24T11:02:30.91857+08:00","gmt_modified":"2026-04-24T11:04:05.339576+08:00","raw_data":"WikiEncrypted:esVoUJ7ZE3JHzIVFBls2kBN3sRNq72F+2dVFRiBKd+IrKVrEmIv5onipM8erIVXb1pP69wHz5wuM2zNLXG0Ok25RXMybvVHkFqWAEJZpvoheUZoKQmWosbt/UANV5ZMnjhjv0ugRLP8tCwG6HlqUXa4nXCgq5eT+9CKzBTZAc4gf0pl58FewLHZ717UOV2vGW8V5Sc2aVmo/U4kxF9AoGPen+UMUBOILg3LRfP1EM8uA0NcfMu0/dTEUhVAoYdg3egrk6V0LTUamV5NV1SNEVaJfKvMAbt0cYc8sTySSeM8Snn/OvSpnZV2OyrhySqbTxicufzGyCTg/r00/80Kp/vQ96wbKsGjdmbm1F12CjGpKngHQMvn6jGX1n4TtKe4WXqhzWD8nSBjxmMuHQfT8IIpn7seKyIYsAno3TuGU8reVJsl4T9zxMpyipiCssZHp","layer_level":2},{"id":"9ac86c99-3b7e-4745-bc95-9586153d616e","repo_id":"1095f823-f6f5-4e66-9aad-9f0b5b6b99d1","name":"管理员仪表板系统","description":"admin-dashboard-system","parent_id":"178b681f-d013-44b7-aef8-dee7ca8c22a9","order":1,"progress_status":"completed","dependent_files":"backend/app/api/admin.py,backend/app/services/admin.py,frontend/app/(dashboard)/dashboard/admin/page.tsx","gmt_create":"2026-04-24T11:04:06.082629+08:00","gmt_modified":"2026-04-24T11:06:01.089787+08:00","raw_data":"WikiEncrypted:VQqnnGxIj1CWE0rWwHbIomxfew9b7C1uZnUxTSvoHNsF7jhPgOFZS93QZowJJe0Bae/WW9gTFISgZqZ6JAIQlKjp5+H4hYIxP4IyhsAvFP0LcPKdx9gdtkqMwGuidWR2jaXij4fO24hbtjQmmqGXzUUbNnTur6SoiIIKMQ50UFibNp6+YGkvBNWvYJucvpgox24f7/W4o623WN3fB7olfkunOV4HVtCrMdz7LTroAFTZrFhDQtadQmH2JKYCypsT6SHcUyxNUvEZKgLDm1LnOAV0ZyfEx3DuALwEmdt1djL4f0HygoGjNMpqhiA4vnlg4puNMiDyY1yoIUNQDPK+RQ==","layer_level":2},{"id":"d54446b1-5984-4fe6-8fc1-ad0322ab7914","repo_id":"1095f823-f6f5-4e66-9aad-9f0b5b6b99d1","name":"安全增强功能","description":"security-enhancements","parent_id":"178b681f-d013-44b7-aef8-dee7ca8c22a9","order":1,"progress_status":"completed","dependent_files":"backend/app/middleware/rate_limit.py,backend/app/middleware/logging_middleware.py,backend/app/main.py","gmt_create":"2026-04-24T11:06:01.807432+08:00","gmt_modified":"2026-04-24T11:07:19.927506+08:00","raw_data":"WikiEncrypted:6g8iffgXzed698CsRven+bBahvPZ7dIWZ8oYo2ql8SUqS81oHqMdt4/8dBPkLJmUIV4rpltw/NKHLMVVnedRfw/FNgssHH7lJc6ouSeYuFX3t4LMNLJCZkqOnMgC+EkvVhhY7xeMZKjKAR0WN5yHtQ8nh+sWXX5BRoIgiZVs+G4ejsoPo06ZZ7dCm3NkqT1esGxyyfRka2pRlAtMZopE67FJNPBax6aDb7t3Tp40D3FqwBrnPkLvNpEpjadhQJLLGbUZ1ZVau7pWleXvys3qtdfdlpt3SRU3GxhleT5RyWyb6H7xliffBBWs6e2+EPrg","layer_level":2},{"id":"d645182f-1eaa-4439-854c-0437806ceebb","repo_id":"1095f823-f6f5-4e66-9aad-9f0b5b6b99d1","name":"PDF报告系统","description":"pdf-reporting-system","parent_id":"178b681f-d013-44b7-aef8-dee7ca8c22a9","order":1,"progress_status":"completed","dependent_files":"backend/app/services/citation.py,frontend/app/(dashboard)/dashboard/reports/page.tsx","gmt_create":"2026-04-24T11:07:20.621291+08:00","gmt_modified":"2026-04-24T11:08:42.188151+08:00","raw_data":"WikiEncrypted:JtXUgB2EREv7ncJ+MegCx6wn6P3rv/DbcpMX2oD3DhY8Q8TNEnThfOLhKKIJTZNfzlKgubFFqtmmSTVW7QSMR71tLjgZgSLACwoE6wo1/FhEifj/8lOp77v9Aa5u7WO+EgtLVWSz4kKO750z4owTufvhVR+uZ2ahVoHSKD9mXo4KuqrWwFr60hm65igoFdhy/Y+hyNsaJejQJMCUwntWiPiJoBxyTIgf/GpbNj3Ed3Rz67bKvr4/rnGpjDMYKrLKqH5QhLo8wpIaf7MZcfqc6GYtYhyLXCLk61wnw7Xgs08=","layer_level":2},{"id":"7c2ac186-ec90-400a-ac1d-b3b7ca2f01d5","repo_id":"1095f823-f6f5-4e66-9aad-9f0b5b6b99d1","name":"后端系统架构","description":"backend-architecture","prompt":"为GEO后端系统创建全面的架构文档。详细描述基于FastAPI的后端架构设计,包括应用配置、中间件设置、路由组织和生命周期管理。解释数据库连接、ORM配置和异步处理机制。文档化认证系统的实现,包括JWT令牌管理、权限控制和用户会话处理。说明API接口设计原则、错误处理机制和响应格式规范。包含系统监控、日志记录和性能优化策略。提供架构决策的技术背景和权衡考虑。","order":2,"progress_status":"completed","dependent_files":"backend/app/middleware/rate_limit.py,backend/app/middleware/logging_middleware.py,backend/app/services/auth.py,backend/app/services/subscription.py,backend/app/services/admin.py,backend/app/services/citation.py,backend/app/main.py,backend/app/database.py,backend/app/config.py,backend/app/api/,backend/app/models/,backend/app/workers/","gmt_create":"2026-04-22T18:56:47.08233+08:00","gmt_modified":"2026-05-23T15:24:02.349698+08:00","raw_data":"WikiEncrypted:7Nn1MUEMCjrO9aPSED6FHT454wxodEJExHk1Z3tdkRG7psPg9iIsEKvTk2vItDaJAXIG4d4xq8Laz0GUpWi7tvVyLa03YCfOyluItzeFyggOAAnOECGGCu8+eZnrHGjCrLMORlQ+1wEw9nkOpcZHrAs9OhT91iKgU5h0B74rt6WjaJ6MNzH84B64xYyEqmHM0niEHypbMjA8WO+d7J7BmhjgtxWBkUJMprVu/3XnDqSwD4nrvstGxDp6a2Me/1xldqPAIH33Bh7jHl8jwBH57j5llwy6peK7Pcn56nd6/IUHuPpwTrnoc5YduJIMKWGYxu1xF9PNaWMAkurHhHCoMemJuTlpc4HVN6jdvDHV1XLd1WD+tWrKhA2iqcmzuvaGu9XkVGmdF9XSUr3QcpLHFeBkTanbvFYTANI7G07mjpGtPOIvGgmHilbbqh883xvi0eQEyrXDdoAqA5jU+paPRtXoLxib8JBQEqB+fcKcniH+C74h9BHKdauZgcLRT46tYmeFNQiyrNO1vcm7emWe5DFtjbfwrxYUv0K5IY6AUMUzoATIs+eb7f/Y0X4T56LR9E2aUyeViaWeVtnLMiXVSgRMz1/fAG0OfZ1BYXRB08PvPctEfVdY3C2FC9+10XmkN/9fasMBvjcmO9WvIqX6eguoLy23soTupv+OrVuoZ6hiCfInpOcYV2r/ApKBP60ayqitCwvs+ndNATQGz2v3VVvoolt8ZIZvqhvzyOE4JAltTznL18weTTPLWlFYhCPnG3qPm4/bDu07klIkZYx7sKLgTJk+q9nrNphi7sFpmzfC6wnhOtCPR6moX9vrKxydsmZt9cgBuSBia2j8lOQuW4fB5z4WqWJ77Tt1H5EjT5vr3XU4FH20+0eYQYPZNXm52VxrLvB9embAi+nRLiJ1efhYYT/43T4PaUpLTjNMd+g9dYZAgDJ0SVX05PLYNgf0hrDicYjtZkb1/nYUORVOB1zsV5Vlxd64mw1OyQeTokBZYMIKVwfz5UppkEO0an24PaWXjGBnGwjQuDU+aQcm41Tzj+RpNOs5Jgj4MNTv/O+qBC2nvJ+HzTDKmL3LiAV7NfixyGTkrgW8UwAIlDIoPw9OhoM0cQUt7ngzx0vqevePxkh+zyEVs5vjLNwy/sC/UnJpsSsSAlFZ2knnjVE7Og7MI9qWikoCxEYO0qe0Rs33TTI4BlWyFvy4ts/7qO5lG7mkLjHXKv9351kbCuJfG0L4w/Pe7iuve16Nb4unvEKDxYCa+6CzFAjLIsZa4BdOQRsVxyUXf9P4rokWxV5I9sV4jt+WMARYpD5jvN8S2SOqqH6mgcz6Avyd7Ae/46d8Fwo1fLqt+vaQ8zAN+1W6NxUD3NRJqtbcG74m4zp77sPb+jKwNzpnAEewLzpcefAjyBDM9G0IQkgIucrvTCPUr0dK6NCS1H5VIGRNHT936f5C7AFiKxngxFR+EPtBbl3+5AB6y/yxA6jOwcyP22+d/rGsqnkMfxru4kZXc+SJWu6y5nLjRGUBJDZuECrt9WAGscutosi+ugvzvbZwXU8Ws3Ld2j11PJ2MFiPdItEBwKaK1uaEtnFGebbA+g4v2w79ingJODsBC/sZU9N9nFi37WgPpulaDGOkX/9hIyA61F1KNe0Qj5ACKj+VZUN9BdhIk6DNHWMVTRqAvdbP6aXn5Xe9uIJ2hmLtxltTcZMh/YQxM+FUEN02HPI9R2mkP5qg"},{"id":"159f2ccf-71b7-4d1b-a4c4-c15b23a4126e","repo_id":"1095f823-f6f5-4e66-9aad-9f0b5b6b99d1","name":"API接口设计","description":"api-design","prompt":"为GEO API接口设计创建详细的规范文档。解释RESTful API设计原则和路由组织结构,包括URL命名规范、HTTP方法使用和状态码标准。详细说明API版本控制策略和路由前缀管理。文档化请求和响应数据模型,包括Pydantic模型定义、字段验证和序列化规则。解释错误处理机制,包括异常类型分类、错误响应格式和HTTP状态码映射。说明API文档生成和测试策略。包含认证和授权在API层的实现,包括权限检查和访问控制。提供API使用示例和最佳实践指南。","parent_id":"7c2ac186-ec90-400a-ac1d-b3b7ca2f01d5","order":2,"progress_status":"completed","dependent_files":"backend/app/api/auth.py,backend/app/api/queries.py,backend/app/api/citations.py,backend/app/api/reports.py","gmt_create":"2026-04-22T18:57:02.317509+08:00","gmt_modified":"2026-04-22T19:15:14.078939+08:00","raw_data":"WikiEncrypted:xKp6XrvgQ6yDy/qZb6DBAyzRhY9oY9wND++XWs8abaIu3G2LITgI+Z0UQBWYGKhuTqBsuTOr5OLyKixlekyR1Xfq7usrLYQyUqykz50fvTC/eHiVp24qJjGIE/yM/QXCeZCQ0Io9avqxwyMLsy7oz+0kRVW2WjLzRO6OrvbiUY+8yPMkSPi3UCtyM0GVLTpD/1yhEPFlJimDIuMsn1U/6MxjS0vcd+yEDjCBtrAoR40VIxrMz5v+dKD/pjfzoR1p6GEjf7b6zpzZGPhEtFmhzIahThZIdAaGShFz2YepbNwjns9s+2XJPvMdDYb5mBTcQCjoCHeUfqpQ5eRpjJ47qGFAfFw7lpv7GfOixRgEasUkVhJaX2fS+R0bGg3mmJFfg8tK9XXCm0OvNdgj+aJ6EUKT7GWXDkWLJd4NWEHKvqO9jfXu7YBJxM5tfR1i4e7CPz16fSaCPJtKsI+HgIoTf1JQ+3TrBqGncHko/5j2BznPg08EvIvKnECTrZEH1ATf3+Dpz7cY5x5f+D+oBDxG88V899fkfZSrXbY4YZJnhO691mRZPnKUgr3TsGO4kK0/eZw19HvuCyKxuqWlpHvV2nWGiFCyQpLul9lskV53bxNE6LCdF4LpQgsnxp3NRkXRo9kqVcTFEVZX1D65nknWMQHMOr91wEbFu5y7eHBY/M1mlvT+FpX/uzM6NvEAUkyKHsIpLihbh/obM0dUOwFr/y/hUOLfs5gw3aMosXT7+uwJRXkzxJlNzCyzWUQoMQbw19Mq53uhogOLGeVQNV9+lYZlsF9DEbUg7pWX1HOTZw0qj0G50JKHtiM0mGIwmRxZy7HDNhqrMGXboadds7LRAL8up6y1uZya4V4Y43X61XVoJJrERnU6caJROOJ+2I5yEbNYOvo/g+dDZf6DLrj/5IPInHUF/rwxMPX3V17obui48Yk9OOgLp3s7TEAU+t97lkEPo58h2oDARfsbxrnrVd0I9z2/IJSBouFoAA5+wGUVU3BH0Wdc9bwTyjJg6t+iiz5Z14RRB6hnBI45qD3U9a5fIJ1mWWGl2mBaOfvJck5hTbq7v+Au4iOMprm6m9SIq8C9D5w/PtHslYGeBDUYeIOWciDfxj90/WlNjcdIpE8qX8PqRFKdnwDCBOD0xewCH5Cw+MxNEuc6RRDsFu6vhFjjYe/vtb6bNc674kCJn5eQOGFAo6+v5wfkkZhG1S1q5EY8GJf+H3HgtucPikTjpKAbpBkkiorIBJ4n6Gdi9Jof2lYe1Ina6yJPsnNyd1MyQgdpEg7sStrvevt6IaMoeIe0vQ+WPecPhqsIm9X4wS4nI7Knd7q8WUsBQfphwlTzUb0igehWxKagmMc8N3x64Q==","layer_level":1},{"id":"9cc59a5a-f597-4707-b994-b6c49514d553","repo_id":"1095f823-f6f5-4e66-9aad-9f0b5b6b99d1","name":"页面组件设计","description":"page-components","prompt":"创建页面组件设计的综合文档。详细说明仪表板、查询管理、引用数据、报告导出和设置页面的组件结构和实现。文档化页面布局设计、导航结构和用户体验流程。解释页面级数据获取策略、状态管理和错误边界处理。说明页面间的导航逻辑、路由参数传递和页面生命周期管理。包含页面性能优化、懒加载策略和SEO配置。提供页面组件的开发规范和最佳实践。","parent_id":"d907a8eb-795c-4060-9cdd-50d31cf39be3","order":2,"progress_status":"completed","dependent_files":"frontend/app/(dashboard)/dashboard/page.tsx,frontend/app/(dashboard)/dashboard/queries/page.tsx,frontend/app/(dashboard)/dashboard/citations/page.tsx,frontend/app/(dashboard)/dashboard/reports/page.tsx,frontend/app/(dashboard)/queries/page.tsx,frontend/app/(dashboard)/citations/page.tsx,frontend/app/(dashboard)/reports/page.tsx,frontend/app/(dashboard)/settings/page.tsx,frontend/app/(auth)/login/page.tsx,frontend/app/(auth)/register/page.tsx","gmt_create":"2026-04-22T18:57:04.216604+08:00","gmt_modified":"2026-04-23T15:19:43.818179+08:00","raw_data":"WikiEncrypted:5oI5y1yTFbg14yVSXHYDGFeITEbIkjmdES7qr/P4na8TrPHqKZDCV0OwvONxgczey0MsZEE95T/q1IqTn1MDXDe+zweBCSZSlefgNsHwrtPEnyqFrV2NhO5nKlcD6tYwGnW5Ag8vX/svtjfAjl//gRYZD89hOQGnlYrcSU5a6FC1LQaaD4KqNgrn7yYxshfLveO4k610B0mb5BrOdyTpLLBcuNmEgY9/GKvdoyt0cfpZPwN5J+wPoYjAnGjm9LDIkL9L02r9Lvvq1mhN88A7yKU49c6lU6S75IzcT+OFjTd7OXXastuPBLJRb1A0sFMKjZVshweginUNg6fhc3vFQ08Hthoizv1Pjm4qNnloa7P3w/rnuQrvCJk3Nt1PWn+ouHeenTb9bsV/KwF6BGJ4HGDSDyFcd0YmY4CDfW5aSBFP1QYneJUBxux4dxgw1GbBsa6R2o+cDCB4DqSA14RqNvsI4r16PlAraoYSaQRYj8NQzY5dRbzpEnhmyPsBmgzcW1gLo067XcLiF0DJvlouezCyJW+Y9YA0fmJslQSYvcMhcI8mYdAfGDi1EoXoUiQYMnvlYq8J8ktBwLbIskG3FgeWvmoAFZE08E9APByPtLjDcHHan03Nwy7CPZqb6FtXLeHH6H4TK+WRnxyWWUCCGwQxVYXq0SDxaUvHuhZ4XUr7+Q1U42rlW6cND/0kiOhqZxe5qp/7PBom2IrcPdORh4lVv3RCQrIDCkHcBzCV+1WIwFeaxUaSDNJMmZ500JhDl+ECx+6dgbMAMTRPh+SxHxLd/OJMI9dD9eWQZMj4RwDxTbqlVp8cpoAEGPNvmweo2JApNndlNo1gDMJ++de+I8cKsyCdEsPfQ8ikJHY3R/UaPh/mPp8pQaKIBBP/nvMsT8jYMtdv59ejwQy6+/9dplr/mqdQCkRA4B/maZQ57aFmnsw8HZM9ukvo0Ni9KpUFM7iFAVdZy3NGVf8DX4J0jwAjd643HXH9I6+6dP2Jfs7ezsKz1T5yAHvocFPqxtbC3b6WrwrjPWf32N1a/qM1RiZdPyUNGE5ij+CTm9PUzcQxUcatfkjdDGnwRIAJMmmrtYVTBvCP+xUKuAp2UmXU9xfTYxlU6rdp5LyGQS9dHP0x7KBg+yOWNzECNEzMiCgE7gOqv+X75WA7D/sSBMaO52H6f4qtJovvnkwq4r67A/ByroGz4ctZ/wSVqTHti+gzlXIxgHKWr8VVq1HUFUCSRdZH3Q8PaR08vmQcapIQHpDRW13nUf7saKZh3N6R63lREJu04Ie+fQ8i7VUsNE4QclcrUsdj7eUxv5xtz7xrCEBDZooPT3RW8OM08MJ2Qe9sU6bdCvHTPE21OkEYFD1tWzWH7149QZPhOzkXIQ7qGdKQlmRvyOnd4uL20k58I3p/q9ktqLxBCy5s9Ac6PYODpXPLAelkYzhV3TcJAzxphaGjCmR8goNGJJWsqw3FOOCjGqWliL0JmW23Xo4emXDMUU50N9Ru8dM6NBIs6o8Hy3YcM2dj4t5RwlVejQhCn9gwtm742VYEdCEYKq+8FJtp49Xm01KPOtgTyFN0lF+HOQG6LCrIBY8cXRQtkck1aTvxD+KmKoVxp09guujaDutV+eyhyb5dYSytjq2ptL1FsYHLS14Xa+GW6DEvniGGnCzP2LTzntbqIVzx3J6F7gquTfsiDTTPkIijyYxWvkSseJc=","layer_level":1},{"id":"f70f5d9b-d7c7-4dc6-b36a-5f4508e6acaa","repo_id":"1095f823-f6f5-4e66-9aad-9f0b5b6b99d1","name":"系统架构","description":"system-architecture","prompt":"为GEO项目创建系统架构文档。描述整体的分层架构设计,包括表现层(Next.js前端)、业务逻辑层(FastAPI后端)、数据访问层(SQLAlchemy ORM)和基础设施层(Docker容器)。详细说明核心组件之间的交互关系,如前端通过API与后端通信、后端通过工作器调用AI平台、数据库存储业务数据等。解释数据流向和处理流程,从用户请求到AI平台查询再到结果返回的完整链路。介绍关键的设计模式,如适配器模式用于AI平台集成、依赖注入用于服务管理等。提供系统拓扑图和组件关系图,帮助开发者理解系统的整体结构和各部分职责。","parent_id":"1bb55e12-24c4-42cb-8f59-ddc303460d45","order":2,"progress_status":"completed","dependent_files":"backend/app/main.py,backend/app/database.py,docker-compose.yml,backend/app/workers/scheduler.py","gmt_create":"2026-04-22T18:57:13.329904+08:00","gmt_modified":"2026-04-22T19:15:17.452724+08:00","raw_data":"WikiEncrypted:gWB8HBj+8+/15rQhXgtMjCy7qJxJBEw3w9EAqc5Otte14+SfcEK3DSbmZRhW2TgD6BlsxDXHpLcSijck/Nymh09xxwlFe9hXY5fsIsj1IZW9egIbof/vmRQ/HkxJSvNy7WDeHEuuU7TDae+7kls5UELL0/oUUiCC4fjizzoaOlqMuOvW/DImO8fA0xbQ2wAt6L3bqB1pcGWvnB10d6EKKhQYmUj8xv/2M3cUBtDMkUdyKbAuduBIInt+jZnOGnXKcr1w3W66u8elz0iqgWhMCsMFd54QokMhn1Uyguz3NcIfEVH6IlKil0ufINdb2d/QV+9aukLvJ4Mq4YDlUjQ2iJ8oxAYYUb8eIjBnsLHPfBnMUyXVAo0tbyNB7wUmRb/L1VR7ipOMMKd9mEohzKGpsTxHpM8my7x8Ryc9N1guO/H766qiiNij1HNCu4rWVW12oeTTjAoEKdLzLyn59Fc4QjYVkS/I+r/lwRtMNN0OGjWXGXea+HUaIHwW1088PW3eZj3FlyGEsTiYb6ysJAWanY2qoIhASm31o8s9DekhdxTRbWeBCNzGN2ufTYGM9ygKNDHF5dCbVW0/Vtc6FC/TDiflhIaDY44Gvuu84O4l7SRBl0jKM8uCFHOgx/NzDlnUdNFaSOdjUBxQ7vVyi0Q5X6P4H/ERPzJQvOa0gmXW7S1ry0P4/CRjOCzq0Afw+mAf2j4PHM/4MWFkvrFkycbEkHWoWnPY+DWYI00TVSdTWjj4n4l9wbj1XDhXavLdg00qHVjv0dTq1ghcZKv3C04T5MfvVQjMXCKPQaK0KzwZDfXydWnlyLPgM8t95lTETMkjjEpIMtiv2w1gJda4ChFrJq27oPmVlEoVzGPuuk2B4YN3z6A5y3ehJpejis1/EuBjd0vXHhwghZeUv8mMD4smRPUMA8GcEeKVs9TQgBHqVuuVDdEAQfE7w1ILarmq3trYAuc+LH1KMUyPD0aZEbhKZdMRkFYWLhfyYeuazm9SfO1BqtEuTVoAXdLD86TCQNmxxTZPgU9OB9JluopAMt1oszBwKK/88UqwBqgUZle95RTKVR6QPn7zAGZaDbfsbYvsGUfNBSH08o6nnraxB0Vpj+r6WaoZLCcxhqSWoTp60YlMt7BDsla0Lt8r6D+a89AtCqZOHLJbrEx6T4wsmiykEi1uC/9XhtcsTHuytq/rHeDWR/bTToB+mGjBipoGscvIFMgUJonYCOjLDyBPGpeWispYZV21bIJQtFIYv06NKYU/IV9ZISLel9AttowTEXv/Y/U1xRtmaTp3BgGI4iRdwXYMJICv7Jyr5kYd2CrLJQPzEBdkJi7+q3WNdTCWBPd3B3hL/tTL2lFNDOc1sqMga78PcdWWHQfheORW9OfH3cDRiq85LJziojysfwkQVqHY7niPkDyphAwn9F2xZZl9ZfahAaU07CgK26wyavgkYOAU0dlWI6WrAKE2gQOzOxBL","layer_level":1},{"id":"816a2805-76c9-4f32-a3cf-96428208081e","repo_id":"1095f823-f6f5-4e66-9aad-9f0b5b6b99d1","name":"数据模型","description":"data-models","prompt":"创建GEO项目数据模型文档。详细说明SQLAlchemy ORM模型的实现,包括模型类定义、字段映射和关系配置。文档化每个模型的属性、方法和业务逻辑。解释模型之间的关系映射,包括级联操作和外键约束。说明模型的序列化、反序列化和数据验证机制。包含模型的生命周期管理、事件钩子和自定义行为。提供模型使用示例和最佳实践指南。","parent_id":"243a1a45-d31f-405e-a3b9-694d2fe617d5","order":2,"progress_status":"completed","dependent_files":"backend/app/models/user.py,backend/app/models/query.py,backend/app/models/citation_record.py,backend/app/models/query_task.py,backend/app/models/subscription.py,backend/app/models/__init__.py","gmt_create":"2026-04-22T18:57:14.161024+08:00","gmt_modified":"2026-04-23T15:21:46.785144+08:00","raw_data":"WikiEncrypted:Zb5TNaG1u/mRrgPr+sDyCr47uD+4y/GruMCqF9C9nxStxKZi2OWvk4ViC2NJmWUO/Jxugi7iel+AeINiHAz9c7erlmOh78DEPvZI5zcQaIYzm9l0e6yLGbMS64gON4GYqx4TUizeLGAIntFG405vTATENZMylmwR0jTbWx2uP/KlAPch72o8TGREvPTy7FGikY773VIwNZq0MXKYxjbwvld1ADWYjtxMoKmZ7pixx5LeZM3O+bfisD7UTqLobS2VvR5Ic2ynsAkEEzef+Rh5O85TXra/uluSuAOST9W65TENzfEzwHe+CNAQmUp47/vG6d7I14WPEipc0/aKbh43AhJkclnRjpR0bYFPJrW/HuN6chk1uhxzBK9sKpOUOLZ5MffdIttkTAOz4Ny5MxnUwt0zj4hDsVOevpasy4FZ/3pVx07fb7SlIDC18p+OUYQIk9JqBxZmgeMslhOBSkmRTAwqir6PN/GuLEeeC0mPlAMNhsvDrklfLlJmLY8MuSQHqteqYJryoZ1cp1yeqxATnDfeigUr8eSSaFqZc5S/AlgSIrvr+7XJWk/Oz0wKPLRXNUcG9yDweys2pdDb/hV5hiTmLYjgvYvnDLMMjrFgR6Fogz3U5ItD0xLC3lt09GJfm8jhS9E4AJd36iPN2WMeHsM0ctdvzYB/MKtWIIrBkWuRD7CZeGJepiGO/GJprp9HK9m+APjZQ4oc5d43tgDModdepglAEgNklY7IzUAPW0Qls3DhfUUHq/Zuf5AxAfUAAg1JOW2qEQWV+btkeoRPEiHjZXFDLGsC226d9yUlnYcTkFOeVbL2gomt13MPt6c4EQ3y4BSoG1CYqO0q6IgkX6a4g9QE7OKjdE3RX8rNGixxNJzfx3oeGtcne/lDvhO9/U5SlpNgbkkemAIPu+eZw1zMpknFdRwUdwOwgyVNxR/tt9AEktJ2gcaxRGfG3xTSa0JHoniO9otA8VI+Paw/il8qAI4Z1kf2w+L8LavGt05hchhlzWcrGbBjXF/VkCoYxFvM6JX9FafcLjoT3FtVTSorVysHodJyR1nHB1TL6/SH9v5IZMlZeQ6/Gm87g4SquVaVgvEBMuFPA6c7BBhWUqGw48UIBxfB3Ri4l8HYfRBiqrPSIuldaD+xTVL8F5XsVhczS4JXDnX3RLtvjOuBZRcejVO0ubg+syCfBhf+6CtYOyDTTQDGgwdiNg0MjJnmjy5TMmMdynOGSm2oF6wS+tUuWG8lMMBtredaLHdyVb455+OY2oQ5hJZGo7eyzchNabr+Xous+Ve/4cM2FOoHdQ==","layer_level":1},{"id":"64cbb894-755f-47b5-854e-c26c7821e9b2","repo_id":"1095f823-f6f5-4e66-9aad-9f0b5b6b99d1","name":"文心平台集成","description":"wenxin-platform-integration","prompt":"创建文心平台集成的详细文档。详细说明文心平台适配器的实现,包括API调用封装和HTTP请求处理。文档化请求参数构建,包括关键词处理、请求头设置和认证机制。解释响应解析逻辑,包括JSON数据提取、错误码处理和异常情况处理。说明配置管理机制,包括API密钥管理、请求超时设置和重试配置。提供文心平台API调用的具体示例和错误处理方案。包含安全注意事项和最佳实践建议。","parent_id":"7e66719b-4a8a-484d-889d-10fdc76788bb","order":2,"progress_status":"completed","dependent_files":"backend/app/workers/platforms/wenxin.py","gmt_create":"2026-04-22T18:57:14.59287+08:00","gmt_modified":"2026-04-23T20:31:50.506814+08:00","raw_data":"WikiEncrypted:2Sm2Oxxfu6PsmMr2pZflRJ0uQ9gYQuPnIUHmJotOVM3YPmWq0HSDTQGvIE8WdDGtHlaemWXQzS6Ra6mdo6lkRL4Slh8EfpKUg4wigWPN0r3GaSXHkkAIs0wgET5OjWqYvTL1QooFFzxPhX1ZTdHcTpcp7CVvRNSVGiTu93qzZloeLF1EwOxsLvQ8hFf9SuWGjeOUYDGh7ktNwrMbeUIV32VkQlqsqQ1HqoKoqjAh2d6Xou7+peaCdxzJOhMf14e/vNiC12p6PfM2oyBY8gR9sMPKd1zgEepWsc+ePSazz3RO+zy9fbc5pJTLZdtswhL0xGhZKuYgYlctRId70DLeyiJHlvEQzEE8KB7QJqULfiB4lgMO84A+DhPeslR4F9Edbm+5P11/ycz4y8kzZQwnt5F4iIOC7HOPRSdGTYTxO53cEcqSfBI/wH7enb6Zt49h8mK4UyYW0fUuKBE7dPAjxC6IxbdabWdu8WefhxUR1oFx6BkdGWLLmj9ZOLMReTwnsJdK5xmoA8wQvV8MMlYiCgBuPj7mYce5s5hpglFxtJdEeDq6P2Mtusvj9uegGeFmCJSn1nbBhJr2r+WxLk/WpDO5lwhggW6V/wdvqcmRvaGHCFspVdzbC2qx104c8i+2wum6kMLHVTGAM9kTy4M5vHtvBELFl/qfldVQ8BK9hUvE9jdUbNQkoiBwFpPt2NNFYvz94CAxqbObxiZ7C1VhKWPH2AMX330wwjiHjh0eshve8e+pjBsDeM4/nTh3PH0P2XNUsomNEDxCQpXG7qngeiMXljTWmyGsLk56SzHFqfCgQX8fLlxv3PzSHXpCkAdymDxnJlcuK6WZIMj0AjQydGVSLgItD0boSI0YfvyDXhrO57OoFuwUU5Enq0do/w+quy8Qt0Qc9Q0afMg0GVUksiDfURVugssB75pqSqdNSrJy3wxM+kSBndgaiKYIakZ1idHkzpiGUshjyAr3V8/N1vW7VGyY2wnoquEclltaRAO6V+O8ymywFWL+/RrPEn4DKy8ul6EmHuryCQh1dfEPk5ZAgYg1K9ecbb2dLwTfMgXIhD/ar0ZfRO5OdwADW376","layer_level":1},{"id":"412f8cb5-54c1-4f32-8966-fa0e5e75bbca","repo_id":"1095f823-f6f5-4e66-9aad-9f0b5b6b99d1","name":"性能优化","description":"performance-optimization","prompt":"创建性能优化的详细文档。解释调度系统的性能瓶颈识别和优化策略,包括并发控制、资源管理和内存优化。详细说明异步任务的并发限制、数据库连接池配置和事件循环优化。文档化调度频率调优、批量处理策略和缓存机制。提供性能监控指标、基准测试方法和性能分析工具使用指南。包含实际的性能优化案例、配置参数调整和故障排查技巧。说明如何在高负载情况下保持系统的稳定性和响应性。","parent_id":"7416db23-312f-478d-8883-2fc3c41ac2e8","order":2,"progress_status":"completed","dependent_files":"backend/app/workers/scheduler.py","gmt_create":"2026-04-22T18:57:25.383759+08:00","gmt_modified":"2026-04-22T19:16:37.81704+08:00","raw_data":"WikiEncrypted:9uOBpMbLX4DyZqW4us3Wm3Q7klXxmeD+JMMoGiSO2oNryWBo1gw9kLkawvxQIW9CASZSiyAjiA/zeT5DwD4S8PDqEsVNE73i6DrCAWvPET3MMPQasVfJTaLge2tk6gbYlx3R6JKZcUoi06jS7okoLDzJAFru3F6zguqySliKZSG/00oFVcDHXlZZc0L7hiq11k1jOD8uBl6n35lAvst/AgFv9MUzrhf43XDwtHiMAxjCAkwKnrWOow44Lwzy5fG3nWKZLSHE3/CUmZ17U3GmEqfG43ai1yloAkMou+sTRIk73sRdXPDze0HhNdNfNXTaOHTxW0gT2TwKGHgG9Jt0Y+1qWq4Nxj/oJTP/hztBLy5SEPndXXqeZTkBaesRTr0adQv49fH0QoFV6D6dxlEOodMiFhvvYd1rvR+HwbQbqU3W5UDVnKfPlMXHsz0a9NPu4aGgk5yevh/s0AP/v2R8mgz3N41lETHxk6Q71f35L04S7u7P6MlorIwKzkeijhFf8sPrChMYX7dwf8dWba+Nwm6fgb+9AbSZ4VczhQInnbiv+GUKiFnezNVSHUUXqTCvRIuhF52jqnOqjPei/1oeS7xAMmB67o3v2so8T17xg94F9FoEl2XuuwA+RFDarVZKACDTPxjt70OXdAoxoERTZ3ivU93OANsuuWx1x0HgFdBj0q6seNC8cbySc3ZuQBWGu1YWMmyIYGL5l6L7CNSmkkl9/pkb1TSfkyM+Hk3VLXy8VIvtgHxGX2OU8yX1nX0DCGS9Yt3dK17lAVH2XF2mo39noQPG2nxjOc+lO/O9cL/CC1Bqzd51YLHapcRLPPbuaMT4ljyLvQ3GMvKHB6c0sjdaKjykN96LhXpO5PAqs3N2edkVKVMC6lg5fTBMZi6B8r4rup3M9CPDs4ehmVYTtnZpt5zKxyXP8QfTO1FfDyNQRpbXj8TyLOwwqEFvZPQlV7Iupj3lpi6crQhtpXBtU9M+vjP31rOrdFpBHXCckE4T9QryVWvQuNDjsc1+tYKLgF6S8ixDQFCHEAfzctdMM3iiLCeBy1szBZEZTE+OS0ERSbgqusmZBkz3ouKp6suUgXLJp3Kystu+dAVWhA6BAD2WHT76h+Hbazixj8F2qAoxmUb+P8Z7u0grbWJksg6u","layer_level":1},{"id":"40ac97e8-7ef0-4198-82d7-d2e332be9d34","repo_id":"1095f823-f6f5-4e66-9aad-9f0b5b6b99d1","name":"测试最佳实践","description":"test-best-practices","prompt":"创建GEO项目测试最佳实践的指导文档。详细说明测试代码的编写规范,包括命名约定、测试结构和注释标准。文档化测试覆盖率的要求和测量方法,包括行覆盖率、分支覆盖率和功能覆盖率。说明持续集成配置,包括GitHub Actions或类似CI/CD工具的设置。提供测试调试技巧,包括pytest调试选项、日志配置和错误排查方法。包含测试环境管理、测试数据管理和测试报告生成的实践指南。","parent_id":"fc6f24c3-594e-4153-854f-19250834eeb1","order":2,"progress_status":"completed","dependent_files":"tests/conftest.py,.pytest_cache/,backend/app/config.py","gmt_create":"2026-04-22T18:57:25.616954+08:00","gmt_modified":"2026-04-22T19:17:48.81542+08:00","raw_data":"WikiEncrypted:3lrOgsvw7LaJXRS/Bz00iEsb4RzJUAxxpmqaBblS/51b52WVRQtf4YGBQ9MC2MYcYNyKxRGZljd03HKmm078aoRU+suxjG3HIqwkvM6ruyPxwlLdBEn6ogbrhm8eOKuGWjiEso+PrOqSXW0boT4qGE+/L4MkPiyeOB9YnDB49/ByvDHsjeesTQqGwpa9FmIQtVqpqDZA3Sx+x8TB+MSqT5PMZ4egRgCW1ODcidZrTriWvseFNQDFLzo8g2H/HF5CFLcVsZVK+kWI7b7oWLmNlIKz2SyVJuYqvCblPzw+/773Wv4RVHYdK/pxISCon/L1KjPyfZjddr5sDjJO7rNFbBshPxUIQhtXnnAEqLOpzZwHm2a0bA3vSR42bZZoSAY0v3aZxXQ5IvxNT/aNAmiFzd4SkTlz0okDXnBsArnOUpLLRfjLhxt5ueRUi9Dl2edsdycd6XznT6/oAUHTf05zhhKC6JR1OsKiFQyoo0il7LYjDxXJM0dZycDlENYwZ3Bd/82Qr+7VNmgpLdnB/7z9DPG9iou6TIpztKrdSRYqWBcl75qs2L/R2Sy6MOyfSwALTRUi5udf8sNlsHOk5y2qY0h7vd1GzYwtxKQ63ypJLL/8fAcPKmH3FCwKvrN3zuEu0Meyq+y2v8eYeXNozeOa2zum6fI5sw7hnzX9Jqy7fyQD2yBFqyylQ1ZW3nwFd9liZLnWfm7zbLDlqSgzGYGxvNIe0X2rhwsthMZTLEXOZVDW1/NqHg2E9qXOfg7XhQRHKZz6Wu8eZ6MGyCvq6ft2SJI2vltHD0M4somneHGSMo4jKY8rMeGl7qkW1V7aaurBnh0xp6cOJ25IdbN4VEDYm1Oj5nlM4wnEQzWiVyEqA+3oU2k2k9Plm/xs6g846/lBJxHL9ztsKmm0BnrUFR1ttgTVRAFvHpfkmSgLGGB/9824DJpxXMiWnExCaZzWbFYPhXnDF6Kh3SB6P3NyVwVdC9/pkf4/UQ4Em3rvbVuWICjGSScoDtOu5MrHDaUSbtN/XtqOptA1ApGbnTSKxOm0KAck4ApFPdk6aRLdC4eRf9XWsWUaOFjkqAoU0Kp035pHaGrCrx4KmgoKBNFNbS55CA==","layer_level":1},{"id":"41a414d2-e13a-497c-8a03-212624dbf5fe","repo_id":"1095f823-f6f5-4e66-9aad-9f0b5b6b99d1","name":"引用数据接口","description":"citations-api","prompt":"创建引用数据查询和分析的完整API文档。详细记录引用数据的查询接口、统计分析功能和上下文提取机制。说明引用检测结果的数据结构、置信度评分和品牌识别算法。文档化引用趋势分析、平台对比和竞争品牌识别的API端点。包含数据过滤、排序和分页查询的参数说明。提供引用数据可视化和报告生成功能的接口使用指南。","parent_id":"dd12cc44-0c95-45d5-a726-e7b8bcf2531b","order":2,"progress_status":"completed","dependent_files":"backend/app/api/citations.py,backend/app/schemas/citation.py,backend/app/models/citation_record.py","gmt_create":"2026-04-22T18:57:37.836961+08:00","gmt_modified":"2026-04-22T19:18:18.055339+08:00","raw_data":"WikiEncrypted:qByx+WzXalKNnda2aYUs+Mi+kQm14b3+m7dy1helFRbYWzECOnPEzHl0ufCZlQvKjQqSxHIwqppPXSdvXYc/8Z7buvJqBV/Q/faiP/SBsAH3RrfF2Ppti6QanNvcAtBLcojqJkmfYWFej1OYdagzBcSAu0xIIA7qBG1LwkdNG8crxSwebM8is42SnI+aRvlbF4UdAqHHPdfUvnzs7zIODnildIoR60AvLFeNEWO4prQkFyS16p1YH96SousrFgBu2YZZYrNOOhDXyrRoW3TE6990oaIi3Xe0B7jFtC4pce8JamwzT8B33FAJ6utCOBMUkFKq6l0kD5rN2owZaBtGc4Q66Xcb62y3arqrvxcgE1ox1nAp2D9pNqRy3W1ePW2fWZk4+3co4z2+ANQ1JO8q5eAFI6Q6zG7hM4rvNlL07iD+hZeqd5+vGw0KmjkN4VMqJC5ypFf5UCF4qHgB6TS9ToQUAWk6HWlwBR1DVpCcK1kyGcunn6EiivJyjJLRYUXI66AmajxIzRHtyhxBnA5Q4hZNgr40jHMoUbWHmiQTQr7Ca4/VDS2V5FWlm6K1fN8xWRIUCI3VtH0A/wG+QBnJmF5YeqDZ37Nx9vkiaO+hutXsGHsjwj8+IZO/gpn6UT6QpOGaeqGl37HW+lMZSRUqFFaLg7jxlzSa3IliOyZI7N6xjFFFTrLV1ShVsDcWDg4eXL2IjJ7QfXjmD0vq5mH8mkZK6HbhpNH5kFXDuMYWPIHAXUk39ttNvut9r22RLpkXYWtxE7XoqXW+k+Edmt2eNvZImq/e7mUwa82Cae86WiRtz7B7TJeOf96EvN6EQBg8E8KT5Ckd1exHhFtySkw3tYfChBZfD75zY7tUcZcC+McO1Kf0ORqTZtnNjVnot7wirysiS6WKQ3O2L0CeBUUV7DlmFd8xAgJ8YhtHJKulJ2B0yCCswfb+PR6u9GKFVK1EcspZe5BsT22vlhQyAJxlqiAi9xRk+XaCWoUT5ymT+KMOXdLoB4EvD2ftgXy5GMxZIK2q1QtLAYEu7nOBsq2aNAg9i9IsVJ6OlCN7VMzDinzkoC1IAWKxKE67ZeLq/VfPmCqLKGl0z1JfkfC/kU8KFA==","layer_level":1},{"id":"2f7fa0ab-cd3d-4f45-a1c1-389d5a0c2561","repo_id":"1095f823-f6f5-4e66-9aad-9f0b5b6b99d1","name":"开发工具","description":"development-tools","prompt":"创建GEO项目开发工具使用文档。详细说明IDE配置和推荐插件,包括VS Code配置、Python和TypeScript扩展。文档化调试工具的使用方法,包括断点调试、日志分析和性能分析。说明开发辅助工具,如API测试工具、数据库管理工具和Docker容器管理。提供命令行工具和脚本的使用指南。包含开发环境的优化配置和故障排查方法。","parent_id":"2148d7d6-25c4-497f-8894-c4eb7a0d2bd7","order":2,"progress_status":"completed","dependent_files":"frontend/tsconfig.json,frontend/tailwind.config.ts,backend/requirements.txt,frontend/.eslintrc.json","gmt_create":"2026-04-22T18:57:39.374817+08:00","gmt_modified":"2026-04-22T19:17:43.353691+08:00","raw_data":"WikiEncrypted:F3QgleoEfoy16cQggYe9CzRj7niAsR4WPU/tuSJ2vBrZ49vjzLlsqusYQAR0/FVC/Mfa58hrglY/tUSn8LBYDGZlVr/UyLd9/U09SEPTjzLPzOXWOffceGYhaM8E9Cx6c+FHZRQ0fYUDQXxWM6dQF6WQbUmiZISlUpgtOkT5wX0oc/n1YeDUxEpgiCWnOdIBH6SDoRDdGUFrWdqF66bEdplp0Yy3VYVBKKwUy1XVXtLbdv1T5/0TVJO7EtkHdoheIwKCPIYHsaJqBv4U8cMNegSJ1Ti8bsgUakd6FM/X0ybfTay+IyTIqYXj/dS0tWMm22zjLqYmw59+s8gJ7AlgwXhqYhM5Ycwh/PNrDHHFbgQdt45DjAaMWjrjXrbIvM+kXuSiwxW0dEvQtouckPTVohVcRWEPbg2o02/8Y5DzmxpceOC7KgybfaaCQeJHbg9C91itVc+0NvorhivJt105EYs1ndSOla9hoFppywKIbIM61cvqgHjsJF5DrN1pneGmTtYxijl3J/QpJHn5QuIBR8ugoHdJ3EVjUR38vQReVBeDxI/VMe8k/l3EI/Zk7paXexGeTrJmmnZI1I6WbPN1TPS4nLFZWwkA5ZA7wMkdHiHdnt/FZGccFyq8X9Okog2xv6uqH6Kwz3hseWlrSygNPzDr0cFj2EQqDH7+xZDEkAvTuFLHn+HzUfBv0vfZFa/FRg+5/agC9EcMHM+75jEvtSeeHXHOLpuuFcyOcZ0IQP99QdzSEsLaISCINs5SKkzKAMQnJv4PEDo/vFAKBulCSqjXmLeyhcKmCGqafN7IMWUWF5pmZuXe7wL1F6n+x3+RvScmsWND74hQhn0/Sn8kpFHJ5xV/5t0GDZxWybDFRRuFC8oImKyB+6h8CstsERuFeiIjMv2TS5lz8+eb1/yCUkGO9X5mUpJZXfZ+0vu2SkEN3WR92tM5Di/78rDlulwZ4oykT8NzYMTzpX4WlgUfazNKLyIhSoFZcWUyOFcU8IWCoOdrBFn5CSpe0VXbOlP3pAU1Lz6Y016JUHo1t1YE9xU/m7OTxhMexA8jCoSswgGT+Cjs9u+KP1ji2RSyZHQ6","layer_level":1},{"id":"2713d5c6-c6b0-4a38-83f6-56940c2bf695","repo_id":"1095f823-f6f5-4e66-9aad-9f0b5b6b99d1","name":"监控与日志管理","description":"monitoring-logging","prompt":"创建GEO项目监控与日志管理的完整方案。说明应用健康检查的实现,包括服务可用性监控、响应时间监控和错误率统计。文档化日志收集和管理策略,包括结构化日志格式、日志轮转和存储策略。详细解释错误追踪机制,包括异常捕获、堆栈跟踪和告警通知。提供性能监控指标,包括CPU使用率、内存占用、数据库连接数和API响应时间。说明监控工具的选择和配置,如Prometheus、Grafana或云监控服务。包含日志分析和故障诊断的最佳实践。","parent_id":"803bfef4-3985-477e-a61c-915a246d0061","order":2,"progress_status":"completed","dependent_files":"docker-compose.yml,backend/app/main.py,frontend/app/layout.tsx","gmt_create":"2026-04-22T18:57:40.355514+08:00","gmt_modified":"2026-04-22T19:18:41.773778+08:00","raw_data":"WikiEncrypted:HL3VqGjXq8A3aGeLxAjVPg+lnGgkT5PNghnzp51sgLDjuJwvzPZp6KDp64sXTqk/PvlUYRCEe6pgM8WKdtus6ThN6y8bzS650UmrWXRgW48k0tbm2PEPd8NIqpzEYwRwyuzLECVz8rV+mgvy+OHzvrt+wEQeT7z1uljirnxeLZWJjIrFBr8Q1T8WQ9InM3Ttnvm7OYO+YH2Mqi6IC38bW7w4WGqApS+Byn7/ZrJhR3B/XWh91FPwq0GRUJ9cqrNuIcYtnWAfVIHWOe3iET8Jw+Un5x7ZRepcJlINGIIMBE2hO7UsbC/K3z8rkz7mx6uoPTPpxkKkgoQQ1OAsShE/wpHpRYSOJEnV26GFo4bXBTk6xJYw7daKnJVIYDSqSrtJQI4yPlTR0OtJescXSLobznoVSBo+L+PU/nRvotp5KzX0SUpbkqNzGychqcBuJhpS1eaEP0cTBjvjC4MJ5Lsye51X6aOdYYC7tBWHxtgBO93tkpcIRlHk8Dfmzh8nKcD0rPHYGnaeFpzXgGH7ZfabAwxiMhej6OXWsfnbHGg4gheWhXfokxCMKkFnzrsYcuFtB0BqUeadjP5LArbJJGeyVEZovmPxtzQ5z/ayxJs+oyc0oH2SMXCFtIQv2h03ZSOCkohVRs2oTJnMI2p41dY59B5qiSOp+0qwxTWL9NnpqM2gjlLZhcgwF//R7ag4ndECWejInOcA9Ayvx6cPAuH6uEoFTcUOCLaOZ/u9T8890S5KHS7PcNM8dEewoFviz/mRiernAhd08l7a9lR6zck842Ywi5H8+fuuHyt64Pwco/+52MhD01pkK+HWSR0EqPc8URlkOKjQSW0jd8E/9ow54aZA0+1Vto3d+Lqi/tAOlhRF34rIJgTEN3f/udCEVycON9KNtssYzZVNPdvTkvzPYdUHIcnYmz3jbQhnYnrYvuaWNvO0cPISLZI9szxLP8IhmUc9xT4U3OvoRfFka8TABGicEUAF6vpH6H2rCqnWdBydaTpRTa3VAR7QJ+M0aPlzeKov93eljMa/djYoQo+w8Rm3A9vGmGXJKfWdZobh+fQgc38Z/0yRCHnIPnY8o6CDBfwbANfjDRpjyVkqWq1cuqYNnMul/jpzDS9vMSbMnefISRuF0kH8XS5C7pIB+WFn1vxeYFBYED7ZI4FD9pxxS6GWGcYOXEoFcqtR+lEiMdj0Q09jo1nEuMKJbPQre/RG08O0boFCzF9KOSnS0UA09/82vFQyQZKHNwpz7OkZZa2cX5X1L/pdsDlDRoIdp2lzyAEOidStaIWywEj11EYVNbG7sK562p96Sr15ueIXP0s=","layer_level":1},{"id":"c8a468af-2982-4d9c-82c0-313b5d2ee89c","repo_id":"1095f823-f6f5-4e66-9aad-9f0b5b6b99d1","name":"第三方集成","description":"third-party-integration","prompt":"创建GEO项目第三方集成的详细指南。说明新AI平台接入的完整流程,包括适配器接口实现、平台认证配置和查询逻辑适配。详细介绍新数据库支持的集成方法,包括SQLAlchemy模型扩展、迁移脚本编写和连接配置。文档化新认证方式的集成步骤,包括OAuth提供商配置、JWT令牌处理和权限系统扩展。提供插件系统的使用指南,包括插件注册机制、生命周期管理和错误处理。包含具体的集成示例和常见问题解决方案。","parent_id":"b2bb2e3c-5661-497c-97dd-15bf6ee8b7d4","order":2,"progress_status":"completed","dependent_files":"backend/app/workers/platforms/base.py,backend/app/workers/platforms/kimi.py,backend/app/workers/platforms/wenxin.py,backend/app/services/auth.py","gmt_create":"2026-04-22T18:57:48.68499+08:00","gmt_modified":"2026-04-22T19:19:17.361215+08:00","raw_data":"WikiEncrypted:WxCGFGSl9zR6IDeUdkqKNACFcGLyx5HNn0UQzHtkOJVoVN2BLrMtPbbNkfhYYzEQGaeK3o4fBODff6YTXKxAV6HYhCHjmdXJqBaBsEPBB205lzDAllfBZL4/6ljz+/HZSgaWAxPECD1m2GUFvjlKHTSXEb0x5iVOg9R3VDjYQgKl1SF3S/AuJj7QBbGiwmkyPrqO8+NXDlKH7pI3G6me5ulZrK6M85KSH8nVAnqY/Mvjc6UGQJBwS1QyKJVzzK2JwKGhQSSLemxD887b22bSe7q1IEDRYcpqkbfyICB0zF1Gg1h/cAfQgzjiG0+MQiC5CF3QwkFteFbN4KZDEjCTcbIR+HqI+yCs8Wue/MwdoTYQQKpR9FyClONZn5T/UqHQaVT8SemYF0QC/kawyEZFH5Tkj/6RwS+taTWw1fx2QC69xQlW04ManahzsBDwfz2W4RkufM3ZfW8HAN7SorY7oYr1Vam2p2u/93jzHmi7PO/Y6VphQNACzUlfRYsPALVBkiqpN4TIiicrjOvhgATUxqpku2MrAtbXTkiuiiQBamK/XrF4JNlh+79VGoHKWniah1nvo+dzl7jll4j0woKwWKIzmfPXLS68HekW9h5BH9SUeuyAEW/pvnGAUw8Od3CgsEmap86k42Tg9pRZC/sT9bCWUbjO6ijJ9IPAgWE6bkLCu68L2BD1yKE3gfLg0hJmELn79lHaFCUc5jlRdJ4HEsalAFGS62beLGkude98NvSY5pQoO9jbTj3Da8t6Yj8p97WtE73vmWW9Pu/YyAtxJH7Cdwvv9mbvLYVnLzUWGwsaiaXmDJiqfSHiOrHQNyonHQa8N/LYrbB8qBSUmLyBUhgI1YfYMa+zNfCaeHvRLlmVZpui5MOegWen1Z61WhPc6WoFYHyFAdgS7k21cC9jVay3u87SjSzooFT3MJjN+yMIjrQ5U+tVFbiBQK7IGPLFHRmvFBrBwSFVBI5VnCxn4piz7VBp7mm3e6N3CJUKShQWQT9tmUIRXLmmzsKTit/kRAUrycFjixIK8Hm4kSwtVBREbX3opXE6clXKGVB0bpSDUzB8Ae7wOPE8Gqo/ewy3kh2mdNnvI3+MfOOgPc+Ovqu3KGFBH/MYKl2xIUGdYtEHfHRCIFFVVknX8+Q+tfbkmo/Tw+kJfq67IQO6VT1WjP/q1G3rOhp0Ah5h1wmxVfdIaHSUOT03yQTBm/tqCXlgUW7rZbTc2wF0zdUUWleQoq9pc14c0F2SNFCSaQNLhxvfeC2aH8O9nuZi+kVb+GVV4vWcxcz/7dfTkXpogDwy6uqVHySe/TAn04uWlCabYSrA3ahnl0VpBmalBU1dtaTG5apgcCJ9PULyHWKf+iW0vle9pOVgZQ4oUv0vXxDpZQkO1SOBCfKG20swUEItxbAxIVoMowR52maIRnCKh3g18NF3JUZX2ptDny7A2gmsYWU=","layer_level":1},{"id":"d907a8eb-795c-4060-9cdd-50d31cf39be3","repo_id":"1095f823-f6f5-4e66-9aad-9f0b5b6b99d1","name":"前端系统架构","description":"frontend-architecture","prompt":"创建GEO前端系统的架构文档。详细说明基于Next.js 14的应用架构设计,包括App Router的页面组织、服务器组件和客户端组件的混合使用模式。文档化认证系统的前端实现,包括NextAuth.js集成、会话管理和路由保护机制。解释UI组件库的设计理念、组件复用策略和样式系统配置。说明数据获取策略、状态管理和错误处理机制。包含响应式设计、可访问性支持和性能优化方案。提供前端开发的最佳实践和代码组织规范。","order":3,"progress_status":"completed","dependent_files":"frontend/app/(auth)/forgot-password/page.tsx,frontend/app/(auth)/reset-password/page.tsx,frontend/app/(auth)/verify-email/page.tsx,frontend/app/(dashboard)/dashboard/admin/page.tsx,frontend/app/(dashboard)/dashboard/settings/page.tsx,frontend/lib/api.ts,frontend/lib/auth.ts,frontend/app/layout.tsx,frontend/components/,frontend/next.config.mjs,frontend/tailwind.config.ts","gmt_create":"2026-04-22T18:56:47.082624+08:00","gmt_modified":"2026-05-23T15:22:58.592252+08:00","raw_data":"WikiEncrypted:caZUAHH9Plb/hKq4968GAlxdfXo1OZ/T5bAEX+yDDFnwmkOIiMXkaH0ZIHauIC0wfdpuxtoUKmX43kiFQyTbPAtTiYEiDR6Tc0QitLHu+/t2EuUEwUv7xUQwEV4sW//IvEpbtqaL5pRUagOGJPFa99C4e52Nk9vZW1Kx2qPB4qhq5J3Yu0nD02qlXghyoNL0NJHwuCxv7EahSsg/DYFr7sH0a3S5ETkZqxe96N44pBOsBHzuIrVBbRVxAXK34mDFp06Mg6X+bx/FzcoakGVIQ2IA1/sQmnUSpwDxGqn3UvGx6xVk7KBPYjKthY6SgyELy3XXUvLqYYrMzXJIpLCJenAAXTvXsseT+uR3pZTNb8c8t6DMq8wmc/nSYKx0/o0eWgxwGCW7U/hzreWW7EG1vT6Wvls/+9iCH022pB7CS06DX6cdGv+wSYp0wvWU6q7c+JXjhvI3Tz9BouXfgOipLBXfzo1GPVD211oTxUEOthWdIsJ/xrK33RKfN0edxP363h7CV1jAUHsZPO0hLP6ZZRpC7kDuFps/PTY5k+15rMjKsA3p4d2gO79r8IJ+nN0PDwK0ncShwqlQ74k0G1vS9tFBnH9lhq/1UdozkYQsNxDa5+YN28fNiYVXPNLS7cqj61w7y6GbW1rL7QuJy4pTuPCl1lJrFqDN0xi2a3KM4l00HZ9qbBQPyC2zF3cSmK/bbd8R4rrwbXzSJKOHyb/7Uhx0mbARihsrOJ9s68hspwmIvznUBYnF+y0y27DfTemQ5/UpNlT/WzU1zwIk8xA0KX1bdYS+fdH/CRZH7axSnG0WcjwloudpfvLbXWzUGypiGhAvZSnTEATuWW/rp86QszDvxQXgB7N1OSJFUuOUE6vxX1nwr/YGFsk75EmWWRT/5l3BoNW5rsNqeaOLPCUIe7RFj4U2hiWsrhjyXXyMpm/dpjmAIgPnYGeaPQ6+3ndGg1ooLn2zeijt4pY+yaM0JWp5giDt8jr7YhAcLRW7ojqK8IAhk51K/khU5x0HFI/rUYBS3k7j6V0pkUQYziBrVpYavetotm9w6yw1tQrB4G9Pkh4/NGGjdJ9ZtPdoAhxwq/vFKRixUOxtOzPW+gjiBJx5aBFLlGh4OeNikZu8dkvi4o72oyn86HfoxqjayhfyKFjnAhLuk7u4H7UAw5+imyWFIuT10HE4ku7WESF+jU2I9KtomZm4+j88sEG1m/c2PAvqMWR/TbzgZdogHbPk99qTZ9/Gxa8sAEqijUgFeXZHhD6fT+Owl9unUBxIhv0T7zY7KJFcowSL9eOirUOnlOuZcqFUdFT1pE9B9MpnS+aAo4H68NaI+k/JsFne7qyToLEjzezrMiWggu4qPvxqH/1YvhZKbm99SeiGQ/fSWhVKN3kcpby3wdWau5I3Eg0DApusN4Z+nnZY3kwY8CbBAHbv6lx5XVCfA2tw9MHDPpiVaxmBdA5fWmu4HSnt0v0Vrb5r3R/ZVl9ERMQUne52UjUl3II1fMML4ZrZzOexAOnQ1WJ+zHyQjGkcBkU6xS0R8uOhu5xA3obBmqzzET2RslAFXre9XhksI9E/qhzxB5abhiKMV8vs5G8GNJ1rQ0nQq0M/BbL6Rz6is7oJWTf8pL91hYykA0bUMRKq60t6umP9XKaKzF31+7PIs18PRJQ8Rzji9jXk2GJ9TpT4sc9ty9XTBQg6Je/vhkN2SlkNbxA0RoiWRMA5QxA4fnjOxWOFdP7X8ugdY1SIyFHmAR+TiEiGbH6qjNqMQD+PTmmi+1s="},{"id":"9eee7fab-6cd9-4ef3-9415-2f8137f1d199","repo_id":"1095f823-f6f5-4e66-9aad-9f0b5b6b99d1","name":"数据模型设计","description":"data-models","prompt":"为GEO数据模型创建全面的设计文档。详细解释SQLAlchemy ORM模型定义,包括类结构设计、字段类型选择和关系映射。文档化用户模型(User),包括用户属性、权限字段和关联关系。说明查询模型(Query)的设计,包括查询参数、执行状态和时间戳字段。解释引用记录模型(CitationRecord),包括品牌信息、置信度评分和上下文数据。详细描述查询任务模型(QueryTask),包括调度状态、执行历史和错误信息。包含订阅模型(Subscription)的设计和用途。提供模型间关系图、索引策略和性能优化建议。说明数据验证规则和业务约束。","parent_id":"7c2ac186-ec90-400a-ac1d-b3b7ca2f01d5","order":3,"progress_status":"completed","dependent_files":"backend/app/models/user.py,backend/app/models/query.py,backend/app/models/citation_record.py,backend/app/models/query_task.py,backend/app/models/subscription.py","gmt_create":"2026-04-22T18:57:02.317816+08:00","gmt_modified":"2026-04-22T19:19:19.281909+08:00","raw_data":"WikiEncrypted:klcgW2PbPxJambbKMzvFtzxL0nPpsuPMPxr5hj83lS7k/WfePQWgQNKbEysjyVqFS8lXlJL069Py2sSf8yXxHJzOE+5qAqcKClz711a5h2iXkF0al3mIdEvPGsZtmu7Tz91D+nYN6P20/dGDD6jbfsmIRXLEv3fpccmaTd5XoNj9Y/QT7a0xg+LkG6A8bzQONV8mQsFJZMj512PXdrzG8bSiiAdWa7PEbotJVKJRklAdLNFr4FCsLXLsdS/G2RlAo97zi5J4mpx26Q7SGM1kx14TxsQYatCIUYP+iZ14NDPPPp8tQ+HGPLEonVbYiRiktzJo8Iaqbcsh59qHBoGZBndXEwalDBXzD3sIbYrhxlOU509HDe43hiq+M5eC2SEeTfGdYZ412t/aAJFPEfq3dRl0wa6Oiw4t4rox0s/f+rCg9Sr5yX/vsXrADGwowbhqt/EdTudfsdha7MXN3Kn9e9TckQ+HOqdgqW3+RnY3B08ijVPZchn/Y7XZvx8GujUHSuM3x7EDAXegqkPwkfR+hl4yb4BuuY5AC17g3hvn9yDvBN3m/Ky7mJ4Q9qvXfFaUqDE/FxwPWjugAnVOgAmWns1elVLUS/2nol2BUAuyt1w821y7+N79TkQ07amTWILYvO7I/5v6hStaHk5+ftwpaWSLofuk3Nwbuab8ULq6lj/Tz3uWkEg5/nIIYGVDSN2y9JKgkNta0J9Y4C25DpKnPb2HPfbnD/315IEyxKddS9DpOHC92uT3Ad5v/X0LgVsefqUUep4D2mVUeevDE2o9NuUqYyWYu16AL2UaQOWH86Q97+Accmt37g5580pjdVyzcgVL6Lat1P4W42Nk0vOIncIdM8Bt+iWUIOjmIWDK6nUytRrluJ6RAGeewol6Eb8eMy65WkJ8SsDWFj936G3imq6uoKEsmn9kHznKIfsvt/p4IAv+IbkliuuV7/VNQdN4jgfgKyRp8b4aQd35Qrv1ypuTdf2HQS3w/t3nb8hBriaZZc8a93LekZYaGpvrws/aq3ESXMU+csJKfWhEGhH4VT4cjy6j+jHgihUuUWhO1X/Kpm8iseqreG85CZeU9woTd/nPIayXO14kUEfNVL1ih3p7GtsFGDYpr4EcPU7JpPp61gLhfdpHydKVDLW4eaaCuTR4REP2Vs2BxiwN8GCpJcCbpPeF52n9qB1DE3uIVBITabqC0jiIHeVfb8caysKpddelqqLNn4GGL7BeUFq4RKhlVTmCGuBRWABBDEhDRHXsScje6Av8bOxE/QFVlZmFE8EkDM/WhG9hB5BQ+8u4pKPxsL3/n7xyMyrBnO2n+nTEGscgwlEnpxknYpBTrtZQgU5YB8KRGG+VnvSlbM95vPmdiXS5y7JM9ftKUbdxgnxOVrM2ydbK+5IGvaNB27szvHBbvqtxiY8lXfLRhMYcQEIcD0AM4Xl1qH90xIrHF3lHogdPgwXR/UWGRDWDXKVUEXGRLQHTlRTCJ2oRBGig4FvIztUbBVqouwtJBqoGXoMET7JbuNkxdHs7pfsL8sV5FksVAyNxvV7rRG5QAMaIvUMdDT+XAhtcrNagCHcb53sPxuz9ldlj9adP1H+FxOw7","layer_level":1},{"id":"d9e45b2a-6443-4a9b-8ed3-4c3c04773772","repo_id":"1095f823-f6f5-4e66-9aad-9f0b5b6b99d1","name":"UI组件库","description":"ui-component-library","prompt":"创建UI组件库的详细文档。说明基于Radix UI的组件设计原则、可访问性和一致性保证。文档化基础UI组件的功能特性、属性配置和使用示例。解释组件的样式定制、主题支持和响应式行为。说明组件组合模式、状态管理和事件处理机制。包含组件的无障碍支持、键盘导航和屏幕阅读器兼容性。提供组件使用规范、最佳实践和自定义扩展指南。","parent_id":"d907a8eb-795c-4060-9cdd-50d31cf39be3","order":3,"progress_status":"completed","dependent_files":"frontend/components/ui/button.tsx,frontend/components/ui/input.tsx,frontend/components/ui/select.tsx,frontend/components/ui/dialog.tsx,frontend/components/ui/table.tsx,frontend/components/ui/card.tsx,frontend/components/ui/tabs.tsx,frontend/components/ui/dropdown-menu.tsx","gmt_create":"2026-04-22T18:57:04.216865+08:00","gmt_modified":"2026-04-23T15:22:23.573963+08:00","raw_data":"WikiEncrypted:mOhGqVhKXtp0S+QeVzok74WypWJ7klGHRH+KdUSnimLTYfyBjBDRPAzXT+gcOXfQVvcrNlnW0hq9eH7zZFCqkZsBgmYKEU+paWYmItwEmPFSm8j97/vwvs9ugP1aTV0WKgu1SgAg9UjbHTpC/aH+MMWl8IEcuuqWfI5XbGaUR87WXcEDmdrb3wUoUJRDu/cGjCf/fvmakwSGbuyVnUxAKC0b89qWigFSx7MqlY8I3hXqAtSNiskE28duoh2j488f5d1qN4KsTvxvRe26wRYqlD4qzi7WQGBZQUoeoyVRA8PrJFhxeH6clcVYO0kStx160hPPrlpF93ul/lDmdVwrTZfpWh5RRY5u02+lOo2Vcl73yz1ixYzt/OXYaenA0jUTFVdPJ2OcTZGDQV7xMOPFPX3iFNKxuHY9aks8ARFEUs2BtyH+KlyKfPdKqDAlklqIVzP4MH2E6uDcvYMSORu7S1T+53+R9br9Cfu1PSZkuVdmHNqUuKSLA7pMI1QiVYXtwk2GYmRGYUH7geeQddC61wxpCG1rXcVzBMSS8LxtR3SSj/9VQ0v2YyrqKzRh44BKjm+ojKbz8rNcf69UZ5Fu4dU5kGqXy/XWbFbSmoUmrWXnZ2zWPhMIgHAIsTe/iX6JC5Q3L70XVbXk4S/ffk/sKKtdV7XrQVmVPhSquUc7x1RcfMyLVgxyoFEOwwk9LfQIPE9n16lNCvDWX3UuK2TDcqDbwJQ/FMmjaZDilRQFs+8MA5I/UUtC5CyzoOiLRXvPqQQiqXjBs6jefxc0cpGAJwUkaISOvQum6WtKWK3y1CphRMH2hkB4bF7NgyOm8z/0JXMSpcPR8nMUY4M8pW9MZYQEL76sWcQAD/oiWlgAUccgiRPnCiU0Xz7/MplIj0jTRwXXzc8arUGle1DmiJFEVmztGZOQsIGDqSwKGG5XHEdLyKe2hWHqBGRWkqZrsBqS8KrFUWk5lefvdDZvi8ci+S4wdZQX8IDx0siYw5cfdMlilWuaptf6qf/qEVaIO5DX+MMGPmGBz7jnyaQfo2QWlpybbe/uLTvhZTe75uY9Revd+DPo+zgmDUmGj4hSliiZx0smUxDq2wMZmKLx3x7N8m1jdGgqT+LVQAhdUcmE1Qx3W7e51K9wB4PN3L8k8bDewzE25kuU6a7QpDLdn5lSa8n0E0Yug9cp3wgllhZVFVmyjVr/oC3c0I5z3elvtrYub9jPeRtR4AmW7w2RPcUt/8f7j8aMH/1lUBQk+GL6OhXAEnzmav2Q2smdsQqWS4cVj/FV1lrfoV+peL4fo5CxYMv/ZJSvbJaFSpBOPzf09qJBxUptVeosUyAUDv7YsJdUo02ZE8B3ZXZGcpKGKSRiBeLQKjuqkck1rBeJK4PnEEXZ5vtz2ONe8tddj5qna0a3","layer_level":1},{"id":"178b681f-d013-44b7-aef8-dee7ca8c22a9","repo_id":"1095f823-f6f5-4e66-9aad-9f0b5b6b99d1","name":"核心功能","description":"core-features","prompt":"为GEO项目创建核心功能概览文档。详细介绍GEO平台的主要功能模块,包括用户认证与权限管理、智能查询任务管理、品牌引用检测引擎、多AI平台数据集成、数据分析与可视化、报告导出等。解释每个功能模块的核心价值和使用场景,如查询任务的定时执行、引用检测的置信度评分、趋势图表的数据可视化等。说明功能模块之间的协作关系和数据流转。提供典型使用流程和操作示例,帮助用户快速理解如何使用各项功能。面向不同角色用户提供功能介绍,如管理员的系统管理、研究人员的查询分析等。","parent_id":"1bb55e12-24c4-42cb-8f59-ddc303460d45","order":3,"progress_status":"completed","dependent_files":"backend/app/api/queries.py,backend/app/api/citations.py,backend/app/workers/citation_engine.py,frontend/app/(dashboard)/dashboard/page.tsx","gmt_create":"2026-04-22T18:57:13.330097+08:00","gmt_modified":"2026-05-23T15:23:21.993776+08:00","raw_data":"WikiEncrypted:T7sUiJOX3kDqyMLpD1WxBIoa4LuUt0BbmRUUbwQKSxGYrSupCPI/c9cAW4Z1FJ3a1KfzsqdN2t6YAo/gosyxBdAnQrG5i041HZhmJKdZMwMbHjgD/RwvogODN6jShAuCXS1wYxG016ckUnMfO1cR27Jpvg5/1VIs4Z0RBM7gHaNEutGfgMGN/I67TUKhPXC/gwiBILP7Y1VZXpfd9oYmAeRE4Hsw3Nu7OTZqs2gFIjiQwx55aB0rjkS10JeQsgk9pIlNX/9lDYZMl6xYjsBJQ8lxF2zGBk1tLhlpPhnAn9HdhyZoPni3elvWwv6UW9GLHlQXTtW9AGhQGm4JhCw9U4fboYKFJraw2Nv4bUmzUZEwcrJifeC8ncf/VMdXqwmsMncVFJIOusFzAYsDMYvPgZwYitYWE0ELl0m+VrGfg3gMEyvuer6DFPFXJYr3zn/8bxxUDtay+rbQW4gDLy2l12BDDD6lmuvJbof4HWkiX2EylGcHKkqDjfiyJefn/gr1vqUR5Hh+6/xhXEb1dg+EWe4d1AxDLjIZVYuxvN6CNIcrihYs4wM2Zz1cE5GDUXsjvGBhLizJl+zSzLw1eEKqursiPFj4ZLuMpZtZPoHgaqMEE4jc5YBNU/dZ5vox5QB/9JxbSziQf8n9RNHAZieiKS1QEsQo41P3/53Ax4xwvzAoamtIo2Gxz9b17VFPCXFNArl+QzjdgDAhu9WTDTjuTjTsc/pt/WGUtc+PZdAtBeuLYJpCW8hGHB87/xEQ7/IKjcYB7lX8YTVK/Io9szc+APABgA1I0DfiTZ2G9tR0V32MhOPGfFvq0gqsiBzO3kmgrBHVxP3RR4Th9JKzzd+O7DET9G2a/04uAfqk1j/uvmxG7k/o93XQKWQ7AVieZrJnTDajI6xewy3dXCmYmf2IfnwEwctUJ5qEtWAdHH3PXTpZdN6haMsFKlsEGTt40ZSzELm7MWmMnlTiTwYQ/BSp9B8cYVauEYpqt8gEDQVJzH2mvFZFI8KJ5wAUo/W5jrP62ijIg/TjqVeyPVSbipePWw+mCi4MLJy7ZaQ5I5YFk/SjqNZyKvOj2WMHZvUF4bBbqPh6YUokCLivlOKRRPrIYHbRgsWmIbinQeyYHTNiaHiujGWxIYL1WjkFbe1BUCv9q4gpPjVs7grIYbPxPREC5yu5FrCu7UXmFRBxpZ5KR3gZRlsU6TgNQtwUUYgIYsQeGclv2BeMBD9i5fQVaSGeuXeCPnHFUr50RpSUObWVX/y4C6Djns5ABd794m/HYgNsw81dRog2rHKJmLr3c0K2zHKTsp3EPRH0yPo6fLQjUiWNPrU4js9xwwPgc6OCWpnIUQtgdYfoZxuH9D5C3wNAwdMlPO4VBZS/r06+YI9GMJgxvvcPnfsndwOEn8Wp+Jbr2rU1cuPNIqYZRZpxiszhc9t4Dl5neRb0JdpJJWFzrtOxkkr2K6FdyNDxeezvgjNYIUkMHTk9ayOYfhZjXrKrhA==","layer_level":1},{"id":"f210509a-2381-46fe-8c22-0ed768e6ca70","repo_id":"1095f823-f6f5-4e66-9aad-9f0b5b6b99d1","name":"数据库迁移","description":"database-migration","prompt":"创建GEO项目数据库迁移文档。详细说明Alembic迁移框架的配置和使用,包括迁移脚本的生成、版本管理和数据库升级策略。文档化初始迁移脚本的实现,包括表创建、索引建立和约束添加。解释迁移命令的使用方法,如upgrade、downgrade和autogenerate功能。说明迁移过程中的数据保护、回滚机制和版本控制。包含生产环境迁移的最佳实践和风险控制措施。","parent_id":"243a1a45-d31f-405e-a3b9-694d2fe617d5","order":3,"progress_status":"completed","dependent_files":"backend/alembic/,backend/alembic.ini,backend/alembic/versions/488d0bd5ab01_initial_migration.py","gmt_create":"2026-04-22T18:57:14.161329+08:00","gmt_modified":"2026-04-22T19:20:15.066432+08:00","raw_data":"WikiEncrypted:veTYwq2y4io5qXerCTrkkH9ryxDJ0NroguMukGrnBDccbI7FhPTNCbxlVVf68ZQ7vvUzAxXQ43tY1R33KAEW91uvBjnohUVl7Q+D/Ap3SUnHDpWQWBM8qdBbgPmANzeAhinu9R6LqaM1BaUXXk7OeSNamXR7nrg52Su/KTt/eSPCFzeoio7iY3vORVHeaHpWs3y+ipYf26jobCXk1cLVjF9BgaKQ8UIEk4JobP8DZM0dSC9SqfPLDnh2e6k9t39q8JNd3MaV90E75j7KuZKZZJemgTfwdUTe5c8Bn5uNxCf3TK5iuMxVxJXD1PTU+9tadOMcx1qXGJ3cb3nuH7g/03z2UrmsQfIRf/cZLGBqAdGIWhQpJph2OlUELy5WTq8t4R//c0t+IUVTKieR2A1E1U7uGurYXL5ymVtiLnckbHeLMEoxbJYmh7d4xn4mWF5hcIhAZoHvjqh+shIGNwCfXJQGswpnJNML0vWzQNhsJ1YcTUnHC0P8Y6nj9VmXMpUYuJLWuIRuqBS5lkS7ChcQMXO4wfad4N4RMHX9jLYytT/wOoty1KlEalUzriEMahdDn7h2DsLzOJL35SLwpVZ4NVnInvcE89IzYO4wyJIz4NdOfBYseoIv20Qv7qO8B7xhRtTudUyynfaz1jmkT8F9UgZFcdBJqg08MH6VdQSdrlKqUGSGsFAxtB9OC7yv25xznJq5n5SUwpLmFNbQ1evjOqqsogzLg8vClnH52aVuE6TfQWggj1wDjxG7jUj/W7mHSOsDI6AhtMWrP+2OVg2Wx9Bab3iLivdVe+mg93LH2FvF3a8iAdcDRseeNZj2UeJJfYnmzpsRpm+CeJo8Te1ab8UeOeGebDsnVTTILuEg+qe85nTuG8+PmgOs+n4r+781gUSlyoOO2Cde7QwES0X+oENbplkkSZM719jK09dcnbG27vqoeh8rTrzO9ygM48IjQzZWUJCnAIP4Y7VVrcTBiyrZhRLikSrVvSCvWU3K7KW18pnOJh1narIx0e6w+bctledpWsEGZJ9fwk/ae5P5ZvACxfM/2LOdDFqshVbr6grRIeSNNf+tl5nDunlOTUEY8fGNt4lsr35UgKwPwO9TxACZGCsd25DuEtHum9DU/GYli2+rgNaOokcc0Xtw/R8OuN2pa7ohiD6ACjJ82m0kKC0mBBymsNAdo3bDXv3yoyI=","layer_level":1},{"id":"aad61788-1dc9-4682-b743-47188d7aecb6","repo_id":"1095f823-f6f5-4e66-9aad-9f0b5b6b99d1","name":"引用检测算法","description":"citation-detection-algorithm","prompt":"创建引用检测算法的详细文档。详细解释引用检测引擎的核心算法实现,包括BrandMatcher品牌匹配策略和CompetitorDetector竞争品牌识别机制。文档化置信度评分系统的计算方法,包括关键词匹配权重、上下文相关性评估和结果排序规则。说明引用上下文提取技术,包括文本片段截取、语义分析和相关性判断。解释算法优化策略,包括性能提升技术和准确性改进方法。提供算法调优指南和实际应用场景示例。","parent_id":"7e66719b-4a8a-484d-889d-10fdc76788bb","order":3,"progress_status":"completed","dependent_files":"backend/app/workers/citation_engine.py","gmt_create":"2026-04-22T18:57:14.593043+08:00","gmt_modified":"2026-04-22T19:21:33.125768+08:00","raw_data":"WikiEncrypted:qByx+WzXalKNnda2aYUs+KheFrHbXoPYZO+RPCaekyWxjKaQvamRZeOm1WgroVS/6iDS9zNWvth+zIYrS27hz/NZLNtt2wOUw9iZG139S+OGMVcZB6KjsnlgG3fSA05ZEdrwDfB531npeEpy2DodlOkcXOSBrgCwkOsVexBDKcWLpthBpfOCieqWsVnTfFkeXE8VvMLROtjojlr+6So18lnYzdEekhgU4Az61W3QEoXC7l+uPBNpRUYZY9z5nLzihT1o3I2bDEfAACTaa8pU8izFltiEd4qID4z3TepI7IuVr7oTmPOaD4MzHULu/4RaMo7/7c9Ql0uGsFrxRb3QFXiiH6QZN++2X9EDTl4UjA5k2E+OTcO2UOZm2dV7vi51lNAZwI50VwaIjtaC4LrPpX7fklk3hQ1qbw4w0FPjYlraJyO5MLseOOQXmURr5BCOhJcWoJmwJadtfh8EAO/9XRK9CRjr2wpAuL9kan2Vkympa3UCszQwVox0j4IkjJNYlG/7UEt2ixgTU4pQi+CAJy+8tZGJxY1gk1MCILniaClaQQImJhi6TfYfWSVywTFVltVcxPd7kMwK116KQmtoiqet/DRC4rzqeEbb6w8I7HZu+VwSR1TXSN8teXJTRMAFEgg9vh+vAOconlX3LzcgvFPohvC+teXJqTADp9XvqcC6Xh41G53xVAvDteT9pJCZHMZsfgh0bErBFzrvnwSObsmJEkvWnlDRN5tdVsRIk9LGcvaflUwWHmIof5SJj7wO9fSm2BN0gW+VA9nbQxyuHt8YqvNR5D0WUpbY1/UDw6IDhAxuTh/6yyVt0HqirNDXslgDardkMaphsQs4xh1fShhK/PcG4y+xX5VsoXIm/tjfGAEXYIeGOHtVuldTaCxG32uSnuT/aFQh7H6df2Hhb7c576oZ6QbZ4HyiG+Qa9iZr6deKWdGhtuuUzj3FBAXLtLont+yuXSCWi/AWM5MOMVyScyci2LKIjH5haWCCgS4nm9tLvifzUgmdeycw/Dhve3nrgdkgO+bIRuUQxXRIxZRUdxEr0DKIa2tEKVeorc5pIX9m1bErC53nDhnrLBj4/ZQjHp33XcgGQ+4jAfmWK/AN+P/SNbyF/K6O0qlKXPqQk/w5bOZWCtcIjrDLhyxZce/pYHOGotrSGaKOK56cJA==","layer_level":1},{"id":"ac0658da-7670-4e41-9e57-02d9d0d50680","repo_id":"1095f823-f6f5-4e66-9aad-9f0b5b6b99d1","name":"报告导出接口","description":"reports-api","prompt":"创建报告导出系统的详细API文档。记录CSV格式数据导出的完整流程和参数配置。说明报告生成的触发机制、数据筛选条件和输出格式选项。文档化批量导出、定时导出和手动导出的不同模式。包含导出进度监控、错误处理和文件下载功能。提供报告模板定制、数据格式转换和性能优化的使用指南。","parent_id":"dd12cc44-0c95-45d5-a726-e7b8bcf2531b","order":3,"progress_status":"completed","dependent_files":"backend/app/api/reports.py","gmt_create":"2026-04-22T18:57:37.837258+08:00","gmt_modified":"2026-04-22T19:21:24.246329+08:00","raw_data":"WikiEncrypted:ncgUburcUGIQoFYRn+jCfmA+PbmqRFCE8+U3jYVfh2v8RywptgptFxq5lhwZlmleN1AF4e6ox3Zeepx7xqM72ox5n+mZFIvpPAV03iG0mffmuvwBURuWuzG3zvukYRbxLcpPqC6v5q4GXBz/rMTsxy+K9HHfwtlYbga6fioIcJrpFn0O0GBCxvse/EcV3UFGM+LHRaRVZqk3N16dHYVOsIgwcqfz+E1qQhOc9tSvlN8OuLBl1z0ukshjGXiX/lY4xzl1WSrFXAIsz6WAKGLPlkePgVZg61CHsK9/iXfq1HIs4Mv/RYwTtuMKkyWX9+6LO+AwRjoeHSIVgJsaSwMBS+MqugD6JwGdLsb5/QGcsDSVaN1zVhbjD1WnJ01uK+tBWcULWdYGAkgo7z9A/YQJsV8PUfXfdZnfuydZi59mopfaX1AYtCXeceMgKnzkAIwjWUl72+Pwtvdke5upjMFgEvoy5NrCoYwpZJBePLoPrgu0kURoy/vWGZ77WhOuGQs2/cn/pk4vCFes3r34gglCIF0tHwwh9piyAabHid5VZ3EIuOlhBHL4O9L6zlAgO0opbo23bXt7kIR8MIjEqb8b3SoUIGY7PElOLeOIwJiz1LzOnccT84S/avMIJR7fgzi/me7mJyD+8h7mZ3GY/AsbFhi2oh6bcqc7U1UcO40wTqx7myMlwrMOo9zRr+aAfR/lqH6YwFw89kkxflBfKQ8X7UwPI/vFeOnYkPFjj7XzgHUtclkOUbxztMSSnhxiBMGzbNf6/hnfqT9O5xO2ZF4ufJ0t2Ci/vTK7mqMRvj6sBAzXnGCig4zpnDKbOrVJnB53v6AnqjeFLvqUCGI5Aj9nn+g4LDMtPzzDhfm/HtoxVJjclFmC6FQSLvHlh2FILylIvVxzY7rDDuK3bTiuZFz9Hw==","layer_level":1},{"id":"7cb1d921-44ed-4e22-8bf9-baba7ff8b7c7","repo_id":"1095f823-f6f5-4e66-9aad-9f0b5b6b99d1","name":"新功能开发","description":"feature-development","prompt":"创建GEO项目新功能开发指导文档。详细说明功能模块设计原则,包括模块划分、接口定义和依赖管理。文档化API开发流程,包括路由设计、请求响应处理和错误处理。说明前端页面开发规范,包括页面组织、组件设计和状态管理。提供数据库模型设计指导,包括表结构设计、关系映射和索引策略。包含测试驱动开发(TDD)的最佳实践和单元测试编写指南。","parent_id":"2148d7d6-25c4-497f-8894-c4eb7a0d2bd7","order":3,"progress_status":"completed","dependent_files":"backend/app/api/__init__.py,backend/app/models/__init__.py,frontend/app/(dashboard)/layout.tsx,tests/conftest.py","gmt_create":"2026-04-22T18:57:39.375268+08:00","gmt_modified":"2026-04-22T19:21:46.916012+08:00","raw_data":"WikiEncrypted:5RlNBsIi2/3o8ATlHuzaYHdvL7yJfTe6YPwFoSkO/GgZuVYfBQkVBn+1kZzpIDRMGSVFSuoDX3pyax2f9XzBxnZshkSCM7o1L+HEG+sgCns6EUSGCL3KfZi4emTF8vVzG/3m0dhVOWuoQXf3TK1+2Aa07EE3HJ86aWB+sLQgQyR8gNqS+MsRztbE2Am9O9oDis36vAh+tGO64VIsi4ulSBpI8D3+dRXcAI8RsujwrZpp57UaW+DyGg8Jkp+WqqjfbgBGcdkno2KfRFyWKqKLB1g6yKJCePYymOK9DHhXbdBC9mKr7EWc8T394B1klPsqywIZs0i3xy/Pr5FAuzklEn/8jhNkYpmgcVvXaZ43AUVTklSOgSC0cwvfeHd91QuNSlfIbIs9Xh0pfhmz3XAts9WErkdoph3YSvrNDMuXK9CMNhlu9XMkMCQcV7ac8ax69JKW4uVaVHcjbU7PbzOeQ7vSALRtfK0zhIWlbQ3za72G9FvDogDqrLfOBzEXA/cyXMdpeZP/ICE7OsSCRM/i/yU/K2YUAWnRJczSn3cX/8lGIDywmB0jU+IL4l7eteQD1Ea3elS3ne3N6t0WqX/T4jybDWQQZqz0+gOrFuJUKTQ18p+2afWRjcYZnqg0EMvXxpXaT5fmpQAxMA89c70flWUr6l+ZNckhODBS1Uj27vp+ECTFfhbNt2CmqrDWIfdobRz1gXYkZI6LR+xgc598+CJDjc6zizQcychGbsbPqawU+CCQfSVqPCknZLlSyJrMF+FMoe4jm8fpOVyOOfqGN3N04W6++aIiU3eZIMB0F/1pjONP/d5egIYaJhs0Zo+ciWBBR+Me05kVd2tyIK0ldRH8iELZu4XmfrNdcGPMTZsENU4lZZiJxIXbeoKUQF7KbjsDcLTmuXfl4jcPFk48k+LwUEE2fyaAoG6SFrEaDZiZ/yR292cbQegdgcOrF+/QZDnMqVS6yFRaljF5C5+ce7VNxUOs5dzK46Z/0xD4kXHkT4QT5/727yUeQ8KmshnsLpu0XgxdbjIAKa0UpiByR2sen9DI8GblyzqpH/4jM/yMtc2COW+MLDnPw7xho10kjKNljBjsabSa5q/wLnYGofR/pA1CmnrwERR7Cytik91YmtyTb1D+rjh+uOjSVOB5NqjX7dqhFcV0CLE3KfUAkA==","layer_level":1},{"id":"c45e66b9-1ca0-41da-a796-6b98f394faa1","repo_id":"1095f823-f6f5-4e66-9aad-9f0b5b6b99d1","name":"运维最佳实践","description":"maintenance-operations","prompt":"创建GEO项目运维最佳实践指南。详细说明日常运维任务,包括定期备份策略、数据库维护和系统更新流程。文档化安全运维实践,包括漏洞扫描、安全补丁管理和访问审计。提供故障恢复流程,包括灾难恢复计划、数据恢复和系统回滚策略。说明容量规划和扩容策略,包括水平扩展和垂直扩展的决策因素。包含运维自动化脚本和CI/CD流水线配置。提供运维团队的职责分工和应急响应流程。包含成本优化建议和资源利用率监控方法。","parent_id":"803bfef4-3985-477e-a61c-915a246d0061","order":3,"progress_status":"completed","dependent_files":"docker-compose.yml,backend/requirements.txt,frontend/package.json","gmt_create":"2026-04-22T18:57:40.355828+08:00","gmt_modified":"2026-04-22T19:22:39.446821+08:00","raw_data":"WikiEncrypted:AymRokkaRBrPd1uk5umiX/dhQHTPPm6nf5mmDPb1IMODwfEt6djM0VBnDWaMwjVsVSuT1AHD1pfVap7WBute6Wsiarqj6ltamY09KvCs0YHxEqOor+0AYSzm2Aa31Dwx0HGTr+fgwTnE6RMJGGceRIs4cV8RBM7Bs4/C9pv4JQQe1wx9fBauJxXtVZgZmkTwsQz1zMKUv/my9/bZ9Q05aHGQVWSs0vQA7fX+eO9Ugt8ztv2KzLkMHjTPQwDUKBMhAsMb47fa/gUJRb4vX0XaRC/0NRwbOvV9kGE8ZhfJSMzck20DTmUNjRs+txGlORGu4UWZsefqLmppB1YdHehQUnSp53vMgJwj0a9BHe2ZU8oB3BBo+Ky3c3OR4uaa4rfHtatz+jzKcC5vq+Oa2OkwFMyKF/rHCf5c9kOD3c9bg/wQwxJpIov1DkWxrbmp2EHHUtHsb07ASQhGLV3SX7POirp4b3urFGRk2MwXKxT5U/gA8wytKMJhKBFtElvFBq2i7nSPeaH2xj0DS3o9rwbrhRJQvLfp/3z63umdp/84RCiI8SwdYgPx4ACqLY3QKXNo0LIi6rsgWkaf5Suyks+dimQcPtAllHZGQA/gcWYidV5oQCnhHJ/meCiKRy7Xb4GttMbIeOA7UNNRQ9IFS7wyprb/n36lYgLOcuQ5Nugly0pl7iFTkl4qWn4pZ+zE4TR9CK3+3oihqJMUeVFdsWHHzgVsh4Vy/4MCPUipHMfRj4T7BabCmkvaTRaf6oRiYEXPGH1mUXCLnQuty4lKx7e8LxdqWP6gciPJOcuRMBYoeBHqUKw/JNmAzN8FuypXsdUryS7GDozcilxOcRE9j3D0JEW+8ONdKF5sp2JAXYX0mhqtfB+RscbqU7E352fF8vZAqHdS0XHCguOUcPuOk1PjzrKK0PJcxoWJPrW1H76CpfhWX9kC1CX6ji8+oMevPaHlwwFIAPnELyRyWOvaAia+6TeiAn8YTup3BXf//p7UweBdBGz//qMDvWoMqMf67cKrFP45gozQjSEYzm8AQ8g0Rqx6ctmJotfnBMpbUoG/k/Br9U3yCwUW5C4ELNIkZ8HMTq1vu6GKzheTjgM5lsZSBhR9qgPwf7cYyU47KLN2oWaoSG9Ke9U5fc+blB461oN7Tb9p1M9jYYAi3IfY13WbWR9kQ09yQOl6zNP4E/TOZ/WG1O8YhDVo6O9b5nQ7Txck2F7a8+Oqzy404YpIRpdXWJvx2sNjxCQXQVXqKKTnxP5lOsLb4vYZqXeHpIw8VawHDzn9M5zowBo/3M96UZSy84F3QEP3JU1nF98Rqg82vqB50gv8dY6wl5RPTzKd+Fi2","layer_level":1},{"id":"243a1a45-d31f-405e-a3b9-694d2fe617d5","repo_id":"1095f823-f6f5-4e66-9aad-9f0b5b6b99d1","name":"数据库设计","description":"database-design","prompt":"创建GEO项目的数据库设计文档。详细描述基于PostgreSQL的关系型数据库架构,包括表结构设计、实体关系映射和索引策略。文档化SQLAlchemy ORM模型的实现,包括模型定义、关系配置和查询优化。说明数据库迁移管理、版本控制和部署策略。解释数据完整性约束、事务处理和并发控制机制。包含性能优化方案、查询分析和缓存策略。提供数据备份、恢复和维护的最佳实践。","order":4,"progress_status":"completed","dependent_files":"backend/alembic/versions/c3d5e7f9ab12_add_user_management_fields.py,backend/app/models/user.py,backend/alembic/versions/b2c4d6e8fa10_add_confidence_match_type_to_citation_records.py,backend/app/models/citation_record.py,backend/app/models/,backend/alembic/,backend/alembic.ini,backend/app/database.py","gmt_create":"2026-04-22T18:56:47.082886+08:00","gmt_modified":"2026-05-23T15:19:23.714682+08:00","raw_data":"WikiEncrypted:Zb5TNaG1u/mRrgPr+sDyCqW7t7yX8M+Ha+5tSgGfMUOChQVv8Rc8RrXA+lpSqmcv/gkaDzP81agTYjHvX46erg7PWFncGZ1TOXKqQP7QcGfliH5ak9tnEamgIuPyt7GD7X/ktYWZNBw0rkib1u8riLrYblHZPip1fA5nWgiNve9JAWR8A5LSXb1/MkK85pGhIT0hbxgGSC6PkPVIRisy/D8xDYn6rcwMs8isn1Q0j0kMKiUwDu5D73M4vDsI4y/ZxAWd6WYEFgkqYOoeV5KveiHRDQ1BWHqQDFCNR/UWM2lxXlj/whmN8VaSk9Ye/JHiiNYbkSuvcUcO2YiOPia8H44APQcfRpcKUh9SBToYsFV8Fu3Sz330VdqGSjrk4hlw+DAQy0ANf9SxneL1SSgh7UEQb3mCmwf4ol0W2OOEKOPj3+srwFiYVbOmSKLMUezu4sRx8BecH0DQJj+w6u0jFTCVwHJcsSZXsJ6ftM8zeW4Gb62L/9E3eGd5gznXE4MrfDGV0U+SHOXTHVLHjIiiDCFL5EKuriwMozfYOYiXp1kgte0NR3DLzOoxAk9NQViv6c9ckVvlxSytmvKn7bbuCU9m9ZkZwa/+maXmuIEHvYRmeD0JBzVAPZtqvr9Q0yjLJDSWQ4z/0GDbEER7obUFIM+E+N8/yfexWunfYvUfL0mWXCcTd9J82nMzWM+Wgy2xUD086AHFPLXHH07CREuqOjUxZsvdQDG1grk7lObH8izbD8w2Zxaayy9lIwqJBEPCqaRdF14OuD+avHkK3Llo+7V1HYjHFYLa73gJvxSO79Ww/qvzvLWynNytnZEci9NCrzeZdZ+0TKrk+9i9L/5cU33O7IFTcVDDUQKU/ZCbP4D+ICH+K0AmOTiZaS343BGpR6hGlcrljtEjmFjbtENwJ6Dj67zXXVvUFWRlWwnk1ueUMxE7uNPzkF8R6XnOJQZxjv1ZhoYTrCdpi1eofq2LSlp9DGEyVNgS2UvYp3ZKdt2nOQi+NGHfy4nEMXUm2HiIciMAWERbdIZFH7igmgNwCQvvOKfnwxsB9aToLxzFTklkYilSbsBc+lBi3dbwXpvyfvcETruYMAK6xpcl1vfnkx0UVzmWg5ScYPlMwAyAkThsdYB31r9HWM0W2zlrsan196zyJUp/Ga7/dTuGbTW9g8RIVFlbvyO2+q1QBoBXM4lBDOEZPZPxpCubiCkbvshTREXUBElpgabfbBe5oufQCqpMvpO22rjfEwEMp4XMcih8I7Me+WEJuO55dx7hs54WCDmTwEa9xLmb0hXAKG1v6asdjp08CZo4Jbvnp/BrARqvkJ04j9cZpY5ybL5tKEtCbWWnIkSTC14or1XZksHDT3UZgFTpCOoAIbC8wOL00HXgI+rkt7UFfccjoV/i+y2xOlkwPUt3/LqSnsYRftUSpnJIj/vsMl8Gt25CJqSzSyvVGY59wIhWaWWzMldJK0IvOnc8JOGNTLwumjK5BG1apFMsHQ5IsoaZlJ8jed5aM7jLsu4v7wCNEpb1mh2FX9ntfdmHo4fqvttaKBlZqzO6/2JSNVRJz7KekqHYM0Z5QJ4="},{"id":"05214c1a-d804-4f3c-9048-20ba4de3be0f","repo_id":"1095f823-f6f5-4e66-9aad-9f0b5b6b99d1","name":"引用检测引擎","description":"citation-engine","prompt":"为GEO引用检测引擎创建详细的技术文档。深入解释引用检测算法的实现原理,包括文本预处理、品牌识别和上下文分析。详细说明BrandMatcher类的设计和实现,包括品牌匹配策略、正则表达式规则和模糊匹配算法。文档化CompetitorDetector的竞争品牌识别机制,包括竞争关系定义、相似度计算和过滤规则。解释置信度评分系统,包括评分算法、阈值设置和结果排序。说明异步处理机制和并发控制策略。包含错误处理、日志记录和性能监控。提供算法优化建议和自定义扩展指南。详细描述与AI平台的集成接口和数据流转过程。","parent_id":"7c2ac186-ec90-400a-ac1d-b3b7ca2f01d5","order":4,"progress_status":"completed","dependent_files":"backend/app/workers/citation_engine.py,backend/app/services/citation.py","gmt_create":"2026-04-22T18:57:02.318113+08:00","gmt_modified":"2026-04-23T20:33:37.372717+08:00","raw_data":"WikiEncrypted:5AsZyvafBXiUtsQ5ntd2xSs3ILjH2jK3KRqQeqYdLK3xV++pdLq+4satUA35s4AktJpvtIlBIE91BpoSSxdMIJzlzjcEII8kW/R0EytB/VdNUbQKg1RverfqOp1bPEWLBmM0oXoe7+3qkzPC2Mf1ooT1qY+Wnye4CAfG78TD/q0AMQdykzQydTep7eypfUng3BGXStCcjUkwnitXy9jgftpC0/tEyMhSJIRwfEyHMC8pCZ3uBu05K/kbWJMAVzeN+RbpjqQl/AMRIDLTMg6TBQrvrH5uB7kEmNLnso0k4IwbKjYBfsoAT1f/RhrPR6uEpuyMZCI7868kZ98SRi4JNdev+YK7Ek74Y4AW+/z0d/9fpp2VQ3lDuYYADB2ihvzHrK09yCDPV5DfYbOE+YmgfP/W+1ZayVWcVf5jjw/kQ0+wXXpByj9Bf0MvKeJO8OmWNbW11YKf1Zhr9O9ssfAGhQ61tEWdGwr2vpPRZecLhmP/3vAso3UexUhMF+42ursRQIxusBVhGnBG3395aphiScvidcQ3AWZDt7qWaigup/9WWvvwKEk+gWaJBnO8dib6i/mBuB+XC33fXmvrkk6ESP9afV1Ag2XJnNosrx5wpwCnwwVeYm1+mo2FyjpkCyIesooi9FNVuMYQUiR7o2ORBBXyp8r8l4pab4wvhmQ5F/kvyrDq2IUoSgVwCe1WVokpscxHDzemlRiqQALcb9vHFogShoOIw4NQd8JE6Ciw2NTcEbgq5i0hiaO1w/VhbUyxoqA105/8aSzbEwdAcuMG9ciHKwbMkoyR0UaMKUZLJy6VO02JFFpRtlh3OD72t3VNoDS4lWyWJe4G6NccX+XAohN1rsZU+ROCL8Y63mODms+oacpzuNvCQC0f91XvoRbftpDjven11QkJUdRxC+QBid+X3RB5HjEUZI6amQjQESEX2z28T4td0i5MNlp7IQfJjM00IuaVZmFavGuu+RJfvR7n78hqrcdjNGJE2t3TTozXstxH3HLmjwKzaA1DGdcvjISEAlWpSDq1Z+8ExFSDbevtUFgnb30/rRPe8E/+VsDMR1FqWh+HovxPuOeMpbUi9ijTGv8ynn1DWdoSvT0kIfsNMhReSibvIGRprPdW7oZEiI5y1SQYXU4kMBOpPdNuCyaPRA/3Mx5z0o+l66QqRA2tAMfS5JvFR53tL+M8eEjH5xvgW0VmBTv2+9VGk9aRLHXSHANLk78McmWR3P66okFWF0OhqkaLPqj1lqn8SMDBv297qL/7vaz/5ZMq+1nKCtq/I4rY9/FziNmhBZi9jtXj+845Jyt4Qi7hprnHQYqmX7caLgy44MGdtGDcZ/fxMNY3A2QbuIeQRT767L2gpffBKmqQxLcfEBwxKol5OB8/jdyvVTpGLMdROGD3baQASEk3njuah/PfjZcfuARA6oVvcpj+RhM9HEGKondRlyBHvD2f5p7nK7WyubfWPvcD/iKl45JOn7zLMHQYvIYu5w==","layer_level":1},{"id":"bfca5ffe-8905-4ac2-a0a3-8e4dc43533b1","repo_id":"1095f823-f6f5-4e66-9aad-9f0b5b6b99d1","name":"数据可视化","description":"data-visualization","prompt":"创建数据可视化的详细实现文档。说明基于Recharts的图表组件设计和数据绑定机制。文档化趋势图表和平台对比图表的实现原理、数据格式和配置选项。解释图表的交互功能、动画效果和响应式适配。说明数据预处理、格式转换和实时更新机制。包含图表的主题定制、样式配置和可访问性支持。提供图表组件的使用示例、性能优化和调试方法。","parent_id":"d907a8eb-795c-4060-9cdd-50d31cf39be3","order":4,"progress_status":"completed","dependent_files":"frontend/components/charts/trend-chart.tsx,frontend/components/charts/platform-chart.tsx","gmt_create":"2026-04-22T18:57:04.217105+08:00","gmt_modified":"2026-04-22T19:23:03.405364+08:00","raw_data":"WikiEncrypted:LlssVZ/E1BSUywfa50FLlWyGoIcJJpOig8KP9B9gWWZZI8ePi8CsG3BxaOR4OzxCxm2XiNUDCA5f2LMwvnigr2SlxVBiSNHUI0lCgSHHEunmkPytqBjFiqGB9yeyKz3O1rSdq/m6COB07RDEp6Tymfd/Ich7hNqr0ALiJKFBMfTRXbiXa3naRlzgzc5/DA1h/zbAk9yl3yaR4bB4p7xAmyNn8C67e2gxrbHOKN7NK15dfXoIag0XHJMVwFE6SysJ+lA7fykhvt72SHx+Qz58/QamURb9OcCEnEtIYqW1uga1vc2HXP+r8Ud+tutKATUxPch908D2Dm70HjZTkDqV0y1RwdTE86O++EPgx5Sx24CmB2Y9KEs2TsxQBSxas2iX7ajhgIL9xFqjJIMVJWfRNeL/ql2x/OsrzEXUWybjh//bQHE/MIs2lMcn3jl6uggDT3q//Zf/jugKwK1117XAp1NDps6xhJqmTf0/J+uk2DjJwURNZ+f/hL4XNyCoPSOpjPZMIk+ikrqwiBBFy1t5dz/fksmYdzw5H1wSGwFPks461EvwT7SUd3qHg+HDEWwCrMRQLhaalcb+5T4rD4Gg7Aa0Y5Q7v043Oz/0rnmFckpB7QJrcI4yUtnbNxu/HuY+NFZLqpJUrNC6MhZKZ1Nf8HjXwbb7FvRLPTJk/0J2UGgZIuFkHqA398GnAHSj3OegnBaKM+qHr8cVs0wfQ/uFwwYzgoBd9gSGURpkSSDhsDUj2XJMeQPghyYg+au4UrCpUVHdYOyliR8OyttchGTRgDox14AD6X6BPxBueyw2Yb6orKjSBwNfDa9SZQK8dW9S0BehKqK7QLDHIzpglx66chB/QwWwaryM7BrEciDg6cdFeFQSmV+EgDmEePwse6hlzNdSXObTbNXLDwYhtifAxjK0xxhVUCtc7HVAFKLROk36HCFnlzxLpVmtppYzoprXfyXDe6BHU55d+PSdjtYyR7k/tigqJv5jX3TTrH6McF+/v+eR2ZtsTDIjWz+prq1cMVTVPgIB9WoT0+dXP1fMoZ52xLzWjSkgrQ7djAo7jyy1G9plvOx0bdGh5lBGOz+/zY7MTLVaKx8eK6kKS+juFkRK2kCuesUi79TGLidetA+vkruZiHzNPBJWntDodb79","layer_level":1},{"id":"b32b024e-2d06-45c8-94c2-a07fd25ab9b3","repo_id":"1095f823-f6f5-4e66-9aad-9f0b5b6b99d1","name":"快速开始","description":"quick-start","prompt":"为GEO项目创建快速开始指南。提供完整的环境搭建步骤,包括Python 3.9+、Node.js、Docker等前置条件的安装和配置。详细说明项目克隆、依赖安装、数据库初始化、环境变量配置等关键步骤。提供docker-compose一键启动的完整流程,包括容器编排、服务启动顺序、端口映射等。说明首次运行后的基本操作,如用户注册、创建查询任务、查看结果等。提供常见问题的解决方案和故障排除提示。确保新用户能够在最短时间内成功运行项目并体验核心功能。包含具体的命令行示例和预期输出结果。","parent_id":"1bb55e12-24c4-42cb-8f59-ddc303460d45","order":4,"progress_status":"completed","dependent_files":"docker-compose.yml,backend/requirements.txt,frontend/package.json,.env.example","gmt_create":"2026-04-22T18:57:13.330281+08:00","gmt_modified":"2026-04-22T19:23:49.7972+08:00","raw_data":"WikiEncrypted:1aHEw3M2aeluf1++NE1n1HTCzLNrSYNKzc2IVp06RQtbuAYcMEXChpU7tJYS1f3O0opR6Xc/vB+l5keQe8PgCR2ncFv/1Td0hCZ2YAOzrKcU9vT19aDXTs2wVsNg8N0rDLvVcTazfsrfReCkGbF3t4KIDlALR7E9k/sBc8Aux87FRnIqhElZnBvZS4Wsv6VYjg+rG70cB28ZbZapx09FwTbE2gyXj7Ck6qNOm9h31VGeQcyIEPfTlQzKWWghd2UuAwraAXbHFeTBwAzBOPZrVi2iMW5N0fiPvrofJe2RpvtWwEWsHguXuXUfXywdpjyOFbnrTokbwQiiwiHpgbktPSypaW3QvBywnGVAjxPBIfRlzbrxj8jlb7w8YznQPbWcNRuYRt3TVMBHR1Ix8UjdR2JwWu4yZQUrLOP4XJ1OVoFdLu5sT3ug3YetVAWSBGUiyUEIQ1U7QoHxxE03qI1ZmrGvC069cAhyU3YQYL0g+PfXWWo86/F20gUXppepBbqg0yRPlCX5asdDuL0vX+i9vl/JI2++deWQKu7cSc8+5tRNcN2AF8Klslhvy5KUEZpxqPaEhxXek/RE8thYcMjT02y2lWMR/WID/CEUm0DZjOC2fQE7kYjogUTC8OhNTBXocpLyn1sbyngxfQ3KsE6+Ysl41LroJ5F7SN8+p5pueRZgBbM32odMU1Dil6T14I/HwltMjiGAjHurPSB8hcX7nNvkuZnVTE2YMjB8ZEhhf76D9Pp1naI3P2d3j0DprvLXRiuPSfO9NBTu6LwZKuMaI2MBEDI2zoV182wdrC1T6AxOiHNcJXYiaF+ZOpMA0vabvcycoioAE6VOZ0mBQ9ZPVSZDf/Dw+VTsC8U1qruh1IAQVYCHsnjY9etX9sTaj6Izd3VrvgQkqP5vAteSDZTy1FOTlTi3X6RzcurXdR3833HqpXa/a0ot8JiRdmjIG0ydOuPYeZPs+Jb0FMN85H71mBziu41udCrikCTPBRTVz6VCG9yBdOgeW4s/iNhPqWCnDibKpfJy1GfSyZ7Jja1d4K91Y+IHVrJxB0+TZPezxY/htgMg4W7MtRoOOPc0eRqst/S2zmEgxMMpU4dfaQIne5zGbUEPNb24qp3HsO9v2un6P17rFQV86RwmPCnyngxtddo0vUNesY0s594GhsGEquA9XlaYa4/KNM14pVDEm4ReIC1JvvqdiQdUAPv3nMXASqe3FxbJmsi93mpWhKWx2q4W+P3ZivXtxhQ5OB4Rs2uXmArlB3MNPKk8TL7wHCUAsFUcCGoPtT2+ov9ntDTLyjKsb0YUGjYUqAceHGdvLCM=","layer_level":1},{"id":"15d6170d-716c-4d2a-833d-81211a59027c","repo_id":"1095f823-f6f5-4e66-9aad-9f0b5b6b99d1","name":"平台适配器扩展指南","description":"platform-adapter-extension","prompt":"创建平台适配器扩展指南的详细文档。提供新AI平台接入的完整流程和步骤说明,包括继承BasePlatformAdapter基类、实现必需方法和配置平台参数。详细说明不同类型平台的适配策略,包括基于浏览器的平台和基于API的平台的不同实现方式。提供代码模板和最佳实践示例,包括错误处理、资源管理和性能优化。解释平台适配器的测试方法和验证标准。包含常见问题排查和解决方案指南。","parent_id":"7e66719b-4a8a-484d-889d-10fdc76788bb","order":4,"progress_status":"completed","dependent_files":"backend/app/workers/platforms/base.py,backend/app/workers/platforms/kimi.py,backend/app/workers/platforms/wenxin.py","gmt_create":"2026-04-22T18:57:14.593273+08:00","gmt_modified":"2026-04-22T19:25:18.719953+08:00","raw_data":"WikiEncrypted:Djug3Ni1DAZ8Du2qShzHYuqLmnJOyyKhsCPSfayzAMoLf9J+rFBy0LePWIX3b5/HwiLgJX57X2JBlObsW70y9DLEgX5HDr3AAeBC0dRNACFssPk0GwpdFdJeFwRtoB01ZTdr+IpYAK2YG8gaEA/2ysFJOZzxpGWgTq/Xz+KO29a2kcDgYhZKt55uqT/Mo/5Dzr6AN+qXdLL5xSqrvCkpmhYMFmzgIBOUjJM1mUISEtf/X+gK0L0wXSj/tCJnDQtGJqbFK24HEYyVnkon1GdnIvb+Vptmby7Qg9iNT/xb8JEVTTLM92335BfpTwTp+D4fNkMNyZgXv/XW6K5J/dLRulOCKwxJxPROAyvyEc5xLI8vh6BGP2+b8TgKAKILZTXg3SemKVhGrB3MqY5+V6whOOMT57LHnuwJUEMNMJsswFiLp6UbAlqwiICRF/Jnb+bvCliw4xXvKC6xfAJDQ5qAtcTCAm0uGslNVB5T07pzLFy5EaJS00hqRmvac/P3e8UyL84KjzdngtT3yZ95yCL30Ad9SpGXt76JgCgVJoPFcnPYlJZiXneeB39wFX7rogSSye9XkcBSqEt2ZITemhNHF6LmqSUdnA3rX85S/zDmRiN2NjS1Zjvgc63JjB4B8gQhw3rDllzHDLPBIO3PNInvmVsx5zHOjAMZmyIaoVRtB9BQQnUdHn1WvHdRXmZfs3eVA7jNhDQmTtBzdGtJ31XIHAVkP5ul/NXNBKUytIXDS5hE2s/ZR6j60eIWBlCNxNIlj+42vefIOU+e5kJufMVcBv4aXyQHpunohRHMUYteEC24NO2CW1FNZJlH9BEyf8RKg1/0hDEmySMxcj/S/pXTp5i8nevE+JleHdj3zeyWlGqJsJa7arZV/Kj7qPJYtN4VHoDGp7MFHgKvq6W26lje9EuwJEikt3hqjinocemgMjzEx+PMVPovHIBXyCfuSOtygo59bhUm0pvPgdMmml9UgZeVV1GMzDT//kfmf33ZL+aXTl+zEmnw5fZYwccKfmY6Q++ZjfSQLB9eV6u79F0yq3zh7zGb4RqRR5ZeL2vQaNsL3wyqgNppyJMYSC6gX+ce1aAimwDx4Lr/EnY474W0FXvid1Xc6Bg6KdPrwnKJJpi18zMOmECI68RvMpwmM+92oe/m3dj6YGItooug3uasMy8SPsvLi1RV2F0CQD5CqYs=","layer_level":1},{"id":"7e66719b-4a8a-484d-889d-10fdc76788bb","repo_id":"1095f823-f6f5-4e66-9aad-9f0b5b6b99d1","name":"AI平台集成","description":"ai-platform-integration","prompt":"创建AI平台集成的详细文档。解释适配器架构设计,包括BasePlatformAdapter抽象基类的实现和扩展机制。详细说明Kimi平台的浏览器自动化集成,包括Playwright配置、页面交互逻辑和错误重试机制。文档化文心平台的API集成实现,包括请求封装、响应解析和配置管理。说明引用检测引擎的工作原理,包括品牌匹配策略、竞争品牌识别和置信度评分机制。提供新AI平台接入的扩展指南和最佳实践。","order":5,"progress_status":"completed","dependent_files":"backend/app/workers/platforms/tongyi.py,backend/app/workers/platforms/doubao.py,backend/app/workers/platforms/qingyan.py,backend/app/workers/platforms/tiangong.py,backend/app/workers/platforms/xinghuo.py,backend/app/workers/platforms/search_engine.py,backend/app/workers/platforms/base.py,backend/app/workers/platforms/kimi.py,backend/app/workers/platforms/wenxin.py,backend/app/workers/citation_engine.py","gmt_create":"2026-04-22T18:56:47.083138+08:00","gmt_modified":"2026-04-23T20:31:36.620063+08:00","raw_data":"WikiEncrypted:wpnkiTiqqfzSOLf9jfRAk0Q6rmj54V4PX4cfdCN1v7vUnV27EqfgO0UCzli2MtUnJ51CgpvG/pn/E3FsASRJX83W5OtoHXDNZ4j26fcGYWMK9zRC5hi8J/dMZoaQzJzzsT8qKvXJnD4D7Bjp4ZqFEme7Smze8hNvF5wytAi0n14HrcR90C0v1NYf6UWM/I1F5Nqo0+3N+pfMTr9vJAv1ZqDstNHpvNePzJyNYVmfwpIE7rezCdxATA1CVuPpwaFA5xsmJ+vkqC26R1ecrjj4kaKngH6RRRDgQhhQ6aRB3vt5nqJTkK/GUHcF5T1XjKaL+a/sKF+40wgULRooeO7uAuC8Zv55v4uHR206FqyBmzQ2n2oL7aEvTlkvDbpN4K4o46nOw6eAh4cC2u+M/6UyRJ/vHl8dGbnZjB21BICs+8mtyY9X8HX95c3q/eXaBcsnPvE/pQo/8Z6wSj7GzmxfueajIQAC0N3PypyM475sPJJAQYRRBk4tB8BeeHAheffcSAiLI86gW5xCar2+kHIHTkRg3pcdkaw1EkhKeqcQw6ew0Z83+q31K2+D+G5Dp7k0yg57Yy+wQYoQpi482aVJTCvTl4DM1GdhaLBYK1/O9ybs6CsHHuhAMGPJeOCtMI8ehbz37vhncd/r5KFUwVm+e8+iVqLPjIA7A6uUm8oef8IZswkzAIcBjZTd0HQmfhdO7p2GfuJKvyAMwWchCj+pryelFxsQ1XiY4QCO1g7ORVxu6x+4/k2PNCOhk6gEBxOjJQzXNM+PjMhiZHJslw5eSbtEAXm+1F5jyhyYY972p9cQQS3iRFts9dQK7qtI8+zm8/UMh2S3rh9y089hgBEUB71Gg5cUb7gaiI0gJYh5HrUXvqt3g6H5zQQs+913IJZ7giMElPAP2Qjbk7hKfAuLl+gm7pG21vEiGBgdafi0W/SeGMfEfargk5rycBiAux4yqzolMzt6ZY1G6bSEdxhBwAL7IPHlaguENQ7PIDWDT1mlEboyeR60e3xngdX3d6vQeuuV5+OWjDecOeZTiBxvDIPgHbMXc4UEzS0YKWD8ao1VsXgT+V+KP4QhvazHdx0dXUhAJlmfrXF13WzadCYVAAlfJ5iNGkT47I5Z7NwqDIF2jO1g5hfgR/LgTwdLyuzF0R79gBMRfYZusLAkvoVjfKdTxjMIrkuXKoXEbgtcZDj99mrJe5eVpoCtl/nL+FDv5U8e1VDikgYWnXY62y5ZnhnOcvlUDLD2mJVlDEbnDBkMkFc2WW6TRTZQAb1pLCRTbsDr+kQD5BLd0YLql1xTFN8IsAKgz3fkhafmSS0hAEBsKC2Ntov35ZpS0cXcMYb1oGIIGPVAMq4Uk43QUUSLac4pkX/xpRkDI/wPdmaebMbCDw83xHKBNY4h9STf5rFicv01m7HLBHfkB3BTFwYsKGhOqxnJPkYnD0ZSz+ia3lw0eV2RoqWx6ITdxEvkaka3zPxNSnqrnTBwjBwTbLz5tXrCmK8Fn5Dd5N9xlYM6+6iveOBt9he/WYkedO6pClHq3NK1RmLgTQWpL532vkJNeI9p8YUcv89XqnwXSi1YhPMe1PKgYTDGoZvsPk66RDWaeTNkfhF/vcZudTvgMmZzQVRfZ/clH6wRHfgZzl1X4HZ6WJ7PKSSwwUBw/jkvMZ2rixaio10OXuEfyOqYqV4EoQ/upbXArnmYKjEbhcULNFk="},{"id":"850fc702-3eb6-45b4-acd2-ae87fec1f4f1","repo_id":"1095f823-f6f5-4e66-9aad-9f0b5b6b99d1","name":"工作器系统","description":"worker-system","prompt":"为GEO工作器系统创建全面的架构文档。详细解释APScheduler任务调度器的配置和使用,包括调度策略、并发控制和错误恢复机制。文档化工作器抽象基类(BaseWorker)的设计,包括通用接口定义、生命周期管理和状态跟踪。说明平台适配器架构,包括BasePlatformAdapter抽象基类、接口规范和扩展机制。详细描述Kimi平台适配器的实现,包括Playwright浏览器自动化、页面交互逻辑和错误重试策略。解释文心平台适配器的设计,包括API调用封装、响应解析和配置管理。包含工作器注册、启动和停止流程。提供性能监控、资源管理和故障诊断指南。","parent_id":"7c2ac186-ec90-400a-ac1d-b3b7ca2f01d5","order":5,"progress_status":"completed","dependent_files":"backend/app/workers/scheduler.py,backend/app/workers/platforms/base.py,backend/app/workers/platforms/kimi.py,backend/app/workers/platforms/wenxin.py","gmt_create":"2026-04-22T18:57:02.318442+08:00","gmt_modified":"2026-04-22T19:24:30.529121+08:00","raw_data":"WikiEncrypted:NKkj/YX2GdbxYjFllBaf8+HUgx0ecKFsz1U3HC2t2IRMbOkBCmoy+IYbhzuQ50K4pCdPARIwK+MaHbv1MDUXpcbdnvRL12GKezTnD100oXzQKqQkhZdDDC4nIEcp6weWLVGVffqyB7aL/dnt1QlE63XyJfCwizBlecxl1GDUB4J0O7SsTFL5gI6enVYO6hOzx3JrWnEFzirRjA6Llz1iFiFUWxTjxjToT1qkxAdREq2omi39vXL1s84I0XOA1blljfNNIGbpkxXW5uohJBndl6l7Bh23wF8z1LfdAavsFmljavCWqoMvA61Dn4jpJT9oDmaKXZpVSuxfMF2Tu3WOJZwISUGfGBJfdbfxNalhuFff+bhZR8P717nLoM3Do7T26rsqW/pr0NJL6aKxrlPCeIzL0v6Ct+HU3ULHT0EZpG8HfU2NhGWAJd0NhX8RZ8B2ZpfXZKioKtCkLhl4oWV6P8/k5g1nWpnP3wpmDwvp+/pGBeaBcYSenwJWgcGR2s0KgVsEW1niM8+JLaK15wFrmKcxve0hIWBiiPnbZKscAYq+5hj3ecte8h/JevEf+SBNB7ify6uUGU3Eve1jXyPeBrc2FCU5ueeJSFD3wu5pHlkzm7PP8UAbQOfwmENf/Mc1YRNi1FJsujdQuJ67474CyCTkCWFhTC539/6iIa7hN8505GK99PxHcIrsPMMT5LU69r67SizSnWV5bawiMPKGosexCHZfhT1jrScQCKeuld0X/lE1WXXm6ADBbfxZrn/iEFK0zc0WKsnT0X/nQI+ycJaw40Cm+soCO6/KtdYYGEzpzViqi2KxYhRyey+o+yIi8V7nVsxUCbaVRVmYNjnK9yX+3ypdVpJLIJXQ5ywaUWfvqgCrsC7Xxba9P9D+0kmnq6jH6ZdIuubXp0yOtWxe+VC4bHAWoc08RoBdLrlTCGz/hmgi5S83hM8MN0gLdQtc2YDsc0Pxw60+ylnkdlKIefBmb7XPiD8RMRvcbDUCGnrpenbxf5eoWLjLWfyULNQHoYINDdIFvn+skLu10KkfTf8lpRNqd2uHkHVhTTCFh25GlRLAdL7QDHMMQbmwG9OTjjt1tMlW6aYJ/pvYQq95uzmLAiICIsf+nT4xgqoFK+tTBmOst7Z3+bj1YJCPtUNyIzC9a3YYfRwlB1ckjgJaCURcXpImdkDtdpl3GP2mtDp9O52ZDAQVAJFVA3wFFV1G+qjqGRl4cDFK7BlAs04O4fvskn26jrDYiVqgdF0pc6eIiPhAJg/1BabciIggV78rEnEg6jiNJ8AhUmKLo8JOvL/C3m1mfcaUbU2K7oK8damVm8BSmIypHMJfCXzHIt6i+CaJLNlZ+c+MJ4WhqgPWc263/SnxO24wH0vaRtqmZ8g72SSFVa+6E65bdhSUaIejIDvILaBv+73KdUt7LGKPmqKoftErfP4grQZACnS3zQLXmnMfdzurPkKbBI1PkyT/ase2Czwu5/LwHWdWDcRQD2uZmUjndsKpbR6/xVu5Ry5VLB/ds2BrgjUp5pD+Z0U995X4yVwpr9oCNxR5r1sl+2Wv3jotf19l+safw9XwODQoURKcJiGxtJDymJvVEyl3ZEe1Izwl7SF4UqtboIYt9vEoEIilsuPPDtujnpN5pkY=","layer_level":1},{"id":"fda0598d-7e92-4b8b-be52-92ae63c3cd98","repo_id":"1095f823-f6f5-4e66-9aad-9f0b5b6b99d1","name":"API客户端","description":"api-client","prompt":"创建API客户端的详细实现文档。说明RESTful API的封装设计、请求配置和响应处理机制。文档化API客户端的错误处理、重试机制和超时控制。解释请求拦截器、响应拦截器和中间件模式。说明API版本管理、URL构建和参数序列化。包含认证头自动添加、状态码处理和错误消息格式化。提供API调用的最佳实践、性能优化和调试技巧。","parent_id":"d907a8eb-795c-4060-9cdd-50d31cf39be3","order":5,"progress_status":"completed","dependent_files":"frontend/lib/api.ts","gmt_create":"2026-04-22T18:57:04.217601+08:00","gmt_modified":"2026-04-22T19:24:50.486294+08:00","raw_data":"WikiEncrypted:/umMwKXdJhL9PqhJYRia9MjBtE8cuBSpJq1+zwyrvadwhOTuxc7+NNlJizkRp6kCDsj6HmsrrrEG2WmrNf4m1kFf/yUci2Hny4otqjfpEsOXzmFIxnq13zAZFe1oDyDiHr+shS0DH1omM5IrOroFuNXfBlFlOGXuTKJ3wXXPweq+qAH9QLU237hwRdKdI1UNXoGFfFF9nN8NzOmkwSQ0cRMvswtunfw+yphm0doFqLjrjc0WUZSar4loGeSR6pOSLU8ebi/JkrnwesaWnoYc/1aUJBPdJqVPSJQzjx/Oupuf/R1ihtrn81TMYOUvEaKLk9wVSfSvjh8RGttelGQzTBNJsssgMeqcDh+Qz6r4RJeFKgaRlhn753ONhpYFsHOA/05biB01p6yVuJUR2A3I4tqTlKZ+Xt5K6nvklSqGfR/asdknv3YOkVZOtQxAjyjg/RmmtnslgrEae+k+pBRvgZU23ZT5nZ82LarvwQLYZlu2F16oJjpKEgT3cw98zGHlLEIanqAXIOhT8iR7Fwk6TTKreGcH+oOkFNmbXHWXAD9ixtGbLqoidjzBlLLSR1++hGoabWTFiJX2LKj3lCJ4z30snHEvEL5ruTnKMF+gXM+truHTDsrO5CuaWyGY3WYVTndJKFLi2PQu5FclItm6ykG7LLkMlOXcKTmOrUqOgQhgDR0R7UuPYneG3+8tP49Gar78dBGx+Da8xGwikj9K9OJYAlHpVo05oKo78qku6h+6J2fHgIvIyJPSC88Whc+HpqTBbVMAIjzOQDzTTafDZnEoLWczvFoR5x2aPLnYwXdjyljOhmpXH/bShHcfo1W4KEEzka0Yp+DMZpTiSyhBpA5iLdjZdU9RnTUPTwMtqSXfdbbf0fdgem+z3CsmiuZJVViFNkOfRqL5f7Np4ITC0v2XwLSWr/bC7gbUZiEQdwEr7jwVO1Bk6/MCzvN1G217W7/RUPA4Up/Iu6PRBPcC4dd2r16kpGY4U68Ud7F6iXnc1Twr1Znb+cuTdO4Fu2DQ","layer_level":1},{"id":"7416db23-312f-478d-8883-2fc3c41ac2e8","repo_id":"1095f823-f6f5-4e66-9aad-9f0b5b6b99d1","name":"任务调度系统","description":"task-scheduling-system","prompt":"创建任务调度系统的详细文档。解释基于APScheduler的异步任务调度架构,包括调度器配置、任务队列管理和并发控制机制。详细说明查询任务的生命周期管理,包括任务创建、状态跟踪、执行监控和错误恢复。文档化异步任务处理流程,包括任务分发、执行优先级和资源管理。说明调度系统的性能优化策略、监控指标和故障处理机制。提供任务调度的配置选项、扩展方法和调试技巧。","order":6,"progress_status":"completed","dependent_files":"backend/app/workers/scheduler.py,tests/test_scheduler.py,backend/app/workers/citation_engine.py","gmt_create":"2026-04-22T18:56:47.083393+08:00","gmt_modified":"2026-04-23T15:20:09.061178+08:00","raw_data":"WikiEncrypted:VyywLMbCKto41PC5aDsBo+87rJy1wKhB+t/+dFn1cQKhRzLNGkc+cdUADwdeiVqAIwtiwaq+rwA2WFYQdbiGz8cyKHFmC9lmt3Jas1uZAz4Osy7WTe5xdzE2SEY35xhzdqPvBbNe/p8j0HjSJGFgENGbjEhhukipSO73yvj8CPLzAxa5OEqoQt3uMA0dCSgyFv2LovXFxAXl3U9omZ+jIerOmf0scDYFZ4Cjk4x8Bzb0xm/6wMRJahXUi7eKOQNBfFSlRnxNY+u8u6x0eLR9rZQJsBFNgTapyPe11i341lFAvV8GVMJsgmLfZeTV/A+CJWTGWbc7TTvNnWcbYK7l8zeSZ7dH4rEnOvERyY5kxDrOEwU/Yjdg0OIz0cgmb+dlRmAPiX3OWjxUXJg4aSEFFG16FvCKl2nOFUF8LecaPl1ENKZOzyeeouQpzJp6MwRbCvWKCbKjmM2LofkPlbYC3ljZcmitkM3M0iUQSDo8uwQ71JEBqciChTxdYCFkbs5lTGlaj7NMUVD0hinIuBaEJQ1j0Irfxqf1ncrLdx8ZNQfA0gzLgSYcvydd0BeII/j0Mao27RFzOAqYLYT4lwZn3J2ZefvqYbOF2Sifr+D0ZdG7elOtYhiRAUEHGhPSUWaoI5CpzqRPYnRva8JuLDZi4Kj0EyjpgPrSYN9dp01ryHcTMd7FaHIiskbn258Y9zpaK7mnlVvyKtjxlJL6MtuIV32lhcB+5EW7WH/6QDYQTwSBHw8UP0tyMyNbps8z+8Q5FmgH8vHxFljollei7t8eaPHYkk5rnVsXfTSQ4SjT3Ki6R/yfZ5BEnJidV+OTY4jtwp6TKE+kf6ioudhBQQXHEpufZoZaVaTZXTiIGuNSUBDlZ8hnbIS8ou6QcKMly3uw16qq1jpI+sVrLhWSLFcfRqW774uvsXptcHlY3jyOYYvgNSnLk9DHpURDX2VPzmVnzh4qOFmePV/gjmpSqLQpV1/iNIt9g3DADVd6eBWCjpp7/eefKoA1yLf1v3cLqoz1NFJZDj+xZBAIGNokT1IaiTnENcvwwJWL3xKUl+n4thAe+UgHXKJZ2an3jTF5IKjCZK3wFTIHqnkVBqLbYTnNr8t764mZT1/9wh4OKLf46TVR2knmcx1cuUtGr3Sewy3daul0qF4ixlI8qx00gkAJPhMSgdD9NphN7vd38cFIdIrhJ257ibJH98P6LFTvtBlJtLNk0e8UNLU9gvqtKe+mlotbHy1WlN3l1P02b370hBTcnBA0JVykYqIO2Yux+kvP"},{"id":"dd12cc44-0c95-45d5-a726-e7b8bcf2531b","repo_id":"1095f823-f6f5-4e66-9aad-9f0b5b6b99d1","name":"API接口文档","description":"api-documentation","prompt":"创建GEO平台的完整API接口文档。详细记录所有RESTful API端点,包括HTTP方法、URL模式、请求参数和响应格式。文档化认证接口的JWT令牌管理、用户注册登录和权限验证机制。说明查询管理接口的任务创建、编辑、删除和执行功能。详细描述引用数据接口的数据查询、统计分析和上下文提取功能。文档化报告导出接口的CSV格式生成和数据导出流程。包含错误处理、状态码说明和API使用示例。","order":7,"progress_status":"completed","dependent_files":"backend/app/api/subscriptions.py,backend/app/api/admin.py,backend/app/middleware/rate_limit.py,backend/app/middleware/logging_middleware.py,backend/app/services/citation.py,backend/app/api/auth.py,backend/app/api/queries.py,backend/app/api/citations.py,backend/app/api/reports.py,backend/app/api/deps.py","gmt_create":"2026-04-22T18:56:47.083629+08:00","gmt_modified":"2026-05-23T15:17:24.331381+08:00","raw_data":"WikiEncrypted:rEJA+fDSevRLFPlWlcH+C02eArPzlHQTxpYkpRmh+m+CmPwrZOHSqyEVvpFbcfuzlCdXmMyG1qoekj03JLnUhMCX8p4fjuyWVCjGyWgOqZfEYH4zqWamc16YOPdK+sCFQ4QmdrKW6cFcIs/JSz1BcE42L6PRCsFSdjC3x3Ir2kmeZ2xCyI4DTuIg5MWkYlr15jZuzLH5rMyvHib5uxo2LCklVn7i/8Yc6NLOW0AIHuLJGKU9hVU2nes18OolWvbkowwiJKV4MSqSrfUSL53HCd6IbvHajavu3hulkI00H4b/6Rkqq/mkJOEzBVSWXMI2Vj0Ww7mlzTkfkOv9v5Kp1CMC2qupcuFy78Q2J8fnj+tjDbvXOrkAe3LGWo59kGJXRS+LdWUjxsPwbaItkh9PFj2MOBQJ4dj38tLJ7OTH8Zag/VQP1Rr0yLqacQC0kduxAW/GKP5mj949etgdOr5Lsjt2hG9a/1bqVl7DWYX88aeyobv3qSg0/o/486gC040fYXNi3RFhZJev7cFLhxmkWPUFqKblmvIDwS5eDfYnWF4VVACVcqUVKWN/0V1whA2/u83e0nSdQLHU6gs1dAadBeJ0WvtCalaRzumPYSlz4Aw8pywfTE9u5GXpaONFFjCfgFuf6Mm3qpvL8InOKs1DhtGavpj+3P8MaFERk72a/Gb08fD1Ri60LsgMXjD5XdSw7IDRukJVTBRP80/vYYdNlDoeuM6uHvxuORxFCZNsTmC6PSerCo3AGnfpERUDzSV+ejU1fSrOc18pronb4I2lfIHjNpr3mjVLfnNEbsMRu/VHtk9lrPlkd3RxYRlC76W8XAK1cJr8Q6qtOz7qkNAs4W5VZoSO+6QAec2P5ej0aUJ0xR0Z1ZZhFyYPQE0VCrvcKSUJgeHUhcoBWbkPuxmk1l0FC4+Cu8JOksLcMRzb/2trJowZ57fQA7N/3YYOKlKW7wFqNXNJQ2djP2A5WflT9OL22/D0Py4o2wLDr7vtXv/4E2A0YJAPcqdwbeeYHN8Cika4GiA0Z48TomRK5PEPSop0NRekjHc2q3gppQK0+Pwy8GM0JOO04VeLCsbRKwjCrIB9+B9ciiBEDh2F/9+OxmySWZVKQB32NFozE4bT00ufcsFWApvwewZkiqUTWBaDjTrXxm1AnewI+T+/bLaY+m6Lr4yGO7jAuUDYkTSVT+IVNFX9ep2FVdMUqZFYp6+Vukj3nVwL8lRaG8zJaJ5TxxiB7grWdRXzaNT5CJlkTSEdFBkExAkNik1S4Xhfs2uU+BSvjZTzB7gOZKEYhjkV5m707rsT75hYFqeRLdIaCSWxZzHIHHTCxOfrAncP+2EkLHjP8bWAOjhdABT3djMsTSgm15W9NG8oAayRIoAE6M/ZAizrqiaAAKxQFAthKpGNTZZfdHNbxIfhk+D65kW8zTuk1aWN2k1ktFAc/sjQplPFkr/rY9K0PiBMFlXrye60kFAtFxjRpPUbtuRr3sMdJjPiHxB/bIi9XODVl9m7eyjDeTZFKmmxzafzNT9VP+YpBSy4QdKXaZkR219fdyhs52iRnGXP+9Phy6uUEh650InWE9CNFGZMSTRPpUkn9xJq/mVLJ667r9W0/aAs7ETC4g=="},{"id":"fc6f24c3-594e-4153-854f-19250834eeb1","repo_id":"1095f823-f6f5-4e66-9aad-9f0b5b6b99d1","name":"测试策略","description":"testing-strategy","prompt":"创建GEO项目的测试策略文档。详细说明Pytest测试框架的配置和使用方法,包括测试夹具、模拟对象和测试数据管理。文档化单元测试的实现,包括认证模块、引用引擎、查询处理等功能的测试用例设计。说明集成测试的策略,包括API端到端测试、数据库测试和系统集成测试。提供测试最佳实践,包括测试覆盖率要求、持续集成配置和测试环境管理。包含测试调试技巧和性能测试方法。","order":8,"progress_status":"completed","dependent_files":"test_output.txt,tests/test_business_flow.py,tests/test_scheduler.py,tests/,tests/conftest.py,tests/test_auth.py,tests/test_citation_engine.py,tests/test_citations.py,tests/test_queries.py","gmt_create":"2026-04-22T18:56:47.083879+08:00","gmt_modified":"2026-05-23T15:16:36.35803+08:00","raw_data":"WikiEncrypted:Xd2Zu8BM8p49theGlFJHkHqkA5ycuMpwkltd7rjxfkZm5u2F/OCOa2rxC3NxLrZDZf5D15q4Vh8tHCK9cPrOS/yjJEFoGKYx888+pCfJVQGvOvV8lbxJ/fNWDqo3ccIMDBY5poew3y/74L1tz0L9vjHRBLPVQADCR3UfTk94UBhlYGXamKDS74D8TgPqiuz1dVhmkX95unpFQiGQxCgxeV/sDgwTl7DYpnPy4VqFJbcPHD2Xvv828icOoxqz7hWaOp/65B5Vcn9P4LVk7dQmHzrLBdrDLBe+5Rv6mDD3+Rqrv3ZX+1v7tJ1dnmaQ2ZF8tE9ttI6ENeaFys0BrcucTSrsbSDtmFINzGh/aW0G3Q/YRtNfmkC9t+R8wRSnAgYadYSkUuNTVWQRRs4JxAcn+cHODObsEdp79EwDCqcLktVlpNaLJ//B0sOyLQA741MiLH5iM6tglYaOoQ48Ydyw7Fp5U9agWwgK7yZO7REk4ZB9U+juDzjf+qUHyjIVlXUxJXg7ATsy4euCmDpjyxJGRH7Z89wWkOotsSC3igqSM391kOqbzl9P5ZiruYliru20PndDwtXbJQ0jcvvKJsK3RkIYX0ml7BOL9H7Y16TL1Jwc6DVcRkwWQ4IEKG1fJhqYcb4WI/vPDD1jIhHBe6O5VAZtPPA+SIpYJg8+/qf0FQY73EPqWe0jPuc6I2jyN7UbjUMHRAeb0sVvj18qVYb4E+KKwNZyuAs+0SvTk/nTgqFPdNrOZ923/jnJTNt2Df1p89NDS0NGeHobiC4XD8koxe9vshUUdeDjXIopttcYBg4LcWAudoq8OO07eB6xiqn/MwXPaZySdWrqr3bh2xxxaQPR/NTrfrBkN+81NO784cJEkYHfSfUzIqhLhTTNEQpfl12WDM+GnbHWCcyWuN2dvZ6Op/ZCpLO+cQhZnXFPILnCzFf8DyNrbD3niQYcOC6H1nFlaGSmx57lswjyX14vwqOB+yNR8n+xG1a7JwxscBYaNQG5kvfLaJJKpxIdSB2YIKrIwImPHtzTI1Qahh3MfLtqI99aH9p/1LMaKJQsASKr1Ja1X3dO+ZpIiQRTeDR/jdWnzBA7Hk9SjB6ALHJhLYTutqKVkeIL08U9HNeWn3BFwCthEXMHapg0Vh/guoIq1j28UwzPkqMcSynuv98uyhHfUgRbOWQ9WTDis8gPn2jxpoCZyVCAxOTfF+67GDoTn6smJmqHIkQkMjrxLVZE3FfMtXHAcZ2kG9DC1aLVFNm64bP9X/W11dT6vm5SkabIiu1AzYuZDce+Rbg73WaCMrv4sXmBpNYhYUkLRj4gwNEFSd+eOJ/GS6MZSkA7p6A73OY1PHXlRnFrcLN10/XzFaPAM8L3h4WmqYoxFNJPTx5hRuwX2MfiwZgZlaICfBuO"},{"id":"803bfef4-3985-477e-a61c-915a246d0061","repo_id":"1095f823-f6f5-4e66-9aad-9f0b5b6b99d1","name":"部署与运维","description":"deployment-operations","prompt":"创建GEO项目的部署与运维文档。详细说明Docker容器化部署的完整流程,包括镜像构建、容器编排和环境配置。文档化生产环境的部署策略,包括Nginx反向代理配置、SSL证书管理和负载均衡设置。说明监控和日志管理方案,包括应用健康检查、错误追踪和性能监控。提供运维最佳实践,包括备份策略、安全配置和故障恢复流程。包含CI/CD流水线配置和自动化部署方法。","order":9,"progress_status":"completed","dependent_files":"docker-compose.yml,backend/Dockerfile,frontend/Dockerfile,backend/requirements.txt,frontend/package.json","gmt_create":"2026-04-22T18:56:47.08417+08:00","gmt_modified":"2026-05-23T15:19:55.903951+08:00","raw_data":"WikiEncrypted:XJiAh4Py4zdOGBbpygpFvP2f+xZrLdOVjdkWVTkd9gNZugMlEc15uGPZP/rOKei73finM/xzqTLj8dzUBfzhoso2Si3u9jWEKBhnERW9MW+jwXRrsLHgJ8/WEK9QHKbGl5gw2ib+bp5Pwa3apjwkDwN5hBQC4+vjqTVbQlLqK0Ec0taA3iua9wbtV8nY5tSgUrtYRdRqzYd0Em0JPfrNHfDBKqGbhIQEUICLTk1cXUkVNLZKNUKN2gJ7Q9NlheaerlKDVWNp7Mt5ZecokwsM47Wiey36A1pO4kEQC1jZn/NgxPB30sC1zrjdI9mVBfMdWMqeNtBsE5zL8M/Ix6ikOpjqm9PfHkvZrqrO0WGPE73wyU+o4Y9pOZBbS3LmrWZVjTFjhJpbRCtc6yjqX6cnon067zrHSs6jN3OwPdIL2QlEK0kfeK3Xd7Gmgpciptuo4sAetP+NGr7L8qUmtZNA0LJj+G+6vT1ErRdauMsNrnHaWSPvz8j85Gi0LZxFyvHiY0jh+p4llPzjOdvFBF+0Js0sQE70kxor3NCunmf0YkA1+Xn4UhiJnQTVC6FSA/n6ZHmiyK5XJ9Ca3IDAnYdxZAZ43BodukbTg81j6fHPL03zHVg3nunXKZc11hTWaTweKhrfSzff+W7/183vgUybq811/AaSC/wXh483Lj+/QHEYJCz5kUSnMkw5ZcBJM8WV4Nh1+68paKY2TnViG1OkbNXQar07qmeyz+1Qee5lVPriiiYAulSw4fc5w0tssZVrJXpDP+SseXKQDiqxEToU0cz3TdWLKEV9p8koKUGYYAU5q8rP03IsmocbgqvSQf6RJ/B905IWZ2UK2QQop28wF4NOBt395jw/7+LbLwMnmLw4RP67Z1ptgrZksi437IrZyhuOhAzO4cqml7FP+lVNfdYIsIi+BYAfow60IWKBkBg4j3Ljwhqxeggz6flWuRMtwcSGty7LRv6pNy9Q1ofyxZTDBkvFnRmJpBOKkgUxSZBwKLavC88mCLPet/b2LuLGcj7nMw4KW/xBxqt5eR3zI6OHs/6eYvLe0Qv9aln8WRnBJFXe9PtVPjlkCr4C/+liP+3QwiNS3+fSazJtX6pRe+3R4zzU4uVkLhoIc0lxDc5q7MUBUhnigZHESotAn/B8Y7izX/69qm2ZzZWIvwRMR25GjM6PgIz2eAFzsZb0Vmy2CuPE3r86A2/svEjBSnsIeag8jTo7oAclMCCqWKa1Av0kSrFyZug4OYkIoTnOOCCq+JPuuiRdX2BsIApIHHZv"},{"id":"2148d7d6-25c4-497f-8894-c4eb7a0d2bd7","repo_id":"1095f823-f6f5-4e66-9aad-9f0b5b6b99d1","name":"开发指南","description":"development-guide","prompt":"创建GEO项目的开发指南文档。详细说明代码规范和最佳实践,包括Python代码风格、TypeScript类型规范和命名约定。文档化开发流程和工作流,包括Git分支策略、代码审查流程和版本发布管理。说明开发工具的使用方法,包括IDE配置、调试技巧和性能分析工具。提供新功能开发的指导原则,包括模块设计、接口定义和测试要求。包含常见开发问题的解决方案和故障排查方法。","order":10,"progress_status":"completed","dependent_files":"push_script.sh,frontend/tsconfig.json,frontend/tailwind.config.ts,frontend/.eslintrc.json,backend/requirements.txt,CONTRIBUTING.md","gmt_create":"2026-04-22T18:56:47.084469+08:00","gmt_modified":"2026-05-23T15:18:41.224011+08:00","raw_data":"WikiEncrypted:9b1XqHriaqPGsMtQmhzV28eiWwL8soWZUx4jD7Lpj1ZvEeRHqDXnLB57Wv0GJdW0bSai+es/AGcSLV4r5Y1zXQCgYNssGUbbdn66dv22fGk42xijVyio7TzEJPm2vZsrwpJe+/yfqkj5uigIlIv06GRfmEvdn6T8ivaGf4o8qPrbbaCqfb656Ecihx7i5F1ZXK+etNk5HJeheOAvl/WoiZD0TchF59yuuB06Rl/W0/sfm7xUtkC5QYYoo6qYsIuOIE9ynhoHFI2junjkQwS3m3E/W3kKHTNe57a56kaMBo2fa1in+LuWr0jPxfsXJWHwwN47eEs+neAYXoxz+AHzJxrd+FTvW8o+Jr7hmJjODk/1u5VGWqquek2DS33JHThmmD3ant8C85SI0QDd2Rez4xia2mCq+kIzwnOuORyodpDeIHYWrwbL0X6Q4KzwwZKXYBlWZH+PqiovtlIQpZ+FrabfOImECKTIsdYECFDGwvOvZdH09Kmi2TqBszsArbv/apEc8HtRyn3MbxlOmBZ3C86pepDzntKeY8OsRhZv1/EHc12+zlfgBxkzS7g3sZhf01vr2xPsYdFU6Zpts9eWNmMJAthuG+wyeYrGDXuGHQFbXa7Rhz/mWmDKqcUZcrGo2ScQwNuk19uCmQ5x7ZTM1iNSbKYWaJwW4jn9gG8sw9+saye/tFTCyDoaqyyumHT8s/aE3bvalg4fA4AE8RigKIlwzLKW7sZmL8sY6b3PBgIJB054DRRSUF/jEW24wPDgcW29SEG6MwyqEVCpBGvI1t7zhmmM6IRklQNvVzGaoQ5GkTDxAaMh5ULEbqPdmjMJkyTP8xtyLhrJz/UJRuvvFOpf2zyyHg8Do9zNEP/FNUbq2sjjMPwMUwZAVcU2jQvNyiUYJXLvzaYk7fSEr74I3YbU9XE+/dofBpCd8tPG/BmV09UZCVgI3UrSRYd+GcgziKhnbDf/UVR691bhj4lUBtNzyNM2AnUWoQN9IMyjpMEo6EDlTrIL6wqn36aRNqPibx1vbsAdFAwmJQbf0oVZ43AGDJde58EOtIh6QzXdY5yj+UYIl8iCXO0VtnMm79ouguB3g59SOTIbv6X/iFjQ3rvERX6pFPBI9GyKfhKQTwib98D+9pkHnU2n625WeukHx67ieQLvZ7pZLfqMYTEQvo80N0JfbAP4FNz4Mtuc7jpXm2JyV/tAI/Y4Lbx1KMUq2mDsZRamD6HWF61GEGr94VsrM8kFcf2RHb9C6Lt3EuKlasgwJqSnr8iO5oONILiT"},{"id":"b2bb2e3c-5661-497c-97dd-15bf6ee8b7d4","repo_id":"1095f823-f6f5-4e66-9aad-9f0b5b6b99d1","name":"扩展与定制","description":"extension-customization","prompt":"创建GEO项目的扩展与定制文档。详细说明系统的扩展机制,包括新增API接口、前端页面扩展和数据模型扩展的方法。文档化配置定制选项,包括环境变量配置、功能开关和性能调优参数。说明第三方集成的扩展方法,包括新AI平台接入、新数据库支持和新认证方式的集成流程。提供插件系统的使用指南和扩展开发的最佳实践。包含系统定制化的案例研究和实施建议。","order":11,"progress_status":"completed","dependent_files":"backend/app/workers/platforms/base.py,backend/app/models/,frontend/components/,backend/app/api/","gmt_create":"2026-04-22T18:56:47.085228+08:00","gmt_modified":"2026-05-23T15:26:10.260607+08:00","raw_data":"WikiEncrypted:LeuqUwl+gnRWd4pQx2elJJnaNsYdZ/J63Pw0fce9aNqmpJpPYIsQ5TrEOxu/uvHnQSFFKBmEUts4wkhM6Rw84oLNhVY4dAAe1SgbxUSAMBPaB14KY8PUqWIpdCEioEWmzsnVj7K/kD5jbg2km9CoQTfth8WHg/Y6a9BjIyCgjHAkN8xdYtoIZ019phFFwhiFZHTzwOMsaOLE4uNYhO/5VtM7enfDpbUkYkPKaI9O89GwD5CV1zTnlHpsmZpnGl/lWC/ucBfeyb0EAeKXW03W4in8q8jTKNJYPZnawgbDI9LGakgP1/F6i/T2CTB7vUWI3RvEcxDjIFn/g4Y9lrvxxRwi7tELxBj1tRN1UQ/UWC++syM1xNd8EqmIsChyPd/qyec4Cq8hwcS20hlCJ/A5b6lkkrCcVSybCKYh2rTwydQ0IyvDY4CBB/IkmGyuRiir9sLD7ikE6/pyC5puDhgPwf0C9dgMOcDm3Hprnsj2fNPGx5XiCghoWPOws5Nlqf8hLtlXGYO1rIG7QXzZHlSsqHr1Xx19ZR7PbU3xd5Lzgz9QlTbqVeTIyFnM4NPhSHICOwmIDlPFhO8Hb3uwgfAgq7DFiQNhSaVXFzWC6xw+ai66iwkC6IuqjxlW2zpJ/tRo15UZ7Jwwt5QajmUIgxHjERg7s/ccW7jYphuD4P4NjCD9aqveeWlujnM9OUglJ/BRS8lrVKjd11Po/t2FayPjpjAjoIfRK2r6GykToOAcBdnulkEeuVJetR9lR3/6iZf9fd8rTRiN99+R/b39s1UPSyCuJW3N5XzSOT7em2iCquEFIPw7Mb8cx147EY3dis458UKoEMmUIhD/IzxL9kk3dlp8ypRv0REsXkYWYNK9pBAZAE9RO0pAz/4KiHYRlw3tpR/h+QNQFjEIl26ntoyFpK0iCgQNwD+tloHz0YrpfvIk0syjsbZyEKBexmsMrvRO+d4/6Tjba1Z8sujKcvCI4XcS1cSjwJB8l3mOYlONmFTBXwqAUtoV+oAbWIQYk35NBDsxQtndMU5JI8CdBd2+qW8IUlgnGbOEwOoM4zKpLxsE22b+g2Mm4JpJ0pcDPFSGqgQKTO2P0/IoyjFU+6cBk8Xu/i9uBitDoXLU6kbntHlRM4BW+ndKIN0VsWVgq1LoKJFqyRl6uzvpbPLv7KjVuN7TwalTWG+XIPN7UW2iReTfVVTfvBftrXpVHqmJeRL1"},{"id":"8e3d62e8-ddbe-4820-bc41-7da9e91ea598","repo_id":"1095f823-f6f5-4e66-9aad-9f0b5b6b99d1","name":"故障排除与FAQ","description":"troubleshooting-faq","prompt":"创建GEO项目的故障排除与常见问题解答文档。详细列举和解决常见的认证问题、数据库连接问题、API调用问题和性能问题。提供系统监控和诊断的方法,包括健康检查、错误日志分析和性能指标监控。说明调试技巧和工具使用,包括开发环境调试、生产环境问题排查和性能分析方法。包含常见错误代码的含义和解决方案,以及预防性维护的最佳实践。提供紧急情况下的故障恢复流程和应急处理方案。","order":12,"progress_status":"completed","dependent_files":"backend/app/main.py,backend/app/config.py,frontend/lib/api.ts,docker-compose.yml","gmt_create":"2026-04-22T18:56:47.085508+08:00","gmt_modified":"2026-04-22T19:04:06.13183+08:00","raw_data":"WikiEncrypted:CaKOW8OSSWs4aEYk06Hu0tuZET5JxbVXxA/4vFailoRiq8l6SCRMdp2PbHfZPheZXyPTAgE3AT8Ce8j9xPOCdJxNKAOstuOjZEIRRi9OOYwoluR4MUnob24X+IyLHwTgsJGf9uPY1LVFTI9RTQt8aG1cBHibaRNEJ8+DVkXJW/EDypOxFpOxDxlaCscMdiPRLwhr9V4vJqWV9j2rk1LjP2/M8SJJQ8hbaDoeLevKdECB+aEw9JrL9ycGW0dhxKxQLf/ril9zNHrvahlSXbVZSZ39dpBl57NdFcFaOYt+paf3O6hv3bCTAKGLTRnYa/IuAZ6Xa7YnhqaGQ684LKCBz6VySRNYVUCEvZotYHf1IQdWOj0zFzR7LEIEikIlZyKak++yTNYfbQyBEzye3g6YCmlh6VaVmtGIRzjOYpu0K1UftNcRa1mWnIMrB/Pqe9DpNTg+Yxo3ZHrPyv3ZAmrd8MqA+T+P+/NerCmFD3dRf94NLPP8KU7in+VSfEjVmdE0N+3OfntU+uvNL/kkOhyWNRUKYKFxbqdwCTKqv3Nchs73XyhfNRP7gPkR/stgnowCRnKWS4ncUEJDZTWVFID52kE8nH7Kq/yuB5bJxFX9AeUUaNSBgvMc5YNkq3vULFEqC1/N0bpU4r9+0/U/BcMktmNrRr1HnOIPl3QzwjIsT3j2lp4UXS3Qm4BZFJsh8MVLfgOIMbO1jbuGCXHl88T/rZOCNwf4q93vWo2HnOxDkbdICWgZ9dinRr85RkFQjNWlXdAk0XG8lQPotwJLvS+ZASOv1aWyL42jk/mTJcOU53PFT5rf3+WpVmhNWQGguZ0l04eubO4Va39c6h/+DNsl0OEAiozIMohEgz77qsD47Kf0KZMLnqL3o30TYXYamX/CP8+epBqSWgmzX/ETrrRl/1/JPkSDc//0VC8UmWBJAsdUdzyQh9v9iQddyIZ4MV1k4MGTJ6GwrUqVTszShZJVG80wDMLQvJGqJ0T5rH1P7kBaJ5nBnth822MBy7B1IhN6nDqtLhOJcqT8Qt6x8ODGFx1QMNBdS4lHq5IcRy+nZKiPP3V7uMuuFQsNNodTRhmNnuAliJACWS89hPiGroan2VkusxIu2DW8wdQ/3Z31mIn4cE3O3+Aq6lO+BEMAuYh5WkOEmGsF3cjX/zPPiuBSP7Vd2a9o6gPA7MBfneMWyqodMp6PKh7EG26gaKUaIGq6VkQobSAVfbLxmfIMW6cZ5STH4U1/A7gV2PeuWzwwEJz7axGVQIJ6A9geQevZvD/cnX6BQBuOMkdAOB6PApCpQA=="}],"wiki_items":[{"catalog_id":"1bb55e12-24c4-42cb-8f59-ddc303460d45","title":"项目概述","description":"project-overview","extend":"{}","progress_status":"completed","repo_id":"1095f823-f6f5-4e66-9aad-9f0b5b6b99d1","reference_count":0,"id":"34e572eb-6fc8-4de7-8061-63783ef8be24","gmt_create":"2026-04-22T18:58:50.323135+08:00","gmt_modified":"2026-04-24T10:58:35.431256+08:00"},{"catalog_id":"e3ae8925-4862-4280-b85a-0b376841b15e","title":"快速开始","description":"getting-started","extend":"{}","progress_status":"completed","repo_id":"1095f823-f6f5-4e66-9aad-9f0b5b6b99d1","reference_count":0,"id":"7f028ad1-e989-43ea-b945-c79c33e6f0e3","gmt_create":"2026-04-22T18:58:54.232866+08:00","gmt_modified":"2026-04-22T18:58:54.238013+08:00"},{"catalog_id":"7c2ac186-ec90-400a-ac1d-b3b7ca2f01d5","title":"后端系统架构","description":"backend-architecture","extend":"{}","progress_status":"completed","repo_id":"1095f823-f6f5-4e66-9aad-9f0b5b6b99d1","reference_count":0,"id":"c7eb113b-b503-4d83-be7f-9ccf3350c9d9","gmt_create":"2026-04-22T18:59:20.999631+08:00","gmt_modified":"2026-05-23T15:24:02.350823+08:00"},{"catalog_id":"d907a8eb-795c-4060-9cdd-50d31cf39be3","title":"前端系统架构","description":"frontend-architecture","extend":"{}","progress_status":"completed","repo_id":"1095f823-f6f5-4e66-9aad-9f0b5b6b99d1","reference_count":0,"id":"3af3bb9e-4d99-4dc3-b1ed-2686db385c26","gmt_create":"2026-04-22T18:59:54.989699+08:00","gmt_modified":"2026-05-23T15:22:58.592546+08:00"},{"catalog_id":"243a1a45-d31f-405e-a3b9-694d2fe617d5","title":"数据库设计","description":"database-design","extend":"{}","progress_status":"completed","repo_id":"1095f823-f6f5-4e66-9aad-9f0b5b6b99d1","reference_count":0,"id":"ffbb970e-56e0-40ad-bd88-1a1e55482d96","gmt_create":"2026-04-22T19:00:15.762815+08:00","gmt_modified":"2026-05-23T15:19:23.714851+08:00"},{"catalog_id":"7416db23-312f-478d-8883-2fc3c41ac2e8","title":"任务调度系统","description":"task-scheduling-system","extend":"{}","progress_status":"completed","repo_id":"1095f823-f6f5-4e66-9aad-9f0b5b6b99d1","reference_count":0,"id":"deb919cc-9541-4ed7-a581-ae2876ea67c2","gmt_create":"2026-04-22T19:01:21.979952+08:00","gmt_modified":"2026-04-23T15:20:09.061378+08:00"},{"catalog_id":"7e66719b-4a8a-484d-889d-10fdc76788bb","title":"AI平台集成","description":"ai-platform-integration","extend":"{}","progress_status":"completed","repo_id":"1095f823-f6f5-4e66-9aad-9f0b5b6b99d1","reference_count":0,"id":"cfc48cde-e1c3-47f6-afe2-a6d7a8f4ab69","gmt_create":"2026-04-22T19:01:25.981164+08:00","gmt_modified":"2026-04-23T20:31:36.620216+08:00"},{"catalog_id":"dd12cc44-0c95-45d5-a726-e7b8bcf2531b","title":"API接口文档","description":"api-documentation","extend":"{}","progress_status":"completed","repo_id":"1095f823-f6f5-4e66-9aad-9f0b5b6b99d1","reference_count":0,"id":"49915365-e38e-43b5-beac-6aa7d5a74cbb","gmt_create":"2026-04-22T19:01:28.269494+08:00","gmt_modified":"2026-05-23T15:17:24.331789+08:00"},{"catalog_id":"803bfef4-3985-477e-a61c-915a246d0061","title":"部署与运维","description":"deployment-operations","extend":"{}","progress_status":"completed","repo_id":"1095f823-f6f5-4e66-9aad-9f0b5b6b99d1","reference_count":0,"id":"98909ecc-fceb-4ab7-a26f-741838eb2e50","gmt_create":"2026-04-22T19:02:23.847103+08:00","gmt_modified":"2026-05-23T15:19:55.904209+08:00"},{"catalog_id":"2148d7d6-25c4-497f-8894-c4eb7a0d2bd7","title":"开发指南","description":"development-guide","extend":"{}","progress_status":"completed","repo_id":"1095f823-f6f5-4e66-9aad-9f0b5b6b99d1","reference_count":0,"id":"643984fc-5a57-498b-8f25-68cc318d9d82","gmt_create":"2026-04-22T19:02:27.517117+08:00","gmt_modified":"2026-05-23T15:18:41.224209+08:00"},{"catalog_id":"fc6f24c3-594e-4153-854f-19250834eeb1","title":"测试策略","description":"testing-strategy","extend":"{}","progress_status":"completed","repo_id":"1095f823-f6f5-4e66-9aad-9f0b5b6b99d1","reference_count":0,"id":"b0c36b2b-bb03-4624-933d-c1f6a320b7ca","gmt_create":"2026-04-22T19:02:30.709013+08:00","gmt_modified":"2026-05-23T15:16:36.35829+08:00"},{"catalog_id":"7c3e3c0b-5d1f-4d64-99be-668041c6cd9d","title":"核心框架配置","description":"core-framework","extend":"{}","progress_status":"completed","repo_id":"1095f823-f6f5-4e66-9aad-9f0b5b6b99d1","reference_count":0,"id":"f94da0b4-8a07-4de1-b0b3-d3b32a12c3c1","gmt_create":"2026-04-22T19:03:21.689103+08:00","gmt_modified":"2026-04-22T19:03:21.693211+08:00"},{"catalog_id":"b2bb2e3c-5661-497c-97dd-15bf6ee8b7d4","title":"扩展与定制","description":"extension-customization","extend":"{}","progress_status":"completed","repo_id":"1095f823-f6f5-4e66-9aad-9f0b5b6b99d1","reference_count":0,"id":"c5849940-e223-4222-be17-aa0a6cb36bc8","gmt_create":"2026-04-22T19:03:46.027426+08:00","gmt_modified":"2026-05-23T15:26:10.261496+08:00"},{"catalog_id":"8e3d62e8-ddbe-4820-bc41-7da9e91ea598","title":"故障排除与FAQ","description":"troubleshooting-faq","extend":"{}","progress_status":"completed","repo_id":"1095f823-f6f5-4e66-9aad-9f0b5b6b99d1","reference_count":0,"id":"85306af2-0edf-42b8-b7ad-c03e769cb1e8","gmt_create":"2026-04-22T19:04:06.127415+08:00","gmt_modified":"2026-04-22T19:04:06.131953+08:00"},{"catalog_id":"bcaa04da-04e3-427f-ba01-847ad657e78a","title":"Next.js应用配置","description":"nextjs-app-config","extend":"{}","progress_status":"completed","repo_id":"1095f823-f6f5-4e66-9aad-9f0b5b6b99d1","reference_count":0,"id":"c112a3f4-b0a1-4c4a-a325-e3ede8c90be6","gmt_create":"2026-04-22T19:04:47.356556+08:00","gmt_modified":"2026-04-22T19:04:47.361504+08:00"},{"catalog_id":"9e3d703f-f424-47f4-84df-b99873b93e5a","title":"项目介绍","description":"project-introduction","extend":"{}","progress_status":"completed","repo_id":"1095f823-f6f5-4e66-9aad-9f0b5b6b99d1","reference_count":0,"id":"2793782c-91c8-4052-b9db-39513426c736","gmt_create":"2026-04-22T19:05:00.372036+08:00","gmt_modified":"2026-04-22T19:05:00.376145+08:00"},{"catalog_id":"a06436ee-1678-4a51-bbf8-b0d0ac3456b9","title":"数据库架构","description":"database-architecture","extend":"{}","progress_status":"completed","repo_id":"1095f823-f6f5-4e66-9aad-9f0b5b6b99d1","reference_count":0,"id":"d5c75004-b01b-416f-850a-4791c5489a32","gmt_create":"2026-04-22T19:05:13.619093+08:00","gmt_modified":"2026-04-22T19:05:13.624074+08:00"},{"catalog_id":"7fea5a24-e6de-4003-bc70-9dae6d8fdb25","title":"适配器架构设计","description":"adapter-architecture","extend":"{}","progress_status":"completed","repo_id":"1095f823-f6f5-4e66-9aad-9f0b5b6b99d1","reference_count":0,"id":"37003fc0-1cf5-4264-996b-40807001875f","gmt_create":"2026-04-22T19:06:14.01196+08:00","gmt_modified":"2026-04-22T19:06:14.016291+08:00"},{"catalog_id":"b027f234-4ac5-4d6d-9b38-afc8054325f5","title":"单元测试","description":"unit-testing","extend":"{}","progress_status":"completed","repo_id":"1095f823-f6f5-4e66-9aad-9f0b5b6b99d1","reference_count":0,"id":"8150ddbb-7aa9-48d0-9953-2ef55e4bcfd5","gmt_create":"2026-04-22T19:06:55.084551+08:00","gmt_modified":"2026-04-22T19:06:55.090188+08:00"},{"catalog_id":"940e5918-1689-4001-a284-44f2de75b8ee","title":"认证接口","description":"authentication-api","extend":"{}","progress_status":"completed","repo_id":"1095f823-f6f5-4e66-9aad-9f0b5b6b99d1","reference_count":0,"id":"7c7564ee-7fe2-4555-8ff0-4ec1b757997a","gmt_create":"2026-04-22T19:07:12.352034+08:00","gmt_modified":"2026-04-22T19:07:12.356599+08:00"},{"catalog_id":"78288302-33bd-44f7-8b29-24f516c8b6bb","title":"调度器设计","description":"scheduler-design","extend":"{}","progress_status":"completed","repo_id":"1095f823-f6f5-4e66-9aad-9f0b5b6b99d1","reference_count":0,"id":"a1cc822d-5382-431c-8c49-cf398fb5eb3c","gmt_create":"2026-04-22T19:07:22.166733+08:00","gmt_modified":"2026-04-23T20:33:30.132576+08:00"},{"catalog_id":"6406f42a-e10b-4a2b-84a5-0a21c1c759ea","title":"代码规范","description":"code-standards","extend":"{}","progress_status":"completed","repo_id":"1095f823-f6f5-4e66-9aad-9f0b5b6b99d1","reference_count":0,"id":"13c568d2-dfa7-4d1b-81c0-dfef247cbb67","gmt_create":"2026-04-22T19:07:51.271116+08:00","gmt_modified":"2026-04-22T19:07:51.274241+08:00"},{"catalog_id":"a91fff3d-ec5e-43df-8176-22f0084109ef","title":"功能扩展","description":"feature-extension","extend":"{}","progress_status":"completed","repo_id":"1095f823-f6f5-4e66-9aad-9f0b5b6b99d1","reference_count":0,"id":"d2c7157d-157f-4990-8f76-11f3ea5435f7","gmt_create":"2026-04-22T19:08:25.13644+08:00","gmt_modified":"2026-04-22T19:08:25.14088+08:00"},{"catalog_id":"e8ec6ac6-ad1a-4332-a7be-727b47d71233","title":"Docker容器化部署","description":"docker-containerization","extend":"{}","progress_status":"completed","repo_id":"1095f823-f6f5-4e66-9aad-9f0b5b6b99d1","reference_count":0,"id":"1ed0b482-3d6a-4bfd-af40-47a5d1f3e802","gmt_create":"2026-04-22T19:08:34.079807+08:00","gmt_modified":"2026-04-22T19:08:34.084736+08:00"},{"catalog_id":"c19260e2-5163-43d4-b35a-b48aae995f4a","title":"认证系统","description":"authentication-system","extend":"{}","progress_status":"completed","repo_id":"1095f823-f6f5-4e66-9aad-9f0b5b6b99d1","reference_count":0,"id":"df661133-efbf-43fe-97c3-f581c81f47a7","gmt_create":"2026-04-22T19:09:25.676813+08:00","gmt_modified":"2026-04-24T11:02:17.638458+08:00"},{"catalog_id":"9b71fe02-5927-4a19-8db8-66eb129ecd9a","title":"认证系统前端实现","description":"auth-system-frontend","extend":"{}","progress_status":"completed","repo_id":"1095f823-f6f5-4e66-9aad-9f0b5b6b99d1","reference_count":0,"id":"2b32ec11-d228-42c0-9232-103ba7e44f71","gmt_create":"2026-04-22T19:09:48.743111+08:00","gmt_modified":"2026-04-22T19:09:48.747746+08:00"},{"catalog_id":"b80dc237-1a6a-401f-9f4d-14190edebcdd","title":"技术栈","description":"technology-stack","extend":"{}","progress_status":"completed","repo_id":"1095f823-f6f5-4e66-9aad-9f0b5b6b99d1","reference_count":0,"id":"e23bd86e-b4ac-40eb-b1c1-38d929fd5419","gmt_create":"2026-04-22T19:09:54.21211+08:00","gmt_modified":"2026-04-22T19:09:54.216205+08:00"},{"catalog_id":"7e5c3b8e-5aa3-448d-ae52-d5a96a413b0b","title":"表结构设计","description":"table-schema-design","extend":"{}","progress_status":"completed","repo_id":"1095f823-f6f5-4e66-9aad-9f0b5b6b99d1","reference_count":0,"id":"c3fa653f-8dd7-41fe-8c2e-8b60adbf70f4","gmt_create":"2026-04-22T19:10:23.573187+08:00","gmt_modified":"2026-04-22T19:10:23.576944+08:00"},{"catalog_id":"cc7a1f1b-c70e-4c61-bfbc-6dc408a12ff2","title":"查询执行流程","description":"query-execution-flow","extend":"{}","progress_status":"completed","repo_id":"1095f823-f6f5-4e66-9aad-9f0b5b6b99d1","reference_count":0,"id":"2fc79486-ec65-4533-860a-89c8877c2ea0","gmt_create":"2026-04-22T19:11:29.34722+08:00","gmt_modified":"2026-04-22T19:11:29.353951+08:00"},{"catalog_id":"fec685a0-c9bb-4048-baf4-40b56b2aa29c","title":"集成测试","description":"integration-testing","extend":"{}","progress_status":"completed","repo_id":"1095f823-f6f5-4e66-9aad-9f0b5b6b99d1","reference_count":0,"id":"8c17b44f-1586-459b-a83d-c9b961cd2142","gmt_create":"2026-04-22T19:12:37.811472+08:00","gmt_modified":"2026-04-22T19:12:37.820956+08:00"},{"catalog_id":"9fe32b83-3697-4939-8b10-524f5ed3e65e","title":"Kimi平台集成","description":"kimi-platform-integration","extend":"{}","progress_status":"completed","repo_id":"1095f823-f6f5-4e66-9aad-9f0b5b6b99d1","reference_count":0,"id":"2126339b-b0f5-4152-924b-cbe028cd0c39","gmt_create":"2026-04-22T19:12:57.009145+08:00","gmt_modified":"2026-04-23T20:35:18.737804+08:00"},{"catalog_id":"b10c2334-a850-471a-9851-a1c698e3a485","title":"查询管理接口","description":"queries-api","extend":"{}","progress_status":"completed","repo_id":"1095f823-f6f5-4e66-9aad-9f0b5b6b99d1","reference_count":0,"id":"74d3018f-4e23-4687-8bf4-7fb403f479f7","gmt_create":"2026-04-22T19:13:13.111099+08:00","gmt_modified":"2026-04-23T20:33:57.632097+08:00"},{"catalog_id":"0c1d3542-92cf-4796-8dba-82caf2f7b361","title":"开发流程","description":"development-workflow","extend":"{}","progress_status":"completed","repo_id":"1095f823-f6f5-4e66-9aad-9f0b5b6b99d1","reference_count":0,"id":"222a9371-45c1-4e0d-b1da-e8ada1c501c2","gmt_create":"2026-04-22T19:13:23.079488+08:00","gmt_modified":"2026-04-22T19:13:23.082539+08:00"},{"catalog_id":"109a8fb1-6619-4bc7-8481-e28cc2127d24","title":"生产环境部署","description":"production-deployment","extend":"{}","progress_status":"completed","repo_id":"1095f823-f6f5-4e66-9aad-9f0b5b6b99d1","reference_count":0,"id":"26f80935-eac2-44ee-bcdb-d6a79c537750","gmt_create":"2026-04-22T19:13:58.693673+08:00","gmt_modified":"2026-04-22T19:13:58.69756+08:00"},{"catalog_id":"4d5ac6d7-8812-414b-b8df-68574cc36d7d","title":"配置定制","description":"configuration-customization","extend":"{}","progress_status":"completed","repo_id":"1095f823-f6f5-4e66-9aad-9f0b5b6b99d1","reference_count":0,"id":"e1e0bd0e-01b3-4543-9781-d9beb32b9a57","gmt_create":"2026-04-22T19:14:17.837895+08:00","gmt_modified":"2026-04-22T19:14:17.84356+08:00"},{"catalog_id":"159f2ccf-71b7-4d1b-a4c4-c15b23a4126e","title":"API接口设计","description":"api-design","extend":"{}","progress_status":"completed","repo_id":"1095f823-f6f5-4e66-9aad-9f0b5b6b99d1","reference_count":0,"id":"11936bb5-374f-40f4-bb53-b75264fc4b9d","gmt_create":"2026-04-22T19:15:14.073829+08:00","gmt_modified":"2026-04-22T19:15:14.079089+08:00"},{"catalog_id":"9cc59a5a-f597-4707-b994-b6c49514d553","title":"页面组件设计","description":"page-components","extend":"{}","progress_status":"completed","repo_id":"1095f823-f6f5-4e66-9aad-9f0b5b6b99d1","reference_count":0,"id":"ba0390b3-c249-4e92-a3c8-6820343aeda9","gmt_create":"2026-04-22T19:15:16.958138+08:00","gmt_modified":"2026-04-23T15:19:43.818584+08:00"},{"catalog_id":"f70f5d9b-d7c7-4dc6-b36a-5f4508e6acaa","title":"系统架构","description":"system-architecture","extend":"{}","progress_status":"completed","repo_id":"1095f823-f6f5-4e66-9aad-9f0b5b6b99d1","reference_count":0,"id":"70b3948e-f456-42d2-b7ad-a0097ad5ee5f","gmt_create":"2026-04-22T19:15:17.448445+08:00","gmt_modified":"2026-04-22T19:15:17.452857+08:00"},{"catalog_id":"816a2805-76c9-4f32-a3cf-96428208081e","title":"数据模型","description":"data-models","extend":"{}","progress_status":"completed","repo_id":"1095f823-f6f5-4e66-9aad-9f0b5b6b99d1","reference_count":0,"id":"262a3941-fdc6-46b0-b767-be40aa9d5761","gmt_create":"2026-04-22T19:16:35.087998+08:00","gmt_modified":"2026-04-23T15:21:46.785271+08:00"},{"catalog_id":"64cbb894-755f-47b5-854e-c26c7821e9b2","title":"文心平台集成","description":"wenxin-platform-integration","extend":"{}","progress_status":"completed","repo_id":"1095f823-f6f5-4e66-9aad-9f0b5b6b99d1","reference_count":0,"id":"fab60eaf-9652-4cb5-9f9e-0525caa62d63","gmt_create":"2026-04-22T19:16:36.921828+08:00","gmt_modified":"2026-04-23T20:31:50.506906+08:00"},{"catalog_id":"412f8cb5-54c1-4f32-8966-fa0e5e75bbca","title":"性能优化","description":"performance-optimization","extend":"{}","progress_status":"completed","repo_id":"1095f823-f6f5-4e66-9aad-9f0b5b6b99d1","reference_count":0,"id":"d8e2cef5-37e6-44e7-8a7b-9bd365b82a72","gmt_create":"2026-04-22T19:16:37.806188+08:00","gmt_modified":"2026-04-22T19:16:37.81795+08:00"},{"catalog_id":"2f7fa0ab-cd3d-4f45-a1c1-389d5a0c2561","title":"开发工具","description":"development-tools","extend":"{}","progress_status":"completed","repo_id":"1095f823-f6f5-4e66-9aad-9f0b5b6b99d1","reference_count":0,"id":"979be617-a83d-4db9-b73e-38581348f8c1","gmt_create":"2026-04-22T19:17:43.348035+08:00","gmt_modified":"2026-04-22T19:17:43.3539+08:00"},{"catalog_id":"40ac97e8-7ef0-4198-82d7-d2e332be9d34","title":"测试最佳实践","description":"test-best-practices","extend":"{}","progress_status":"completed","repo_id":"1095f823-f6f5-4e66-9aad-9f0b5b6b99d1","reference_count":0,"id":"05e59a75-d52f-42e1-a924-f6a32f06f2fe","gmt_create":"2026-04-22T19:17:48.811042+08:00","gmt_modified":"2026-04-22T19:17:48.815559+08:00"},{"catalog_id":"41a414d2-e13a-497c-8a03-212624dbf5fe","title":"引用数据接口","description":"citations-api","extend":"{}","progress_status":"completed","repo_id":"1095f823-f6f5-4e66-9aad-9f0b5b6b99d1","reference_count":0,"id":"737f8d6c-bd8f-4c11-b142-71a400423323","gmt_create":"2026-04-22T19:18:18.048509+08:00","gmt_modified":"2026-04-22T19:18:18.055466+08:00"},{"catalog_id":"2713d5c6-c6b0-4a38-83f6-56940c2bf695","title":"监控与日志管理","description":"monitoring-logging","extend":"{}","progress_status":"completed","repo_id":"1095f823-f6f5-4e66-9aad-9f0b5b6b99d1","reference_count":0,"id":"eb1288f7-5ea1-413a-8f54-4f870306d14d","gmt_create":"2026-04-22T19:18:41.294736+08:00","gmt_modified":"2026-04-22T19:18:41.773932+08:00"},{"catalog_id":"c8a468af-2982-4d9c-82c0-313b5d2ee89c","title":"第三方集成","description":"third-party-integration","extend":"{}","progress_status":"completed","repo_id":"1095f823-f6f5-4e66-9aad-9f0b5b6b99d1","reference_count":0,"id":"e9a02c86-236b-49cb-bbed-9462ee123c04","gmt_create":"2026-04-22T19:19:17.34688+08:00","gmt_modified":"2026-04-22T19:19:17.362503+08:00"},{"catalog_id":"9eee7fab-6cd9-4ef3-9415-2f8137f1d199","title":"数据模型设计","description":"data-models","extend":"{}","progress_status":"completed","repo_id":"1095f823-f6f5-4e66-9aad-9f0b5b6b99d1","reference_count":0,"id":"23ad3419-5473-4e2c-ac87-d9715090279d","gmt_create":"2026-04-22T19:19:19.260533+08:00","gmt_modified":"2026-04-22T19:19:19.282116+08:00"},{"catalog_id":"f210509a-2381-46fe-8c22-0ed768e6ca70","title":"数据库迁移","description":"database-migration","extend":"{}","progress_status":"completed","repo_id":"1095f823-f6f5-4e66-9aad-9f0b5b6b99d1","reference_count":0,"id":"7c0201f7-9e02-4cba-9ee1-81c3477f049a","gmt_create":"2026-04-22T19:20:15.023549+08:00","gmt_modified":"2026-04-22T19:20:15.06665+08:00"},{"catalog_id":"d9e45b2a-6443-4a9b-8ed3-4c3c04773772","title":"UI组件库","description":"ui-component-library","extend":"{}","progress_status":"completed","repo_id":"1095f823-f6f5-4e66-9aad-9f0b5b6b99d1","reference_count":0,"id":"760610d4-dff6-4c6d-831f-7c9078db86a6","gmt_create":"2026-04-22T19:20:16.20858+08:00","gmt_modified":"2026-04-23T15:22:23.574113+08:00"},{"catalog_id":"178b681f-d013-44b7-aef8-dee7ca8c22a9","title":"核心功能","description":"core-features","extend":"{}","progress_status":"completed","repo_id":"1095f823-f6f5-4e66-9aad-9f0b5b6b99d1","reference_count":0,"id":"1c4316a1-f1d7-46da-bcfc-ea2fa0c56110","gmt_create":"2026-04-22T19:20:37.644038+08:00","gmt_modified":"2026-05-23T15:23:21.994326+08:00"},{"catalog_id":"ac0658da-7670-4e41-9e57-02d9d0d50680","title":"报告导出接口","description":"reports-api","extend":"{}","progress_status":"completed","repo_id":"1095f823-f6f5-4e66-9aad-9f0b5b6b99d1","reference_count":0,"id":"ae62f4a8-8840-4c8e-9a42-3373370299ff","gmt_create":"2026-04-22T19:21:24.241821+08:00","gmt_modified":"2026-04-22T19:21:24.246484+08:00"},{"catalog_id":"aad61788-1dc9-4682-b743-47188d7aecb6","title":"引用检测算法","description":"citation-detection-algorithm","extend":"{}","progress_status":"completed","repo_id":"1095f823-f6f5-4e66-9aad-9f0b5b6b99d1","reference_count":0,"id":"00359e45-209d-4be3-8795-50dea52bdba1","gmt_create":"2026-04-22T19:21:33.106655+08:00","gmt_modified":"2026-04-22T19:21:33.125906+08:00"},{"catalog_id":"7cb1d921-44ed-4e22-8bf9-baba7ff8b7c7","title":"新功能开发","description":"feature-development","extend":"{}","progress_status":"completed","repo_id":"1095f823-f6f5-4e66-9aad-9f0b5b6b99d1","reference_count":0,"id":"422c46b3-e69c-4023-a878-411a48ae182f","gmt_create":"2026-04-22T19:21:46.910999+08:00","gmt_modified":"2026-04-22T19:21:46.916175+08:00"},{"catalog_id":"c45e66b9-1ca0-41da-a796-6b98f394faa1","title":"运维最佳实践","description":"maintenance-operations","extend":"{}","progress_status":"completed","repo_id":"1095f823-f6f5-4e66-9aad-9f0b5b6b99d1","reference_count":0,"id":"aa6db9b6-71e1-4497-a0e2-f3ff25358d3a","gmt_create":"2026-04-22T19:22:39.442855+08:00","gmt_modified":"2026-04-22T19:22:39.447035+08:00"},{"catalog_id":"bfca5ffe-8905-4ac2-a0a3-8e4dc43533b1","title":"数据可视化","description":"data-visualization","extend":"{}","progress_status":"completed","repo_id":"1095f823-f6f5-4e66-9aad-9f0b5b6b99d1","reference_count":0,"id":"a40267bc-925a-4364-a01f-b96d3df60aea","gmt_create":"2026-04-22T19:23:03.398982+08:00","gmt_modified":"2026-04-22T19:23:03.405853+08:00"},{"catalog_id":"05214c1a-d804-4f3c-9048-20ba4de3be0f","title":"引用检测引擎","description":"citation-engine","extend":"{}","progress_status":"completed","repo_id":"1095f823-f6f5-4e66-9aad-9f0b5b6b99d1","reference_count":0,"id":"19e75845-5147-4aeb-90be-16f3aa270465","gmt_create":"2026-04-22T19:23:12.049419+08:00","gmt_modified":"2026-04-23T20:33:37.372858+08:00"},{"catalog_id":"b32b024e-2d06-45c8-94c2-a07fd25ab9b3","title":"快速开始","description":"quick-start","extend":"{}","progress_status":"completed","repo_id":"1095f823-f6f5-4e66-9aad-9f0b5b6b99d1","reference_count":0,"id":"7e679d62-c415-4d6a-a7e5-d41d00e0ed69","gmt_create":"2026-04-22T19:23:49.794133+08:00","gmt_modified":"2026-04-22T19:23:49.797304+08:00"},{"catalog_id":"850fc702-3eb6-45b4-acd2-ae87fec1f4f1","title":"工作器系统","description":"worker-system","extend":"{}","progress_status":"completed","repo_id":"1095f823-f6f5-4e66-9aad-9f0b5b6b99d1","reference_count":0,"id":"83fe6837-7874-4467-8114-103062f15f58","gmt_create":"2026-04-22T19:24:30.524061+08:00","gmt_modified":"2026-04-22T19:24:30.529283+08:00"},{"catalog_id":"fda0598d-7e92-4b8b-be52-92ae63c3cd98","title":"API客户端","description":"api-client","extend":"{}","progress_status":"completed","repo_id":"1095f823-f6f5-4e66-9aad-9f0b5b6b99d1","reference_count":0,"id":"7bd2c461-81b0-48e8-8cb3-b4b14305806d","gmt_create":"2026-04-22T19:24:50.482622+08:00","gmt_modified":"2026-04-22T19:24:50.486476+08:00"},{"catalog_id":"15d6170d-716c-4d2a-833d-81211a59027c","title":"平台适配器扩展指南","description":"platform-adapter-extension","extend":"{}","progress_status":"completed","repo_id":"1095f823-f6f5-4e66-9aad-9f0b5b6b99d1","reference_count":0,"id":"2632a6f9-774e-4a91-94da-a984bdb20758","gmt_create":"2026-04-22T19:25:18.714623+08:00","gmt_modified":"2026-04-22T19:25:18.720105+08:00"},{"catalog_id":"a232faa5-28b0-4235-8ad4-b082fd226e69","title":"订阅管理系统","description":"subscription-management-system","extend":"{}","progress_status":"completed","repo_id":"1095f823-f6f5-4e66-9aad-9f0b5b6b99d1","reference_count":0,"id":"ec2f1708-d31e-42bb-8959-fa405db7d6da","gmt_create":"2026-04-24T11:04:05.337544+08:00","gmt_modified":"2026-04-24T11:04:05.339776+08:00"},{"catalog_id":"9ac86c99-3b7e-4745-bc95-9586153d616e","title":"管理员仪表板系统","description":"admin-dashboard-system","extend":"{}","progress_status":"completed","repo_id":"1095f823-f6f5-4e66-9aad-9f0b5b6b99d1","reference_count":0,"id":"2059d1cd-98a3-4b7f-b29b-69acf8a0d751","gmt_create":"2026-04-24T11:06:01.087669+08:00","gmt_modified":"2026-04-24T11:06:01.089977+08:00"},{"catalog_id":"d54446b1-5984-4fe6-8fc1-ad0322ab7914","title":"安全增强功能","description":"security-enhancements","extend":"{}","progress_status":"completed","repo_id":"1095f823-f6f5-4e66-9aad-9f0b5b6b99d1","reference_count":0,"id":"d474a7a6-e056-4456-ba79-4aedbb7add58","gmt_create":"2026-04-24T11:07:19.926098+08:00","gmt_modified":"2026-04-24T11:07:19.927668+08:00"},{"catalog_id":"d645182f-1eaa-4439-854c-0437806ceebb","title":"PDF报告系统","description":"pdf-reporting-system","extend":"{}","progress_status":"completed","repo_id":"1095f823-f6f5-4e66-9aad-9f0b5b6b99d1","reference_count":0,"id":"2d7c030d-7b82-418c-9a16-67b067cac93c","gmt_create":"2026-04-24T11:08:42.186525+08:00","gmt_modified":"2026-04-24T11:08:42.188311+08:00"}],"wiki_overview":{"content":"\u003cblog\u003e\n\n# GEO 平台项目全面分析\n\n## 1. 项目介绍\n\n### 目标与愿景\nGEO 平台是一个基于人工智能技术的学术查询与引用管理系统,旨在为用户提供智能化的品牌引用检测和数据分析服务。该项目通过集成多个AI平台,实现对网络内容中特定品牌引用的自动检测和统计分析。\n\n### 核心目标\n- **智能引用检测**:自动识别网络内容中对特定品牌的引用情况\n- **多平台集成**:支持多个AI平台的数据获取和处理\n- **实时监控**:提供定时查询和实时更新功能\n- **数据可视化**:通过图表展示引用趋势和统计数据\n\n### 目标用户\n- 学术研究人员\n- 市场分析师\n- 品牌监测机构\n- 内容创作者\n\n## 2. 技术架构\n\n### 整体架构设计\n\n```mermaid\ngraph TB\n subgraph \"前端层\"\n FE[Next.js 前端]\n UI[React 组件]\n Auth[认证系统]\n end\n \n subgraph \"后端层\"\n API[FastAPI API]\n WS[工作器]\n SCH[调度器]\n end\n \n subgraph \"数据层\"\n DB[(PostgreSQL)]\n RD[Redis 缓存]\n end\n \n subgraph \"AI平台\"\n WX[Wenxin 平台]\n KM[Kimi 平台]\n end\n \n FE --\u003e API\n UI --\u003e FE\n Auth --\u003e FE\n API --\u003e DB\n API --\u003e RD\n WS --\u003e WX\n WS --\u003e KM\n SCH --\u003e WS\n API --\u003e WS\n```\n\n### 核心设计模式\n- **分层架构**:清晰的前后端分离和业务逻辑分层\n- **异步编程**:基于 asyncio 的高性能异步处理\n- **依赖注入**:通过 FastAPI 的依赖系统管理服务\n- **适配器模式**:统一不同AI平台的接口调用\n\n### 系统关系图\n\n```mermaid\nsequenceDiagram\n participant U as 用户\n participant F as 前端\n participant B as 后端API\n participant S as 调度器\n participant W as 引用引擎\n participant P as AI平台\n \n U-\u003e\u003eF: 发起查询请求\n F-\u003e\u003eB: HTTP请求\n B-\u003e\u003eS: 触发查询任务\n S-\u003e\u003eW: 执行查询\n W-\u003e\u003eP: 调用AI平台\n P--\u003e\u003eW: 返回结果\n W--\u003e\u003eB: 处理后的数据\n B--\u003e\u003eF: 响应结果\n F--\u003e\u003eU: 展示数据\n```\n\n## 3. 关键实现\n\n### 主要入口点\n\n**后端主入口**\n- `backend/app/main.py` - FastAPI 应用主入口,包含路由注册和中间件配置\n\n**前端主入口**\n- `frontend/app/layout.tsx` - Next.js 应用布局组件,包含全局样式和提供者配置\n\n### 核心模块\n\n**数据库配置**\n- `backend/app/database.py` - SQLAlchemy 异步数据库配置和会话管理\n\n**配置管理**\n- `backend/app/config.py` - Pydantic 设置类,管理环境变量和配置参数\n\n**工作器系统**\n- `backend/app/workers/scheduler.py` - APScheduler 定时任务调度器\n- `backend/app/workers/citation_engine.py` - 引用检测引擎核心\n\n**API 路由**\n- `backend/app/api/auth.py` - 用户认证相关接口\n- `backend/app/api/citations.py` - 引用数据相关接口\n- `backend/app/api/queries.py` - 查询任务相关接口\n\n### 配置方法\n\n**Docker 配置**\n- `docker-compose.yml` - 多容器部署配置,包含数据库、缓存和应用服务\n\n**依赖管理**\n- `backend/requirements.txt` - Python 后端依赖包\n- `frontend/package.json` - Node.js 前端依赖包\n\n### 外部依赖\n\n**后端关键技术栈**\n- FastAPI + Uvicorn:高性能异步Web框架\n- SQLAlchemy 2.0:异步ORM框架\n- APScheduler:任务调度框架\n- Redis:缓存和队列存储\n- Playwright:浏览器自动化\n\n**前端关键技术栈**\n- Next.js 14:React 框架\n- Radix UI:可访问性UI组件库\n- Recharts:数据可视化图表\n- Tailwind CSS:CSS框架\n\n### 集成点\n\n**AI平台适配**\n- `backend/app/workers/platforms/kimi.py` - Kimi AI平台适配器\n- `backend/app/workers/platforms/wenxin.py` - 百度文心平台适配器\n\n**认证集成**\n- `frontend/components/providers.tsx` - NextAuth.js 认证提供者\n- `frontend/lib/auth.ts` - 前端认证工具函数\n\n### 组件关系图\n\n```mermaid\ngraph LR\n subgraph \"认证模块\"\n AUTH_API[认证API]\n AUTH_FE[认证前端]\n NEXT_AUTH[NextAuth集成]\n end\n \n subgraph \"查询模块\"\n QUERY_API[查询API]\n QUERY_FE[查询前端]\n SCHEDULER[调度器]\n ENGINE[引用引擎]\n end\n \n subgraph \"数据模块\"\n MODELS[数据模型]\n DB[(数据库)]\n REDIS[(Redis)]\n end\n \n AUTH_API --\u003e MODELS\n QUERY_API --\u003e MODELS\n ENGINE --\u003e MODELS\n AUTH_FE --\u003e AUTH_API\n QUERY_FE --\u003e QUERY_API\n SCHEDULER --\u003e ENGINE\n ENGINE --\u003e DB\n ENGINE --\u003e REDIS\n AUTH_API --\u003e DB\n QUERY_API --\u003e DB\n```\n\n## 4. 核心功能\n\n### 功能概览\n\n**用户管理功能**\n- 用户注册和登录认证\n- JWT 令牌管理和会话维护\n- 用户权限控制\n\n**查询管理功能**\n- 自定义关键词查询\n- 多平台AI数据获取\n- 定时任务调度\n- 查询历史记录\n\n**引用检测功能**\n- 品牌引用自动检测\n- 置信度评分算法\n- 竞争品牌识别\n- 文本上下文提取\n\n**数据分析功能**\n- 引用趋势图表\n- 平台对比分析\n- 统计报表生成\n\n### 实现亮点\n\n**智能匹配算法**\n- `backend/app/workers/citation_engine.py` - 实现精确匹配、别名匹配和模糊匹配三种策略\n- 支持中文和英文混合文本处理\n- 提供置信度评分和位置信息\n\n**异步任务处理**\n- `backend/app/workers/scheduler.py` - 基于 APScheduler 的异步任务调度\n- 支持多平台并发查询\n- 完善的任务状态跟踪\n\n**响应式前端界面**\n- `frontend/app/(dashboard)/` - Next.js App Router 页面组织\n- `frontend/components/charts/` - 数据可视化组件\n- `frontend/components/ui/` - 可复用UI组件库\n\n### 功能架构图\n\n```mermaid\nstateDiagram-v2\n [*] --\u003e 用户认证\n 用户认证 --\u003e 查询管理: 登录成功\n 查询管理 --\u003e 任务调度: 创建查询\n 任务调度 --\u003e 引用检测: 定时触发\n 引用检测 --\u003e 数据处理: 获取AI结果\n 数据处理 --\u003e 结果展示: 处理完成\n 结果展示 --\u003e 查询管理: 新查询\n 结果展示 --\u003e [*]: 退出系统\n \n state 查询管理 {\n [*] --\u003e 创建查询\n 创建查询 --\u003e 编辑查询\n 编辑查询 --\u003e 删除查询\n 删除查询 --\u003e [*]\n }\n \n state 引用检测 {\n [*] --\u003e 平台查询\n 平台查询 --\u003e 品牌匹配\n 品牌匹配 --\u003e 竞争检测\n 竞争检测 --\u003e [*]\n }\n```\n\n## 5. 总结与建议\n\n### 项目架构特点\n\n**架构优势**\n- 清晰的分层设计,前后端职责明确\n- 异步编程模型提升了系统性能\n- 模块化设计便于功能扩展和维护\n- 完善的错误处理和日志记录机制\n\n**技术亮点**\n- 基于现代技术栈的全栈开发\n- 智能算法与工程实践的结合\n- 完整的开发到部署流程\n- 良好的代码组织和文档规范\n\n### 改进建议\n\n**性能优化**\n- 考虑引入连接池优化数据库连接\n- 实现缓存策略减少重复查询\n- 添加限流机制防止API滥用\n\n**功能扩展**\n- 增加更多AI平台支持\n- 实现批量查询功能\n- 添加导出数据功能\n- 增强搜索过滤条件\n\n**代码质量**\n- 完善单元测试覆盖率\n- 添加API文档自动生成\n- 实现更详细的错误处理\n- 优化前端组件复用性\n\n### 下一步发展\n\n**短期目标**\n- 完善用户认证和权限系统\n- 优化引用检测算法准确性\n- 增强前端用户体验\n\n**长期规划**\n- 支持多语言和国际化\n- 实现移动端应用\n- 添加机器学习模型优化\n- 构建开发者API平台\n\nSources:\n- [main.py](backend/app/main.py)\n- [config.py](backend/app/config.py)\n- [database.py](backend/app/database.py)\n- [layout.tsx](frontend/app/layout.tsx)\n- [providers.tsx](frontend/components/providers.tsx)\n- [scheduler.py](backend/app/workers/scheduler.py)\n- [citation_engine.py](backend/app/workers/citation_engine.py)\n- [auth.py](backend/app/api/auth.py)\n- [docker-compose.yml](docker-compose.yml)\n- [requirements.txt](backend/requirements.txt)\n- [package.json](frontend/package.json)\n\n\u003c/blog\u003e","gmt_create":"2026-04-22T18:54:45.079999+08:00","gmt_modified":"2026-04-22T18:54:45.079999+08:00","id":"1e2d007d-9249-436e-8822-c9b1a31580d1","repo_id":"1095f823-f6f5-4e66-9aad-9f0b5b6b99d1"},"wiki_readme":{"content":"No readme file","gmt_create":"2026-04-22T18:53:55.057287+08:00","gmt_modified":"2026-04-22T18:53:55.057287+08:00","id":"354aa9f0-35fb-44a7-98d6-034981f130e6","repo_id":"1095f823-f6f5-4e66-9aad-9f0b5b6b99d1"},"wiki_repo":{"id":"1095f823-f6f5-4e66-9aad-9f0b5b6b99d1","name":"GEO","progress_status":"completed","wiki_present_status":"COMPLETED","optimized_catalog":"\".\\n├── .npm-cache/\\n│ ├── _cacache/\\n│ ├── _logs/\\n│ └── _npx/\\n├── .pytest_cache/\\n├── backend/\\n│ ├── alembic/\\n│ │ ├── __pycache__/\\n│ │ ├── versions/\\n│ │ │ ├── __pycache__/\\n│ │ │ └── 488d0bd5ab01_initial_migration.py\\n│ │ ├── README\\n│ │ ├── env.py\\n│ │ └── script.py.mako\\n│ ├── app/\\n│ │ ├── __pycache__/\\n│ │ ├── api/\\n│ │ │ ├── __pycache__/\\n│ │ │ ├── __init__.py\\n│ │ │ ├── auth.py\\n│ │ │ ├── citations.py\\n│ │ │ ├── deps.py\\n│ │ │ ├── queries.py\\n│ │ │ └── reports.py\\n│ │ ├── models/\\n│ │ │ ├── __pycache__/\\n│ │ │ ├── __init__.py\\n│ │ │ ├── citation_record.py\\n│ │ │ ├── query.py\\n│ │ │ ├── query_task.py\\n│ │ │ ├── subscription.py\\n│ │ │ └── user.py\\n│ │ ├── schemas/\\n│ │ │ ├── __pycache__/\\n│ │ │ ├── auth.py\\n│ │ │ ├── citation.py\\n│ │ │ └── query.py\\n│ │ ├── services/\\n│ │ │ ├── __pycache__/\\n│ │ │ ├── auth.py\\n│ │ │ ├── citation.py\\n│ │ │ └── query.py\\n│ │ ├── utils/\\n│ │ ├── workers/\\n│ │ │ ├── __pycache__/\\n│ │ │ ├── platforms/\\n│ │ │ │ ├── __pycache__/\\n│ │ │ │ ├── base.py\\n│ │ │ │ ├── kimi.py\\n│ │ │ │ └── wenxin.py\\n│ │ │ ├── __init__.py\\n│ │ │ ├── citation_engine.py\\n│ │ │ └── scheduler.py\\n│ │ ├── config.py\\n│ │ ├── database.py\\n│ │ └── main.py\\n│ ├── venv/\\n│ ├── Dockerfile\\n│ ├── alembic.ini\\n│ └── requirements.txt\\n├── docs/\\n├── frontend/\\n│ ├── .next/\\n│ ├── app/\\n│ │ ├── (auth)/\\n│ │ │ ├── login/\\n│ │ │ │ └── page.tsx\\n│ │ │ ├── register/\\n│ │ │ │ └── page.tsx\\n│ │ │ └── layout.tsx\\n│ │ ├── (dashboard)/\\n│ │ │ ├── dashboard/\\n│ │ │ │ ├── citations/\\n│ │ │ │ │ └── page.tsx\\n│ │ │ │ ├── queries/\\n│ │ │ │ │ └── page.tsx\\n│ │ │ │ ├── reports/\\n│ │ │ │ │ └── page.tsx\\n│ │ │ │ ├── settings/\\n│ │ │ │ │ └── page.tsx\\n│ │ │ │ └── page.tsx\\n│ │ │ └── layout.tsx\\n│ │ ├── api/auth/[...nextauth]/\\n│ │ │ └── route.ts\\n│ │ ├── fonts/\\n│ │ ├── globals.css\\n│ │ ├── layout.tsx\\n│ │ └── page.tsx\\n│ ├── components/\\n│ │ ├── charts/\\n│ │ │ ├── platform-chart.tsx\\n│ │ │ └── trend-chart.tsx\\n│ │ ├── layout/\\n│ │ │ ├── header.tsx\\n│ │ │ └── sidebar.tsx\\n│ │ ├── ui/\\n│ │ │ ├── badge.tsx\\n│ │ │ ├── button.tsx\\n│ │ │ ├── card.tsx\\n│ │ │ ├── dialog.tsx\\n│ │ │ ├── dropdown-menu.tsx\\n│ │ │ ├── input.tsx\\n│ │ │ ├── label.tsx\\n│ │ │ ├── select.tsx\\n│ │ │ ├── table.tsx\\n│ │ │ └── tabs.tsx\\n│ │ └── providers.tsx\\n│ ├── lib/\\n│ │ ├── api.ts\\n│ │ ├── auth.ts\\n│ │ ├── platforms.ts\\n│ │ └── utils.ts\\n│ ├── node_modules/\\n│ ├── types/\\n│ │ └── next-auth.d.ts\\n│ ├── .eslintrc.json\\n│ ├── .gitignore\\n│ ├── Dockerfile\\n│ ├── README.md\\n│ ├── next-env.d.ts\\n│ ├── next.config.mjs\\n│ ├── package-lock.json\\n│ ├── package.json\\n│ ├── postcss.config.mjs\\n│ ├── tailwind.config.ts\\n│ ├── tsconfig.json\\n│ └── tsconfig.tsbuildinfo\\n├── tests/\\n│ ├── __pycache__/\\n│ ├── conftest.py\\n│ ├── test_auth.py\\n│ ├── test_citation_engine.py\\n│ ├── test_citations.py\\n│ └── test_queries.py\\n└── docker-compose.yml\\n\"","current_document_structure":"WikiEncrypted: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","catalogue_think_content":"WikiEncrypted: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","recovery_checkpoint":"wiki_generation_completed","last_commit_id":"eac12093d659483090ae8b5602372f10e15018fb","last_commit_update":"2026-05-23T15:26:11.57753+08:00","gmt_create":"2026-04-22T17:58:32.591608+08:00","gmt_modified":"2026-05-23T15:26:11.57753+08:00","extend_info":"{\"language\":\"zh\",\"active\":true,\"branch\":\"main\",\"shareStatus\":\"\",\"server_error_code\":\"\",\"cosy_version\":\"\"}"}} \ No newline at end of file diff --git a/README.md b/README.md index cd6b414..3aaca6d 100644 --- a/README.md +++ b/README.md @@ -1,5 +1,8 @@ # GEO - AI搜索引擎品牌曝光度优化平台 +[![CI Pipeline](https://github.com/YOUR_USERNAME/GEO/actions/workflows/ci.yml/badge.svg)](https://github.com/YOUR_USERNAME/GEO/actions/workflows/ci.yml) +[![PR Check](https://github.com/YOUR_USERNAME/GEO/actions/workflows/pr-check.yml/badge.svg)](https://github.com/YOUR_USERNAME/GEO/actions/workflows/pr-check.yml) + ## 项目简介 GEO(Generative Engine Optimization)是一个SaaS平台,帮助品牌监测其在各大AI搜索引擎中的曝光度和引用情况。支持文心一言、Kimi、通义千问、豆包、讯飞星火、天工、清言等主流国内AI平台,以及通用搜索引擎。 diff --git a/backend/.dockerignore b/backend/.dockerignore new file mode 100644 index 0000000..17d5ae3 --- /dev/null +++ b/backend/.dockerignore @@ -0,0 +1,13 @@ +venv/ +__pycache__/ +*.pyc +*.pyo +.pytest_cache/ +.env +.env.* +*.log +tests/ +alembic/versions/__pycache__/ +.git/ +.gitignore +README.md diff --git a/backend/Dockerfile b/backend/Dockerfile index c8e2af5..3c04f46 100644 --- a/backend/Dockerfile +++ b/backend/Dockerfile @@ -37,4 +37,9 @@ COPY . . EXPOSE 8000 -CMD ["uvicorn", "app.main:app", "--host", "0.0.0.0", "--port", "8000"] +# 健康检查 +HEALTHCHECK --interval=30s --timeout=10s --start-period=30s --retries=3 \ + CMD curl -f http://localhost:8000/api/health || exit 1 + +CMD ["gunicorn", "app.main:app", "-w", "4", "-k", "uvicorn.workers.UvicornWorker", \ + "--bind", "0.0.0.0:8000", "--timeout", "120", "--access-logfile", "-"] diff --git a/backend/alembic/versions/d4e6f8a0bc13_add_sentiment_fields.py b/backend/alembic/versions/059724556401_add_missing_sentiment_fields.py similarity index 75% rename from backend/alembic/versions/d4e6f8a0bc13_add_sentiment_fields.py rename to backend/alembic/versions/059724556401_add_missing_sentiment_fields.py index 92f24d6..ea0f334 100644 --- a/backend/alembic/versions/d4e6f8a0bc13_add_sentiment_fields.py +++ b/backend/alembic/versions/059724556401_add_missing_sentiment_fields.py @@ -1,8 +1,8 @@ -"""Add sentiment analysis fields to citation_records +"""add_missing_sentiment_fields -Revision ID: d4e6f8a0bc13 -Revises: c3d5e7f9ab12 -Create Date: 2026-05-19 10:00:00.000000 +Revision ID: 059724556401 +Revises: a7b9c1d3ef67 +Create Date: 2026-05-23 17:19:50.789398 """ from typing import Sequence, Union @@ -12,14 +12,15 @@ import sqlalchemy as sa # revision identifiers, used by Alembic. -revision: str = 'd4e6f8a0bc13' -down_revision: Union[str, Sequence[str], None] = 'c3d5e7f9ab12' +revision: str = '059724556401' +down_revision: Union[str, Sequence[str], None] = 'a7b9c1d3ef67' branch_labels: Union[str, Sequence[str], None] = None depends_on: Union[str, Sequence[str], None] = None def upgrade() -> None: - # 添加情感分析字段 + """Upgrade schema.""" + # 添加情感分析字段到 citation_records 表 op.add_column('citation_records', sa.Column('sentiment', sa.String(20), nullable=True, comment='情感倾向: positive / neutral / negative') @@ -35,6 +36,7 @@ def upgrade() -> None: def downgrade() -> None: + """Downgrade schema.""" op.drop_column('citation_records', 'sentiment_key_phrases') op.drop_column('citation_records', 'sentiment_confidence') op.drop_column('citation_records', 'sentiment') diff --git a/backend/alembic/versions/d4e6f8a0bc23_add_citation_source_analysis_fields.py b/backend/alembic/versions/8ccb553ff975_add_citation_source_analysis_fields.py similarity index 81% rename from backend/alembic/versions/d4e6f8a0bc23_add_citation_source_analysis_fields.py rename to backend/alembic/versions/8ccb553ff975_add_citation_source_analysis_fields.py index 4e09274..12a3255 100644 --- a/backend/alembic/versions/d4e6f8a0bc23_add_citation_source_analysis_fields.py +++ b/backend/alembic/versions/8ccb553ff975_add_citation_source_analysis_fields.py @@ -1,8 +1,8 @@ -"""Add citation source analysis fields to citation_records +"""add_citation_source_analysis_fields -Revision ID: d4e6f8a0bc23 -Revises: c3d5e7f9ab12 -Create Date: 2026-05-19 10:00:00.000000 +Revision ID: 8ccb553ff975 +Revises: 059724556401 +Create Date: 2026-05-23 17:23:03.183460 """ from typing import Sequence, Union @@ -12,14 +12,14 @@ import sqlalchemy as sa # revision identifiers, used by Alembic. -revision: str = 'd4e6f8a0bc23' -down_revision: Union[str, Sequence[str], None] = 'c3d5e7f9ab12' +revision: str = '8ccb553ff975' +down_revision: Union[str, Sequence[str], None] = '059724556401' branch_labels: Union[str, Sequence[str], None] = None depends_on: Union[str, Sequence[str], None] = None def upgrade() -> None: - """Add citation source analysis fields to citation_records table.""" + """Upgrade schema.""" # 数据来源类型标记 op.add_column( 'citation_records', @@ -53,7 +53,7 @@ def upgrade() -> None: def downgrade() -> None: - """Remove citation source analysis fields from citation_records table.""" + """Downgrade schema.""" op.drop_column('citation_records', 'ai_response_text') op.drop_column('citation_records', 'citation_contexts') op.drop_column('citation_records', 'source_titles') diff --git a/backend/alembic/versions/e5f7a9b1cd34_add_alerts_and_alert_settings_tables.py b/backend/alembic/versions/e5f7a9b1cd34_add_alerts_and_alert_settings_tables.py index 35e1860..d8f075c 100644 --- a/backend/alembic/versions/e5f7a9b1cd34_add_alerts_and_alert_settings_tables.py +++ b/backend/alembic/versions/e5f7a9b1cd34_add_alerts_and_alert_settings_tables.py @@ -1,7 +1,7 @@ """Add alerts and alert_settings tables Revision ID: e5f7a9b1cd34 -Revises: d4e6f8a0bc23 +Revises: 8ccb553ff975 Create Date: 2026-05-20 10:00:00.000000 """ @@ -13,7 +13,7 @@ import sqlalchemy as sa # revision identifiers, used by Alembic. revision: str = 'e5f7a9b1cd34' -down_revision: Union[str, Sequence[str], None] = 'd4e6f8a0bc23' +down_revision: Union[str, Sequence[str], None] = '8ccb553ff975' branch_labels: Union[str, Sequence[str], None] = None depends_on: Union[str, Sequence[str], None] = None diff --git a/backend/alembic/versions/e5f7a9b1cd34_add_suggestions_table.py b/backend/alembic/versions/e5f7a9b1cd35_add_suggestions_table.py similarity index 95% rename from backend/alembic/versions/e5f7a9b1cd34_add_suggestions_table.py rename to backend/alembic/versions/e5f7a9b1cd35_add_suggestions_table.py index 2b96e58..81c67c3 100644 --- a/backend/alembic/versions/e5f7a9b1cd34_add_suggestions_table.py +++ b/backend/alembic/versions/e5f7a9b1cd35_add_suggestions_table.py @@ -1,7 +1,7 @@ """add suggestions table -Revision ID: e5f7a9b1cd34 -Revises: d4e6f8a0bc23 +Revision ID: e5f7a9b1cd35 +Revises: e5f7a9b1cd34 Create Date: 2025-01-20 10:00:00.000000 """ from alembic import op @@ -9,8 +9,8 @@ import sqlalchemy as sa from sqlalchemy.dialects.postgresql import UUID, JSONB # revision identifiers -revision = "e5f7a9b1cd34" -down_revision = "d4e6f8a0bc23" +revision = "e5f7a9b1cd35" +down_revision = "e5f7a9b1cd34" branch_labels = None depends_on = None diff --git a/backend/app/agent_framework/base.py b/backend/app/agent_framework/base.py index 7cd7871..93a07cf 100644 --- a/backend/app/agent_framework/base.py +++ b/backend/app/agent_framework/base.py @@ -34,6 +34,7 @@ class BaseAgent(ABC): self._running_tasks: set[str] = set() self._listen_task: asyncio.Task | None = None self._heartbeat_task: asyncio.Task | None = None + self._semaphore: asyncio.Semaphore | None = None @property def status(self) -> AgentStatus: @@ -69,6 +70,14 @@ class BaseAgent(ABC): # 更新状态 self._status = AgentStatus.ONLINE + # 根据 capabilities 的 max_concurrency 初始化 Semaphore + capability = self.get_capabilities() + max_concurrency = getattr(capability, 'max_concurrency', 1) or 1 + self._semaphore = asyncio.Semaphore(max_concurrency) + logger.info( + f"Agent '{self.name}' concurrency limit set to {max_concurrency}" + ) + # 启动心跳 self._heartbeat_task = asyncio.create_task(self._heartbeat_loop()) @@ -172,7 +181,7 @@ class BaseAgent(ABC): try: task_data = json.loads(task_json) task = TaskMessage.from_dict(task_data) - asyncio.create_task(self._execute_task(task)) + asyncio.create_task(self._execute_task_with_semaphore(task)) except Exception as e: logger.error(f"Failed to parse task message: {e}") except asyncio.CancelledError: @@ -180,6 +189,14 @@ class BaseAgent(ABC): except Exception as e: logger.error(f"Task listener error for agent '{self.name}': {e}") + async def _execute_task_with_semaphore(self, task: TaskMessage): + """通过 Semaphore 限制并发执行任务""" + if self._semaphore is None: + await self._execute_task(task) + return + async with self._semaphore: + await self._execute_task(task) + async def _execute_task(self, task: TaskMessage): """执行单个任务""" self._running_tasks.add(task.task_id) diff --git a/backend/app/agent_framework/pipeline/engine.py b/backend/app/agent_framework/pipeline/engine.py index c3f676f..105854c 100644 --- a/backend/app/agent_framework/pipeline/engine.py +++ b/backend/app/agent_framework/pipeline/engine.py @@ -332,9 +332,10 @@ class PipelineEngine: resolved_inputs: dict[str, Any], ) -> StageResult: """ - Dry-run模式执行:模拟Agent返回结果。 + Dry-run模式执行:模拟Agent返回结果。仅用于测试/开发环境。 在没有dispatcher的环境下使用,用于测试和调试Pipeline定义。 + 如果在生产环境中触发,则记录 ERROR 级别告警。 Args: stage: 阶段定义 @@ -343,6 +344,15 @@ class PipelineEngine: Returns: 模拟的StageResult """ + import os + if os.environ.get("ENV", "development") == "production": + logger.error( + f"Pipeline 进入 dry-run 模式(stage={stage.name})!" + "生产环境中 TaskDispatcher 未正确初始化,请检查系统配置。" + ) + else: + logger.warning(f"[DRY-RUN] stage={stage.name} 返回模拟输出") + # 为声明的输出变量生成模拟值 mock_outputs: dict[str, Any] = {} for output_name in stage.outputs: diff --git a/backend/app/api/admin.py b/backend/app/api/admin.py index 86e08a2..f30fb2d 100644 --- a/backend/app/api/admin.py +++ b/backend/app/api/admin.py @@ -3,6 +3,7 @@ import uuid from fastapi import APIRouter, Depends, HTTPException, Query, status from sqlalchemy.ext.asyncio import AsyncSession +from app.api.base import PaginationParams from app.api.deps import get_current_user from app.database import get_db from app.models.user import User @@ -36,13 +37,12 @@ async def read_system_stats( @router.get("/users") async def read_users( - skip: int = Query(0, ge=0), - limit: int = Query(20, ge=1, le=100), + pagination: PaginationParams = Depends(PaginationParams), search: str | None = Query(None), db: AsyncSession = Depends(get_db), admin_user: User = Depends(get_admin_user), ): - return await get_users(db, skip=skip, limit=limit, search=search) + return await get_users(db, skip=pagination.offset, limit=pagination.limit, search=search) @router.get("/users/{user_id}") diff --git a/backend/app/api/agents.py b/backend/app/api/agents.py index 106a309..2f6ea05 100644 --- a/backend/app/api/agents.py +++ b/backend/app/api/agents.py @@ -25,6 +25,7 @@ from app.database import get_db from app.models.agent import AgentTask as AgentTaskModel from app.models.agent import AgentTaskLog as AgentTaskLogModel from app.models.user import User +from app.schemas.common import ErrorCode, ErrorResponse router = APIRouter() @@ -144,7 +145,7 @@ async def list_tasks( db: AsyncSession = Depends(get_db), current_user: User = Depends(get_current_user), ): - stmt = select(AgentTaskModel) + stmt = select(AgentTaskModel).where(AgentTaskModel.created_by == current_user.id) if task_status: stmt = stmt.where(AgentTaskModel.status == task_status) @@ -202,9 +203,11 @@ async def create_task( dispatcher = TaskDispatcher(settings.REDIS_URL) try: + # 从 current_user 获取 organization_id,优先使用用户的组织ID + org_id = str(current_user.organization_id) if current_user.organization_id else str(current_user.id) await dispatcher.dispatch( task=task, - organization_id=str(current_user.id), # fallback, 实际应从 user.org 取 + organization_id=org_id, created_by=str(current_user.id), ) return TaskCreateResponse( @@ -224,8 +227,35 @@ async def create_task( @router.get("/tasks/{task_id}", summary="获取任务状态") async def get_task_status( task_id: str, + db: AsyncSession = Depends(get_db), current_user: User = Depends(get_current_user), ): + # 权限校验:验证任务归属当前用户 + try: + task_uuid = uuid.UUID(task_id) + except ValueError: + raise HTTPException( + status_code=status.HTTP_400_BAD_REQUEST, + detail="Invalid task_id format", + ) + + stmt = select(AgentTaskModel).where(AgentTaskModel.id == task_uuid) + result = await db.execute(stmt) + task = result.scalar_one_or_none() + if task is None: + raise HTTPException( + status_code=status.HTTP_404_NOT_FOUND, + detail=f"Task '{task_id}' not found", + ) + if task.created_by != current_user.id: + raise HTTPException( + status_code=status.HTTP_403_FORBIDDEN, + detail=ErrorResponse( + detail="无权访问此任务", + code=ErrorCode.FORBIDDEN, + ).dict(), + ) + dispatcher = TaskDispatcher(settings.REDIS_URL) try: task_status_data = await dispatcher.get_task_status(task_id) @@ -242,8 +272,35 @@ async def get_task_status( @router.post("/tasks/{task_id}/cancel", summary="取消任务") async def cancel_task( task_id: str, + db: AsyncSession = Depends(get_db), current_user: User = Depends(get_current_user), ): + # 权限校验:验证任务归属当前用户 + try: + task_uuid = uuid.UUID(task_id) + except ValueError: + raise HTTPException( + status_code=status.HTTP_400_BAD_REQUEST, + detail="Invalid task_id format", + ) + + stmt = select(AgentTaskModel).where(AgentTaskModel.id == task_uuid) + result = await db.execute(stmt) + task = result.scalar_one_or_none() + if task is None: + raise HTTPException( + status_code=status.HTTP_404_NOT_FOUND, + detail=f"Task '{task_id}' not found", + ) + if task.created_by != current_user.id: + raise HTTPException( + status_code=status.HTTP_403_FORBIDDEN, + detail=ErrorResponse( + detail="无权取消此任务", + code=ErrorCode.FORBIDDEN, + ).dict(), + ) + dispatcher = TaskDispatcher(settings.REDIS_URL) try: await dispatcher.cancel_task(task_id) @@ -273,6 +330,24 @@ async def get_task_logs( detail="Invalid task_id format", ) + # 权限校验:验证任务归属当前用户 + task_stmt = select(AgentTaskModel).where(AgentTaskModel.id == task_uuid) + task_result = await db.execute(task_stmt) + task = task_result.scalar_one_or_none() + if task is None: + raise HTTPException( + status_code=status.HTTP_404_NOT_FOUND, + detail=f"Task '{task_id}' not found", + ) + if task.created_by != current_user.id: + raise HTTPException( + status_code=status.HTTP_403_FORBIDDEN, + detail=ErrorResponse( + detail="无权访问此任务日志", + code=ErrorCode.FORBIDDEN, + ).dict(), + ) + stmt = ( select(AgentTaskLogModel) .where(AgentTaskLogModel.task_id == task_uuid) diff --git a/backend/app/api/analytics.py b/backend/app/api/analytics.py index 545b980..bd1e5ca 100644 --- a/backend/app/api/analytics.py +++ b/backend/app/api/analytics.py @@ -30,13 +30,10 @@ router = APIRouter() # 辅助:获取当前用户所属组织ID # ------------------------------------------------------------------ # -async def _get_org_id(current_user: User = Depends(get_current_user)) -> str: +async def _get_org_id(current_user: User = Depends(get_current_user)) -> str | None: org_id = getattr(current_user, "organization_id", None) if not org_id: - raise HTTPException( - status_code=status.HTTP_403_FORBIDDEN, - detail="用户未关联组织", - ) + return None return str(org_id) @@ -52,9 +49,14 @@ async def _get_org_id(current_user: User = Depends(get_current_user)) -> str: ) async def record_publish( body: PublishRecordCreate, - org_id: str = Depends(_get_org_id), + org_id: str | None = Depends(_get_org_id), db: AsyncSession = Depends(get_db), ): + if not org_id: + raise HTTPException( + status_code=status.HTTP_403_FORBIDDEN, + detail="用户未关联组织,无法记录发布", + ) tracker = AnalyticsTracker(db) record = await tracker.record_publish(org_id, body.model_dump()) return record @@ -104,9 +106,18 @@ async def update_metrics( summary="获取全局效果概览", ) async def get_overview( - org_id: str = Depends(_get_org_id), + org_id: str | None = Depends(_get_org_id), db: AsyncSession = Depends(get_db), ): + if not org_id: + return OverviewStatsResponse( + total_published=0, + total_views=0, + total_interactions=0, + total_ai_citations=0, + avg_engagement_rate=0.0, + platform_distribution={}, + ) tracker = AnalyticsTracker(db) overview = await tracker.get_overview(org_id) return overview @@ -157,9 +168,11 @@ async def get_content_performance( async def get_top_performing( sort_by: str = Query(default="views", description="排序字段: views/likes/comments/shares/ai_citation_count/read_completion_rate"), limit: int = Query(default=10, ge=1, le=50), - org_id: str = Depends(_get_org_id), + org_id: str | None = Depends(_get_org_id), db: AsyncSession = Depends(get_db), ): + if not org_id: + return TopContentResponse(items=[], sort_by=sort_by, total=0) tracker = AnalyticsTracker(db) items = await tracker.get_top_performing(org_id, limit=limit, sort_by=sort_by) return TopContentResponse(items=items, sort_by=sort_by, total=len(items)) @@ -177,9 +190,11 @@ async def get_top_performing( async def list_insights( limit: int = Query(default=20, ge=1, le=100), insight_type: Optional[str] = Query(default=None), - org_id: str = Depends(_get_org_id), + org_id: str | None = Depends(_get_org_id), db: AsyncSession = Depends(get_db), ): + if not org_id: + return [] stmt = ( select(OptimizationInsight) .where(OptimizationInsight.organization_id == org_id) @@ -204,9 +219,11 @@ async def list_insights( summary="触发AI生成洞察建议", ) async def generate_insights( - org_id: str = Depends(_get_org_id), + org_id: str | None = Depends(_get_org_id), db: AsyncSession = Depends(get_db), ): + if not org_id: + return [] generator = InsightGenerator() insights = await generator.generate_insights(org_id, db) return insights diff --git a/backend/app/api/auth.py b/backend/app/api/auth.py index d7691d2..2e22dbf 100644 --- a/backend/app/api/auth.py +++ b/backend/app/api/auth.py @@ -5,8 +5,10 @@ from app.api.deps import get_current_user from app.database import get_db from app.models.user import User from app.schemas.auth import ( + AccessTokenResponse, ChangePasswordRequest, ForgotPasswordRequest, + RefreshTokenRequest, ResetPasswordRequest, TokenResponse, UpdateProfileRequest, @@ -19,13 +21,16 @@ from app.services.auth import ( authenticate_user, change_password as change_password_service, create_access_token, + create_refresh_token, register_user, reset_password as reset_password_service, send_reset_link, send_verification_code, update_profile as update_profile_service, verify_email as verify_email_service, + verify_refresh_token, ) +from app.services.cache import get_cache_service, TTL_USER_PROFILE router = APIRouter() @@ -34,8 +39,9 @@ router = APIRouter() async def register(user_data: UserRegister, db: AsyncSession = Depends(get_db)): try: user = await register_user(db, user_data) - except ValueError as e: - raise HTTPException(status_code=status.HTTP_400_BAD_REQUEST, detail=str(e) if str(e) else "邮箱已被注册") + except ValueError: + # 不泄露具体原因,防止用户枚举 + raise HTTPException(status_code=status.HTTP_400_BAD_REQUEST, detail="注册失败,请检查输入信息是否已被使用") return user @@ -43,6 +49,7 @@ async def register(user_data: UserRegister, db: AsyncSession = Depends(get_db)): async def login(user_data: UserLogin, db: AsyncSession = Depends(get_db)): user = await authenticate_user(db, user_data.email, user_data.password) if not user: + # 统一错误消息,防止用户枚举(不区分“用户不存在” vs “密码错误”) raise HTTPException( status_code=status.HTTP_401_UNAUTHORIZED, detail="邮箱或密码错误", @@ -50,15 +57,58 @@ async def login(user_data: UserLogin, db: AsyncSession = Depends(get_db)): ) access_token = create_access_token(data={"sub": str(user.id)}) + refresh_token = create_refresh_token(data={"sub": str(user.id)}) return { "access_token": access_token, "token_type": "bearer", + "refresh_token": refresh_token, "user": user, } +@router.post("/refresh", response_model=AccessTokenResponse) +async def refresh_token(req: RefreshTokenRequest): + """ + 刷新接口:使用 refresh_token 获取新的 access_token + refresh_token(滑动过期) + """ + try: + payload = verify_refresh_token(req.refresh_token) + except ValueError: + raise HTTPException( + status_code=status.HTTP_401_UNAUTHORIZED, + detail="刷新令牌无效或已过期", + headers={"WWW-Authenticate": "Bearer"}, + ) + + user_id = payload.get("sub") + if not user_id: + raise HTTPException( + status_code=status.HTTP_401_UNAUTHORIZED, + detail="刷新令牌无效或已过期", + headers={"WWW-Authenticate": "Bearer"}, + ) + + new_access_token = create_access_token(data={"sub": user_id}) + new_refresh_token = create_refresh_token(data={"sub": user_id}) # 滑动过期 + return { + "access_token": new_access_token, + "token_type": "bearer", + "refresh_token": new_refresh_token, + } + + @router.get("/me", response_model=UserResponse) -async def read_current_user(current_user: User = Depends(get_current_user)): +async def read_current_user( + current_user: User = Depends(get_current_user), +): + cache = get_cache_service() + cache_key = f"user:profile:{current_user.id}" + cached = await cache.get_json(cache_key) + if cached is not None: + return cached + + user_data = UserResponse.model_validate(current_user).model_dump(mode="json") + await cache.set_json(cache_key, user_data, expire=TTL_USER_PROFILE) return current_user @@ -111,4 +161,9 @@ async def update_profile( updated_user = await update_profile_service(db, user.id, req) if not updated_user: raise HTTPException(status_code=status.HTTP_404_NOT_FOUND, detail="用户不存在") + + # 失效用户配置缓存 + cache = get_cache_service() + await cache.delete(f"user:profile:{user.id}") + return updated_user diff --git a/backend/app/api/base.py b/backend/app/api/base.py new file mode 100644 index 0000000..409ce0b --- /dev/null +++ b/backend/app/api/base.py @@ -0,0 +1,46 @@ +"""通用分页与过滤工具,供各 API 路由复用。""" +from typing import Generic, TypeVar + +from fastapi import Query +from pydantic import BaseModel, computed_field + +T = TypeVar("T") + + +class PaginationParams: + """依赖注入式分页参数(可直接用于 Depends)。""" + + def __init__( + self, + page: int = Query(1, ge=1, description="页码,从 1 开始"), + page_size: int = Query(20, ge=1, le=100, description="每页条数"), + ): + self.page = page + self.page_size = page_size + + @property + def offset(self) -> int: + return (self.page - 1) * self.page_size + + @property + def limit(self) -> int: + return self.page_size + + +class PaginatedResponse(BaseModel, Generic[T]): + """通用分页响应结构。""" + + items: list[T] + total: int + page: int + page_size: int + + @computed_field # type: ignore[misc] + @property + def total_pages(self) -> int: + if self.page_size == 0: + return 0 + import math + return math.ceil(self.total / self.page_size) + + model_config = {"from_attributes": True} diff --git a/backend/app/api/brands.py b/backend/app/api/brands.py index e5f485f..fa704c0 100644 --- a/backend/app/api/brands.py +++ b/backend/app/api/brands.py @@ -1,10 +1,12 @@ """Brands API endpoints.""" +import json import uuid from typing import Annotated from fastapi import APIRouter, Depends, HTTPException, status from sqlalchemy import select, func from sqlalchemy.ext.asyncio import AsyncSession +from sqlalchemy.orm import selectinload from app.api.deps import get_current_user from app.api.competitors import router as competitors_router @@ -13,6 +15,7 @@ from app.database import get_db from app.models.user import User from app.models.brand import Brand from app.schemas.brand import BrandCreate, BrandUpdate, BrandResponse, BrandListResponse +from app.services.cache import get_cache_service, TTL_BRANDS router = APIRouter() @@ -29,15 +32,32 @@ async def get_brands( db: AsyncSession = Depends(get_db), ): """Get all brands for the current user.""" - stmt = select(Brand, func.count().over().label("total")).where( - Brand.user_id == current_user.id + cache = get_cache_service() + cache_key = f"brands:{current_user.id}" + + # 先读缓存 + cached = await cache.get_json(cache_key) + if cached is not None: + return cached + + # 修复 N+1:一次性加载 competitors 和 suggestions + stmt = ( + select(Brand) + .where(Brand.user_id == current_user.id) + .options( + selectinload(Brand.competitors), + selectinload(Brand.suggestions), + ) ) result = await db.execute(stmt) - rows = result.all() - - items = [row[0] for row in rows] + items = list(result.scalars().all()) total = len(items) + response_data = {"items": [BrandResponse.model_validate(b).model_dump(mode="json") for b in items], "total": total} + + # 写入缓存(TTL: 5 分钟) + await cache.set_json(cache_key, response_data, expire=TTL_BRANDS) + return {"items": items, "total": total} @@ -60,6 +80,11 @@ async def create_brand( db.add(brand) await db.commit() await db.refresh(brand) + + # 失效该用户的品牌列表缓存 + cache = get_cache_service() + await cache.delete(f"brands:{current_user.id}") + return brand @@ -107,6 +132,11 @@ async def update_brand( await db.commit() await db.refresh(brand) + + # 失效该用户的品牌列表缓存 + cache = get_cache_service() + await cache.delete(f"brands:{current_user.id}") + return brand @@ -129,4 +159,9 @@ async def delete_brand( await db.delete(brand) await db.commit() + + # 失效该用户的品牌列表缓存 + cache = get_cache_service() + await cache.delete(f"brands:{current_user.id}") + return None \ No newline at end of file diff --git a/backend/app/api/content.py b/backend/app/api/content.py index cb4c89e..4011f1b 100644 --- a/backend/app/api/content.py +++ b/backend/app/api/content.py @@ -1,5 +1,6 @@ """内容生产API - 串联Agent Pipeline""" import json +import logging import re from typing import Optional @@ -13,6 +14,8 @@ from app.database import get_db from app.models.content import Content, ContentVersion from app.models.user import User +logger = logging.getLogger(__name__) + router = APIRouter() @@ -38,6 +41,44 @@ class ContentGenerateResponse(BaseModel): pipeline_stages: list[dict] = [] # 每个阶段的执行结果摘要 +async def _get_knowledge_context( + db: AsyncSession, + brand_name: str, + knowledge_base_ids: list[str], + target_keyword: str, +) -> str: + """ + 从知识库检索与查询相关的上下文。 + + 如果有知识库ID,则调用 RAGService.search 获取相关内容; + 否则返回空字符串,不影响后续流程。 + """ + if not knowledge_base_ids: + return "" + + try: + from app.services.knowledge.rag_service import RAGService + rag_service = RAGService() + results = await rag_service.search( + session=db, + query=f"{brand_name} {target_keyword}" if brand_name else target_keyword, + knowledge_base_ids=knowledge_base_ids, + top_k=3, + ) + if results: + context_parts = [] + for r in results: + content = r.get("content", "") + title = r.get("document_title", "") + if content: + context_parts.append(f"[{title}] {content}") + return "\n".join(context_parts) + return "" + except Exception as e: + logger.warning(f"知识库检索失败,将不使用知识库上下文: {e}") + return "" + + @router.post("/generate", response_model=ContentGenerateResponse) async def generate_content( req: ContentGenerateRequest, @@ -65,6 +106,11 @@ async def generate_content( try: provider = LLMFactory.get_default() + # 获取知识库上下文 + knowledge_context = await _get_knowledge_context( + db, req.brand_name, req.knowledge_base_ids, req.target_keyword + ) + # Stage 1: 内容生成 gen_variables = { "topic_title": req.target_keyword, @@ -74,7 +120,7 @@ async def generate_content( "content_style": req.content_style, "word_count": str(req.word_count), "brand_name": req.brand_name, - "knowledge_context": "暂无", # TODO: 对接RAG检索 + "knowledge_context": knowledge_context, } messages = CONTENT_GENERATOR_TEMPLATE.render(gen_variables) response = await provider.chat(messages, temperature=0.7, max_tokens=req.word_count * 2) @@ -191,4 +237,4 @@ async def generate_topics( return {"status": "success", "topics": topics} except LLMError as e: - raise HTTPException(status_code=502, detail=str(e)) + raise HTTPException(status_code=502, detail=str(e)) \ No newline at end of file diff --git a/backend/app/api/dashboard.py b/backend/app/api/dashboard.py index 3efed40..70760c9 100644 --- a/backend/app/api/dashboard.py +++ b/backend/app/api/dashboard.py @@ -22,6 +22,7 @@ from app.schemas.dashboard import ( from app.services.scoring_service import ScoringService, get_health_level from app.services.sentiment_service import get_sentiment_service from app.schemas.scoring import CitationResult +from app.services.cache import get_cache_service, TTL_DASHBOARD router = APIRouter() @@ -355,7 +356,8 @@ async def get_dashboard_stats( - 竞品地位(领先/落后数量) - 最近查询记录 """ - # Get the first brand if not specified + cache = get_cache_service() + # 如果 brand_id 尚未确定,先查库取第一个品牌 if brand_id is None: brand_stmt = select(Brand).where(Brand.user_id == current_user.id).limit(1) brand_result = await db.execute(brand_stmt) @@ -377,6 +379,12 @@ async def get_dashboard_stats( total_platforms=7, ) + # 尝试从缓存读取(TTL: 2 分钟) + cache_key = f"dashboard:stats:{current_user.id}:{brand_id}" + cached = await cache.get_json(cache_key) + if cached is not None: + return cached + # Get brand name brand_stmt = select(Brand).where(Brand.id == brand_id) brand_result = await db.execute(brand_stmt) @@ -455,7 +463,7 @@ async def get_dashboard_stats( # Health level health_level = get_health_level(overall_score) - return DashboardStatsResponse( + response = DashboardStatsResponse( overall_score=round(overall_score, 2), health_level=health_level, score_change=score_change, @@ -468,3 +476,12 @@ async def get_dashboard_stats( total_platforms=7, brand_name=brand_name, ) + + # 将结果写入缓存(TTL: 2 分钟) + await cache.set_json( + cache_key, + response.model_dump(mode="json"), + expire=TTL_DASHBOARD, + ) + + return response diff --git a/backend/app/api/lifecycle.py b/backend/app/api/lifecycle.py index 85602fb..61e7cb7 100644 --- a/backend/app/api/lifecycle.py +++ b/backend/app/api/lifecycle.py @@ -31,6 +31,14 @@ STAGE_NAMES = { 5: "持续运维", } +STAGE_INT_TO_STR = { + 1: "diagnosis", + 2: "strategy", + 3: "content", + 4: "publishing", + 5: "monitoring", +} + # ---------- helpers ---------- @@ -82,6 +90,25 @@ async def _load_project_with_stages( # ---------- endpoints ---------- +@router.get("/projects/", response_model=list[ProjectResponse]) +async def list_projects( + db: AsyncSession = Depends(get_db), + current_user: User = Depends(get_current_user), +): + org_id = current_user.organization_id + if not org_id: + return [] + stmt = ( + select(LifecycleProject) + .where(LifecycleProject.organization_id == org_id) + .options(selectinload(LifecycleProject.stages)) + .order_by(LifecycleProject.created_at.desc()) + ) + result = await db.execute(stmt) + projects = result.scalars().all() + return projects + + @router.get("/projects/stats", response_model=ProjectStatsResponse) async def project_stats( db: AsyncSession = Depends(get_db), @@ -92,6 +119,10 @@ async def project_stats( return ProjectStatsResponse( total_projects=0, active_projects=0, + completed_projects=0, + contents_produced=0, + avg_ai_citation_rate=None, + current_stage_distribution={}, stage_distribution={}, completion_rate=0.0, ) @@ -127,9 +158,70 @@ async def project_stats( done = comp_result.scalar() or 0 completion_rate = round(done / total, 4) if total > 0 else 0.0 + # completed projects + completed_stmt = select( + func.count().filter(LifecycleProject.status == "completed").label("completed"), + ).where(LifecycleProject.organization_id == org_id) + completed_result = await db.execute(completed_stmt) + completed = completed_result.scalar() or 0 + + # contents produced (count from content table if available) + try: + from app.models.content import Content + contents_stmt = select(func.count()).where(Content.organization_id == org_id) + contents_result = await db.execute(contents_stmt) + contents_produced = contents_result.scalar() or 0 + except Exception: + contents_produced = 0 + + # avg AI citation rate + try: + from app.models.citation_record import CitationRecord + from app.models.query import Query as QueryModel + # Query uses user_id, so join through users table to get org members + from app.models.organization import OrgMember + org_user_ids_stmt = select(OrgMember.user_id).where(OrgMember.organization_id == org_id) + org_user_ids_result = await db.execute(org_user_ids_stmt) + org_user_ids = [r.user_id for r in org_user_ids_result.all()] + if org_user_ids: + citation_stmt = select( + func.count().label("total_citations"), + func.count().filter(CitationRecord.cited == True).label("cited_count"), + ).join(QueryModel, CitationRecord.query_id == QueryModel.id).where( + QueryModel.user_id.in_(org_user_ids), + ) + citation_result = await db.execute(citation_stmt) + citation_row = citation_result.one() + total_citations = citation_row.total_citations or 0 + cited_count = citation_row.cited_count or 0 + avg_ai_citation_rate = round(cited_count / total_citations, 4) if total_citations > 0 else None + else: + avg_ai_citation_rate = None + except Exception: + avg_ai_citation_rate = None + + # current stage distribution (map int stage to string) + current_stage_dist_stmt = ( + select( + LifecycleProject.current_stage, + func.count().label("cnt"), + ) + .where(LifecycleProject.organization_id == org_id) + .group_by(LifecycleProject.current_stage) + ) + current_stage_dist_result = await db.execute(current_stage_dist_stmt) + current_stage_distribution = {} + for r in current_stage_dist_result.all(): + stage_key = STAGE_INT_TO_STR.get(r.current_stage, str(r.current_stage)) + current_stage_distribution[stage_key] = current_stage_distribution.get(stage_key, 0) + r.cnt + return ProjectStatsResponse( total_projects=total, active_projects=active, + completed_projects=completed, + contents_produced=contents_produced, + avg_ai_citation_rate=avg_ai_citation_rate, + current_stage_distribution=current_stage_distribution, stage_distribution=stage_distribution, completion_rate=completion_rate, ) @@ -143,7 +235,7 @@ async def project_timeline( ): org_id = current_user.organization_id if not org_id: - raise HTTPException(status_code=status.HTTP_404_NOT_FOUND, detail="No organization found") + return [] project = await _load_project_with_stages(db, project_id, org_id) if not project: @@ -238,7 +330,7 @@ async def list_stages( ): org_id = current_user.organization_id if not org_id: - raise HTTPException(status_code=status.HTTP_404_NOT_FOUND, detail="No organization found") + return [] project = await _load_project_with_stages(db, project_id, org_id) if not project: @@ -257,7 +349,7 @@ async def update_stage( ): org_id = current_user.organization_id if not org_id: - raise HTTPException(status_code=status.HTTP_404_NOT_FOUND, detail="No organization found") + raise HTTPException(status_code=status.HTTP_403_FORBIDDEN, detail="用户未关联组织,无法修改项目阶段") # verify project ownership project = await _load_project_with_stages(db, project_id, org_id) diff --git a/backend/app/api/onboarding.py b/backend/app/api/onboarding.py new file mode 100644 index 0000000..471e9cf --- /dev/null +++ b/backend/app/api/onboarding.py @@ -0,0 +1,514 @@ +"""Onboarding API endpoints - 新用户引导流程""" +import logging +import uuid +from typing import Optional + +from fastapi import APIRouter, Depends, HTTPException, Query, status +from pydantic import BaseModel, Field +from sqlalchemy import select, func +from sqlalchemy.ext.asyncio import AsyncSession + +from app.api.deps import get_current_user +from app.api.competitors import ( + INDUSTRY_COMPETITORS, + _get_rule_based_recommendations, + _get_llm_recommendations, + CompetitorRecommendationItem, +) +from app.config import settings +from app.database import get_db +from app.models.user import User +from app.models.brand import Brand +from app.models.competitor import Competitor +from app.models.citation_record import CitationRecord +from app.models.query import Query as QueryModel +from app.services.scoring_service import ScoringService +from app.schemas.brand import BrandCreate, BrandResponse + +logger = logging.getLogger(__name__) + +router = APIRouter(prefix="/onboarding", tags=["onboarding"]) + + +# ------------------------------------------------------------------ +# Request / Response schemas +# ------------------------------------------------------------------ + +class OnboardingBrandCreate(BaseModel): + """Onboarding 创建品牌请求(简化版)""" + name: str = Field(..., min_length=2, max_length=50, description="品牌名称") + description: Optional[str] = Field(None, max_length=500, description="品牌描述") + industry: Optional[str] = Field(None, max_length=50, description="行业") + + +class OnboardingStatusResponse(BaseModel): + """Onboarding 状态响应""" + completed: bool + brand_id: Optional[str] = None + current_step: int + + +class CompetitorRecommendationSimple(BaseModel): + """简化竞品推荐项""" + name: str + description: str + confidence: float + + +class CompetitorRecommendationSimpleResponse(BaseModel): + """简化竞品推荐响应""" + recommendations: list[CompetitorRecommendationSimple] + + +class HealthReportResponse(BaseModel): + """初始健康评分报告""" + brand_id: str + brand_name: str + overall_score: float + platform_scores: dict + strengths: list[str] + weaknesses: list[str] + competitor_scores: list[dict] + + +class ActionSuggestion(BaseModel): + """行动建议项""" + title: str + description: str + priority: str # high / medium / low + action_type: str # e.g. coverage, keyword, sentiment, platform + + +class ActionSuggestionsResponse(BaseModel): + """行动建议响应""" + suggestions: list[ActionSuggestion] + + +class OnboardingCompleteResponse(BaseModel): + """完成 onboarding 响应""" + success: bool + + +# ------------------------------------------------------------------ +# Endpoints +# ------------------------------------------------------------------ + +@router.get("/status", response_model=OnboardingStatusResponse) +async def get_onboarding_status( + current_user: User = Depends(get_current_user), + db: AsyncSession = Depends(get_db), +): + """ + 检查当前用户的 onboarding 状态。 + + 通过查询 brands 表判断:用户是否已创建品牌(即完成 onboarding)。 + - completed=True 且 brand_id 有值 → 已完成 + - completed=False, current_step=1 → 需要创建品牌 + """ + stmt = select(Brand).where(Brand.user_id == current_user.id) + result = await db.execute(stmt) + brand = result.scalar_one_or_none() + + if brand: + return OnboardingStatusResponse( + completed=True, + brand_id=str(brand.id), + current_step=4, + ) + + return OnboardingStatusResponse( + completed=False, + brand_id=None, + current_step=1, + ) + + +@router.post("/brand", response_model=BrandResponse, status_code=status.HTTP_201_CREATED) +async def create_onboarding_brand( + brand_data: OnboardingBrandCreate, + current_user: User = Depends(get_current_user), + db: AsyncSession = Depends(get_db), +): + """ + Onboarding 流程中创建品牌。 + + 复用 Brand 模型,将简化字段映射到完整 BrandCreate。 + """ + full_brand_data = BrandCreate( + name=brand_data.name, + aliases=[], + website=None, + industry=brand_data.industry, + platforms=["wenxin", "kimi"], + frequency="weekly", + ) + + brand = Brand( + user_id=current_user.id, + name=full_brand_data.name, + aliases=full_brand_data.aliases, + website=full_brand_data.website, + industry=full_brand_data.industry, + platforms=full_brand_data.platforms, + frequency=full_brand_data.frequency, + ) + db.add(brand) + await db.commit() + await db.refresh(brand) + + return brand + + +@router.get("/competitor-recommendations", response_model=CompetitorRecommendationSimpleResponse) +async def get_onboarding_competitor_recommendations( + brand_id: uuid.UUID = Query(..., description="品牌ID"), + current_user: User = Depends(get_current_user), + db: AsyncSession = Depends(get_db), +): + """ + 根据品牌推荐竞品。 + + 复用 brands/competitors 中的推荐逻辑, + 支持 LLM 智能推荐和规则推荐两种模式。 + """ + # 验证品牌归属 + stmt = select(Brand).where(Brand.id == brand_id, Brand.user_id == current_user.id) + result = await db.execute(stmt) + brand = result.scalar_one_or_none() + + if not brand: + raise HTTPException( + status_code=status.HTTP_404_NOT_FOUND, + detail="品牌不存在", + ) + + # 获取已有竞品名称(排除) + existing_stmt = select(Competitor.name).where(Competitor.brand_id == brand_id) + existing_result = await db.execute(existing_stmt) + existing_names = [row[0] for row in existing_result.all()] + + # 选择推荐策略 + if settings.ENABLE_LLM and settings.DEEPSEEK_API_KEY: + try: + rec_items = await _get_llm_recommendations( + brand_name=brand.name, + industry=brand.industry, + existing_names=existing_names, + ) + except Exception as e: + logger.warning(f"Onboarding LLM竞品推荐失败,回退规则推荐: {e}") + rec_items = _get_rule_based_recommendations( + brand_name=brand.name, + industry=brand.industry, + existing_names=existing_names, + ) + else: + rec_items = _get_rule_based_recommendations( + brand_name=brand.name, + industry=brand.industry, + existing_names=existing_names, + ) + + # 转换为简化格式 + recommendations = [] + for item in rec_items: + confidence = 0.8 if brand.industry and brand.industry in INDUSTRY_COMPETITORS else 0.5 + recommendations.append(CompetitorRecommendationSimple( + name=item.name, + description=item.reason, + confidence=confidence, + )) + + return CompetitorRecommendationSimpleResponse(recommendations=recommendations) + + +@router.get("/health-report/{brand_id}", response_model=HealthReportResponse) +async def get_onboarding_health_report( + brand_id: uuid.UUID, + current_user: User = Depends(get_current_user), + db: AsyncSession = Depends(get_db), +): + """ + 获取品牌初始健康评分报告。 + + 基于 citation_records 表统计品牌的引用数据, + 如果没有引用数据则返回初始化状态(overall_score: 0)。 + """ + # 验证品牌归属 + stmt = select(Brand).where(Brand.id == brand_id, Brand.user_id == current_user.id) + result = await db.execute(stmt) + brand = result.scalar_one_or_none() + + if not brand: + raise HTTPException( + status_code=status.HTTP_404_NOT_FOUND, + detail="品牌不存在", + ) + + # 查询与品牌关联的 queries + queries_stmt = select(QueryModel).where( + QueryModel.user_id == current_user.id, + QueryModel.target_brand == brand.name, + ) + queries_result = await db.execute(queries_stmt) + queries = list(queries_result.scalars().all()) + + # 没有查询数据 → 返回初始化状态 + if not queries: + return HealthReportResponse( + brand_id=str(brand.id), + brand_name=brand.name, + overall_score=0.0, + platform_scores={}, + strengths=["品牌已创建,等待数据采集"], + weaknesses=["尚无AI平台引用数据,需等待查询执行"], + competitor_scores=[], + ) + + query_ids = [q.id for q in queries] + + # 获取引用记录 + citations_stmt = select(CitationRecord).where( + CitationRecord.query_id.in_(query_ids), + ) + citations_result = await db.execute(citations_stmt) + citations = list(citations_result.scalars().all()) + + total = len(citations) + cited = [c for c in citations if c.cited] + + # 计算各平台评分 + platform_scores: dict[str, float] = {} + platforms_seen: dict[str, dict] = {} # {platform: {total, cited}} + + for c in citations: + p = c.platform or "unknown" + if p not in platforms_seen: + platforms_seen[p] = {"total": 0, "cited": 0} + platforms_seen[p]["total"] += 1 + if c.cited: + platforms_seen[p]["cited"] += 1 + + for p, data in platforms_seen.items(): + rate = (data["cited"] / data["total"] * 100) if data["total"] > 0 else 0.0 + platform_scores[p] = round(rate, 2) + + # 使用 ScoringService 计算 overall_score + scoring_service = ScoringService() + sentiment_counts = {"positive": 0, "neutral": 0, "negative": 0} + for c in cited: + sentiment = c.sentiment or "neutral" + if sentiment in sentiment_counts: + sentiment_counts[sentiment] += 1 + + from app.schemas.scoring import CitationResult + citation_results = [ + CitationResult( + cited=c.cited, + position=c.citation_position, + citation_text=c.citation_text, + sentiment=c.sentiment or "neutral", + confidence=c.confidence or 0.0, + ) + for c in cited + ] + positions = [c.citation_position for c in cited if c.cited] + + # 获取竞品信息 + competitor_stmt = select(Competitor).where(Competitor.brand_id == brand_id) + competitor_result = await db.execute(competitor_stmt) + competitors = list(competitor_result.scalars().all()) + competitor_names = [c.name for c in competitors] + competitor_mentions: dict[str, int] = {} + for comp_name in competitor_names: + count = sum( + 1 for c in citations + if c.cited and c.competitor_brands and comp_name in c.competitor_brands + ) + if count > 0: + competitor_mentions[comp_name] = count + + v2_result = scoring_service.calculate_v2( + mentioned_count=len(cited), + total_queries=total, + positions=positions, + sentiment_counts=sentiment_counts, + citations=citation_results, + brand_mentions=len(cited), + competitor_mentions=competitor_mentions, + ) + + # 生成 strengths/weaknesses + strengths = [] + weaknesses = [] + + if total == 0: + strengths.append("品牌已创建") + weaknesses.append("尚无引用数据") + else: + mention_rate = len(cited) / total * 100 if total > 0 else 0 + if mention_rate >= 50: + strengths.append(f"提及率较高 ({round(mention_rate, 1)}%)") + else: + weaknesses.append(f"提及率偏低 ({round(mention_rate, 1)}%)") + + for p, score in platform_scores.items(): + if score >= 60: + strengths.append(f"{p} 平台表现良好 ({score}%)") + elif score > 0: + weaknesses.append(f"{p} 平台覆盖率不足 ({score}%)") + + if sentiment_counts["positive"] > sentiment_counts["negative"]: + strengths.append("情感倾向正面") + elif sentiment_counts["negative"] > sentiment_counts["positive"]: + weaknesses.append("情感倾向偏负面") + + if not strengths: + strengths.append("已有初步引用数据") + if not weaknesses: + weaknesses.append("暂无明显短板") + + # 竞品评分 + competitor_scores = [] + for comp_name, mentions in competitor_mentions.items(): + comp_score = round(mentions / total * 100, 2) if total > 0 else 0.0 + competitor_scores.append({ + "name": comp_name, + "score": comp_score, + }) + + return HealthReportResponse( + brand_id=str(brand.id), + brand_name=brand.name, + overall_score=round(v2_result.overall_score, 2), + platform_scores=platform_scores, + strengths=strengths, + weaknesses=weaknesses, + competitor_scores=competitor_scores, + ) + + +@router.get("/action-suggestions/{brand_id}", response_model=ActionSuggestionsResponse) +async def get_onboarding_action_suggestions( + brand_id: uuid.UUID, + current_user: User = Depends(get_current_user), + db: AsyncSession = Depends(get_db), +): + """ + 根据健康报告生成行动建议(基于规则引擎,不需要 LLM)。 + """ + # 先获取健康报告数据(复用逻辑) + report = await get_onboarding_health_report(brand_id, current_user, db) + + suggestions = [] + + # 规则引擎:基于评分和平台数据生成建议 + if report.overall_score < 20: + suggestions.append(ActionSuggestion( + title="提升 AI 平台覆盖率", + description=f"当前综合评分仅 {report.overall_score},品牌在AI搜索中几乎未被提及。建议增加查询词覆盖面,让AI平台更频繁地引用品牌。", + priority="high", + action_type="coverage", + )) + + if report.overall_score < 50: + suggestions.append(ActionSuggestion( + title="优化核心关键词", + description="品牌在关键查询词下的提及率偏低,建议调整查询关键词策略,聚焦行业核心术语。", + priority="high", + action_type="keyword", + )) + + # 平台维度建议 + for platform, score in report.platform_scores.items(): + if score < 30: + suggestions.append(ActionSuggestion( + title=f"提升 {platform} 平台覆盖率", + description=f"品牌在 {platform} 平台的引用率仅为 {score}%,需要针对性优化该平台的内容策略。", + priority="medium", + action_type="platform", + )) + + # 情感维度建议 + if "情感倾向偏负面" in report.weaknesses: + suggestions.append(ActionSuggestion( + title="改善品牌情感倾向", + description="AI平台对品牌的情感评价偏负面,建议发布正面品牌内容、优化品牌描述以改善情感得分。", + priority="medium", + action_type="sentiment", + )) + + # 竞品对比建议 + for comp in report.competitor_scores: + if comp["score"] > report.overall_score: + suggestions.append(ActionSuggestion( + title=f"应对竞品 {comp['name']} 威胁", + description=f"竞品 {comp['name']} 评分 ({comp['score']}) 高于本品牌 ({report.overall_score}),建议分析竞品优势领域并制定差异化策略。", + priority="high", + action_type="competitive", + )) + + # 如果没有引用数据,给出基础建议 + if report.overall_score == 0: + suggestions = [ + ActionSuggestion( + title="设置核心查询词", + description="品牌尚无查询数据,建议首先设置与品牌最相关的核心查询词,让系统开始数据采集。", + priority="high", + action_type="keyword", + ), + ActionSuggestion( + title="添加竞品对比", + description="添加主要竞品以便进行对比分析,了解品牌在市场中的定位。", + priority="medium", + action_type="coverage", + ), + ActionSuggestion( + title="完善品牌信息", + description="补充品牌别名、网站、行业等详细信息,有助于提升AI平台识别率。", + priority="medium", + action_type="brand_info", + ), + ] + + # 确保至少有1条建议 + if not suggestions: + suggestions.append(ActionSuggestion( + title="持续监测品牌表现", + description="品牌表现良好,建议持续监测并保持当前策略。", + priority="low", + action_type="monitor", + )) + + return ActionSuggestionsResponse(suggestions=suggestions) + + +@router.post("/complete/{brand_id}", response_model=OnboardingCompleteResponse) +async def complete_onboarding( + brand_id: uuid.UUID, + current_user: User = Depends(get_current_user), + db: AsyncSession = Depends(get_db), +): + """ + 标记用户已完成 onboarding。 + + 通过验证品牌存在并归属当前用户来确认完成状态。 + User 模型当前没有 onboarding_completed 专用字段, + 品牌的创建即代表 onboarding 完成。 + """ + # 验证品牌归属 + stmt = select(Brand).where(Brand.id == brand_id, Brand.user_id == current_user.id) + result = await db.execute(stmt) + brand = result.scalar_one_or_none() + + if not brand: + raise HTTPException( + status_code=status.HTTP_404_NOT_FOUND, + detail="品牌不存在", + ) + + # 品牌已创建即代表 onboarding 完成,无需额外字段更新 + # 后续如需专用字段,可通过 alembic 迁移添加 user.onboarding_completed + logger.info(f"User {current_user.id} completed onboarding with brand {brand_id}") + + return OnboardingCompleteResponse(success=True) \ No newline at end of file diff --git a/backend/app/api/queries.py b/backend/app/api/queries.py index 2a3cee9..1ade055 100644 --- a/backend/app/api/queries.py +++ b/backend/app/api/queries.py @@ -3,6 +3,7 @@ import uuid from fastapi import APIRouter, Depends, HTTPException, Query, status from sqlalchemy.ext.asyncio import AsyncSession +from app.api.base import PaginationParams, PaginatedResponse from app.api.deps import get_current_user from app.database import get_db from app.models.user import User @@ -16,12 +17,15 @@ router = APIRouter() @router.get("/", response_model=QueryListResponse) async def list_queries( - skip: int = Query(0, ge=0), - limit: int = Query(20, ge=1, le=100), + pagination: PaginationParams = Depends(PaginationParams), db: AsyncSession = Depends(get_db), current_user: User = Depends(get_current_user), ): - items, total = await get_queries(db, current_user.id, skip=skip, limit=limit) + items, total = await get_queries( + db, current_user.id, + skip=pagination.offset, + limit=pagination.limit, + ) return {"items": items, "total": total} diff --git a/backend/app/config.py b/backend/app/config.py index d0e45cd..3526994 100644 --- a/backend/app/config.py +++ b/backend/app/config.py @@ -1,5 +1,8 @@ +import sys from pathlib import Path +from pydantic import field_validator, model_validator from pydantic_settings import BaseSettings, SettingsConfigDict +from typing import Optional _env_path = Path(__file__).resolve().parent.parent.parent / ".env" if not _env_path.exists(): @@ -11,10 +14,15 @@ class Settings(BaseSettings): DATABASE_URL: str = "postgresql+asyncpg://postgres:postgres123@db:5432/geo_platform" REDIS_URL: str = "redis://redis:6379/0" - JWT_SECRET: str = "your-secret-key-change-in-production" + + # JWT 密钥:必须通过环境变量设置,不提供任何默认值 + JWT_SECRET: str JWT_EXPIRE_HOURS: int = 24 + + # NextAuth 密钥 + SECRET_KEY: Optional[str] = None + PLAYWRIGHT_BROWSERS_PATH: str = "/ms-playwright" - DEEPSEEK_API_KEY: str = "" ENABLE_LLM: bool = False ZHIPU_API_KEY: str = "" TONGYI_API_KEY: str = "" @@ -41,5 +49,36 @@ class Settings(BaseSettings): # AI平台API调用频率限制(每分钟请求数) API_RATE_LIMIT_RPM: int = 10 + @field_validator("JWT_SECRET") + @classmethod + def validate_jwt_secret(cls, v: str) -> str: + if not v or v.strip() == "": + print( + "[FATAL] JWT_SECRET is not set. " + "Please set a strong secret key (>= 32 characters) in your .env file.", + file=sys.stderr, + ) + sys.exit(1) + if len(v) < 32: + print( + f"[FATAL] JWT_SECRET is too short ({len(v)} chars). " + "It must be at least 32 characters long.", + file=sys.stderr, + ) + sys.exit(1) + return v + + @model_validator(mode="after") + def validate_secret_key(self) -> "Settings": + if self.SECRET_KEY is not None: + if len(self.SECRET_KEY) < 32: + print( + f"[FATAL] SECRET_KEY is too short ({len(self.SECRET_KEY)} chars). " + "It must be at least 32 characters long.", + file=sys.stderr, + ) + sys.exit(1) + return self + settings = Settings() diff --git a/backend/app/database.py b/backend/app/database.py index bb4ba82..0adc019 100644 --- a/backend/app/database.py +++ b/backend/app/database.py @@ -1,12 +1,17 @@ from sqlalchemy.ext.asyncio import create_async_engine, async_sessionmaker, AsyncSession from sqlalchemy.orm import declarative_base +from sqlalchemy import text from app.config import settings engine = create_async_engine( settings.DATABASE_URL, - echo=False, - future=True, + pool_size=10, # 连接池大小 + max_overflow=20, # 最大溢出连接数 + pool_timeout=30, # 等待连接超时(秒) + pool_recycle=3600, # 连接回收时间(1小时) + pool_pre_ping=True, # 使用前 ping 检查连接有效性 + echo=False, # 生产环境关闭 SQL echo ) AsyncSessionLocal = async_sessionmaker( @@ -26,3 +31,13 @@ async def get_db() -> AsyncSession: yield session finally: await session.close() + + +async def check_db_connection() -> bool: + """检查数据库连接是否正常""" + try: + async with AsyncSessionLocal() as session: + await session.execute(text("SELECT 1")) + return True + except Exception: + return False diff --git a/backend/app/logging_config.py b/backend/app/logging_config.py new file mode 100644 index 0000000..ec555f5 --- /dev/null +++ b/backend/app/logging_config.py @@ -0,0 +1,57 @@ +"""结构化 JSON 日志配置模块。""" +import logging +import json +from datetime import datetime, timezone + + +class JSONFormatter(logging.Formatter): + """将日志记录格式化为 JSON 字符串,便于日志收集平台(如 ELK、Loki)解析。""" + + def format(self, record: logging.LogRecord) -> str: + log_entry: dict = { + "timestamp": datetime.now(timezone.utc).isoformat(), + "level": record.levelname, + "message": record.getMessage(), + "logger": record.name, + "module": record.module, + "function": record.funcName, + "line": record.lineno, + } + + if record.exc_info: + log_entry["exception"] = self.formatException(record.exc_info) + + # 从 extra 字段注入的可观测性上下文 + if hasattr(record, "user_id"): + log_entry["user_id"] = record.user_id + if hasattr(record, "request_id"): + log_entry["request_id"] = record.request_id + if hasattr(record, "path"): + log_entry["path"] = record.path + if hasattr(record, "method"): + log_entry["method"] = record.method + if hasattr(record, "duration_ms"): + log_entry["duration_ms"] = record.duration_ms + if hasattr(record, "status_code"): + log_entry["status_code"] = record.status_code + + return json.dumps(log_entry, ensure_ascii=False) + + +def setup_logging(level: int = logging.INFO) -> None: + """初始化全局 JSON 日志配置。 + + 应在应用启动时(import 其他模块之前)调用一次。 + """ + handler = logging.StreamHandler() + handler.setFormatter(JSONFormatter()) + + root_logger = logging.getLogger() + # 清空已有 handlers,避免重复输出 + root_logger.handlers.clear() + root_logger.addHandler(handler) + root_logger.setLevel(level) + + # 降低 uvicorn/sqlalchemy 等第三方库的噪音 + logging.getLogger("uvicorn.access").setLevel(logging.WARNING) + logging.getLogger("sqlalchemy.engine").setLevel(logging.WARNING) diff --git a/backend/app/main.py b/backend/app/main.py index 12b1d98..9b0b29f 100644 --- a/backend/app/main.py +++ b/backend/app/main.py @@ -1,12 +1,17 @@ import logging from contextlib import asynccontextmanager +from datetime import datetime, timezone -from fastapi import FastAPI +from fastapi import FastAPI, HTTPException, Request, Depends +from fastapi.exceptions import RequestValidationError +from fastapi.responses import JSONResponse +from sqlalchemy.ext.asyncio import AsyncSession +from sqlalchemy import text + +# 必须在其他模块 import 之前初始化 JSON 日志 +from app.logging_config import setup_logging +setup_logging() -logging.basicConfig( - level=logging.INFO, - format="%(asctime)s [%(name)s] %(levelname)s: %(message)s" -) from fastapi.middleware.cors import CORSMiddleware from app.api.admin import router as admin_router @@ -23,10 +28,18 @@ from app.api.citations import router as citations_router from app.api.queries import router as queries_router from app.api.reports import router as reports_router from app.api.subscriptions import router as subscription_router +from app.api.alerts import router as alerts_router +from app.api.dashboard import router as dashboard_router +from app.api.brands import router as brands_router +from app.api.onboarding import router as onboarding_router from app.config import settings from app.database import engine, Base +from app.schemas.common import ErrorResponse, ErrorCode from app.middleware.rate_limit import RateLimitMiddleware from app.middleware.logging_middleware import RequestLoggingMiddleware +from app.middleware.request_id import RequestIdMiddleware +from app.middleware.metrics import MetricsMiddleware +from app.database import get_db from app.workers.scheduler import query_scheduler @@ -50,6 +63,45 @@ app = FastAPI( lifespan=lifespan, ) + +@app.exception_handler(HTTPException) +async def http_exception_handler(request: Request, exc: HTTPException) -> JSONResponse: + """统一 HTTP 异常响应格式。""" + code = ErrorCode.from_status(exc.status_code) + return JSONResponse( + status_code=exc.status_code, + content=ErrorResponse( + detail=str(exc.detail), + code=code, + ).model_dump(mode="json"), + ) + + +@app.exception_handler(RequestValidationError) +async def validation_exception_handler(request: Request, exc: RequestValidationError) -> JSONResponse: + """统一参数校验异常响应格式。""" + return JSONResponse( + status_code=422, + content=ErrorResponse( + detail="请求参数校验失败", + code=ErrorCode.VALIDATION_ERROR, + extra={"errors": exc.errors()}, + ).model_dump(mode="json"), + ) + + +@app.exception_handler(Exception) +async def general_exception_handler(request: Request, exc: Exception) -> JSONResponse: + """兜底异常处理器,避免内部错误泄漏给客户端。""" + logging.getLogger(__name__).exception("Unhandled exception: %s", exc) + return JSONResponse( + status_code=500, + content=ErrorResponse( + detail="服务器内部错误,请稍后重试", + code=ErrorCode.INTERNAL_ERROR, + ).model_dump(mode="json"), + ) + _allow_origins = [origin.strip() for origin in settings.CORS_ORIGINS.split(",") if origin.strip()] if not _allow_origins: _allow_origins = ["http://localhost:3000"] @@ -72,11 +124,12 @@ async def add_security_headers(request, call_next): response.headers["Referrer-Policy"] = "strict-origin-when-cross-origin" return response -# 限流中间件 -app.add_middleware(RateLimitMiddleware) - -# 请求日志中间件 +# 中间件注册顺序(FastAPI 后进先出,最后注册的最先执行) +# 执行链:RequestId → Metrics → RateLimit → RequestLogging → CORS → SecurityHeaders app.add_middleware(RequestLoggingMiddleware) +app.add_middleware(RateLimitMiddleware) +app.add_middleware(MetricsMiddleware) +app.add_middleware(RequestIdMiddleware) app.include_router(auth_router, prefix="/api/v1/auth", tags=["认证"]) app.include_router(queries_router, prefix="/api/v1/queries", tags=["查询词"]) @@ -92,8 +145,57 @@ app.include_router(contents_router, prefix="/api/v1/contents", tags=["内容管 app.include_router(clients_router, prefix="/api/v1/clients", tags=["客户管理"]) app.include_router(distribution_router, prefix="/api/v1/distribution", tags=["内容分发"]) app.include_router(analytics_router, prefix="/api/v1/analytics", tags=["监测优化"]) +app.include_router(alerts_router, prefix="/api/v1/alerts", tags=["告警通知"]) +app.include_router(dashboard_router, prefix="/api/v1/dashboard", tags=["仪表盘"]) +app.include_router(brands_router, prefix="/api/v1/brands", tags=["品牌管理"]) +app.include_router(onboarding_router, prefix="/api/v1") -@app.get("/health") +@app.get("/health", tags=["可观测性"]) async def health_check(): - return {"status": "ok"} + """存活检查(Liveness):服务进程是否运行正常。不依赖外部服务。""" + return { + "status": "healthy", + "timestamp": datetime.now(timezone.utc).isoformat(), + } + + +@app.get("/ready", tags=["可观测性"]) +async def readiness_check(db: AsyncSession = Depends(get_db)): + """就绪检查(Readiness):依赖服务(DB / Redis)是否就绪。 + + 供 Kubernetes readinessProbe / Docker healthcheck 使用。 + 不需要认证。 + """ + import redis.asyncio as aioredis # type: ignore + from app.config import settings as _settings + + # --- 检查数据库 --- + try: + await db.execute(text("SELECT 1")) + db_ok = True + except Exception: + db_ok = False + + # --- 检查 Redis --- + redis_ok = False + try: + redis_client = aioredis.from_url(_settings.REDIS_URL, socket_connect_timeout=2) + await redis_client.ping() + await redis_client.aclose() + redis_ok = True + except Exception: + pass + + all_ok = db_ok and redis_ok + return JSONResponse( + status_code=200 if all_ok else 503, + content={ + "status": "ready" if all_ok else "not_ready", + "checks": { + "database": "ok" if db_ok else "error", + "redis": "ok" if redis_ok else "error", + }, + "timestamp": datetime.now(timezone.utc).isoformat(), + }, + ) diff --git a/backend/app/middleware/metrics.py b/backend/app/middleware/metrics.py new file mode 100644 index 0000000..c87b97a --- /dev/null +++ b/backend/app/middleware/metrics.py @@ -0,0 +1,60 @@ +"""请求指标收集中间件:计时、慢请求告警、响应时间响应头。""" +import time +import logging +from starlette.middleware.base import BaseHTTPMiddleware +from starlette.requests import Request +from starlette.responses import Response + +logger = logging.getLogger("geo.metrics") + +# 慢请求阈值(秒) +SLOW_REQUEST_THRESHOLD = 1.0 + +# 跳过指标收集的路径前缀(健康检查等高频低价值路径) +_SKIP_PATHS = {"/health", "/ready", "/docs", "/openapi.json", "/favicon.ico"} + + +class MetricsMiddleware(BaseHTTPMiddleware): + """记录每个 HTTP 请求的耗时,并: + - 在响应头写入 X-Response-Time + - 对超过阈值的慢请求输出 WARNING 日志(携带结构化字段) + - 预留 Sentry / Prometheus 集成点(TODO 注释标注) + """ + + async def dispatch(self, request: Request, call_next) -> Response: + # 跳过健康检查等低价值路径,避免日志噪音 + if request.url.path in _SKIP_PATHS: + return await call_next(request) + + start_time = time.perf_counter() + response = await call_next(request) + duration = time.perf_counter() - start_time + duration_ms = round(duration * 1000, 2) + + # 写回响应时间响应头 + response.headers["X-Response-Time"] = f"{duration:.3f}s" + + # 从 request.state 获取 request_id(由 RequestIdMiddleware 注入) + request_id = getattr(request.state, "request_id", None) + + log_extra: dict = { + "path": request.url.path, + "method": request.method, + "duration_ms": duration_ms, + "status_code": response.status_code, + } + if request_id: + log_extra["request_id"] = request_id + + if duration >= SLOW_REQUEST_THRESHOLD: + logger.warning("Slow request detected", extra=log_extra) + else: + logger.debug("Request completed", extra=log_extra) + + # TODO: 集成 Prometheus Counter/Histogram + # metrics_registry.http_request_duration.observe(duration, labels={...}) + + # TODO: 集成 Sentry 性能监控 + # if sentry_sdk: sentry_sdk.set_measurement("response_time_ms", duration_ms) + + return response diff --git a/backend/app/middleware/rate_limit.py b/backend/app/middleware/rate_limit.py index 8037270..e41f2dc 100644 --- a/backend/app/middleware/rate_limit.py +++ b/backend/app/middleware/rate_limit.py @@ -7,6 +7,26 @@ from starlette.middleware.base import BaseHTTPMiddleware from starlette.requests import Request from starlette.responses import JSONResponse + +def _extract_user_id_from_request(request: Request) -> str | None: + """尝试从 Authorization header 解析 user_id(JWT sub)。 + 解析失败时返回 None,不影响主流程。 + """ + auth_header = request.headers.get("authorization", "") + if not auth_header.startswith("Bearer "): + return None + token = auth_header[len("Bearer "):] + if not token: + return None + try: + from app.services.auth import verify_token + payload = verify_token(token) + user_id: str | None = payload.get("sub") + return user_id + except Exception: + return None + + class RateLimitMiddleware(BaseHTTPMiddleware): def __init__(self, app): super().__init__(app) @@ -15,9 +35,14 @@ class RateLimitMiddleware(BaseHTTPMiddleware): # 限流规则 self.rules = { - "auth": { # /api/v1/auth/login, register, forgot-password - "paths": ["/api/v1/auth/login", "/api/v1/auth/register", "/api/v1/auth/forgot-password"], - "max_requests": 100, + "auth_strict": { # /api/v1/auth/login, register - 严格限流 5次/分钟/IP + "paths": ["/api/v1/auth/login", "/api/v1/auth/register"], + "max_requests": 5, + "window_seconds": 60, + }, + "auth": { # /api/v1/auth/ 其余接口 + "paths": ["/api/v1/auth/forgot-password", "/api/v1/auth/refresh"], + "max_requests": 20, "window_seconds": 60, }, "query_run": { # run-now @@ -35,37 +60,55 @@ class RateLimitMiddleware(BaseHTTPMiddleware): client_ip = request.client.host if request.client else "unknown" path = request.url.path now = time.time() - + # 健康检查不限流 if path == "/health" or path.startswith("/docs") or path.startswith("/openapi"): return await call_next(request) - - # 检查认证接口限流 - if any(path == p for p in self.rules["auth"]["paths"]): + + # 尝试从 Authorization header 解析 user_id + user_id = _extract_user_id_from_request(request) + + # 检查严格限流认证接口(login/register:5次/分钟/IP) + if any(path == p for p in self.rules["auth_strict"]["paths"]): + key = f"auth_strict:{client_ip}" + if self._is_rate_limited(key, now, self.rules["auth_strict"]): + return JSONResponse( + status_code=429, + content={"detail": "请求过于频繁,请稍后再试"} + ) + + # 检查普通认证接口限流 + elif any(path == p for p in self.rules["auth"]["paths"]): key = f"auth:{client_ip}" if self._is_rate_limited(key, now, self.rules["auth"]): return JSONResponse( status_code=429, content={"detail": "请求过于频繁,请稍后再试"} ) - - # 检查查询执行限流 + + # 检查查询执行限流(基于用户ID+IP组合) if path.endswith("/run-now") and request.method == "POST": - key = f"query_run:{client_ip}" + if user_id: + key = f"query_run:{user_id}:{client_ip}" + else: + key = f"query_run:{client_ip}" if self._is_rate_limited(key, now, self.rules["query_run"]): return JSONResponse( status_code=429, content={"detail": "查询执行过于频繁,请稍后再试"} ) - - # 全局限流 - key = f"global:{client_ip}" + + # 全局限流(基于用户ID+IP组合,未认证请求按IP限流) + if user_id: + key = f"global:{user_id}:{client_ip}" + else: + key = f"global:{client_ip}" if self._is_rate_limited(key, now, self.rules["global"]): return JSONResponse( status_code=429, content={"detail": "请求过于频繁,请稍后再试"} ) - + return await call_next(request) def _is_rate_limited(self, key, now, rule): diff --git a/backend/app/middleware/request_id.py b/backend/app/middleware/request_id.py new file mode 100644 index 0000000..a66a6d3 --- /dev/null +++ b/backend/app/middleware/request_id.py @@ -0,0 +1,29 @@ +"""Request ID 中间件:为每个请求生成并传播唯一标识符。""" +import uuid +import logging +from starlette.middleware.base import BaseHTTPMiddleware +from starlette.requests import Request +from starlette.responses import Response + +logger = logging.getLogger("geo.request_id") + +REQUEST_ID_HEADER = "X-Request-ID" + + +class RequestIdMiddleware(BaseHTTPMiddleware): + """从请求头读取或自动生成 X-Request-ID,注入 request.state 并写回响应头。 + + 使用场景: + - 链路追踪:日志中携带 request_id 方便跨服务排查 + - 客户端可主动传入 X-Request-ID,实现端到端追踪 + """ + + async def dispatch(self, request: Request, call_next) -> Response: + request_id = request.headers.get(REQUEST_ID_HEADER) or str(uuid.uuid4()) + + # 注入到 request.state,业务代码可通过 request.state.request_id 读取 + request.state.request_id = request_id + + response = await call_next(request) + response.headers[REQUEST_ID_HEADER] = request_id + return response diff --git a/backend/app/schemas/auth.py b/backend/app/schemas/auth.py index 777bbca..e047470 100644 --- a/backend/app/schemas/auth.py +++ b/backend/app/schemas/auth.py @@ -58,4 +58,16 @@ class UserResponse(BaseModel): class TokenResponse(BaseModel): access_token: str token_type: str + refresh_token: str user: UserResponse + + +class RefreshTokenRequest(BaseModel): + refresh_token: str + + +class AccessTokenResponse(BaseModel): + """刷新接口返回:新 access_token + 新 refresh_token(滑动过期)""" + access_token: str + token_type: str + refresh_token: str diff --git a/backend/app/schemas/common.py b/backend/app/schemas/common.py new file mode 100644 index 0000000..f0caebf --- /dev/null +++ b/backend/app/schemas/common.py @@ -0,0 +1,45 @@ +"""通用响应 Schema。""" +from datetime import datetime +from typing import Any + +from pydantic import BaseModel, Field + + +class ErrorResponse(BaseModel): + """统一错误响应格式。""" + + detail: str + code: str # 如 "NOT_FOUND", "VALIDATION_ERROR", "INTERNAL_ERROR", "FORBIDDEN" + timestamp: datetime = Field(default_factory=datetime.utcnow) + extra: dict[str, Any] | None = None + + model_config = {"from_attributes": True} + + +# 常用错误码常量 +class ErrorCode: + NOT_FOUND = "NOT_FOUND" + VALIDATION_ERROR = "VALIDATION_ERROR" + INTERNAL_ERROR = "INTERNAL_ERROR" + FORBIDDEN = "FORBIDDEN" + UNAUTHORIZED = "UNAUTHORIZED" + CONFLICT = "CONFLICT" + BAD_REQUEST = "BAD_REQUEST" + RATE_LIMITED = "RATE_LIMITED" + + # HTTP 状态码 → 错误码 映射 + STATUS_CODE_MAP: dict[int, str] = { + 400: "BAD_REQUEST", + 401: "UNAUTHORIZED", + 403: "FORBIDDEN", + 404: "NOT_FOUND", + 409: "CONFLICT", + 422: "VALIDATION_ERROR", + 429: "RATE_LIMITED", + 500: "INTERNAL_ERROR", + 503: "SERVICE_UNAVAILABLE", + } + + @classmethod + def from_status(cls, status_code: int) -> str: + return cls.STATUS_CODE_MAP.get(status_code, "INTERNAL_ERROR") diff --git a/backend/app/schemas/lifecycle.py b/backend/app/schemas/lifecycle.py index e462769..32c8225 100644 --- a/backend/app/schemas/lifecycle.py +++ b/backend/app/schemas/lifecycle.py @@ -1,7 +1,7 @@ import uuid from datetime import datetime -from pydantic import BaseModel +from pydantic import BaseModel, model_validator # ---------- Request ---------- @@ -36,10 +36,12 @@ class StageDetailResponse(BaseModel): class ProjectResponse(BaseModel): id: uuid.UUID organization_id: uuid.UUID + name: str = "" # alias for brand_name for frontend compatibility brand_name: str brand_aliases: list - current_stage: int + current_stage: str # mapped from int to string ("diagnosis" etc) for frontend status: str + owner_id: uuid.UUID | None = None # alias for created_by for frontend created_by: uuid.UUID | None created_at: datetime updated_at: datetime @@ -47,11 +49,39 @@ class ProjectResponse(BaseModel): model_config = {"from_attributes": True} + @model_validator(mode="before") + @classmethod + def map_fields(cls, data): + # Handle SQLAlchemy model instance + if hasattr(data, "current_stage"): + stage_int = getattr(data, "current_stage", 1) + stage_map = {1: "diagnosis", 2: "strategy", 3: "content", 4: "publishing", 5: "monitoring"} + if isinstance(stage_int, int): + object.__setattr__(data, "current_stage", stage_map.get(stage_int, "diagnosis")) + # Set name = brand_name for frontend + if not getattr(data, "name", None): + object.__setattr__(data, "name", getattr(data, "brand_name", "")) + # Set owner_id = created_by for frontend + if not getattr(data, "owner_id", None): + object.__setattr__(data, "owner_id", getattr(data, "created_by", None)) + elif isinstance(data, dict): + stage_val = data.get("current_stage", 1) + stage_map = {1: "diagnosis", 2: "strategy", 3: "content", 4: "publishing", 5: "monitoring"} + if isinstance(stage_val, int): + data["current_stage"] = stage_map.get(stage_val, "diagnosis") + data.setdefault("name", data.get("brand_name", "")) + data.setdefault("owner_id", data.get("created_by")) + return data + class ProjectStatsResponse(BaseModel): total_projects: int active_projects: int - stage_distribution: dict[str, int] + completed_projects: int = 0 + contents_produced: int = 0 + avg_ai_citation_rate: float | None = None + current_stage_distribution: dict[str, int] = {} + stage_distribution: dict[str, int] = {} completion_rate: float diff --git a/backend/app/services/admin.py b/backend/app/services/admin.py index d459aa3..252ab8d 100644 --- a/backend/app/services/admin.py +++ b/backend/app/services/admin.py @@ -1,7 +1,7 @@ import uuid from datetime import datetime, timedelta -from sqlalchemy import func, select +from sqlalchemy import func, select, case from sqlalchemy.ext.asyncio import AsyncSession from app.models.citation_record import CitationRecord @@ -64,17 +64,26 @@ async def get_users( base_stmt = base_stmt.order_by(User.created_at.desc()).offset(skip).limit(limit) result = await db.execute(base_stmt) - users = result.scalars().all() + users = list(result.scalars().all()) count_result = await db.execute(count_stmt) total = count_result.scalar_one() + if not users: + return {"items": [], "total": total} + + # 修复 N+1:一次性批量获取所有用户的 query 计数 + user_ids = [u.id for u in users] + query_count_stmt = ( + select(Query.user_id, func.count().label("cnt")) + .where(Query.user_id.in_(user_ids)) + .group_by(Query.user_id) + ) + qc_result = await db.execute(query_count_stmt) + query_counts: dict = {row.user_id: row.cnt for row in qc_result.all()} + items = [] for user in users: - query_count_result = await db.execute( - select(func.count()).select_from(Query).where(Query.user_id == user.id) - ) - query_count = query_count_result.scalar_one() items.append( { "id": user.id, @@ -84,7 +93,7 @@ async def get_users( "is_active": user.is_active, "is_admin": user.is_admin, "email_verified": user.email_verified, - "query_count": query_count, + "query_count": query_counts.get(user.id, 0), "created_at": user.created_at, } ) diff --git a/backend/app/services/auth.py b/backend/app/services/auth.py index a41a0d5..6b37ed3 100644 --- a/backend/app/services/auth.py +++ b/backend/app/services/auth.py @@ -25,14 +25,41 @@ def verify_password(plain_password: str, hashed_password: str) -> bool: def create_access_token(data: dict) -> str: to_encode = data.copy() - expire = datetime.utcnow() + timedelta(hours=settings.JWT_EXPIRE_HOURS) - to_encode.update({"exp": expire}) + # access token 有效期固定为 1 小时(替代原来的 JWT_EXPIRE_HOURS=24h) + expire = datetime.utcnow() + timedelta(hours=1) + to_encode.update({"exp": expire, "type": "access"}) encoded_jwt = jwt.encode(to_encode, settings.JWT_SECRET, algorithm="HS256") return encoded_jwt +def create_refresh_token(data: dict) -> str: + """7 天有效期的刷新令牌,使用 type: 'refresh' 区分""" + to_encode = data.copy() + expire = datetime.utcnow() + timedelta(days=7) + to_encode.update({"exp": expire, "type": "refresh"}) + encoded_jwt = jwt.encode(to_encode, settings.JWT_SECRET, algorithm="HS256") + return encoded_jwt + + +def verify_refresh_token(token: str) -> dict: + """验证 refresh token,返回 payload;如果无效或类型不匹配则抛出异常""" + try: + payload = jwt.decode(token, settings.JWT_SECRET, algorithms=["HS256"]) + except JWTError: + raise ValueError("刷新令牌无效") + if payload.get("type") != "refresh": + raise ValueError("令牌类型错误") + return payload + + def verify_token(token: str) -> dict: - payload = jwt.decode(token, settings.JWT_SECRET, algorithms=["HS256"]) + """验证 access token,返回 payload""" + try: + payload = jwt.decode(token, settings.JWT_SECRET, algorithms=["HS256"]) + except JWTError: + raise ValueError("访问令牌无效") + if payload.get("type") not in ("access", None): # None 兼容旧 token + raise ValueError("令牌类型错误") return payload diff --git a/backend/app/services/cache.py b/backend/app/services/cache.py new file mode 100644 index 0000000..e078739 --- /dev/null +++ b/backend/app/services/cache.py @@ -0,0 +1,106 @@ +"""Redis 缓存服务层。 + +提供统一的缓存读写接口,供各 API 端点使用: +- 品牌列表(TTL: 5 分钟) +- 仪表盘统计数据(TTL: 2 分钟) +- 用户配置信息(TTL: 10 分钟) +""" +import json +import logging +from typing import Any + +import redis.asyncio as aioredis + +from app.config import settings + +logger = logging.getLogger(__name__) + +# TTL 常量(秒) +TTL_BRANDS = 300 # 5 分钟 +TTL_DASHBOARD = 120 # 2 分钟 +TTL_USER_PROFILE = 600 # 10 分钟 + + +class CacheService: + """异步 Redis 缓存服务。""" + + def __init__(self) -> None: + self._redis: aioredis.Redis | None = None + + @property + def redis(self) -> aioredis.Redis: + if self._redis is None: + self._redis = aioredis.from_url( + settings.REDIS_URL, + encoding="utf-8", + decode_responses=True, + ) + return self._redis + + async def get(self, key: str) -> str | None: + """从缓存读取字符串值,不存在或出错时返回 None。""" + try: + return await self.redis.get(key) + except Exception as exc: + logger.warning("Cache GET failed for key=%s: %s", key, exc) + return None + + async def get_json(self, key: str) -> Any | None: + """从缓存读取并反序列化 JSON 值。""" + raw = await self.get(key) + if raw is None: + return None + try: + return json.loads(raw) + except json.JSONDecodeError: + return None + + async def set(self, key: str, value: str, expire: int = 300) -> None: + """写入缓存字符串值,expire 单位为秒。""" + try: + await self.redis.set(key, value, ex=expire) + except Exception as exc: + logger.warning("Cache SET failed for key=%s: %s", key, exc) + + async def set_json(self, key: str, value: Any, expire: int = 300) -> None: + """序列化为 JSON 后写入缓存。""" + try: + await self.set(key, json.dumps(value, default=str), expire=expire) + except Exception as exc: + logger.warning("Cache SET_JSON failed for key=%s: %s", key, exc) + + async def delete(self, key: str) -> None: + """删除指定缓存键。""" + try: + await self.redis.delete(key) + except Exception as exc: + logger.warning("Cache DELETE failed for key=%s: %s", key, exc) + + async def invalidate_pattern(self, pattern: str) -> int: + """批量删除匹配 pattern 的所有缓存键,返回删除数量。""" + try: + keys = await self.redis.keys(pattern) + if keys: + return await self.redis.delete(*keys) + return 0 + except Exception as exc: + logger.warning("Cache INVALIDATE_PATTERN failed for pattern=%s: %s", pattern, exc) + return 0 + + async def close(self) -> None: + """关闭 Redis 连接。""" + if self._redis is not None: + await self._redis.aclose() + self._redis = None + + +# 模块级单例(懒加载,应用启动后自动创建连接池) +_cache_service: CacheService | None = None + + +def get_cache_service() -> CacheService: + """获取全局缓存服务单例。""" + global _cache_service + if _cache_service is None: + _cache_service = CacheService() + return _cache_service diff --git a/backend/app/services/citation.py b/backend/app/services/citation.py index a1fd4be..fa27d48 100644 --- a/backend/app/services/citation.py +++ b/backend/app/services/citation.py @@ -289,6 +289,7 @@ async def trigger_query_now( keyword=query.keyword, target_brand=query.target_brand, brand_aliases=query.brand_aliases or [], + user_id=user_id, ) ) @@ -301,11 +302,19 @@ async def _execute_query_tasks( keyword: str, target_brand: str, brand_aliases: list, + user_id: uuid.UUID | None = None, ): """后台执行查询任务""" engine = CitationEngine() try: async with AsyncSessionLocal() as db: + # 验证 query 归属该用户 + if user_id is not None: + query = await _verify_query_ownership(db, query_id, user_id) + if query is None: + logger.error(f"查询 {query_id} 不属于用户 {user_id},跳过执行") + return + stmt = select(QueryTask).where( QueryTask.query_id == query_id, QueryTask.status == "pending", diff --git a/backend/app/services/knowledge/rag_service.py b/backend/app/services/knowledge/rag_service.py index 403f9b5..3045388 100644 --- a/backend/app/services/knowledge/rag_service.py +++ b/backend/app/services/knowledge/rag_service.py @@ -23,7 +23,16 @@ class RAGService: def __init__(self, embedder: Optional[EmbeddingService] = None): self.chunker = RecursiveChunker() - self.embedder = embedder or MockEmbedder() # 默认 mock,生产注入 OpenAIEmbedder + if embedder is not None: + self.embedder = embedder + else: + from app.config import settings + if settings.OPENAI_API_KEY: + from app.services.knowledge.embedder import OpenAIEmbedder + self.embedder = OpenAIEmbedder(api_key=settings.OPENAI_API_KEY) + else: + logger.warning("未配置 OPENAI_API_KEY,知识库将使用 MockEmbedder(仅适用于开发环境)") + self.embedder = MockEmbedder() self.retriever = HybridRetriever(self.embedder) # ------------------------------------------------------------------ diff --git a/backend/app/services/llm/__init__.py b/backend/app/services/llm/__init__.py index 589e239..6b7414d 100644 --- a/backend/app/services/llm/__init__.py +++ b/backend/app/services/llm/__init__.py @@ -2,6 +2,7 @@ from .base import LLMError, LLMProvider, LLMResponse from .deepseek_provider import DeepSeekProvider from .factory import LLMFactory from .openai_provider import OpenAIProvider +from .rate_limiter import TokenBucketRateLimiter, get_rate_limiter __all__ = [ "LLMProvider", @@ -10,4 +11,6 @@ __all__ = [ "LLMFactory", "OpenAIProvider", "DeepSeekProvider", + "TokenBucketRateLimiter", + "get_rate_limiter", ] diff --git a/backend/app/services/llm/deepseek_provider.py b/backend/app/services/llm/deepseek_provider.py index 581b68b..0e41b4e 100644 --- a/backend/app/services/llm/deepseek_provider.py +++ b/backend/app/services/llm/deepseek_provider.py @@ -6,6 +6,7 @@ from typing import AsyncIterator import httpx from .base import LLMError, LLMProvider, LLMResponse +from .rate_limiter import get_rate_limiter _DEFAULT_MODEL = "deepseek-chat" _DEFAULT_MAX_CONTEXT = 64_000 @@ -111,6 +112,9 @@ class DeepSeekProvider(LLMProvider): async def _request_with_retry(self, payload: dict, *, stream: bool = False) -> dict: """带重试的请求(指数退避:1s, 2s, 4s)""" + # 全局速率限制 + await get_rate_limiter().acquire() + last_error: Exception | None = None for attempt in range(_MAX_RETRIES): @@ -149,6 +153,9 @@ class DeepSeekProvider(LLMProvider): async def _stream_request(self, payload: dict) -> AsyncIterator[str]: """SSE流式请求(OpenAI兼容格式)""" + # 全局速率限制 + await get_rate_limiter().acquire() + last_error: Exception | None = None for attempt in range(_MAX_RETRIES): diff --git a/backend/app/services/llm/openai_provider.py b/backend/app/services/llm/openai_provider.py index 69aa956..ee5da81 100644 --- a/backend/app/services/llm/openai_provider.py +++ b/backend/app/services/llm/openai_provider.py @@ -6,6 +6,7 @@ from typing import AsyncIterator import httpx from .base import LLMError, LLMProvider, LLMResponse +from .rate_limiter import get_rate_limiter # 支持的模型及其上下文长度(百炼 Coding Plan + OpenAI) _OPENAI_MODELS: dict[str, int] = { @@ -126,6 +127,9 @@ class OpenAIProvider(LLMProvider): async def _request_with_retry(self, payload: dict, *, stream: bool = False) -> dict: """带重试的请求(指数退避:1s, 2s, 4s)""" + # 全局速率限制 + await get_rate_limiter().acquire() + last_error: Exception | None = None for attempt in range(_MAX_RETRIES): @@ -166,6 +170,9 @@ class OpenAIProvider(LLMProvider): async def _stream_request(self, payload: dict) -> AsyncIterator[str]: """SSE流式请求""" + # 全局速率限制 + await get_rate_limiter().acquire() + last_error: Exception | None = None for attempt in range(_MAX_RETRIES): diff --git a/backend/app/services/llm/rate_limiter.py b/backend/app/services/llm/rate_limiter.py new file mode 100644 index 0000000..c335645 --- /dev/null +++ b/backend/app/services/llm/rate_limiter.py @@ -0,0 +1,105 @@ +"""LLM 调用全局限速器(令牌桶算法) + +所有 LLMProvider 实例共享同一个 RateLimiter 单例, +确保跨 Provider 的总调用频率不超过配置上限。 +""" + +import asyncio +import logging +import os +import time +from collections import deque + +logger = logging.getLogger(__name__) + + +class TokenBucketRateLimiter: + """基于令牌桶算法的速率限制器 + + 默认 30 RPM(每秒补充约 0.5 个令牌),可通过环境变量 + LLM_RATE_LIMIT_RPM 调整。 + """ + + _instance: "TokenBucketRateLimiter | None" = None + _lock = asyncio.Lock() + + def __init__( + self, + max_rpm: float = 30.0, + ): + self._max_rpm = max_rpm + self._refill_rate = max_rpm / 60.0 # tokens per second + self._max_tokens = max_rpm + self._tokens = max_rpm # start full + self._last_refill = time.monotonic() + self._semaphore = asyncio.Semaphore(1) # 一次只能有一个 acquire 等待 + # 用于记录最近请求时间(调试/监控用) + self._recent_requests: deque[float] = deque(maxlen=int(max_rpm * 2)) + + @classmethod + def get_instance(cls) -> "TokenBucketRateLimiter": + """获取全局单例""" + if cls._instance is None: + rpm = float(os.getenv("LLM_RATE_LIMIT_RPM", "30")) + cls._instance = cls(max_rpm=rpm) + logger.info(f"LLM RateLimiter initialized: {rpm} RPM") + return cls._instance + + @classmethod + async def reset_instance(cls) -> None: + """重置单例(仅用于测试)""" + async with cls._lock: + if cls._instance is not None: + cls._instance = None + + def _refill(self) -> None: + """补充令牌""" + now = time.monotonic() + elapsed = now - self._last_refill + tokens_to_add = elapsed * self._refill_rate + self._tokens = min(self._max_tokens, self._tokens + tokens_to_add) + self._last_refill = now + + async def acquire(self) -> None: + """获取一个令牌,若无可用令牌则等待 + + 此方法可安全地从多个协程并发调用。 + """ + async with self._semaphore: + self._refill() + + if self._tokens >= 1.0: + self._tokens -= 1.0 + self._recent_requests.append(time.monotonic()) + return + + # 如果没有可用令牌,计算等待时间 + wait_time = (1.0 - self._tokens) / self._refill_rate + if wait_time > 0: + logger.debug(f"LLM rate limiter: waiting {wait_time:.2f}s for token") + await asyncio.sleep(wait_time) + + # 重试获取 + async with self._semaphore: + self._refill() + self._tokens = max(0.0, self._tokens - 1.0) + self._recent_requests.append(time.monotonic()) + + @property + def available_tokens(self) -> float: + """当前可用令牌数""" + return self._tokens + + @property + def max_rpm(self) -> float: + """配置的最大 RPM""" + return self._max_rpm + + +# 模块级便捷函数 +_rate_limiter: TokenBucketRateLimiter | None = None + + +def get_rate_limiter() -> TokenBucketRateLimiter: + """获取全局速率限制器实例""" + return TokenBucketRateLimiter.get_instance() diff --git a/backend/app/workers/llm_adapter.py b/backend/app/workers/llm_adapter.py index a996f18..be60a51 100644 --- a/backend/app/workers/llm_adapter.py +++ b/backend/app/workers/llm_adapter.py @@ -31,32 +31,47 @@ class LLMAdapterError(Exception): class LLMAdapter: - """LLM适配器 - 使用DeepSeek API检测品牌引用""" + """LLM适配器 - 使用 OpenAI 兼容协议检测品牌引用(支持百炼/DashScope/DeepSeek)""" def __init__(self, api_key: Optional[str] = None, max_retries: int = 3): """ 初始化LLM适配器 Args: - api_key: DeepSeek API密钥,默认使用settings中的配置 + api_key: API密钥,默认优先使用 OPENAI_API_KEY(百炼/DashScope),其次 DEEPSEEK_API_KEY max_retries: 最大重试次数 """ - self.api_key = api_key or getattr(settings, 'DEEPSEEK_API_KEY', None) + self.api_key = ( + api_key + or getattr(settings, 'OPENAI_API_KEY', None) + or getattr(settings, 'DEEPSEEK_API_KEY', None) + ) + # base_url 优先 OPENAI_BASE_URL,其次 DEEPSEEK_BASE_URL + self.base_url = ( + getattr(settings, 'OPENAI_BASE_URL', None) + or getattr(settings, 'DEEPSEEK_BASE_URL', 'https://api.deepseek.com/v1') + ) + # model 优先 OPENAI_MODEL,其次 DEFAULT_LLM_MODEL + self.model = ( + getattr(settings, 'OPENAI_MODEL', None) + or getattr(settings, 'DEFAULT_LLM_MODEL', 'qwen3-coder-plus') + or 'qwen3-coder-plus' + ) self.max_retries = max_retries self._client = None @property def client(self): - """延迟初始化DeepSeek客户端""" + """延迟初始化 OpenAI 兼容客户端""" if self._client is None: try: from openai import OpenAI self._client = OpenAI( api_key=self.api_key, - base_url="https://api.deepseek.com" + base_url=self.base_url, ) except ImportError: - raise LLMAdapterError("请安装deepseek-sdk或openai库: pip install deepseek-sdk") + raise LLMAdapterError("请安装openai库: pip install openai") return self._client def _build_prompt(self, keyword: str, brand_name: str, brand_aliases: list[str]) -> str: @@ -175,7 +190,7 @@ class LLMAdapter: API响应的JSON解析结果 """ response = self.client.chat.completions.create( - model="deepseek-chat", + model=self.model, messages=[ { "role": "user", diff --git a/backend/fix_citation_schema.py b/backend/fix_citation_schema.py new file mode 100644 index 0000000..6deb136 --- /dev/null +++ b/backend/fix_citation_schema.py @@ -0,0 +1,54 @@ +#!/usr/bin/env python3 +"""Fix missing sentiment columns in citation_records table.""" + +import asyncio +import asyncpg + + +async def fix_schema(): + # Read DATABASE_URL from .env file in project root + db_url = "postgresql://chiguyong@localhost:5432/geo_platform" + + conn = await asyncpg.connect(db_url) + try: + # Check existing columns + rows = await conn.fetch( + "SELECT column_name FROM information_schema.columns WHERE table_name = 'citation_records'" + ) + existing = {r["column_name"] for r in rows} + print(f"Existing columns: {existing}") + + needed = ["sentiment", "sentiment_confidence", "sentiment_key_phrases"] + missing = [c for c in needed if c not in existing] + + if not missing: + print("All sentiment columns already exist.") + return + + print(f"Missing columns: {missing}") + + if "sentiment" in missing: + await conn.execute( + "ALTER TABLE citation_records ADD COLUMN sentiment VARCHAR(20) NULL" + ) + print("Added sentiment column") + + if "sentiment_confidence" in missing: + await conn.execute( + "ALTER TABLE citation_records ADD COLUMN sentiment_confidence DOUBLE PRECISION NULL" + ) + print("Added sentiment_confidence column") + + if "sentiment_key_phrases" in missing: + await conn.execute( + "ALTER TABLE citation_records ADD COLUMN sentiment_key_phrases JSONB NULL" + ) + print("Added sentiment_key_phrases column") + + print("Schema fix complete.") + finally: + await conn.close() + + +if __name__ == "__main__": + asyncio.run(fix_schema()) diff --git a/backend/pyproject.toml b/backend/pyproject.toml new file mode 100644 index 0000000..cf5339b --- /dev/null +++ b/backend/pyproject.toml @@ -0,0 +1,17 @@ +[tool.ruff] +target-version = "py311" +line-length = 120 + +[tool.ruff.lint] +select = ["E", "W", "F", "I"] +ignore = ["E501"] + +[tool.ruff.lint.isort] +known-first-party = ["app"] + +[tool.pytest.ini_options] +asyncio_mode = "auto" +testpaths = ["tests"] +python_files = ["test_*.py"] +python_classes = ["Test*"] +python_functions = ["test_*"] diff --git a/backend/requirements.txt b/backend/requirements.txt index 20a8aaa..42b454a 100644 --- a/backend/requirements.txt +++ b/backend/requirements.txt @@ -1,6 +1,7 @@ # Web框架 fastapi>=0.109.0 uvicorn[standard] +gunicorn>=21.2.0 # 数据库 sqlalchemy>=2.0 diff --git a/backend/tests/test_performance.py b/backend/tests/test_performance.py new file mode 100644 index 0000000..ae9d0fa --- /dev/null +++ b/backend/tests/test_performance.py @@ -0,0 +1,381 @@ +"""Performance tests: concurrent access, response time, and rate limiting.""" +import asyncio +import time +import uuid + +import pytest +import pytest_asyncio +from httpx import AsyncClient, ASGITransport +from sqlalchemy.ext.asyncio import create_async_engine, async_sessionmaker, AsyncSession +from sqlalchemy.pool import StaticPool + +from app.database import Base +from app.main import app +from app.models.user import User +from app.models.query import Query +from app.models.brand import Brand +from app.models.competitor import Competitor +from app.models.suggestion import Suggestion +from app.api.deps import get_current_user, get_db +from app.services.auth import create_access_token, hash_password + +# Only the tables needed for performance tests (avoids JSONB/SQLite incompatibility) +_TEST_TABLES = ( + User.__table__, + Query.__table__, + Brand.__table__, + Competitor.__table__, + Suggestion.__table__, +) + + +# ─────────────────────── Fixtures ─────────────────────── + + +@pytest_asyncio.fixture +async def async_engine(): + """Create async engine for testing with SQLite. + + Only creates the specific tables needed by performance tests, + avoiding PostgreSQL-only types (JSONB) that fail on SQLite. + """ + engine = create_async_engine( + "sqlite+aiosqlite:///:memory:", + connect_args={"check_same_thread": False}, + poolclass=StaticPool, + ) + async with engine.begin() as conn: + await conn.run_sync( + lambda sync_conn: Base.metadata.create_all( + sync_conn, tables=[t for t in _TEST_TABLES] + ) + ) + yield engine + await engine.dispose() + + +@pytest_asyncio.fixture +async def async_session(async_engine): + """Create async session for testing.""" + async_session_maker = async_sessionmaker( + async_engine, + class_=AsyncSession, + expire_on_commit=False, + autoflush=False, + autocommit=False, + ) + async with async_session_maker() as session: + yield session + + +@pytest_asyncio.fixture +async def test_user(async_session): + """Create a test user with properly hashed password.""" + user = User( + id=uuid.uuid4(), + email="perf_test@example.com", + password_hash=hash_password("PerfTest123!"), + name="Performance Test User", + plan="free", + max_queries=50, + is_active=True, + email_verified=True, + ) + async_session.add(user) + await async_session.commit() + await async_session.refresh(user) + return user + + +@pytest_asyncio.fixture +async def async_client(async_session, test_user): + """Create async client for API testing with dependency overrides.""" + session = async_session + + async def override_get_db(): + yield session + + async def override_get_current_user(): + return test_user + + app.dependency_overrides[get_db] = override_get_db + app.dependency_overrides[get_current_user] = override_get_current_user + + transport = ASGITransport(app=app) + async with AsyncClient(transport=transport, base_url="http://test") as client: + yield client + + app.dependency_overrides.clear() + + +@pytest_asyncio.fixture +async def client_no_override(async_session): + """Create async client WITHOUT overriding get_current_user (for real auth flow).""" + session = async_session + + async def override_get_db(): + yield session + + app.dependency_overrides[get_db] = override_get_db + + transport = ASGITransport(app=app) + async with AsyncClient(transport=transport, base_url="http://test") as client: + yield client + + app.dependency_overrides.clear() + + +@pytest.fixture +def auth_headers(test_user): + """Create authentication headers.""" + token = create_access_token(data={"sub": str(test_user.id)}) + return {"Authorization": f"Bearer {token}"} + + +# ═══════════════════════════════════════════════════════════ +# API Response Time Tests +# ═══════════════════════════════════════════════════════════ + + +class TestAPIPerformance: + """Test API response time and concurrency behavior.""" + + @pytest.mark.asyncio + async def test_health_check_fast(self, async_client): + """Health check endpoint should respond quickly (< 100ms).""" + start = time.time() + response = await async_client.get("/health") + elapsed = time.time() - start + assert response.status_code == 200 + assert elapsed < 0.1, f"Health check took {elapsed:.3f}s, expected < 0.1s" + + @pytest.mark.asyncio + async def test_brand_list_performance(self, async_client, async_session, test_user, auth_headers): + """Brand list API should respond within 500ms.""" + # Create several brands for a more realistic test + for i in range(10): + brand = Brand( + user_id=test_user.id, + name=f"Brand {i}", + platforms=["wenxin"], + status="active", + ) + async_session.add(brand) + await async_session.commit() + + start = time.time() + response = await async_client.get("/api/v1/brands/", headers=auth_headers) + elapsed = time.time() - start + + assert response.status_code == 200 + assert elapsed < 0.5, f"Brand list took {elapsed:.3f}s, expected < 0.5s" + + @pytest.mark.asyncio + async def test_query_list_performance(self, async_client, async_session, test_user, auth_headers): + """Query list API should respond within 500ms.""" + # Create several queries for a more realistic test + for i in range(10): + query = Query( + user_id=test_user.id, + keyword=f"query keyword {i}", + target_brand=f"Brand {i}", + platforms=["wenxin"], + status="active", + ) + async_session.add(query) + await async_session.commit() + + start = time.time() + response = await async_client.get("/api/v1/queries/", headers=auth_headers) + elapsed = time.time() - start + + assert response.status_code == 200 + assert elapsed < 0.5, f"Query list took {elapsed:.3f}s, expected < 0.5s" + + @pytest.mark.asyncio + async def test_me_endpoint_performance(self, async_client, auth_headers): + """Current user endpoint should respond within 200ms.""" + start = time.time() + response = await async_client.get("/api/v1/auth/me", headers=auth_headers) + elapsed = time.time() - start + + assert response.status_code == 200 + assert elapsed < 0.2, f"/auth/me took {elapsed:.3f}s, expected < 0.2s" + + +# ═══════════════════════════════════════════════════════════ +# Concurrency Tests +# ═══════════════════════════════════════════════════════════ + + +class TestConcurrency: + """Test concurrent access behavior.""" + + @pytest.mark.asyncio + async def test_concurrent_login_no_crash(self, client_no_override, test_user): + """50 concurrent login requests should not cause system crash. + + Note: Rate limiting will kick in after 5 attempts from same IP, + so most requests will get 429. The key point is no 500 errors. + """ + tasks = [] + for _ in range(50): + task = client_no_override.post( + "/api/v1/auth/login", + json={ + "email": "perf_test@example.com", + "password": "PerfTest123!", + }, + ) + tasks.append(task) + + responses = await asyncio.gather(*tasks, return_exceptions=True) + + for i, resp in enumerate(responses): + if isinstance(resp, Exception): + # Network/transport errors are acceptable under heavy load + continue + # Should NOT get 500 — rate limiting (429) or auth errors (401/422) are fine + assert resp.status_code in (200, 401, 422, 429), ( + f"Concurrent login request {i} returned {resp.status_code}, " + f"expected 200/401/422/429" + ) + + @pytest.mark.asyncio + async def test_concurrent_brand_reads(self, async_client, async_session, test_user, auth_headers): + """Concurrent brand list reads should all succeed.""" + # Pre-create data + for i in range(5): + brand = Brand( + user_id=test_user.id, + name=f"Concurrent Brand {i}", + platforms=["wenxin"], + status="active", + ) + async_session.add(brand) + await async_session.commit() + + # 20 concurrent read requests + tasks = [ + async_client.get("/api/v1/brands/", headers=auth_headers) + for _ in range(20) + ] + responses = await asyncio.gather(*tasks, return_exceptions=True) + + success_count = 0 + for resp in responses: + if isinstance(resp, Exception): + continue + if resp.status_code == 200: + success_count += 1 + + # At least some should succeed + assert success_count > 0, "No concurrent brand reads succeeded" + + @pytest.mark.asyncio + async def test_concurrent_query_reads(self, async_client, async_session, test_user, auth_headers): + """Concurrent query list reads should all succeed.""" + for i in range(5): + query = Query( + user_id=test_user.id, + keyword=f"concurrent query {i}", + target_brand=f"Brand {i}", + platforms=["wenxin"], + status="active", + ) + async_session.add(query) + await async_session.commit() + + tasks = [ + async_client.get("/api/v1/queries/", headers=auth_headers) + for _ in range(20) + ] + responses = await asyncio.gather(*tasks, return_exceptions=True) + + success_count = 0 + for resp in responses: + if isinstance(resp, Exception): + continue + if resp.status_code == 200: + success_count += 1 + + assert success_count > 0, "No concurrent query reads succeeded" + + +# ═══════════════════════════════════════════════════════════ +# Rate Limiting Tests +# ═══════════════════════════════════════════════════════════ + + +class TestRateLimiting: + """Test rate limiting enforcement.""" + + @pytest.mark.asyncio + async def test_login_rate_limit_enforcement(self, client_no_override): + """Login endpoint should enforce rate limiting (5 req/min/IP). + + After 5 rapid login attempts, subsequent requests should get 429. + """ + # Note: RateLimitMiddleware state is shared across the app instance. + # Since other tests may have already sent requests, we need to + # send enough to trigger the limit. The auth_strict rule allows + # 5 requests per 60 seconds per IP. + responses = [] + for _ in range(8): + response = await client_no_override.post( + "/api/v1/auth/login", + json={ + "email": "ratelimit@example.com", + "password": "somepassword123", + }, + ) + responses.append(response) + + # At least one of the later requests should be rate-limited (429) + status_codes = [r.status_code for r in responses] + # After 5 requests, additional ones should get 429 + rate_limited = [code for code in status_codes if code == 429] + assert len(rate_limited) > 0, ( + f"No rate limiting detected. Status codes: {status_codes}. " + f"Expected at least one 429 after 8 rapid login attempts." + ) + + @pytest.mark.asyncio + async def test_global_rate_limit_high_threshold(self, async_client, auth_headers): + """Global rate limit (100 req/min) should allow normal usage patterns. + + Sending 10 rapid requests should all succeed (well within limit). + """ + responses = [] + for _ in range(10): + response = await async_client.get("/health") + responses.append(response) + + # All should succeed — well under global limit + success_count = sum(1 for r in responses if r.status_code == 200) + assert success_count == 10, ( + f"Expected all 10 health checks to succeed, got {success_count}/10" + ) + + @pytest.mark.asyncio + async def test_rate_limit_429_response_format(self, client_no_override): + """Rate-limited responses should have proper 429 format.""" + # Exhaust login rate limit + for _ in range(8): + await client_no_override.post( + "/api/v1/auth/login", + json={"email": "rl@example.com", "password": "password123"}, + ) + + # This one should be rate-limited + response = await client_no_override.post( + "/api/v1/auth/login", + json={"email": "rl@example.com", "password": "password123"}, + ) + + if response.status_code == 429: + data = response.json() + # Should have a detail message + assert "detail" in data or "message" in data, ( + "429 response should include a detail or message field" + ) \ No newline at end of file diff --git a/backend/tests/test_security.py b/backend/tests/test_security.py new file mode 100644 index 0000000..e0ecfe4 --- /dev/null +++ b/backend/tests/test_security.py @@ -0,0 +1,667 @@ +"""Security tests: SQL injection, XSS protection, and authentication security.""" +import uuid +from datetime import datetime, timedelta + +import pytest +import pytest_asyncio +from httpx import AsyncClient, ASGITransport +from jose import jwt +from sqlalchemy.ext.asyncio import create_async_engine, async_sessionmaker, AsyncSession +from sqlalchemy.pool import StaticPool + +from app.database import Base +from app.main import app +from app.models.user import User +from app.models.brand import Brand +from app.models.query import Query +from app.models.competitor import Competitor +from app.models.suggestion import Suggestion +from app.api.deps import get_current_user, get_db +from app.services.auth import create_access_token, create_refresh_token, hash_password +from app.config import settings + +# Only the tables needed for security tests (avoids JSONB/SQLite incompatibility) +_TEST_TABLES = ( + User.__table__, + Brand.__table__, + Query.__table__, + Competitor.__table__, + Suggestion.__table__, +) + + +# ─────────────────────── Fixtures ─────────────────────── + + +@pytest_asyncio.fixture +async def async_engine(): + """Create async engine for testing with SQLite. + + Only creates the specific tables needed by security tests, + avoiding PostgreSQL-only types (JSONB) that fail on SQLite. + """ + engine = create_async_engine( + "sqlite+aiosqlite:///:memory:", + connect_args={"check_same_thread": False}, + poolclass=StaticPool, + ) + async with engine.begin() as conn: + await conn.run_sync( + lambda sync_conn: Base.metadata.create_all( + sync_conn, tables=[t for t in _TEST_TABLES] + ) + ) + yield engine + await engine.dispose() + + +@pytest_asyncio.fixture +async def async_session(async_engine): + """Create async session for testing.""" + async_session_maker = async_sessionmaker( + async_engine, + class_=AsyncSession, + expire_on_commit=False, + autoflush=False, + autocommit=False, + ) + async with async_session_maker() as session: + yield session + + +@pytest_asyncio.fixture +async def test_user(async_session): + """Create a test user with properly hashed password.""" + user = User( + id=uuid.uuid4(), + email="security_test@example.com", + password_hash=hash_password("SecurePass123!"), + name="Security Test User", + plan="free", + max_queries=5, + is_active=True, + email_verified=True, + ) + async_session.add(user) + await async_session.commit() + await async_session.refresh(user) + return user + + +@pytest_asyncio.fixture +async def second_user(async_session): + """Create a second test user for cross-user isolation tests.""" + user = User( + id=uuid.uuid4(), + email="second_user@example.com", + password_hash=hash_password("SecondPass456!"), + name="Second User", + plan="free", + max_queries=5, + is_active=True, + email_verified=True, + ) + async_session.add(user) + await async_session.commit() + await async_session.refresh(user) + return user + + +@pytest_asyncio.fixture +async def async_client(async_session, test_user): + """Create async client for API testing with dependency overrides.""" + session = async_session + + async def override_get_db(): + yield session + + async def override_get_current_user(): + return test_user + + app.dependency_overrides[get_db] = override_get_db + app.dependency_overrides[get_current_user] = override_get_current_user + + transport = ASGITransport(app=app) + async with AsyncClient(transport=transport, base_url="http://test") as client: + yield client + + app.dependency_overrides.clear() + + +@pytest_asyncio.fixture +async def client_no_override(async_session): + """Create async client WITHOUT overriding get_current_user. + + This allows testing real JWT authentication flow. + get_db is still overridden to use test database. + """ + session = async_session + + async def override_get_db(): + yield session + + app.dependency_overrides[get_db] = override_get_db + # Intentionally NOT overriding get_current_user + + transport = ASGITransport(app=app) + async with AsyncClient(transport=transport, base_url="http://test") as client: + yield client + + app.dependency_overrides.clear() + + +@pytest.fixture +def auth_headers(test_user): + """Create authentication headers for test_user.""" + token = create_access_token(data={"sub": str(test_user.id)}) + return {"Authorization": f"Bearer {token}"} + + +@pytest.fixture +def second_auth_headers(second_user): + """Create authentication headers for second_user.""" + token = create_access_token(data={"sub": str(second_user.id)}) + return {"Authorization": f"Bearer {token}"} + + +# ═══════════════════════════════════════════════════════════ +# SQL Injection Protection Tests +# ═══════════════════════════════════════════════════════════ + + +class TestSQLInjection: + """Verify that SQL injection attack vectors are properly mitigated.""" + + @pytest.mark.asyncio + async def test_login_sql_injection_rejected(self, client_no_override): + """Login endpoint should reject SQL injection payloads. + + Email field uses EmailStr validation, so non-email payloads + should return 422 (validation error). The ORM layer uses + parameterized queries, preventing SQL injection even if + payloads pass validation. 429 (rate-limited) is also + acceptable — it means the security layer is working. + """ + payloads = [ + "' OR '1'='1", + "'; DROP TABLE users; --", + "admin'--", + "1' UNION SELECT * FROM users--", + "' OR 1=1 --", + '" OR ""=""', + "1; SELECT * FROM users WHERE '1' = '1'", + ] + for payload in payloads: + response = await client_no_override.post( + "/api/v1/auth/login", + json={"email": payload, "password": payload}, + ) + # 422: EmailStr validation rejects non-email strings + # 401: If valid email format but auth fails + # 429: Rate-limited (also a correct security behavior) + assert response.status_code in (401, 422, 429), ( + f"SQL injection payload '{payload}' returned {response.status_code}, " + f"expected 401/422/429" + ) + + @pytest.mark.asyncio + async def test_register_sql_injection_rejected(self, client_no_override): + """Registration endpoint should reject SQL injection payloads.""" + payloads = [ + "' OR '1'='1", + "admin'--; DROP TABLE users;--", + "1' UNION SELECT * FROM users--", + ] + for payload in payloads: + response = await client_no_override.post( + "/api/v1/auth/register", + json={"email": payload, "password": "password123", "name": "test"}, + ) + # 429 is acceptable — rate-limited is a valid security response + assert response.status_code in (400, 422, 429), ( + f"SQL injection payload '{payload}' returned {response.status_code}" + ) + + @pytest.mark.asyncio + async def test_query_path_param_injection(self, async_client, auth_headers): + """Path parameters should not be vulnerable to SQL injection. + + UUID-type path parameters will fail validation for non-UUID inputs. + """ + injection_payloads = [ + "1' OR '1'='1", + "1; DROP TABLE queries; --", + "' UNION SELECT * FROM users--", + ] + for payload in injection_payloads: + response = await async_client.get( + f"/api/v1/queries/{payload}", + headers=auth_headers, + ) + # Non-UUID path params should return 422 (validation error) + assert response.status_code in (404, 422), ( + f"Path param injection '{payload}' returned {response.status_code}" + ) + + @pytest.mark.asyncio + async def test_brand_path_param_injection(self, async_client, auth_headers): + """Brand path parameters should reject SQL injection.""" + injection_payloads = [ + "1' OR '1'='1", + "1; DROP TABLE brands; --", + ] + for payload in injection_payloads: + response = await async_client.get( + f"/api/v1/brands/{payload}/", + headers=auth_headers, + ) + assert response.status_code in (404, 422), ( + f"Brand path param injection '{payload}' returned {response.status_code}" + ) + + @pytest.mark.asyncio + async def test_forgot_password_sql_injection_rejected(self, client_no_override): + """Forgot-password endpoint should reject SQL injection payloads.""" + payloads = [ + "' OR '1'='1", + "admin'--", + ] + for payload in payloads: + response = await client_no_override.post( + "/api/v1/auth/forgot-password", + json={"email": payload}, + ) + assert response.status_code in (200, 422, 429), ( + f"SQL injection payload '{payload}' returned {response.status_code}" + ) + # Even if 200 (generic response), should not leak user existence + if response.status_code == 200: + data = response.json() + assert "message" in data + + @pytest.mark.asyncio + async def test_reset_password_sql_injection_rejected(self, client_no_override): + """Reset-password endpoint should handle injection payloads safely.""" + response = await client_no_override.post( + "/api/v1/auth/reset-password", + json={ + "token": "' OR '1'='1", + "new_password": "newpassword123", + }, + ) + # Token should be rejected (invalid or expired), not cause SQL error + assert response.status_code in (400, 422, 429), ( + f"Reset password injection returned {response.status_code}" + ) + + +# ═══════════════════════════════════════════════════════════ +# XSS Protection Tests +# ═══════════════════════════════════════════════════════════ + + +class TestXSSProtection: + """Verify that XSS attack vectors are properly mitigated. + + For a pure JSON API, XSS payloads stored as-is in the database is + expected behavior — JSON responses are not rendered as HTML by + browsers. The real XSS protections are: + 1. Content-Type: application/json (prevents HTML rendering) + 2. Security headers (X-XSS-Protection, X-Content-Type-Options, etc.) + 3. Frontend escaping when rendering data in HTML + """ + + @pytest.mark.asyncio + async def test_api_returns_json_content_type(self, async_client, auth_headers): + """All API responses must have Content-Type: application/json. + + This is the primary XSS defense for JSON APIs — browsers will + not execute scripts in JSON responses. + """ + endpoints = [ + ("/api/v1/brands/", "GET"), + ("/api/v1/queries/", "GET"), + ] + for path, method in endpoints: + response = await async_client.get(path, headers=auth_headers) + if response.status_code == 200: + content_type = response.headers.get("content-type", "") + assert "application/json" in content_type, ( + f"Response for {path} has Content-Type '{content_type}', " + f"expected 'application/json'" + ) + + @pytest.mark.asyncio + async def test_brand_name_xss_not_executable(self, async_client, auth_headers): + """XSS payloads in brand name should be stored as plain text. + + In a JSON API, script tags are stored as text and not executed + because the response Content-Type is application/json. + The key assertion is that the response is valid JSON (not HTML). + """ + xss_payloads = [ + "", + "", + "javascript:alert(1)", + "", + "", + ] + for payload in xss_payloads: + response = await async_client.put( + f"/api/v1/brands/{brand.id}/", + json={"aliases": [payload]}, + headers=auth_headers, + ) + if response.status_code == 200: + data = response.json() + content_type = response.headers.get("content-type", "") + assert "application/json" in content_type + # XSS payloads stored as plain text in JSON + assert payload in data.get("aliases", []) + + @pytest.mark.asyncio + async def test_query_keyword_xss_as_plain_text(self, async_client, auth_headers): + """XSS payloads in query keyword should be stored as plain text.""" + xss_payload = "" + response = await async_client.post( + "/api/v1/queries/", + json={ + "keyword": xss_payload, + "target_brand": "Test Brand", + "platforms": ["wenxin"], + }, + headers=auth_headers, + ) + if response.status_code in (200, 201): + data = response.json() + content_type = response.headers.get("content-type", "") + assert "application/json" in content_type + # XSS payload stored as plain text + assert data.get("keyword") == xss_payload + + @pytest.mark.asyncio + async def test_security_headers_present(self, async_client): + """Verify that security response headers are set on all responses.""" + response = await async_client.get("/health") + assert response.status_code == 200 + + # Check essential security headers + assert response.headers.get("x-content-type-options") == "nosniff", ( + "X-Content-Type-Options header missing or incorrect" + ) + assert response.headers.get("x-frame-options") == "DENY", ( + "X-Frame-Options header missing or incorrect" + ) + assert response.headers.get("x-xss-protection") == "1; mode=block", ( + "X-XSS-Protection header missing or incorrect" + ) + assert response.headers.get("referrer-policy") == "strict-origin-when-cross-origin", ( + "Referrer-Policy header missing or incorrect" + ) + + @pytest.mark.asyncio + async def test_security_headers_on_api_endpoints(self, async_client, auth_headers): + """Security headers should be present on API endpoints too.""" + response = await async_client.get("/api/v1/brands/", headers=auth_headers) + if response.status_code == 200: + assert response.headers.get("x-content-type-options") == "nosniff" + assert response.headers.get("x-frame-options") == "DENY" + assert response.headers.get("x-xss-protection") == "1; mode=block" + + +# ═══════════════════════════════════════════════════════════ +# Authentication Security Tests +# ═══════════════════════════════════════════════════════════ + + +class TestAuthSecurity: + """Verify authentication security mechanisms.""" + + @pytest.mark.asyncio + async def test_expired_token_rejected(self, client_no_override): + """Expired JWT tokens should be rejected with 401.""" + # Create a token that expired 1 hour ago + expired_payload = { + "sub": str(uuid.uuid4()), + "exp": datetime.utcnow() - timedelta(hours=1), + "type": "access", + } + expired_token = jwt.encode(expired_payload, settings.JWT_SECRET, algorithm="HS256") + + response = await client_no_override.get( + "/api/v1/auth/me", + headers={"Authorization": f"Bearer {expired_token}"}, + ) + assert response.status_code == 401, ( + f"Expired token should be rejected, got {response.status_code}" + ) + + @pytest.mark.asyncio + async def test_invalid_token_rejected(self, client_no_override): + """Invalid JWT tokens should be rejected with 401.""" + invalid_tokens = [ + "invalid.token.here", + "eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.invalid.payload", + "null", + "undefined", + ] + for token in invalid_tokens: + response = await client_no_override.get( + "/api/v1/auth/me", + headers={"Authorization": f"Bearer {token}"}, + ) + assert response.status_code == 401, ( + f"Invalid token '{token[:20]}...' should be rejected, got {response.status_code}" + ) + + @pytest.mark.asyncio + async def test_invalid_refresh_token(self, client_no_override): + """Invalid refresh tokens should return 401.""" + invalid_tokens = [ + "invalid.refresh.token", + "eyJhbGciOiJIUzI1NiJ9.invalid.payload", + ] + for token in invalid_tokens: + response = await client_no_override.post( + "/api/v1/auth/refresh", + json={"refresh_token": token}, + ) + assert response.status_code == 401, ( + f"Invalid refresh token should be rejected, got {response.status_code}" + ) + + @pytest.mark.asyncio + async def test_access_token_used_as_refresh_rejected(self, client_no_override, test_user): + """Access tokens should not be accepted as refresh tokens.""" + access_token = create_access_token(data={"sub": str(test_user.id)}) + + response = await client_no_override.post( + "/api/v1/auth/refresh", + json={"refresh_token": access_token}, + ) + assert response.status_code == 401, ( + "Access token used as refresh token should be rejected" + ) + + @pytest.mark.asyncio + async def test_refresh_token_used_as_access_rejected(self, client_no_override, test_user): + """Refresh tokens should not be accepted as access tokens.""" + refresh_token = create_refresh_token(data={"sub": str(test_user.id)}) + + response = await client_no_override.get( + "/api/v1/auth/me", + headers={"Authorization": f"Bearer {refresh_token}"}, + ) + assert response.status_code == 401, ( + "Refresh token used as access token should be rejected" + ) + + @pytest.mark.asyncio + async def test_missing_authorization_header(self, client_no_override): + """Requests without Authorization header should return 401.""" + response = await client_no_override.get("/api/v1/auth/me") + assert response.status_code in (401, 403), ( + f"Missing auth should return 401/403, got {response.status_code}" + ) + + @pytest.mark.asyncio + async def test_cross_user_data_isolation( + self, async_session, test_user, second_user, auth_headers + ): + """User A should not be able to access User B's brand data.""" + # Create a brand for second_user + brand = Brand( + id=uuid.uuid4(), + user_id=second_user.id, + name="Second User's Brand", + platforms=["wenxin"], + status="active", + ) + async_session.add(brand) + await async_session.commit() + await async_session.refresh(brand) + + async def override_get_db(): + yield async_session + + app.dependency_overrides[get_db] = override_get_db + # Do NOT override get_current_user — let JWT auth work naturally + + test_user_token = create_access_token(data={"sub": str(test_user.id)}) + transport = ASGITransport(app=app) + async with AsyncClient(transport=transport, base_url="http://test") as client: + # test_user tries to access second_user's brand + response = await client.get( + f"/api/v1/brands/{brand.id}/", + headers={"Authorization": f"Bearer {test_user_token}"}, + ) + assert response.status_code == 404, ( + f"User should not access another user's brand, got {response.status_code}" + ) + + app.dependency_overrides.clear() + + @pytest.mark.asyncio + async def test_cross_user_query_isolation( + self, async_session, test_user, second_user + ): + """User A should not be able to access User B's query data.""" + query = Query( + id=uuid.uuid4(), + user_id=second_user.id, + keyword="Second User Query", + target_brand="Second Brand", + platforms=["wenxin"], + status="active", + ) + async_session.add(query) + await async_session.commit() + await async_session.refresh(query) + + async def override_get_db(): + yield async_session + + app.dependency_overrides[get_db] = override_get_db + + test_user_token = create_access_token(data={"sub": str(test_user.id)}) + transport = ASGITransport(app=app) + async with AsyncClient(transport=transport, base_url="http://test") as client: + response = await client.get( + f"/api/v1/queries/{query.id}", + headers={"Authorization": f"Bearer {test_user_token}"}, + ) + assert response.status_code == 404, ( + f"User should not access another user's query, got {response.status_code}" + ) + + app.dependency_overrides.clear() + + @pytest.mark.asyncio + async def test_nonexistent_user_token_rejected(self, client_no_override): + """Token with nonexistent user_id should be rejected.""" + fake_user_id = str(uuid.uuid4()) + token = create_access_token(data={"sub": fake_user_id}) + + response = await client_no_override.get( + "/api/v1/auth/me", + headers={"Authorization": f"Bearer {token}"}, + ) + assert response.status_code == 401, ( + f"Token for nonexistent user should be rejected, got {response.status_code}" + ) + + @pytest.mark.asyncio + async def test_login_error_message_no_user_enumeration(self, client_no_override): + """Login error messages should not reveal whether email exists. + + Both non-existent email and wrong password should return + the same error status. Rate limiting (429) is also acceptable. + """ + # Non-existent email + response1 = await client_no_override.post( + "/api/v1/auth/login", + json={"email": "nonexistent@example.com", "password": "password123"}, + ) + + # Existing email with wrong password + response2 = await client_no_override.post( + "/api/v1/auth/login", + json={"email": "security_test@example.com", "password": "WrongPassword999!"}, + ) + + # Both should return the same status code (either 401 or 429 if rate-limited) + # The key point: no information leakage about whether the user exists + assert response1.status_code in (401, 429), ( + f"Non-existent email login returned {response1.status_code}, expected 401/429" + ) + assert response2.status_code in (401, 429), ( + f"Wrong password login returned {response2.status_code}, expected 401/429" + ) + + # When both return 401 (not rate-limited), verify same error structure + if response1.status_code == 401 and response2.status_code == 401: + # Both should have consistent error responses (no user enumeration) + assert response1.status_code == response2.status_code diff --git a/backend/update_email.py b/backend/update_email.py deleted file mode 100644 index 4602111..0000000 --- a/backend/update_email.py +++ /dev/null @@ -1,39 +0,0 @@ -"""Update admin email from admin@ficher.com to admin@fischer.com""" -import asyncio -import sys -sys.path.insert(0, '/Users/Chiguyong/Code/GEO/backend') - -from sqlalchemy import text -from app.database import AsyncSessionLocal - -async def main(): - async with AsyncSessionLocal() as session: - # Check current user - result = await session.execute(text("SELECT id, email FROM users WHERE email='admin@ficher.com'")) - row = result.fetchone() - if row: - print(f"Found user: id={row[0]}, email={row[1]}") - await session.execute(text("UPDATE users SET email='admin@fischer.com' WHERE email='admin@ficher.com'")) - await session.commit() - print("Email updated to admin@fischer.com") - else: - print("No user found with admin@ficher.com") - result2 = await session.execute(text("SELECT id, email FROM users WHERE email='admin@fischer.com'")) - row2 = result2.fetchone() - if row2: - print(f"Already updated: id={row2[0]}, email={row2[1]}") - else: - print("No admin user found at all!") - all_users = await session.execute(text("SELECT id, email FROM users LIMIT 10")) - for u in all_users.fetchall(): - print(f" User: id={u[0]}, email={u[1]}") - - # Verify - verify = await session.execute(text("SELECT id, email FROM users WHERE email='admin@fischer.com'")) - v = verify.fetchone() - if v: - print(f"Verified: id={v[0]}, email={v[1]}") - else: - print("WARNING: Verification failed - admin@fischer.com not found!") - -asyncio.run(main()) diff --git a/csrf.json b/csrf.json new file mode 100644 index 0000000..96602e2 --- /dev/null +++ b/csrf.json @@ -0,0 +1 @@ +{"csrfToken":"defd4951c4d87238088193a161570b32ea50fa5015753e6e6eeb4adc1d7c0f8c"} \ No newline at end of file diff --git a/csrf_headers.txt b/csrf_headers.txt new file mode 100644 index 0000000..f547534 --- /dev/null +++ b/csrf_headers.txt @@ -0,0 +1,13 @@ +HTTP/1.1 200 OK +vary: RSC, Next-Router-State-Tree, Next-Router-Prefetch +cache-control: private, no-cache, no-store +content-type: application/json +expires: 0 +pragma: no-cache +set-cookie: next-auth.csrf-token=8ecba5438bf185bf0a664e52de0510a57ded93697162fbcf4d61435397cba604%7C6d4116c237ade107969662e104cfd7ab4580ea3306b948a5842c27202943ef5d; Path=/; HttpOnly; SameSite=Lax +set-cookie: next-auth.callback-url=http%3A%2F%2Flocalhost%3A3000; Path=/; HttpOnly; SameSite=Lax +Date: Sat, 23 May 2026 08:44:02 GMT +Connection: keep-alive +Keep-Alive: timeout=5 +Transfer-Encoding: chunked + diff --git a/csrf_resp.json b/csrf_resp.json new file mode 100644 index 0000000..193cfd1 --- /dev/null +++ b/csrf_resp.json @@ -0,0 +1 @@ +{"csrfToken":"8ecba5438bf185bf0a664e52de0510a57ded93697162fbcf4d61435397cba604"} \ No newline at end of file diff --git a/docker-compose.prod.yml b/docker-compose.prod.yml new file mode 100644 index 0000000..1d9c806 --- /dev/null +++ b/docker-compose.prod.yml @@ -0,0 +1,140 @@ +# ============================================================ +# GEO Platform — 生产环境 Docker Compose 配置 +# +# 生产部署前必须完成的配置: +# 1. 创建 .env.production 文件(参考 .env.example),配置真实密钥: +# - SECRET_KEY / NEXTAUTH_SECRET(使用随机强密码) +# - DATABASE_URL(建议使用托管数据库,如 RDS / Cloud SQL) +# - REDIS_URL(建议使用托管 Redis,如 ElastiCache) +# - LLM API Keys(DASHSCOPE_API_KEY 等) +# 2. 配置反向代理(Nginx / Caddy)并启用 HTTPS +# 3. 将数据库和 Redis 卷挂载到持久化存储(或使用托管服务) +# 4. 检查防火墙规则,生产环境不应暴露 5432 / 6379 端口到公网 +# 5. 使用 docker compose -f docker-compose.prod.yml up -d 启动 +# ============================================================ + +version: "3.9" + +services: + db: + image: postgres:15-alpine + container_name: geo_db_prod + restart: always + environment: + POSTGRES_USER: ${POSTGRES_USER} + POSTGRES_PASSWORD: ${POSTGRES_PASSWORD} + POSTGRES_DB: ${POSTGRES_DB:-geo_platform} + # 生产环境不对外暴露数据库端口 + expose: + - "5432" + volumes: + - postgres_data:/var/lib/postgresql/data + healthcheck: + test: ["CMD-SHELL", "pg_isready -U ${POSTGRES_USER} -d ${POSTGRES_DB:-geo_platform}"] + interval: 10s + timeout: 5s + retries: 5 + start_period: 30s + deploy: + resources: + limits: + memory: 1g + cpus: '1.0' + reservations: + memory: 512m + networks: + - geo_internal + + redis: + image: redis:7-alpine + container_name: geo_redis_prod + restart: always + # 使用密码保护 Redis(生产必须配置) + command: redis-server --requirepass ${REDIS_PASSWORD} --maxmemory 200mb --maxmemory-policy allkeys-lru + expose: + - "6379" + volumes: + - redis_data:/data + healthcheck: + test: ["CMD", "redis-cli", "-a", "${REDIS_PASSWORD}", "ping"] + interval: 10s + timeout: 5s + retries: 5 + start_period: 15s + deploy: + resources: + limits: + memory: 256m + cpus: '0.5' + reservations: + memory: 128m + networks: + - geo_internal + + backend: + build: + context: ./backend + dockerfile: Dockerfile + container_name: geo_backend_prod + restart: always + expose: + - "8000" + env_file: + - .env.production + # 生产环境不挂载源代码目录,镜像内已包含完整代码 + depends_on: + db: + condition: service_healthy + redis: + condition: service_healthy + # 使用 Dockerfile 中定义的 gunicorn 启动命令 + deploy: + resources: + limits: + memory: 1g + cpus: '2.0' + reservations: + memory: 512m + networks: + - geo_internal + - geo_public + + frontend: + build: + context: ./frontend + dockerfile: Dockerfile + container_name: geo_frontend_prod + restart: always + ports: + # 通过反向代理访问,本地仅绑定 127.0.0.1 + - "127.0.0.1:3000:3000" + env_file: + - .env.production + # 生产环境不挂载源代码目录 + depends_on: + - backend + deploy: + resources: + limits: + memory: 512m + cpus: '1.0' + reservations: + memory: 256m + networks: + - geo_internal + - geo_public + +volumes: + postgres_data: + driver: local + redis_data: + driver: local + +networks: + # 内部网络:服务间通信,不对外暴露 + geo_internal: + driver: bridge + internal: true + # 公共网络:frontend/backend 对外提供服务 + geo_public: + driver: bridge diff --git a/docker-compose.yml b/docker-compose.yml index c1c9735..70de3ff 100644 --- a/docker-compose.yml +++ b/docker-compose.yml @@ -18,6 +18,13 @@ services: interval: 5s timeout: 5s retries: 5 + deploy: + resources: + limits: + memory: 512m + cpus: '0.5' + reservations: + memory: 256m redis: image: redis:7-alpine @@ -32,6 +39,13 @@ services: interval: 5s timeout: 5s retries: 5 + deploy: + resources: + limits: + memory: 128m + cpus: '0.25' + reservations: + memory: 64m backend: build: ./backend @@ -49,6 +63,13 @@ services: redis: condition: service_healthy command: uvicorn app.main:app --host 0.0.0.0 --port 8000 --reload + deploy: + resources: + limits: + memory: 512m + cpus: '1.0' + reservations: + memory: 256m frontend: build: ./frontend @@ -64,6 +85,13 @@ services: depends_on: - backend command: npm run dev + deploy: + resources: + limits: + memory: 256m + cpus: '0.5' + reservations: + memory: 128m volumes: postgres_data: diff --git a/docs/后续待办事项.md b/docs/后续待办事项.md new file mode 100644 index 0000000..6d40599 --- /dev/null +++ b/docs/后续待办事项.md @@ -0,0 +1,116 @@ +# GEO 平台后续待办事项 + +## 优先级说明 +- 🔴 P0:阻断核心业务,必须立即处理 +- 🟠 P1:影响用户体验,本周内解决 +- 🟡 P2:功能增强,下一迭代安排 +- 🟢 P3:锦上添花,有空再做 + +--- + +## 🟠 P1 - 本周优先 + +### 1. 数据库迁移同步 +- [ ] 为 onboarding API 中可能缺少的字段创建 Alembic 迁移 +- [ ] 检查 brands/competitors 表结构是否完整匹配当前 API 需求 +- [ ] 运行 `alembic revision --autogenerate` 确认无漂移 + +### 2. 多 AI 平台真实对接验证 +- [ ] 验证文心一言平台适配器能否正常工作 +- [ ] 验证 Kimi(月之暗面)平台适配器能否正常工作(`MOONSHOT_API_KEY`) +- [ ] 验证通义千问平台适配器能否正常工作(`TONGYI_API_KEY`) +- [ ] 验证百度千帆平台适配器能否正常工作(`BAIDU_QIANFAN_API_KEY`) +- [ ] 验证豆包(字节跳动)平台适配器能否正常工作(`DOUBAO_API_KEY`) +- [ ] 配置各平台所需的 API Key 到 .env + +### 3. 定时调度器验证 +- [ ] 确认 APScheduler 定时任务是否正常触发 +- [ ] 验证每日/每周查询自动执行 +- [ ] 测试调度器重启后任务恢复 + +--- + +## 🟡 P2 - 下一迭代 + +### 4. Agent 架构完善 +- [ ] Legacy Worker 迁移到 Agent 框架 +- [ ] Pipeline YAML 编排引擎增强(条件分支、循环) +- [ ] Agent 监控 Dashboard(执行状态、耗时、成功率) +- [ ] 新增内容审核 Agent + +### 5. 内容生产完整链路 +- [ ] 完善 AI 内容生成质量(Prompt 优化) +- [ ] 实现内容审核流程(人工 + AI 双审) +- [ ] 多平台发布管理(知乎、百家号、头条等) +- [ ] 发布后效果归因(发布 → 引用率变化关联) +- [ ] 将 MockEmbedder 替换为 OpenAIEmbedder(生产环境) + +### 6. 平台规则审查 +- [ ] 建立各 AI 平台收录规则库 +- [ ] 内容合规性自动检查 +- [ ] SEO/GEO 最佳实践建议引擎 + +### 7. 数据分析增强 +- [ ] 品牌健康分趋势预测 +- [ ] 竞品动态预警(某竞品引用率突增) +- [ ] 行业基准对比 +- [ ] 自定义报告模板 + +--- + +## 🟢 P3 - 长期规划 + +### 8. 多租户与商业化 +- [ ] 订阅套餐计费实现(免费/Pro/Enterprise) +- [ ] 多组织/团队协作 +- [ ] 使用量配额与计费 +- [ ] 发票与支付集成 + +### 9. 性能与可扩展性 +- [ ] 引用检测任务队列(Celery/RQ)替代内存调度 +- [ ] 数据库读写分离 +- [ ] CDN 静态资源加速 +- [ ] WebSocket 实时通知 + +### 10. 运维与部署 +- [ ] K8s 部署配置 +- [ ] CI/CD 中 README 的 GitHub 用户名替换 +- [ ] Sentry 错误监控接入(ErrorBoundary 已预留) +- [ ] Grafana + Prometheus 监控大盘 +- [ ] 自动化备份策略 + +### 11. 用户体验 +- [ ] 邮件通知系统(监测报告推送) +- [ ] 移动端适配 +- [ ] 国际化(i18n) +- [ ] 用户引导优化(交互式教程) + +--- + +## 已完成项目 ✅ + +- [x] JWT 认证 + NextAuth 集成(Access Token + Refresh Token 滑动过期) +- [x] 品牌/竞品/查询 CRUD +- [x] 引用检测(百炼 qwen3-coder-plus 真实调用) +- [x] Onboarding 引导流程(前后端完整对接) +- [x] 知识库 RAG 对接(MockEmbedder + RAGService) +- [x] 内容管理 + RAG 知识库检索 + 版本管理 +- [x] 内容生产 Pipeline(生成→去AI化→GEO优化) +- [x] 多用户数据隔离修复 +- [x] Agent 并发控制(Semaphore) +- [x] LLM 令牌桶限流 +- [x] 前端 SWR + Zustand 状态管理 +- [x] 结构化日志 + RequestID + 性能监控 +- [x] 安全测试 + 前端测试体系 +- [x] GitHub Actions CI/CD +- [x] 健康检查 /health + /ready +- [x] 告警通知系统(告警列表 + 告警设置 + 未读计数) +- [x] 内容分发管理(平台规则 + 格式化 + 发布排期) +- [x] 监测优化 Analytics(发布记录 + 效果指标 + AI 洞察) +- [x] 客户管理(Organization 映射) +- [x] 生命周期项目管理(5 阶段 + 时间线) +- [x] 订阅管理(套餐/订阅/取消/历史) +- [x] 管理员后台(用户管理 + 套餐管理 + 系统统计) +- [x] 多 LLM Provider 支持(OpenAI 兼容 + DeepSeek) +- [x] Redis 缓存层(品牌列表 + 仪表盘 + 用户 Profile) +- [x] 安全响应头(X-Content-Type-Options / X-Frame-Options / X-XSS-Protection) diff --git a/docs/操作流程.md b/docs/操作流程.md new file mode 100644 index 0000000..86e32ad --- /dev/null +++ b/docs/操作流程.md @@ -0,0 +1,399 @@ +# GEO 平台操作流程 + +## 一、环境准备 + +### 1.1 系统要求 +- Node.js 18+ +- Python 3.11+ +- PostgreSQL 15 +- Redis 7 +- Docker & Docker Compose(推荐) + +### 1.2 环境变量配置 + +在项目根目录 `.env` 文件中配置以下关键项: + +| 变量名 | 示例值 | 说明 | +|--------|--------|------| +| `DATABASE_URL` | `postgresql+asyncpg://chiguyong@localhost:5432/geo_platform` | PostgreSQL 异步连接串 | +| `REDIS_URL` | `redis://localhost:6379/0` | Redis 连接串 | +| `JWT_SECRET` | `a3f8c2e1d7b9...` | JWT 签名密钥,**必须 ≥ 32 字符**,否则启动失败 | +| `JWT_EXPIRE_HOURS` | `24` | JWT Access Token 过期时间(小时) | +| `NEXT_PUBLIC_API_URL` | `http://localhost:8000` | 前端调用后端的 API 地址 | +| `CORS_ORIGINS` | `http://localhost:3000,http://localhost:3001` | 允许跨域的前端地址 | +| `ENABLE_LLM` | `true` | 启用真实 AI 引用检测(`false` 则使用 Mock) | +| `OPENAI_API_KEY` | `sk-sp-c76f198d...` | 百炼 DashScope API 密钥 | +| `OPENAI_BASE_URL` | `https://coding.dashscope.aliyuncs.com/v1` | 百炼 DashScope 端点(OpenAI 兼容格式) | +| `DEFAULT_LLM_PROVIDER` | `openai` | LLM 提供商(`openai` / `deepseek`) | +| `LLM_MODEL` | `qwen3-coder-plus` | 默认调用模型名 | +| `ZHIPU_API_KEY` | _(可选)_ | 智谱 AI API Key | +| `TONGYI_API_KEY` | _(可选)_ | 通义千问 API Key | +| `MOONSHOT_API_KEY` | _(可选)_ | Kimi(月之暗面)API Key | +| `BAIDU_QIANFAN_API_KEY` | _(可选)_ | 百度千帆 API Key | +| `DOUBAO_API_KEY` | _(可选)_ | 豆包(字节跳动)API Key | +| `API_RATE_LIMIT_RPM` | `10` | AI 平台 API 调用频率限制(每分钟请求数) | + +> **提示**:`JWT_SECRET` 启动时会强制校验长度,不足 32 字符将直接退出进程。可用以下命令生成: +> ```bash +> python3 -c "import secrets; print(secrets.token_hex(32))" +> ``` + +--- + +## 二、系统启动 + +### 2.1 Docker 一键启动(推荐) + +```bash +docker-compose up -d +``` + +启动后访问: +- 前端:http://localhost:3000 +- 后端 API:http://localhost:8000 +- API 文档(Swagger):http://localhost:8000/docs + +Docker Compose 编排四个服务: + +| 服务 | 镜像 | 端口 | 依赖 | +|------|------|------|------| +| `db` | postgres:15-alpine | 5432 | — | +| `redis` | redis:7-alpine | 6379 | — | +| `backend` | 自建(./backend) | 8000 | db + redis 健康检查 | +| `frontend` | 自建(./frontend) | 3000 | backend | + +数据持久化卷:`postgres_data`、`redis_data` + +### 2.2 本地开发启动 + +后端: +```bash +cd backend +pip install -r requirements.txt +alembic upgrade head +uvicorn app.main:app --reload --port 8000 +``` + +前端: +```bash +cd frontend +npm install +npm run dev +``` + +> **注意**:生产环境启动后端应使用 `--no-reload` 参数,避免文件监视导致的进程崩溃。 + +--- + +## 三、业务操作流程 + +### 3.1 用户注册与登录 +- 测试账号:`admin@fischer.com` / `Admin@123` +- 注册流程:`POST /api/v1/auth/register` → 邮箱验证 → 登录 +- 登录流程:`POST /api/v1/auth/login` → 获取 Access Token + Refresh Token + +### 3.2 Onboarding 引导(新用户首次登录) +1. 创建品牌(填写品牌名称、行业)→ `POST /api/v1/onboarding/brand` +2. 选择竞品(系统自动推荐 + 手动添加)→ `GET /api/v1/onboarding/competitor-recommendations` +3. 查看品牌健康报告(AI 分析品牌在各平台的表现)→ `GET /api/v1/onboarding/health-report/{brand_id}` +4. 获取行动建议(基于数据的优化建议)→ `GET /api/v1/onboarding/action-suggestions/{brand_id}` +5. 完成引导 → `POST /api/v1/onboarding/complete/{brand_id}` → 进入仪表盘 + +### 3.3 品牌管理 +- 创建/编辑/删除品牌(`/api/v1/brands/`) +- 管理品牌下的竞品(`/api/v1/brands/{brand_id}/competitors/`) +- 查看品牌评分(`/api/v1/brands/{brand_id}/score/`、`/api/v1/brands/{brand_id}/score/history/`) +- 配置品牌别名(用于多名称匹配) + +### 3.4 查询管理 +- 创建监测查询词(如"XXX品牌怎么样")→ `POST /api/v1/queries/` +- 查看查询列表 → `GET /api/v1/queries/` +- 立即执行检测 → `POST /api/v1/queries/{query_id}/run-now` +- 设置查询频率(即时/每日/每周),由 APScheduler 定时调度自动执行 + +### 3.5 引用检测 +- 系统自动调用 AI 平台检测品牌引用 +- 使用百炼 `qwen3-coder-plus` 模型分析引用情况 +- 记录:是否被引用、引用位置、情感倾向、置信度 +- 查看引用列表 → `GET /api/v1/citations/` +- 查看引用统计 → `GET /api/v1/citations/stats` + +### 3.6 数据分析与报告 +- 仪表盘统计:`GET /api/v1/dashboard/stats` + - 综合评分(V2)、健康等级、较昨日变化 + - 五维度评分详情(提及率、推荐排名、情感评分、引用质量、竞争地位) + - 各平台评分对比(含竞品) +- 报告导出:`GET /api/v1/reports/export/csv`、`GET /api/v1/reports/export/pdf` +- 引用详情查看与筛选 + +### 3.7 内容管理 +- 内容 CRUD:`/api/v1/contents/`(列表、创建、查看、更新、删除、发布) +- AI 内容生成:`POST /api/v1/content/generate` + - 流程:内容生成 → 去AI化 → GEO优化(三阶段 Pipeline) + - 支持知识库 RAG 上下文增强 +- AI 选题生成:`POST /api/v1/content/generate-topics` +- 品牌知识库条目:`/api/v1/contents/knowledge/`(CRUD) + +### 3.8 知识库 +- 创建/列出/查看/删除知识库 → `/api/v1/knowledge/bases` +- 上传文档到知识库 → `POST /api/v1/knowledge/bases/{kb_id}/documents` + - 支持 text / markdown / url 三种来源 + - 自动分块 + 向量化(MockEmbedder / OpenAIEmbedder) +- 文档管理(列出/删除)→ `/api/v1/knowledge/bases/{kb_id}/documents` +- 查看文档分块 → `GET /api/v1/knowledge/bases/{kb_id}/documents/{doc_id}/chunks` +- RAG 检索 → `POST /api/v1/knowledge/search` + +### 3.9 内容分发 +- 获取支持平台列表 → `GET /api/v1/distribution/platforms` +- 内容合规校验 → `POST /api/v1/distribution/validate` +- 生成发布策略 → `POST /api/v1/distribution/strategy` +- 内容格式化 → `POST /api/v1/distribution/format` +- 创建发布排期 → `POST /api/v1/distribution/schedule` + +### 3.10 监测优化(Analytics) +- 记录发布 → `POST /api/v1/analytics/publish` +- 更新效果指标 → `PUT /api/v1/analytics/metrics/{publish_id}` +- 全局概览 → `GET /api/v1/analytics/overview` +- 单内容详情 → `GET /api/v1/analytics/content/{publish_id}` +- 排行榜 → `GET /api/v1/analytics/top` +- 洞察列表 → `GET /api/v1/analytics/insights` +- AI 生成洞察 → `POST /api/v1/analytics/insights/generate` +- 标记洞察已应用 → `POST /api/v1/analytics/insights/{insight_id}/apply` + +### 3.11 告警通知 +- 查看告警列表 → `GET /api/v1/alerts/` +- 未读告警数 → `GET /api/v1/alerts/unread-count` +- 全部标为已读 → `PATCH /api/v1/alerts/read-all` +- 单条标为已读 → `PATCH /api/v1/alerts/{alert_id}/read` +- 告警设置管理 → `/api/v1/alerts/settings` + +### 3.12 客户管理 +- 客户(组织)CRUD → `/api/v1/clients/` +- 查看客户下项目 → `GET /api/v1/clients/{client_id}/projects` + +### 3.13 生命周期项目管理 +- 项目列表 → `GET /api/v1/lifecycle/projects/` +- 项目统计 → `GET /api/v1/lifecycle/projects/stats` +- 快速创建项目 → `POST /api/v1/lifecycle/projects/quick-start` +- 项目时间线 → `GET /api/v1/lifecycle/projects/{project_id}/timeline` +- 阶段管理 → `/api/v1/lifecycle/projects/{project_id}/stages` + +### 3.14 Agent 管理 +- 列出所有 Agent → `GET /api/v1/agents/` +- Agent 详情/配置 → `/api/v1/agents/{agent_name}` +- 任务管理 → `/api/v1/agents/tasks/`(创建、查询状态、取消、日志) + +### 3.15 订阅管理 +- 查看套餐 → `GET /api/v1/subscriptions/plans` +- 当前订阅 → `GET /api/v1/subscriptions/current` +- 订阅 → `POST /api/v1/subscriptions/subscribe` +- 取消订阅 → `POST /api/v1/subscriptions/cancel` +- 订阅历史 → `GET /api/v1/subscriptions/history` + +--- + +## 四、API 接口总览 + +### 认证 `/api/v1/auth` +| 方法 | 路径 | 说明 | +|------|------|------| +| POST | `/register` | 用户注册 | +| POST | `/login` | 用户登录(返回 Access + Refresh Token) | +| POST | `/refresh` | 刷新 Token(滑动过期) | +| GET | `/me` | 获取当前用户信息 | +| POST | `/forgot-password` | 忘记密码(发送重置链接) | +| POST | `/reset-password` | 重置密码 | +| POST | `/verify-email` | 验证邮箱 | +| POST | `/resend-verification` | 重发验证码 | +| PUT | `/change-password` | 修改密码 | +| PUT | `/profile` | 更新个人资料 | + +### 品牌管理 `/api/v1/brands` +| 方法 | 路径 | 说明 | +|------|------|------| +| GET | `/` | 获取当前用户所有品牌 | +| POST | `/` | 创建品牌 | +| GET | `/{brand_id}/` | 获取品牌详情 | +| PUT | `/{brand_id}/` | 更新品牌 | +| DELETE | `/{brand_id}/` | 删除品牌 | +| GET | `/{brand_id}/score/` | 获取品牌评分 | +| GET | `/{brand_id}/score/history/` | 获取评分历史 | +| * | `/{brand_id}/competitors/...` | 竞品管理(子路由) | + +### 查询词 `/api/v1/queries` +| 方法 | 路径 | 说明 | +|------|------|------| +| GET | `/` | 查询词列表(分页) | +| POST | `/` | 创建查询词 | +| GET | `/{query_id}` | 查询词详情 | +| PUT | `/{query_id}` | 更新查询词 | +| DELETE | `/{query_id}` | 删除查询词 | +| POST | `/{query_id}/run-now` | 立即执行检测 | + +### 引用数据 `/api/v1/citations` +| 方法 | 路径 | 说明 | +|------|------|------| +| GET | `/` | 引用列表(支持按 query_id/platform/日期筛选) | +| GET | `/stats` | 引用统计 | + +### 报告 `/api/v1/reports` +| 方法 | 路径 | 说明 | +|------|------|------| +| GET | `/export/csv` | 导出 CSV 报告 | +| GET | `/export/pdf` | 导出 PDF 报告 | + +### Onboarding `/api/v1/onboarding` +| 方法 | 路径 | 说明 | +|------|------|------| +| GET | `/status` | 检查 Onboarding 状态 | +| POST | `/brand` | 创建品牌(简化版) | +| GET | `/competitor-recommendations` | 竞品推荐 | +| GET | `/health-report/{brand_id}` | 品牌健康报告 | +| GET | `/action-suggestions/{brand_id}` | 行动建议 | +| POST | `/complete/{brand_id}` | 完成 Onboarding | + +### 内容生产 `/api/v1/content` +| 方法 | 路径 | 说明 | +|------|------|------| +| POST | `/generate` | 一键生成内容(Pipeline:生成→去AI化→GEO优化) | +| POST | `/generate-topics` | AI 选题生成 | + +### 内容管理 `/api/v1/contents` +| 方法 | 路径 | 说明 | +|------|------|------| +| GET | `/` | 内容列表(分页、筛选) | +| POST | `/` | 创建内容 | +| GET | `/{content_id}` | 内容详情 | +| PUT | `/{content_id}` | 更新内容 | +| DELETE | `/{content_id}` | 删除内容 | +| POST | `/{content_id}/publish` | 发布内容 | +| GET | `/knowledge/` | 品牌知识库条目列表 | +| POST | `/knowledge/` | 创建品牌知识库条目 | +| PUT | `/knowledge/{knowledge_id}` | 更新品牌知识库条目 | +| DELETE | `/knowledge/{knowledge_id}` | 删除品牌知识库条目 | + +### 知识库 `/api/v1/knowledge` +| 方法 | 路径 | 说明 | +|------|------|------| +| POST | `/bases` | 创建知识库 | +| GET | `/bases` | 列出知识库 | +| GET | `/bases/{kb_id}` | 知识库详情 | +| DELETE | `/bases/{kb_id}` | 删除知识库 | +| POST | `/bases/{kb_id}/documents` | 上传文档 | +| GET | `/bases/{kb_id}/documents` | 列出文档 | +| DELETE | `/bases/{kb_id}/documents/{doc_id}` | 删除文档 | +| GET | `/bases/{kb_id}/documents/{doc_id}/chunks` | 查看文档分块 | +| POST | `/search` | RAG 语义检索 | + +### 仪表盘 `/api/v1/dashboard` +| 方法 | 路径 | 说明 | +|------|------|------| +| GET | `/stats` | 仪表盘统计(综合评分、维度、平台、竞品对比) | + +### 内容分发 `/api/v1/distribution` +| 方法 | 路径 | 说明 | +|------|------|------| +| GET | `/platforms` | 支持平台列表 | +| POST | `/validate` | 内容合规校验 | +| POST | `/strategy` | 生成发布策略 | +| POST | `/format` | 内容格式化 | +| POST | `/schedule` | 创建发布排期 | + +### 监测优化 `/api/v1/analytics` +| 方法 | 路径 | 说明 | +|------|------|------| +| POST | `/publish` | 记录内容发布 | +| PUT | `/metrics/{publish_id}` | 更新效果指标 | +| GET | `/overview` | 全局效果概览 | +| GET | `/content/{publish_id}` | 单内容详细表现 | +| GET | `/top` | 表现最好内容排行 | +| GET | `/insights` | 洞察列表 | +| POST | `/insights/generate` | AI 生成洞察 | +| POST | `/insights/{insight_id}/apply` | 标记洞察已应用 | + +### 告警通知 `/api/v1/alerts` +| 方法 | 路径 | 说明 | +|------|------|------| +| GET | `/` | 告警列表(支持类型/严重程度/已读状态/品牌筛选) | +| GET | `/unread-count` | 未读告警数 | +| PATCH | `/read-all` | 全部标为已读 | +| PATCH | `/{alert_id}/read` | 单条标为已读 | +| GET | `/settings` | 告警设置列表 | +| PUT | `/settings` | 批量更新告警设置 | +| PUT | `/settings/{setting_id}` | 更新单条告警设置 | + +### 客户管理 `/api/v1/clients` +| 方法 | 路径 | 说明 | +|------|------|------| +| GET | `/` | 客户列表 | +| POST | `/` | 创建客户 | +| GET | `/{client_id}` | 客户详情 | +| PUT | `/{client_id}` | 更新客户 | +| DELETE | `/{client_id}` | 删除客户 | +| GET | `/{client_id}/projects` | 客户下的项目列表 | + +### 生命周期 `/api/v1/lifecycle` +| 方法 | 路径 | 说明 | +|------|------|------| +| GET | `/projects/` | 项目列表 | +| GET | `/projects/stats` | 项目统计 | +| POST | `/projects/quick-start` | 快速创建项目 | +| GET | `/projects/{project_id}/timeline` | 项目时间线 | +| GET | `/projects/{project_id}/stages` | 项目阶段列表 | +| PUT | `/projects/{project_id}/stages/{stage_number}` | 更新阶段状态 | + +### Agent 管理 `/api/v1/agents` +| 方法 | 路径 | 说明 | +|------|------|------| +| GET | `/` | 列出所有 Agent | +| GET | `/{agent_name}` | Agent 详情 | +| GET | `/{agent_name}/config` | Agent 配置 | +| PUT | `/{agent_name}/config` | 更新 Agent 配置 | +| GET | `/tasks/` | 任务列表 | +| POST | `/tasks/` | 创建任务(分发给 Agent) | +| GET | `/tasks/{task_id}` | 任务状态 | +| POST | `/tasks/{task_id}/cancel` | 取消任务 | +| GET | `/tasks/{task_id}/logs` | 任务日志 | + +### 订阅 `/api/v1/subscriptions` +| 方法 | 路径 | 说明 | +|------|------|------| +| GET | `/plans` | 套餐列表 | +| GET | `/current` | 当前订阅 | +| POST | `/subscribe` | 订阅套餐 | +| POST | `/cancel` | 取消订阅 | +| GET | `/history` | 订阅历史 | + +### 管理员 `/api/v1/admin`(需管理员权限) +| 方法 | 路径 | 说明 | +|------|------|------| +| GET | `/stats` | 系统统计 | +| GET | `/users` | 用户列表(分页、搜索) | +| GET | `/users/{user_id}` | 用户详情 | +| POST | `/users/{user_id}/toggle-active` | 启用/禁用用户 | +| PUT | `/users/{user_id}/update-plan` | 更新用户套餐 | + +--- + +## 五、监控与运维 + +### 5.1 健康检查 +- `GET /health` — 基础存活检查(Liveness),不依赖外部服务 +- `GET /ready` — 依赖就绪检查(Readiness),检测 DB + Redis 连通性 + - 返回 `200` + `{"status": "ready"}` 表示全部就绪 + - 返回 `503` + `{"status": "not_ready"}` 表示依赖异常 + +### 5.2 日志 +- 结构化 JSON 日志(`setup_logging()` 在启动时初始化) +- 每个请求附带 `X-Request-ID`(由 `RequestIdMiddleware` 注入) +- 慢请求(>1s)自动告警 +- 中间件执行链:RequestId → Metrics → RateLimit → RequestLogging → CORS → SecurityHeaders + +### 5.3 安全特性 +- JWT 认证 + 用户级数据隔离(所有查询均按 `current_user.id` 过滤) +- 用户+IP 组合限流(`RateLimitMiddleware`) +- Agent 并发控制(Semaphore) +- LLM 令牌桶限流(30 RPM) +- 安全响应头:`X-Content-Type-Options: nosniff`、`X-Frame-Options: DENY`、`X-XSS-Protection: 1; mode=block` +- 统一异常处理(不泄漏内部错误详情) +- 密码重置/邮箱验证等敏感操作防止用户枚举 diff --git a/frontend/.dockerignore b/frontend/.dockerignore new file mode 100644 index 0000000..ecba89a --- /dev/null +++ b/frontend/.dockerignore @@ -0,0 +1,11 @@ +node_modules/ +.next/ +.env.local +.env.* +*.log +.git/ +.gitignore +README.md +test-results/ +playwright-report/ +e2e/ diff --git a/frontend/Dockerfile b/frontend/Dockerfile index e1c7a6c..85c054c 100644 --- a/frontend/Dockerfile +++ b/frontend/Dockerfile @@ -1,14 +1,45 @@ -FROM node:20-alpine +# ============================================================ +# Stage 1: Builder — 构建 Next.js 生产产物 +# ============================================================ +FROM node:20-alpine AS builder WORKDIR /app -# 安装依赖 +# 安装依赖(利用缓存层) COPY package.json package-lock.json ./ RUN npm ci -# 复制应用代码 +# 复制源码并构建 COPY . . +RUN npm run build + +# ============================================================ +# Stage 2: Runner — 只保留运行时必要文件 +# ============================================================ +FROM node:20-alpine AS runner + +WORKDIR /app + +ENV NODE_ENV=production + +# 创建非 root 用户运行应用 +RUN addgroup --system --gid 1001 nodejs \ + && adduser --system --uid 1001 nextjs + +# 复制 standalone 构建产物 +COPY --from=builder --chown=nextjs:nodejs /app/.next/standalone ./ +COPY --from=builder --chown=nextjs:nodejs /app/.next/static ./.next/static +COPY --from=builder --chown=nextjs:nodejs /app/public ./public + +USER nextjs EXPOSE 3000 -CMD ["npm", "run", "dev"] +ENV PORT=3000 +ENV HOSTNAME="0.0.0.0" + +# 健康检查 +HEALTHCHECK --interval=30s --timeout=10s --start-period=20s --retries=3 \ + CMD wget -qO- http://localhost:3000/ || exit 1 + +CMD ["node", "server.js"] diff --git a/frontend/__tests__/hooks/use-api.test.ts b/frontend/__tests__/hooks/use-api.test.ts new file mode 100644 index 0000000..e0a665f --- /dev/null +++ b/frontend/__tests__/hooks/use-api.test.ts @@ -0,0 +1,314 @@ +/** + * useApi / usePaginatedApi / useApiMutation Hooks 单元测试 + * + * 覆盖:加载/成功/错误状态、分页参数、mutation trigger + */ + +import { describe, it, expect, vi, beforeEach } from "vitest"; +import { renderHook, act, waitFor } from "@testing-library/react"; +import useSWR from "swr"; +import { + useApi, + usePaginatedApi, + useApiMutation, + swrFetcher, +} from "@/lib/hooks/use-api"; +import type { PaginatedResponse } from "@/lib/hooks/use-api"; + +// ── Mock fetchWithAuth ──────────────────────────────────────────────────────── + +vi.mock("@/lib/api/client", () => ({ + fetchWithAuth: vi.fn(), +})); + +import { fetchWithAuth } from "@/lib/api/client"; +const mockFetchWithAuth = vi.mocked(fetchWithAuth); + +// ── swrFetcher ──────────────────────────────────────────────────────────────── + +describe("swrFetcher", () => { + it("应调用 fetchWithAuth 并返回结果", async () => { + mockFetchWithAuth.mockResolvedValueOnce({ data: "test" }); + + const result = await swrFetcher("/api/test"); + expect(result).toEqual({ data: "test" }); + expect(mockFetchWithAuth).toHaveBeenCalledWith("/api/test"); + }); +}); + +// ── useApi ──────────────────────────────────────────────────────────────────── + +describe("useApi", () => { + beforeEach(() => { + vi.clearAllMocks(); + // 清除 SWR 缓存,避免测试间数据残留 + useSWR.clearCache?.(); + }); + + it("url 为 null 时应暂停请求", () => { + const { result } = renderHook(() => useApi(null)); + + expect(result.current.isLoading).toBe(false); + expect(result.current.data).toBeUndefined(); + expect(mockFetchWithAuth).not.toHaveBeenCalled(); + }); + + it("请求成功应返回数据", async () => { + const mockData = { items: [{ id: "1", name: "品牌" }], total: 1 }; + mockFetchWithAuth.mockResolvedValueOnce(mockData); + + const { result } = renderHook(() => useApi("/api/brands-success")); + + await waitFor(() => { + expect(result.current.data).toEqual(mockData); + expect(result.current.error).toBeUndefined(); + expect(result.current.isLoading).toBe(false); + }); + }); + + it("请求失败应返回错误", async () => { + mockFetchWithAuth.mockRejectedValueOnce(new Error("网络错误")); + + const { result } = renderHook(() => useApi("/api/brands-error")); + + await waitFor(() => { + expect(result.current.error).toBeInstanceOf(Error); + expect(result.current.error?.message).toBe("网络错误"); + }); + }); + + it("refresh 应触发重新获取", async () => { + mockFetchWithAuth.mockResolvedValue({ items: [] }); + + const { result } = renderHook(() => useApi("/api/brands-refresh")); + + await waitFor(() => { + expect(result.current.isLoading).toBe(false); + }); + + const callCount = mockFetchWithAuth.mock.calls.length; + act(() => { + result.current.refresh(); + }); + + await waitFor(() => { + expect(mockFetchWithAuth.mock.calls.length).toBeGreaterThan(callCount); + }); + }); +}); + +// ── usePaginatedApi ─────────────────────────────────────────────────────────── + +describe("usePaginatedApi", () => { + beforeEach(() => { + vi.clearAllMocks(); + useSWR.clearCache?.(); + }); + + it("应正确构造分页 URL", async () => { + const mockResponse: PaginatedResponse<{ id: string }> = { + items: [{ id: "1" }], + total: 10, + }; + mockFetchWithAuth.mockResolvedValueOnce(mockResponse); + + renderHook(() => + usePaginatedApi("/api/brands-page1", { page: 1, pageSize: 10 }) + ); + + await waitFor(() => { + // page=1, pageSize=10 → offset=0, limit=10 + expect(mockFetchWithAuth).toHaveBeenCalledWith( + "/api/brands-page1?limit=10&offset=0" + ); + }); + }); + + it("第2页应正确计算 offset", async () => { + const mockResponse: PaginatedResponse<{ id: string }> = { + items: [], + total: 20, + }; + mockFetchWithAuth.mockResolvedValueOnce(mockResponse); + + renderHook(() => + usePaginatedApi("/api/brands-page2", { page: 2, pageSize: 5 }) + ); + + await waitFor(() => { + // page=2, pageSize=5 → offset=5, limit=5 + expect(mockFetchWithAuth).toHaveBeenCalledWith( + "/api/brands-page2?limit=5&offset=5" + ); + }); + }); + + it("baseUrl 为 null 时应暂停请求", () => { + const { result } = renderHook(() => + usePaginatedApi(null, { page: 1, pageSize: 10 }) + ); + + expect(result.current.isLoading).toBe(false); + expect(result.current.data).toBeUndefined(); + }); + + it("应返回 total 和分页信息", async () => { + const mockResponse: PaginatedResponse<{ id: string }> = { + items: [{ id: "1" }, { id: "2" }], + total: 25, + }; + mockFetchWithAuth.mockResolvedValueOnce(mockResponse); + + const { result } = renderHook(() => + usePaginatedApi("/api/brands-total", { page: 1, pageSize: 10 }) + ); + + await waitFor(() => { + expect(result.current.data).toEqual([{ id: "1" }, { id: "2" }]); + expect(result.current.total).toBe(25); + expect(result.current.page).toBe(1); + expect(result.current.pageSize).toBe(10); + }); + }); + + it("setPage 应更新页码", async () => { + mockFetchWithAuth.mockResolvedValue({ + items: [], + total: 30, + }); + + const { result } = renderHook(() => + usePaginatedApi("/api/brands-setpage", { page: 1, pageSize: 10 }) + ); + + await waitFor(() => { + expect(result.current.isLoading).toBe(false); + }); + + act(() => { + result.current.setPage(3); + }); + + await waitFor(() => { + expect(result.current.page).toBe(3); + }); + }); + + it("数据未加载时 total 应为 0", () => { + // 用 null URL 确保无请求发出,total 为 0 + const { result } = renderHook(() => + usePaginatedApi(null, { page: 1, pageSize: 10 }) + ); + + expect(result.current.total).toBe(0); + }); +}); + +// ── useApiMutation ──────────────────────────────────────────────────────────── + +describe("useApiMutation", () => { + beforeEach(() => { + vi.clearAllMocks(); + useSWR.clearCache?.(); + }); + + it("trigger 成功应返回数据", async () => { + const mockResult = { id: "1", name: "新品牌" }; + mockFetchWithAuth.mockResolvedValueOnce(mockResult); + + const { result } = renderHook(() => + useApiMutation("/api/brands", "POST") + ); + + let response: unknown; + await act(async () => { + response = await result.current.trigger({ name: "新品牌" }); + }); + + expect(response).toEqual(mockResult); + expect(result.current.isMutating).toBe(false); + expect(result.current.error).toBeUndefined(); + }); + + it("trigger 失败应返回 null 并设置 error", async () => { + mockFetchWithAuth.mockRejectedValueOnce(new Error("服务器错误")); + + const { result } = renderHook(() => + useApiMutation("/api/brands", "POST") + ); + + let response: unknown; + await act(async () => { + response = await result.current.trigger({ name: "失败" }); + }); + + expect(response).toBeNull(); + expect(result.current.error).toBeInstanceOf(Error); + expect(result.current.error?.message).toBe("服务器错误"); + expect(result.current.isMutating).toBe(false); + }); + + it("trigger 过程中 isMutating 应为 true", async () => { + let resolveMutation: (value: unknown) => void; + mockFetchWithAuth.mockReturnValueOnce( + new Promise((resolve) => { + resolveMutation = resolve; + }) + ); + + const { result } = renderHook(() => + useApiMutation("/api/brands", "PUT") + ); + + act(() => { + result.current.trigger({ name: "更新" }); + }); + + await waitFor(() => { + expect(result.current.isMutating).toBe(true); + }); + + resolveMutation!({ id: "1" }); + + await waitFor(() => { + expect(result.current.isMutating).toBe(false); + }); + }); + + it("reset 应清除错误状态", async () => { + mockFetchWithAuth.mockRejectedValueOnce(new Error("出错了")); + + const { result } = renderHook(() => + useApiMutation("/api/brands", "DELETE") + ); + + await act(async () => { + await result.current.trigger(); + }); + + expect(result.current.error).toBeDefined(); + + act(() => { + result.current.reset(); + }); + + expect(result.current.error).toBeUndefined(); + }); + + it("应正确传递 method 和 body", async () => { + mockFetchWithAuth.mockResolvedValueOnce({ success: true }); + + const { result } = renderHook(() => + useApiMutation("/api/brands/1", "PUT") + ); + + await act(async () => { + await result.current.trigger({ name: "更新品牌" }); + }); + + expect(mockFetchWithAuth).toHaveBeenCalledWith("/api/brands/1", { + method: "PUT", + body: JSON.stringify({ name: "更新品牌" }), + }); + }); +}); diff --git a/frontend/__tests__/lib/api/client.test.ts b/frontend/__tests__/lib/api/client.test.ts new file mode 100644 index 0000000..55d8fc0 --- /dev/null +++ b/frontend/__tests__/lib/api/client.test.ts @@ -0,0 +1,239 @@ +/** + * API Client (fetchWithAuth) 单元测试 + * + * 覆盖:带 token 请求、错误处理(401/500/204) + */ + +import { describe, it, expect, vi, beforeEach, afterEach } from "vitest"; +import { fetchWithAuth, API_BASE, getApiUrl } from "@/lib/api/client"; + +// ── Mock next-auth/react ────────────────────────────────────────────────────── + +vi.mock("next-auth/react", () => ({ + getSession: vi.fn(() => + Promise.resolve({ accessToken: "session-token-123" }) + ), +})); + +import { getSession } from "next-auth/react"; +const mockGetSession = vi.mocked(getSession); + +// ── Mock global fetch ───────────────────────────────────────────────────────── + +const mockFetch = vi.fn(); +const originalFetch = global.fetch; + +beforeEach(() => { + global.fetch = mockFetch; + vi.clearAllMocks(); +}); + +afterEach(() => { + global.fetch = originalFetch; +}); + +// ── 辅助 ────────────────────────────────────────────────────────────────────── + +function mockFetchResponse(options: { + ok: boolean; + status: number; + json?: () => Promise; +}) { + return { + ok: options.ok, + status: options.status, + json: options.json ?? (() => Promise.resolve({})), + }; +} + +// ── getApiUrl ───────────────────────────────────────────────────────────────── + +describe("getApiUrl", () => { + it("应拼接 API_BASE 和路径", () => { + const url = getApiUrl("/api/v1/brands"); + expect(url).toBe(`${API_BASE}/api/v1/brands`); + }); +}); + +// ── fetchWithAuth ───────────────────────────────────────────────────────────── + +describe("fetchWithAuth", () => { + it("显式传入 token 时应添加 Authorization 头", async () => { + mockFetch.mockResolvedValueOnce( + mockFetchResponse({ ok: true, status: 200, json: () => Promise.resolve({ data: "ok" }) }) + ); + + await fetchWithAuth("/api/test", {}, "my-secret-token"); + + const [url, options] = mockFetch.mock.calls[0]; + expect(url).toBe(`${API_BASE}/api/test`); + expect(options.headers.Authorization).toBe("Bearer my-secret-token"); + expect(options.headers["Content-Type"]).toBe("application/json"); + }); + + it("未传入 token 且在浏览器环境下应从 session 获取", async () => { + // 模拟浏览器环境 + const originalWindow = global.window; + Object.defineProperty(global, "window", { + value: { location: {} }, + writable: true, + }); + + mockGetSession.mockResolvedValueOnce({ + accessToken: "session-token-123", + }); + + mockFetch.mockResolvedValueOnce( + mockFetchResponse({ ok: true, status: 200, json: () => Promise.resolve({ data: "ok" }) }) + ); + + await fetchWithAuth("/api/test", {}); + + const options = mockFetch.mock.calls[0][1]; + expect(options.headers.Authorization).toBe("Bearer session-token-123"); + + Object.defineProperty(global, "window", { + value: originalWindow, + writable: true, + }); + }); + + it("session 无 accessToken 时不应添加 Authorization 头", async () => { + // jsdom 环境下 typeof window !== "undefined",所以会走 session 路径 + mockGetSession.mockResolvedValueOnce({}); // session 没有 accessToken + + mockFetch.mockResolvedValueOnce( + mockFetchResponse({ ok: true, status: 200, json: () => Promise.resolve({ data: "ok" }) }) + ); + + await fetchWithAuth("/api/test", {}); + + const options = mockFetch.mock.calls[0][1]; + expect(options.headers.Authorization).toBeUndefined(); + }); + + it("session 获取失败时不应添加 Authorization 头", async () => { + mockGetSession.mockRejectedValueOnce(new Error("session error")); + + mockFetch.mockResolvedValueOnce( + mockFetchResponse({ ok: true, status: 200, json: () => Promise.resolve({ data: "ok" }) }) + ); + + await fetchWithAuth("/api/test", {}); + + const options = mockFetch.mock.calls[0][1]; + expect(options.headers.Authorization).toBeUndefined(); + }); + + it("应合并自定义 headers", async () => { + mockFetch.mockResolvedValueOnce( + mockFetchResponse({ ok: true, status: 200, json: () => Promise.resolve({}) }) + ); + + await fetchWithAuth("/api/test", { + headers: { "X-Custom": "value" }, + }, "token"); + + const options = mockFetch.mock.calls[0][1]; + expect(options.headers["Content-Type"]).toBe("application/json"); + expect(options.headers["X-Custom"]).toBe("value"); + expect(options.headers.Authorization).toBe("Bearer token"); + }); + + // ── 401 错误 ─────────────────────────────────────────────────────────── + + it("401 应抛出'登录已过期'错误", async () => { + mockFetch.mockResolvedValueOnce( + mockFetchResponse({ ok: false, status: 401 }) + ); + + await expect(fetchWithAuth("/api/test", {}, "token")).rejects.toThrow( + "登录已过期,请重新登录" + ); + }); + + // ── 500 错误 ─────────────────────────────────────────────────────────── + + it("500 错误应抛出包含状态码的错误", async () => { + mockFetch.mockResolvedValueOnce( + mockFetchResponse({ + ok: false, + status: 500, + json: () => Promise.resolve({ detail: "内部服务器错误" }), + }) + ); + + await expect(fetchWithAuth("/api/test", {}, "token")).rejects.toThrow( + "内部服务器错误" + ); + }); + + it("500 错误且 JSON 解析失败应使用默认错误信息", async () => { + mockFetch.mockResolvedValueOnce( + mockFetchResponse({ + ok: false, + status: 500, + json: () => Promise.reject(new Error("invalid json")), + }) + ); + + await expect(fetchWithAuth("/api/test", {}, "token")).rejects.toThrow( + "请求失败 (HTTP 500)" + ); + }); + + it("其他错误状态码应正确抛出", async () => { + mockFetch.mockResolvedValueOnce( + mockFetchResponse({ + ok: false, + status: 422, + json: () => Promise.resolve({ detail: "参数校验失败" }), + }) + ); + + await expect(fetchWithAuth("/api/test", {}, "token")).rejects.toThrow( + "参数校验失败" + ); + }); + + // ── 成功响应 ──────────────────────────────────────────────────────────── + + it("200 应返回 JSON 数据", async () => { + const mockData = { id: "1", name: "品牌" }; + mockFetch.mockResolvedValueOnce( + mockFetchResponse({ + ok: true, + status: 200, + json: () => Promise.resolve(mockData), + }) + ); + + const result = await fetchWithAuth("/api/test", {}, "token"); + expect(result).toEqual(mockData); + }); + + it("204 应返回 null", async () => { + mockFetch.mockResolvedValueOnce( + mockFetchResponse({ ok: true, status: 204 }) + ); + + const result = await fetchWithAuth("/api/test", {}, "token"); + expect(result).toBeNull(); + }); + + // ── 错误响应的 message 字段 ──────────────────────────────────────────── + + it("错误响应包含 message 字段时应优先使用", async () => { + mockFetch.mockResolvedValueOnce( + mockFetchResponse({ + ok: false, + status: 400, + json: () => Promise.resolve({ message: "品牌名称已存在" }), + }) + ); + + await expect(fetchWithAuth("/api/test", {}, "token")).rejects.toThrow( + "品牌名称已存在" + ); + }); +}); diff --git a/frontend/__tests__/stores/brand-store.test.ts b/frontend/__tests__/stores/brand-store.test.ts new file mode 100644 index 0000000..f76d226 --- /dev/null +++ b/frontend/__tests__/stores/brand-store.test.ts @@ -0,0 +1,440 @@ +/** + * Brand Store 单元测试 + * + * 覆盖:selectBrand / clearSelection / optimisticCreate / optimisticUpdate + */ + +import { describe, it, expect, vi, beforeEach } from "vitest"; +import { useBrandStore } from "@/lib/stores/brand-store"; +import type { BrandListItem } from "@/types/brand"; + +// ── Mock 依赖 ──────────────────────────────────────────────────────────────── + +vi.mock("@/lib/api/client", () => ({ + fetchWithAuth: vi.fn(), +})); + +vi.mock("@/lib/api/brands", () => ({ + brandsApi: { + create: vi.fn(), + update: vi.fn(), + delete: vi.fn(), + }, +})); + +vi.mock("@/lib/stores/notification-store", () => ({ + useNotificationStore: { + getState: () => ({ + addNotification: vi.fn(), + }), + }, +})); + +// ── 测试数据 ───────────────────────────────────────────────────────────────── + +const MOCK_BRAND: BrandListItem = { + id: "brand-1", + name: "测试品牌", + aliases: ["测试"], + platforms: ["bing"], + frequency: "weekly", + status: "active", + score: 85, + last_queried_at: "2024-01-01T00:00:00Z", + next_query_at: "2024-01-08T00:00:00Z", + created_at: "2024-01-01T00:00:00Z", +}; + +const MOCK_BRAND_2: BrandListItem = { + id: "brand-2", + name: "另一个品牌", + aliases: [], + platforms: ["google"], + frequency: "daily", + status: "pending", + score: null, + last_queried_at: null, + next_query_at: null, + created_at: "2024-01-02T00:00:00Z", +}; + +// ── 测试 ────────────────────────────────────────────────────────────────────── + +describe("useBrandStore", () => { + beforeEach(() => { + // 重置 store 到初始状态 + useBrandStore.setState({ + selectedBrandId: null, + selectedBrandName: null, + localBrands: [], + optimisticAction: null, + }); + vi.clearAllMocks(); + }); + + // ── selectBrand / clearSelection ──────────────────────────────────────── + + describe("selectBrand / clearSelection", () => { + it("应正确选中品牌", () => { + const { selectBrand } = useBrandStore.getState(); + selectBrand("brand-1", "测试品牌"); + + const state = useBrandStore.getState(); + expect(state.selectedBrandId).toBe("brand-1"); + expect(state.selectedBrandName).toBe("测试品牌"); + }); + + it("选中品牌时 name 参数可选", () => { + const { selectBrand } = useBrandStore.getState(); + selectBrand("brand-2"); + + const state = useBrandStore.getState(); + expect(state.selectedBrandId).toBe("brand-2"); + expect(state.selectedBrandName).toBeNull(); + }); + + it("应正确清除选中品牌", () => { + useBrandStore.setState({ + selectedBrandId: "brand-1", + selectedBrandName: "测试品牌", + }); + + const { clearSelection } = useBrandStore.getState(); + clearSelection(); + + const state = useBrandStore.getState(); + expect(state.selectedBrandId).toBeNull(); + expect(state.selectedBrandName).toBeNull(); + }); + + it("切换选中品牌应覆盖旧值", () => { + useBrandStore.setState({ + selectedBrandId: "brand-1", + selectedBrandName: "旧品牌", + }); + + const { selectBrand } = useBrandStore.getState(); + selectBrand("brand-2", "新品牌"); + + const state = useBrandStore.getState(); + expect(state.selectedBrandId).toBe("brand-2"); + expect(state.selectedBrandName).toBe("新品牌"); + }); + }); + + // ── syncFromSWR ───────────────────────────────────────────────────────── + + describe("syncFromSWR", () => { + it("应同步 SWR 数据到本地副本", () => { + const { syncFromSWR } = useBrandStore.getState(); + syncFromSWR([MOCK_BRAND, MOCK_BRAND_2]); + + const state = useBrandStore.getState(); + expect(state.localBrands).toHaveLength(2); + expect(state.localBrands[0].id).toBe("brand-1"); + expect(state.localBrands[1].id).toBe("brand-2"); + }); + + it("多次同步应替换而非追加", () => { + const { syncFromSWR } = useBrandStore.getState(); + syncFromSWR([MOCK_BRAND]); + syncFromSWR([MOCK_BRAND_2]); + + const state = useBrandStore.getState(); + expect(state.localBrands).toHaveLength(1); + expect(state.localBrands[0].id).toBe("brand-2"); + }); + }); + + // ── optimisticCreate ──────────────────────────────────────────────────── + + describe("optimisticCreate", () => { + it("成功时应在本地添加临时条目后替换为真实数据", async () => { + const { brandsApi } = await import("@/lib/api/brands"); + const created = vi.mocked(brandsApi.create).mockResolvedValueOnce( + MOCK_BRAND as never + ); + + const swrMutate = vi.fn(); + const { optimisticCreate } = useBrandStore.getState(); + + const result = await optimisticCreate( + "test-token", + { name: "测试品牌", platforms: ["bing"] }, + swrMutate + ); + + // 返回值应为 API 创建结果 + expect(result).toEqual(MOCK_BRAND); + + // 乐观操作状态已清除 + expect(useBrandStore.getState().optimisticAction).toBeNull(); + + // 本地列表应包含真实数据(非临时 ID) + const brands = useBrandStore.getState().localBrands; + expect(brands).toHaveLength(1); + expect(brands[0].id).toBe("brand-1"); + + // SWR mutate 应被调用 + expect(swrMutate).toHaveBeenCalled(); + }); + + it("失败时应回滚本地临时条目", async () => { + const { brandsApi } = await import("@/lib/api/brands"); + vi.mocked(brandsApi.create).mockRejectedValueOnce( + new Error("创建失败") as never + ); + + const swrMutate = vi.fn(); + const { optimisticCreate } = useBrandStore.getState(); + + const result = await optimisticCreate( + "test-token", + { name: "失败品牌" }, + swrMutate + ); + + // 返回 null + expect(result).toBeNull(); + + // 本地列表应回滚(为空) + expect(useBrandStore.getState().localBrands).toHaveLength(0); + + // 乐观操作状态已清除 + expect(useBrandStore.getState().optimisticAction).toBeNull(); + + // SWR mutate 不应被调用 + expect(swrMutate).not.toHaveBeenCalled(); + }); + + it("创建过程中 optimisticAction 应为 creating", async () => { + const { brandsApi } = await import("@/lib/api/brands"); + let resolveCreate: (value: unknown) => void; + const createPromise = new Promise((resolve) => { + resolveCreate = resolve; + }); + vi.mocked(brandsApi.create).mockReturnValueOnce( + createPromise as never + ); + + const { optimisticCreate } = useBrandStore.getState(); + const createResult = optimisticCreate("test-token", { name: "异步品牌" }); + + // API 调用期间 + expect(useBrandStore.getState().optimisticAction).toBe("creating"); + expect(useBrandStore.getState().localBrands).toHaveLength(1); + expect(useBrandStore.getState().localBrands[0].name).toBe("异步品牌"); + + // 解析 API + resolveCreate!(MOCK_BRAND); + await createResult; + + expect(useBrandStore.getState().optimisticAction).toBeNull(); + }); + }); + + // ── optimisticUpdate ──────────────────────────────────────────────────── + + describe("optimisticUpdate", () => { + beforeEach(() => { + useBrandStore.setState({ + localBrands: [MOCK_BRAND, MOCK_BRAND_2], + }); + }); + + it("成功时应在本地乐观更新后替换为 API 返回数据", async () => { + const updatedBrand: BrandListItem = { + ...MOCK_BRAND, + name: "更新后品牌", + }; + + const { brandsApi } = await import("@/lib/api/brands"); + vi.mocked(brandsApi.update).mockResolvedValueOnce( + updatedBrand as never + ); + + const swrMutate = vi.fn(); + const { optimisticUpdate } = useBrandStore.getState(); + + const result = await optimisticUpdate( + "test-token", + "brand-1", + { name: "更新后品牌" }, + swrMutate + ); + + expect(result).toEqual(updatedBrand); + expect(useBrandStore.getState().optimisticAction).toBeNull(); + + // 本地列表应包含更新后的数据 + const brands = useBrandStore.getState().localBrands; + expect(brands.find((b) => b.id === "brand-1")?.name).toBe("更新后品牌"); + + expect(swrMutate).toHaveBeenCalled(); + }); + + it("失败时应回滚到原始数据", async () => { + const { brandsApi } = await import("@/lib/api/brands"); + vi.mocked(brandsApi.update).mockRejectedValueOnce( + new Error("更新失败") as never + ); + + const swrMutate = vi.fn(); + const { optimisticUpdate } = useBrandStore.getState(); + + const result = await optimisticUpdate( + "test-token", + "brand-1", + { name: "回滚品牌" }, + swrMutate + ); + + expect(result).toBeNull(); + expect(useBrandStore.getState().optimisticAction).toBeNull(); + + // 本地列表应回滚到原始数据 + const brands = useBrandStore.getState().localBrands; + expect(brands.find((b) => b.id === "brand-1")?.name).toBe("测试品牌"); + + expect(swrMutate).not.toHaveBeenCalled(); + }); + + it("本地无品牌时直接走 API", async () => { + useBrandStore.setState({ localBrands: [] }); + + const updatedBrand: BrandListItem = { ...MOCK_BRAND, name: "新品牌" }; + const { brandsApi } = await import("@/lib/api/brands"); + vi.mocked(brandsApi.update).mockResolvedValueOnce( + updatedBrand as never + ); + + const swrMutate = vi.fn(); + const { optimisticUpdate } = useBrandStore.getState(); + + const result = await optimisticUpdate( + "test-token", + "brand-1", + { name: "新品牌" }, + swrMutate + ); + + expect(result).toEqual(updatedBrand); + expect(swrMutate).toHaveBeenCalled(); + }); + + it("更新过程中 optimisticAction 应为 updating", async () => { + const { brandsApi } = await import("@/lib/api/brands"); + let resolveUpdate: (value: unknown) => void; + const updatePromise = new Promise((resolve) => { + resolveUpdate = resolve; + }); + vi.mocked(brandsApi.update).mockReturnValueOnce( + updatePromise as never + ); + + const { optimisticUpdate } = useBrandStore.getState(); + const updateResult = optimisticUpdate( + "test-token", + "brand-1", + { name: "异步更新" } + ); + + // API 调用期间 + expect(useBrandStore.getState().optimisticAction).toBe("updating"); + + // 本地应已乐观更新 + expect( + useBrandStore.getState().localBrands.find((b) => b.id === "brand-1")?.name + ).toBe("异步更新"); + + resolveUpdate!({ ...MOCK_BRAND, name: "异步更新" }); + await updateResult; + + expect(useBrandStore.getState().optimisticAction).toBeNull(); + }); + }); + + // ── optimisticDelete ──────────────────────────────────────────────────── + + describe("optimisticDelete", () => { + beforeEach(() => { + useBrandStore.setState({ + localBrands: [MOCK_BRAND, MOCK_BRAND_2], + selectedBrandId: null, + selectedBrandName: null, + }); + }); + + it("成功时应在本地移除品牌", async () => { + const { brandsApi } = await import("@/lib/api/brands"); + vi.mocked(brandsApi.delete).mockResolvedValueOnce(undefined as never); + + const swrMutate = vi.fn(); + const { optimisticDelete } = useBrandStore.getState(); + + const result = await optimisticDelete("test-token", "brand-1", swrMutate); + + expect(result).toBe(true); + expect(useBrandStore.getState().optimisticAction).toBeNull(); + + // 本地列表不再包含被删除品牌 + const brands = useBrandStore.getState().localBrands; + expect(brands).toHaveLength(1); + expect(brands.find((b) => b.id === "brand-1")).toBeUndefined(); + + expect(swrMutate).toHaveBeenCalled(); + }); + + it("失败时应恢复被删除的品牌", async () => { + const { brandsApi } = await import("@/lib/api/brands"); + vi.mocked(brandsApi.delete).mockRejectedValueOnce( + new Error("删除失败") as never + ); + + const swrMutate = vi.fn(); + const { optimisticDelete } = useBrandStore.getState(); + + const result = await optimisticDelete("test-token", "brand-1", swrMutate); + + expect(result).toBe(false); + expect(useBrandStore.getState().optimisticAction).toBeNull(); + + // 本地列表应恢复被删除品牌 + const brands = useBrandStore.getState().localBrands; + expect(brands).toHaveLength(2); + expect(brands.find((b) => b.id === "brand-1")).toBeDefined(); + }); + + it("删除当前选中品牌时应清除选择", async () => { + useBrandStore.setState({ + selectedBrandId: "brand-1", + selectedBrandName: "测试品牌", + }); + + const { brandsApi } = await import("@/lib/api/brands"); + vi.mocked(brandsApi.delete).mockResolvedValueOnce(undefined as never); + + const { optimisticDelete } = useBrandStore.getState(); + await optimisticDelete("test-token", "brand-1"); + + expect(useBrandStore.getState().selectedBrandId).toBeNull(); + expect(useBrandStore.getState().selectedBrandName).toBeNull(); + }); + + it("删除非选中品牌时不应影响选择", async () => { + useBrandStore.setState({ + selectedBrandId: "brand-1", + selectedBrandName: "测试品牌", + }); + + const { brandsApi } = await import("@/lib/api/brands"); + vi.mocked(brandsApi.delete).mockResolvedValueOnce(undefined as never); + + const { optimisticDelete } = useBrandStore.getState(); + await optimisticDelete("test-token", "brand-2"); + + expect(useBrandStore.getState().selectedBrandId).toBe("brand-1"); + expect(useBrandStore.getState().selectedBrandName).toBe("测试品牌"); + }); + }); +}); diff --git a/frontend/__tests__/stores/notification-store.test.ts b/frontend/__tests__/stores/notification-store.test.ts new file mode 100644 index 0000000..0b7475d --- /dev/null +++ b/frontend/__tests__/stores/notification-store.test.ts @@ -0,0 +1,232 @@ +/** + * Notification Store 单元测试 + * + * 覆盖:addNotification / removeNotification / clearAll / 自动过期清除 + */ + +import { describe, it, expect, vi, beforeEach, afterEach } from "vitest"; +import { useNotificationStore } from "@/lib/stores/notification-store"; + +describe("useNotificationStore", () => { + beforeEach(() => { + // 重置 store 到初始状态 + useNotificationStore.setState({ notifications: [] }); + vi.useFakeTimers(); + }); + + afterEach(() => { + vi.useRealTimers(); + }); + + // ── addNotification ──────────────────────────────────────────────────── + + describe("addNotification", () => { + it("应添加一条通知到队列", () => { + const { addNotification } = useNotificationStore.getState(); + const id = addNotification({ type: "success", message: "操作成功" }); + + expect(id).toBeTruthy(); + expect(id).toMatch(/^notif-/); + + const { notifications } = useNotificationStore.getState(); + expect(notifications).toHaveLength(1); + expect(notifications[0].type).toBe("success"); + expect(notifications[0].message).toBe("操作成功"); + }); + + it("应支持不同类型的通知", () => { + const { addNotification } = useNotificationStore.getState(); + + addNotification({ type: "success", message: "成功" }); + addNotification({ type: "error", message: "错误" }); + addNotification({ type: "warning", message: "警告" }); + addNotification({ type: "info", message: "信息" }); + + const { notifications } = useNotificationStore.getState(); + expect(notifications).toHaveLength(4); + expect(notifications[0].type).toBe("success"); + expect(notifications[1].type).toBe("error"); + expect(notifications[2].type).toBe("warning"); + expect(notifications[3].type).toBe("info"); + }); + + it("应支持可选标题", () => { + const { addNotification } = useNotificationStore.getState(); + addNotification({ type: "info", message: "消息", title: "标题" }); + + const { notifications } = useNotificationStore.getState(); + expect(notifications[0].title).toBe("标题"); + }); + + it("默认过期时间应按类型自动设置", () => { + const { addNotification } = useNotificationStore.getState(); + + addNotification({ type: "success", message: "成功" }); + addNotification({ type: "error", message: "错误" }); + addNotification({ type: "warning", message: "警告" }); + addNotification({ type: "info", message: "信息" }); + + const { notifications } = useNotificationStore.getState(); + expect(notifications[0].duration).toBe(3000); // success + expect(notifications[1].duration).toBe(5000); // error + expect(notifications[2].duration).toBe(4000); // warning + expect(notifications[3].duration).toBe(3000); // info + }); + + it("应支持自定义过期时间", () => { + const { addNotification } = useNotificationStore.getState(); + addNotification({ type: "success", message: "自定义", duration: 10000 }); + + const { notifications } = useNotificationStore.getState(); + expect(notifications[0].duration).toBe(10000); + }); + + it("duration 为 undefined 时应使用默认过期时间", () => { + const { addNotification } = useNotificationStore.getState(); + // 不传 duration,使用 error 类型的默认值 5000 + addNotification({ type: "error", message: "使用默认" }); + + const { notifications } = useNotificationStore.getState(); + expect(notifications[0].duration).toBe(5000); + }); + + it("每条通知应有唯一 ID", () => { + const { addNotification } = useNotificationStore.getState(); + const id1 = addNotification({ type: "info", message: "第一条" }); + const id2 = addNotification({ type: "info", message: "第二条" }); + + expect(id1).not.toBe(id2); + }); + }); + + // ── removeNotification ───────────────────────────────────────────────── + + describe("removeNotification", () => { + it("应移除指定 ID 的通知", () => { + const { addNotification, removeNotification } = + useNotificationStore.getState(); + + const id1 = addNotification({ type: "success", message: "保留" }); + const id2 = addNotification({ type: "error", message: "移除" }); + + removeNotification(id2); + + const { notifications } = useNotificationStore.getState(); + expect(notifications).toHaveLength(1); + expect(notifications[0].id).toBe(id1); + }); + + it("移除不存在的 ID 不应报错", () => { + const { addNotification, removeNotification } = + useNotificationStore.getState(); + + addNotification({ type: "info", message: "测试" }); + expect(() => removeNotification("non-existent")).not.toThrow(); + + const { notifications } = useNotificationStore.getState(); + expect(notifications).toHaveLength(1); + }); + + it("移除通知时应清除其定时器", () => { + const { addNotification, removeNotification } = + useNotificationStore.getState(); + + const id = addNotification({ type: "success", message: "提前移除" }); + removeNotification(id); + + // 快进超过默认过期时间,不应再触发移除(避免对空列表操作) + vi.advanceTimersByTime(5000); + + const { notifications } = useNotificationStore.getState(); + expect(notifications).toHaveLength(0); + }); + }); + + // ── 自动过期清除 ─────────────────────────────────────────────────────── + + describe("自动过期清除", () => { + it("到达过期时间后应自动移除通知", () => { + const { addNotification } = useNotificationStore.getState(); + addNotification({ type: "success", message: "3秒后过期" }); + + // 快进 3 秒 + vi.advanceTimersByTime(3000); + + const { notifications } = useNotificationStore.getState(); + expect(notifications).toHaveLength(0); + }); + + it("不同类型通知在不同时间过期", () => { + const { addNotification } = useNotificationStore.getState(); + addNotification({ type: "success", message: "3秒" }); + addNotification({ type: "error", message: "5秒" }); + + // 快进 3 秒,success 应被清除 + vi.advanceTimersByTime(3000); + expect(useNotificationStore.getState().notifications).toHaveLength(1); + expect(useNotificationStore.getState().notifications[0].type).toBe( + "error" + ); + + // 再快进 2 秒(共 5 秒),error 也应被清除 + vi.advanceTimersByTime(2000); + expect(useNotificationStore.getState().notifications).toHaveLength(0); + }); + + it("自定义 duration=0 的通知不会自动过期", () => { + const { addNotification } = useNotificationStore.getState(); + // duration=0 时 setTimeout(cb, 0) 会在下一个事件循环触发 + // 但 effectiveDuration !== null 为 true,所以会设置定时器 + // 这里测试 duration 传入 0 的行为 + addNotification({ type: "error", message: "0 毫秒过期", duration: 0 }); + + // 0 毫秒定时器应立即触发 + vi.advanceTimersByTime(1); + + const { notifications } = useNotificationStore.getState(); + expect(notifications).toHaveLength(0); + }); + + it("自定义 duration 应在指定时间后过期", () => { + const { addNotification } = useNotificationStore.getState(); + addNotification({ type: "info", message: "1秒过期", duration: 1000 }); + + vi.advanceTimersByTime(999); + expect(useNotificationStore.getState().notifications).toHaveLength(1); + + vi.advanceTimersByTime(1); + expect(useNotificationStore.getState().notifications).toHaveLength(0); + }); + }); + + // ── clearAll ──────────────────────────────────────────────────────────── + + describe("clearAll", () => { + it("应清空所有通知", () => { + const { addNotification } = useNotificationStore.getState(); + addNotification({ type: "success", message: "A" }); + addNotification({ type: "error", message: "B" }); + addNotification({ type: "warning", message: "C" }); + + expect(useNotificationStore.getState().notifications).toHaveLength(3); + + const { clearAll } = useNotificationStore.getState(); + clearAll(); + + expect(useNotificationStore.getState().notifications).toHaveLength(0); + }); + + it("clearAll 后定时器不应再触发", () => { + const { addNotification } = useNotificationStore.getState(); + addNotification({ type: "success", message: "3秒后过期" }); + + const { clearAll } = useNotificationStore.getState(); + clearAll(); + + // 快进超过过期时间 + vi.advanceTimersByTime(5000); + + expect(useNotificationStore.getState().notifications).toHaveLength(0); + }); + }); +}); diff --git a/frontend/app/(auth)/login/page.tsx b/frontend/app/(auth)/login/page.tsx index d408f86..8a2d639 100644 --- a/frontend/app/(auth)/login/page.tsx +++ b/frontend/app/(auth)/login/page.tsx @@ -2,7 +2,6 @@ import { useState } from "react"; import { signIn } from "next-auth/react"; -import { useRouter } from "next/navigation"; import Link from "next/link"; import { Button } from "@/components/ui/button"; import { Input } from "@/components/ui/input"; @@ -17,7 +16,6 @@ import { } from "@/components/ui/card"; export default function LoginPage() { - const router = useRouter(); const [email, setEmail] = useState(""); const [password, setPassword] = useState(""); const [error, setError] = useState(""); @@ -36,8 +34,10 @@ export default function LoginPage() { if (result?.error) { setError("邮箱或密码错误"); } else { - router.push("/dashboard"); - router.refresh(); + // 使用 window.location.href 进行完整页面加载,确保 SessionProvider + // 重新初始化并获取最新的 session cookie,避免客户端导航时 + // useSession() 读到旧的 unauthenticated 缓存状态导致跳回登录页 + window.location.href = "/dashboard"; } }; diff --git a/frontend/app/(dashboard)/brands/page.tsx b/frontend/app/(dashboard)/brands/page.tsx index 3ae8071..4c9673f 100644 --- a/frontend/app/(dashboard)/brands/page.tsx +++ b/frontend/app/(dashboard)/brands/page.tsx @@ -1,19 +1,19 @@ "use client"; -import { useEffect, useState, useCallback } from "react"; +import { useState, useEffect } from "react"; import { useSession } from "next-auth/react"; import Link from "next/link"; import { useRouter } from "next/navigation"; import { Card, CardContent, CardHeader, CardTitle } from "@/components/ui/card"; import { Button } from "@/components/ui/button"; import { Badge } from "@/components/ui/badge"; -import { Skeleton } from "@/components/ui/skeleton"; import { BrandFormDialog, AddBrandButton, } from "@/components/brand/BrandFormDialog"; import { api } from "@/lib/api"; import { PLATFORM_MAP } from "@/lib/platforms"; +import { useNotificationStore, useBrandStore } from "@/lib/stores"; import type { BrandListItem, BrandListResponse } from "@/types/brand"; import { Search, Star, Calendar, Edit, Trash2 } from "lucide-react"; import { @@ -24,45 +24,50 @@ import { DialogHeader, DialogTitle, } from "@/components/ui/dialog"; +import { useApi } from "@/lib/hooks/use-api"; +import { LoadingState, ErrorState, EmptyState } from "@/components/ui/api-states"; export default function BrandsPage() { const { data: session } = useSession(); const router = useRouter(); - const [brands, setBrands] = useState([]); - const [loading, setLoading] = useState(true); - const [error, setError] = useState(null); const [deleteBrand, setDeleteBrand] = useState(null); const [deleting, setDeleting] = useState(false); - const fetchBrands = useCallback(async () => { - const token = session?.accessToken; - if (!token) return; + const { data: brandsResponse, isLoading: loading, error: apiError, refresh: fetchBrands } = + useApi("/api/v1/brands/"); - try { - setLoading(true); - const response = (await api.brands.list(token)) as BrandListResponse; - setBrands(response.items || []); - } catch (err) { - setError(err instanceof Error ? err.message : "加载品牌失败"); - } finally { - setLoading(false); - } - }, [session?.accessToken]); + const brands: BrandListItem[] = brandsResponse?.items ?? []; + const error = apiError?.message ?? null; + // 同步 SWR 数据到 brand-store + const syncFromSWR = useBrandStore((s) => s.syncFromSWR); useEffect(() => { - fetchBrands(); - }, [fetchBrands]); + if (brands.length > 0) { + syncFromSWR(brands); + } + }, [brands, syncFromSWR]); + + const addNotification = useNotificationStore((s) => s.addNotification); + const optimisticDelete = useBrandStore((s) => s.optimisticDelete); const handleDelete = async () => { if (!deleteBrand || !session?.accessToken) return; try { setDeleting(true); - await api.brands.delete(session.accessToken, deleteBrand.id); - setDeleteBrand(null); - fetchBrands(); + const success = await optimisticDelete( + session.accessToken, + deleteBrand.id, + fetchBrands + ); + if (success) { + setDeleteBrand(null); + } } catch (err) { - alert(err instanceof Error ? err.message : "删除失败"); + addNotification({ + type: "error", + message: err instanceof Error ? err.message : "删除失败", + }); } finally { setDeleting(false); } @@ -108,35 +113,22 @@ export default function BrandsPage() {

品牌管理

管理您的品牌监控列表

- - -
- {Array.from({ length: 3 }).map((_, i) => ( - - - - - - - - - - ))}
+ ); } if (error) { return ( -
-

{error}

- +
+
+
+

品牌管理

+

管理您的品牌监控列表

+
+
+
); } @@ -150,17 +142,12 @@ export default function BrandsPage() {

管理您的品牌监控列表

- -
-
- -
-

暂无品牌

-

- 添加您的第一个品牌,开始监控其在AI搜索中的表现 -

- -
+ } + message="暂无品牌" + description="添加您的第一个品牌,开始监控其在AI搜索中的表现" + action={} + /> ); } diff --git a/frontend/app/(dashboard)/dashboard/admin/page.tsx b/frontend/app/(dashboard)/dashboard/admin/page.tsx index 9c6737f..6b6e5af 100644 --- a/frontend/app/(dashboard)/dashboard/admin/page.tsx +++ b/frontend/app/(dashboard)/dashboard/admin/page.tsx @@ -1,7 +1,6 @@ "use client"; -import { useEffect, useState } from "react"; -import { useSession } from "next-auth/react"; +import { useState } from "react"; import { Card, CardContent, CardHeader, CardTitle } from "@/components/ui/card"; import { Button } from "@/components/ui/button"; import { Input } from "@/components/ui/input"; @@ -29,7 +28,11 @@ import { TableHeader, TableRow, } from "@/components/ui/table"; -import { api } from "@/lib/api"; +import { fetchWithAuth } from "@/lib/api/client"; +import type { AdminStatsData, AdminUser, AdminUserListResponse, AdminActionResponse } from "@/lib/api/admin"; +import { useApi } from "@/lib/hooks/use-api"; +import { LoadingState, ErrorState } from "@/components/ui/api-states"; +import { clsx } from "clsx"; import { Users, Search, @@ -44,26 +47,6 @@ import { ChevronRight, } from "lucide-react"; -interface StatsData { - total_users: number; - total_queries: number; - total_citations: number; - citation_rate: number; - today_active_users: number; -} - -interface AdminUser { - id: string; - email: string; - name: string | null; - plan: string; - is_active: boolean; - is_admin: boolean; - email_verified: boolean; - query_count: number; - created_at: string; -} - const PLAN_OPTIONS = [ { value: "free", label: "免费版" }, { value: "starter", label: "入门版" }, @@ -74,15 +57,9 @@ const PLAN_OPTIONS = [ const LIMIT = 10; export default function AdminPage() { - const { data: session } = useSession(); - const [stats, setStats] = useState(null); - const [users, setUsers] = useState([]); - const [totalUsers, setTotalUsers] = useState(0); const [skip, setSkip] = useState(0); const [search, setSearch] = useState(""); - const [loadingStats, setLoadingStats] = useState(false); - const [loadingUsers, setLoadingUsers] = useState(false); - const [error, setError] = useState(null); + const [mutationError, setMutationError] = useState(null); const [success, setSuccess] = useState(null); const [dialogOpen, setDialogOpen] = useState(false); @@ -91,48 +68,16 @@ export default function AdminPage() { const [selectedPlan, setSelectedPlan] = useState(""); const [actionLoading, setActionLoading] = useState(false); - const token = session?.accessToken; + const { data: stats, isLoading: loadingStats, error: statsError } = + useApi("/api/v1/admin/stats"); - useEffect(() => { - if (!token) return; - loadStats(); - // eslint-disable-next-line react-hooks/exhaustive-deps - }, [token]); + const usersUrl = `/api/v1/admin/users?skip=${skip}&limit=${LIMIT}${search ? `&search=${encodeURIComponent(search)}` : ""}`; + const { data: usersData, isLoading: loadingUsers, error: usersError, refresh: refreshUsers } = + useApi(usersUrl); - useEffect(() => { - if (!token) return; - loadUsers(); - // eslint-disable-next-line react-hooks/exhaustive-deps - }, [token, skip, search]); - - async function loadStats() { - if (!token) return; - setLoadingStats(true); - try { - const data = await api.admin.getStats(token); - setStats(data); - setError(null); - } catch (err) { - setError(err instanceof Error ? err.message : "加载统计失败"); - } finally { - setLoadingStats(false); - } - } - - async function loadUsers() { - if (!token) return; - setLoadingUsers(true); - try { - const data = await api.admin.getUsers(token, { skip, limit: LIMIT, search: search || undefined }); - setUsers(data.items || []); - setTotalUsers(data.total || 0); - setError(null); - } catch (err) { - setError(err instanceof Error ? err.message : "加载用户列表失败"); - } finally { - setLoadingUsers(false); - } - } + const users: AdminUser[] = usersData?.items ?? []; + const totalUsers = usersData?.total ?? 0; + const error = mutationError || statsError?.message || usersError?.message || null; function openToggleDialog(user: AdminUser) { setSelectedUser(user); @@ -148,22 +93,29 @@ export default function AdminPage() { } async function handleConfirm() { - if (!token || !selectedUser) return; + if (!selectedUser) return; setActionLoading(true); setSuccess(null); + setMutationError(null); try { if (dialogType === "toggle") { - const res = await api.admin.toggleUserActive(token, selectedUser.id); + const res = await fetchWithAuth( + `/api/v1/admin/users/${selectedUser.id}/toggle-active`, + { method: "POST" } + ) as AdminActionResponse; setSuccess(res.message || "操作成功"); } else { - const res = await api.admin.updateUserPlan(token, selectedUser.id, selectedPlan); + const res = await fetchWithAuth( + `/api/v1/admin/users/${selectedUser.id}/update-plan`, + { method: "PUT", body: JSON.stringify({ plan: selectedPlan }) } + ) as AdminActionResponse; setSuccess(res.message || "套餐更新成功"); } - await loadUsers(); + refreshUsers(); setDialogOpen(false); setTimeout(() => setSuccess(null), 3000); } catch (err) { - setError(err instanceof Error ? err.message : "操作失败"); + setMutationError(err instanceof Error ? err.message : "操作失败"); setDialogOpen(false); } finally { setActionLoading(false); @@ -210,6 +162,19 @@ export default function AdminPage() { return d.toLocaleDateString("zh-CN"); } + if (loadingStats && !stats) { + return ( +
+
+

管理后台

+

系统统计与用户管理

+
+ + +
+ ); + } + return (
@@ -236,8 +201,8 @@ export default function AdminPage() { {statCards.map((card) => ( -
- +
+

{card.title}

@@ -271,88 +236,92 @@ export default function AdminPage() {
-
- - - - 邮箱 - 用户名 - 套餐 - 查询数 - 邮箱验证 - 状态 - 注册日期 - 操作 - - - - {loadingUsers ? ( + {usersError ? ( + + ) : ( +
+
+ - - - + 邮箱 + 用户名 + 套餐 + 查询数 + 邮箱验证 + 状态 + 注册日期 + 操作 - ) : users.length === 0 ? ( - - - 暂无用户数据 - - - ) : ( - users.map((user) => ( - - {user.email} - {user.name || "-"} - - {user.plan} - - {user.query_count} - - {user.email_verified ? ( - - 已验证 - - ) : ( - - 未验证 - - )} - - - {user.is_active ? ( - - 正常 - - ) : ( - 禁用 - )} - - {formatDate(user.created_at)} - -
- - -
+
+ + {loadingUsers ? ( + + + - )) - )} - -
-
+ ) : users.length === 0 ? ( + + + 暂无用户数据 + + + ) : ( + users.map((user) => ( + + {user.email} + {user.name || "-"} + + {user.plan} + + {user.query_count} + + {user.email_verified ? ( + + 已验证 + + ) : ( + + 未验证 + + )} + + + {user.is_active ? ( + + 正常 + + ) : ( + 禁用 + )} + + {formatDate(user.created_at)} + +
+ + +
+
+
+ )) + )} + + +
+ )} {/* Pagination */} {totalPages > 1 && ( @@ -428,7 +397,3 @@ export default function AdminPage() {
); } - -function cn(...classes: (string | undefined | false)[]) { - return classes.filter(Boolean).join(" "); -} diff --git a/frontend/app/(dashboard)/dashboard/analytics/page.tsx b/frontend/app/(dashboard)/dashboard/analytics/page.tsx index b8877f7..ba010a8 100644 --- a/frontend/app/(dashboard)/dashboard/analytics/page.tsx +++ b/frontend/app/(dashboard)/dashboard/analytics/page.tsx @@ -1,10 +1,9 @@ "use client"; -import { useState, useEffect } from "react"; +import { useState } from "react"; import { Card, CardContent } from "@/components/ui/card"; import { Button } from "@/components/ui/button"; import { Badge } from "@/components/ui/badge"; -import { Skeleton } from "@/components/ui/skeleton"; import { Table, TableBody, @@ -23,8 +22,6 @@ import { AlertTriangle, Check, BarChart3, - AlertCircle, - RefreshCw, } from "lucide-react"; import { BarChart, @@ -44,6 +41,8 @@ import { type TopContentItem, type InsightResponse, } from "@/lib/api"; +import { useApi } from "@/lib/hooks/use-api"; +import { LoadingState, ErrorState } from "@/components/ui/api-states"; // ─── Types ─────────────────────────────────────────────────────────────────── @@ -177,45 +176,30 @@ function MetricCard({ subtext?: string; }) { return ( - - -
-
- {icon} -
- {highlight && ( - - GEO核心指标 - - )} +
+
+

{label}

+
+ {icon}
-
-

- {typeof value === "number" ? value.toLocaleString() : value} -

-

{label}

- {subtext &&

{subtext}

} -
- - +
+

+ {typeof value === "number" ? value.toLocaleString() : value} +

+ {subtext &&

{subtext}

} +
); } function EmptyTopContent() { return (
- -

暂无发布内容数据

-

发布内容后这里将展示表现排行榜

+ +

暂无发布内容数据

+

发布内容后这里将展示表现排行榜

); } @@ -223,9 +207,9 @@ function EmptyTopContent() { function EmptyInsights() { return (
- -

暂无AI洞察

-

积累更多数据后,AI将为您生成优化建议

+ +

暂无AI洞察

+

积累更多数据后,AI将为您生成优化建议

); } @@ -235,35 +219,52 @@ function EmptyInsights() { export default function AnalyticsPage() { const [selectedPlatforms, setSelectedPlatforms] = useState([]); const [timeRange, setTimeRange] = useState("30"); + const [appliedInsights, setAppliedInsights] = useState>(new Set()); - const [overview, setOverview] = useState(null); - const [topContent, setTopContent] = useState([]); - const [insights, setInsights] = useState([]); - const [loading, setLoading] = useState(true); - const [error, setError] = useState(null); + // SWR 数据获取 + const { + data: overview, + isLoading: overviewLoading, + error: overviewError, + refresh: refreshOverview, + } = useApi("/api/v1/analytics/overview"); - useEffect(() => { - async function fetchAnalyticsData() { - try { - setLoading(true); - setError(null); - const [overviewData, topData, insightsData] = await Promise.all([ - analyticsApi.getOverview(), - analyticsApi.getTopContent(undefined, { limit: 5 }), - analyticsApi.getInsights(undefined, { limit: 6 }), - ]); - setOverview(overviewData); - setTopContent(topData?.items ?? []); - setInsights(mapApiInsights(insightsData ?? [])); - } catch (err) { - console.error("Analytics fetch error:", err); - setError(err instanceof Error ? err.message : "数据加载失败"); - } finally { - setLoading(false); - } - } - fetchAnalyticsData(); - }, []); + const { + data: topContentData, + isLoading: topLoading, + error: topError, + refresh: refreshTop, + } = useApi<{ items: TopContentItem[]; sort_by: string; total: number }>("/api/v1/analytics/top?limit=5"); + + const { + data: insightsData, + isLoading: insightsLoading, + error: insightsError, + refresh: refreshInsights, + } = useApi("/api/v1/analytics/insights?limit=6"); + + const loading = overviewLoading || topLoading || insightsLoading; + + // "用户未关联组织" 类错误视为空状态 + const isOrgError = (err: Error | undefined) => + err?.message.includes("未关联组织") || err?.message.includes("No organization"); + + const hasOrgError = isOrgError(overviewError) || isOrgError(topError) || isOrgError(insightsError); + const error = !hasOrgError && (overviewError || topError || insightsError) + ? overviewError || topError || insightsError + : undefined; + + const topContent: TopContentItem[] = topContentData?.items ?? []; + const rawInsights: InsightResponse[] = insightsData ?? []; + const insights = mapApiInsights(rawInsights).map((ins) => + appliedInsights.has(ins.id) ? { ...ins, applied: true } : ins + ); + + const handleRetry = () => { + refreshOverview(); + refreshTop(); + refreshInsights(); + }; const togglePlatform = (key: string) => { setSelectedPlatforms((prev) => @@ -274,9 +275,7 @@ export default function AnalyticsPage() { const handleApplyInsight = async (insightId: string) => { try { await analyticsApi.applyInsight(undefined, insightId); - setInsights((prev) => - prev.map((ins) => (ins.id === insightId ? { ...ins, applied: true } : ins)) - ); + setAppliedInsights((prev) => new Set(prev).add(insightId)); } catch (err) { console.error("Apply insight error:", err); } @@ -285,14 +284,10 @@ export default function AnalyticsPage() { if (loading) { return (
- -
- {Array.from({ length: 4 }).map((_, i) => ( - - ))} -
- - + + + +
); } @@ -300,16 +295,8 @@ export default function AnalyticsPage() { if (error) { return (
-

数据监测中心

-
- -

数据加载失败

-

{error}

- -
+

数据监测中心

+
); } @@ -324,12 +311,12 @@ export default function AnalyticsPage() { return (
{/* Top Area */} -
+
-

+

数据监测中心

-

+

全渠道内容表现追踪与AI引用洞察

@@ -379,27 +366,26 @@ export default function AnalyticsPage() { } + icon={} iconBg="bg-blue-50" /> } + icon={} iconBg="bg-purple-50" /> } + icon={} iconBg="bg-amber-50" /> } - iconBg="bg-primary/10" - highlight + icon={} + iconBg="bg-emerald-50" subtext={ overview?.avg_engagement_rate ? `互动率 ${(overview.avg_engagement_rate * 100).toFixed(1)}%` @@ -408,15 +394,14 @@ export default function AnalyticsPage() { />
- {/* Trend Chart — platform distribution */} - - -
-

平台内容分布

- - 实时数据 - -
+ {/* Trend Chart */} +
+
+

平台内容分布

+ + 实时数据 + +
{trendData.length > 0 ? ( @@ -437,8 +422,8 @@ export default function AnalyticsPage() { /> ) : (
- -

暂无平台分布数据

+ +

暂无平台分布数据

)} - - +
{/* Performance Table */} - - -
-

内容表现排行榜

- - Top {topContent.length} - -
+
+
+

内容表现排行榜

+ + Top {topContent.length} + +
{topContent.length === 0 ? ( ) : ( @@ -482,12 +465,12 @@ export default function AnalyticsPage() { - 排名 - 标题 - 平台 - 曝光 - 互动率 - AI引用数 + 排名 + 标题 + 平台 + 曝光 + 互动率 + AI引用数 @@ -498,7 +481,7 @@ export default function AnalyticsPage() { ? ((item.search_clicks / item.search_impressions) * 100).toFixed(1) : "0.0"; return ( - + - + {item.content_title} @@ -522,10 +505,10 @@ export default function AnalyticsPage() { {item.platform} - + {(item.views || item.search_impressions).toLocaleString()} - + {interactionRate}% @@ -541,40 +524,37 @@ export default function AnalyticsPage() {
)} -
-
+
{/* AI Insights */} -
-

+
+

AI 智能洞察

{insights.length === 0 ? ( - - - - - +
+ +
) : (
{insights.map((insight) => { const styles = getSeverityStyles(insight.severity); return ( -
-
- +
+
-

+

{insight.title}

-

+

{insight.description}

{insight.recommendation && ( @@ -597,7 +577,7 @@ export default function AnalyticsPage() {
- +
); })}
diff --git a/frontend/app/(dashboard)/dashboard/citations/page.tsx b/frontend/app/(dashboard)/dashboard/citations/page.tsx index 351026b..7e3df9d 100644 --- a/frontend/app/(dashboard)/dashboard/citations/page.tsx +++ b/frontend/app/(dashboard)/dashboard/citations/page.tsx @@ -1,7 +1,6 @@ "use client"; -import { useEffect, useRef, useState } from "react"; -import { useSession } from "next-auth/react"; +import { useState } from "react"; import { Table, TableBody, @@ -22,9 +21,10 @@ import { SelectValue, } from "@/components/ui/select"; import { Button } from "@/components/ui/button"; -import { api } from "@/lib/api"; import { PLATFORM_MAP } from "@/lib/platforms"; -import { Check, X, Loader2, Quote, Filter } from "lucide-react"; +import { Check, X, Quote, Filter } from "lucide-react"; +import { useApi } from "@/lib/hooks/use-api"; +import { LoadingState } from "@/components/ui/api-states"; interface CitationItem { id: string; @@ -43,69 +43,44 @@ interface QueryOption { } export default function CitationsPage() { - const { data: session } = useSession(); - const [citations, setCitations] = useState([]); - const [queries, setQueries] = useState([]); - const [loading, setLoading] = useState(true); - const [error, setError] = useState(null); - const [selectedQuery, setSelectedQuery] = useState("all"); const [selectedPlatform, setSelectedPlatform] = useState("all"); const [startDate, setStartDate] = useState(""); const [endDate, setEndDate] = useState(""); - const isFirstFilterEffect = useRef(true); + // 用于手动触发筛选 + const [filterKey, setFilterKey] = useState(0); - useEffect(() => { - if (!session?.accessToken) return; - loadQueries(); - loadCitations(); - // eslint-disable-next-line react-hooks/exhaustive-deps - }, [session?.accessToken]); + // 构建引用记录查询 URL + const citationsUrl = (() => { + const params = new URLSearchParams(); + if (selectedQuery && selectedQuery !== "all") params.append("query_id", selectedQuery); + if (selectedPlatform && selectedPlatform !== "all") params.append("platform", selectedPlatform); + if (startDate) params.append("start_date", startDate); + if (endDate) params.append("end_date", endDate); + const qs = params.toString(); + // filterKey 作为虚拟参数,即使筛选条件不变也允许重新请求 + return `/api/v1/citations/${qs ? `?${qs}&_k=${filterKey}` : `?_k=${filterKey}`}`; + })(); - useEffect(() => { - if (!session?.accessToken) return; - if (isFirstFilterEffect.current) { - isFirstFilterEffect.current = false; - return; - } - loadCitations(); - // eslint-disable-next-line react-hooks/exhaustive-deps - }, [selectedQuery, selectedPlatform, startDate, endDate, session?.accessToken]); + const { + data: citationsData, + isLoading, + error: citationsError, + refresh: refreshCitations, + } = useApi<{ items: CitationItem[] }>( + citationsUrl, + { dedupingInterval: 0 } + ); - async function loadQueries() { - try { - const data = await api.queries.list(session!.accessToken); - setQueries(data.items || []); - } catch { - // 静默失败,查询词筛选为非必需 - } - } + const { + data: queriesData, + } = useApi<{ items: QueryOption[] }>("/api/v1/queries/"); - async function loadCitations() { - if (!session?.accessToken) return; - try { - setLoading(true); - const params = new URLSearchParams(); - if (selectedQuery && selectedQuery !== "all") params.append("query_id", selectedQuery); - if (selectedPlatform && selectedPlatform !== "all") params.append("platform", selectedPlatform); - if (startDate) params.append("start_date", startDate); - if (endDate) params.append("end_date", endDate); - - const data = await api.citations.list( - session.accessToken, - params.toString() - ); - setCitations(data.items || []); - setError(null); - } catch (err) { - setError(err instanceof Error ? err.message : "加载引用记录失败"); - } finally { - setLoading(false); - } - } + const citations: CitationItem[] = citationsData?.items ?? []; + const queries: QueryOption[] = queriesData?.items ?? []; function handleFilter() { - loadCitations(); + setFilterKey((k) => k + 1); } function handleReset() { @@ -113,18 +88,17 @@ export default function CitationsPage() { setSelectedPlatform("all"); setStartDate(""); setEndDate(""); + setFilterKey((k) => k + 1); } - if (loading && citations.length === 0) { + if (isLoading && citations.length === 0) { return (

引用记录

查看各平台的引用检测结果

-
- -
+
); } @@ -207,9 +181,9 @@ export default function CitationsPage() {
- {error && ( + {citationsError && (
- {error} + {citationsError.message}
)} diff --git a/frontend/app/(dashboard)/dashboard/content/page.tsx b/frontend/app/(dashboard)/dashboard/content/page.tsx index f52edfc..016433a 100644 --- a/frontend/app/(dashboard)/dashboard/content/page.tsx +++ b/frontend/app/(dashboard)/dashboard/content/page.tsx @@ -134,10 +134,10 @@ function ContentCard({ item }: { item: Content }) { const dateStr = new Date(item.created_at).toLocaleDateString("zh-CN"); return ( - - +
+
-

+

{item.title}

@@ -149,7 +149,7 @@ function ContentCard({ item }: { item: Content }) { {statusConfig.label}
-
+
@@ -166,8 +166,8 @@ function ContentCard({ item }: { item: Content }) { )}
- - +
+
); } @@ -226,17 +226,17 @@ function PipelineTimeline({ steps }: { steps: PipelineStep[] }) { function EmptyState({ onGenerate }: { onGenerate: () => void }) { return ( -
-
- +
+
+
-

还没有内容

-

+

还没有内容

+

让AI帮你创作第一篇内容,开启智能内容生产之旅

+ +
+
) : recommendations.length > 0 ? (
{recommendations.map((comp) => { diff --git a/frontend/app/(dashboard)/onboarding/Step4HealthReport.tsx b/frontend/app/(dashboard)/onboarding/Step4HealthReport.tsx index db674d6..46c81e1 100644 --- a/frontend/app/(dashboard)/onboarding/Step4HealthReport.tsx +++ b/frontend/app/(dashboard)/onboarding/Step4HealthReport.tsx @@ -46,52 +46,31 @@ export function Step4HealthReport({ const { data: session } = useSession(); const [report, setReport] = useState(null); const [loading, setLoading] = useState(true); - const [error] = useState(null); + const [error, setError] = useState(null); + + const fetchReport = async () => { + if (!session?.accessToken) return; + + try { + setLoading(true); + setError(null); + const data = (await api.onboarding.getHealthReport( + session.accessToken, + brandId, + )) as BrandHealthReport; + setReport(data); + } catch (err) { + console.error("获取健康报告失败:", err); + setError("获取健康报告失败,请重试"); + } finally { + setLoading(false); + } + }; useEffect(() => { - const fetchReport = async () => { - if (!session?.accessToken) return; - - try { - setLoading(true); - const data = (await api.onboarding.getHealthReport( - session.accessToken, - brandId, - )) as BrandHealthReport; - setReport(data); - } catch (err) { - console.error("获取健康报告失败:", err); - // 使用模拟数据 - setReport({ - brand_id: brandId, - brand_name: brandName, - overall_score: 68, - platform_scores: { - wenxin: 72, - kimi: 65, - tongyi: 70, - baidu_ai: 68, - yuanbao: 60, - qingyan: 75, - doubao: 62, - }, - competitor_scores: [ - { name: "竞品A", score: 75, is_leading: false }, - { name: "竞品B", score: 58, is_leading: true }, - { name: "竞品C", score: 82, is_leading: false }, - ], - strengths: ["在Kimi平台表现优秀", "品牌提及率稳定"], - weaknesses: ["在腾讯元宝平台覆盖率低", "内容质量有待提升"], - }); - } finally { - setLoading(false); - } - }; - - // 模拟加载时间 - const timer = setTimeout(fetchReport, 1500); - return () => clearTimeout(timer); - }, [session?.accessToken, brandId, brandName]); + fetchReport(); + // eslint-disable-next-line react-hooks/exhaustive-deps + }, [session?.accessToken, brandId]); if (loading) { return ( @@ -120,7 +99,7 @@ export function Step4HealthReport({ ); } - if (error || !report) { + if (error || (!loading && !report)) { return (
@@ -138,12 +117,24 @@ export function Step4HealthReport({ 上一步 - + +
); } + // TypeScript 类型守卫:经过 loading 和 error 检查后,report 必定存在 + if (!report) return null; + const healthLevel = getHealthLevel(report.overall_score); const healthConfig = HEALTH_LEVELS[healthLevel]; diff --git a/frontend/app/(dashboard)/onboarding/Step5ActionSuggestions.tsx b/frontend/app/(dashboard)/onboarding/Step5ActionSuggestions.tsx index 243fddc..3ae7c90 100644 --- a/frontend/app/(dashboard)/onboarding/Step5ActionSuggestions.tsx +++ b/frontend/app/(dashboard)/onboarding/Step5ActionSuggestions.tsx @@ -18,6 +18,7 @@ import { ArrowLeft, CheckCircle2, LayoutDashboard, + AlertTriangle, } from "lucide-react"; import { api } from "@/lib/api"; import type { ActionSuggestion } from "@/types/onboarding"; @@ -62,61 +63,30 @@ export function Step5ActionSuggestions({ const [suggestions, setSuggestions] = useState([]); const [loading, setLoading] = useState(true); const [completing, setCompleting] = useState(false); - const [error] = useState(null); + const [error, setError] = useState(null); + + const fetchSuggestions = async () => { + if (!session?.accessToken) return; + + try { + setLoading(true); + setError(null); + const data = (await api.onboarding.getActionSuggestions( + session.accessToken, + brandId, + )) as ActionSuggestion[]; + setSuggestions(data || []); + } catch (err) { + console.error("获取行动建议失败:", err); + setError("获取行动建议失败,请重试"); + } finally { + setLoading(false); + } + }; useEffect(() => { - const fetchSuggestions = async () => { - if (!session?.accessToken) return; - - try { - setLoading(true); - const data = (await api.onboarding.getActionSuggestions( - session.accessToken, - brandId, - )) as ActionSuggestion[]; - setSuggestions(data || []); - } catch (err) { - console.error("获取行动建议失败:", err); - // 使用模拟数据 - setSuggestions([ - { - id: "1", - title: "优化腾讯元宝平台内容", - description: - "在腾讯元宝平台的搜索结果中曝光率较低,建议增加相关内容布局", - priority: "high", - action_type: "improve_platform", - }, - { - id: "2", - title: "提升整体内容质量", - description: "内容被引用率偏低,建议优化内容的专业性和权威性", - priority: "high", - action_type: "optimize_content", - }, - { - id: "3", - title: "添加新的竞品对手", - description: "建议添加3个新的竞品以获得更全面的对比分析", - priority: "medium", - action_type: "add_competitor", - }, - { - id: "4", - title: "提高查询频率", - description: "当前每周查询可能错过重要信息,建议调整为每日查询", - priority: "low", - action_type: "increase_frequency", - }, - ]); - } finally { - setLoading(false); - } - }; - - // 模拟加载时间 - const timer = setTimeout(fetchSuggestions, 1000); - return () => clearTimeout(timer); + fetchSuggestions(); + // eslint-disable-next-line react-hooks/exhaustive-deps }, [session?.accessToken, brandId]); const handleComplete = async () => { @@ -166,6 +136,25 @@ export function Step5ActionSuggestions({ ); } + // 错误状态 + if (!loading && error) { + return ( +
+
+
+ +
+

获取建议失败

+

{error}

+
+
+ + +
+
+ ); + } + // 按优先级分组 const highPriority = suggestions.filter((s) => s.priority === "high"); const mediumPriority = suggestions.filter((s) => s.priority === "medium"); diff --git a/frontend/app/globals.css b/frontend/app/globals.css index 1cd3c28..2586026 100644 --- a/frontend/app/globals.css +++ b/frontend/app/globals.css @@ -28,11 +28,14 @@ --radius: 1rem; /* 16px base radius */ /* GEO Custom tokens */ - --geo-nav-bg: #1a1f2e; - --geo-nav-hover: #252b3b; + --geo-nav-bg: #FFFFFF; + --geo-nav-hover: #F3F4F6; --geo-nav-active: #10B981; - --geo-shadow-card: 0 2px 8px 0 rgba(0,0,0,0.06); - --geo-shadow-card-hover: 0 8px 24px 0 rgba(0,0,0,0.10); + --geo-nav-text: #374151; + --geo-nav-text-active: #059669; + --geo-nav-active-bg: #ECFDF5; + --geo-shadow-card: 0 1px 3px rgba(0,0,0,0.04); + --geo-shadow-card-hover: 0 4px 12px rgba(0,0,0,0.06); --geo-transition: 200ms ease; } @@ -84,7 +87,7 @@ @apply bg-white rounded-lg border border-geo-border shadow-card transition-all duration-200; } .geo-card:hover { - @apply -translate-y-0.5 shadow-card-hover; + @apply shadow-card-hover border-primary/30; } /* GEO Scrollbar */ diff --git a/frontend/app/layout.tsx b/frontend/app/layout.tsx index e556400..3eb33b1 100644 --- a/frontend/app/layout.tsx +++ b/frontend/app/layout.tsx @@ -2,6 +2,7 @@ import type { Metadata } from "next"; import localFont from "next/font/local"; import "./globals.css"; import { Providers } from "@/components/providers"; +import { ErrorBoundary } from "@/components/ErrorBoundary"; const geistSans = localFont({ src: "./fonts/GeistVF.woff", @@ -29,7 +30,9 @@ export default function RootLayout({ - {children} + + {children} + ); diff --git a/frontend/components/ErrorBoundary.tsx b/frontend/components/ErrorBoundary.tsx new file mode 100644 index 0000000..ee436ba --- /dev/null +++ b/frontend/components/ErrorBoundary.tsx @@ -0,0 +1,130 @@ +"use client"; + +/** + * 全局错误边界组件 + * + * - 捕获子树中的 React 渲染错误,防止整个页面白屏 + * - 在开发环境输出详细错误栈到 console + * - 预留 Sentry 集成点(搜索 TODO:SENTRY) + * - 提供可重置的友好错误 UI + */ + +import React, { Component, ErrorInfo, ReactNode } from "react"; + +interface Props { + children: ReactNode; + /** 自定义 fallback UI;不传则使用内置样式 */ + fallback?: ReactNode; +} + +interface State { + hasError: boolean; + error: Error | null; + errorInfo: ErrorInfo | null; +} + +export class ErrorBoundary extends Component { + constructor(props: Props) { + super(props); + this.state = { hasError: false, error: null, errorInfo: null }; + } + + static getDerivedStateFromError(error: Error): Partial { + return { hasError: true, error }; + } + + componentDidCatch(error: Error, errorInfo: ErrorInfo): void { + this.setState({ errorInfo }); + + // 开发环境:完整错误栈 + if (process.env.NODE_ENV !== "production") { + console.group("[ErrorBoundary] 捕获到未处理的渲染错误"); + console.error("Error:", error); + console.error("Component Stack:", errorInfo.componentStack); + console.groupEnd(); + } else { + console.error("[ErrorBoundary]", error.message); + } + + // TODO:SENTRY — 生产环境错误上报 + // import * as Sentry from "@sentry/nextjs"; + // Sentry.captureException(error, { extra: { componentStack: errorInfo.componentStack } }); + } + + handleReset = (): void => { + this.setState({ hasError: false, error: null, errorInfo: null }); + }; + + render(): ReactNode { + if (!this.state.hasError) { + return this.props.children; + } + + // 使用自定义 fallback + if (this.props.fallback) { + return this.props.fallback; + } + + // 内置友好错误页面 + return ( +
+
+ {/* 图标 */} +
+ +
+ +

+ 页面出现了错误 +

+

+ 应用遇到了一个意外错误。您可以尝试刷新页面,或点击下方按钮重试。 +

+ + {/* 开发环境:展示错误摘要 */} + {process.env.NODE_ENV !== "production" && this.state.error && ( +
+ + 错误详情(开发模式) + +
+                {this.state.error.message}
+                {this.state.errorInfo?.componentStack}
+              
+
+ )} + +
+ + +
+
+
+ ); + } +} + +export default ErrorBoundary; diff --git a/frontend/components/business/metric-card.tsx b/frontend/components/business/metric-card.tsx index ea220c4..8ae070b 100644 --- a/frontend/components/business/metric-card.tsx +++ b/frontend/components/business/metric-card.tsx @@ -2,7 +2,6 @@ import * as React from "react"; import { cn } from "@/lib/utils"; -import { Card } from "@/components/ui/card"; export type TrendDirection = "up" | "down" | "neutral"; @@ -31,59 +30,6 @@ export interface MetricCardProps extends React.HTMLAttributes { size?: "sm" | "default" | "lg"; } -const TrendArrow = ({ direction }: { direction: TrendDirection }) => { - if (direction === "neutral") return null; - const isUp = direction === "up"; - return ( - - {isUp ? ( - - ) : ( - - )} - - ); -}; - -const Sparkline = ({ data, trend }: { data: SparklinePoint[]; trend?: TrendDirection }) => { - if (!data || data.length < 2) return null; - const max = Math.max(...data.map((d) => d.value)); - const min = Math.min(...data.map((d) => d.value)); - const range = max - min || 1; - const width = 80; - const height = 28; - const points = data.map((d, i) => { - const x = (i / (data.length - 1)) * width; - const y = height - ((d.value - min) / range) * height; - return `${x},${y}`; - }); - const isUp = trend !== "down"; - return ( - - - {/* last dot */} - - - ); -}; - const MetricCard = React.forwardRef( ( { @@ -114,80 +60,64 @@ const MetricCard = React.forwardRef( }[size]; return ( - -
- {/* Label row */} -
-

- {label} -

- {icon && ( -
- {icon} -
+
+ {/* Left color bar */} +
+ /> - {/* Value + sparkline row */} -
-
- - {value} - - {subValue && ( - {subValue} - )} -
- {sparklineData && sparklineData.length >= 2 && ( -
- -
- )} -
- - {/* Trend row */} - {(trendValue || trendLabel) && ( -
+ {/* Content */} +
+ {/* Label row */} +
+

+ {label} +

{trendValue && ( -
- - {trendValue} -
- )} - {trendLabel && ( - {trendLabel} + {trend === "up" && "+"}{trendValue} + )}
- )} -
- {/* subtle background accent */} -
- + {/* Value */} +

+ {value} +

+ + {/* Trend label */} + {trendLabel && ( +

{trendLabel}

+ )} +
+
+
); } ); diff --git a/frontend/components/layout/header.tsx b/frontend/components/layout/header.tsx index e20d385..502f4b2 100644 --- a/frontend/components/layout/header.tsx +++ b/frontend/components/layout/header.tsx @@ -1,30 +1,38 @@ "use client"; -import { useSession, signOut } from "next-auth/react"; -import { Button } from "@/components/ui/button"; -import { LogOut, User } from "lucide-react"; +import { useSession } from "next-auth/react"; +import { Search, Bell } from "lucide-react"; import { AlertBell } from "@/components/layout/alert-bell"; export function Header() { const { data: session } = useSession(); + const userName = session?.user?.name || session?.user?.email || "用户"; + const initials = userName.slice(0, 2).toUpperCase(); return ( -
-

GEO Platform

+
+ {/* Left: Search */} +
+ + +
+ + {/* Right: Actions */}
+ {/* Notification bell */} -
- - {session?.user?.name || session?.user?.email || "用户"} + + {/* User avatar + name */} +
+
+ {initials} +
+ {userName}
-
); diff --git a/frontend/components/layout/side-nav.tsx b/frontend/components/layout/side-nav.tsx index fbb4881..5e3e537 100644 --- a/frontend/components/layout/side-nav.tsx +++ b/frontend/components/layout/side-nav.tsx @@ -20,50 +20,29 @@ export interface NavGroup { items: NavItem[]; } -export interface SideNavUser { - name: string; - email?: string; - avatar?: string; - /** 完成度 0-100 */ - completionPercent?: number; - completionLabel?: string; -} - export interface SideNavProps extends React.HTMLAttributes { - /** 品牌 Logo/名称区域 */ - logo?: React.ReactNode; /** 品牌名 */ brandName?: string; + /** 品牌图标 */ + brandIcon?: React.ReactNode; /** 导航分组 */ groups: NavGroup[]; /** 当前激活的导航项 id */ activeId?: string; /** 导航项点击回调 */ onNavClick?: (item: NavItem) => void; - /** 底部用户信息 */ - user?: SideNavUser; - /** 底部额外操作区 */ - footerExtra?: React.ReactNode; - /** 是否折叠(仅展示图标) */ - collapsed?: boolean; - /** 折叠切换回调 */ - onCollapsedChange?: (collapsed: boolean) => void; - /** "更多工具"分组标签 */ - moreToolsLabel?: string; } -// ─── Sub-components ──────────────────────────────────────────────────────────── +// ─── NavItemRow ─────────────────────────────────────────────────────────────── const NavItemRow = React.memo( ({ item, active, - collapsed, onClick, }: { item: NavItem; active: boolean; - collapsed?: boolean; onClick?: () => void; }) => { return ( @@ -71,28 +50,21 @@ const NavItemRow = React.memo( type="button" disabled={item.disabled} onClick={onClick} - title={collapsed ? item.label : undefined} className={cn( - "group relative flex w-full items-center gap-3 rounded-lg px-3 py-2 text-sm font-medium transition-all duration-200", - "focus-visible:outline-none focus-visible:ring-2 focus-visible:ring-geo-nav-active focus-visible:ring-offset-1 focus-visible:ring-offset-geo-nav", + "group relative flex w-full items-center gap-3 rounded-lg py-2.5 px-4 text-sm font-medium transition-all duration-150", + "focus-visible:outline-none focus-visible:ring-2 focus-visible:ring-emerald-500 focus-visible:ring-offset-1", "disabled:pointer-events-none disabled:opacity-40", active - ? "bg-geo-nav-active/15 text-geo-nav-active" - : "text-white/70 hover:bg-white/8 hover:text-white", - collapsed && "justify-center px-2" + ? "bg-emerald-50 text-emerald-600 font-semibold border-l-[3px] border-emerald-500" + : "text-gray-600 hover:bg-gray-50 border-l-[3px] border-transparent" )} > - {/* active indicator bar */} - {active && ( - - )} - {/* icon */} {item.icon && ( {item.icon} @@ -100,18 +72,16 @@ const NavItemRow = React.memo( )} {/* label */} - {!collapsed && ( - {item.label} - )} + {item.label} {/* badge */} - {!collapsed && item.badge !== undefined && ( + {item.badge !== undefined && ( {item.badge} @@ -123,101 +93,17 @@ const NavItemRow = React.memo( ); NavItemRow.displayName = "NavItemRow"; -// ─── User info footer ────────────────────────────────────────────────────────── - -const UserFooter = ({ - user, - collapsed, -}: { - user: SideNavUser; - collapsed?: boolean; -}) => { - return ( -
- {/* Completion progress bar */} - {!collapsed && user.completionPercent !== undefined && ( -
-
- - {user.completionLabel ?? "Profile Completion"} - - - {user.completionPercent}% - -
-
-
-
-
- )} - - {/* User row */} -
- {/* avatar */} -
- {user.avatar ? ( - {user.name} - ) : ( -
- {user.name.slice(0, 2).toUpperCase()} -
- )} - -
- - {/* user info */} - {!collapsed && ( -
-

{user.name}

- {user.email && ( -

{user.email}

- )} -
- )} - - {/* chevron */} - {!collapsed && ( - - - - )} -
-
- ); -}; - -// ─── Main SideNav ────────────────────────────────────────────────────────────── +// ─── Main SideNav ───────────────────────────────────────────────────────────── const SideNav = React.forwardRef( ( { className, - logo, - brandName = "GEO", + brandName = "GEO Platform", + brandIcon, groups, activeId, onNavClick, - user, - footerExtra, - collapsed = false, - onCollapsedChange, ...props }, ref @@ -226,75 +112,44 @@ const SideNav = React.forwardRef( ); } diff --git a/frontend/components/ui/api-states.tsx b/frontend/components/ui/api-states.tsx new file mode 100644 index 0000000..f7c5c4f --- /dev/null +++ b/frontend/components/ui/api-states.tsx @@ -0,0 +1,137 @@ +"use client"; + +/** + * 统一 API 状态组件 + * - LoadingState: 骨架屏加载状态 + * - ErrorState: 错误展示 + 重试按钮 + * - EmptyState: 空数据状态 + */ + +import { AlertCircle, RefreshCw, Inbox } from "lucide-react"; +import { Button } from "@/components/ui/button"; +import { Skeleton } from "@/components/ui/skeleton"; + +// ── LoadingState ───────────────────────────────────────────────────────────── + +export interface LoadingStateProps { + /** 骨架行数(默认 3) */ + rows?: number; + /** 是否展示卡片网格布局(默认 false,展示列表) */ + grid?: boolean; + /** 网格列数(grid=true 时生效,默认 3) */ + cols?: 2 | 3 | 4; + /** 自定义高度类名(如 "h-24") */ + rowHeight?: string; +} + +export function LoadingState({ + rows = 3, + grid = false, + cols = 3, + rowHeight = "h-24", +}: LoadingStateProps) { + const colClass = { + 2: "md:grid-cols-2", + 3: "md:grid-cols-2 lg:grid-cols-3", + 4: "md:grid-cols-2 lg:grid-cols-4", + }[cols]; + + if (grid) { + return ( +
+ {Array.from({ length: rows }).map((_, i) => ( + + ))} +
+ ); + } + + return ( +
+ {Array.from({ length: rows }).map((_, i) => ( + + ))} +
+ ); +} + +// ── ErrorState ─────────────────────────────────────────────────────────────── + +export interface ErrorStateProps { + /** 错误对象或错误消息字符串 */ + error: Error | string | null | undefined; + /** 点击重试的回调 */ + onRetry?: () => void; + /** 重试按钮文字(默认"重试") */ + retryLabel?: string; + /** 标题(默认"数据加载失败") */ + title?: string; +} + +export function ErrorState({ + error, + onRetry, + retryLabel = "重试", + title = "数据加载失败", +}: ErrorStateProps) { + const message = + error instanceof Error + ? error.message + : typeof error === "string" + ? error + : "发生未知错误,请稍后重试"; + + return ( +
+ +

{title}

+

{message}

+ {onRetry && ( + + )} +
+ ); +} + +// ── EmptyState ─────────────────────────────────────────────────────────────── + +export interface EmptyStateProps { + /** 主提示文字 */ + message?: string; + /** 次级说明文字 */ + description?: string; + /** 操作按钮(可选) */ + action?: React.ReactNode; + /** 自定义图标 */ + icon?: React.ReactNode; +} + +export function EmptyState({ + message = "暂无数据", + description, + action, + icon, +}: EmptyStateProps) { + return ( +
+
+ {icon ?? } +
+

{message}

+ {description && ( +

+ {description} +

+ )} + {action &&
{action}
} +
+ ); +} diff --git a/frontend/components/ui/button.tsx b/frontend/components/ui/button.tsx index 781a4e1..d9bbcd6 100644 --- a/frontend/components/ui/button.tsx +++ b/frontend/components/ui/button.tsx @@ -10,19 +10,19 @@ const buttonVariants = cva( variants: { variant: { default: - "bg-primary text-primary-foreground shadow-sm hover:bg-primary/90 hover:shadow-md hover:-translate-y-px", + "bg-primary text-primary-foreground shadow-sm hover:bg-primary/90 hover:shadow-md", destructive: - "bg-destructive text-destructive-foreground shadow-sm hover:bg-destructive/90 hover:shadow-md hover:-translate-y-px", + "bg-destructive text-destructive-foreground shadow-sm hover:bg-destructive/90 hover:shadow-md", outline: - "border border-border bg-background text-foreground hover:bg-muted hover:border-primary/40 hover:-translate-y-px", + "border border-border bg-background text-foreground hover:bg-muted hover:border-primary/40", secondary: - "bg-muted text-foreground hover:bg-muted/80 hover:-translate-y-px", + "bg-muted text-foreground hover:bg-muted/80", ghost: "text-foreground hover:bg-muted hover:text-foreground", link: "text-primary underline-offset-4 hover:underline p-0 h-auto", accent: - "bg-accent text-accent-foreground shadow-sm hover:bg-accent/90 hover:shadow-md hover:-translate-y-px", + "bg-accent text-accent-foreground shadow-sm hover:bg-accent/90 hover:shadow-md", }, size: { default: "h-10 px-5 py-2.5", diff --git a/frontend/components/ui/card.tsx b/frontend/components/ui/card.tsx index e2501f3..8cfdd2b 100644 --- a/frontend/components/ui/card.tsx +++ b/frontend/components/ui/card.tsx @@ -8,9 +8,9 @@ const cardVariants = cva( { variants: { variant: { - default: "shadow-card hover:shadow-card-hover hover:-translate-y-0.5", + default: "shadow-sm hover:shadow-card-hover hover:border-primary/30", flat: "shadow-none", - elevated: "shadow-md hover:shadow-hover hover:-translate-y-1", + elevated: "shadow-md hover:shadow-lg hover:border-primary/30", ghost: "border-transparent shadow-none bg-transparent", }, padding: { diff --git a/frontend/components/ui/notification-container.tsx b/frontend/components/ui/notification-container.tsx new file mode 100644 index 0000000..f3865a4 --- /dev/null +++ b/frontend/components/ui/notification-container.tsx @@ -0,0 +1,90 @@ +/** + * 全局 Toast/通知 UI 组件 + * + * 从 notification-store 读取通知队列,渲染为浮动通知列表。 + * 放置在 layout 层级,自动显示/消失。 + */ + +"use client"; + +import { X, CheckCircle, AlertTriangle, Info, AlertCircle } from "lucide-react"; +import { useNotificationStore } from "@/lib/stores/notification-store"; +import type { Notification, NotificationType } from "@/lib/stores/notification-store"; +import { cn } from "@/lib/utils"; + +// ── 图标映射 ──────────────────────────────────────────────────────────── + +const ICON_BY_TYPE: Record = { + success: , + error: , + warning: , + info: , +}; + +// ── 样式映射 ──────────────────────────────────────────────────────────── + +const STYLE_BY_TYPE: Record = { + success: "border-emerald-200 bg-emerald-50 text-emerald-800", + error: "border-red-200 bg-red-50 text-red-800", + warning: "border-amber-200 bg-amber-50 text-amber-800", + info: "border-blue-200 bg-blue-50 text-blue-800", +}; + +// ── 单条通知 ──────────────────────────────────────────────────────────── + +function NotificationItem({ + notification, + onRemove, +}: { + notification: Notification; + onRemove: (id: string) => void; +}) { + return ( +
+
{ICON_BY_TYPE[notification.type]}
+
+ {notification.title && ( +

+ {notification.title} +

+ )} +

{notification.message}

+
+ +
+ ); +} + +// ── 通知容器 ──────────────────────────────────────────────────────────── + +export function NotificationContainer() { + const notifications = useNotificationStore((s) => s.notifications); + const removeNotification = useNotificationStore((s) => s.removeNotification); + + if (notifications.length === 0) return null; + + return ( +
+ {notifications.map((notification) => ( +
+ +
+ ))} +
+ ); +} \ No newline at end of file diff --git a/frontend/e2e/tests/login-redirect-system-chrome.spec.ts b/frontend/e2e/tests/login-redirect-system-chrome.spec.ts new file mode 100644 index 0000000..90b14f8 --- /dev/null +++ b/frontend/e2e/tests/login-redirect-system-chrome.spec.ts @@ -0,0 +1,27 @@ +import { test, expect, chromium } from "@playwright/test"; + +const TEST_USER = { + email: "admin@fischer.com", + password: "Admin@123", +}; + +test.use({ + launchOptions: { + executablePath: "/Applications/Google Chrome.app/Contents/MacOS/Google Chrome", + }, +}); + +test.describe("登录跳转测试(系统Chrome)", () => { + test("登录成功后应跳转到dashboard并保持在dashboard", async ({ page }) => { + await page.goto("/login"); + + await page.locator("#email").fill(TEST_USER.email); + await page.locator("#password").fill(TEST_USER.password); + await page.getByRole("button", { name: /登录/ }).click(); + + await expect(page).toHaveURL(/\/dashboard/, { timeout: 15000 }); + await page.waitForTimeout(3000); + await expect(page).toHaveURL(/\/dashboard/); + await expect(page.getByText("Overview", { exact: false })).toBeVisible({ timeout: 10000 }); + }); +}); diff --git a/frontend/e2e/tests/login-redirect.spec.ts b/frontend/e2e/tests/login-redirect.spec.ts new file mode 100644 index 0000000..304e6e1 --- /dev/null +++ b/frontend/e2e/tests/login-redirect.spec.ts @@ -0,0 +1,53 @@ +import { test, expect } from "@playwright/test"; + +const TEST_USER = { + email: "admin@fischer.com", + password: "Admin@123", +}; + +test.describe("登录跳转测试", () => { + test("登录成功后应跳转到dashboard并保持在dashboard", async ({ page }) => { + await page.goto("/login"); + + // 填写登录表单 + await page.locator("#email").fill(TEST_USER.email); + await page.locator("#password").fill(TEST_USER.password); + await page.getByRole("button", { name: /登录/ }).click(); + + // 等待导航到dashboard + await expect(page).toHaveURL(/\/dashboard/, { timeout: 15000 }); + + // 等待页面稳定,确保没有跳回login + await page.waitForTimeout(3000); + await expect(page).toHaveURL(/\/dashboard/); + + // 验证dashboard内容可见 + await expect(page.getByText("Overview", { exact: false })).toBeVisible({ timeout: 10000 }); + }); + + test("登录后应能访问所有dashboard子页面", async ({ page }) => { + await page.goto("/login"); + + await page.locator("#email").fill(TEST_USER.email); + await page.locator("#password").fill(TEST_USER.password); + await page.getByRole("button", { name: /登录/ }).click(); + + await expect(page).toHaveURL(/\/dashboard/, { timeout: 15000 }); + + // 测试各个子页面 + const pages = [ + "/dashboard/analytics", + "/dashboard/knowledge", + "/dashboard/content", + "/dashboard/distribution", + ]; + + for (const url of pages) { + await page.goto(url); + await expect(page).toHaveURL(url, { timeout: 10000 }); + // 确保没有跳回login + await page.waitForTimeout(1000); + await expect(page).not.toHaveURL(/\/login/); + } + }); +}); diff --git a/frontend/lib/api.ts b/frontend/lib/api.ts index 06c8019..a278e39 100644 --- a/frontend/lib/api.ts +++ b/frontend/lib/api.ts @@ -22,6 +22,10 @@ export { contentGenerationApi, distributionApi, analyticsApi, + alertsApi, + brandsApi, + suggestionsApi, + onboardingApi, } from "./api/index"; export type { diff --git a/frontend/lib/api/admin.ts b/frontend/lib/api/admin.ts index 5622be3..4b82b7a 100644 --- a/frontend/lib/api/admin.ts +++ b/frontend/lib/api/admin.ts @@ -1,8 +1,37 @@ import { fetchWithAuth } from "./client"; +export interface AdminStatsData { + total_users: number; + total_queries: number; + total_citations: number; + citation_rate: number; + today_active_users: number; +} + +export interface AdminUser { + id: string; + email: string; + name: string | null; + plan: string; + is_active: boolean; + is_admin: boolean; + email_verified: boolean; + query_count: number; + created_at: string; +} + +export interface AdminUserListResponse { + items: AdminUser[]; + total: number; +} + +export interface AdminActionResponse { + message: string; +} + export const adminApi = { getStats: async (token: string) => - fetchWithAuth("/api/v1/admin/stats", {}, token), + fetchWithAuth("/api/v1/admin/stats", {}, token) as Promise, getUsers: async ( token: string, params?: { skip?: number; limit?: number; search?: string } @@ -15,16 +44,16 @@ export const adminApi = { ) as [string, string][] ).toString() : ""; - return fetchWithAuth(`/api/v1/admin/users${query}`, {}, token); + return fetchWithAuth(`/api/v1/admin/users${query}`, {}, token) as Promise; }, getUserDetail: async (token: string, userId: string) => - fetchWithAuth(`/api/v1/admin/users/${userId}`, {}, token), + fetchWithAuth(`/api/v1/admin/users/${userId}`, {}, token) as Promise, toggleUserActive: async (token: string, userId: string) => fetchWithAuth( `/api/v1/admin/users/${userId}/toggle-active`, { method: "POST" }, token - ), + ) as Promise, updateUserPlan: async (token: string, userId: string, plan: string) => fetchWithAuth( `/api/v1/admin/users/${userId}/update-plan`, @@ -33,5 +62,5 @@ export const adminApi = { body: JSON.stringify({ plan }), }, token - ), + ) as Promise, }; diff --git a/frontend/lib/api/alerts.ts b/frontend/lib/api/alerts.ts new file mode 100644 index 0000000..ceddfe9 --- /dev/null +++ b/frontend/lib/api/alerts.ts @@ -0,0 +1,49 @@ +import { fetchWithAuth } from "./client"; + +function buildQuery(params: Record): string { + const qs = Object.entries(params) + .filter(([, v]) => v !== undefined) + .map(([k, v]) => `${encodeURIComponent(k)}=${encodeURIComponent(String(v))}`) + .join("&"); + return qs ? `?${qs}` : ""; +} + +export const alertsApi = { + /** 获取未读告警数量 */ + getUnreadCount: (token: string) => + fetchWithAuth("/api/v1/alerts/unread-count", {}, token), + + /** 获取告警列表 */ + getAlerts: ( + token: string, + params?: { limit?: number; offset?: number; is_read?: boolean } + ) => fetchWithAuth(`/api/v1/alerts/${buildQuery(params || {})}`, {}, token), + + /** 标记单条告警已读 */ + markRead: (token: string, alertId: string) => + fetchWithAuth(`/api/v1/alerts/${alertId}/read`, { method: "POST" }, token), + + /** 标记所有告警已读 */ + markAllRead: (token: string) => + fetchWithAuth("/api/v1/alerts/read-all", { method: "POST" }, token), + + /** 获取告警设置 */ + getSettings: (token: string, brandId: string) => + fetchWithAuth(`/api/v1/alerts/settings?brand_id=${encodeURIComponent(brandId)}`, {}, token), + + /** 更新告警设置 */ + updateSettings: ( + token: string, + data: Array<{ + brand_id: string; + alert_type: string; + enabled: boolean; + threshold?: number; + }> + ) => + fetchWithAuth( + "/api/v1/alerts/settings", + { method: "PUT", body: JSON.stringify(data) }, + token + ), +}; diff --git a/frontend/lib/api/brands.ts b/frontend/lib/api/brands.ts new file mode 100644 index 0000000..d1f1c69 --- /dev/null +++ b/frontend/lib/api/brands.ts @@ -0,0 +1,89 @@ +import { fetchWithAuth } from "./client"; + +export interface CreateBrandPayload { + name: string; + aliases?: string[]; + website?: string | null; + industry?: string | null; + platforms?: string[]; + frequency?: string; +} + +export interface UpdateBrandPayload { + name?: string; + aliases?: string[]; + website?: string | null; + industry?: string | null; + platforms?: string[]; + frequency?: string; + status?: string; +} + +export interface AddCompetitorPayload { + competitor_brand_id?: string; + competitor_name?: string; + name?: string; + aliases?: string[]; +} + +function buildQuery(params: Record): string { + const qs = Object.entries(params) + .filter(([, v]) => v !== undefined) + .map(([k, v]) => `${encodeURIComponent(k)}=${encodeURIComponent(String(v))}`) + .join("&"); + return qs ? `?${qs}` : ""; +} + +export const brandsApi = { + /** 获取品牌列表 */ + list: (token: string, params?: { limit?: number; offset?: number }) => + fetchWithAuth(`/api/v1/brands/${buildQuery(params || {})}`, {}, token), + + /** 创建品牌 */ + create: (token: string, data: CreateBrandPayload) => + fetchWithAuth("/api/v1/brands/", { method: "POST", body: JSON.stringify(data) }, token), + + /** 更新品牌 */ + update: (token: string, brandId: string, data: UpdateBrandPayload) => + fetchWithAuth( + `/api/v1/brands/${brandId}`, + { method: "PUT", body: JSON.stringify(data) }, + token + ), + + /** 删除品牌 */ + delete: (token: string, brandId: string) => + fetchWithAuth(`/api/v1/brands/${brandId}`, { method: "DELETE" }, token), + + /** 获取品牌详情 */ + getDetail: (token: string, brandId: string) => + fetchWithAuth(`/api/v1/brands/${brandId}`, {}, token), + + /** 立即查询品牌 */ + queryNow: (token: string, brandId: string) => + fetchWithAuth(`/api/v1/brands/${brandId}/query-now`, { method: "POST" }, token), + + /** 添加竞品 */ + addCompetitor: (token: string, brandId: string, data: AddCompetitorPayload) => + fetchWithAuth( + `/api/v1/brands/${brandId}/competitors`, + { method: "POST", body: JSON.stringify(data) }, + token + ), + + /** 删除竞品 */ + deleteCompetitor: (token: string, brandId: string, competitorId: string) => + fetchWithAuth( + `/api/v1/brands/${brandId}/competitors/${competitorId}`, + { method: "DELETE" }, + token + ), + + /** 获取竞品推荐 */ + getCompetitorRecommendations: (token: string, brandId: string) => + fetchWithAuth(`/api/v1/brands/${brandId}/competitor-recommendations`, {}, token), + + /** 获取品牌对比数据 */ + getCompare: (token: string, brandId: string) => + fetchWithAuth(`/api/v1/brands/${brandId}/compare`, {}, token), +}; diff --git a/frontend/lib/api/citations.ts b/frontend/lib/api/citations.ts index 499be34..e7b7c3f 100644 --- a/frontend/lib/api/citations.ts +++ b/frontend/lib/api/citations.ts @@ -1,12 +1,37 @@ import { fetchWithAuth } from "./client"; +export interface CitationRecord { + id: string; + query_id: string; + platform: string; + cited: boolean; + citation_position: number | null; + citation_text: string | null; + competitor_brands: string[]; + confidence: number | null; + match_type: string | null; + queried_at: string; +} + +export interface CitationListResponse { + items: CitationRecord[]; + total: number; +} + +export interface CitationStats { + total_queries: number; + total_citations: number; + citation_rate: number; + avg_position: number | null; +} + export const citationsApi = { list: (token: string, params?: string) => fetchWithAuth( `/api/v1/citations/${params ? `?${params}` : ""}`, {}, token - ), + ) as Promise, getStats: (token: string) => - fetchWithAuth("/api/v1/citations/stats/", {}, token), + fetchWithAuth("/api/v1/citations/stats/", {}, token) as Promise, }; diff --git a/frontend/lib/api/client.ts b/frontend/lib/api/client.ts index 3fcef2c..d214045 100644 --- a/frontend/lib/api/client.ts +++ b/frontend/lib/api/client.ts @@ -1,3 +1,6 @@ +import { getSession } from "next-auth/react"; +import type { Session } from "next-auth"; + export const API_BASE = process.env.NEXT_PUBLIC_API_URL || "http://localhost:8000"; export function getApiUrl(path: string): string { @@ -9,19 +12,28 @@ export async function fetchWithAuth( options: RequestInit = {}, token?: string ) { + // 如果没有显式传入 token,尝试从 NextAuth session 获取 + let authToken = token; + if (!authToken && typeof window !== "undefined") { + try { + const session = await getSession(); + authToken = (session as Session)?.accessToken; + } catch { + // ignore session fetch error + } + } + const headers: Record = { "Content-Type": "application/json", ...((options.headers as Record) || {}), }; - if (token) { - headers["Authorization"] = `Bearer ${token}`; + if (authToken) { + headers["Authorization"] = `Bearer ${authToken}`; } const res = await fetch(`${API_BASE}${url}`, { ...options, headers }); if (res.status === 401) { - if (typeof window !== "undefined") { - window.location.href = "/login"; - } + // 不要自动跳转登录页,让页面组件/layout自行处理认证状态 throw new Error("登录已过期,请重新登录"); } diff --git a/frontend/lib/api/index.ts b/frontend/lib/api/index.ts index 02dad56..134db9c 100644 --- a/frontend/lib/api/index.ts +++ b/frontend/lib/api/index.ts @@ -4,10 +4,13 @@ export { fetchWithAuth, getApiUrl, API_BASE } from "./client"; // ── 各模块 API ───────────────────────────────────────────────────────────────── export { authApi } from "./auth"; export { queriesApi } from "./queries"; +export type { ApiQueryItem, QueryListResponse, CreateQueryPayload, UpdateQueryPayload } from "./queries"; export { citationsApi } from "./citations"; +export type { CitationRecord, CitationListResponse, CitationStats } from "./citations"; export { reportsApi } from "./reports"; export { subscriptionsApi } from "./subscriptions"; export { adminApi } from "./admin"; +export type { AdminStatsData, AdminUser, AdminUserListResponse, AdminActionResponse } from "./admin"; export { agentsApi } from "./agents"; export { lifecycleApi } from "./lifecycle"; export { contentsApi } from "./contents"; @@ -16,6 +19,11 @@ export { knowledgeApi } from "./knowledge"; export { contentGenerationApi } from "./content"; export { distributionApi } from "./distribution"; export { analyticsApi } from "./analytics"; +export { alertsApi } from "./alerts"; +export { brandsApi } from "./brands"; +export type { CreateBrandPayload, UpdateBrandPayload, AddCompetitorPayload } from "./brands"; +export { suggestionsApi } from "./suggestions"; +export { onboardingApi } from "./onboarding"; // ── 类型导出 ─────────────────────────────────────────────────────────────────── export type { Agent, AgentRunLog } from "./agents"; @@ -93,6 +101,10 @@ import { knowledgeApi } from "./knowledge"; import { contentGenerationApi } from "./content"; import { distributionApi } from "./distribution"; import { analyticsApi } from "./analytics"; +import { alertsApi } from "./alerts"; +import { brandsApi } from "./brands"; +import { suggestionsApi } from "./suggestions"; +import { onboardingApi } from "./onboarding"; /** * 聚合 API 对象,保持与原 `import { api } from "@/lib/api"` 的向后兼容。 @@ -113,4 +125,8 @@ export const api = { contentGeneration: contentGenerationApi, distribution: distributionApi, analytics: analyticsApi, + alerts: alertsApi, + brands: brandsApi, + suggestions: suggestionsApi, + onboarding: onboardingApi, }; diff --git a/frontend/lib/api/knowledge.ts b/frontend/lib/api/knowledge.ts index 0fa3413..c004a28 100644 --- a/frontend/lib/api/knowledge.ts +++ b/frontend/lib/api/knowledge.ts @@ -29,7 +29,7 @@ export interface SearchResult { score: number; document_id: string; document_title: string; - metadata: Record; + metadata: Record; } export interface SearchResponse { diff --git a/frontend/lib/api/onboarding.ts b/frontend/lib/api/onboarding.ts new file mode 100644 index 0000000..4d36686 --- /dev/null +++ b/frontend/lib/api/onboarding.ts @@ -0,0 +1,47 @@ +import { fetchWithAuth } from "./client"; + +export const onboardingApi = { + /** 检查引导状态 */ + checkOnboardingStatus: (token: string) => + fetchWithAuth("/api/v1/onboarding/status", {}, token), + + /** 创建引导品牌 */ + createOnboardingBrand: ( + token: string, + data: { + name: string; + competitors: string[]; + platforms: string[]; + frequency: "daily" | "weekly" | "monthly"; + } + ) => + fetchWithAuth( + "/api/v1/onboarding/brand", + { method: "POST", body: JSON.stringify(data) }, + token + ), + + /** 获取竞品推荐 */ + getCompetitorRecommendations: (token: string, brandName: string) => + fetchWithAuth( + `/api/v1/onboarding/competitor-recommendations?brand_name=${encodeURIComponent(brandName)}`, + {}, + token + ), + + /** 获取健康报告 */ + getHealthReport: (token: string, brandId: string) => + fetchWithAuth(`/api/v1/onboarding/health-report/${brandId}`, {}, token), + + /** 获取行动建议 */ + getActionSuggestions: (token: string, brandId: string) => + fetchWithAuth(`/api/v1/onboarding/action-suggestions/${brandId}`, {}, token), + + /** 完成引导 */ + completeOnboarding: (token: string, brandId: string) => + fetchWithAuth( + `/api/v1/onboarding/complete/${brandId}`, + { method: "POST" }, + token + ), +}; diff --git a/frontend/lib/api/queries.ts b/frontend/lib/api/queries.ts index 5e2fabf..256b81f 100644 --- a/frontend/lib/api/queries.ts +++ b/frontend/lib/api/queries.ts @@ -1,19 +1,52 @@ import { fetchWithAuth } from "./client"; +export interface CreateQueryPayload { + keyword: string; + brand_id?: string; + platforms?: string[]; + frequency?: string; +} + +export interface UpdateQueryPayload { + keyword?: string; + platforms?: string[]; + frequency?: string; + is_active?: boolean; +} + +export interface ApiQueryItem { + id: string; + keyword: string; + target_brand: string; + brand_id?: string; + brand_aliases?: string[]; + platforms: string[]; + frequency: string; + is_active: boolean; + status: string; + last_queried_at: string | null; + created_at: string; +} + +export interface QueryListResponse { + items: ApiQueryItem[]; + total: number; +} + export const queriesApi = { - list: (token: string) => fetchWithAuth("/api/v1/queries/", {}, token), - create: (token: string, data: unknown) => + list: (token: string) => fetchWithAuth("/api/v1/queries/", {}, token) as Promise, + create: (token: string, data: CreateQueryPayload) => fetchWithAuth( "/api/v1/queries/", { method: "POST", body: JSON.stringify(data) }, token - ), - update: (token: string, id: string, data: unknown) => + ) as Promise, + update: (token: string, id: string, data: UpdateQueryPayload) => fetchWithAuth( `/api/v1/queries/${id}`, { method: "PUT", body: JSON.stringify(data) }, token - ), + ) as Promise, delete: (token: string, id: string) => fetchWithAuth(`/api/v1/queries/${id}`, { method: "DELETE" }, token), runNow: (token: string, id: string) => diff --git a/frontend/lib/api/suggestions.ts b/frontend/lib/api/suggestions.ts new file mode 100644 index 0000000..1fedf05 --- /dev/null +++ b/frontend/lib/api/suggestions.ts @@ -0,0 +1,44 @@ +import { fetchWithAuth } from "./client"; + +function buildQuery(params: Record): string { + const qs = Object.entries(params) + .filter(([, v]) => v !== undefined) + .map(([k, v]) => `${encodeURIComponent(k)}=${encodeURIComponent(String(v))}`) + .join("&"); + return qs ? `?${qs}` : ""; +} + +export const suggestionsApi = { + /** 获取建议列表 */ + getSuggestions: ( + token: string, + brandId: string, + params?: Record + ) => + fetchWithAuth( + `/api/v1/suggestions/${brandId}${buildQuery(params || {})}`, + {}, + token + ), + + /** 重新生成建议 */ + regenerateSuggestions: (token: string, brandId: string) => + fetchWithAuth( + `/api/v1/suggestions/${brandId}/regenerate`, + { method: "POST" }, + token + ), + + /** 更新建议状态 */ + updateSuggestionStatus: ( + token: string, + brandId: string, + suggestionId: string, + status: string + ) => + fetchWithAuth( + `/api/v1/suggestions/${brandId}/${suggestionId}/status`, + { method: "PUT", body: JSON.stringify({ status }) }, + token + ), +}; diff --git a/frontend/lib/auth.ts b/frontend/lib/auth.ts index dd44123..a12ed6c 100644 --- a/frontend/lib/auth.ts +++ b/frontend/lib/auth.ts @@ -2,6 +2,38 @@ import { NextAuthOptions } from "next-auth"; import CredentialsProvider from "next-auth/providers/credentials"; import { api } from "@/lib/api"; +/** 尝试使用 refresh token 获取新的 access token */ +async function refreshAccessToken(token: Record) { + try { + const backendUrl = process.env.NEXT_PUBLIC_API_URL || "http://localhost:8000"; + const res = await fetch(`${backendUrl}/api/v1/auth/refresh`, { + method: "POST", + headers: { "Content-Type": "application/json" }, + body: JSON.stringify({ refresh_token: token.refreshToken }), + }); + + if (!res.ok) { + throw new Error(`Refresh failed: ${res.status}`); + } + + const data = await res.json(); + return { + ...token, + accessToken: data.access_token, + refreshToken: data.refresh_token, // 滑动过期:更新为新 refresh token + // 新 access token 有效期 1 小时 + expires_at: Date.now() + 60 * 60 * 1000, + error: undefined, + }; + } catch (error) { + // 刷新失败:标记错误,让前端展示重新登录 + return { + ...token, + error: "RefreshAccessTokenError", + }; + } +} + export const authOptions: NextAuthOptions = { providers: [ CredentialsProvider({ @@ -11,9 +43,7 @@ export const authOptions: NextAuthOptions = { password: { label: "密码", type: "password" }, }, async authorize(credentials) { - console.log("[NextAuth] authorize called with email:", credentials?.email); if (!credentials?.email || !credentials?.password) { - console.log("[NextAuth] missing credentials"); return null; } try { @@ -21,27 +51,19 @@ export const authOptions: NextAuthOptions = { email: credentials.email, password: credentials.password, }); - console.log("[NextAuth] login response:", JSON.stringify({ - hasAccessToken: !!res.access_token, - userId: res.user?.id, - userEmail: res.user?.email, - isAdmin: res.user?.is_admin, - })); if (res.access_token) { const user = { id: res.user?.id || credentials.email, name: res.user?.name, email: res.user?.email, accessToken: res.access_token, + refreshToken: res.refresh_token, is_admin: res.user?.is_admin || false, }; - console.log("[NextAuth] returning user:", JSON.stringify(user)); return user; } - console.log("[NextAuth] no access_token in response"); return null; } catch (error) { - console.error("[NextAuth] authorize error:", error); return null; } }, @@ -52,17 +74,35 @@ export const authOptions: NextAuthOptions = { }, callbacks: { async jwt({ token, user }) { + // 初次登录:将用户信息写入 token if (user) { + token.sub = user.id; token.accessToken = user.accessToken; + token.refreshToken = (user as unknown as Record).refreshToken as string; token.id = user.id; - token.is_admin = user.is_admin; + token.is_admin = (user as unknown as Record).is_admin as boolean; + // access token 有效期 1 小时 + token.expires_at = Date.now() + 60 * 60 * 1000; + return token; } + + // 后续请求:检查 access token 是否即将过期(提前 5 分钟刷新) + const expiresAt = token.expires_at as number | undefined; + if (expiresAt && expiresAt < Date.now() + 5 * 60 * 1000) { + return refreshAccessToken(token as Record); + } + return token; }, async session({ session, token }) { session.accessToken = token.accessToken as string; - session.user.id = token.id as string; - session.user.is_admin = token.is_admin as boolean; + session.refreshToken = token.refreshToken as string; + // 将 refresh 失败错误传递给前端,以便触发重新登录 + session.error = token.error as string | undefined; + if (session.user) { + session.user.id = token.id as string; + session.user.is_admin = token.is_admin as boolean; + } return session; }, }, diff --git a/frontend/lib/hooks/use-api.ts b/frontend/lib/hooks/use-api.ts new file mode 100644 index 0000000..be72d41 --- /dev/null +++ b/frontend/lib/hooks/use-api.ts @@ -0,0 +1,171 @@ +/** + * 通用 SWR Hooks + * 封装 useSWR + fetchWithAuth,统一处理加载/错误/重试逻辑 + */ + +import useSWR, { type SWRConfiguration, type KeyedMutator } from "swr"; +import { useCallback, useState } from "react"; +import { fetchWithAuth } from "@/lib/api/client"; + +// ── 类型定义 ──────────────────────────────────────────────────────────────────── + +export interface UseApiReturn { + data: T | undefined; + isLoading: boolean; + error: Error | undefined; + mutate: KeyedMutator; + /** 手动重新获取数据 */ + refresh: () => void; +} + +export interface UsePaginatedApiReturn extends UseApiReturn { + total: number; + page: number; + pageSize: number; + setPage: (page: number) => void; +} + +export interface UseApiMutationReturn { + trigger: (body?: B) => Promise; + isMutating: boolean; + error: Error | undefined; + reset: () => void; +} + +// ── SWR 全局 Fetcher ───────────────────────────────────────────────────────── + +/** + * 基于 fetchWithAuth 的 SWR fetcher + * key 格式:url string 或 [url, token] + */ +export async function swrFetcher(url: string): Promise { + return fetchWithAuth(url) as Promise; +} + +// ── 主 Hook ────────────────────────────────────────────────────────────────── + +/** + * 基础数据获取 Hook + * @param url API 路径(null 时暂停请求) + * @param options SWR 配置项 + */ +export function useApi( + url: string | null, + options?: SWRConfiguration +): UseApiReturn { + const { data, error, isLoading, mutate } = useSWR( + url, + swrFetcher, + { + revalidateOnFocus: false, + shouldRetryOnError: true, + errorRetryCount: 2, + errorRetryInterval: 3000, + ...options, + } + ); + + const refresh = useCallback(() => { + mutate(); + }, [mutate]); + + return { + data, + isLoading, + error: error as Error | undefined, + mutate, + refresh, + }; +} + +// ── 分页 Hook ──────────────────────────────────────────────────────────────── + +export interface PaginatedResponse { + items: T[]; + total: number; +} + +/** + * 支持分页的数据获取 Hook + * @param baseUrl 基础 API 路径(不含分页参数) + * @param params 分页参数 + */ +export function usePaginatedApi( + baseUrl: string | null, + params: { page: number; pageSize: number } +): UsePaginatedApiReturn { + const [page, setPage] = useState(params.page); + const { pageSize } = params; + + const url = baseUrl + ? `${baseUrl}?limit=${pageSize}&offset=${(page - 1) * pageSize}` + : null; + + const { data, error, isLoading, mutate } = useSWR>( + url, + swrFetcher>, + { + revalidateOnFocus: false, + shouldRetryOnError: true, + errorRetryCount: 2, + } + ); + + const refresh = useCallback(() => { + mutate(); + }, [mutate]); + + return { + data: data?.items, + total: data?.total ?? 0, + isLoading, + error: error as Error | undefined, + mutate: mutate as unknown as KeyedMutator, + refresh, + page, + pageSize, + setPage, + }; +} + +// ── Mutation Hook ──────────────────────────────────────────────────────────── + +/** + * API 数据变更 Hook(POST / PUT / DELETE) + * @param url API 路径 + * @param method HTTP 方法(默认 POST) + */ +export function useApiMutation( + url: string, + method: string = "POST" +): UseApiMutationReturn { + const [isMutating, setIsMutating] = useState(false); + const [error, setError] = useState(undefined); + + const trigger = useCallback( + async (body?: B): Promise => { + try { + setIsMutating(true); + setError(undefined); + const result = await fetchWithAuth(url, { + method, + body: body !== undefined ? JSON.stringify(body) : undefined, + }) as T; + return result; + } catch (err) { + const e = err instanceof Error ? err : new Error(String(err)); + setError(e); + return null; + } finally { + setIsMutating(false); + } + }, + [url, method] + ); + + const reset = useCallback(() => { + setError(undefined); + }, []); + + return { trigger, isMutating, error, reset }; +} diff --git a/frontend/lib/stores/brand-store.ts b/frontend/lib/stores/brand-store.ts new file mode 100644 index 0000000..1ea70ce --- /dev/null +++ b/frontend/lib/stores/brand-store.ts @@ -0,0 +1,306 @@ +/** + * 品牌全局状态 Store (Zustand) + * + * 与 SWR 互补: + * - SWR 管理服务端缓存(品牌列表数据获取、缓存、重验证) + * - 此 Store 管理客户端侧状态: + * 1. 当前选中品牌(跨页面共享) + * 2. 乐观更新(操作先更新本地,API 失败再回滚) + * 3. 品牌列表的本地增删(配合 SWR mutate) + */ + +import { create } from "zustand"; +import { fetchWithAuth } from "@/lib/api/client"; +import { brandsApi } from "@/lib/api/brands"; +import type { + BrandListItem, + BrandListResponse, +} from "@/types/brand"; +import type { CreateBrandPayload, UpdateBrandPayload } from "@/lib/api/brands"; +import { useNotificationStore } from "./notification-store"; + +// ── 类型定义 ──────────────────────────────────────────────────────────────────── + +export interface BrandState { + /** 当前选中品牌 ID */ + selectedBrandId: string | null; + /** 当前选中品牌名称(方便 UI 直接显示) */ + selectedBrandName: string | null; + /** 品牌列表本地副本(用于乐观更新时的临时状态) */ + localBrands: BrandListItem[]; + /** 正在进行乐观更新的操作类型 */ + optimisticAction: "creating" | "updating" | "deleting" | null; +} + +export interface BrandActions { + /** 选中品牌 */ + selectBrand: (brandId: string, brandName?: string) => void; + /** 清除选中品牌 */ + clearSelection: () => void; + /** 从 SWR 数据同步品牌列表到本地副本 */ + syncFromSWR: (brands: BrandListItem[]) => void; + + // ── 乐观更新操作 ────────────────────────────────────────────────────────── + /** + * 乐观创建品牌: + * 1. 先在本地列表添加临时条目 + * 2. 异步调用 API + * 3. 成功 → 用真实数据替换临时条目(配合 SWR mutate) + * 4. 失败 → 回滚本地列表,显示错误通知 + */ + optimisticCreate: ( + token: string, + payload: CreateBrandPayload, + /** SWR mutate 回调,用于刷新服务端缓存 */ + swrMutate?: () => void, + ) => Promise; + + /** + * 乐观更新品牌: + * 1. 先在本地列表更新条目 + * 2. 异步调用 API + * 3. 成功 → 配合 SWR mutate + * 4. 失败 → 回滚本地列表 + */ + optimisticUpdate: ( + token: string, + brandId: string, + payload: UpdateBrandPayload, + swrMutate?: () => void, + ) => Promise; + + /** + * 乐观删除品牌: + * 1. 先从本地列表移除条目 + * 2. 异步调用 API + * 3. 成功 → 配合 SWR mutate + * 4. 失败 → 恢复本地列表条目 + */ + optimisticDelete: ( + token: string, + brandId: string, + swrMutate?: () => void, + ) => Promise; +} + +// ── 辅助 ──────────────────────────────────────────────────────────────────────── + +/** 生成临时 ID(乐观创建用) */ +function generateTempId(): string { + return `temp-${Date.now()}-${Math.random().toString(36).slice(2, 8)}`; +} + +// ── 默认值 ────────────────────────────────────────────────────────────────────── + +const INITIAL_STATE: BrandState = { + selectedBrandId: null, + selectedBrandName: null, + localBrands: [], + optimisticAction: null, +}; + +// ── Store ─────────────────────────────────────────────────────────────────────── + +export const useBrandStore = create()((set, get) => ({ + ...INITIAL_STATE, + + selectBrand: (brandId, brandName) => { + set({ + selectedBrandId: brandId, + selectedBrandName: brandName ?? null, + }); + }, + + clearSelection: () => { + set({ selectedBrandId: null, selectedBrandName: null }); + }, + + syncFromSWR: (brands) => { + set({ localBrands: brands }); + }, + + // ── 乐观创建 ──────────────────────────────────────────────────────────── + optimisticCreate: async (token, payload, swrMutate) => { + const { localBrands } = get(); + const notificationStore = useNotificationStore.getState(); + + // 1. 创建临时条目 + const tempBrand: BrandListItem = { + id: generateTempId(), + name: payload.name, + aliases: payload.aliases ?? [], + platforms: payload.platforms ?? [], + frequency: (payload.frequency ?? "weekly") as BrandListItem["frequency"], + status: "pending", + score: null, + last_queried_at: null, + next_query_at: null, + created_at: new Date().toISOString(), + }; + + set({ + localBrands: [...localBrands, tempBrand], + optimisticAction: "creating", + }); + + // 2. 异步调用 API + try { + const created = await brandsApi.create(token, payload as CreateBrandPayload) as BrandListItem; + + // 3. 成功 → 用真实数据替换临时条目 + set((state) => ({ + localBrands: state.localBrands.map((b) => + b.id === tempBrand.id ? created : b + ), + optimisticAction: null, + })); + + notificationStore.addNotification({ + type: "success", + message: `品牌「${created.name}」创建成功`, + }); + + // 触发 SWR 重新获取,保证服务端缓存同步 + swrMutate?.(); + + return created; + } catch (err) { + // 4. 失败 → 回滚 + set((state) => ({ + localBrands: state.localBrands.filter((b) => b.id !== tempBrand.id), + optimisticAction: null, + })); + + const message = err instanceof Error ? err.message : "创建品牌失败"; + notificationStore.addNotification({ type: "error", message }); + + return null; + } + }, + + // ── 乐观更新 ──────────────────────────────────────────────────────────── + optimisticUpdate: async (token, brandId, payload, swrMutate) => { + const { localBrands } = get(); + const notificationStore = useNotificationStore.getState(); + + // 1. 保存原始数据用于回滚 + const originalBrand = localBrands.find((b) => b.id === brandId); + if (!originalBrand) { + // 本地没有此品牌,无法乐观更新,直接走 API + try { + const updated = await brandsApi.update(token, brandId, payload as UpdateBrandPayload) as BrandListItem; + swrMutate?.(); + return updated; + } catch (err) { + const message = err instanceof Error ? err.message : "更新品牌失败"; + notificationStore.addNotification({ type: "error", message }); + return null; + } + } + + // 2. 乐观更新本地列表 + const optimisticBrand = { + ...originalBrand, + ...payload, + id: brandId, // 确保 ID 不被覆盖 + } as BrandListItem; + + set({ + localBrands: localBrands.map((b) => + b.id === brandId ? optimisticBrand : b + ), + optimisticAction: "updating", + }); + + // 3. 异步调用 API + try { + const updated = await brandsApi.update(token, brandId, payload as UpdateBrandPayload) as BrandListItem; + + set({ + localBrands: get().localBrands.map((b) => + b.id === brandId ? updated : b + ), + optimisticAction: null, + }); + + notificationStore.addNotification({ + type: "success", + message: `品牌「${updated.name}」更新成功`, + }); + + swrMutate?.(); + + return updated; + } catch (err) { + // 4. 失败 → 回滚到原始数据 + set((state) => ({ + localBrands: state.localBrands.map((b) => + b.id === brandId ? originalBrand : b + ), + optimisticAction: null, + })); + + const message = err instanceof Error ? err.message : "更新品牌失败"; + notificationStore.addNotification({ type: "error", message }); + + return null; + } + }, + + // ── 乐观删除 ──────────────────────────────────────────────────────────── + optimisticDelete: async (token, brandId, swrMutate) => { + const { localBrands, selectedBrandId } = get(); + const notificationStore = useNotificationStore.getState(); + + // 1. 保存原始数据用于回滚 + const originalBrand = localBrands.find((b) => b.id === brandId); + if (!originalBrand) { + // 本地没有此品牌,直接走 API + try { + await brandsApi.delete(token, brandId); + swrMutate?.(); + return true; + } catch (err) { + const message = err instanceof Error ? err.message : "删除品牌失败"; + notificationStore.addNotification({ type: "error", message }); + return false; + } + } + + // 2. 乐观删除:从本地列表移除 + set({ + localBrands: localBrands.filter((b) => b.id !== brandId), + optimisticAction: "deleting", + // 如果删除的是当前选中品牌,清除选择 + selectedBrandId: selectedBrandId === brandId ? null : selectedBrandId, + selectedBrandName: selectedBrandId === brandId ? null : get().selectedBrandName, + }); + + // 3. 异步调用 API + try { + await brandsApi.delete(token, brandId); + + set({ optimisticAction: null }); + + notificationStore.addNotification({ + type: "success", + message: `品牌「${originalBrand.name}」已删除`, + }); + + swrMutate?.(); + + return true; + } catch (err) { + // 4. 失败 → 恢复原始条目 + set((state) => ({ + localBrands: [...state.localBrands, originalBrand], + optimisticAction: null, + })); + + const message = err instanceof Error ? err.message : "删除品牌失败"; + notificationStore.addNotification({ type: "error", message }); + + return false; + } + }, +})); \ No newline at end of file diff --git a/frontend/lib/stores/index.ts b/frontend/lib/stores/index.ts new file mode 100644 index 0000000..83ba7bc --- /dev/null +++ b/frontend/lib/stores/index.ts @@ -0,0 +1,30 @@ +/** + * Zustand Stores 统一导出 + * + * 使用方式: + * import { useUserStore, useBrandStore, useNotificationStore } from "@/lib/stores"; + */ + +// ── Stores ────────────────────────────────────────────────────────────────── +export { useUserStore } from "./user-store"; +export { useBrandStore } from "./brand-store"; +export { useNotificationStore } from "./notification-store"; + +// ── 类型导出 ──────────────────────────────────────────────────────────────── +export type { + UserPreferences, + UserState, + UserActions, +} from "./user-store"; + +export type { + BrandState, + BrandActions, +} from "./brand-store"; + +export type { + Notification, + NotificationType, + NotificationState, + NotificationActions, +} from "./notification-store"; \ No newline at end of file diff --git a/frontend/lib/stores/notification-store.ts b/frontend/lib/stores/notification-store.ts new file mode 100644 index 0000000..4f400ec --- /dev/null +++ b/frontend/lib/stores/notification-store.ts @@ -0,0 +1,134 @@ +/** + * 全局通知/Toast 状态 Store (Zustand) + * + * 管理应用全局的 toast / 通知队列: + * - 添加通知(支持 success / error / warning / info) + * - 自动过期清除 + * - 手动移除 + */ + +import { create } from "zustand"; + +// ── 类型定义 ──────────────────────────────────────────────────────────── + +export type NotificationType = "success" | "error" | "warning" | "info"; + +export interface Notification { + /** 通知唯一 ID */ + id: string; + /** 通知类型 */ + type: NotificationType; + /** 通知消息 */ + message: string; + /** 通知标题(可选) */ + title?: string; + /** 创建时间戳 */ + createdAt: number; + /** 自动过期时间(毫秒),null 表示不自动过期 */ + duration: number | null; +} + +export interface NotificationState { + /** 当前通知队列 */ + notifications: Notification[]; +} + +export interface NotificationActions { + /** 添加一条通知 */ + addNotification: (payload: { + type: NotificationType; + message: string; + title?: string; + /** 自定义过期时间(毫秒),默认按 type 自动设置 */ + duration?: number | null; + }) => string; + + /** 移除一条通知 */ + removeNotification: (id: string) => void; + + /** 清空所有通知 */ + clearAll: () => void; +} + +// ── 默认过期时间 ──────────────────────────────────────────────────────── + +const DEFAULT_DURATION_BY_TYPE: Record = { + success: 3000, + error: 5000, + warning: 4000, + info: 3000, +}; + +// ── 辅助 ──────────────────────────────────────────────────────────────────── + +/** 生成通知 ID */ +function generateNotificationId(): string { + return `notif-${Date.now()}-${Math.random().toString(36).slice(2, 6)}`; +} + +/** 定时器映射,避免重复 */ +const timers = new Map>(); + +// ── 默认值 ────────────────────────────────────────────────────────────────── + +const INITIAL_STATE: NotificationState = { + notifications: [], +}; + +// ── Store ─────────────────────────────────────────────────────────────────── + +export const useNotificationStore = create()( + (set, get) => ({ + ...INITIAL_STATE, + + addNotification: ({ type, message, title, duration }) => { + const id = generateNotificationId(); + const effectiveDuration = duration ?? DEFAULT_DURATION_BY_TYPE[type]; + + const notification: Notification = { + id, + type, + message, + title, + createdAt: Date.now(), + duration: effectiveDuration, + }; + + set((state) => ({ + notifications: [...state.notifications, notification], + })); + + // 设置自动过期 + if (effectiveDuration !== null) { + const timer = setTimeout(() => { + get().removeNotification(id); + timers.delete(id); + }, effectiveDuration); + timers.set(id, timer); + } + + return id; + }, + + removeNotification: (id) => { + // 清除定时器 + const timer = timers.get(id); + if (timer) { + clearTimeout(timer); + timers.delete(id); + } + + set((state) => ({ + notifications: state.notifications.filter((n) => n.id !== id), + })); + }, + + clearAll: () => { + // 清除所有定时器 + timers.forEach((timer) => clearTimeout(timer)); + timers.clear(); + + set({ notifications: [] }); + }, + }) +); \ No newline at end of file diff --git a/frontend/lib/stores/user-store.ts b/frontend/lib/stores/user-store.ts new file mode 100644 index 0000000..674dd2b --- /dev/null +++ b/frontend/lib/stores/user-store.ts @@ -0,0 +1,104 @@ +/** + * 用户全局状态 Store (Zustand) + * + * 与 NextAuth Session 互补: + * - Session 由 next-auth 管理,负责认证流程 + * - 此 Store 管理客户端侧的用户偏好和 UI 状态 + * - 通过 syncFromSession 将 session 数据同步到 store + */ + +import { create } from "zustand"; +import type { Session } from "next-auth"; + +// ── 类型定义 ──────────────────────────────────────────────────────────────────── + +export interface UserPreferences { + /** 侧边栏是否折叠 */ + sidebarCollapsed: boolean; + /** 默认查询频率偏好 */ + defaultFrequency: "daily" | "weekly" | "monthly"; + /** 主题偏好(预留) */ + theme: "light" | "dark" | "system"; +} + +export interface UserState { + /** 当前用户 ID(从 session 同步) */ + userId: string | null; + /** 用户名 */ + userName: string | null; + /** 用户邮箱 */ + userEmail: string | null; + /** 是否管理员 */ + isAdmin: boolean; + /** 是否已认证 */ + isAuthenticated: boolean; + /** 用户偏好设置 */ + preferences: UserPreferences; +} + +export interface UserActions { + /** 从 NextAuth session 同步用户信息 */ + syncFromSession: (session: Session | null) => void; + /** 清除用户状态(登出时调用) */ + clear: () => void; + /** 更新偏好设置(部分更新) */ + updatePreferences: (patch: Partial) => void; + /** 切换侧边栏折叠状态 */ + toggleSidebar: () => void; +} + +// ── 默认值 ────────────────────────────────────────────────────────────────────── + +const DEFAULT_PREFERENCES: UserPreferences = { + sidebarCollapsed: false, + defaultFrequency: "weekly", + theme: "light", +}; + +const INITIAL_STATE: UserState = { + userId: null, + userName: null, + userEmail: null, + isAdmin: false, + isAuthenticated: false, + preferences: DEFAULT_PREFERENCES, +}; + +// ── Store ─────────────────────────────────────────────────────────────────────── + +export const useUserStore = create()((set) => ({ + ...INITIAL_STATE, + + syncFromSession: (session) => { + if (!session || !session.user) { + set(INITIAL_STATE); + return; + } + set({ + userId: session.user.id, + userName: session.user.name ?? null, + userEmail: session.user.email ?? null, + isAdmin: session.user.is_admin ?? false, + isAuthenticated: true, + }); + }, + + clear: () => { + set(INITIAL_STATE); + }, + + updatePreferences: (patch) => { + set((state) => ({ + preferences: { ...state.preferences, ...patch }, + })); + }, + + toggleSidebar: () => { + set((state) => ({ + preferences: { + ...state.preferences, + sidebarCollapsed: !state.preferences.sidebarCollapsed, + }, + })); + }, +})); \ No newline at end of file diff --git a/frontend/next.config.mjs b/frontend/next.config.mjs index 4678774..e25a6a2 100644 --- a/frontend/next.config.mjs +++ b/frontend/next.config.mjs @@ -1,4 +1,6 @@ /** @type {import('next').NextConfig} */ -const nextConfig = {}; +const nextConfig = { + output: 'standalone', +}; export default nextConfig; diff --git a/frontend/package-lock.json b/frontend/package-lock.json index 812cd8e..7ba922b 100644 --- a/frontend/package-lock.json +++ b/frontend/package-lock.json @@ -23,21 +23,36 @@ "react": "^18", "react-dom": "^18", "recharts": "^2.15.4", + "swr": "^2.4.1", "tailwind-merge": "^3.5.0", - "tailwindcss-animate": "^1.0.7" + "tailwindcss-animate": "^1.0.7", + "zustand": "^5.0.13" }, "devDependencies": { - "@playwright/test": "^1.59.1", + "@playwright/test": "^1.60.0", + "@testing-library/jest-dom": "^6.9.1", + "@testing-library/react": "^16.3.2", "@types/node": "^20", "@types/react": "^18", "@types/react-dom": "^18", + "@vitejs/plugin-react": "^6.0.2", + "@vitest/coverage-v8": "^4.1.7", "eslint": "^8", "eslint-config-next": "14.2.35", + "jsdom": "^29.1.1", "postcss": "^8", "tailwindcss": "^3.4.1", - "typescript": "^5" + "typescript": "^5", + "vitest": "^4.1.7" } }, + "node_modules/@adobe/css-tools": { + "version": "4.5.0", + "resolved": "https://registry.npmmirror.com/@adobe/css-tools/-/css-tools-4.5.0.tgz", + "integrity": "sha512-6OzddxPio9UiWTCemp4N8cYLV2ZN1ncRnV1cVGtve7dhPOtRkleRyx32GQCYSwDYgaHU3USMm84tNsvKzRCa1Q==", + "dev": true, + "license": "MIT" + }, "node_modules/@alloc/quick-lru": { "version": "5.2.0", "resolved": "https://registry.npmmirror.com/@alloc/quick-lru/-/quick-lru-5.2.0.tgz", @@ -50,6 +65,109 @@ "url": "https://github.com/sponsors/sindresorhus" } }, + "node_modules/@asamuzakjp/css-color": { + "version": "5.1.11", + "resolved": "https://registry.npmmirror.com/@asamuzakjp/css-color/-/css-color-5.1.11.tgz", + "integrity": "sha512-KVw6qIiCTUQhByfTd78h2yD1/00waTmm9uy/R7Ck/ctUyAPj+AEDLkQIdJW0T8+qGgj3j5bpNKK7Q3G+LedJWg==", + "dev": true, + "license": "MIT", + "dependencies": { + "@asamuzakjp/generational-cache": "^1.0.1", + "@csstools/css-calc": "^3.2.0", + "@csstools/css-color-parser": "^4.1.0", + "@csstools/css-parser-algorithms": "^4.0.0", + "@csstools/css-tokenizer": "^4.0.0" + }, + "engines": { + "node": "^20.19.0 || ^22.12.0 || >=24.0.0" + } + }, + "node_modules/@asamuzakjp/dom-selector": { + "version": "7.1.1", + "resolved": "https://registry.npmmirror.com/@asamuzakjp/dom-selector/-/dom-selector-7.1.1.tgz", + "integrity": "sha512-67RZDnYRc8H/8MLDgQCDE//zoqVFwajkepHZgmXrbwybzXOEwOWGPYGmALYl9J2DOLfFPPs6kKCqmbzV895hTQ==", + "dev": true, + "license": "MIT", + "dependencies": { + "@asamuzakjp/generational-cache": "^1.0.1", + "@asamuzakjp/nwsapi": "^2.3.9", + "bidi-js": "^1.0.3", + "css-tree": "^3.2.1", + "is-potential-custom-element-name": "^1.0.1" + }, + "engines": { + "node": "^20.19.0 || ^22.12.0 || >=24.0.0" + } + }, + "node_modules/@asamuzakjp/generational-cache": { + "version": "1.0.1", + "resolved": "https://registry.npmmirror.com/@asamuzakjp/generational-cache/-/generational-cache-1.0.1.tgz", + "integrity": "sha512-wajfB8KqzMCN2KGNFdLkReeHncd0AslUSrvHVvvYWuU8ghncRJoA50kT3zP9MVL0+9g4/67H+cdvBskj9THPzg==", + "dev": true, + "license": "MIT", + "engines": { + "node": "^20.19.0 || ^22.12.0 || >=24.0.0" + } + }, + "node_modules/@asamuzakjp/nwsapi": { + "version": "2.3.9", + "resolved": "https://registry.npmmirror.com/@asamuzakjp/nwsapi/-/nwsapi-2.3.9.tgz", + "integrity": "sha512-n8GuYSrI9bF7FFZ/SjhwevlHc8xaVlb/7HmHelnc/PZXBD2ZR49NnN9sMMuDdEGPeeRQ5d0hqlSlEpgCX3Wl0Q==", + "dev": true, + "license": "MIT" + }, + "node_modules/@babel/code-frame": { + "version": "7.29.0", + "resolved": "https://registry.npmmirror.com/@babel/code-frame/-/code-frame-7.29.0.tgz", + "integrity": "sha512-9NhCeYjq9+3uxgdtp20LSiJXJvN0FeCtNGpJxuMFZ1Kv3cWUNb6DOhJwUvcVCzKGR66cw4njwM6hrJLqgOwbcw==", + "dev": true, + "license": "MIT", + "peer": true, + "dependencies": { + "@babel/helper-validator-identifier": "^7.28.5", + "js-tokens": "^4.0.0", + "picocolors": "^1.1.1" + }, + "engines": { + "node": ">=6.9.0" + } + }, + "node_modules/@babel/helper-string-parser": { + "version": "7.27.1", + "resolved": "https://registry.npmmirror.com/@babel/helper-string-parser/-/helper-string-parser-7.27.1.tgz", + "integrity": "sha512-qMlSxKbpRlAridDExk92nSobyDdpPijUq2DW6oDnUqd0iOGxmQjyqhMIihI9+zv4LPyZdRje2cavWPbCbWm3eA==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=6.9.0" + } + }, + "node_modules/@babel/helper-validator-identifier": { + "version": "7.28.5", + "resolved": "https://registry.npmmirror.com/@babel/helper-validator-identifier/-/helper-validator-identifier-7.28.5.tgz", + "integrity": "sha512-qSs4ifwzKJSV39ucNjsvc6WVHs6b7S03sOh2OcHF9UHfVPqWWALUsNUVzhSBiItjRZoLHx7nIarVjqKVusUZ1Q==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=6.9.0" + } + }, + "node_modules/@babel/parser": { + "version": "7.29.3", + "resolved": "https://registry.npmmirror.com/@babel/parser/-/parser-7.29.3.tgz", + "integrity": "sha512-b3ctpQwp+PROvU/cttc4OYl4MzfJUWy6FZg+PMXfzmt/+39iHVF0sDfqay8TQM3JA2EUOyKcFZt75jWriQijsA==", + "dev": true, + "license": "MIT", + "dependencies": { + "@babel/types": "^7.29.0" + }, + "bin": { + "parser": "bin/babel-parser.js" + }, + "engines": { + "node": ">=6.0.0" + } + }, "node_modules/@babel/runtime": { "version": "7.29.2", "resolved": "https://registry.npmmirror.com/@babel/runtime/-/runtime-7.29.2.tgz", @@ -59,6 +177,183 @@ "node": ">=6.9.0" } }, + "node_modules/@babel/types": { + "version": "7.29.0", + "resolved": "https://registry.npmmirror.com/@babel/types/-/types-7.29.0.tgz", + "integrity": "sha512-LwdZHpScM4Qz8Xw2iKSzS+cfglZzJGvofQICy7W7v4caru4EaAmyUuO6BGrbyQ2mYV11W0U8j5mBhd14dd3B0A==", + "dev": true, + "license": "MIT", + "dependencies": { + "@babel/helper-string-parser": "^7.27.1", + "@babel/helper-validator-identifier": "^7.28.5" + }, + "engines": { + "node": ">=6.9.0" + } + }, + "node_modules/@bcoe/v8-coverage": { + "version": "1.0.2", + "resolved": "https://registry.npmmirror.com/@bcoe/v8-coverage/-/v8-coverage-1.0.2.tgz", + "integrity": "sha512-6zABk/ECA/QYSCQ1NGiVwwbQerUCZ+TQbp64Q3AgmfNvurHH0j8TtXa1qbShXA6qqkpAj4V5W8pP6mLe1mcMqA==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=18" + } + }, + "node_modules/@bramus/specificity": { + "version": "2.4.2", + "resolved": "https://registry.npmmirror.com/@bramus/specificity/-/specificity-2.4.2.tgz", + "integrity": "sha512-ctxtJ/eA+t+6q2++vj5j7FYX3nRu311q1wfYH3xjlLOsczhlhxAg2FWNUXhpGvAw3BWo1xBcvOV6/YLc2r5FJw==", + "dev": true, + "license": "MIT", + "dependencies": { + "css-tree": "^3.0.0" + }, + "bin": { + "specificity": "bin/cli.js" + } + }, + "node_modules/@csstools/color-helpers": { + "version": "6.0.2", + "resolved": "https://registry.npmmirror.com/@csstools/color-helpers/-/color-helpers-6.0.2.tgz", + "integrity": "sha512-LMGQLS9EuADloEFkcTBR3BwV/CGHV7zyDxVRtVDTwdI2Ca4it0CCVTT9wCkxSgokjE5Ho41hEPgb8OEUwoXr6Q==", + "dev": true, + "funding": [ + { + "type": "github", + "url": "https://github.com/sponsors/csstools" + }, + { + "type": "opencollective", + "url": "https://opencollective.com/csstools" + } + ], + "license": "MIT-0", + "engines": { + "node": ">=20.19.0" + } + }, + "node_modules/@csstools/css-calc": { + "version": "3.2.1", + "resolved": "https://registry.npmmirror.com/@csstools/css-calc/-/css-calc-3.2.1.tgz", + "integrity": "sha512-DtdHlgXh5ZkA43cwBcAm+huzgJiwx3ZTWVjBs94kwz2xKqSimDA3lBgCjphYgwgVUMWatSM0pDd8TILB1yrVVg==", + "dev": true, + "funding": [ + { + "type": "github", + "url": "https://github.com/sponsors/csstools" + }, + { + "type": "opencollective", + "url": "https://opencollective.com/csstools" + } + ], + "license": "MIT", + "engines": { + "node": ">=20.19.0" + }, + "peerDependencies": { + "@csstools/css-parser-algorithms": "^4.0.0", + "@csstools/css-tokenizer": "^4.0.0" + } + }, + "node_modules/@csstools/css-color-parser": { + "version": "4.1.1", + "resolved": "https://registry.npmmirror.com/@csstools/css-color-parser/-/css-color-parser-4.1.1.tgz", + "integrity": "sha512-eZ5XOtyhK+mggRafYUWzA0tvaYOFgdY8AkgQiCJF9qNAePnUo/zmsqqYubBBb3sQ8uNUaSKTY9s9klfRaAXL0g==", + "dev": true, + "funding": [ + { + "type": "github", + "url": "https://github.com/sponsors/csstools" + }, + { + "type": "opencollective", + "url": "https://opencollective.com/csstools" + } + ], + "license": "MIT", + "dependencies": { + "@csstools/color-helpers": "^6.0.2", + "@csstools/css-calc": "^3.2.1" + }, + "engines": { + "node": ">=20.19.0" + }, + "peerDependencies": { + "@csstools/css-parser-algorithms": "^4.0.0", + "@csstools/css-tokenizer": "^4.0.0" + } + }, + "node_modules/@csstools/css-parser-algorithms": { + "version": "4.0.0", + "resolved": "https://registry.npmmirror.com/@csstools/css-parser-algorithms/-/css-parser-algorithms-4.0.0.tgz", + "integrity": "sha512-+B87qS7fIG3L5h3qwJ/IFbjoVoOe/bpOdh9hAjXbvx0o8ImEmUsGXN0inFOnk2ChCFgqkkGFQ+TpM5rbhkKe4w==", + "dev": true, + "funding": [ + { + "type": "github", + "url": "https://github.com/sponsors/csstools" + }, + { + "type": "opencollective", + "url": "https://opencollective.com/csstools" + } + ], + "license": "MIT", + "engines": { + "node": ">=20.19.0" + }, + "peerDependencies": { + "@csstools/css-tokenizer": "^4.0.0" + } + }, + "node_modules/@csstools/css-syntax-patches-for-csstree": { + "version": "1.1.4", + "resolved": "https://registry.npmmirror.com/@csstools/css-syntax-patches-for-csstree/-/css-syntax-patches-for-csstree-1.1.4.tgz", + "integrity": "sha512-wgsqt92b7C7tQhIdPNxj0n9zuUbQlvAuI1exyzeNrOKOi62SD7ren8zqszmpVREjAOqg8cD2FqYhQfAuKjk4sw==", + "dev": true, + "funding": [ + { + "type": "github", + "url": "https://github.com/sponsors/csstools" + }, + { + "type": "opencollective", + "url": "https://opencollective.com/csstools" + } + ], + "license": "MIT-0", + "peerDependencies": { + "css-tree": "^3.2.1" + }, + "peerDependenciesMeta": { + "css-tree": { + "optional": true + } + } + }, + "node_modules/@csstools/css-tokenizer": { + "version": "4.0.0", + "resolved": "https://registry.npmmirror.com/@csstools/css-tokenizer/-/css-tokenizer-4.0.0.tgz", + "integrity": "sha512-QxULHAm7cNu72w97JUNCBFODFaXpbDg+dP8b/oWFAZ2MTRppA3U00Y2L1HqaS4J6yBqxwa/Y3nMBaxVKbB/NsA==", + "dev": true, + "funding": [ + { + "type": "github", + "url": "https://github.com/sponsors/csstools" + }, + { + "type": "opencollective", + "url": "https://opencollective.com/csstools" + } + ], + "license": "MIT", + "engines": { + "node": ">=20.19.0" + } + }, "node_modules/@emnapi/core": { "version": "1.10.0", "resolved": "https://registry.npmmirror.com/@emnapi/core/-/core-1.10.0.tgz", @@ -156,6 +451,24 @@ "node": "^12.22.0 || ^14.17.0 || >=16.0.0" } }, + "node_modules/@exodus/bytes": { + "version": "1.15.1", + "resolved": "https://registry.npmmirror.com/@exodus/bytes/-/bytes-1.15.1.tgz", + "integrity": "sha512-S6mL0yNB/Abt9Ei4tq8gDhcczc4S3+vQ4ra7vxnAf+YHC02srtqxKKZghx2Dq6p0e66THKwR6r8N6P95wEty7Q==", + "dev": true, + "license": "MIT", + "engines": { + "node": "^20.19.0 || ^22.12.0 || >=24.0.0" + }, + "peerDependencies": { + "@noble/hashes": "^1.8.0 || ^2.0.0" + }, + "peerDependenciesMeta": { + "@noble/hashes": { + "optional": true + } + } + }, "node_modules/@floating-ui/core": { "version": "1.7.5", "resolved": "https://registry.npmmirror.com/@floating-ui/core/-/core-1.7.5.tgz", @@ -532,6 +845,16 @@ "node": ">=12.4.0" } }, + "node_modules/@oxc-project/types": { + "version": "0.132.0", + "resolved": "https://registry.npmmirror.com/@oxc-project/types/-/types-0.132.0.tgz", + "integrity": "sha512-FESMOxil5Se014ui/Eq8fT5uHJo6nIRwH0PfJrZJXs6Gek3ZVFOrpUv3YIZT20m+extU98Hg1Ym72U58rlsxUQ==", + "dev": true, + "license": "MIT", + "funding": { + "url": "https://github.com/sponsors/Boshen" + } + }, "node_modules/@panva/hkdf": { "version": "1.2.1", "resolved": "https://registry.npmmirror.com/@panva/hkdf/-/hkdf-1.2.1.tgz", @@ -553,13 +876,13 @@ } }, "node_modules/@playwright/test": { - "version": "1.59.1", - "resolved": "https://registry.npmmirror.com/@playwright/test/-/test-1.59.1.tgz", - "integrity": "sha512-PG6q63nQg5c9rIi4/Z5lR5IVF7yU5MqmKaPOe0HSc0O2cX1fPi96sUQu5j7eo4gKCkB2AnNGoWt7y4/Xx3Kcqg==", + "version": "1.60.0", + "resolved": "https://registry.npmmirror.com/@playwright/test/-/test-1.60.0.tgz", + "integrity": "sha512-O71yZIbAh/PxDMNGns37GHBIfrVkEVyn+AXyIa5dOTfb4/xNvRWV+Vv/NMbNCtODB/pO7vLlF2OTmMVLhmr7Ag==", "devOptional": true, "license": "Apache-2.0", "dependencies": { - "playwright": "1.59.1" + "playwright": "1.60.0" }, "bin": { "playwright": "cli.js" @@ -1445,6 +1768,289 @@ "integrity": "sha512-HPwpGIzkl28mWyZqG52jiqDJ12waP11Pa1lGoiyUkIEuMLBP0oeK/C89esbXrxsky5we7dfd8U58nm0SgAWpVw==", "license": "MIT" }, + "node_modules/@rolldown/binding-android-arm64": { + "version": "1.0.2", + "resolved": "https://registry.npmmirror.com/@rolldown/binding-android-arm64/-/binding-android-arm64-1.0.2.tgz", + "integrity": "sha512-ZS4D1JPGn/MYQN/SYDWftIE/nVsM8j/AFOYEzAoOE2O3NktQOZru+/vYXGbR/qtdLdIfGCP0lcoJiYVzsEz+iQ==", + "cpu": [ + "arm64" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "android" + ], + "engines": { + "node": "^20.19.0 || >=22.12.0" + } + }, + "node_modules/@rolldown/binding-darwin-arm64": { + "version": "1.0.2", + "resolved": "https://registry.npmmirror.com/@rolldown/binding-darwin-arm64/-/binding-darwin-arm64-1.0.2.tgz", + "integrity": "sha512-vdFA9+C/rekyGce7WqHs/xoT0ioZEWaOFyZLIV1mEeNFaFDUQrPIo8Vs2GvJ6eetb3rzDUtUBgzto3ExpXJB3w==", + "cpu": [ + "arm64" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "darwin" + ], + "engines": { + "node": "^20.19.0 || >=22.12.0" + } + }, + "node_modules/@rolldown/binding-darwin-x64": { + "version": "1.0.2", + "resolved": "https://registry.npmmirror.com/@rolldown/binding-darwin-x64/-/binding-darwin-x64-1.0.2.tgz", + "integrity": "sha512-BewSOwTHazv77DTYiAZXSqqKZ4KP/KonFisDMVU7PImxoWfB2aepnPhd2E4SWz3zDzYgDNbs6jBmTdgNnF02GA==", + "cpu": [ + "x64" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "darwin" + ], + "engines": { + "node": "^20.19.0 || >=22.12.0" + } + }, + "node_modules/@rolldown/binding-freebsd-x64": { + "version": "1.0.2", + "resolved": "https://registry.npmmirror.com/@rolldown/binding-freebsd-x64/-/binding-freebsd-x64-1.0.2.tgz", + "integrity": "sha512-m41o7M0YWtUdqk61Tb+jnKb2rN++iRdIASlExkUoKfIAH30DOHCB8fVLzSUpbWHHU8esmEioY62PxzexE8MBuA==", + "cpu": [ + "x64" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "freebsd" + ], + "engines": { + "node": "^20.19.0 || >=22.12.0" + } + }, + "node_modules/@rolldown/binding-linux-arm-gnueabihf": { + "version": "1.0.2", + "resolved": "https://registry.npmmirror.com/@rolldown/binding-linux-arm-gnueabihf/-/binding-linux-arm-gnueabihf-1.0.2.tgz", + "integrity": "sha512-jcojB9H7W/jS29pMKWAK1N+fU99vXodHDTatS3b3y/XSOCiHo0kkA74pL3jJmkoQtYpOCxDvaKs1fo2Ij/1X5w==", + "cpu": [ + "arm" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "linux" + ], + "engines": { + "node": "^20.19.0 || >=22.12.0" + } + }, + "node_modules/@rolldown/binding-linux-arm64-gnu": { + "version": "1.0.2", + "resolved": "https://registry.npmmirror.com/@rolldown/binding-linux-arm64-gnu/-/binding-linux-arm64-gnu-1.0.2.tgz", + "integrity": "sha512-1jn6qDU5iiOgFgygDzKUuKP0maTi0/f1+sBLgvij/76C77Nm3ts6ufz9Bjg5q5dduxiUIxtq86JIoBvo1xQ4Ig==", + "cpu": [ + "arm64" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "linux" + ], + "engines": { + "node": "^20.19.0 || >=22.12.0" + } + }, + "node_modules/@rolldown/binding-linux-arm64-musl": { + "version": "1.0.2", + "resolved": "https://registry.npmmirror.com/@rolldown/binding-linux-arm64-musl/-/binding-linux-arm64-musl-1.0.2.tgz", + "integrity": "sha512-QVLO/czFMdoMFSqlX3bcswcJNm/23r+qoa/jgtmFc/qEp6/jXmIkDjF/XIo8dPfGaiwy1xfQn8o77L79GeXFgw==", + "cpu": [ + "arm64" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "linux" + ], + "engines": { + "node": "^20.19.0 || >=22.12.0" + } + }, + "node_modules/@rolldown/binding-linux-ppc64-gnu": { + "version": "1.0.2", + "resolved": "https://registry.npmmirror.com/@rolldown/binding-linux-ppc64-gnu/-/binding-linux-ppc64-gnu-1.0.2.tgz", + "integrity": "sha512-hgO5Abm0w5UL6FEa2iFnZqo2KlK7TQ5QhV5x09hujBf7t5KzHQ1VmfPuTpqRy/rNlSxua3eWH374xxiVrP+lcA==", + "cpu": [ + "ppc64" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "linux" + ], + "engines": { + "node": "^20.19.0 || >=22.12.0" + } + }, + "node_modules/@rolldown/binding-linux-s390x-gnu": { + "version": "1.0.2", + "resolved": "https://registry.npmmirror.com/@rolldown/binding-linux-s390x-gnu/-/binding-linux-s390x-gnu-1.0.2.tgz", + "integrity": "sha512-fy8rXxuYEu602abC8MUNaPjYLIFzReOaEIEMKMUa0rFEUxNpVXhs15KSSQ4qlqSaM7B6rcj9rDZgADh/IGDzLQ==", + "cpu": [ + "s390x" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "linux" + ], + "engines": { + "node": "^20.19.0 || >=22.12.0" + } + }, + "node_modules/@rolldown/binding-linux-x64-gnu": { + "version": "1.0.2", + "resolved": "https://registry.npmmirror.com/@rolldown/binding-linux-x64-gnu/-/binding-linux-x64-gnu-1.0.2.tgz", + "integrity": "sha512-0+bOkiQ779+r1WpoHOWHqncvyySci0vKph+myNDYb+im6meJAzHQXay6oEgnkHuUGouM1LKTZwqKpBow6Kj7CQ==", + "cpu": [ + "x64" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "linux" + ], + "engines": { + "node": "^20.19.0 || >=22.12.0" + } + }, + "node_modules/@rolldown/binding-linux-x64-musl": { + "version": "1.0.2", + "resolved": "https://registry.npmmirror.com/@rolldown/binding-linux-x64-musl/-/binding-linux-x64-musl-1.0.2.tgz", + "integrity": "sha512-mjSkrzZK5Qsl0a9d1JgILOiuZOSDTVdKENcSXBoqbzSrspLR/4/IRVDo5wd2GgZjNss/viBFJdeq+j7qH2nypw==", + "cpu": [ + "x64" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "linux" + ], + "engines": { + "node": "^20.19.0 || >=22.12.0" + } + }, + "node_modules/@rolldown/binding-openharmony-arm64": { + "version": "1.0.2", + "resolved": "https://registry.npmmirror.com/@rolldown/binding-openharmony-arm64/-/binding-openharmony-arm64-1.0.2.tgz", + "integrity": "sha512-1v5vHasdfQAZoEHakBV72LIFAC9JjnymsiKxp+GEr/ma3+NJCPSaYK+qavInOovJkgwFrs7GccX2d6IgDA3Z5w==", + "cpu": [ + "arm64" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "openharmony" + ], + "engines": { + "node": "^20.19.0 || >=22.12.0" + } + }, + "node_modules/@rolldown/binding-wasm32-wasi": { + "version": "1.0.2", + "resolved": "https://registry.npmmirror.com/@rolldown/binding-wasm32-wasi/-/binding-wasm32-wasi-1.0.2.tgz", + "integrity": "sha512-mb1VobWn6NheziTk5/WEaR6AKVbrwT5sOi6C7zk3gy/pD1qtJfU1j4PgTo2NJnOtbL9Dl3Aeei8w9jJ7qC2jZQ==", + "cpu": [ + "wasm32" + ], + "dev": true, + "license": "MIT", + "optional": true, + "dependencies": { + "@emnapi/core": "1.10.0", + "@emnapi/runtime": "1.10.0", + "@napi-rs/wasm-runtime": "^1.1.4" + }, + "engines": { + "node": "^20.19.0 || >=22.12.0" + } + }, + "node_modules/@rolldown/binding-wasm32-wasi/node_modules/@napi-rs/wasm-runtime": { + "version": "1.1.4", + "resolved": "https://registry.npmmirror.com/@napi-rs/wasm-runtime/-/wasm-runtime-1.1.4.tgz", + "integrity": "sha512-3NQNNgA1YSlJb/kMH1ildASP9HW7/7kYnRI2szWJaofaS1hWmbGI4H+d3+22aGzXXN9IJ+n+GiFVcGipJP18ow==", + "dev": true, + "license": "MIT", + "optional": true, + "dependencies": { + "@tybys/wasm-util": "^0.10.1" + }, + "funding": { + "type": "github", + "url": "https://github.com/sponsors/Brooooooklyn" + }, + "peerDependencies": { + "@emnapi/core": "^1.7.1", + "@emnapi/runtime": "^1.7.1" + } + }, + "node_modules/@rolldown/binding-win32-arm64-msvc": { + "version": "1.0.2", + "resolved": "https://registry.npmmirror.com/@rolldown/binding-win32-arm64-msvc/-/binding-win32-arm64-msvc-1.0.2.tgz", + "integrity": "sha512-SqKonF56vA/L2yHwHYcEp2P34URpOZ7d1fS635cTkpDnUtEGdUbhI6NzsPdqeSWvAAeGDrxjWjNmibDIdFf9/A==", + "cpu": [ + "arm64" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "win32" + ], + "engines": { + "node": "^20.19.0 || >=22.12.0" + } + }, + "node_modules/@rolldown/binding-win32-x64-msvc": { + "version": "1.0.2", + "resolved": "https://registry.npmmirror.com/@rolldown/binding-win32-x64-msvc/-/binding-win32-x64-msvc-1.0.2.tgz", + "integrity": "sha512-v7qRI7gXLRINcOGXt+7YmAZ6iFuyZVMIoXAxhd8oP+DR9dLfL9GfNIx7PLMxmhZdvq8waUJBQiWN9EKNy+TRBQ==", + "cpu": [ + "x64" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "win32" + ], + "engines": { + "node": "^20.19.0 || >=22.12.0" + } + }, + "node_modules/@rolldown/pluginutils": { + "version": "1.0.1", + "resolved": "https://registry.npmmirror.com/@rolldown/pluginutils/-/pluginutils-1.0.1.tgz", + "integrity": "sha512-2j9bGt5Jh8hj+vPtgzPtl72j0yRxHAyumoo6TNfAjsLB04UtpSvPbPcDcBMxz7n+9CYB0c1GxQFxYRg2jimqGw==", + "dev": true, + "license": "MIT" + }, "node_modules/@rtsao/scc": { "version": "1.1.0", "resolved": "https://registry.npmmirror.com/@rtsao/scc/-/scc-1.1.0.tgz", @@ -1459,6 +2065,13 @@ "dev": true, "license": "MIT" }, + "node_modules/@standard-schema/spec": { + "version": "1.1.0", + "resolved": "https://registry.npmmirror.com/@standard-schema/spec/-/spec-1.1.0.tgz", + "integrity": "sha512-l2aFy5jALhniG5HgqrD6jXLi/rUWrKvqN/qJx6yoJsgKhblVd+iqqU4RCXavm/jPityDo5TCvKMnpjKnOriy0w==", + "dev": true, + "license": "MIT" + }, "node_modules/@swc/counter": { "version": "0.1.3", "resolved": "https://registry.npmmirror.com/@swc/counter/-/counter-0.1.3.tgz", @@ -1475,6 +2088,131 @@ "tslib": "^2.4.0" } }, + "node_modules/@testing-library/dom": { + "version": "10.4.1", + "resolved": "https://registry.npmmirror.com/@testing-library/dom/-/dom-10.4.1.tgz", + "integrity": "sha512-o4PXJQidqJl82ckFaXUeoAW+XysPLauYI43Abki5hABd853iMhitooc6znOnczgbTYmEP6U6/y1ZyKAIsvMKGg==", + "dev": true, + "license": "MIT", + "peer": true, + "dependencies": { + "@babel/code-frame": "^7.10.4", + "@babel/runtime": "^7.12.5", + "@types/aria-query": "^5.0.1", + "aria-query": "5.3.0", + "dom-accessibility-api": "^0.5.9", + "lz-string": "^1.5.0", + "picocolors": "1.1.1", + "pretty-format": "^27.0.2" + }, + "engines": { + "node": ">=18" + } + }, + "node_modules/@testing-library/dom/node_modules/ansi-styles": { + "version": "5.2.0", + "resolved": "https://registry.npmmirror.com/ansi-styles/-/ansi-styles-5.2.0.tgz", + "integrity": "sha512-Cxwpt2SfTzTtXcfOlzGEee8O+c+MmUgGrNiBcXnuWxuFJHe6a5Hz7qwhwe5OgaSYI0IJvkLqWX1ASG+cJOkEiA==", + "dev": true, + "license": "MIT", + "peer": true, + "engines": { + "node": ">=10" + }, + "funding": { + "url": "https://github.com/chalk/ansi-styles?sponsor=1" + } + }, + "node_modules/@testing-library/dom/node_modules/aria-query": { + "version": "5.3.0", + "resolved": "https://registry.npmmirror.com/aria-query/-/aria-query-5.3.0.tgz", + "integrity": "sha512-b0P0sZPKtyu8HkeRAfCq0IfURZK+SuwMjY1UXGBU27wpAiTwQAIlq56IbIO+ytk/JjS1fMR14ee5WBBfKi5J6A==", + "dev": true, + "license": "Apache-2.0", + "peer": true, + "dependencies": { + "dequal": "^2.0.3" + } + }, + "node_modules/@testing-library/dom/node_modules/pretty-format": { + "version": "27.5.1", + "resolved": "https://registry.npmmirror.com/pretty-format/-/pretty-format-27.5.1.tgz", + "integrity": "sha512-Qb1gy5OrP5+zDf2Bvnzdl3jsTf1qXVMazbvCoKhtKqVs4/YK4ozX4gKQJJVyNe+cajNPn0KoC0MC3FUmaHWEmQ==", + "dev": true, + "license": "MIT", + "peer": true, + "dependencies": { + "ansi-regex": "^5.0.1", + "ansi-styles": "^5.0.0", + "react-is": "^17.0.1" + }, + "engines": { + "node": "^10.13.0 || ^12.13.0 || ^14.15.0 || >=15.0.0" + } + }, + "node_modules/@testing-library/dom/node_modules/react-is": { + "version": "17.0.2", + "resolved": "https://registry.npmmirror.com/react-is/-/react-is-17.0.2.tgz", + "integrity": "sha512-w2GsyukL62IJnlaff/nRegPQR94C/XXamvMWmSHRJ4y7Ts/4ocGRmTHvOs8PSE6pB3dWOrD/nueuU5sduBsQ4w==", + "dev": true, + "license": "MIT", + "peer": true + }, + "node_modules/@testing-library/jest-dom": { + "version": "6.9.1", + "resolved": "https://registry.npmmirror.com/@testing-library/jest-dom/-/jest-dom-6.9.1.tgz", + "integrity": "sha512-zIcONa+hVtVSSep9UT3jZ5rizo2BsxgyDYU7WFD5eICBE7no3881HGeb/QkGfsJs6JTkY1aQhT7rIPC7e+0nnA==", + "dev": true, + "license": "MIT", + "dependencies": { + "@adobe/css-tools": "^4.4.0", + "aria-query": "^5.0.0", + "css.escape": "^1.5.1", + "dom-accessibility-api": "^0.6.3", + "picocolors": "^1.1.1", + "redent": "^3.0.0" + }, + "engines": { + "node": ">=14", + "npm": ">=6", + "yarn": ">=1" + } + }, + "node_modules/@testing-library/jest-dom/node_modules/dom-accessibility-api": { + "version": "0.6.3", + "resolved": "https://registry.npmmirror.com/dom-accessibility-api/-/dom-accessibility-api-0.6.3.tgz", + "integrity": "sha512-7ZgogeTnjuHbo+ct10G9Ffp0mif17idi0IyWNVA/wcwcm7NPOD/WEHVP3n7n3MhXqxoIYm8d6MuZohYWIZ4T3w==", + "dev": true, + "license": "MIT" + }, + "node_modules/@testing-library/react": { + "version": "16.3.2", + "resolved": "https://registry.npmmirror.com/@testing-library/react/-/react-16.3.2.tgz", + "integrity": "sha512-XU5/SytQM+ykqMnAnvB2umaJNIOsLF3PVv//1Ew4CTcpz0/BRyy/af40qqrt7SjKpDdT1saBMc42CUok5gaw+g==", + "dev": true, + "license": "MIT", + "dependencies": { + "@babel/runtime": "^7.12.5" + }, + "engines": { + "node": ">=18" + }, + "peerDependencies": { + "@testing-library/dom": "^10.0.0", + "@types/react": "^18.0.0 || ^19.0.0", + "@types/react-dom": "^18.0.0 || ^19.0.0", + "react": "^18.0.0 || ^19.0.0", + "react-dom": "^18.0.0 || ^19.0.0" + }, + "peerDependenciesMeta": { + "@types/react": { + "optional": true + }, + "@types/react-dom": { + "optional": true + } + } + }, "node_modules/@tybys/wasm-util": { "version": "0.10.1", "resolved": "https://registry.npmmirror.com/@tybys/wasm-util/-/wasm-util-0.10.1.tgz", @@ -1486,6 +2224,25 @@ "tslib": "^2.4.0" } }, + "node_modules/@types/aria-query": { + "version": "5.0.4", + "resolved": "https://registry.npmmirror.com/@types/aria-query/-/aria-query-5.0.4.tgz", + "integrity": "sha512-rfT93uj5s0PRL7EzccGMs3brplhcrghnDoV26NqKhCAS1hVo+WdNsPvE/yb6ilfr5hi2MEk6d5EWJTKdxg8jVw==", + "dev": true, + "license": "MIT", + "peer": true + }, + "node_modules/@types/chai": { + "version": "5.2.3", + "resolved": "https://registry.npmmirror.com/@types/chai/-/chai-5.2.3.tgz", + "integrity": "sha512-Mw558oeA9fFbv65/y4mHtXDs9bPnFMZAL/jxdPFUpOHHIXX91mcgEHbS5Lahr+pwZFR8A7GQleRWeI6cGFC2UA==", + "dev": true, + "license": "MIT", + "dependencies": { + "@types/deep-eql": "*", + "assertion-error": "^2.0.1" + } + }, "node_modules/@types/d3-array": { "version": "3.2.2", "resolved": "https://registry.npmmirror.com/@types/d3-array/-/d3-array-3.2.2.tgz", @@ -1549,6 +2306,20 @@ "integrity": "sha512-Ps3T8E8dZDam6fUyNiMkekK3XUsaUEik+idO9/YjPtfj2qruF8tFBXS7XhtE4iIXBLxhmLjP3SXpLhVf21I9Lw==", "license": "MIT" }, + "node_modules/@types/deep-eql": { + "version": "4.0.2", + "resolved": "https://registry.npmmirror.com/@types/deep-eql/-/deep-eql-4.0.2.tgz", + "integrity": "sha512-c9h9dVVMigMPc4bwTvC5dxqtqJZwQPePsWjPlpSOnojbor6pGqdk541lfA7AqFQr5pB1BRdq0juY9db81BwyFw==", + "dev": true, + "license": "MIT" + }, + "node_modules/@types/estree": { + "version": "1.0.9", + "resolved": "https://registry.npmmirror.com/@types/estree/-/estree-1.0.9.tgz", + "integrity": "sha512-GhdPgy1el4/ImP05X05Uw4cw2/M93BCUmnEvWZNStlCzEKME4Fkk+YpoA5OiHNQmoS7Cafb8Xa3Pya8m1Qrzeg==", + "dev": true, + "license": "MIT" + }, "node_modules/@types/json5": { "version": "0.0.29", "resolved": "https://registry.npmmirror.com/@types/json5/-/json5-0.0.29.tgz", @@ -2152,6 +2923,176 @@ "win32" ] }, + "node_modules/@vitejs/plugin-react": { + "version": "6.0.2", + "resolved": "https://registry.npmmirror.com/@vitejs/plugin-react/-/plugin-react-6.0.2.tgz", + "integrity": "sha512-DlSMqo4WhThw4vB8Mpn0Woe9J+Jfq1geJ61AKW0QEgLzGMNwtIMdxbDUzLxcun8W7NbJO0e2Jg/Nxm3cCSVzzg==", + "dev": true, + "license": "MIT", + "dependencies": { + "@rolldown/pluginutils": "^1.0.0" + }, + "engines": { + "node": "^20.19.0 || >=22.12.0" + }, + "peerDependencies": { + "@rolldown/plugin-babel": "^0.1.7 || ^0.2.0", + "babel-plugin-react-compiler": "^1.0.0", + "vite": "^8.0.0" + }, + "peerDependenciesMeta": { + "@rolldown/plugin-babel": { + "optional": true + }, + "babel-plugin-react-compiler": { + "optional": true + } + } + }, + "node_modules/@vitest/coverage-v8": { + "version": "4.1.7", + "resolved": "https://registry.npmmirror.com/@vitest/coverage-v8/-/coverage-v8-4.1.7.tgz", + "integrity": "sha512-qsYPeXc5Q9dFLd1i8Ap+Bx8sQgcp+rFVQo4R0dDsWNBzl26ldVF1qOO+RL24K7FDrR6pA+50XedRLSoSG24bVQ==", + "dev": true, + "license": "MIT", + "dependencies": { + "@bcoe/v8-coverage": "^1.0.2", + "@vitest/utils": "4.1.7", + "ast-v8-to-istanbul": "^1.0.0", + "istanbul-lib-coverage": "^3.2.2", + "istanbul-lib-report": "^3.0.1", + "istanbul-reports": "^3.2.0", + "magicast": "^0.5.2", + "obug": "^2.1.1", + "std-env": "^4.0.0-rc.1", + "tinyrainbow": "^3.1.0" + }, + "funding": { + "url": "https://opencollective.com/vitest" + }, + "peerDependencies": { + "@vitest/browser": "4.1.7", + "vitest": "4.1.7" + }, + "peerDependenciesMeta": { + "@vitest/browser": { + "optional": true + } + } + }, + "node_modules/@vitest/expect": { + "version": "4.1.7", + "resolved": "https://registry.npmmirror.com/@vitest/expect/-/expect-4.1.7.tgz", + "integrity": "sha512-1R+tw0ortHEbZDGMymm+pN7/AFQ/RkFFdtd7EN+VBpynKmLbP8A3rpEXdshBJ7+8hQ9zBJh/i1s0yKNtxAnU7w==", + "dev": true, + "license": "MIT", + "dependencies": { + "@standard-schema/spec": "^1.1.0", + "@types/chai": "^5.2.2", + "@vitest/spy": "4.1.7", + "@vitest/utils": "4.1.7", + "chai": "^6.2.2", + "tinyrainbow": "^3.1.0" + }, + "funding": { + "url": "https://opencollective.com/vitest" + } + }, + "node_modules/@vitest/mocker": { + "version": "4.1.7", + "resolved": "https://registry.npmmirror.com/@vitest/mocker/-/mocker-4.1.7.tgz", + "integrity": "sha512-vY7nuamKgfvpA1Koa3oYIw/k7D6kZnpGyNMZW8loow2bsBYla1TFdqTaXncWdRn4pgwNs+90RhnXhJScDwQeJA==", + "dev": true, + "license": "MIT", + "dependencies": { + "@vitest/spy": "4.1.7", + "estree-walker": "^3.0.3", + "magic-string": "^0.30.21" + }, + "funding": { + "url": "https://opencollective.com/vitest" + }, + "peerDependencies": { + "msw": "^2.4.9", + "vite": "^6.0.0 || ^7.0.0 || ^8.0.0" + }, + "peerDependenciesMeta": { + "msw": { + "optional": true + }, + "vite": { + "optional": true + } + } + }, + "node_modules/@vitest/pretty-format": { + "version": "4.1.7", + "resolved": "https://registry.npmmirror.com/@vitest/pretty-format/-/pretty-format-4.1.7.tgz", + "integrity": "sha512-umgCarTOYQWIaDMvGDRZij+6b9oVeLIyJzfN+AS88e0ZOU3QTgNNSTtjQOpcvWr3np1N0j4WgZj+sb3oYBDscw==", + "dev": true, + "license": "MIT", + "dependencies": { + "tinyrainbow": "^3.1.0" + }, + "funding": { + "url": "https://opencollective.com/vitest" + } + }, + "node_modules/@vitest/runner": { + "version": "4.1.7", + "resolved": "https://registry.npmmirror.com/@vitest/runner/-/runner-4.1.7.tgz", + "integrity": "sha512-BapjmAQ2aI78WdMEfeUWivnfVzB+VPGwWRQcJE0OUq7qEeEcBsCSf+0T5iREBNE5nBb4wA5Ya0W6IA+sghdEFw==", + "dev": true, + "license": "MIT", + "dependencies": { + "@vitest/utils": "4.1.7", + "pathe": "^2.0.3" + }, + "funding": { + "url": "https://opencollective.com/vitest" + } + }, + "node_modules/@vitest/snapshot": { + "version": "4.1.7", + "resolved": "https://registry.npmmirror.com/@vitest/snapshot/-/snapshot-4.1.7.tgz", + "integrity": "sha512-ZacLzja+TmJeZ1h14xW2FB/WpeimUD3haBXQPyJqxvo8jQTmfeA8zv58mtjN2C7EHXZDYVcVYdYmAxjkWVvKCw==", + "dev": true, + "license": "MIT", + "dependencies": { + "@vitest/pretty-format": "4.1.7", + "@vitest/utils": "4.1.7", + "magic-string": "^0.30.21", + "pathe": "^2.0.3" + }, + "funding": { + "url": "https://opencollective.com/vitest" + } + }, + "node_modules/@vitest/spy": { + "version": "4.1.7", + "resolved": "https://registry.npmmirror.com/@vitest/spy/-/spy-4.1.7.tgz", + "integrity": "sha512-kbkI5LMWakyuTIvs6fUJ5qdIVb1XVKsYJAT4OJ938cHMROYMSfmoQdZy0aaAnjbbc8F61vkoTqz/Az+/HiIu5Q==", + "dev": true, + "license": "MIT", + "funding": { + "url": "https://opencollective.com/vitest" + } + }, + "node_modules/@vitest/utils": { + "version": "4.1.7", + "resolved": "https://registry.npmmirror.com/@vitest/utils/-/utils-4.1.7.tgz", + "integrity": "sha512-T532WBu791cBxJlCl6SO+J14l81DQx6uQHm1bQbmCDY7nqlEIgkza/UFnSBNaUtSf41unldDFjdOBYEQC4b5Hw==", + "dev": true, + "license": "MIT", + "dependencies": { + "@vitest/pretty-format": "4.1.7", + "convert-source-map": "^2.0.0", + "tinyrainbow": "^3.1.0" + }, + "funding": { + "url": "https://opencollective.com/vitest" + } + }, "node_modules/acorn": { "version": "8.16.0", "resolved": "https://registry.npmmirror.com/acorn/-/acorn-8.16.0.tgz", @@ -2432,6 +3373,16 @@ "url": "https://github.com/sponsors/ljharb" } }, + "node_modules/assertion-error": { + "version": "2.0.1", + "resolved": "https://registry.npmmirror.com/assertion-error/-/assertion-error-2.0.1.tgz", + "integrity": "sha512-Izi8RQcffqCeNVgFigKli1ssklIbpHnCYc6AknXGYoB6grJqyeby7jv12JUQgmTAnIDnbck1uxksT4dzN3PWBA==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=12" + } + }, "node_modules/ast-types-flow": { "version": "0.0.8", "resolved": "https://registry.npmmirror.com/ast-types-flow/-/ast-types-flow-0.0.8.tgz", @@ -2439,6 +3390,25 @@ "dev": true, "license": "MIT" }, + "node_modules/ast-v8-to-istanbul": { + "version": "1.0.0", + "resolved": "https://registry.npmmirror.com/ast-v8-to-istanbul/-/ast-v8-to-istanbul-1.0.0.tgz", + "integrity": "sha512-1fSfIwuDICFA4LKkCzRPO7F0hzFf0B7+Xqrl27ynQaa+Rh0e1Es0v6kWHPott3lU10AyAr7oKHa65OppjLn3Rg==", + "dev": true, + "license": "MIT", + "dependencies": { + "@jridgewell/trace-mapping": "^0.3.31", + "estree-walker": "^3.0.3", + "js-tokens": "^10.0.0" + } + }, + "node_modules/ast-v8-to-istanbul/node_modules/js-tokens": { + "version": "10.0.0", + "resolved": "https://registry.npmmirror.com/js-tokens/-/js-tokens-10.0.0.tgz", + "integrity": "sha512-lM/UBzQmfJRo9ABXbPWemivdCW8V2G8FHaHdypQaIy523snUjog0W71ayWXTjiR+ixeMyVHN2XcpnTd/liPg/Q==", + "dev": true, + "license": "MIT" + }, "node_modules/async-function": { "version": "1.0.0", "resolved": "https://registry.npmmirror.com/async-function/-/async-function-1.0.0.tgz", @@ -2492,6 +3462,16 @@ "dev": true, "license": "MIT" }, + "node_modules/bidi-js": { + "version": "1.0.3", + "resolved": "https://registry.npmmirror.com/bidi-js/-/bidi-js-1.0.3.tgz", + "integrity": "sha512-RKshQI1R3YQ+n9YJz2QQ147P66ELpa1FQEg20Dk8oW9t2KgLbpDLLp9aGZ7y8WHSshDknG0bknqGw5/tyCs5tw==", + "dev": true, + "license": "MIT", + "dependencies": { + "require-from-string": "^2.0.2" + } + }, "node_modules/binary-extensions": { "version": "2.3.0", "resolved": "https://registry.npmmirror.com/binary-extensions/-/binary-extensions-2.3.0.tgz", @@ -2627,6 +3607,16 @@ ], "license": "CC-BY-4.0" }, + "node_modules/chai": { + "version": "6.2.2", + "resolved": "https://registry.npmmirror.com/chai/-/chai-6.2.2.tgz", + "integrity": "sha512-NUPRluOfOiTKBKvWPtSD4PhFvWCqOi0BGStNWs57X9js7XGTprSmFoz5F0tWhR4WPjNeR9jXqdC7/UpSJTnlRg==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=18" + } + }, "node_modules/chalk": { "version": "4.1.2", "resolved": "https://registry.npmmirror.com/chalk/-/chalk-4.1.2.tgz", @@ -2743,6 +3733,13 @@ "dev": true, "license": "MIT" }, + "node_modules/convert-source-map": { + "version": "2.0.0", + "resolved": "https://registry.npmmirror.com/convert-source-map/-/convert-source-map-2.0.0.tgz", + "integrity": "sha512-Kvp459HrV2FEJ1CAsi1Ku+MY3kasH19TFykTz2xWmMeq6bk2NU3XXvfJ+Q61m0xktWwt+1HSYf3JZsTms3aRJg==", + "dev": true, + "license": "MIT" + }, "node_modules/cookie": { "version": "0.7.2", "resolved": "https://registry.npmmirror.com/cookie/-/cookie-0.7.2.tgz", @@ -2767,6 +3764,27 @@ "node": ">= 8" } }, + "node_modules/css-tree": { + "version": "3.2.1", + "resolved": "https://registry.npmmirror.com/css-tree/-/css-tree-3.2.1.tgz", + "integrity": "sha512-X7sjQzceUhu1u7Y/ylrRZFU2FS6LRiFVp6rKLPg23y3x3c3DOKAwuXGDp+PAGjh6CSnCjYeAul8pcT8bAl+lSA==", + "dev": true, + "license": "MIT", + "dependencies": { + "mdn-data": "2.27.1", + "source-map-js": "^1.2.1" + }, + "engines": { + "node": "^10 || ^12.20.0 || ^14.13.0 || >=15.0.0" + } + }, + "node_modules/css.escape": { + "version": "1.5.1", + "resolved": "https://registry.npmmirror.com/css.escape/-/css.escape-1.5.1.tgz", + "integrity": "sha512-YUifsXXuknHlUsmlgyY0PKzgPOr7/FjCePfHNt0jxm83wHZi44VDMQ7/fGNkjY3/jV1MC+1CmZbaHzugyeRtpg==", + "dev": true, + "license": "MIT" + }, "node_modules/cssesc": { "version": "3.0.0", "resolved": "https://registry.npmmirror.com/cssesc/-/cssesc-3.0.0.tgz", @@ -2913,6 +3931,20 @@ "dev": true, "license": "BSD-2-Clause" }, + "node_modules/data-urls": { + "version": "7.0.0", + "resolved": "https://registry.npmmirror.com/data-urls/-/data-urls-7.0.0.tgz", + "integrity": "sha512-23XHcCF+coGYevirZceTVD7NdJOqVn+49IHyxgszm+JIiHLoB2TkmPtsYkNWT1pvRSGkc35L6NHs0yHkN2SumA==", + "dev": true, + "license": "MIT", + "dependencies": { + "whatwg-mimetype": "^5.0.0", + "whatwg-url": "^16.0.0" + }, + "engines": { + "node": "^20.19.0 || ^22.12.0 || >=24.0.0" + } + }, "node_modules/data-view-buffer": { "version": "1.0.2", "resolved": "https://registry.npmmirror.com/data-view-buffer/-/data-view-buffer-1.0.2.tgz", @@ -2985,6 +4017,13 @@ } } }, + "node_modules/decimal.js": { + "version": "10.6.0", + "resolved": "https://registry.npmmirror.com/decimal.js/-/decimal.js-10.6.0.tgz", + "integrity": "sha512-YpgQiITW3JXGntzdUmyUR1V812Hn8T1YVXhCu+wO3OpS4eU9l4YdD3qjyiKdV6mvV29zapkMeD390UVEf2lkUg==", + "dev": true, + "license": "MIT" + }, "node_modules/decimal.js-light": { "version": "2.5.1", "resolved": "https://registry.npmmirror.com/decimal.js-light/-/decimal.js-light-2.5.1.tgz", @@ -3034,6 +4073,25 @@ "url": "https://github.com/sponsors/ljharb" } }, + "node_modules/dequal": { + "version": "2.0.3", + "resolved": "https://registry.npmmirror.com/dequal/-/dequal-2.0.3.tgz", + "integrity": "sha512-0je+qPKHEMohvfRTCEo3CrPG6cAzAYgmzKyxRiYSSDkS6eGJdyVJm7WaYA5ECaAD9wLB2T4EEeymA5aFVcYXCA==", + "license": "MIT", + "engines": { + "node": ">=6" + } + }, + "node_modules/detect-libc": { + "version": "2.1.2", + "resolved": "https://registry.npmmirror.com/detect-libc/-/detect-libc-2.1.2.tgz", + "integrity": "sha512-Btj2BOOO83o3WyH59e8MgXsxEQVcarkUOpEYrubB0urwnN10yQ364rsiByU11nZlqWYZm05i/of7io4mzihBtQ==", + "dev": true, + "license": "Apache-2.0", + "engines": { + "node": ">=8" + } + }, "node_modules/detect-node-es": { "version": "1.1.0", "resolved": "https://registry.npmmirror.com/detect-node-es/-/detect-node-es-1.1.0.tgz", @@ -3065,6 +4123,14 @@ "node": ">=6.0.0" } }, + "node_modules/dom-accessibility-api": { + "version": "0.5.16", + "resolved": "https://registry.npmmirror.com/dom-accessibility-api/-/dom-accessibility-api-0.5.16.tgz", + "integrity": "sha512-X7BJ2yElsnOJ30pZF4uIIDfBEVgF4XEBxL9Bxhy6dnrm5hkzqmsWHGTiHqRiITNhMyFLyAiWndIJP7Z1NTteDg==", + "dev": true, + "license": "MIT", + "peer": true + }, "node_modules/dom-helpers": { "version": "5.2.1", "resolved": "https://registry.npmmirror.com/dom-helpers/-/dom-helpers-5.2.1.tgz", @@ -3104,6 +4170,19 @@ "dev": true, "license": "MIT" }, + "node_modules/entities": { + "version": "8.0.0", + "resolved": "https://registry.npmmirror.com/entities/-/entities-8.0.0.tgz", + "integrity": "sha512-zwfzJecQ/Uej6tusMqwAqU/6KL2XaB2VZ2Jg54Je6ahNBGNH6Ek6g3jjNCF0fG9EWQKGZNddNjU5F1ZQn/sBnA==", + "dev": true, + "license": "BSD-2-Clause", + "engines": { + "node": ">=20.19.0" + }, + "funding": { + "url": "https://github.com/fb55/entities?sponsor=1" + } + }, "node_modules/es-abstract": { "version": "1.24.2", "resolved": "https://registry.npmmirror.com/es-abstract/-/es-abstract-1.24.2.tgz", @@ -3220,6 +4299,13 @@ "node": ">= 0.4" } }, + "node_modules/es-module-lexer": { + "version": "2.1.0", + "resolved": "https://registry.npmmirror.com/es-module-lexer/-/es-module-lexer-2.1.0.tgz", + "integrity": "sha512-n27zTYMjYu1aj4MjCWzSP7G9r75utsaoc8m61weK+W8JMBGGQybd43GstCXZ3WNmSFtGT9wi59qQTW6mhTR5LQ==", + "dev": true, + "license": "MIT" + }, "node_modules/es-object-atoms": { "version": "1.1.1", "resolved": "https://registry.npmmirror.com/es-object-atoms/-/es-object-atoms-1.1.1.tgz", @@ -3713,6 +4799,16 @@ "node": ">=4.0" } }, + "node_modules/estree-walker": { + "version": "3.0.3", + "resolved": "https://registry.npmmirror.com/estree-walker/-/estree-walker-3.0.3.tgz", + "integrity": "sha512-7RUKfXgSMMkzt6ZuXmqapOurLGPPfgj6l9uRZ7lRGolvk0y2yocc35LdcxKC5PQZdn2DMqioAQ2NoWcrTKmm6g==", + "dev": true, + "license": "MIT", + "dependencies": { + "@types/estree": "^1.0.0" + } + }, "node_modules/esutils": { "version": "2.0.3", "resolved": "https://registry.npmmirror.com/esutils/-/esutils-2.0.3.tgz", @@ -3729,6 +4825,16 @@ "integrity": "sha512-8guHBZCwKnFhYdHr2ysuRWErTwhoN2X8XELRlrRwpmfeY2jjuUN4taQMsULKUVo1K4DvZl+0pgfyoysHxvmvEw==", "license": "MIT" }, + "node_modules/expect-type": { + "version": "1.3.0", + "resolved": "https://registry.npmmirror.com/expect-type/-/expect-type-1.3.0.tgz", + "integrity": "sha512-knvyeauYhqjOYvQ66MznSMs83wmHrCycNEN6Ao+2AeYEfxUIkuiVxdEa1qlGEPK+We3n0THiDciYSsCcgW/DoA==", + "dev": true, + "license": "Apache-2.0", + "engines": { + "node": ">=12.0.0" + } + }, "node_modules/fast-deep-equal": { "version": "3.1.3", "resolved": "https://registry.npmmirror.com/fast-deep-equal/-/fast-deep-equal-3.1.3.tgz", @@ -4256,6 +5362,26 @@ "node": ">= 0.4" } }, + "node_modules/html-encoding-sniffer": { + "version": "6.0.0", + "resolved": "https://registry.npmmirror.com/html-encoding-sniffer/-/html-encoding-sniffer-6.0.0.tgz", + "integrity": "sha512-CV9TW3Y3f8/wT0BRFc1/KAVQ3TUHiXmaAb6VW9vtiMFf7SLoMd1PdAc4W3KFOFETBJUb90KatHqlsZMWV+R9Gg==", + "dev": true, + "license": "MIT", + "dependencies": { + "@exodus/bytes": "^1.6.0" + }, + "engines": { + "node": "^20.19.0 || ^22.12.0 || >=24.0.0" + } + }, + "node_modules/html-escaper": { + "version": "2.0.2", + "resolved": "https://registry.npmmirror.com/html-escaper/-/html-escaper-2.0.2.tgz", + "integrity": "sha512-H2iMtd0I4Mt5eYiapRdIDjp+XzelXQ0tFE4JS7YFwFevXXMmOp9myNrUvCg0D6ws8iqkRPBfKHgbwig1SmlLfg==", + "dev": true, + "license": "MIT" + }, "node_modules/ignore": { "version": "5.3.2", "resolved": "https://registry.npmmirror.com/ignore/-/ignore-5.3.2.tgz", @@ -4293,6 +5419,16 @@ "node": ">=0.8.19" } }, + "node_modules/indent-string": { + "version": "4.0.0", + "resolved": "https://registry.npmmirror.com/indent-string/-/indent-string-4.0.0.tgz", + "integrity": "sha512-EdDDZu4A2OyIK7Lr/2zG+w5jmbuk1DVBnEwREQvBzspBJkCEbRa8GxU1lghYcaGJCnRWibjDXlq779X1/y5xwg==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=8" + } + }, "node_modules/inflight": { "version": "1.0.6", "resolved": "https://registry.npmmirror.com/inflight/-/inflight-1.0.6.tgz", @@ -4621,6 +5757,13 @@ "node": ">=8" } }, + "node_modules/is-potential-custom-element-name": { + "version": "1.0.1", + "resolved": "https://registry.npmmirror.com/is-potential-custom-element-name/-/is-potential-custom-element-name-1.0.1.tgz", + "integrity": "sha512-bCYeRA2rVibKZd+s2625gGnGF/t7DSqDs4dP7CrLA1m7jKWz6pps0LpYLJN8Q64HtmPKJ1hrN3nzPNKFEKOUiQ==", + "dev": true, + "license": "MIT" + }, "node_modules/is-regex": { "version": "1.2.1", "resolved": "https://registry.npmmirror.com/is-regex/-/is-regex-1.2.1.tgz", @@ -4780,6 +5923,45 @@ "dev": true, "license": "ISC" }, + "node_modules/istanbul-lib-coverage": { + "version": "3.2.2", + "resolved": "https://registry.npmmirror.com/istanbul-lib-coverage/-/istanbul-lib-coverage-3.2.2.tgz", + "integrity": "sha512-O8dpsF+r0WV/8MNRKfnmrtCWhuKjxrq2w+jpzBL5UZKTi2LeVWnWOmWRxFlesJONmc+wLAGvKQZEOanko0LFTg==", + "dev": true, + "license": "BSD-3-Clause", + "engines": { + "node": ">=8" + } + }, + "node_modules/istanbul-lib-report": { + "version": "3.0.1", + "resolved": "https://registry.npmmirror.com/istanbul-lib-report/-/istanbul-lib-report-3.0.1.tgz", + "integrity": "sha512-GCfE1mtsHGOELCU8e/Z7YWzpmybrx/+dSTfLrvY8qRmaY6zXTKWn6WQIjaAFw069icm6GVMNkgu0NzI4iPZUNw==", + "dev": true, + "license": "BSD-3-Clause", + "dependencies": { + "istanbul-lib-coverage": "^3.0.0", + "make-dir": "^4.0.0", + "supports-color": "^7.1.0" + }, + "engines": { + "node": ">=10" + } + }, + "node_modules/istanbul-reports": { + "version": "3.2.0", + "resolved": "https://registry.npmmirror.com/istanbul-reports/-/istanbul-reports-3.2.0.tgz", + "integrity": "sha512-HGYWWS/ehqTV3xN10i23tkPkpH46MLCIMFNCaaKNavAXTF1RkqxawEPtnjnGZ6XKSInBKkiOA5BKS+aZiY3AvA==", + "dev": true, + "license": "BSD-3-Clause", + "dependencies": { + "html-escaper": "^2.0.0", + "istanbul-lib-report": "^3.0.0" + }, + "engines": { + "node": ">=8" + } + }, "node_modules/iterator.prototype": { "version": "1.1.5", "resolved": "https://registry.npmmirror.com/iterator.prototype/-/iterator.prototype-1.1.5.tgz", @@ -4854,6 +6036,57 @@ "js-yaml": "bin/js-yaml.js" } }, + "node_modules/jsdom": { + "version": "29.1.1", + "resolved": "https://registry.npmmirror.com/jsdom/-/jsdom-29.1.1.tgz", + "integrity": "sha512-ECi4Fi2f7BdJtUKTflYRTiaMxIB0O6zfR1fX0GXpUrf6flp8QIYn1UT20YQqdSOfk2dfkCwS8LAFoJDEppNK5Q==", + "dev": true, + "license": "MIT", + "dependencies": { + "@asamuzakjp/css-color": "^5.1.11", + "@asamuzakjp/dom-selector": "^7.1.1", + "@bramus/specificity": "^2.4.2", + "@csstools/css-syntax-patches-for-csstree": "^1.1.3", + "@exodus/bytes": "^1.15.0", + "css-tree": "^3.2.1", + "data-urls": "^7.0.0", + "decimal.js": "^10.6.0", + "html-encoding-sniffer": "^6.0.0", + "is-potential-custom-element-name": "^1.0.1", + "lru-cache": "^11.3.5", + "parse5": "^8.0.1", + "saxes": "^6.0.0", + "symbol-tree": "^3.2.4", + "tough-cookie": "^6.0.1", + "undici": "^7.25.0", + "w3c-xmlserializer": "^5.0.0", + "webidl-conversions": "^8.0.1", + "whatwg-mimetype": "^5.0.0", + "whatwg-url": "^16.0.1", + "xml-name-validator": "^5.0.0" + }, + "engines": { + "node": "^20.19.0 || ^22.13.0 || >=24.0.0" + }, + "peerDependencies": { + "canvas": "^3.0.0" + }, + "peerDependenciesMeta": { + "canvas": { + "optional": true + } + } + }, + "node_modules/jsdom/node_modules/lru-cache": { + "version": "11.5.0", + "resolved": "https://registry.npmmirror.com/lru-cache/-/lru-cache-11.5.0.tgz", + "integrity": "sha512-5YgH9UJd7wVb9hIouI2adWpgqrrICkt070Dnj8EUY1+B4B2P9eRLPAkAAo6NICA7CEhOIeBHl46u9zSNpNu7zA==", + "dev": true, + "license": "BlueOak-1.0.0", + "engines": { + "node": "20 || >=22" + } + }, "node_modules/json-buffer": { "version": "3.0.1", "resolved": "https://registry.npmmirror.com/json-buffer/-/json-buffer-3.0.1.tgz", @@ -4948,6 +6181,267 @@ "node": ">= 0.8.0" } }, + "node_modules/lightningcss": { + "version": "1.32.0", + "resolved": "https://registry.npmmirror.com/lightningcss/-/lightningcss-1.32.0.tgz", + "integrity": "sha512-NXYBzinNrblfraPGyrbPoD19C1h9lfI/1mzgWYvXUTe414Gz/X1FD2XBZSZM7rRTrMA8JL3OtAaGifrIKhQ5yQ==", + "dev": true, + "license": "MPL-2.0", + "dependencies": { + "detect-libc": "^2.0.3" + }, + "engines": { + "node": ">= 12.0.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/parcel" + }, + "optionalDependencies": { + "lightningcss-android-arm64": "1.32.0", + "lightningcss-darwin-arm64": "1.32.0", + "lightningcss-darwin-x64": "1.32.0", + "lightningcss-freebsd-x64": "1.32.0", + "lightningcss-linux-arm-gnueabihf": "1.32.0", + "lightningcss-linux-arm64-gnu": "1.32.0", + "lightningcss-linux-arm64-musl": "1.32.0", + "lightningcss-linux-x64-gnu": "1.32.0", + "lightningcss-linux-x64-musl": "1.32.0", + "lightningcss-win32-arm64-msvc": "1.32.0", + "lightningcss-win32-x64-msvc": "1.32.0" + } + }, + "node_modules/lightningcss-android-arm64": { + "version": "1.32.0", + "resolved": "https://registry.npmmirror.com/lightningcss-android-arm64/-/lightningcss-android-arm64-1.32.0.tgz", + "integrity": "sha512-YK7/ClTt4kAK0vo6w3X+Pnm0D2cf2vPHbhOXdoNti1Ga0al1P4TBZhwjATvjNwLEBCnKvjJc2jQgHXH0NEwlAg==", + "cpu": [ + "arm64" + ], + "dev": true, + "license": "MPL-2.0", + "optional": true, + "os": [ + "android" + ], + "engines": { + "node": ">= 12.0.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/parcel" + } + }, + "node_modules/lightningcss-darwin-arm64": { + "version": "1.32.0", + "resolved": "https://registry.npmmirror.com/lightningcss-darwin-arm64/-/lightningcss-darwin-arm64-1.32.0.tgz", + "integrity": "sha512-RzeG9Ju5bag2Bv1/lwlVJvBE3q6TtXskdZLLCyfg5pt+HLz9BqlICO7LZM7VHNTTn/5PRhHFBSjk5lc4cmscPQ==", + "cpu": [ + "arm64" + ], + "dev": true, + "license": "MPL-2.0", + "optional": true, + "os": [ + "darwin" + ], + "engines": { + "node": ">= 12.0.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/parcel" + } + }, + "node_modules/lightningcss-darwin-x64": { + "version": "1.32.0", + "resolved": "https://registry.npmmirror.com/lightningcss-darwin-x64/-/lightningcss-darwin-x64-1.32.0.tgz", + "integrity": "sha512-U+QsBp2m/s2wqpUYT/6wnlagdZbtZdndSmut/NJqlCcMLTWp5muCrID+K5UJ6jqD2BFshejCYXniPDbNh73V8w==", + "cpu": [ + "x64" + ], + "dev": true, + "license": "MPL-2.0", + "optional": true, + "os": [ + "darwin" + ], + "engines": { + "node": ">= 12.0.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/parcel" + } + }, + "node_modules/lightningcss-freebsd-x64": { + "version": "1.32.0", + "resolved": "https://registry.npmmirror.com/lightningcss-freebsd-x64/-/lightningcss-freebsd-x64-1.32.0.tgz", + "integrity": "sha512-JCTigedEksZk3tHTTthnMdVfGf61Fky8Ji2E4YjUTEQX14xiy/lTzXnu1vwiZe3bYe0q+SpsSH/CTeDXK6WHig==", + "cpu": [ + "x64" + ], + "dev": true, + "license": "MPL-2.0", + "optional": true, + "os": [ + "freebsd" + ], + "engines": { + "node": ">= 12.0.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/parcel" + } + }, + "node_modules/lightningcss-linux-arm-gnueabihf": { + "version": "1.32.0", + "resolved": "https://registry.npmmirror.com/lightningcss-linux-arm-gnueabihf/-/lightningcss-linux-arm-gnueabihf-1.32.0.tgz", + "integrity": "sha512-x6rnnpRa2GL0zQOkt6rts3YDPzduLpWvwAF6EMhXFVZXD4tPrBkEFqzGowzCsIWsPjqSK+tyNEODUBXeeVHSkw==", + "cpu": [ + "arm" + ], + "dev": true, + "license": "MPL-2.0", + "optional": true, + "os": [ + "linux" + ], + "engines": { + "node": ">= 12.0.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/parcel" + } + }, + "node_modules/lightningcss-linux-arm64-gnu": { + "version": "1.32.0", + "resolved": "https://registry.npmmirror.com/lightningcss-linux-arm64-gnu/-/lightningcss-linux-arm64-gnu-1.32.0.tgz", + "integrity": "sha512-0nnMyoyOLRJXfbMOilaSRcLH3Jw5z9HDNGfT/gwCPgaDjnx0i8w7vBzFLFR1f6CMLKF8gVbebmkUN3fa/kQJpQ==", + "cpu": [ + "arm64" + ], + "dev": true, + "license": "MPL-2.0", + "optional": true, + "os": [ + "linux" + ], + "engines": { + "node": ">= 12.0.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/parcel" + } + }, + "node_modules/lightningcss-linux-arm64-musl": { + "version": "1.32.0", + "resolved": "https://registry.npmmirror.com/lightningcss-linux-arm64-musl/-/lightningcss-linux-arm64-musl-1.32.0.tgz", + "integrity": "sha512-UpQkoenr4UJEzgVIYpI80lDFvRmPVg6oqboNHfoH4CQIfNA+HOrZ7Mo7KZP02dC6LjghPQJeBsvXhJod/wnIBg==", + "cpu": [ + "arm64" + ], + "dev": true, + "license": "MPL-2.0", + "optional": true, + "os": [ + "linux" + ], + "engines": { + "node": ">= 12.0.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/parcel" + } + }, + "node_modules/lightningcss-linux-x64-gnu": { + "version": "1.32.0", + "resolved": "https://registry.npmmirror.com/lightningcss-linux-x64-gnu/-/lightningcss-linux-x64-gnu-1.32.0.tgz", + "integrity": "sha512-V7Qr52IhZmdKPVr+Vtw8o+WLsQJYCTd8loIfpDaMRWGUZfBOYEJeyJIkqGIDMZPwPx24pUMfwSxxI8phr/MbOA==", + "cpu": [ + "x64" + ], + "dev": true, + "license": "MPL-2.0", + "optional": true, + "os": [ + "linux" + ], + "engines": { + "node": ">= 12.0.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/parcel" + } + }, + "node_modules/lightningcss-linux-x64-musl": { + "version": "1.32.0", + "resolved": "https://registry.npmmirror.com/lightningcss-linux-x64-musl/-/lightningcss-linux-x64-musl-1.32.0.tgz", + "integrity": "sha512-bYcLp+Vb0awsiXg/80uCRezCYHNg1/l3mt0gzHnWV9XP1W5sKa5/TCdGWaR/zBM2PeF/HbsQv/j2URNOiVuxWg==", + "cpu": [ + "x64" + ], + "dev": true, + "license": "MPL-2.0", + "optional": true, + "os": [ + "linux" + ], + "engines": { + "node": ">= 12.0.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/parcel" + } + }, + "node_modules/lightningcss-win32-arm64-msvc": { + "version": "1.32.0", + "resolved": "https://registry.npmmirror.com/lightningcss-win32-arm64-msvc/-/lightningcss-win32-arm64-msvc-1.32.0.tgz", + "integrity": "sha512-8SbC8BR40pS6baCM8sbtYDSwEVQd4JlFTOlaD3gWGHfThTcABnNDBda6eTZeqbofalIJhFx0qKzgHJmcPTnGdw==", + "cpu": [ + "arm64" + ], + "dev": true, + "license": "MPL-2.0", + "optional": true, + "os": [ + "win32" + ], + "engines": { + "node": ">= 12.0.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/parcel" + } + }, + "node_modules/lightningcss-win32-x64-msvc": { + "version": "1.32.0", + "resolved": "https://registry.npmmirror.com/lightningcss-win32-x64-msvc/-/lightningcss-win32-x64-msvc-1.32.0.tgz", + "integrity": "sha512-Amq9B/SoZYdDi1kFrojnoqPLxYhQ4Wo5XiL8EVJrVsB8ARoC1PWW6VGtT0WKCemjy8aC+louJnjS7U18x3b06Q==", + "cpu": [ + "x64" + ], + "dev": true, + "license": "MPL-2.0", + "optional": true, + "os": [ + "win32" + ], + "engines": { + "node": ">= 12.0.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/parcel" + } + }, "node_modules/lilconfig": { "version": "3.1.3", "resolved": "https://registry.npmmirror.com/lilconfig/-/lilconfig-3.1.3.tgz", @@ -5023,6 +6517,55 @@ "react": "^16.5.1 || ^17.0.0 || ^18.0.0 || ^19.0.0" } }, + "node_modules/lz-string": { + "version": "1.5.0", + "resolved": "https://registry.npmmirror.com/lz-string/-/lz-string-1.5.0.tgz", + "integrity": "sha512-h5bgJWpxJNswbU7qCrV0tIKQCaS3blPDrqKWx+QxzuzL1zGUzij9XCWLrSLsJPu5t+eWA/ycetzYAO5IOMcWAQ==", + "dev": true, + "license": "MIT", + "peer": true, + "bin": { + "lz-string": "bin/bin.js" + } + }, + "node_modules/magic-string": { + "version": "0.30.21", + "resolved": "https://registry.npmmirror.com/magic-string/-/magic-string-0.30.21.tgz", + "integrity": "sha512-vd2F4YUyEXKGcLHoq+TEyCjxueSeHnFxyyjNp80yg0XV4vUhnDer/lvvlqM/arB5bXQN5K2/3oinyCRyx8T2CQ==", + "dev": true, + "license": "MIT", + "dependencies": { + "@jridgewell/sourcemap-codec": "^1.5.5" + } + }, + "node_modules/magicast": { + "version": "0.5.3", + "resolved": "https://registry.npmmirror.com/magicast/-/magicast-0.5.3.tgz", + "integrity": "sha512-pVKE4UdSQ7DvHzivsCIFx2BJn1mHG6KsyrFcaxFx6tONdneEuThrDx0Cj3AMg58KyN4pzYT+LHOotxDQDjNvkw==", + "dev": true, + "license": "MIT", + "dependencies": { + "@babel/parser": "^7.29.3", + "@babel/types": "^7.29.0", + "source-map-js": "^1.2.1" + } + }, + "node_modules/make-dir": { + "version": "4.0.0", + "resolved": "https://registry.npmmirror.com/make-dir/-/make-dir-4.0.0.tgz", + "integrity": "sha512-hXdUTZYIVOt1Ex//jAQi+wTZZpUpwBj/0QsOzqegb3rGMMeJiSEu5xLHnYfBrRV4RH2+OCSOO95Is/7x1WJ4bw==", + "dev": true, + "license": "MIT", + "dependencies": { + "semver": "^7.5.3" + }, + "engines": { + "node": ">=10" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, "node_modules/math-intrinsics": { "version": "1.1.0", "resolved": "https://registry.npmmirror.com/math-intrinsics/-/math-intrinsics-1.1.0.tgz", @@ -5033,6 +6576,13 @@ "node": ">= 0.4" } }, + "node_modules/mdn-data": { + "version": "2.27.1", + "resolved": "https://registry.npmmirror.com/mdn-data/-/mdn-data-2.27.1.tgz", + "integrity": "sha512-9Yubnt3e8A0OKwxYSXyhLymGW4sCufcLG6VdiDdUGVkPhpqLxlvP5vl1983gQjJl3tqbrM731mjaZaP68AgosQ==", + "dev": true, + "license": "CC0-1.0" + }, "node_modules/merge2": { "version": "1.4.1", "resolved": "https://registry.npmmirror.com/merge2/-/merge2-1.4.1.tgz", @@ -5055,6 +6605,16 @@ "node": ">=8.6" } }, + "node_modules/min-indent": { + "version": "1.0.1", + "resolved": "https://registry.npmmirror.com/min-indent/-/min-indent-1.0.1.tgz", + "integrity": "sha512-I9jwMn07Sy/IwOj3zVkVik2JTvgpaykDZEigL6Rx6N9LbMywwUSMtxET+7lVoDLLd3O3IXwJwvuuns8UB/HeAg==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=4" + } + }, "node_modules/minimatch": { "version": "3.1.5", "resolved": "https://registry.npmmirror.com/minimatch/-/minimatch-3.1.5.tgz", @@ -5107,9 +6667,9 @@ } }, "node_modules/nanoid": { - "version": "3.3.11", - "resolved": "https://registry.npmmirror.com/nanoid/-/nanoid-3.3.11.tgz", - "integrity": "sha512-N8SpfPUnUp1bK+PMYW8qSWdl9U+wwNWI4QKxOYDy9JAro3WMX7p2OeVRF9v+347pnakNevPmiHhNmZ2HbFA76w==", + "version": "3.3.12", + "resolved": "https://registry.npmmirror.com/nanoid/-/nanoid-3.3.12.tgz", + "integrity": "sha512-ZB9RH/39qpq5Vu6Y+NmUaFhQR6pp+M2Xt76XBnEwDaGcVAqhlvxrl3B2bKS5D3NH3QR76v3aSrKaF/Kiy7lEtQ==", "funding": [ { "type": "github", @@ -5432,6 +6992,17 @@ "url": "https://github.com/sponsors/ljharb" } }, + "node_modules/obug": { + "version": "2.1.1", + "resolved": "https://registry.npmmirror.com/obug/-/obug-2.1.1.tgz", + "integrity": "sha512-uTqF9MuPraAQ+IsnPf366RG4cP9RtUi7MLO1N3KEc+wb0a6yKpeL0lmk2IB1jY5KHPAlTc6T/JRdC/YqxHNwkQ==", + "dev": true, + "funding": [ + "https://github.com/sponsors/sxzz", + "https://opencollective.com/debug" + ], + "license": "MIT" + }, "node_modules/oidc-token-hash": { "version": "5.2.0", "resolved": "https://registry.npmmirror.com/oidc-token-hash/-/oidc-token-hash-5.2.0.tgz", @@ -5568,6 +7139,19 @@ "node": ">=6" } }, + "node_modules/parse5": { + "version": "8.0.1", + "resolved": "https://registry.npmmirror.com/parse5/-/parse5-8.0.1.tgz", + "integrity": "sha512-z1e/HMG90obSGeidlli3hj7cbocou0/wa5HacvI3ASx34PecNjNQeaHNo5WIZpWofN9kgkqV1q5YvXe3F0FoPw==", + "dev": true, + "license": "MIT", + "dependencies": { + "entities": "^8.0.0" + }, + "funding": { + "url": "https://github.com/inikulin/parse5?sponsor=1" + } + }, "node_modules/path-exists": { "version": "4.0.0", "resolved": "https://registry.npmmirror.com/path-exists/-/path-exists-4.0.0.tgz", @@ -5621,6 +7205,13 @@ "url": "https://github.com/sponsors/isaacs" } }, + "node_modules/pathe": { + "version": "2.0.3", + "resolved": "https://registry.npmmirror.com/pathe/-/pathe-2.0.3.tgz", + "integrity": "sha512-WUjGcAqP1gQacoQe+OBJsFA7Ld4DyXuUIjZ5cc75cLHvJ7dtNsTugphxIADwspS+AraAUePCKrSVtPLFj/F88w==", + "dev": true, + "license": "MIT" + }, "node_modules/picocolors": { "version": "1.1.1", "resolved": "https://registry.npmmirror.com/picocolors/-/picocolors-1.1.1.tgz", @@ -5658,13 +7249,13 @@ } }, "node_modules/playwright": { - "version": "1.59.1", - "resolved": "https://registry.npmmirror.com/playwright/-/playwright-1.59.1.tgz", - "integrity": "sha512-C8oWjPR3F81yljW9o5OxcWzfh6avkVwDD2VYdwIGqTkl+OGFISgypqzfu7dOe4QNLL2aqcWBmI3PMtLIK233lw==", + "version": "1.60.0", + "resolved": "https://registry.npmmirror.com/playwright/-/playwright-1.60.0.tgz", + "integrity": "sha512-hheHdokM8cdqCb0lcE3s+zT4t4W+vvjpGxsZlDnikarzx8tSzMebh3UiFtgqwFwnTnjYQcsyMF8ei2mCO/tpeA==", "devOptional": true, "license": "Apache-2.0", "dependencies": { - "playwright-core": "1.59.1" + "playwright-core": "1.60.0" }, "bin": { "playwright": "cli.js" @@ -5677,9 +7268,9 @@ } }, "node_modules/playwright-core": { - "version": "1.59.1", - "resolved": "https://registry.npmmirror.com/playwright-core/-/playwright-core-1.59.1.tgz", - "integrity": "sha512-HBV/RJg81z5BiiZ9yPzIiClYV/QMsDCKUyogwH9p3MCP6IYjUFu/MActgYAvK0oWyV9NlwM3GLBjADyWgydVyg==", + "version": "1.60.0", + "resolved": "https://registry.npmmirror.com/playwright-core/-/playwright-core-1.60.0.tgz", + "integrity": "sha512-9bW6zvX/m0lEbgTKJ6YppOKx8H3VOPBMOCFh2irXFOT4BbHgrx5hPjwJYLT40Lu+4qtD36qKc/Hn56StUW57IA==", "devOptional": true, "license": "Apache-2.0", "bin": { @@ -5714,9 +7305,9 @@ } }, "node_modules/postcss": { - "version": "8.5.10", - "resolved": "https://registry.npmmirror.com/postcss/-/postcss-8.5.10.tgz", - "integrity": "sha512-pMMHxBOZKFU6HgAZ4eyGnwXF/EvPGGqUr0MnZ5+99485wwW41kW91A4LOGxSHhgugZmSChL5AlElNdwlNgcnLQ==", + "version": "8.5.15", + "resolved": "https://registry.npmmirror.com/postcss/-/postcss-8.5.15.tgz", + "integrity": "sha512-FfR8sjd4em2T6fb3I2MwAJU7HWVMr9zba+enmQeeWFfCbm+UOC/0X4DS8XtpUTMwWMGbjKYP7xjfNekzyGmB3A==", "funding": [ { "type": "opencollective", @@ -5733,7 +7324,7 @@ ], "license": "MIT", "dependencies": { - "nanoid": "^3.3.11", + "nanoid": "^3.3.12", "picocolors": "^1.1.1", "source-map-js": "^1.2.1" }, @@ -6159,6 +7750,20 @@ "integrity": "sha512-/LLMVyas0ljjAtoYiPqYiL8VWXzUUdThrmU5+n20DZv+a+ClRoevUzw5JxU+Ieh5/c87ytoTBV9G1FiKfNJdmg==", "license": "MIT" }, + "node_modules/redent": { + "version": "3.0.0", + "resolved": "https://registry.npmmirror.com/redent/-/redent-3.0.0.tgz", + "integrity": "sha512-6tDA8g98We0zd0GvVeMT9arEOnTw9qM03L9cJXaCjrip1OO764RDBLBfrB4cwzNGDj5OA5ioymC9GkizgWJDUg==", + "dev": true, + "license": "MIT", + "dependencies": { + "indent-string": "^4.0.0", + "strip-indent": "^3.0.0" + }, + "engines": { + "node": ">=8" + } + }, "node_modules/reflect.getprototypeof": { "version": "1.0.10", "resolved": "https://registry.npmmirror.com/reflect.getprototypeof/-/reflect.getprototypeof-1.0.10.tgz", @@ -6203,6 +7808,16 @@ "url": "https://github.com/sponsors/ljharb" } }, + "node_modules/require-from-string": { + "version": "2.0.2", + "resolved": "https://registry.npmmirror.com/require-from-string/-/require-from-string-2.0.2.tgz", + "integrity": "sha512-Xf0nWe6RseziFMu+Ap9biiUbmplq6S9/p+7w7YXP/JBHhrUDDUhwa+vANyubuqfZWTveU//DYVGsDG7RKL/vEw==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=0.10.0" + } + }, "node_modules/resolve": { "version": "2.0.0-next.6", "resolved": "https://registry.npmmirror.com/resolve/-/resolve-2.0.0-next.6.tgz", @@ -6296,6 +7911,40 @@ "url": "https://github.com/sponsors/isaacs" } }, + "node_modules/rolldown": { + "version": "1.0.2", + "resolved": "https://registry.npmmirror.com/rolldown/-/rolldown-1.0.2.tgz", + "integrity": "sha512-oZx5zVDtVB44AW3eaifgDml1gWRDZGvjcfdxonE4swNPG98PrrXjaO/KrnUjzlMnztCCRVlUueA1kCXhARGk6g==", + "dev": true, + "license": "MIT", + "dependencies": { + "@oxc-project/types": "=0.132.0", + "@rolldown/pluginutils": "^1.0.0" + }, + "bin": { + "rolldown": "bin/cli.mjs" + }, + "engines": { + "node": "^20.19.0 || >=22.12.0" + }, + "optionalDependencies": { + "@rolldown/binding-android-arm64": "1.0.2", + "@rolldown/binding-darwin-arm64": "1.0.2", + "@rolldown/binding-darwin-x64": "1.0.2", + "@rolldown/binding-freebsd-x64": "1.0.2", + "@rolldown/binding-linux-arm-gnueabihf": "1.0.2", + "@rolldown/binding-linux-arm64-gnu": "1.0.2", + "@rolldown/binding-linux-arm64-musl": "1.0.2", + "@rolldown/binding-linux-ppc64-gnu": "1.0.2", + "@rolldown/binding-linux-s390x-gnu": "1.0.2", + "@rolldown/binding-linux-x64-gnu": "1.0.2", + "@rolldown/binding-linux-x64-musl": "1.0.2", + "@rolldown/binding-openharmony-arm64": "1.0.2", + "@rolldown/binding-wasm32-wasi": "1.0.2", + "@rolldown/binding-win32-arm64-msvc": "1.0.2", + "@rolldown/binding-win32-x64-msvc": "1.0.2" + } + }, "node_modules/run-parallel": { "version": "1.2.0", "resolved": "https://registry.npmmirror.com/run-parallel/-/run-parallel-1.2.0.tgz", @@ -6374,6 +8023,19 @@ "url": "https://github.com/sponsors/ljharb" } }, + "node_modules/saxes": { + "version": "6.0.0", + "resolved": "https://registry.npmmirror.com/saxes/-/saxes-6.0.0.tgz", + "integrity": "sha512-xAg7SOnEhrm5zI3puOOKyy1OMcMlIJZYNJY7xLBwSze0UjhPLnWfj2GF2EpT0jmzaJKIWKHLsaSSajf35bcYnA==", + "dev": true, + "license": "ISC", + "dependencies": { + "xmlchars": "^2.2.0" + }, + "engines": { + "node": ">=v12.22.7" + } + }, "node_modules/scheduler": { "version": "0.23.2", "resolved": "https://registry.npmmirror.com/scheduler/-/scheduler-0.23.2.tgz", @@ -6544,6 +8206,13 @@ "url": "https://github.com/sponsors/ljharb" } }, + "node_modules/siginfo": { + "version": "2.0.0", + "resolved": "https://registry.npmmirror.com/siginfo/-/siginfo-2.0.0.tgz", + "integrity": "sha512-ybx0WO1/8bSBLEWXZvEd7gMW3Sn3JFlW3TvX1nREbDLRNQNaeNN8WK0meBwPdAaOI7TtRRRJn/Es1zhrrCHu7g==", + "dev": true, + "license": "ISC" + }, "node_modules/signal-exit": { "version": "4.1.0", "resolved": "https://registry.npmmirror.com/signal-exit/-/signal-exit-4.1.0.tgz", @@ -6573,6 +8242,20 @@ "dev": true, "license": "MIT" }, + "node_modules/stackback": { + "version": "0.0.2", + "resolved": "https://registry.npmmirror.com/stackback/-/stackback-0.0.2.tgz", + "integrity": "sha512-1XMJE5fQo1jGH6Y/7ebnwPOBEkIEnT4QF32d5R1+VXdXveM0IBMJt8zfaxX1P3QhVwrYe+576+jkANtSS2mBbw==", + "dev": true, + "license": "MIT" + }, + "node_modules/std-env": { + "version": "4.1.0", + "resolved": "https://registry.npmmirror.com/std-env/-/std-env-4.1.0.tgz", + "integrity": "sha512-Rq7ybcX2RuC55r9oaPVEW7/xu3tj8u4GeBYHBWCychFtzMIr86A7e3PPEBPT37sHStKX3+TiX/Fr/ACmJLVlLQ==", + "dev": true, + "license": "MIT" + }, "node_modules/stop-iteration-iterator": { "version": "1.1.0", "resolved": "https://registry.npmmirror.com/stop-iteration-iterator/-/stop-iteration-iterator-1.1.0.tgz", @@ -6815,6 +8498,19 @@ "node": ">=4" } }, + "node_modules/strip-indent": { + "version": "3.0.0", + "resolved": "https://registry.npmmirror.com/strip-indent/-/strip-indent-3.0.0.tgz", + "integrity": "sha512-laJTa3Jb+VQpaC6DseHhF7dXVqHTfJPCRDaEbid/drOhgitgYku/letMUqOXFoWV0zIIUbjpdH2t+tYj4bQMRQ==", + "dev": true, + "license": "MIT", + "dependencies": { + "min-indent": "^1.0.0" + }, + "engines": { + "node": ">=8" + } + }, "node_modules/strip-json-comments": { "version": "3.1.1", "resolved": "https://registry.npmmirror.com/strip-json-comments/-/strip-json-comments-3.1.1.tgz", @@ -6898,6 +8594,26 @@ "url": "https://github.com/sponsors/ljharb" } }, + "node_modules/swr": { + "version": "2.4.1", + "resolved": "https://registry.npmmirror.com/swr/-/swr-2.4.1.tgz", + "integrity": "sha512-2CC6CiKQtEwaEeNiqWTAw9PGykW8SR5zZX8MZk6TeAvEAnVS7Visz8WzphqgtQ8v2xz/4Q5K+j+SeMaKXeeQIA==", + "license": "MIT", + "dependencies": { + "dequal": "^2.0.3", + "use-sync-external-store": "^1.6.0" + }, + "peerDependencies": { + "react": "^16.11.0 || ^17.0.0 || ^18.0.0 || ^19.0.0" + } + }, + "node_modules/symbol-tree": { + "version": "3.2.4", + "resolved": "https://registry.npmmirror.com/symbol-tree/-/symbol-tree-3.2.4.tgz", + "integrity": "sha512-9QNk5KwDF+Bvz+PyObkmSYjI5ksVUYtjW7AU22r2NKcfLJcXp96hkDWU3+XndOsUb+AQ9QhfzfCT2O+CNWT5Tw==", + "dev": true, + "license": "MIT" + }, "node_modules/tailwind-merge": { "version": "3.5.0", "resolved": "https://registry.npmmirror.com/tailwind-merge/-/tailwind-merge-3.5.0.tgz", @@ -7009,6 +8725,23 @@ "integrity": "sha512-+FbBPE1o9QAYvviau/qC5SE3caw21q3xkvWKBtja5vgqOWIHHJ3ioaq1VPfn/Szqctz2bU/oYeKd9/z5BL+PVg==", "license": "MIT" }, + "node_modules/tinybench": { + "version": "2.9.0", + "resolved": "https://registry.npmmirror.com/tinybench/-/tinybench-2.9.0.tgz", + "integrity": "sha512-0+DUvqWMValLmha6lr4kD8iAMK1HzV0/aKnCtWb9v9641TnP/MFb7Pc2bxoxQjTXAErryXVgUOfv2YqNllqGeg==", + "dev": true, + "license": "MIT" + }, + "node_modules/tinyexec": { + "version": "1.1.2", + "resolved": "https://registry.npmmirror.com/tinyexec/-/tinyexec-1.1.2.tgz", + "integrity": "sha512-dAqSqE/RabpBKI8+h26GfLq6Vb3JVXs30XYQjdMjaj/c2tS8IYYMbIzP599KtRj7c57/wYApb3QjgRgXmrCukA==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=18" + } + }, "node_modules/tinyglobby": { "version": "0.2.16", "resolved": "https://registry.npmmirror.com/tinyglobby/-/tinyglobby-0.2.16.tgz", @@ -7054,6 +8787,36 @@ "url": "https://github.com/sponsors/jonschlinkert" } }, + "node_modules/tinyrainbow": { + "version": "3.1.0", + "resolved": "https://registry.npmmirror.com/tinyrainbow/-/tinyrainbow-3.1.0.tgz", + "integrity": "sha512-Bf+ILmBgretUrdJxzXM0SgXLZ3XfiaUuOj/IKQHuTXip+05Xn+uyEYdVg0kYDipTBcLrCVyUzAPz7QmArb0mmw==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=14.0.0" + } + }, + "node_modules/tldts": { + "version": "7.0.30", + "resolved": "https://registry.npmmirror.com/tldts/-/tldts-7.0.30.tgz", + "integrity": "sha512-ELrFxuqsDdHUwoh0XxDbxuLD3Wnz49Z57IFvTtvWy1hJdcMZjXLIuonjilCiWHlT2GbE4Wlv1wKVTzDFnXH1aw==", + "dev": true, + "license": "MIT", + "dependencies": { + "tldts-core": "^7.0.30" + }, + "bin": { + "tldts": "bin/cli.js" + } + }, + "node_modules/tldts-core": { + "version": "7.0.30", + "resolved": "https://registry.npmmirror.com/tldts-core/-/tldts-core-7.0.30.tgz", + "integrity": "sha512-uiHN8PIB1VmWyS98eZYja4xzlYqeFZVjb4OuYlJQnZAuJhMw4PbKQOKgHKhBdJR3FE/t5mUQ1Kd80++B+qhD1Q==", + "dev": true, + "license": "MIT" + }, "node_modules/to-regex-range": { "version": "5.0.1", "resolved": "https://registry.npmmirror.com/to-regex-range/-/to-regex-range-5.0.1.tgz", @@ -7066,6 +8829,32 @@ "node": ">=8.0" } }, + "node_modules/tough-cookie": { + "version": "6.0.1", + "resolved": "https://registry.npmmirror.com/tough-cookie/-/tough-cookie-6.0.1.tgz", + "integrity": "sha512-LktZQb3IeoUWB9lqR5EWTHgW/VTITCXg4D21M+lvybRVdylLrRMnqaIONLVb5mav8vM19m44HIcGq4qASeu2Qw==", + "dev": true, + "license": "BSD-3-Clause", + "dependencies": { + "tldts": "^7.0.5" + }, + "engines": { + "node": ">=16" + } + }, + "node_modules/tr46": { + "version": "6.0.0", + "resolved": "https://registry.npmmirror.com/tr46/-/tr46-6.0.0.tgz", + "integrity": "sha512-bLVMLPtstlZ4iMQHpFHTR7GAGj2jxi8Dg0s2h2MafAE4uSWF98FC/3MomU51iQAMf8/qDUbKWf5GxuvvVcXEhw==", + "dev": true, + "license": "MIT", + "dependencies": { + "punycode": "^2.3.1" + }, + "engines": { + "node": ">=20" + } + }, "node_modules/ts-api-utils": { "version": "2.5.0", "resolved": "https://registry.npmmirror.com/ts-api-utils/-/ts-api-utils-2.5.0.tgz", @@ -7241,6 +9030,16 @@ "url": "https://github.com/sponsors/ljharb" } }, + "node_modules/undici": { + "version": "7.25.0", + "resolved": "https://registry.npmmirror.com/undici/-/undici-7.25.0.tgz", + "integrity": "sha512-xXnp4kTyor2Zq+J1FfPI6Eq3ew5h6Vl0F/8d9XU5zZQf1tX9s2Su1/3PiMmUANFULpmksxkClamIZcaUqryHsQ==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=20.18.1" + } + }, "node_modules/undici-types": { "version": "6.21.0", "resolved": "https://registry.npmmirror.com/undici-types/-/undici-types-6.21.0.tgz", @@ -7336,6 +9135,15 @@ } } }, + "node_modules/use-sync-external-store": { + "version": "1.6.0", + "resolved": "https://registry.npmmirror.com/use-sync-external-store/-/use-sync-external-store-1.6.0.tgz", + "integrity": "sha512-Pp6GSwGP/NrPIrxVFAIkOQeyw8lFenOHijQWkUTrDvrF4ALqylP2C/KCkeS9dpUM3KvYRQhna5vt7IL95+ZQ9w==", + "license": "MIT", + "peerDependencies": { + "react": "^16.8.0 || ^17.0.0 || ^18.0.0 || ^19.0.0" + } + }, "node_modules/util-deprecate": { "version": "1.0.2", "resolved": "https://registry.npmmirror.com/util-deprecate/-/util-deprecate-1.0.2.tgz", @@ -7373,6 +9181,248 @@ "d3-timer": "^3.0.1" } }, + "node_modules/vite": { + "version": "8.0.14", + "resolved": "https://registry.npmmirror.com/vite/-/vite-8.0.14.tgz", + "integrity": "sha512-s4BJJ+5y1pYL6Otw51FHhVJQhPnuRinKig64g/1+EUNaJsd3gCKdD31IPFvswUgW9/60QT9oFHbZHbQK5imcxw==", + "dev": true, + "license": "MIT", + "dependencies": { + "lightningcss": "^1.32.0", + "picomatch": "^4.0.4", + "postcss": "^8.5.15", + "rolldown": "1.0.2", + "tinyglobby": "^0.2.16" + }, + "bin": { + "vite": "bin/vite.js" + }, + "engines": { + "node": "^20.19.0 || >=22.12.0" + }, + "funding": { + "url": "https://github.com/vitejs/vite?sponsor=1" + }, + "optionalDependencies": { + "fsevents": "~2.3.3" + }, + "peerDependencies": { + "@types/node": "^20.19.0 || >=22.12.0", + "@vitejs/devtools": "^0.1.18", + "esbuild": "^0.27.0 || ^0.28.0", + "jiti": ">=1.21.0", + "less": "^4.0.0", + "sass": "^1.70.0", + "sass-embedded": "^1.70.0", + "stylus": ">=0.54.8", + "sugarss": "^5.0.0", + "terser": "^5.16.0", + "tsx": "^4.8.1", + "yaml": "^2.4.2" + }, + "peerDependenciesMeta": { + "@types/node": { + "optional": true + }, + "@vitejs/devtools": { + "optional": true + }, + "esbuild": { + "optional": true + }, + "jiti": { + "optional": true + }, + "less": { + "optional": true + }, + "sass": { + "optional": true + }, + "sass-embedded": { + "optional": true + }, + "stylus": { + "optional": true + }, + "sugarss": { + "optional": true + }, + "terser": { + "optional": true + }, + "tsx": { + "optional": true + }, + "yaml": { + "optional": true + } + } + }, + "node_modules/vite/node_modules/picomatch": { + "version": "4.0.4", + "resolved": "https://registry.npmmirror.com/picomatch/-/picomatch-4.0.4.tgz", + "integrity": "sha512-QP88BAKvMam/3NxH6vj2o21R6MjxZUAd6nlwAS/pnGvN9IVLocLHxGYIzFhg6fUQ+5th6P4dv4eW9jX3DSIj7A==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=12" + }, + "funding": { + "url": "https://github.com/sponsors/jonschlinkert" + } + }, + "node_modules/vitest": { + "version": "4.1.7", + "resolved": "https://registry.npmmirror.com/vitest/-/vitest-4.1.7.tgz", + "integrity": "sha512-flYyaFd2CgoCoU+0UKt3pxksgC+S02iTDN0n3LtqaMeXsI9SBcdNujc2k0DeFLzUn/0k538yNjOSdwgCqcrwJA==", + "dev": true, + "license": "MIT", + "dependencies": { + "@vitest/expect": "4.1.7", + "@vitest/mocker": "4.1.7", + "@vitest/pretty-format": "4.1.7", + "@vitest/runner": "4.1.7", + "@vitest/snapshot": "4.1.7", + "@vitest/spy": "4.1.7", + "@vitest/utils": "4.1.7", + "es-module-lexer": "^2.0.0", + "expect-type": "^1.3.0", + "magic-string": "^0.30.21", + "obug": "^2.1.1", + "pathe": "^2.0.3", + "picomatch": "^4.0.3", + "std-env": "^4.0.0-rc.1", + "tinybench": "^2.9.0", + "tinyexec": "^1.0.2", + "tinyglobby": "^0.2.15", + "tinyrainbow": "^3.1.0", + "vite": "^6.0.0 || ^7.0.0 || ^8.0.0", + "why-is-node-running": "^2.3.0" + }, + "bin": { + "vitest": "vitest.mjs" + }, + "engines": { + "node": "^20.0.0 || ^22.0.0 || >=24.0.0" + }, + "funding": { + "url": "https://opencollective.com/vitest" + }, + "peerDependencies": { + "@edge-runtime/vm": "*", + "@opentelemetry/api": "^1.9.0", + "@types/node": "^20.0.0 || ^22.0.0 || >=24.0.0", + "@vitest/browser-playwright": "4.1.7", + "@vitest/browser-preview": "4.1.7", + "@vitest/browser-webdriverio": "4.1.7", + "@vitest/coverage-istanbul": "4.1.7", + "@vitest/coverage-v8": "4.1.7", + "@vitest/ui": "4.1.7", + "happy-dom": "*", + "jsdom": "*", + "vite": "^6.0.0 || ^7.0.0 || ^8.0.0" + }, + "peerDependenciesMeta": { + "@edge-runtime/vm": { + "optional": true + }, + "@opentelemetry/api": { + "optional": true + }, + "@types/node": { + "optional": true + }, + "@vitest/browser-playwright": { + "optional": true + }, + "@vitest/browser-preview": { + "optional": true + }, + "@vitest/browser-webdriverio": { + "optional": true + }, + "@vitest/coverage-istanbul": { + "optional": true + }, + "@vitest/coverage-v8": { + "optional": true + }, + "@vitest/ui": { + "optional": true + }, + "happy-dom": { + "optional": true + }, + "jsdom": { + "optional": true + }, + "vite": { + "optional": false + } + } + }, + "node_modules/vitest/node_modules/picomatch": { + "version": "4.0.4", + "resolved": "https://registry.npmmirror.com/picomatch/-/picomatch-4.0.4.tgz", + "integrity": "sha512-QP88BAKvMam/3NxH6vj2o21R6MjxZUAd6nlwAS/pnGvN9IVLocLHxGYIzFhg6fUQ+5th6P4dv4eW9jX3DSIj7A==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=12" + }, + "funding": { + "url": "https://github.com/sponsors/jonschlinkert" + } + }, + "node_modules/w3c-xmlserializer": { + "version": "5.0.0", + "resolved": "https://registry.npmmirror.com/w3c-xmlserializer/-/w3c-xmlserializer-5.0.0.tgz", + "integrity": "sha512-o8qghlI8NZHU1lLPrpi2+Uq7abh4GGPpYANlalzWxyWteJOCsr/P+oPBA49TOLu5FTZO4d3F9MnWJfiMo4BkmA==", + "dev": true, + "license": "MIT", + "dependencies": { + "xml-name-validator": "^5.0.0" + }, + "engines": { + "node": ">=18" + } + }, + "node_modules/webidl-conversions": { + "version": "8.0.1", + "resolved": "https://registry.npmmirror.com/webidl-conversions/-/webidl-conversions-8.0.1.tgz", + "integrity": "sha512-BMhLD/Sw+GbJC21C/UgyaZX41nPt8bUTg+jWyDeg7e7YN4xOM05YPSIXceACnXVtqyEw/LMClUQMtMZ+PGGpqQ==", + "dev": true, + "license": "BSD-2-Clause", + "engines": { + "node": ">=20" + } + }, + "node_modules/whatwg-mimetype": { + "version": "5.0.0", + "resolved": "https://registry.npmmirror.com/whatwg-mimetype/-/whatwg-mimetype-5.0.0.tgz", + "integrity": "sha512-sXcNcHOC51uPGF0P/D4NVtrkjSU2fNsm9iog4ZvZJsL3rjoDAzXZhkm2MWt1y+PUdggKAYVoMAIYcs78wJ51Cw==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=20" + } + }, + "node_modules/whatwg-url": { + "version": "16.0.1", + "resolved": "https://registry.npmmirror.com/whatwg-url/-/whatwg-url-16.0.1.tgz", + "integrity": "sha512-1to4zXBxmXHV3IiSSEInrreIlu02vUOvrhxJJH5vcxYTBDAx51cqZiKdyTxlecdKNSjj8EcxGBxNf6Vg+945gw==", + "dev": true, + "license": "MIT", + "dependencies": { + "@exodus/bytes": "^1.11.0", + "tr46": "^6.0.0", + "webidl-conversions": "^8.0.1" + }, + "engines": { + "node": "^20.19.0 || ^22.12.0 || >=24.0.0" + } + }, "node_modules/which": { "version": "2.0.2", "resolved": "https://registry.npmmirror.com/which/-/which-2.0.2.tgz", @@ -7478,6 +9528,23 @@ "url": "https://github.com/sponsors/ljharb" } }, + "node_modules/why-is-node-running": { + "version": "2.3.0", + "resolved": "https://registry.npmmirror.com/why-is-node-running/-/why-is-node-running-2.3.0.tgz", + "integrity": "sha512-hUrmaWBdVDcxvYqnyh09zunKzROWjbZTiNy8dBEjkS7ehEDQibXJ7XvlmtbwuTclUiIyN+CyXQD4Vmko8fNm8w==", + "dev": true, + "license": "MIT", + "dependencies": { + "siginfo": "^2.0.0", + "stackback": "0.0.2" + }, + "bin": { + "why-is-node-running": "cli.js" + }, + "engines": { + "node": ">=8" + } + }, "node_modules/word-wrap": { "version": "1.2.5", "resolved": "https://registry.npmmirror.com/word-wrap/-/word-wrap-1.2.5.tgz", @@ -7596,6 +9663,23 @@ "dev": true, "license": "ISC" }, + "node_modules/xml-name-validator": { + "version": "5.0.0", + "resolved": "https://registry.npmmirror.com/xml-name-validator/-/xml-name-validator-5.0.0.tgz", + "integrity": "sha512-EvGK8EJ3DhaHfbRlETOWAS5pO9MZITeauHKJyb8wyajUfQUenkIg2MvLDTZ4T/TgIcm3HU0TFBgWWboAZ30UHg==", + "dev": true, + "license": "Apache-2.0", + "engines": { + "node": ">=18" + } + }, + "node_modules/xmlchars": { + "version": "2.2.0", + "resolved": "https://registry.npmmirror.com/xmlchars/-/xmlchars-2.2.0.tgz", + "integrity": "sha512-JZnDKK8B0RCDw84FNdDAIpZK+JuJw+s7Lz8nksI7SIuU3UXJJslUthsi+uWBUYOwPFwW7W7PRLRfUKpxjtjFCw==", + "dev": true, + "license": "MIT" + }, "node_modules/yallist": { "version": "4.0.0", "resolved": "https://registry.npmmirror.com/yallist/-/yallist-4.0.0.tgz", @@ -7614,6 +9698,35 @@ "funding": { "url": "https://github.com/sponsors/sindresorhus" } + }, + "node_modules/zustand": { + "version": "5.0.13", + "resolved": "https://registry.npmmirror.com/zustand/-/zustand-5.0.13.tgz", + "integrity": "sha512-efI2tVaVQPqtOh114loML/Z80Y4NP3yc+Ff0fYiZJPauNeWZeIp/bRFD7I9bfmCOYBh/PHxlglQ9+wvlwnPikQ==", + "license": "MIT", + "engines": { + "node": ">=12.20.0" + }, + "peerDependencies": { + "@types/react": ">=18.0.0", + "immer": ">=9.0.6", + "react": ">=18.0.0", + "use-sync-external-store": ">=1.2.0" + }, + "peerDependenciesMeta": { + "@types/react": { + "optional": true + }, + "immer": { + "optional": true + }, + "react": { + "optional": true + }, + "use-sync-external-store": { + "optional": true + } + } } } } diff --git a/frontend/package.json b/frontend/package.json index 7084023..3287b31 100644 --- a/frontend/package.json +++ b/frontend/package.json @@ -9,7 +9,9 @@ "lint": "next lint", "test:e2e": "playwright test", "test:e2e:ui": "playwright test --ui", - "test:e2e:headed": "playwright test --headed" + "test:e2e:headed": "playwright test --headed", + "test": "vitest", + "test:ci": "vitest run --coverage" }, "dependencies": { "@radix-ui/react-dialog": "^1.1.15", @@ -27,18 +29,26 @@ "react": "^18", "react-dom": "^18", "recharts": "^2.15.4", + "swr": "^2.4.1", "tailwind-merge": "^3.5.0", - "tailwindcss-animate": "^1.0.7" + "tailwindcss-animate": "^1.0.7", + "zustand": "^5.0.13" }, "devDependencies": { - "@playwright/test": "^1.59.1", + "@playwright/test": "^1.60.0", + "@testing-library/jest-dom": "^6.9.1", + "@testing-library/react": "^16.3.2", "@types/node": "^20", "@types/react": "^18", "@types/react-dom": "^18", + "@vitejs/plugin-react": "^6.0.2", + "@vitest/coverage-v8": "^4.1.7", "eslint": "^8", "eslint-config-next": "14.2.35", + "jsdom": "^29.1.1", "postcss": "^8", "tailwindcss": "^3.4.1", - "typescript": "^5" + "typescript": "^5", + "vitest": "^4.1.7" } } diff --git a/frontend/playwright-report/data/02c38299aac52370c08620b8c68905e55ba39c4b.png b/frontend/playwright-report/data/02c38299aac52370c08620b8c68905e55ba39c4b.png deleted file mode 100644 index 6d4dec9518ec057407e5154954ab5cb8d6231447..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 27041 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 M*Ds4-y#4rJ09dd6xc~qF diff --git a/frontend/playwright-report/data/050b25ad409e051f9fc12fa8d03dd42cc4eb465a.zip b/frontend/playwright-report/data/050b25ad409e051f9fc12fa8d03dd42cc4eb465a.zip deleted file mode 100644 index 9daed0aadc5e17d0e8b568b9e119d0316c31e43b..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 356984 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 @M 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�`q!Hha*Bqzo$(DUv&kkHdFu!s;H&{iSnr_oJ42`ixSR6E__;J zGPa=BWI74P$-QXwIY%VwJ6CIjp5Ndl2v9M)vN9a_T-;wtUnXPP0u^gJ{Zhvaw}?w< zjo0ZHyz5$9W3D8@o@T71t#mjqQQaT~*Kf(+I8JZOG}N(NBXJP(EqL6KVP0T+%L)Rf z!p_ZR<%uE^EtW{Pc2a4xiF>OtmlGBVmTMxb=?WN7N(wQFL#SHWpTy$LEPSG_$40-s z3kQe6Ppr5r#7a|KjnlYfTxjwu;6VEhpX_3{Ww`L4 zKly8HYe5@7@v2%lj?By*jNqaAqja zt3AEj?)KD3Pn!?bH4dLHDj_%{w*X>380zlg)_Eg=b&#%b{~*uc)35i69``Y zmDi!Z{dT)duKg{uiV%ixBqel+XdLVh8EEnyjfhY=MnMu9qXHwr?C!Yxwh#E0rw;+K zH_tyxwY1X-T<}1gTh5!p9*CfooG39sp*8R2>)92yYKw;{Y6XIr6QcgXLP7=~-r@oV!HL%7Zo> z`KDOEeB;L78tdGpIVHWaW7l9tpKhKAY|9BbQ$24LU5FHw3Km98QJ^=aqD9qiv&8iM zcGu(6jT!kTH2wX7h4f*%0A^G0@J-hXs;0 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 z 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

#B-3wI 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 健康状态Dashboard - 响应式设计测试 >> 移动端视口下概览卡片堆叠显示 -- Location: e2e/tests/dashboard-health.spec.ts:239:7 - -# Error details - -``` -Error: expect(locator).toBeVisible() failed - -Locator: locator('text=综合评分').first() -Expected: visible -Timeout: 10000ms -Error: element(s) not found - -Call log: - - Expect "toBeVisible" with timeout 10000ms - - waiting for locator('text=综合评分').first() - -``` - -# Page snapshot - -```yaml -- generic [active] [ref=e1]: - - alert [ref=e2] - - generic [ref=e3]: - - complementary [ref=e4]: - - generic [ref=e6]: GEO Platform - - navigation [ref=e7]: - - link "数据总览" [ref=e8] [cursor=pointer]: - - /url: /dashboard - - img [ref=e9] - - text: 数据总览 - - link "品牌管理" [ref=e14] [cursor=pointer]: - - /url: /brands - - img [ref=e15] - - text: 品牌管理 - - link "竞品对比" [ref=e17] [cursor=pointer]: - - /url: /compare - - img [ref=e18] - - text: 竞品对比 - - link "查询管理" [ref=e23] [cursor=pointer]: - - /url: /dashboard/queries - - img [ref=e24] - - text: 查询管理 - - link "引用记录" [ref=e27] [cursor=pointer]: - - /url: /dashboard/citations - - img [ref=e28] - - text: 引用记录 - - link "报告导出" [ref=e31] [cursor=pointer]: - - /url: /dashboard/reports - - img [ref=e32] - - text: 报告导出 - - link "设置" [ref=e36] [cursor=pointer]: - - /url: /dashboard/settings - - img [ref=e37] - - text: 设置 - - link "管理后台" [ref=e40] [cursor=pointer]: - - /url: /dashboard/admin - - img [ref=e41] - - text: 管理后台 - - generic [ref=e43]: - - banner [ref=e44]: - - heading "GEO Platform" [level=1] [ref=e45] - - generic [ref=e46]: - - generic [ref=e47]: - - img [ref=e48] - - generic [ref=e51]: 管理员 - - button "退出登录" [ref=e52] [cursor=pointer]: - - img [ref=e53] - - text: 退出登录 - - main [ref=e56]: - - generic [ref=e57]: - - paragraph [ref=e58]: Failed to fetch - - button "重新加载" [ref=e59] [cursor=pointer] -``` - -# Test source - -```ts - 1 | import { Page, Locator, expect } from "@playwright/test"; - 2 | - 3 | export class DashboardPage { - 4 | readonly page: Page; - 5 | readonly pageTitle: Locator; - 6 | readonly healthScoreCard: Locator; - 7 | readonly competitorStatusCard: Locator; - 8 | readonly trendCard: Locator; - 9 | readonly monitorPlatformCard: Locator; - 10 | readonly platformScoreList: Locator; - 11 | readonly actionSuggestions: Locator; - 12 | - 13 | constructor(page: Page) { - 14 | this.page = page; - 15 | // 品牌健康中心标题 - 16 | this.pageTitle = page.getByRole("heading", { name: "品牌健康中心" }); - 17 | // 概览卡片 - 18 | this.healthScoreCard = page.locator("text=综合评分").first(); - 19 | this.competitorStatusCard = page.locator("text=竞品地位").first(); - 20 | this.trendCard = page.locator("text=趋势").first(); - 21 | this.monitorPlatformCard = page.locator("text=监控平台").first(); - 22 | // 平台评分列表 - 23 | this.platformScoreList = page.locator("text=平台评分详情"); - 24 | // 行动建议 - 25 | this.actionSuggestions = page.locator("text=为您推荐的下一步行动"); - 26 | } - 27 | - 28 | async goto() { - 29 | await this.page.goto("/dashboard"); - 30 | } - 31 | - 32 | async expectToBeVisible() { - 33 | await expect(this.pageTitle).toBeVisible(); - 34 | } - 35 | - 36 | // 等待健康状态卡片加载 - 37 | async waitForHealthCards() { -> 38 | await expect(this.healthScoreCard).toBeVisible({ timeout: 10000 }); - | ^ Error: expect(locator).toBeVisible() failed - 39 | } - 40 | - 41 | // 获取综合评分值 - 42 | async getOverallScore(): Promise { - 43 | const scoreElement = this.page.locator(".text-5xl.font-bold").first(); - 44 | if (await scoreElement.isVisible()) { - 45 | return scoreElement.textContent(); - 46 | } - 47 | return null; - 48 | } - 49 | - 50 | // 获取健康等级标签 - 51 | async getHealthLevel(): Promise { - 52 | return this.page.locator(".rounded-full.px-3.py-1.text-sm.font-medium").first(); - 53 | } - 54 | - 55 | // 获取平台评分项数量 - 56 | async getPlatformScoreCount(): Promise { - 57 | const items = this.page.locator("text=/文心一言|Kimi|通义千问|豆包|讯飞星火|天工AI|智谱清言/"); - 58 | return items.count(); - 59 | } - 60 | - 61 | // 获取行动建议数量 - 62 | async getActionSuggestionCount(): Promise { - 63 | const suggestions = this.page.locator(".rounded-lg.border p-4"); - 64 | return suggestions.count(); - 65 | } - 66 | - 67 | // 检查危险平台是否被高亮 - 68 | async isDangerPlatformHighlighted(): Promise { - 69 | const dangerCard = this.page.locator(".border-red-200.bg-red-50\\/50"); - 70 | const count = await dangerCard.count(); - 71 | return count > 0; - 72 | } - 73 | } - 74 | -``` \ No newline at end of file diff --git a/frontend/playwright-report/data/0af630aa468fe7ee067da8e5a5eab9ce0475d05c.zip b/frontend/playwright-report/data/0af630aa468fe7ee067da8e5a5eab9ce0475d05c.zip deleted file mode 100644 index 582eda85ea7e59d904b4894ff5d22d6a48d761f2..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 1132197 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 lMSJ`KT%uyq5Of!rhS< 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

Dat02q5xI3Jd72h*J-=8EB818jCZddvY7~Q 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