## Summary epic r04 - begin refactor ## Change Type - [x] Cowork feature - [ ] Bug fix - [ ] Core AI contribution - [ ] Test / hardening - [ ] Performance - [ ] Documentation ## Related Work Cowork Task: Core Repo: http://34.143.229.138/gitea-admin/fsg-ai-core-assets Core AI Issue: Core Task: Related PR: ## Scope What is intentionally included? What is intentionally NOT included? ## Validation - [ ] Unit tests - [ ] Integration tests - [ ] Manual verification - [ ] Regression check Commands / evidence: ## Security Impact Permission / credential / network / customer data impact: ## Compatibility - [ ] No breaking change - [ ] Breaking change documented ## Reviewer Notes Anything Cowork reviewers should pay attention to. --------- Co-authored-by: Anh Tran Nguyen Minh <anhtnm1@fpt.com> Co-authored-by: Huong Le Thi Thien <huongltt35@fpt.com> Co-authored-by: Nam Pham Dinh Thanh <nampdt@fpt.com> Co-authored-by: Vu Dam Tuan <vudt15@fpt.com> Co-authored-by: Hiep Ha Van <hiephv3@fpt.com> Co-authored-by: Lam Hoang Van <lamhv7@fpt.com> Reviewed-on: #7 Co-authored-by: Duy Le Huu <duylh19@fpt.com>
This commit was merged in pull request #7.
This commit is contained in:
@@ -0,0 +1,124 @@
|
||||
# Contributor Recipes — Hướng Dẫn Mở Rộng Hệ Thống (EPIC R10-T04)
|
||||
|
||||
Tài liệu này cung cấp các công thức chuẩn hóa (Step-by-Step Recipes) giúp các lập trình viên mở rộng tính năng trong hệ thống **Cowork Local** mà vẫn tuân thủ tuyệt đối **Kiến trúc 4 Tầng Sạch (4-Tier Clean Architecture)** và các tiêu chuẩn kiểm duyệt **CASAN**.
|
||||
|
||||
---
|
||||
|
||||
## 🍳 Recipe 1: Thêm Một Model Provider Mới (AI Provider)
|
||||
|
||||
Khi bạn muốn tích hợp một nhà cung cấp mô hình AI mới (ví dụ: Cohere, Groq, DeepSeek, AWS Bedrock...):
|
||||
|
||||
### Bước 1: Khai báo định danh trong Domain Layer
|
||||
Mở file [`domain/models/provider_descriptor.py`](file:///c:/Users/HuongLTT35/OneDrive%20-%20FPT%20Corporation/Documents/ITCorreTeam/CoworkLocal/cowork_local/domain/models/provider_descriptor.py):
|
||||
- Thêm định danh provider vào enum hoặc hằng số.
|
||||
- Khai báo model mặc định và năng lực hỗ trợ (Streaming, Tool Calling, Vision, Reasoning).
|
||||
|
||||
### Bước 2: Cài đặt Adapter trong Infrastructure Layer
|
||||
Tạo file mới tại `infrastructure/providers/<provider_name>_provider.py` (hoặc mở rộng module hiện có):
|
||||
- Kế thừa lớp `BaseModelProvider` hoặc cài đặt interface adapter tương ứng.
|
||||
- Đảm bảo xử lý streaming qua generator / callbacks.
|
||||
- Đọc API key từ `SecretStore` (Keyring), tuyệt đối không lưu hardcoded credentials.
|
||||
|
||||
```python
|
||||
# infrastructure/providers/custom_provider.py
|
||||
from cowork_local.domain.models.provider_descriptor import ProviderDescriptor
|
||||
|
||||
class CustomProviderAdapter:
|
||||
"""Adapter for Custom AI Provider supporting streaming and tool execution."""
|
||||
def __init__(self, api_key: str, base_url: str | None = None) -> None:
|
||||
self._api_key = api_key
|
||||
self._base_url = base_url
|
||||
|
||||
def stream_chat(self, prompt: str, system_prompt: str = ""):
|
||||
# Yield text chunks
|
||||
yield "..."
|
||||
```
|
||||
|
||||
### Bước 3: Đăng ký vào Provider Registry
|
||||
Mở [`infrastructure/providers/provider_registry.py`](file:///c:/Users/HuongLTT35/OneDrive%20-%20FPT%20Corporation/Documents/ITCorreTeam/CoworkLocal/cowork_local/infrastructure/providers/provider_registry.py):
|
||||
- Đăng ký adapter factory vào registry.
|
||||
|
||||
### Bước 4: Viết Contract Test
|
||||
Mở [`tests/contracts/test_providers.py`](file:///c:/Users/HuongLTT35/OneDrive%20-%20FPT%20Corporation/Documents/ITCorreTeam/CoworkLocal/cowork_local/tests/contracts/test_providers.py):
|
||||
- Thêm test case kiểm tra hợp đồng cho Provider mới bằng `FakeProvider` hoặc offline contract.
|
||||
|
||||
---
|
||||
|
||||
## 🛠️ Recipe 2: Thêm Một Tool Nội Bộ Hoặc Kết Nối MCP Server Mới
|
||||
|
||||
### Bước 1: Khai báo Tool Descriptor & Quyền Hạn
|
||||
Mở [`domain/models/tool_descriptor.py`](file:///c:/Users/HuongLTT35/OneDrive%20-%20FPT%20Corporation/Documents/ITCorreTeam/CoworkLocal/cowork_local/domain/models/tool_descriptor.py):
|
||||
- Định nghĩa tên tool, mô tả, JSON Schema tham số.
|
||||
- Thiết lập cờ Capability: `READ_ONLY`, `GATED`, `DANGEROUS`, v.v.
|
||||
|
||||
### Bước 2: Cài đặt Tool Executor
|
||||
- Nếu là Built-in Tool: Cài đặt trong `infrastructure/tools/` hoặc tích hợp qua `ToolPolicyGateway`.
|
||||
- Nếu là MCP Server: Cấu hình qua `infrastructure/mcp/mcp_tool_source_manager.py` với stdin/stdout JSON-RPC protocol.
|
||||
|
||||
```python
|
||||
# Example: Adding a safe read-only tool
|
||||
descriptor = ToolDescriptor(
|
||||
name="system_disk_usage",
|
||||
description="Inspect available disk space on the local workstation.",
|
||||
parameters_schema={
|
||||
"type": "object",
|
||||
"properties": {"path": {"type": "string"}},
|
||||
"required": ["path"],
|
||||
},
|
||||
capabilities=ToolCapability.READ_ONLY,
|
||||
)
|
||||
```
|
||||
|
||||
### Bước 3: Viết Unit Test & Kiểm Tra Gate
|
||||
- Thêm test case vào `tests/unit/test_tool_registry_and_policy.py`.
|
||||
- Xác nhận tool tôn trọng cờ an toàn (`ToolPolicyGateway`) trước khi thực thi.
|
||||
|
||||
---
|
||||
|
||||
## 🖥️ Recipe 3: Thêm Một Màn Hình / Tab / Widget Giao Diện Mới
|
||||
|
||||
### Bước 1: Tạo module dưới `presentation/<feature>/`
|
||||
- Tạo thư mục riêng (ví dụ: `presentation/analytics/`).
|
||||
- Tách các widget con nhỏ gọn, **mỗi file < 400 dòng code (LOC)**.
|
||||
- Giao diện kế thừa `PySide6.QtWidgets.QWidget` và sử dụng CSS token từ `cowork_local.theme`.
|
||||
|
||||
```python
|
||||
# presentation/analytics/analytics_tab.py
|
||||
"""Analytics Tab Widget (LOC < 400)."""
|
||||
from PySide6.QtWidgets import QWidget, QVBoxLayout, QLabel
|
||||
from cowork_local.state import AppContext
|
||||
from cowork_local.i18n import tr
|
||||
|
||||
class AnalyticsTab(QWidget):
|
||||
"""Analytics view displaying workspace telemetry."""
|
||||
def __init__(self, ctx: AppContext, parent: QWidget | None = None) -> None:
|
||||
super().__init__(parent)
|
||||
self.ctx = ctx
|
||||
self._setup_ui()
|
||||
|
||||
def _setup_ui(self) -> None:
|
||||
layout = QVBoxLayout(self)
|
||||
self.title = QLabel(tr("analytics.title") if tr("analytics.title") != "analytics.title" else "Analytics Dashboard")
|
||||
layout.addWidget(self.title)
|
||||
```
|
||||
|
||||
### Bước 2: Nối Dữ Liệu Qua Tầng Application Service
|
||||
- **QUY TẮC CỐT TỬ**: Widget giao diện CHỈ ĐƯỢC gọi xuống các Service của tầng `application/` (ví dụ: `TaskApplicationService`, `DashboardQueryService`, `ConversationApplicationService`).
|
||||
- Tuyệt đối không query trực tiếp SQLite/JSON hoặc thực thi AI logic trực tiếp trong GUI thread.
|
||||
|
||||
### Bước 3: Đăng Ký Vào Shell Navigation
|
||||
- Mở [`presentation/shell/page_registry.py`](file:///c:/Users/HuongLTT35/OneDrive%20-%20FPT%20Corporation/Documents/ITCorreTeam/CoworkLocal/cowork_local/presentation/shell/page_registry.py) và thêm trang mới vào danh sách menu điều hướng (`NavRail`).
|
||||
|
||||
### Bước 4: Viết Integration Test Cho Widget
|
||||
- Tạo file test dưới `tests/integration/` hoặc `tests/ui/`.
|
||||
- Đảm bảo test chạy được ở chế độ headless (`QT_QPA_PLATFORM=offscreen`).
|
||||
|
||||
---
|
||||
|
||||
## 🛡️ Kiểm Duyệt Chất Lượng Trước Khi Gửi PR (Checklist CASAN)
|
||||
|
||||
Trước khi commit và tạo Pull Request, chạy lệnh kiểm tra tổng thể:
|
||||
```bash
|
||||
python scripts/run_quality_gate.py
|
||||
```
|
||||
Nếu toàn bộ 4 cổng báo `[PASS]` thì mã nguồn của bạn đã sẵn sàng được merge vào nhánh chính!
|
||||
Reference in New Issue
Block a user