Files
cowork-local/docs/governance/contributor-recipes.md
f9f6bc01fd
CI / test (push) Canceled after 0s
Feature/delta team/epic r04 (#7)
## 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>
2026-08-31 05:15:13 +00:00

6.1 KiB

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:

  • 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.
# 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:

  • Đăng ký adapter factory vào registry.

Bước 4: Viết Contract Test

Mở 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:

  • Đị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.
# 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.
# 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

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ể:

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!