mirror of
https://github.com/dataelement/bisheng.git
synced 2026-10-29 18:14:15 +08:00
docs(agents): dedupe layered AGENTS.md, add runtime topology + backend pitfalls
- root: fix client react-query v5->v4 (@tanstack ^4.28), add 5-line runtime topology block to §1, release-contract.md path in SDD step 0, accurate §7 pitfall pointers, docs-index pointers and instruction-file loading map in §8 - frontend platform/client: remove the 7 hard rules duplicated from root §4 (single source of truth; kills the <600 vs <=600 drift), keep only app-specific rules; promote any-minimize + named-exports to root §4 - backend: new Known Pitfalls section (tenant auto-filter is SELECT-only — bulk UPDATE/DELETE and raw SQL need hand-written tenant conditions; ruff PostToolUse hook drops not-yet-used imports; Celery Beat x multi-tenant context; DB config 100s Redis TTL) + Quick Map accuracy fixes - docs/README.md: drop dead links (qa/, archive/, gateway-deploy dir), add PRD/ and observability/ rows Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
This commit is contained in:
co-authored by
Claude Fable 5
parent
063dd79049
commit
7669c1a3cf
@@ -10,7 +10,13 @@
|
||||
|------|---------|-------|
|
||||
| `src/backend/` | FastAPI + Celery Workers + Linsight Worker | Python 3.11+, uv, SQLModel, LangGraph |
|
||||
| `src/frontend/platform/` | Admin / builder UI | Vite 5 + **Zustand** + react-query v3 + bs-ui |
|
||||
| `src/frontend/client/` | End-user chat UI (`/workspace` base path) | Vite 6 + **Recoil** + react-query v5 + shadcn/ui |
|
||||
| `src/frontend/client/` | End-user chat UI (`/workspace` base path) | Vite 6 + **Recoil** + react-query v4 (@tanstack) + shadcn/ui |
|
||||
|
||||
**Runtime topology** (full picture → `docs/architecture/01-architecture-overview.md`):
|
||||
- Two SPAs — platform (:3001) and client (:4001, base `/workspace`) — call FastAPI (:7860): `/api/v1` frontend-facing, `/api/v2` open RPC. Commercial edition inserts a Java gateway in front (→ `architecture/11-gateway.md`).
|
||||
- Async work: Celery workers (knowledge / workflow / default queues) + Beat; the Linsight agent runs as an independent worker process fed by a Redis queue.
|
||||
- Storage ×6: MySQL|DM8 (dual-DB law C2), Redis, Milvus + ES (RAG dual recall), MinIO, OpenFGA (ReBAC).
|
||||
- Cross-cutting: tenant isolation auto-injected via ContextVar (C3); every permission check goes through PermissionService → OpenFGA (C4).
|
||||
|
||||
---
|
||||
|
||||
@@ -33,12 +39,13 @@ Middleware (MySQL / Redis / Milvus / ES / MinIO / OpenFGA): integration tests ru
|
||||
|
||||
Two React apps that **must not be mixed**. Per-app rules auto-load from each sub-project's `AGENTS.md`:
|
||||
- `src/frontend/platform/AGENTS.md` — Admin/builder UI (Zustand, react-query v3, bs-ui, `@/`)
|
||||
- `src/frontend/client/AGENTS.md` — End-user chat UI (Recoil, react-query v5, shadcn, `~/`)
|
||||
- `src/frontend/client/AGENTS.md` — End-user chat UI (Recoil, react-query v4, shadcn, `~/`)
|
||||
|
||||
**Hard rules (both apps):**
|
||||
**Hard rules (both apps — single source of truth here; per-app files add only app-specific detail):**
|
||||
- TypeScript only (`.ts` / `.tsx`); functional components only; no class components.
|
||||
- Single file ≤ 600 lines. Extract sub-components or hooks when exceeded.
|
||||
- `interface` for Props; `type` for internal types. `handleXxx` internal handlers / `onXxx` props.
|
||||
- `interface` for Props; `type` for internal types. `handleXxx` internal handlers / `onXxx` props. PascalCase components, camelCase utilities/hooks.
|
||||
- Named exports for components (`export function`); no default exports. Minimize `any` — if unavoidable, `// eslint-disable-next-line` + a one-line reason.
|
||||
- **Never** `import axios` directly — use the wrapped request module. (store must not call HTTP = constitution **C7**)
|
||||
- **Never** introduce new UI or state-management libraries.
|
||||
- All code comments in English.
|
||||
@@ -58,7 +65,8 @@ The 8 RULEs are the machine-enforcement arm of constitution **C1 / C4 / C6 / C7*
|
||||
**Full guide — track selection, ★ pause points, deviation re-confirm rule, document roles, constitution gate, harness → [`docs/SDD-Guide.md`](docs/SDD-Guide.md).**
|
||||
|
||||
```
|
||||
0. release-contract.md + read constitution.md
|
||||
0. release-contract.md (features/v{X.Y.Z}/release-contract.md;
|
||||
version's first feature creates it) + read constitution.md
|
||||
1. Spec Discovery → ★ user confirms
|
||||
2. spec.md → /sdd-review <dir> spec → ★ user confirms
|
||||
3. design.md → /sdd-review <dir> design → ★ user confirms (Constitution Check)
|
||||
@@ -70,7 +78,7 @@ The 8 RULEs are the machine-enforcement arm of constitution **C1 / C4 / C6 / C7*
|
||||
9. merge
|
||||
```
|
||||
|
||||
Artifacts: `features/v{X.Y.Z}/{NNN}-{name}/{spec,design,tasks}.md`. Templates: `features/_templates/`.
|
||||
Artifacts: `features/v{X.Y.Z}/{NNN}-{name}/{spec,design,tasks}.md`. Templates: `features/_templates/` (incl. `release-contract.md`).
|
||||
**★ cannot be skipped.** Trivial/hotfix changes use a lighter track — see SDD-Guide §1.
|
||||
|
||||
Tests: new backend tests under `test/<module>/` (e.g., `test/approval/`), not `test/` root. `asyncio_mode=auto`.
|
||||
@@ -79,7 +87,7 @@ Tests: new backend tests under `test/<module>/` (e.g., `test/approval/`), not `t
|
||||
|
||||
## 7. Common Pitfalls
|
||||
|
||||
Runtime/deploy pitfalls (MinIO `sharepoint`, Celery Beat × multi-tenant, DB config Redis TTL) → `src/backend/AGENTS.md`. Commercial edition (`BISHENG_PRO` env, gateway proxy, SSO) → `docs/architecture/11-gateway.md`.
|
||||
Backend runtime pitfalls (tenant-filter SELECT-only gap, ruff hook import trap, Celery Beat × multi-tenant, DB config Redis TTL) → `src/backend/AGENTS.md` §Known Pitfalls. MinIO `sharepoint` image-proxy pitfall → `src/frontend/platform/AGENTS.md` §Known Pitfalls. Commercial edition (`BISHENG_PRO` env, gateway proxy, SSO) → `docs/architecture/11-gateway.md`.
|
||||
|
||||
| Pitfall | Reality |
|
||||
|---------|---------|
|
||||
@@ -91,6 +99,9 @@ Runtime/deploy pitfalls (MinIO `sharepoint`, Celery Beat × multi-tenant, DB con
|
||||
|
||||
## 8. Reference
|
||||
|
||||
- **Docs index** → `docs/README.md` (navigation hub); onboarding & testing → `docs/architecture/09-development-guide.md`
|
||||
- **Architecture docs** → `docs/architecture/` (overview, permission, gateway, multi-tenant, data-models, …)
|
||||
- **Skills**: `/sdd-review`, `/task-review`, `/code-review`, `/e2e-test`, `/i18n-localizer`, `/react-component-refactor`
|
||||
|
||||
**Instruction files (AGENTS.md map).** Root = this file, loaded every session. Auto-loaded on top when editing the matching directory: `src/backend/`, `src/frontend/platform/`, `src/frontend/client/`, plus deep-dir specials `src/backend/bisheng/core/database/alembic/` (migrations) and `src/backend/scripts/` (one-off scripts). Every `CLAUDE.md` is a symlink to its sibling `AGENTS.md` — edit `AGENTS.md` only. Put a new rule in the deepest file covering its scope (cross-app / cross-module → this file; app- or dir-specific → the nearest file); never duplicate a rule across levels — it *will* drift.
|
||||
|
||||
|
||||
+3
-10
@@ -23,14 +23,7 @@
|
||||
| 目录 | 内容 |
|
||||
|------|------|
|
||||
| [`api/`](api/) | 接口文档(filelib 纯检索、知识空间/知识库接口) |
|
||||
| [`qa/`](qa/) | 本地测试数据备忘(星辰公司组织结构与账号) |
|
||||
| [`私有化部署/`](私有化部署/) · [`商业拓展套件gateway部署说明/`](商业拓展套件gateway部署说明/) | 部署文档 |
|
||||
| [`PRD/`](PRD/) | 现行迭代的产品 PRD 与技术方案(按 `{版本} {主题} PRD/` 组织) |
|
||||
| [`observability/`](observability/) | BS_METRIC 指标日志契约(监控团队解析依据) |
|
||||
| [`私有化部署/`](私有化部署/) | 部署文档 |
|
||||
| [`blog/`](blog/) | 设计科普(如"企业权限体系的前世今生") |
|
||||
|
||||
## 历史(仅供追溯,非现行规范)
|
||||
|
||||
[`archive/`](archive/):
|
||||
- `2.5 权限管理体系改造 PRD/` — v2.5 多租户/权限改造的完整 PRD、技术方案、运维手册(已实现,移此归档)
|
||||
- `2.5-review-process/` — v2.5 权限/ReBAC review 过程文档、迁移排查、代码质量报告
|
||||
- `cleanup-tasks/` — 各类"移除/清理"任务清单(org_sync、默认用户组)
|
||||
- `legacy-sdd/` — 旧 SDD 的 spec/plan(达梦支持、文件解析调度等;现已被 `features/` + `SDD-Guide.md` 取代)
|
||||
|
||||
+24
-8
@@ -68,7 +68,7 @@ Applies to async (`asyncio.gather(..., return_exceptions=True)` results must be
|
||||
|
||||
```bash
|
||||
# Dependencies (uv, lockfile = uv.lock, Python must be 3.11.x — pyproject requires-python >=3.11)
|
||||
uv sync --frozen --python uv run python
|
||||
uv sync --frozen
|
||||
|
||||
# Tests
|
||||
uv run pytest test/ # all
|
||||
@@ -94,7 +94,7 @@ uv run celery -A bisheng.worker.main beat -l info
|
||||
# Linsight Worker (optional)
|
||||
uv run python bisheng/linsight/worker.py --worker_num 4 --max_concurrency 5
|
||||
|
||||
# DB migration (alembic.ini in src/backend/)
|
||||
# DB migration (alembic.ini in src/backend/; revisions live in bisheng/core/database/alembic/versions/)
|
||||
uv run alembic upgrade head
|
||||
uv run alembic revision --autogenerate -m "msg" # autogen reflects MySQL only; review DM8 compat manually
|
||||
```
|
||||
@@ -103,28 +103,35 @@ uv run alembic revision --autogenerate -m "msg" # autogen reflects MySQL only;
|
||||
|
||||
**Migration vs. script — keep them separate:**
|
||||
|
||||
- **Schema changes** (DDL: create/alter/drop table, columns, indexes, constraints) → Alembic revision under `migrations/versions/`. These are versioned and replayed on every environment via `alembic upgrade head`.
|
||||
- **Schema changes** (DDL: create/alter/drop table, columns, indexes, constraints) → Alembic revision under `bisheng/core/database/alembic/versions/`. These are versioned and replayed on every environment via `alembic upgrade head`.
|
||||
- **One-off data migration or cleanup** (backfill/transform rows, purge stale data, fix-up jobs run once) → a standalone script under `scripts/`, **not** Alembic. Don't bury data-only operations in schema revisions.
|
||||
|
||||
---
|
||||
|
||||
## Quick Map (indexes — architecture detail in `docs/architecture/`)
|
||||
|
||||
**Domain modules** (own top dir + `api/` + `domain/`): knowledge, workflow, permission, linsight, llm, chat_session, tool, channel, message, user, finetune, share_link, telemetry_search, workstation, open_endpoints, mcp_manage.
|
||||
**Non-standalone** (routes under `api/v1/`, no top dir): assistant, evaluation, audit, group, tag, mark, flows, skillcenter, variable, report, invite_code.
|
||||
**Domain modules** — convention: own top dir under `bisheng/` with `api/` + `domain/` (knowledge, linsight, permission, approval, tenant, evaluation, llm, chat_session, …). `ls bisheng/` is the authoritative list — do not maintain a full enumeration here, it rots. Structural exceptions: `workflow/` (engine layout: graph/nodes/edges, no api/domain) and `mcp_manage/` (clients/langchain only).
|
||||
**Non-standalone** (single-file routes under `api/v1/`, no top dir): assistant, audit, group, tag, mark, flows, skillcenter, variable, report, invite_code, plus legacy chat/dataset/endpoints.
|
||||
→ responsibilities: `architecture/02-backend-modules.md`.
|
||||
|
||||
**API routes**: v1 `/api/v1` (29 routes, frontend-facing); v2 RPC `/api/v2` (6 routes, in `open_endpoints/api/`).
|
||||
**API routes**: v1 `/api/v1` (frontend-facing) + v2 RPC `/api/v2` (in `open_endpoints/api/`) — authoritative registry: `bisheng/api/router.py`.
|
||||
|
||||
**Subsystems** (quick entry points; architecture in the linked doc):
|
||||
- **Workflow engine** — LangGraph DAG. Key files `workflow/graph/{graph_engine,graph_state,workflow}.py`, `nodes/node_manage.py`. 14 node types. Add node = enum in `workflow/common/node.py` + node class under `workflow/nodes/<name>/` (inherit `BaseNode`) + register in `NODE_CLASS_MAP`. → `architecture/03`
|
||||
- **Workflow engine** — LangGraph DAG. Key files `workflow/graph/{graph_engine,graph_state,workflow}.py`, `nodes/node_manage.py`. Node types = `NodeType` enum in `workflow/common/node.py`. Add node = enum member + node class under `workflow/nodes/<name>/` (inherit `BaseNode`) + register in `NODE_CLASS_MAP` (`node_manage.py`). → `architecture/03`
|
||||
- **Knowledge/RAG** — Load → Transform → Ingest; Milvus (dense) + ES (sparse) dual write; async via `knowledge_celery`. Core: `knowledge/rag/pipeline/base.py`. → `architecture/04`
|
||||
- **Linsight agent** — independent Worker via Redis queue. `linsight/worker.py`, `linsight/domain/task_exec.py`. → `architecture/05`
|
||||
- **Permission** (ReBAC / OpenFGA) → `architecture/10` (+ constitution C4)
|
||||
- **Multi-tenant** → `architecture/12` (+ constitution C3)
|
||||
- **Gateway** (commercial) → `architecture/11`
|
||||
- **Approval center (F025)** — `approval/` (domain module) + `worker/approval/` (outbox exec) + `notification/` (in-app messages). Read the `approval-module` skill before touching it.
|
||||
|
||||
**Key enums**: `FlowType` ASSISTANT=5, WORKFLOW=10, WORKSTATION=15, LINSIGHT=20, CHANNEL_ARTICLE=25, KNOWLEDGE_SPACE=30. File states: WAITING(5)→PROCESSING(1)→SUCCESS(2)/FAILED(3)/TIMEOUT(6). → models detail: `architecture/07-data-models.md` + `数据库表结构与关联说明.md`.
|
||||
**Cross-cutting dirs** (not domain modules; touched constantly):
|
||||
- `core/` — config loading, Alembic migrations (`core/database/alembic/versions/`), tenant ContextVar (`core/context/tenant.py`), OpenFGA client (`core/openfga/manager.py`)
|
||||
- `common/` — `resp_*`/pagination schemas (`common/schemas/api.py`), error codes (`common/errcode/`), auth deps (`common/dependencies/`)
|
||||
- `database/models/` — legacy ORM layer; many live models (e.g. `FlowType`) are here, not in domain modules
|
||||
- `worker/` — Celery task tree (knowledge, workflow, approval, telemetry, …); app entry `worker/main.py`
|
||||
|
||||
**Key enums**: `FlowType` (`database/models/flow.py`) ASSISTANT=5, WORKFLOW=10, WORKSTATION=15, LINSIGHT=20, CHANNEL_ARTICLE=25, KNOLEDGE_SPACE=30 (member name is misspelled in code — no W; grep accordingly). File states: WAITING(5)→PROCESSING(1)→SUCCESS(2)/FAILED(3)/TIMEOUT(6). → models detail: `architecture/07-data-models.md` + `architecture/数据库表结构与关联说明.md`.
|
||||
|
||||
**Celery queues**: `knowledge_celery` (20 threads, doc parse/embed/vector), `workflow_celery` (100, DAG exec), `celery` default (100, telemetry). Beat iterates all active tenants per task.
|
||||
|
||||
@@ -134,6 +141,15 @@ uv run alembic revision --autogenerate -m "msg" # autogen reflects MySQL only;
|
||||
|
||||
---
|
||||
|
||||
## Known Pitfalls
|
||||
|
||||
- **Tenant auto-filter only intercepts SELECT.** The `do_orm_execute` listener (`core/database/tenant_filter.py`) returns early for non-SELECT; `before_flush` auto-fills `tenant_id` on INSERT. Bulk `update()` / `delete()` statements and raw `text()` SQL get **no** tenant injection — hand-write the `tenant_id` condition (has leaked cross-tenant twice: LLM module, F035).
|
||||
- **The ruff PostToolUse hook deletes not-yet-used imports.** Every written `.py` gets `ruff check --fix`; an import added in one edit whose usage lands only in a later edit is removed as unused (F401) in between. Land import + usage in the same edit, or write the usage first.
|
||||
- **Celery Beat × multi-tenant.** A Beat schedule fires once; the task body iterates all active tenants — call `set_current_tenant_id()` per iteration, and wrap the cross-tenant enumeration query itself in `bypass_tenant_filter()` (`core/context/tenant.py`), otherwise queries fail on missing tenant context.
|
||||
- **DB config changes take up to 100s.** DB-layer config is cached in Redis with a 100s TTL — don't chase "config not applied" inside that window.
|
||||
|
||||
---
|
||||
|
||||
## Entry Points
|
||||
|
||||
- `main.py` — FastAPI app creation + lifespan
|
||||
|
||||
@@ -1,7 +1,7 @@
|
||||
# Frontend Rules — Client (End-user Chat UI)
|
||||
|
||||
Auto-loaded when editing files in `src/frontend/client/`. Base path: `/workspace`.
|
||||
Cross-app boundary + hard rules common to both apps: root `AGENTS.md §4`. The store-must-not-call-HTTP law: `docs/constitution.md` C7 (arch-guard RULE-6).
|
||||
Cross-app boundary + hard rules common to both apps: root `AGENTS.md §4` (single source — not repeated here). The store-must-not-call-HTTP law: `docs/constitution.md` C7 (arch-guard RULE-6).
|
||||
|
||||
## Commands (cwd: `src/frontend/client/`)
|
||||
|
||||
@@ -11,19 +11,15 @@ npm run dev # dev server on :4001
|
||||
```
|
||||
|
||||
## Tech Stack
|
||||
Vite 6 + React 18 + TypeScript + TailwindCSS 3 + Radix UI (shadcn/ui) + **Recoil** + **react-query v5** + react-i18next + react-router-dom v6 + **lucide-react** + axios (wrapped in `~/api/request.ts`)
|
||||
Vite 6 + React 18 + TypeScript + TailwindCSS 3 + Radix UI (shadcn/ui) + **Recoil** + **react-query v4 (@tanstack)** + react-i18next + react-router-dom v6 + **lucide-react** + axios (wrapped in `~/api/request.ts`)
|
||||
|
||||
## Mandatory Rules
|
||||
- **TypeScript only**: all new files `.ts` / `.tsx`.
|
||||
- **Functional Components**: hooks only; class components prohibited.
|
||||
## Mandatory Rules (client-specific — common hard rules in root §4)
|
||||
- **Path Aliases**: `~/` (or `@/`) → `src/`.
|
||||
- **HTTP Requests**: must use `~/api/request.ts`; never import `axios` directly.
|
||||
- **HTTP Requests**: wrapper is `~/api/request.ts`.
|
||||
- **State Management**: Recoil (`~/store/`). Context or other solutions prohibited for new state.
|
||||
- **UI Components**: `~/components/ui/` (shadcn / Radix-based). No new UI libraries.
|
||||
- **UI Components**: `~/components/ui/` (shadcn / Radix-based).
|
||||
- **Icons**: prefer `bisheng-icons` — `import { Outlined } from 'bisheng-icons'` → `<Outlined.Delete />` (variants `Outlined` / `Filled` / `Colored`). Use `lucide-react` ONLY as a fallback when `bisheng-icons` has no matching-semantic icon.
|
||||
- **⚠️ After upgrading `bisheng-icons`**, clear the Vite pre-bundle cache or new icons crash the page (`Element type is invalid`): `npm run dev -- --force` (or `rm -rf node_modules/.vite && npm run dev`). Its git-source `exports` field defeats Vite's dep-change detection, so the stale pre-bundled snapshot is served unless forced.
|
||||
- **Code Comments**: English.
|
||||
- **Component Size**: < 600 lines; extract sub-components or hooks when exceeded.
|
||||
- **Toast**: `const { showToast } = useToastContext(); showToast?.({ message, severity: 'error' | 'success' })`.
|
||||
- **i18n**: `useLocalize()` from `~/hooks` → `localize()`. Locale files at `src/locales/{en,zh-Hans,ja}/translation.json` (single file). New keys use nested namespace format (see `/i18n-localizer` skill).
|
||||
- **Brand theme (blue⇄green)**: brand-colored UI MUST follow the theme — **never hardcode brand hex** (`#165DFF`/`#024DE3`/`#19B476`/`#187C54`…).
|
||||
@@ -33,12 +29,3 @@ Vite 6 + React 18 + TypeScript + TailwindCSS 3 + Radix UI (shadcn/ui) + **Recoil
|
||||
- **Illustrations**: inline SVG, `fill`/`stroke` = `rgb(var(--illus-NNN))` (separate brighter palette, in `src/components/illustrations/`). SVG presentation attrs ignore `var()` → use inline `style`/className/CSS-mask, and `useId()` to dedupe gradient/clip ids.
|
||||
- **Do NOT theme**: semantic colors (success `#00b42a` / danger `#f53f3f` / warning `#ff7d00`), type colors (skill-purple, assistant-orange), third-party logos. Need a muted-but-themed brand color → `rgb(var(--brand-muted))`.
|
||||
- Full guide: `BRAND-THEME-HANDOFF.md`.
|
||||
|
||||
## Coding Style
|
||||
- **Naming**: `interface` for Props; `type` for internal types. PascalCase components, camelCase utilities/hooks.
|
||||
- **Event Handling**: `handleXxx` for internal logic, `onXxx` for props.
|
||||
- **Any Type**: minimize; if necessary add `// eslint-disable-next-line` with a brief reason.
|
||||
- **Exports**: named exports (`export function`); no default exports for components.
|
||||
|
||||
## Known Pitfalls
|
||||
- **403 Errors**: handled automatically in the response interceptor with redirection. No manual handling needed in business logic.
|
||||
|
||||
@@ -1,7 +1,7 @@
|
||||
# Frontend Rules — Platform (Admin / Builder UI)
|
||||
|
||||
Auto-loaded when editing files in `src/frontend/platform/`.
|
||||
Cross-app boundary + hard rules common to both apps: root `AGENTS.md §4`. The store-must-not-call-HTTP law: `docs/constitution.md` C7 (arch-guard RULE-6).
|
||||
Cross-app boundary + hard rules common to both apps: root `AGENTS.md §4` (single source — not repeated here). The store-must-not-call-HTTP law: `docs/constitution.md` C7 (arch-guard RULE-6).
|
||||
|
||||
## Commands (cwd: `src/frontend/platform/`)
|
||||
|
||||
@@ -14,26 +14,16 @@ VITE_PROXY_TARGET=http://localhost:8180 npm start -- --host 0.0.0.0 # commercia
|
||||
## Tech Stack
|
||||
Vite 5 + React 18 + TypeScript + TailwindCSS 3 + Radix UI (bs-ui) + **Zustand** + React Context + **react-query v3** + react-i18next + react-router-dom v6 + **@xyflow/react** + axios (wrapped in `@/controllers/request.ts`)
|
||||
|
||||
## Mandatory Rules
|
||||
- **TypeScript only**: all new files `.ts` / `.tsx`.
|
||||
- **Functional Components**: hooks only; class components prohibited.
|
||||
## Mandatory Rules (platform-specific — common hard rules in root §4)
|
||||
- **Path Aliases**: `@/` → `src/`.
|
||||
- **HTTP Requests**: must use `@/controllers/request.ts`; never import `axios` directly. API modules in `@/controllers/API/`.
|
||||
- **State Management**: Zustand stores in `@/store/` (cross-page); React Context (`@/contexts/`) for UI-scoped state (alerts, theme, tabs). No new state libraries.
|
||||
- **UI Components**: `@/components/bs-ui/` (Radix-based). Icons from `@/components/bs-icons/`. No new UI libraries.
|
||||
- **HTTP Requests**: wrapper is `@/controllers/request.ts`; API modules in `@/controllers/API/`.
|
||||
- **State Management**: Zustand stores in `@/store/` (cross-page); React Context (`@/contexts/`) for UI-scoped state (alerts, theme, tabs).
|
||||
- **UI Components**: `@/components/bs-ui/` (Radix-based). Icons from `@/components/bs-icons/`.
|
||||
- **Workflow editor**: `@xyflow/react` (**not** `react-flow-renderer`); nodes in `src/CustomNodes/`.
|
||||
- **Code Comments**: English.
|
||||
- **Component Size**: < 600 lines; extract sub-components or hooks when exceeded.
|
||||
- **Toast**: `import { toast } from "@/components/bs-ui/toast/use-toast"; toast({ title, variant: 'error' | 'success', description })`.
|
||||
- **Confirm Dialogs**: `import { bsConfirm } from "@/components/bs-ui/alertDialog/useConfirm"`.
|
||||
- **i18n**: `useTranslation()` from react-i18next → `t()`. Locale files at `public/locales/{en-US,zh-Hans,ja}/{ns}.json`. Namespaces: bs, flow, model, tool, dashboard, knowledge.
|
||||
|
||||
## Coding Style
|
||||
- **Naming**: `interface` for Props; `type` for internal types. PascalCase components, camelCase utilities/hooks.
|
||||
- **Event Handling**: `handleXxx` for internal logic, `onXxx` for props.
|
||||
- **Any Type**: minimize; if necessary add `// eslint-disable-next-line` with a brief reason.
|
||||
- **Exports**: named exports (`export function`); no default exports for components.
|
||||
|
||||
## API Layer Pattern
|
||||
```typescript
|
||||
// @/controllers/API/xxx.ts
|
||||
@@ -49,5 +39,4 @@ captureAndAlertRequestErrorHoc(getSomething()).then(res => { ... })
|
||||
```
|
||||
|
||||
## Known Pitfalls
|
||||
- **403 Errors**: handled automatically in the response interceptor. No manual handling needed.
|
||||
- **MinIO Image Proxy**: Vite `fileServiceTarget` must match backend `config.yaml` `object_storage.minio.sharepoint`, otherwise image requests get 403.
|
||||
|
||||
Reference in New Issue
Block a user