From 04617a382ca03bf85321d9d3f048a4ae37136264 Mon Sep 17 00:00:00 2001 From: tian <11429339@qq.com> Date: Sat, 25 Jul 2026 14:11:50 +0800 Subject: [PATCH] =?UTF-8?q?docs:=20=E6=9B=B4=E6=96=B0AGENTS.md=EF=BC=8C?= =?UTF-8?q?=E5=8A=A0=E5=85=A581=E7=BC=96=E8=AF=91=E9=83=A8=E7=BD=B2?= =?UTF-8?q?=E6=B5=81=E7=A8=8B=E5=92=8C=E8=AE=BE=E8=AE=A1=E5=8E=9F=E5=88=99?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- AGENTS.md | 127 ++++++++++++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 127 insertions(+) create mode 100644 AGENTS.md diff --git a/AGENTS.md b/AGENTS.md new file mode 100644 index 0000000..6493dd8 --- /dev/null +++ b/AGENTS.md @@ -0,0 +1,127 @@ +# CLAUDE.md + +This file provides guidance to Claude Code (claude.ai/code) when working with code in this repository. + +## Build, Test & Restart Commands + +### 本地 Windows 编译 +- Build: `go build -o managerd ./cmd/managerd` 或 `pwsh -File scripts/managerd.ps1 build` +- Run: `./managerd` (uses `managerd.json` config) or `./managerd ` +- 重启服务(编译+启停+健康检查一站式):`pwsh -File scripts/managerd.ps1 restart` +- 查看服务状态:`pwsh -File scripts/managerd.ps1 status` +- Test all: `go test ./...` +- Test single package: `go test ./internal/service/...` +- Test single test: `go test ./internal/storage/... -run TestAssetsRepo_SaveTemplate` +- Verbose test: `go test ./internal/web/... -v -run TestUI_ActionDevicesBatchAction` + +### 81 (ARM64) 编译部署(主要开发流程) + +Windows 上改代码 push → 81 上 pull 编译部署: +```bash +# 管理端 +cd ~/apps/safesight-control +git pull +GOPROXY=https://goproxy.cn,direct bash scripts/build.sh +sudo systemctl restart safesightd + +# Edge agent +cd ~/apps/safesight-edge/agent +git pull +GOPROXY=https://goproxy.cn,direct go build -ldflags="-s -w" -o safesight-edge-agent ./cmd/safesight-agent/ +sudo systemctl restart safesight-edge-agent +``` + +81 已安装 Go 1.23.4,设置 goproxy.cn 镜像代理。 + +## Codebase Architecture + +### Layered Structure (no DI framework — manual wiring in main.go) + +``` +cmd/managerd/main.go — Composition root: builds config, services, storage, router +internal/api/ — Thin HTTP handlers that delegate to services (chi router, no framework) +internal/web/ — Embedded HTML UI (Go html/template + layout.html pattern) +internal/service/ — Business logic (discovery, registry, tasks, config assets, preview rendering, template slots) +internal/storage/ — SQLite persistence (raw SQL via database/sql, pure-Go modernc.org/sqlite driver) +internal/config/ — JSON config file loading (managerd.json) +internal/models/ — Core domain types (Device, Task, DeviceTaskStatus, etc.) +templates/ — Local JSON template files loaded at runtime +templates/standard_templates/ — "Standard" templates (std_ prefix) imported into SQLite on startup +``` + +### Dependency Flow (all wired in main.go) + +``` +config → service (agent client, registry, discovery) +config + service → storage (opens SQLite, creates repos) +storage → service (task service, config preview, etc.) +service + storage → api + web (HTTP handlers) +chi.Router → mounts api routes + UI +``` + +### Device Communication + +- `AgentClient` proxies HTTP requests to device-side `rk3588-agent` via the device's IP/port. +- Two timeout tiers: 3s for normal requests, 120s for long operations (config apply, media server, model uploads). +- All proxied requests carry `X-RK-Token` header from config. +- Generic passthrough: `r.Handle("/devices/{id}/v1/*", proxyAgentV1)` covers agent sub-routes. + +### Config Asset Management + +The system manages four asset types stored as JSON blobs in SQLite: + +| Asset | Table | Key Concept | +|---|---|---| +| Templates | `templates` | Base config template with bindings/variables | +| Profiles | `profiles` | Template-specific configuration (references `primary_template_name`) | +| Overlays | `overlays` | Named config overrides that can be appended to any profile | +| Integration Services | `integration_services` | Third-party service definitions (e.g., RTMP, HTTP push) | +| Video Sources | `video_sources` | Camera/stream source definitions | + +Naming convention: names starting with `std_` are read-only standard templates, imported on startup from `templates/standard_templates/`. + +The config preview rendering pipeline: merge template + profile + overlays → resolve binding references (video sources, integration services) → expand slot tokens (`${slot:name.field}`) → compute SHA256 hash. + +### Background Goroutines + +- RegistryService: 2s tick for offline pruning, 30s tick for graph polling +- DiscoveryService: UDP broadcast listener (blocking goroutine per discovery request) +- TaskService: concurrent task execution gated by a semaphore channel + +### Key Database Tables (SQLite, migrations in storage/migrate.go) + +- `devices` — device registry (device_id PK, ip, port, online status, last_seen) +- `templates`, `profiles`, `overlays` — config assets +- `integration_services`, `video_sources` — third-party service and video source definitions +- `tasks` + `task_devices` — batch task execution (type, status, per-device status) +- `device_config_state` — per-device applied config state +- `audit_logs` — action audit trail (actor, action, target, details) + +### Test Patterns + +- Test files co-located with source: `*_test.go` +- Services constructed with nil/real dependencies (no mocking framework) +- HTTP tests use `httptest.NewRequest` + `httptest.NewRecorder` +- Storage tests use in-memory SQLite (tests seed their own data via repo methods) +- Tests assert on status codes, redirect URLs, and response body content + +## Coding Rules + +- **Never use `sed`** on Windows (Git Bash). It produces stray `t` characters, broken indentation, and corrupted files. +- **Use `rg` and `fd`** for searching (not `grep`/`find`). Both are installed. +- **File editing**: use the `write` tool for new/rewritten files and `edit` tool for precise changes. For complex find-and-replace, write a small temporary Go program. +- **No tabs**: use spaces for indentation in all source files. +- **No `fetch()` in templates** for page data — all API calls must go through Go server-side handlers. JS is only for UI interactivity (modals, carousels, confirm dialogs). +- **No inline `onclick` with complex quoting** — use `data-*` attributes + event delegation instead. +- **Use `pwsh`** for PowerShell commands (v7.6.1 in PATH, not `powershell.exe`). +- **重启服务**:统一用 `pwsh -File scripts/managerd.ps1 restart`,它会先编译、停旧进程、再启动新进程并做健康检查。不要手动 kill + build + start。 +- **如无必要,不使用数据库事务**:SQLite 只允许一个写者,事务会阻塞所有其他写操作。单个 `Exec` 已是原子操作,绝大多数场景不需要包裹事务。仅模板重命名等必须原子完成的多步操作才用事务。 +- **调试时只加日志,不改代码**:遇到 bug 先用 `fmt.Printf` 全量打印关键路径的状态和数据流,定位根因后再动手修。不要猜测、不要加 workaround(重试、超时、锁之类)。 +- **UDP 仅用于设备发现**:`dev.Online` 只用于 UI 指示灯,不做业务操作的准入判断。所有 agent HTTP 调用直接发出,由 HTTP 结果判断设备是否可达。 +- **运行时配置持久化到文件**:系统配置(告警保留天数、公司名称等)通过 UI 修改后写入 `safesightd.json`,配置模板 `safesightd.json.template` 为只读参考。 + +## 测试设备 + +- RK3588: `orangepi@10.0.0.81` / password: `orangepi` / key: `~/.ssh/id_ed25519_rk3588` +- Agent:9100 / Media:9000 / Token:`4fe2d69fda23d0d5d04a1486d4920e68` +- 详细命令参考 [docs/test-devices.md](docs/test-devices.md)