AI Curfew · AI 熄灯
把「AI 永远在线」拧成「AI 也要下班」。
到点之后回复越来越短,深夜档把 max_tokens 从 2048 慢慢压到 64,凌晨三点只回一句「明天再说」。
高峰时段不上班、低谷时段上班;已下班状态照样收消息,但只回一个「。」。
卖点不是让模型演下班,而是真的下班:下班后一个 API 请求都不发 —— 0 token、0 成本、毫秒返回。
on-duty 上班中 ──→ winding 打烊倒计时 ──→ off-duty 已下班 ──→ lights-out 熄灯
(满血) maxTokens 2048→64 只回「。」 只回「明天再说。」
行为
| 时刻 | 判定 | 回法 |
|---|---|---|
| 周二 10:00 | 高峰 | 。 |
| 周二 20:00 | 低谷、未到宵禁 | 正常上班 |
| 周二 23:30 | 宵禁 winding | 短回复,预算 ≈1824 |
| 周三 01:30 | 宵禁 winding | 一句话,预算 ≈560 |
| 周三 02:30 | 宵禁 winding | 最多 20 字,预算 ≈192 |
| 周三 03:10 | 宵禁到底 | 明天再说。 |
| 周日 14:00 | 周末全天低谷 | 正常上班 |
两条独立的轴,取谁更严谁生效:
- A 峰谷班表 —— 高峰不上班、低谷上班(周一至周五 9:00–12:00、14:00–18:00,扣掉周末与法定节假日)
- B 宵禁曲线 —— 到点后预算沿锚点表从 2048 滑到 64,凌晨 3 点彻底熄灯
闸门 A 可以单独关掉,退化成纯宵禁插件。
安装
profile 是 DSH 里一套隔离的插件与配置环境,一台机器可以有好几套(常见的有 desktop、web、
headless)。把下面的 desktop 换成你实际在跑的那个。
从 GitHub 装(装了固定版本,推荐):
dsh plugin --profile desktop add github:qiz42144-web/dsh-ai-curfew#v0.1.0
末尾的 #v0.1.0 是 tag;去掉它就会跟着 main 的最新状态走。
从本地目录装(改这个插件本身时用):
dsh plugin --profile desktop add link:/绝对路径/ai-curfew
装好后客户端半体由 /plugins 提供(侧栏底部的状态胶囊 + Settings 里的班表页),Host 半体即刻生效。
配置
配置是 $DSH_HOME/dsh-ai-curfew/config.json,改完即生效(按 mtime 热读,不用重启)。
文件里只写你想改的键,其余走默认值:
{
"curfewStart": "23:00",
"lightsOut": "03:00",
"wakeUp": "09:00",
"peakShift": true,
"offDutyReply": "。",
"lightsOutReply": "明天再说。",
"debugNow": "01:30"
}
| 键 | 默认 | 说明 |
|---|---|---|
enabled |
true |
总开关 |
timezone |
Asia/Shanghai |
班表按时区本地时间算 |
wakeUp / curfewStart / lightsOut |
09:00 / 23:00 / 03:00 |
一天的四个相位,窗口可跨午夜 |
anchors |
23:00→2048 … 03:00→64 | 预算锚点表,[时刻, tokens] |
curve |
linear |
linear(锚点间插值) / step(阶梯) / easeIn(先稳后崩) |
peakShift / peakWindows / weekendValley / holidays |
开 / 9-12,14-18 / 开 / 2026 表 | 峰谷闸门 |
offDutyReply / lightsOutReply |
。 / 明天再说。 |
不请求时回什么 |
tiredPersona / tierTexts |
开 / 四档 | 往提示词注入的疲惫档位,每四分之一窗口一档 |
denyToolsWhenOffDuty |
true |
下班后不再执行工具调用 |
windingReasoningEffort |
null |
可选:宵禁期间降到某个 reasoning effort id |
dryRun |
false |
只判定并记录,照常发请求(安全试跑) |
debugNow |
null |
时间机器:HH:MM 或 YYYY-MM-DD HH:MM |
applyToSubagents |
true |
子代理是否一起宵禁;设 false 让派出去的活继续干完 |
exemptSessions |
[] |
豁免的会话 id,完全不干预 |
safetyMaxTokens |
null |
见下方说明,默认关闭 |
命令行
/curfew 看班表:当前判定、预算与依据
/curfew overtime 30m 强制加班 30 分钟(宵禁暂停,期间正常上班)
/curfew off 立刻下班
/curfew auto 恢复自动班表(加班 / 强制下班 / 时间机器 全部取消)
/curfew debug 01:30 时间机器,随时试任何时段
/curfew debug clear 回到真实时间
命令不经过模型,所以下班状态下也能用 —— 这是「把自己关在门外」的逃生口。
为什么是「加班」不是「请假」:请假的主语是 AI,是它在请求不上班;但 /curfew overtime
实际发生的是你命令它加班。同理 off 只管「AI 下班」这一件事,不再兼职表示「宵禁关掉」。
关于 safetyMaxTokens
默认关闭,这是有意的。下班由 llm/stream 短路保证,所以第二道上限在它有用的地方都是多余的;
而在它不该管的地方反而有害 —— reasoning 模型会把很小的预算全花在思考上,于是既没有正文也没有
工具调用,供应商直接判这一轮失败:
Command Code reached the output token limit without producing answer text or a tool call
(finish_reason=length, max_tokens=16, outputTokens=16, reasoningTokens=16) [OUTPUT_TOKEN_LIMIT]
想加一道硬上限可以自己填数字,但请按模型的思考预算来给,而不是按你期望的回复长度。
原理
下班回复走 llm/stream waterfall 的短路:直接吐一段合成的流,完全不触网。
这不是 agent/pre-step 的 reject —— 那样这一轮会彻底没有回复,用户看到的是「AI 死了」。
需求是「照样收消息,只回一个句号」,所以必须产出一条真实的 assistant 消息,由 agent loop 自己
组装并写入会话日志,我们只负责提供 chunk。
完整设计、踩过的坑、以及「为什么不能用 agent/pre-step + 手写事件」见
docs/architecture.md;核实过的 DSH 契约见
docs/dsh-contracts.md。
开发
node --test # 零依赖;验收表就是断言
行为判定全是纯函数(duty.js / clock.js),所以整套班表不需要跑 Host 就能测。
徽章是提交进仓库的本地 SVG(node scripts/make-badges.mjs 重新生成),不走 shields.io ——
不依赖任何第三方服务,也不会因为图片代理不可达而裂图。只有 tests 那个是 GitHub 自己的工作流
徽章(同样在 github.com 上,不经第三方),因为它报的是测试现在过不过,比"用什么命令跑"有用。
CI 跑在 GitHub Actions 上:Node 22 / 24 × Linux / Windows 四个组合。因为零依赖,没有 install
步骤,就是 checkout + 一行 node --test。同一条流水线还会校验 badges/ 与生成器一致 ——
手改徽章或改了生成器没重跑,都会红。
改完代码要重启 DSH 才生效。 运行中的进程按 URL 缓存插件的 ES module,停用再启用只会重跑
apply(),不会重新 import。scripts/dev-reload.ps1 用一个新 revision 目录 + 重接 junction 绕开它,
代价只要一次停用/启用。为什么 HMR 那条路走不通,也记在
docs/architecture.md。
状态
尚未发布到 npm,从 GitHub 装上就能用(见上面的安装一节);版本 0.1.0。
哪些行为已经实测验收、哪些还没有,见 docs/acceptance.md。
许可与出处
MIT。峰谷口径与 2026 节假日数据的来源、署名,以及必须每年 11 月补表的维护责任,见
PROVENANCE.md。
No comments yet. Be the first to write one.