用户令逐字:「E:/ProgramData/.workbuddy/skills 提交仓库是指的这里」—— 即本目录就是仓库(2026-10-07 已在本目录建仓,见当日日志 §22),本轮把余下未纳管的 9 个技能一并提交。 本次入库(9 个技能,46 个文件): 1、`AI HOT` 2、`draw-ui` 3、`dsh-diagnose` 4、`dsh-knowledge` 5、`dsh-local-env` 6、`dsh-opensource-release` 7、`dsh-workflow` 8、`oil-motion` 9、`skills-security-check` 提交前核对: · **凭据类扫描**(`*.env` / `*token*` / `*.key` / `*secret*` / `*.pem`)⇒ **零命中** ✓; · 体积合计约 20 MB(`draw-ui` 12M + `oil-motion` 6.5M 是大头,形态为配图/素材 —— 仓库 `.gitignore` 里明写「`assets/*.png` 是内容不是产物」⇒ 属刻意入库); · 运行产物仍按既定规则排除(`__pycache__` / `logs/` / `tmp/` / `.venv/` / `*.egg-info` / `uv.lock` / `.workbuddy/`)。
9.7 KiB
AI HOT v1 API 参考
只在需要完整参数、字段、分页或构建客户端时读取本文件。普通资讯问答优先遵循 SKILL.md 的默认路由。
共同合同
- Base URL:
https://aihot.virxact.com - 匿名只读,不需要 API Key,不发送 cookie。
- OpenAPI:
https://aihot.virxact.com/openapi-v1.json - 所有 cursor 都是不透明书签:只原样回传给产生它的同一端点和同一查询,不解析、不修改、不跨查询复用。
- 未知参数、无效参数、损坏或跨查询 cursor 都返回明确的 Problem JSON,不会静默回到第一页。
- 对同一完整 URL 保存响应
ETag;下次发送If-None-Match。304表示内容未变化。 - items cursor 没有按时间自动失效,但 24 小时/7 天是滚动窗口,较老条目可能在两次翻页之间自然离开窗口;需要精确镜像时改用 selected snapshot + changes。
操作
最近资讯、分类与搜索
GET /api/v1/items
| 参数 | 合同 |
|---|---|
mode |
selected 或 all;默认 selected |
window |
24h 或 7d;默认 7d |
by |
timeline 或 published;默认 timeline(见下方「时间口径」) |
category |
ai-models、ai-products、industry、paper、tip |
q |
2—200 字;使用服务端搜索 |
limit |
1—100;默认 50。只需要头几条时显式调小,别默认拉满 50 |
cursor |
原样回传上一页的 page.nextCursor |
时间口径
window 从哪个时间点往回算、结果按哪个时间排序,由 by 决定。两个原始时间戳恒定随每条返回,可自行判断。
by=timeline(默认):与 aihot.virxact.com 网页看到的顺序和集合一致。规则是——原文发布后 72 小时内被收录,按收录时间;超过 72 小时才收录的历史回填,归位到原文发布日。所以官方博客、公众号、HuggingFace Daily 这类「原文两三天前发、今天才抓到」的慢推信源,仍会出现在window=24h里,同时旧文回填不会冒充最近。by=published:只按第三方原文发布时间。慢推信源会掉出短窗口——同一时刻window=24h下它比默认口径少约两成条目。需要严格按原文时间线对账时才用。
切换 by 会让已持有的 cursor 失效并返回 invalid_cursor,这是有意的:换了口径继续用旧书签会串页。重新从第一页开始即可。
响应外层:
{
"schemaVersion": 1,
"query": {
"mode": "selected",
"category": null,
"q": null,
"window": "24h",
"by": "timeline",
"ordering": "timelineDesc"
},
"items": [],
"page": {
"count": 0,
"hasMore": false,
"nextCursor": null
}
}
每个 item 必有以下键:
idtitleoriginalTitlesummarysource.namelinks.aihotlinks.originalpublishedAtdiscoveredAtcategoryscoreselected
其中 originalTitle、summary、publishedAt、category 和 score 的键始终存在,但值可以是 null;展示前必须判空。id、title、source.name、links.aihot、links.original、discoveredAt 和 selected 为非空值。响应还可能带可选的 attribution,客户端不得依赖它一定存在,也不得因未来新增未知字段而报错。page.count 是本页条数,不是全库总数。
示例:
GET /api/v1/items?mode=selected&window=24h&limit=8
GET /api/v1/items?mode=selected&window=7d&category=paper&limit=20
GET /api/v1/items?mode=selected&window=7d&q=OpenAI&limit=20
GET /api/v1/items?mode=all&window=24h&limit=50
当前热点
GET /api/v1/hot-topics
响应为 {schemaVersion, count, items},不是可续页集合。保持 API 热度顺序。item 包含 sourceCount、signalCount、sourceNames、latestAt,并可能包含可选的 links.story(给人阅读的 HTML 事件页);其中 sourceCount 是独立信源数。热点与普通资讯字段不同,不得把两种响应强行混成同一列表协议。
事件详情
GET /api/v1/stories/{publicId}
publicId 只取自实际返回的 hot-topics links.story,或另一个 story 响应里 storyline/related 的引用。对于 links.story,先确认 URL 属于 https://aihot.virxact.com/story/{publicId},只提取路径末段的实际 publicId,再调用本 API;不得直接请求该 HTML 网页 URL,也不得把网页响应当 API 数据。字段缺失或 URL 格式不符时不得猜测 id,改用 items 关键词查询。响应为 {schemaVersion, story}:story.reports 是逆序报道时间线(每条含站内 links.aihot);story.digest 是随事件演化增量更新的 AI 综述(与旧结论矛盾处会显式标注),story.latest 是最新进展一句话;storyline/related 是关联事件引用(含 links.api 可直接续跳)。事件被合并时返回 308,跟随 Location 即可;404 表示事件层或该事件当前不可用,回落到 items。status 为 settled 表示事件已收束(超过 48 小时无新报道)。
日报
GET /api/v1/dailies?limit=7
GET /api/v1/dailies/latest
GET /api/v1/dailies/2026-07-24
- 索引响应为
{schemaVersion, count, items},不是可续页集合。 - 最新或指定日报响应为
{schemaVersion, report}。 - 保留 report 的
lead、sections与flashes结构,不把日报重排成普通 items。 - 日报索引项和 report 顶层的
links.aihot必有。sections/flashes 中links.aihot可能为null;此时使用必有的links.original,不要再寻找旧字段permalink或sourceUrl。 - 最新日报或指定日期返回 404 时,索引只查一次有界的
/api/v1/dailies?limit=7。索引有结果时,从中选择实际返回的最近日期,再请求一次对应的/api/v1/dailies/{date}取得完整日报并如实说明日期;索引为空就报告当前没有可用日报。绝不猜“昨天”或自行拼接日期。
正文与周期报告边界
items只返回标题、摘要、来源、时间、评分和链接,不返回正文,也没有/api/v1/items/{id}。用户要深入阅读时提供links.aihot和links.original,不要抓网页或全文 RSS 冒充单篇正文 API。- AI HOT 编辑成品周报与月报目前只有
/weekly和/monthly网页,没有 v1、Skill 或 RSS 端点。“最近一周精选”仍是滚动 7 天 items 查询,不得称为正式周报。
完整精选同步
GET /api/v1/selected/snapshot?fields=minimal&limit=500
GET /api/v1/selected/snapshot?fields=minimal&limit=500&page=<opaque>
GET /api/v1/selected/changes?cursor=<opaque>&limit=100
只有用户明确要求当前全部精选或持久镜像时才使用。完整算法见 sync.md;不要仅凭本文件实现同步状态机。
snapshot 是分页的,一次请求拿不到全部:
| 参数 | 合同 |
|---|---|
fields |
default 或 minimal;默认 default。minimal 去掉摘要与原文链接,体积约为 default 的四分之一 |
limit |
1—1000;默认 500 |
page |
原样回传上一响应的 nextPage;续页的 fields 由游标锁定,传不同值无效 |
响应里有两个不同的游标,不要混用:
cursor:同步游标,逐页恒定,指向第一页取到的水位。翻完所有页之后才拿它调changes。nextPage:翻页游标,只在本轮快照内有效。hasMore=true时必须继续翻,否则镜像不完整。
规模参考:当前约 2900 条,fields=default 全量约 3.1MB(gzip 1.05MB),fields=minimal 约 1.08MB(gzip 247KB)。条目只增不减,会逐年变大——不确定就用 minimal,需要摘要时再取 default。
分页
- 处理当前页全部 items。
page.hasMore=true时,原样回传page.nextCursor请求下一页。- 达到用户指定数量即可停止;无需为了“完整”耗尽所有页。
page.hasMore=false时结束。- cursor 报错就报告或按对应恢复合同处理,绝不删掉 cursor 后假装翻页成功。
- 普通 items 分页不是一致性快照;新条目不会造成已翻页内容重复,但滚动窗口内的编辑、撤选和自然过期可能改变后续页。完整、可恢复同步只使用 selected snapshot + changes。
字段语义
links.aihot:AI HOT 站内中文阅读页,默认主链接。links.original:第三方原文,仅在用户要出处时附加。originalTitle:来源原标题,可能不是英文。publishedAt:第三方原文发布时间。展示前把 ISO 时间转换到Asia/Shanghai。discoveredAt:AI HOT 首次收到时间。publishedAt为空时可回退使用,但必须标为“AI HOT 收录时间”。score:0—100 总分,可能为空,不表示当前响应按它排序。selected:是否属于当前精选。category:允许未来增加新值;不要把未知值当成响应损坏。
时间范围
v1 只承诺 24h 和 7d 两个服务端窗口:
- 今天、过去 24 小时:用
24h。 - 最近、最近一周:用
7d。 - 用户要 2 天、3 天等其它七天内范围:取
7d后本地收窄。收窄用的字段必须与请求的by口径一致,否则会切掉服务端本来算在窗口内的条目:- 默认
by=timeline:用时间轴值——publishedAt为空取discoveredAt;discoveredAt - publishedAt > 72 小时(历史回填)取publishedAt;其余取discoveredAt。 - 显式
by=published:才直接用publishedAt。 - 拿
publishedAt去收窄默认口径,会把官方博客、公众号、HuggingFace Daily 这类慢推信源整批误删(见上方「时间口径」)。
- 默认
- 超过 7 天的普通公开池不承诺可用;不要用 selected snapshot 冒充历史搜索。