✨ feat(vscode): 代码阅读的注释挂到它讲的代码块上成「注释」一行,重写注释改用技能一句话加结构化结果

- 普通注释不再单独成卡片:同一层挂到后面最近的块(隔空行也算),后面没有挂到前面那块,整层没代码挂到父块;只有文件开头隔着空行的注释、模块 docstring、//!、@file 单独成「文件开头的说明」
- 各语言(Python、TypeScript、Rust、Shell、Dockerfile)建好树后统一调 attachComments;块的编辑范围连着挂上的注释,差异、跳转、钉住卡片都按它
- 宿主统一给每张卡片(语言卡片、翻译插件的属性表、库规则卡片、一行译文的语句卡片)插「注释」一行,排在名称、说明后面
- TypeScript 的 JSDoc 也能当常量、变量的说明;sqlx、React 不再单独处理前面的注释
- 「重写注释」每块都有:提示只发 /ecc:writing-code-comments 路径:起-止,模型只读、按 --json-schema 交 body,没交结构化正文就失败不写;扩展换掉块前面的注释或在块上面新写一段
This commit is contained in:
cruldra committed 2026-10-08 07:51:21 +08:00
1 parent 335cf9ca9f
commit 582ac4c987
49 files changed
+1730 -757

No files matched your search

@@ -0,0 +1,139 @@
from collections import Counter
from collections.abc import Sequence
from datetime import date, datetime
from sqlalchemy import exists, func, select
from sqlalchemy.ext.asyncio import AsyncSession
from luffy_agent.acquisition.models import AcquisitionChannel
from luffy_agent.core.filter.repository import FilterableRepository
from luffy_agent.core.time import to_shanghai_date
from luffy_agent.referral.models import ReferralRelation
# luffy_agent.user.models.User 在各方法体内按需局部导入 (非模块顶层):
# user 包 __init__ 会级联加载到 acquisition.service, 而 acquisition 是整个
# 应用最早被 import 的域之一 (见 api_routers.py 的 include 顺序), 顶层导入
# 会与该级联互相等待, 构成循环导入。
class AcquisitionChannelRepository(
FilterableRepository[AcquisitionChannel, dict[str, object], dict[str, object], int]
):
def __init__(self) -> None:
super().__init__(AcquisitionChannel)
self._filter_config = {"field_mapping": {}, "search_fields": ["code", "name"]}
async def get_by_code(
self, db: AsyncSession, *, code: str
) -> AcquisitionChannel | None:
result = await db.execute(
select(AcquisitionChannel).where(AcquisitionChannel.code == code)
)
return result.scalar_one_or_none()
async def get_required_system(
self, db: AsyncSession, *, code: str
) -> AcquisitionChannel:
channel = await self.get_by_code(db, code=code)
if channel is None or not channel.is_system:
raise RuntimeError(f"system acquisition channel missing: {code}")
return channel
async def list_all(self, db: AsyncSession) -> Sequence[AcquisitionChannel]:
"""全量渠道列表, 按 id 升序, 无 limit。
渠道基数小 (系统内置 + 管理员自建), 不做分页; 不可复用
``list_filtered`` 的默认 ``limit=100``, 否则超过 100 个渠道时
管理后台列表与来源分析 report 会被静默截断。
"""
result = await db.execute(
select(AcquisitionChannel).order_by(AcquisitionChannel.id.asc())
)
return result.scalars().all()
async def count_users_by_channel(
self, db: AsyncSession, *, start_at: datetime, end_at: datetime
) -> list[tuple[AcquisitionChannel, int]]:
"""窗口内 (半开区间) 各渠道用户数, 仅含窗口内有用户的渠道。"""
from luffy_agent.user.models import User
from luffy_agent.user.repositories import customer_user_predicate
stmt = (
select(AcquisitionChannel, func.count(User.id))
.join(User, User.acquisition_channel_id == AcquisitionChannel.id)
.where(
User.created_at >= start_at,
User.created_at < end_at,
customer_user_predicate(),
)
.group_by(AcquisitionChannel.id)
)
result = await db.execute(stmt)
return [(channel, count) for channel, count in result.all()]
async def count_daily_by_channel(
self, db: AsyncSession, *, start_at: datetime, end_at: datetime
) -> list[tuple[int, date, int]]:
"""窗口内各渠道逐日 (沪时区自然日) 用户数。"""
from luffy_agent.user.models import User
from luffy_agent.user.repositories import customer_user_predicate
stmt = select(User.acquisition_channel_id, User.created_at).where(
User.created_at >= start_at,
User.created_at < end_at,
customer_user_predicate(),
)
result = await db.execute(stmt)
counter: Counter[tuple[int, date]] = Counter(
(channel_id, to_shanghai_date(created_at))
for channel_id, created_at in result.all()
)
return [
(channel_id, day, count) for (channel_id, day), count in counter.items()
]
async def count_referred_users(
self, db: AsyncSession, *, start_at: datetime, end_at: datetime
) -> int:
"""窗口内曾被邀请过的用户数 (不看邀请关系 status/expire_time)。"""
from luffy_agent.user.models import User
from luffy_agent.user.repositories import customer_user_predicate
stmt = select(func.count(User.id)).where(
User.created_at >= start_at,
User.created_at < end_at,
customer_user_predicate(),
exists(
select(ReferralRelation.id).where(
ReferralRelation.invitee_user_id == User.id
)
),
)
result = await db.execute(stmt)
return result.scalar_one()
async def count_referred_daily(
self, db: AsyncSession, *, start_at: datetime, end_at: datetime
) -> list[tuple[date, int]]:
"""窗口内被邀请用户逐日 (沪时区自然日) 数量。"""
from luffy_agent.user.models import User
from luffy_agent.user.repositories import customer_user_predicate
stmt = select(User.created_at).where(
User.created_at >= start_at,
User.created_at < end_at,
customer_user_predicate(),
exists(
select(ReferralRelation.id).where(
ReferralRelation.invitee_user_id == User.id
)
),
)
result = await db.execute(stmt)
counter = Counter(
to_shanghai_date(created_at) for (created_at,) in result.all()
)
return list(counter.items())
acquisition_channel_repository = AcquisitionChannelRepository()