一键导入
api-design
当用户要求"设计API"、"创建DTO"、"定义数据结构"、"API文档"、"请求响应格式",或者提到"API设计"、"数据传输对象"、"契约"、"接口"时使用此技能。用于 API 设计模式、数据建模、类型安全或后端 API 结构设计。
用 Codex 或 Claude 帮你安装 复制这段 Prompt,粘贴到 Codex、Claude 或其他助手里,让它检查 Skill 页面并帮你完成安装。
菜单
当用户要求"设计API"、"创建DTO"、"定义数据结构"、"API文档"、"请求响应格式",或者提到"API设计"、"数据传输对象"、"契约"、"接口"时使用此技能。用于 API 设计模式、数据建模、类型安全或后端 API 结构设计。
用 Codex 或 Claude 帮你安装 复制这段 Prompt,粘贴到 Codex、Claude 或其他助手里,让它检查 Skill 页面并帮你完成安装。
基于 SOC 职业分类
This skill should be used when the user requests merging work into main and then deleting all other local and remote branches, keeping only main.
当用户要求"DeepSeek API 集成"、"AI 服务"、"生成回复建议"、"调用 LLM"、"HTTP 请求"、"流式响应"、"连接池优化"、"重试策略",或者提到"DeepSeek"、"API 调用"、"reqwest"、"streaming"时使用此技能。用于 DeepSeek API 集成、HTTP 客户端配置、错误处理、流式响应、连接池优化和 API 密钥管理。
当用户要求"IPC 通信"、"进程通信"、"Agent 协议"、"stdin/stdout"、"JSON 消息"、"Orchestrator 通信"、"消息序列化",或者提到"进程间通信"、"Agent 集成"、"消息协议"时使用此技能。用于实现 Rust Orchestrator 和 Platform Agents 之间的 IPC 通信,包括消息格式定义、序列化、错误处理和性能优化。
macOS Agent 开发规范(Swift + Accessibility API),包括项目结构、Accessibility API 使用、UI Automation、IPC 通信集成、错误处理和测试。
Background knowledge about WeReply project architecture, features, and context. Automatically loaded for AI reference, not directly user-invocable.
Python Agent 开发规范(Windows wxauto v4),包括项目结构、模块化、wxauto 使用、IPC 集成、错误处理、测试和部署。
| name | api-design |
| description | 当用户要求"设计API"、"创建DTO"、"定义数据结构"、"API文档"、"请求响应格式",或者提到"API设计"、"数据传输对象"、"契约"、"接口"时使用此技能。用于 API 设计模式、数据建模、类型安全或后端 API 结构设计。 |
| version | 2.0.0 |
Expert guidance for designing robust, type-safe APIs and data structures in Tauri applications.
This skill provides guidance for:
This skill activates when:
✓ Good: Explicit, typed structures
use serde::{Deserialize, Serialize};
use specta::Type;
#[derive(Serialize, Deserialize, Type, Clone)]
#[specta(inline)]
pub struct CreateFormulaDto {
/// Formula name (2-100 characters)
#[serde(alias = "formulaName")]
pub name: String,
/// Species code (e.g., "pig", "chicken")
#[serde(alias = "speciesCode")]
pub species_code: String,
/// Optional description
pub description: Option<String>,
/// Formula materials
pub materials: Vec<FormulaMaterialDto>,
}
#[derive(Serialize, Deserialize, Type, Clone)]
#[specta(inline)]
pub struct FormulaMaterialDto {
/// Material code
#[serde(alias = "materialCode")]
pub material_code: String,
/// Proportion in percentage (0-100)
pub proportion: f64,
}
✗ Bad: Untyped or generic structures
// ✗ Avoid generic maps
pub type RequestData = HashMap<String, serde_json::Value>;
// ✗ Avoid raw JSON
pub fn create_formula(data: serde_json::Value) -> Result<Formula>;
Rust → TypeScript Mapping:
| Rust | TypeScript | Notes |
|---|---|---|
snake_case | camelCase | Auto-converted by specta |
formula_id | formulaId | Use #[serde(alias)] for compatibility |
species_code | speciesCode | Keep consistent |
#[derive(Serialize, Deserialize, Type)]
pub struct ApiResponse {
pub formula_id: i64, // TypeScript: formulaId
pub species_code: String, // TypeScript: speciesCode
pub total_cost: f64, // TypeScript: totalCost
}
use validators::Validators;
#[derive(Serialize, Deserialize, Type, Clone)]
#[specta(inline)]
pub struct CreateFormulaDto {
pub name: String,
pub species_code: String,
pub materials: Vec<FormulaMaterialDto>,
}
impl CreateFormulaDto {
pub fn validate(&self) -> Result<(), ValidationError> {
// Validate name
if self.name.is_empty() {
return Err(ValidationError {
field: "name".to_string(),
message: "名称不能为空".to_string(),
});
}
if self.name.len() > 100 {
return Err(ValidationError {
field: "name".to_string(),
message: "名称不能超过100个字符".to_string(),
});
}
// Validate materials
if self.materials.is_empty() {
return Err(ValidationError {
field: "materials".to_string(),
message: "至少需要一种原料".to_string(),
});
}
let total_proportion: f64 = self.materials
.iter()
.map(|m| m.proportion)
.sum();
if (total_proportion - 100.0).abs() > 0.01 {
return Err(ValidationError {
field: "materials".to_string(),
message: format!("原料总比例必须为100%,当前为{}", total_proportion),
});
}
Ok(())
}
}
#[tauri::command]
#[specta::specta]
pub async fn create_formula(
dto: CreateFormulaDto,
state: State<'_, TauriAppState>,
) -> ApiResponse<Formula> {
// Validate before processing
if let Err(e) = dto.validate() {
return api_err(format!("参数验证失败: {}", e.message));
}
// Proceed with creation
with_service(state, |ctx| async move {
ctx.formula_service.create_validated(dto).await
})
.await
}
use serde::{Deserialize, Serialize};
use specta::Type;
/// Standard API response wrapper
#[derive(Serialize, Deserialize, Type)]
pub struct ApiResponse<T> {
pub success: bool,
pub data: Option<T>,
pub message: Option<String>,
pub code: Option<String>,
}
impl<T> ApiResponse<T> {
pub fn ok(data: T) -> Self {
Self {
success: true,
data: Some(data),
message: None,
code: None,
}
}
pub fn err(message: String) -> Self {
Self {
success: false,
data: None,
message: Some(message),
code: Some("ERROR".to_string()),
}
}
pub fn with_code(mut self, code: &str) -> Self {
self.code = Some(code.to_string());
self
}
}
#[derive(Serialize, Deserialize, Type)]
#[specta(inline)]
pub struct PaginatedResponse<T> {
pub data: Vec<T>,
pub total: usize,
pub page: usize,
pub page_size: usize,
pub total_pages: usize,
}
#[derive(Serialize, Deserialize, Type)]
#[specta(inline)]
pub struct PaginationParams {
pub page: Option<usize>,
pub page_size: Option<usize>,
pub sort_by: Option<String>,
pub sort_order: Option<SortOrder>,
}
#[tauri::command]
#[specta::specta]
pub async fn list_materials(
params: PaginationParams,
state: State<'_, TauriAppState>,
) -> ApiResponse<PaginatedResponse<Material>> {
let page = params.page.unwrap_or(1);
let page_size = params.page_size.unwrap_or(20);
with_service(state, |ctx| async move {
let result = ctx.material_service
.paginate(page, page_size)
.await?;
api_ok(result)
})
.await
}
use thiserror::Error;
#[derive(Error, Debug, Serialize, Deserialize, Type)]
pub enum ApiError {
#[error("Validation failed: {field} - {message}")]
Validation { field: String, message: String },
#[error("Resource not found: {resource} with id {id}")]
NotFound { resource: String, id: i64 },
#[error("Permission denied: {action}")]
Permission { action: String },
#[error("Conflict: {resource} already exists")]
Conflict { resource: String },
#[error("Internal server error: {0}")]
Internal(String),
}
impl From<ApiError> for ApiResponse<()> {
fn from(err: ApiError) -> Self {
let (code, message) = match &err {
ApiError::Validation { .. } => ("VALIDATION_ERROR", err.to_string()),
ApiError::NotFound { .. } => ("NOT_FOUND", err.to_string()),
ApiError::Permission { .. } => ("PERMISSION_DENIED", err.to_string()),
ApiError::Conflict { .. } => ("CONFLICT", err.to_string()),
ApiError::Internal(_) => ("INTERNAL_ERROR", "服务器内部错误".to_string()),
};
ApiResponse {
success: false,
data: None,
message: Some(message),
code: Some(code.to_string()),
}
}
}
/// Creates a new formula with the specified materials.
///
/// # Arguments
///
/// * `dto` - Formula creation data
/// - `name`: Formula name (2-100 characters)
/// - `species_code`: Target species code
/// - `materials`: List of materials with proportions
///
/// # Returns
///
/// Created formula with assigned ID
///
/// # Errors
///
/// - `VALIDATION_ERROR`: Invalid input data
/// - `CONFLICT`: Formula name already exists
///
/// # Example
///
/// ```typescript
/// const result = await commands.createFormula({
/// name: "Growing Pig Formula",
/// speciesCode: "pig",
/// materials: [
/// { materialCode: "corn", proportion: 50.0 },
/// { materialCode: "soybean", proportion: 50.0 }
/// ]
/// });
/// ```
#[tauri::command]
#[specta::specta]
pub async fn create_formula(
dto: CreateFormulaDto,
state: State<'_, TauriAppState>,
) -> ApiResponse<Formula> {
// Implementation
}
Create corresponding TypeScript documentation:
/**
* Creates a new formula
*
* @param dto - Formula creation data
* @param dto.name - Formula name (2-100 characters)
* @param dto.speciesCode - Target species code (e.g., "pig", "chicken")
* @param dto.materials - Array of materials with proportions
* @returns Promise with created formula
* @throws ValidationError if input data is invalid
* @throws ConflictError if formula name already exists
*
* @example
* ```typescript
* const result = await commands.createFormula({
* name: "Growing Pig Formula",
* speciesCode: "pig",
* materials: [
* { materialCode: "corn", proportion: 50.0 },
* { materialCode: "soybean", proportion: 50.0 }
* ]
* });
*
* if (!result.success) {
* message.error(result.message);
* return;
* }
*
* const formula = result.data;
* console.log(`Created formula with ID: ${formula.id}`);
* ```
*/
// Current version (v1)
#[tauri::command]
#[specta::specta)]
pub async fn create_formula_v1(dto: CreateFormulaDtoV1) -> ApiResponse<Formula> {
// Implementation
}
// New version with additional fields
#[derive(Serialize, Deserialize, Type, Clone)]
#[specta(inline)]
pub struct CreateFormulaDtoV2 {
// Inherit v1 fields
#[serde(flatten)]
pub v1_fields: CreateFormulaDtoV1,
// New fields
pub formula_type: FormulaType,
pub tags: Vec<String>,
}
#[tauri::command]
#[specta::specta]
pub async fn create_formula(dto: CreateFormulaDtoV2) -> ApiResponse<Formula> {
// Use latest version as default
}
Option<T>#[specta::specta] on all commands#[specta(inline)] on all DTOsbindings.tsas any type assertions#[tauri::command]
#[specta::specta]
pub async fn command_name(
dto: RequestDto,
state: State<'_, TauriAppState>,
) -> ApiResponse<ResponseData> {
// 1. Validate input
dto.validate()?;
// 2. Process with service
with_service(state, |ctx| async move {
ctx.service.do_work(dto).await
})
.await
}
#[derive(Serialize, Deserialize, Type, Clone)]
#[specta(inline)]
pub struct RequestDto {
#[serde(alias = "fieldName")]
pub field_name: String,
pub optional_field: Option<String>,
}
const result = await commands.commandName({ fieldName: "value" });
if (!result.success) {
message.error(result.message);
return;
}
const data = result.data;
// Create
#[tauri::command]
#[specta::specta]
pub async fn create_formula(dto: CreateFormulaDto, state: State<'_>)
-> ApiResponse<Formula>;
// Read
#[tauri::command]
#[specta::specta]
pub async fn get_formula(id: i64, state: State<'_>)
-> ApiResponse<Formula>;
// Update
#[tauri::command]
#[specta::specta]
pub async fn update_formula(id: i64, dto: UpdateFormulaDto, state: State<'_>)
-> ApiResponse<Formula>;
// Delete
#[tauri::command]
#[specta::specta]
pub async fn delete_formula(id: i64, state: State<'_>)
-> ApiResponse<()>;
// List
#[tauri::command]
#[specta::specta]
pub async fn list_formulas(params: ListParams, state: State<'_>)
-> ApiResponse<PaginatedResponse<Formula>>;
Activate this skill when: