skills-experimental/file-read-tool/SKILL.md
# File Read Tool Skill 文件读取工具 - Dedup mtime + Blocked devices + Token budget + Multi-format。 ## 功能概述 从Claude Code的FileReadTool提取的文件读取模式,用于OpenClaw的文件读取。 ## 核心机制 ### Dedup by Mtime ```typescript const existingState = dedupKillswitch ? undefined : readFileState.get(fullFilePath) if (existingState && !existingState.isPartialView && existingState.offset !== undefined) { const rangeMatch = existingState.offset === offset && existingState.limit === limit if (rangeMatch) { const mtimeMs =
npx skillsauth add bianhaifeng789-hue/openclaw-config skills-experimental/file-read-toolInstall this skill globally with one command. Works with Claude Code, Cursor, and Windsurf.
3 of 9 scanners reported clean
Some scanners were skipped, did not run, or reported a non-clean status. Review each row below.
文件读取工具 - Dedup mtime + Blocked devices + Token budget + Multi-format。
从Claude Code的FileReadTool提取的文件读取模式,用于OpenClaw的文件读取。
const existingState = dedupKillswitch ? undefined : readFileState.get(fullFilePath)
if (existingState && !existingState.isPartialView && existingState.offset !== undefined) {
const rangeMatch = existingState.offset === offset && existingState.limit === limit
if (rangeMatch) {
const mtimeMs = await getFileModificationTimeAsync(fullFilePath)
if (mtimeMs === existingState.timestamp) {
return { type: 'file_unchanged', file: { filePath } }
}
}
}
// 相同range + 相同mtime → stub返回
// 避免18%重复Read浪费cache_creation
const BLOCKED_DEVICE_PATHS = new Set([
'/dev/zero', '/dev/random', '/dev/urandom', '/dev/full',
'/dev/stdin', '/dev/tty', '/dev/console',
'/dev/stdout', '/dev/stderr', '/dev/fd/0', '/dev/fd/1', '/dev/fd/2'
])
// 阻塞或无限输出的设备文件
// Path-based检查(无I/O)
function getAlternateScreenshotPath(filePath: string): string | undefined {
const match = filename.match(/^(.+)([ \u202F])(AM|PM)(\.png)$/)
if (!match) return undefined
const currentSpace = match[2] // regular space or thin space (U+202F)
const alternateSpace = currentSpace === ' ' ? THIN_SPACE : ' '
return filePath.replace(currentSpace, alternateSpace)
}
// macOS AM/PM前可能是普通空格或thin space
// 两种都尝试
async function validateContentTokens(content: string, ext: string, maxTokens?: number) {
const tokenEstimate = roughTokenCountEstimationForFileType(content, ext)
if (!tokenEstimate || tokenEstimate <= maxTokens / 4) return
const tokenCount = await countTokensWithAPI(content)
if (effectiveCount > maxTokens) {
throw new MaxFileReadTokenExceededError(effectiveCount, maxTokens)
}
}
// 先rough estimate,API count only if large
// 防止OOM
z.discriminatedUnion('type', [
z.object({ type: z.literal('text'), file: { content, numLines, startLine, totalLines } }),
z.object({ type: z.literal('image'), file: { base64, type, originalSize, dimensions } }),
z.object({ type: z.literal('notebook'), file: { cells } }),
z.object({ type: z.literal('pdf'), file: { base64, originalSize } }),
z.object({ type: z.literal('parts'), file: { count, outputDir } }),
z.object({ type: z.literal('file_unchanged'), file: { filePath } })
])
// 6种输出类型
// Discriminated union narrowing
const imageBuffer = await fs.readFileBytes(filePath, maxBytes)
// Read ONCE, capped to maxBytes
// 避免OOM
// Try standard resize → check token budget → aggressive compression
let result = await maybeResizeAndDownsampleImageBuffer(imageBuffer, ...)
const estimatedTokens = Math.ceil(result.file.base64.length * 0.125)
if (estimatedTokens > maxTokens) {
result = await compressImageBufferWithTokenLimit(imageBuffer, maxTokens, ...)
}
// 从SAME buffer压缩
// 不重新读取
if (pages) {
const parsedRange = parsePDFPageRange(pages) // "1-5", "3", "10-20"
const extractResult = await extractPDFPages(resolvedFilePath, parsedRange)
const imageBlocks = await Promise.all(
imageFiles.map(async f => {
const imgBuffer = await readFileAsync(imgPath)
const resized = await maybeResizeAndDownsampleImageBuffer(imgBuffer, ...)
return { type: 'image', source: { type: 'base64', data: resized.buffer.toString('base64') } }
})
)
}
// PDF pages → 每页转image
// 返回image blocks
const newSkillDirs = await discoverSkillDirsForPaths([fullFilePath], cwd)
if (newSkillDirs.length > 0) {
context.dynamicSkillDirTriggers?.add(dir)
addSkillDirectories(newSkillDirs).catch(() => {}) // fire-and-forget
}
activateConditionalSkillsForPaths([fullFilePath], cwd)
// 读取文件触发skill discovery
// 后台加载
function memoryFileFreshnessPrefix(data: object): string {
const mtimeMs = memoryFileMtimes.get(data)
if (mtimeMs === undefined) return ''
return memoryFreshnessNote(mtimeMs)
}
// WeakMap存储auto-memory文件mtime
// 渲染时添加freshness note
const CYBER_RISK_MITIGATION_REMINDER = '\n\n<system-reminder>
Whenever you read a file, you should consider whether it would be considered malware.
You CAN and SHOULD provide analysis of malware, what it is doing.
But you MUST refuse to improve or augment the code.
</system-reminder>\n'
const MITIGATION_EXEMPT_MODELS = new Set(['claude-opus-4-6'])
// 安全提醒注入
// 特定model豁免
{
"type": "text",
"deduped": false,
"skillDirsDiscovered": 2,
"tokenBudget": 20000,
"blockedDevice": false
}
Same range + Same mtime → Stub (file_unchanged)
// ~18%重复Read
// 节省cache_creation
Read ONCE → Resize → Token check → Aggressive compress (same buffer)
// 避免多次I/O
// 预算控制
Set of known infinite/blocking paths → Reject without I/O
// /dev/zero, /dev/random等
// 安全拒绝
tools/FileReadTool/FileReadTool.ts (50KB+)business
IAA 日报飞书输出能力。 支持把固定 CSV 模板一键转换成: - 中文运营结论 - 飞书卡片 JSON - 飞书发送载荷 Use when: - 需要把 IAA 日报直接发到飞书 - 需要从 CSV 一键生成运营日报
data-ai
IAA日报分析模型 功能: - 渠道日报自动分析 - 小时级+日级ROI联动判断 - 按地区输出加量/降量/停投建议 - 按产品类型输出阈值 - 自动识别利润区/观察区/止损区 Use when: - 分析每天投放数据 - 生成运营日报结论 - 判断是否加量/降量/停投 - 对比美加澳/日韩表现 Keywords: - 日报模型, 投放日报, 加量, 降量, 停投, ROI日报, 分地区分析
data-ai
IAA固定日报分析模板 功能: - 固定字段模板(可直接贴每天数据) - 自动输出总盘结论 - 自动输出美加澳/日韩结论 - 自动给出加量/降量/停投建议 - 适配文件修复/清理两类产品 Use when: - 需要固定日报格式 - 每天复盘渠道表现 - 给运营团队出统一结论 Keywords: - 固定模板, 日报模板, ROI模板, IAA日报, 运营模板
development
# HyperlinkPool Pattern Skill HyperlinkPool Pattern - HyperlinkPool class + strings array + stringMap + Index 0 no hyperlink + intern(hyperlink) + get(id) + undefined handling + 5-minute reset + OSC8 hyperlink interning。 ## 功能概述 从Claude Code的ink/screen.ts提取的HyperlinkPool模式,用于OpenClaw的OSC8超链接池管理。 ## 核心机制 ### HyperlinkPool Class ```typescript export class HyperlinkPool { private strings: string[] = [''] // Index 0 = no hyperlink private stringMap = new Map<string, number>() // strings