PicoClaw 工程规范

代码风格

Go 规范

  • 遵循标准 Go 代码风格(gofmt

  • 包名:小写单词,不用下划线

  • 文件名:snake_case(如 context_cache_test.go

  • 平台特定代码:_linux.go, _windows.go, _unix.go, _other.go 后缀

  • 构建标签://go:build !cgo 等用于条件编译

项目约定

  • CGO_ENABLED=0:默认禁用 CGO,确保静态链接

  • 构建标签 stdjson:使用标准库 JSON(避免依赖 CGO JSON 库)

  • 版本信息通过 -ldflags 注入:config.Version, config.GitCommit, config.BuildTime

Lint 配置

使用 golangci-lint,配置在 .golangci.yaml

# 关键 linter
linters:
  enable:
    - errcheck
    - govet
    - ineffassign
    - staticcheck
    - unused
    - gosec
    - errorlint
    - bodyclose

运行方式:

make lint    # 运行 lint
make fix     # 自动修复
make fmt     # 格式化
make vet     # go vet

错误处理

Provider 层

// FailoverError 分类错误类型
type FailoverError struct {
    Reason   FailoverReason  // auth | rate_limit | billing | timeout | format | overloaded | unknown
    Provider string
    Model    string
    Status   int
    Wrapped  error
}
  • auth:认证失败,切换 Provider

  • rate_limit:限流,切换 Provider + 冷却

  • billing:余额不足,切换 Provider

  • timeout:超时,切换 Provider

  • format:请求格式错误,不重试(问题在请求本身)

  • overloaded:服务过载,切换 Provider + 冷却

渠道层

// pkg/channels/errors.go
type ChannelError struct {
    Channel string
    Op      string
    Err     error
}

工具层

// pkg/tools/result.go
type ToolResult struct {
    Content string
    IsError bool
}

日志规范

使用 pkg/logger/ 包,基于标准库 log/slog

logger.Info("message processed", "channel", channel, "duration", elapsed)
logger.Error("provider failed", "error", err, "model", model)

配置管理

配置来源优先级

  1. 命令行参数

  2. 环境变量(caarlos0/env 库)

  3. config.json 文件

  4. 默认值(pkg/config/defaults.go

配置迁移

pkg/config/migration.go 处理配置版本升级:

// 自动检测旧格式并迁移
func MigrateConfig(cfg *Config) error {
    // v1 → v2: providers → model_list
    // v2 → v3: ...
}

环境变量

变量

说明

PICOCLAW_CONFIG

配置文件路径

PICOCLAW_GATEWAY_HOST

网关监听地址

PICOCLAW_LOG_LEVEL

日志级别

渠道开发规范

新增渠道需要:

  1. pkg/channels/ 下创建子目录

  2. 实现 channels.Channel 接口

  3. init.go 中通过 channels.Register() 自注册

  4. pkg/gateway/gateway.go 中添加 import _ 引入

  5. config.example.json 中添加配置模板

  6. docs/channels/ 下添加配置文档

Channel 接口

type Channel interface {
    Start(ctx context.Context) error
    Stop() error
    SendMessage(msg OutboundMessage) error
    Name() string
}

工具开发规范

新增工具需要:

  1. pkg/tools/ 下创建文件

  2. 实现 Tool 接口

  3. pkg/agent/instance.goNewAgentInstance() 中注册

  4. config.example.jsontools 中添加配置

测试规范

  • 测试文件与源文件同目录:xxx.goxxx_test.go

  • 使用标准库 testing

  • Mock 通过接口实现(如 mock_provider_test.go

  • 集成测试文件名:xxx_integration_test.go

make test     # 运行所有测试
make check    # deps + fmt + vet + test

禁止事项(Anti-Patterns)

  • ❌ 不要使用 CGO(除非有明确的硬件需求且提供 fallback)

  • ❌ 不要在 pkg/ 中引入 cmd/ 的依赖

  • ❌ 不要硬编码 API Key(使用配置或 OAuth)

  • ❌ 不要在渠道层直接调用 LLM(必须通过 MessageBus → AgentLoop)

  • ❌ 不要忽略 context.Context 的取消信号

  • ❌ 不要在工具执行中阻塞超过配置的超时时间