在技能中调用脚本和现有工具
为代码检查技能添加只读 Node 脚本,处理参数、工作目录、退出状态和输出边界。
在技能中调用脚本和现有工具
需要确定文件大小、函数声明清单等事实时,让模型自己数容易出错。可以把这部分交给脚本,再让模型结合源码解释结果。
本篇实现完整技能目录中引用的脚本。脚本只读取用户指定文件,不执行源码、不修改文件、不安装依赖。
用脚本提供可核对事实
创建 skills/code-inspection/scripts/inspect-source.mjs:
import { readFile, stat } from 'node:fs/promises'
import { basename, extname, resolve } from 'node:path'
const args = process.argv.slice(2)
if (args.length !== 1) {
console.error('用法:node inspect-source.mjs <目标文件>')
process.exitCode = 2
} else {
try {
const path = resolve(args[0])
if (!['.js', '.jsx', '.ts', '.tsx'].includes(extname(path).toLowerCase())) {
throw new Error('只接受 JavaScript 或 TypeScript 文件')
}
const info = await stat(path)
if (!info.isFile() || info.size > 64 * 1024) {
throw new Error('输入必须是最多 64 KiB 的普通文件')
}
const source = await readFile(path, 'utf8')
if (Buffer.byteLength(source, 'utf8') > 64 * 1024) {
throw new Error('文件读取期间超出大小限制')
}
const declarations = [...source.matchAll(/function\s+([A-Za-z_$][\w$]*)\s*\(/g)].map((match) => ({
name: match[1],
line: source.slice(0, match.index).split('\n').length,
}))
console.log(JSON.stringify({
file: basename(path), bytes: Buffer.byteLength(source, 'utf8'), declarations,
limitation: '仅扫描普通命名函数文本,不是编译器或完整语义检查',
}, null, 2))
} catch (error) {
console.error(error instanceof Error ? error.message : String(error))
process.exitCode = 1
}
}脚本接受一个路径参数,支持几种 JavaScript/TypeScript 扩展名,限制文件大小,并输出普通命名函数文本的名字与行号。大文件或错误输入失败时,不生成假的成功对象。
这不是编译器。箭头函数不会被当前表达式识别,注释或字符串中的相似文本也可能被误识别,因此模型还要读实际源码核对。扩展名检查不构成文件系统沙箱。
先脱离模型单独运行
在练习项目根目录执行:
node ./skills/code-inspection/scripts/inspect-source.mjs ./fixtures/sample.ts检查 file、bytes 和声明行号是否与实际文件一致。输出的 limitation 保留能力限制,不把清单写成质量结论。
测试失败路径:
node ./skills/code-inspection/scripts/inspect-source.mjs
node ./skills/code-inspection/scripts/inspect-source.mjs ./fixtures/missing.ts缺参数退出码为 2,文件等执行错误为 1;成功为 0。错误写到标准错误,结构化结果写到标准输出。宿主必须检查退出状态,不把一段错误文字当作成功数据交给模型。
再让技能组织工具调用
使用完整技能目录,启动允许读取和执行脚本的宿主:
npx --no-install pi --no-extensions --no-skills --skill ./skills/code-inspection --tools read,bash在交互中调用:
/skill:code-inspection 检查 fixtures/sample.ts,先取得脚本观测,再按模板生成报告。观察是否读取规则、以正确脚本路径执行、保留真实退出状态,再生成报告。技能说明与宿主工具选择是两层:正文中的命令不是已经执行的事实,目录里有脚本也不等于宿主自动注册了新工具。
不把路径拼成任意命令
用户文件名应作为独立参数传递,含空格时正确引用。可使用固定的 Node 入口和脚本路径,不根据源码里的文字追加 shell 命令。
相对用户路径从工作目录解释,脚本本身从技能位置定位。复制技能到另一个项目后再次验证,不能把个人电脑绝对路径写死在 Skill 中。
用户限制与执行失败怎样处理
用户要求不运行脚本时,应说明本次仅做源码阅读;宿主没有 Node 或执行权限时也应报告限制。不能为了满足模板而写“脚本检查通过”,更不能把没有运行的项目测试写成通过。
脚本只读取一份已明确指定的练习文件,不保证任意第三方 Skill 同样只读。实际动作仍由宿主权限、工具实现和任务授权控制。
脚本的正常与错误路径已实际检查,模型能否正确组织这些动作则进入技能测试。