Files
Kin Gao f7fc6c9fcd feat(pet): 真人表情包桌宠,适配 Codex 与 DSH
- pet/:零依赖桌宠(本地 HTTP 服务 + SSE + 状态清单),六种状态
  各有动作与台词;内置「鼓掌」实拍素材作为庆祝态示例
- Codex 适配:integrations/codex-notify.mjs 挂到 config.toml 的
  notify 钩子,回合完成即鼓掌
- DSH 适配:integrations/dsh-watch.mjs 观察会话活动自动切状态,
  agent 也可用 CLI 直接触发
- 安装器新增 DSH skill 目录检测;隐私检查覆盖 pet/
2026-08-24 00:28:14 +08:00

53 lines
2.1 KiB
JavaScript

#!/usr/bin/env node
import { readFile, readdir } from 'node:fs/promises';
import path from 'node:path';
import { fileURLToPath } from 'node:url';
const here = path.dirname(fileURLToPath(import.meta.url));
const repoRoot = path.resolve(here, '..');
const packageRoots = ['README.md', 'SKILL.md', 'START.md', 'agents', 'bin', 'package.json', 'pet', 'references', 'scripts'];
const forbiddenContent = [
{ label: '本机绝对路径', pattern: /(?:\/Users\/|\/home\/[^/\s]+\/|[A-Za-z]:\\Users\\)/ },
{ label: '飞书共享链接', pattern: /https:\/\/[^\s)]+\.feishu\.cn\/share\//i },
{ label: '私钥块', pattern: /-----BEGIN (?:RSA |EC |OPENSSH )?PRIVATE KEY-----/ },
{ label: '常见密钥或令牌', pattern: /(?:github_pat_|ghp_|xox[baprs]-|AKIA)[A-Za-z0-9_-]{12,}/ },
{ label: '微信内部 ID', pattern: /wxid_[A-Za-z0-9_-]{6,}/i },
];
const forbiddenName = /(?:^|[._-])(?:\.env|credentials?|secrets?|private|tokens?)(?:[._-]|$)/i;
async function collect(relativePath) {
const absolutePath = path.join(repoRoot, relativePath);
const entries = await readdir(absolutePath, { withFileTypes: true }).catch(() => null);
if (!entries) return [relativePath];
const files = [];
for (const entry of entries) {
const child = path.join(relativePath, entry.name);
if (entry.isDirectory()) files.push(...await collect(child));
else if (entry.isFile()) files.push(child);
}
return files;
}
const files = (await Promise.all(packageRoots.map(collect))).flat();
const errors = [];
for (const relativePath of files) {
if (forbiddenName.test(relativePath)) errors.push(`${relativePath}: 可疑文件名`);
const text = await readFile(path.join(repoRoot, relativePath), 'utf8').catch(() => null);
if (text === null) continue;
for (const check of forbiddenContent) {
if (check.pattern.test(text)) errors.push(`${relativePath}: ${check.label}`);
}
}
if (errors.length) {
process.stderr.write(`隐私检查失败:\n- ${errors.join('\n- ')}\n`);
process.exitCode = 1;
} else {
process.stdout.write(`隐私检查通过:已检查 ${files.length} 个发布文件。\n`);
}