Hồi quy đã vá
-------------
F-12 Kéo–thả hoặc dán tệp vào ô chat ném NameError. R08 tách `_Input` sang
`chat_input_box.py` nhưng để `_paths_from_mime()` ở lại
`composer_widget.py`, nên hai hàm sự kiện Qt gọi một cái tên không tồn
tại. Bốn hàm dùng chung chuyển sang `composer_mime.py` — module thứ ba
là chỗ duy nhất không lặp lại được lỗi này. Đo lại: cả thả lẫn dán đều
gắn 1 tệp, khớp bản trước refactor.
F-01 Đổi provider thì bộ chọn model AI-Edit không làm gì. Hook cũ kiểm
`folder.ai_model_combo`, thuộc tính R08-T12 đã dời sang
`ai_panel.resolver`. Làm mới vô điều kiện, đúng như tab cũ: lần lấy đầu
tiên hỏng thì đổi provider chính là lúc phải thử lại.
F-07 Hàng chọn kỳ của Dashboard bị đẩy xuống dưới các thẻ số liệu. Hàng này
lọc CẢ BA thẻ con chứ không riêng biểu đồ, nên để nó nằm dưới là bắt
người dùng đọc con số trước khi thấy con số đó tính cho kỳ nào. Kèm
theo: `TokenUsageCardWidget` bị bỏ sót `setContentsMargins(0,0,0,0)`
mà hai thẻ con còn lại đã có, đẩy cả hàng thẻ lệch 9px.
`check_layout_geometry` nay khớp TỪNG BYTE với bản trước refactor.
F-11 Hai lớp khai trùng tên phương thức; Python giữ bản sau nên bản đầu là
mã chết. `co4e_tab.py::showEvent` bản đầu gọi `_narrow_guard.attach()`
và không bao giờ chạy.
Tách file (F-09)
----------------
Bốn file chạm trần 400 dòng, mỗi lần cắt ra một trách nhiệm thật:
graph_renderer.py -> graph_scene_builder.py + graph_export.py
co4e_workflow_service.py -> co4e_run_history.py
json_config_repository.py -> config_sections.py
agents_admin_tab.py -> shared/agent_kind_visuals.py
File cuối còn xoá 3 bản sao của hàm đã có trong `shared/formatters.py`,
giống hệt đến từng dòng — nay định dạng thời gian và avatar không lệch nhau
giữa các bảng Giám sát nữa.
Docstring
---------
41,6% -> 100% (3.478/3.478 định nghĩa production), kể cả module dormant và
phương thức dunder. Toàn bộ phần bổ sung viết bằng tiếng Việt; comment tiếng
Anh có sẵn giữ nguyên — dịch ngược là một đợt riêng.
Seam chưa nối dây (F-05)
------------------------
9 seam mang nhãn `SEAM · dựng <ngày>` kèm hai câu: được nối khi nào, và để
dormant thì hỏng gì. Ngày lấy từ lịch sử git, không phải hạn tự đặt. Gate O
đọc nhãn đó và nhắc khi quá 30 ngày.
859 test xanh · 4/4 cổng CASAN · 19/24 checker khớp từng byte bản cũ.
Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
129 lines
5.5 KiB
Python
129 lines
5.5 KiB
Python
"""Các nhóm cấu hình đọc thẳng từ dict — tách khỏi ``json_config_repository.py``.
|
|
|
|
Mỗi thành viên ở đây chỉ làm đúng một việc: đặt tên cho một khoá trong file
|
|
cấu hình và nói rõ giá trị mặc định khi khoá đó chưa có. Không có hành vi nào
|
|
đáng bàn, nhưng có đến hơn hai mươi cái — để chung với phần có logic thật
|
|
(trộn mặc định, kho bí mật, di trú schema, ghi nguyên tử) thì phần ấy bị chìm.
|
|
|
|
Dùng ``setdefault`` chứ không ``get``: bên gọi sửa thẳng vào dict trả về
|
|
(``cfg.routing["switch_mode"] = ...``) rồi mới ``save()``, nên cái trả về phải
|
|
là dict THẬT nằm trong ``data``, không phải một bản sao rồi bị vứt đi.
|
|
|
|
Mixin chứ không phải lớp riêng: 29 file đang gọi ``ctx.config.<tên>`` thẳng,
|
|
nên tách thành ``ctx.config.sections.<tên>`` sẽ là đổi API công khai — việc
|
|
này chỉ chia file, không chia bề mặt.
|
|
"""
|
|
from __future__ import annotations
|
|
|
|
import copy
|
|
from typing import Any, Dict
|
|
|
|
|
|
class ConfigSectionsMixin:
|
|
"""Phần truy cập nhóm cấu hình của :class:`JsonConfigRepository`.
|
|
|
|
Chỉ trông vào hai thứ của lớp chủ: ``self.data`` (dict cấu hình đã trộn
|
|
mặc định) và ``self.save()``. Không tự đứng một mình được — và cũng không
|
|
cần, vì không có ai khác dùng.
|
|
"""
|
|
|
|
|
|
@property
|
|
def code(self) -> Dict[str, Any]:
|
|
"""Nhóm ``code``: thiết lập của agent lập trình (thư mục làm việc, model)."""
|
|
return self.data["code"]
|
|
|
|
@property
|
|
def teams(self) -> Dict[str, Any]:
|
|
"""Nhóm ``teams``: thiết lập tích hợp Microsoft Teams."""
|
|
return self.data["teams"]
|
|
|
|
@property
|
|
def history(self) -> Dict[str, Any]:
|
|
"""Nhóm ``history``: lưu lịch sử hội thoại (bật/tắt, giới hạn)."""
|
|
return self.data["history"]
|
|
|
|
@property
|
|
def codebase_memory(self) -> Dict[str, Any]:
|
|
"""Nhóm ``codebase_memory``: bộ nhớ mã nguồn cho agent lập trình."""
|
|
return self.data["codebase_memory"]
|
|
|
|
@property
|
|
def cowork(self) -> Dict[str, Any]:
|
|
"""Nhóm ``cowork``: thiết lập màn Cowork (thư mục kết quả, model mặc định)."""
|
|
return self.data["cowork"]
|
|
|
|
@property
|
|
def mcp_servers(self) -> list:
|
|
"""Danh sách máy chủ MCP đã khai báo; rỗng nếu chưa có cái nào."""
|
|
return self.data.setdefault("mcp_servers", [])
|
|
|
|
@property
|
|
def structure(self) -> Dict[str, Any]:
|
|
"""Nhóm ``structure``: trần số node/cạnh khi vẽ đồ thị GraphRAG.
|
|
|
|
Mặc định 400/400 — vượt ngưỡng đó thì đồ thị vừa vẽ chậm vừa rối, không
|
|
còn đọc được nữa.
|
|
"""
|
|
return self.data.setdefault("structure", {"max_nodes": 400, "max_edges": 400})
|
|
|
|
@property
|
|
def monitoring_visibility(self) -> Dict[str, bool]:
|
|
"""Nhóm ``monitoring_visibility``: tab nào của màn Giám sát được hiện.
|
|
|
|
Lấy bản sao sâu của mặc định khi khoá chưa có, để người dùng tắt một tab
|
|
không vô tình sửa luôn bộ mặc định dùng chung.
|
|
"""
|
|
return self.data.setdefault(
|
|
"monitoring_visibility",
|
|
copy.deepcopy(self._defaults["monitoring_visibility"]))
|
|
|
|
@property
|
|
def ext_connectors(self) -> Dict[str, list]:
|
|
"""Connector (MCP) gom theo nhóm CAD/CAE/MS365/Other."""
|
|
d = self.data.setdefault(
|
|
"ext_connectors", {"cad": [], "cae": [], "ms365": [], "other": []})
|
|
for cat in ("cad", "cae", "ms365", "other"):
|
|
d.setdefault(cat, [])
|
|
return d
|
|
|
|
# ---- công tắc tổng cho connector -------------------------------------
|
|
|
|
@property
|
|
def connect_external(self) -> bool:
|
|
"""Tắt cái này là agent không nối tới connector ngoài nào cả. Mặc định
|
|
BẬT để cấu hình đang chạy không đổi hành vi."""
|
|
return bool(self.data.setdefault("tools", {}).get("connect_external", True))
|
|
|
|
def set_connect_external(self, enabled: bool) -> None:
|
|
"""Bật/tắt công tắc tổng cho connector ngoài, ghi đĩa ngay."""
|
|
self.data.setdefault("tools", {})["connect_external"] = bool(enabled)
|
|
self.save()
|
|
|
|
# ---- những thứ đã gieo sẵn -------------------------------------------
|
|
|
|
@property
|
|
def seeded_library_skills(self) -> list:
|
|
"""Slug của skill thư viện đã gieo — để cái người dùng xoá đi không bị
|
|
lặng lẽ gieo lại."""
|
|
return list(self.data.setdefault("seeded_library_skills", []))
|
|
|
|
@seeded_library_skills.setter
|
|
def seeded_library_skills(self, slugs) -> None:
|
|
"""Ghi lại danh sách slug đã gieo, bỏ trùng và giữ nguyên thứ tự."""
|
|
self.data["seeded_library_skills"] = list(dict.fromkeys(slugs or []))
|
|
|
|
@property
|
|
def seeded_builtin_flows(self) -> list:
|
|
"""Id của flow Co4E dựng sẵn đã gieo (cùng quy tắc tôn trọng việc người
|
|
dùng đã xoá như seeded_library_skills)."""
|
|
return list(self.data.setdefault("seeded_builtin_flows", []))
|
|
|
|
@seeded_builtin_flows.setter
|
|
def seeded_builtin_flows(self, ids) -> None:
|
|
"""Ghi lại danh sách id flow đã gieo, bỏ trùng và giữ nguyên thứ tự."""
|
|
self.data["seeded_builtin_flows"] = list(dict.fromkeys(ids or []))
|
|
|
|
|
|
__all__ = ["ConfigSectionsMixin"]
|