# AGENTS.md - NetCat Client Ruby Sinatra 应用

本文档为使用此 Ruby Sinatra 应用的智能编码助手提供全面指南。包含构建命令、代码风格指南和仓库特定模式。

## 项目概述

- **类型**: Ruby Sinatra Web 应用
- **Ruby 版本**: 3.0.2
- **框架**: Sinatra 4.2
- **数据库**: SQLite3 + Sequel ORM
- **Web 服务器**: Puma

## 构建与开发命令

### 环境设置
```bash
# 安装依赖
bundle install

# 设置数据库
# 数据库通过 config/database.rb 自动配置
# 无需手动设置

# 运行开发服务器
bundle exec ruby app.rb

# 带自动重载的开发模式
RACK_ENV=development bundle exec ruby app.rb
```

### 运行应用
```bash
# 默认端口: 4567（在 app.rb 中配置）
# 访问地址: http://localhost:4567

# 带环境变量运行
RACK_ENV=development bundle exec ruby app.rb
```

### 数据库操作
```bash
# 应用使用 SQLite3 和 Sequel ORM
# 数据库文件: config/db/client.db
# 迁移通过 config/database.rb 在启动时自动运行
```

### 测试
```bash
# 运行所有测试
bundle exec rspec

# 运行单个测试文件
bundle exec rspec spec/requests/home_spec.rb

# 使用文档格式运行测试
bundle exec rspec --format documentation

# 仅运行失败的测试（需要设置 example_status_persistence_file_path）
bundle exec rspec --only-failures
```

### 代码检查与格式化
**注意**: 此项目目前没有正式的代码检查/格式化配置。
```bash
# 如果需要添加代码检查，推荐：
bundle exec rubocop      # 使用 Rubocop
bundle exec standardrb   # 使用 StandardRB
```

## 代码风格指南

### 缩进
- 所有缩进使用 **2 个空格**（不要用 tab）
- 在所有 Ruby 文件中保持一致
- 示例：
  ```ruby
  class NetCatClient < Sinatra::Base
    configure do
      set :port, 4567
    end
  end
  ```

### 命名约定
- **类**: `PascalCase` - `NetCatClient`, `LocalDevice`, `CloudClient`
- **方法**: `snake_case` - `decrypt_password`, `full_connection_info`
- **变量**: `snake_case` - `api_token`, `base_url`, `access_token`
- **常量**: `UPPER_SNAKE_CASE` - `CONNECTION_TYPES`, `DEFAULT_PORT`
- **模块**: `PascalCase` - `DeviceRoutes`, `TaskRoutes`

### 文件组织
```
├── app.rb              # 主 Sinatra 应用
├── config/
│   ├── boot.rb        # 启动配置
│   ├── database.rb    # 数据库设置
│   └── settings.rb    # 应用设置
├── models/            # Sequel 模型
├── routes/           # Sinatra 路由模块
├── services/         # 业务逻辑服务
├── lib/              # 核心库
├── views/            # ERB 模板
└── public/           # 静态资源
```

### 导入模式
- 对 gem 依赖使用 `require`：
  ```ruby
  require 'sinatra'
  require 'sequel'
  require 'httparty'
  ```

- 对本地文件使用 `require_relative`：
  ```ruby
  require_relative '../config/database'
  require_relative './models/local_device'
  ```

- 使用 `require_all`（来自 gem）加载目录：
  ```ruby
  require_all './models'
  ```

### 错误处理
- 使用带特定异常处理的 `begin/rescue` 块：
  ```ruby
  begin
    # 可能失败的操作
  rescue StandardError => e
    LogService.error("错误: #{e.message}")
    # 恢复或重新抛出
  end
  ```

- 对显式错误条件使用 `raise`：
  ```ruby
  raise "未配置 API 令牌" unless api_token
  ```

- 使用自定义错误类：
  ```ruby
  class PasswordEncryptor::DecryptionError < StandardError
  end
  ```

### 注释与文档
- **主要语言**: 业务逻辑使用中文注释
- **次要语言**: 技术解释使用中文
- **注释风格**: 解释"为什么"而不是"做什么"的内联注释,需要包含业务逻辑以及隐性知识
- **示例**：
  ```ruby
  # 确保数据库连接已建立并设置全局Sequel模型数据库
  Database.connection
  
  # TelnetDevice 类用于通过 Telnet 管理 CLI 设备
  # 隐性知识：xxx
  class TelnetDevice
    # 默认 Telnet 端口
    DEFAULT_PORT = 23
  end
  ```

