用户令逐字:「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/`)。
11 KiB
平台速查(硬编码事实,勿猜)
归属:技能
dsh-change-workflow的详情档(按需读,不是每次都要读)。 本档覆盖:平台速查(硬编码事实,勿猜)(原行 L14–L92)。 主文件 / 判据与流程主干 =../SKILL.md(§1 六阶段流程 · §2 红线 R1–R8 原文速查 · §3 本机 Git Bash 环境坑 · §4 并行调度结论)。 来源:2026-09-22「技能重组线」把../SKILL.md的 L14–L92 段逐行原样下沉到本文件,未改一字。 跨档引用:正文里的「§N / 见 §8 坑 N / 见下表」等编号,用../SKILL.md末节「详情索引」的原章节列定位。 维护:本文件与../SKILL.md的指针行成对;改内容时同时核对主文件的指针描述是否仍准确。
平台速查(硬编码事实,勿猜)
⚠️ 正确域名 =
ai1net.com(2026-09-19 由alotbuy.com迁入);alotbuy.com是旧域名、已降为 nginx 301 过渡装置 ——对它抓页面只会拿到 301 HTML,别误判为"改动没生效"(2026-09-11 踩过)。 平台页由门户直出(127.0.0.1:3080),生效副本只有/opt/dshs/web/一份。 存量会话提示(档案 45)落在web/login.html:告知「shell 频繁要求审批 → 新开一个会话即可」。⚠️
*.ai1net.com(含每个用户子域)都由同一个 vhost 先proxy_pass 127.0.0.1:3080(门户), 再由门户的src/supervisor/proxy.ts转发到实例 → 想改"子域访问行为"要改proxy.ts, nginx 的error_page/location到不了实例层(档案 49 实测)。 实例空闲回收后首次访问的链路(档案 49):导航(GET+Accept: text/html)→ 立刻 302 到web/wake.html(门户同源,动画 + 自动调/api/dsh/enter跳回);XHR/API → 等实例就绪后 继续转发(不是回错误/动画 —— 让请求最终成功,dsh 自身 loading 即反馈)。⚠️ 实例的浏览器凭证 cookie 名带随机后缀:
dsh-auth-<随机后缀>=v1.<base64>.<sig>(HttpOnly/Secure)。 实例重建后这个后缀会变(不是"过期",是"名字都不对")→ 已打开的页面手里那份对新实例永远无效。 档案 51 的修法在proxy.ts:非导航请求遇实例侧 401 → 取当前实例 token →GET /?token=换新 cookie → 覆盖 cookie 头透明重放同一请求 → 响应追加Set-Cookie回写浏览器(此后含 SSE 自动重连直接成功)。 重放闸门是canReplay = mayHaveBody ? bodyBuf !== undefined : true—— GET/HEAD 无请求体,一样要能重放。⚠️ "空闲回收"实际从未生效(2026-09-11 核实,别再拿它解释现象): ① TTL
instanceIdleTtlSeconds默认 = 7 天(src/config.ts:16760*60*24*7),线上 env 未设 → 等于不会触发; ② LRU 上限maxIdleInstances默认 = 4,只有第 5 个用户拉起实例时才淘汰最久未活跃者(现有 2 用户永远达不到); ③reapOnce()只看lastActive,而proxy.ts::resolveSubdomainAccess()每个子域请求都touch(), dsh 前端还有常驻 SSE/plugins/events→ 页面开着就永远"活跃",TTL 规则不可能命中。 历史实证:全历史grep -c "idle-reap"= 1(09-09 12:24 stop … idle>20s,是档案 08 拿 TTL=20s 做验证那次)。⛔ 别把"回收没生效"外推成"实例不会中断"(2026-09-11 我犯过这个错,被用户当面纠正)
「页面等一会就模型断开、必须刷新」的真凶是中断,与"空闲回收"是两码事。实测统计:
中断来源 实证 机制 ① 门户服务重启(主因) 2026-09-11 一天重启 48 次(全是部署/探活) 重启后 supervisor 内存 mains表清空 → 旧实例变孤儿(进程还在但不被跟踪)→ 再访问判not_running→ 重新拉起新实例(新端口/token/cookie 名) → 旧页面带旧 cookie → 401。这正是档案 51 的触发源② 实例崩溃后自动重启 近 4 天 crash-restart69 次(admin 34 / guest 16 / 测试号 19)admin 根因 = duplicate loader entry id: permission(exitCode 1)——启用与官方permission撞 id 的候选插件所致;guest = 信号终止(无 exitCode),紧跟服务重启③ 空闲回收 全历史 [idle-reap]仅 1 次(09-09 测试值 20s)从来没生效,不构成中断来源 必查手法:
journalctl -u dshs --since "-1d" | grep -c "Started DSH server login orchestrator"(重启次数)
grep -c crash-restart+grep -c idle-reap—— 三个数一比就知道该往哪查。治本方向(待办):① 部署攒批重启(别每改一处重启一次);② supervisor 启动时收养已存在 scope (本地模式目前无收养逻辑,
reconcile.ts只覆盖 k8s)→ 重启不再产生"新实例 + 401";③ 业务插件探活失败自动摘 bundle。 ⚠️ 配置风险:maxIdleInstances=4×MemoryMax=1024M(硬限上界) = 4096M 远超 宿主总量 1870MB(上限非预留,但真跑满必然换页)→ 撑不住,建议调 2。⚠️ dsh web 客户端的会话事件流走 SSE(
EventSource),不是 WebSocket(源码dsh-api-session-controller/lib/types/client/sessions/session.js)。凡"页面内自愈"类注入脚本, 只 hookfetch/XMLHttpRequest是够不到主链路的 —— EventSource 遇 401 只静默onerror重连, 界面什么都不显示(档案 50 因此对真实用户无效,档案 51 才在传输层根治)。 判断前端用什么传输别猜:grep -rl "new WebSocket\|EventSource" <dsh 包>。⛔ 注入脚本(
src/supervisor/proxy.ts的SESSION_*_JS)两条铁律 —— 2026-09-13 事故换来的: ① 它是 TS 模板字面量,里面的\n/${/ 反引号会在模板求值时先被处理一次。 写.join('\n')(单反斜杠)⇒ 求值后变裸换行 ⇒ 注入的 JS 直接 SyntaxError ⇒ 整段脚本静默不执行(浮层 / 自愈 / 助手面板全废,页面只剩 dsh 自己的「连接异常」)。 → 用String.fromCharCode(10);校验必须"先模板求值、再node --check":node 07-scripts/verify-inject.cjs lib/supervisor/proxy.js(已接入npm test,勿绕过)。 ⚠️new Function(原文)与「grep 页面 HTML 有没有标记」都是假绿 —— 前者跳过求值,后者验不出"跑不跑得起来"。 ② 触发面必须覆盖"页面开着不动":用户盯着页面时无任何事件;现已有 可见时 25 s 心跳 +EventSource/WebSocket断流包装,且两者都连续两次失败才恢复(恢复=原地 replace,会丢未保存输入)。🔴 浏览器自动化:唯一允许
browser-harness(⚠️ 2026-09-25 用户明令:「改为 browser-harness,只允许使用这个」 ⇒ 此前「两件(含agent-browser)」的口径作废): ①browser-harness(CDP)—— 唯一允许的一条:全局 console scriptbrowser-harness(~/.local/bin); ⛔ 动手前必须先list_tabs();默认起独立 headless 实例(BU_CDP_URL指向 9223),⛔ 绝不附着用户日常 Chrome —— 旧事故:在其浏览器里登录测试号 → 覆盖了用户的.ai1net.com的sid。 📂 正确调用(含 2026-09-25 实测路径更正)⇒08-浏览器验证栈详解.md。 ⛔agent-browser已禁用(2026-09-13 曾定为「本项目默认」,2026-09-25 用户明令收窄 ⇒ 新增此禁); ⛔ 禁止 Playwright /playwright-core(含「独立无头」用法)(用户 2026-09-13 明令:「playwright 禁止使用,加到规则中」)。 静态页与 API 取数优先curl/ WebFetch,别动浏览器。
| 项 | 值 |
|---|---|
| 服务器 | 47.77.182.89(Alibaba Cloud Linux al8);SSH:ssh -i ~/.ssh/id_ed25519 -p 22 [email protected](🔴 2026-09-22 实测更正:~/.ssh/config 里的别名 bt-server 写死 Port 32022,而 sshd 只监听 22 ⇒ 用它必 Connection refused;私钥真名 ~/.ssh/id_ed25519,⛔ 技能旧文里的 id_ed25519_dsh 不存在) |
| 门户 | dshs(systemd dshs,127.0.0.1:3080);源码 /opt/dshs(git master) |
| 数据 | /var/lib/dshs/users/<id>/{home,ws};DB /var/lib/dshs/dshs.db(root 600) |
| 域名 | ai1net.com(门户,CF 代理 + 通配证书,源站 443);用户子域 <用户名>.ai1net.com 经 portal proxy 转发实例;旧 alotbuy.com 301 → ai1net.com(档案 22 / 2026-09-19 迁入) |
| 实例 | 门户 spawn node /usr/local/bin/dsh --profile web --host 127.0.0.1 --port <动态>;ISOLATION account(setpriv,uid∈[100000,199999];admin=114801) |
| 文档 | 本机 git 工作树 = 唯一源:🔴 D:/github/dsh_shenxian/dsh-server-docs(仓库 dsh_shenxian_doc)→ 同步到服务器 /opt/dsh/docs(无 .git 的部署镜像;08-skills/** 与根 README.md/INDEX.md 均 600 root:root)。⚠️ 2026-09-22 实测更正:旧文写的 E://ProgramData//AI技能//aliyun-dsh-server//dsh-server-docs 该目录不存在(本工作区里只有 docs/,那是会话规则副本);⚠️ 根 README.md/INDEX.md 也在服务器上有一份 ⇒ 登记跟改后要连它们一起推。⛔ 本行 2026-09-13 更正:原文写「服务器唯一源 / 本地不保留副本 / dsh-server-docs/ 已废弃」——那是更早的状态,现已作废 |
| 文档同步 | 改完跑四件套:docs-audit.py → docs-index-stats.py --write(INDEX 状态摘要机器生成)→ docs-manifest.py → docs-sync-check.sh → docs-consistency.py;只 scp 自己本次改的文件、推前复跑对账。⛔ docs-status/ 机制已不存在(原文作废) |
| 硬规则 | 动文档 / 代码 / 服务器之前先抢全局执行锁(bash dsh-server-docs/07-scripts/handoff-guard.sh --claim-exec "<会话名>");要动生产再占服务器侧 07-scripts/op-lock.sh;同一时刻只放一个执行会话。规则实体在项目根 CODEBUDDY.md(§3 红线 R1–R9 / §6 并发纪律)—— 本技能不复述、也不得与之冲突。⚠️ 释放 op-lock 必须带 ME=<原占用者>,否则按 R9 被拒 |
| 档案号 | 复跑取号,勿写死(`ls 04-调整方案/ |