safesight-control/AGENTS.md

130 lines
7.1 KiB
Markdown
Raw Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

# 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 <config-path>`
- 重启服务(编译+启停+健康检查一站式):`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)
- **Git push 失败重试**HTTP 凭证偶尔过期push 失败后再执行一次即可(第二次会弹出 Windows 凭据框)。