### 字符串字面量
- 始终在文件顶部包含冻结字符串字面量注释：
  ```ruby
  # frozen_string_literal: true
  ```

- 插值字符串使用双引号，否则使用单引号
- 与 Ruby 社区标准保持一致

### 数据库模型
- 所有模型都继承自 `Sequel::Model`
- 使用 Sequel 插件实现常见功能：
  ```ruby
  plugin :timestamps, update_on_create: true
  plugin :validation_helpers
  plugin :json_serializer
  ```

- 在 `validate` 方法中进行验证：
  ```ruby
  def validate
    super
    validates_presence :name
    validates_unique :name
  end
  ```

### 路由模块
- Sinatra 路由组织为模块：
  ```ruby
  module DeviceRoutes
    def self.registered(app)
      app.get '/devices' do
        # 路由逻辑
      end
    end
  end
  ```

- 在主应用中注册：
  ```ruby
  class NetCatClient < Sinatra::Base
    register DeviceRoutes
    register TaskRoutes
  end
  ```

### 服务类
- 用于业务逻辑的普通 Ruby 类
- 通常使用单例模式或类方法
- 示例：
  ```ruby
  class CloudClient
    include Singleton
    
    def initialize
      @base_url = ENV['CLOUD_API_URL']
    end
    
    def sync_device(device)
      # API 调用逻辑
    end
  end
  ```


## 开发工作流

### 添加新功能
1. **模型**: 作为 `Sequel::Model` 子类添加到 `models/` 目录
2. **路由**: 作为 Sinatra 模块添加到 `routes/` 目录
3. **服务**: 作为普通 Ruby 类添加到 `services/` 目录
4. **视图**: 作为 ERB 模板添加到 `views/` 目录

### 代码审查清单
- [ ] 2 空格缩进
- [ ] 在 .rb 文件顶部有 `# frozen_string_literal: true`
- [ ] 适当的地方使用中文注释写业务逻辑
- [ ] 使用 `begin/rescue` 处理错误
- [ ] 一致的命名约定
- [ ] Sequel 模型使用适当的插件
- [ ] 路由遵循 Sinatra 模块模式

### 需遵循的常见模式

#### 密码加密
```ruby
# 模型遵循此密码处理模式
def password=(plain_password)
  return if plain_password.nil? || plain_password.empty?
  self.encrypted_password = password_encryptor.encrypt(plain_password)
end

def decrypt_password
  return nil if encrypted_password.nil? || encrypted_password.empty?
  password_encryptor.decrypt(encrypted_password)
end
```

#### API 客户端模式
```ruby
class CloudClient
  def initialize
    @base_url = ENV['CLOUD_API_URL']
    @api_token = ENV['CLOUD_API_TOKEN']
  end
  
  def make_request(endpoint, method: :get, data: nil)
    # 带错误处理的 HTTP 请求
  end
end
```

#### Telnet 设备连接
```ruby
# lib/telnet_device.rb 中的模式
class TelnetDevice
  DEFAULT_PORT = 23
  DEFAULT_TIMEOUT = 30
  
  def initialize(host:, port: DEFAULT_PORT, **options)
    @host = host
    @port = port
    # 连接设置
  end
end
```

## 故障排除

### 常见问题
1. **端口已被占用**: 应用默认运行在端口 4567
   ```bash
   # 检查使用端口 4567 的进程
   lsof -ti:4567
   # 必要时杀死进程
   kill -9 $(lsof -ti:4567)
   ```

2. **数据库连接问题**: 确保已安装 SQLite3
3. **Gem 依赖**: 在 Gemfile 更改后运行 `bundle install`

### 调试
- 使用 `pry` 进行交互式调试（已在 Gemfile 中）
- 开发模式在浏览器中显示异常
- 日志写入标准输出

## 未来改进

### 测试（推荐）
```bash
# 添加到 Gemfile:
group :test do
  gem 'rspec'
  gem 'rack-test'
end

# 然后创建带测试的 spec/ 目录
```

### 代码检查（推荐）
```bash
# 添加到 Gemfile:
group :development do
  gem 'rubocop'
  gem 'rubocop-rake'
  gem 'rubocop-rspec'
end

# 创建带项目特定规则的 .rubocop.yml
```

### 文档
- 添加带设置说明的 `README.md`
- 如适用添加 API 文档
- 考虑为 API 路由添加 Swagger/OpenAPI

---

*本文档基于对代码库结构和模式的分析生成。随着项目发展更新。*