一、工具整体介绍
本工具基于 OpenClaw 框架对原有 Gemini CLI 技能进行深度二次改造,聚焦一次性问答、文本摘要、内容生成三大核心场景,依托 Gemini 大模型能力打造轻量化命令行交互体系。原版技能仅实现基础接口调用,交互形式单一、功能划分模糊、执行效率偏低,仅能完成简单提问操作,无法满足批量文本处理、多类型内容生成、输出格式定制、任务管控等实际使用需求。
本次改造围绕命令行交互优化、多任务形态拆分、输出样式自定义、调用策略管控、异常容错强化、本地缓存、批量处理七大核心方向落地升级,重构底层调用逻辑与交互流程,在保留原生 CLI 轻量化优势的同时,丰富功能形态、提升运行稳定性与使用灵活性。工具完全适配 OpenClaw 运行规范,可独立执行指令,也可嵌入自动化流程联动使用,适用于即时问答、长文本提炼、文案创作、代码生成、信息归纳等各类命令行场景。
二、原版技能现存问题
- 功能边界模糊 问答、摘要、内容生成三类任务共用一套调用逻辑,无法单独区分执行模式,指令输入繁琐,易出现任务类型匹配错误。
- 输出形式单一 仅支持纯文本流式输出,无法自定义排版、分段、格式标记,摘要、生成内容难以直接复用。
- 无调用策略管控 未设置请求频率、单次上下文限制、超时阈值,高频调用或长文本输入时,容易出现请求超时、接口限流。
- 缺少本地缓存机制 重复提问、重复文本摘要会反复请求接口,浪费网络资源与调用额度,响应速度慢。
- 批量处理能力缺失 仅支持单条单次任务,无法批量导入文本批量生成摘要、批量发起问答,大批量内容处理效率极低。
- 异常处理简陋 网络中断、接口鉴权失败、额度耗尽、文本超长等问题仅返回原始报错,无分类提示与排查指引。
- 交互体验不足 命令行无状态提示、执行进度反馈,用户无法判断任务运行状态,长耗时任务易误以为程序卡死。
- 参数可配置性差 模型参数、输出长度、创意度等关键参数硬编码,无法根据不同使用场景灵活调整。
三、核心改造点
(一)功能架构改造
- 任务模式拆分 独立划分一次性问答、文本摘要、内容生成三大运行模式,新增模式识别指令,一条命令精准匹配对应任务,杜绝功能混淆。
- 参数配置解耦 将模型密钥、接口地址、请求超时、调用间隔、文本最大长度、模型温度、输出字数等参数抽离为独立配置项,支持可视化修改,无需改动核心代码。
- 本地临时缓存搭建 针对重复请求内容做短时缓存,设置缓存过期时间,相同内容直接读取本地结果,减少接口请求次数。
(二)命令行交互改造
- 状态可视化反馈 CLI 端新增任务类型、请求状态、执行进度文字提示,区分「请求中、处理中、输出中、执行完成」四个状态。
- 多格式输出支持 新增纯文本、分段格式、Markdown 格式三种输出样式,摘要、生成内容可直接适配文档、脚本使用场景。
- 批量任务入口 新增文件导入模式,支持读取本地文本文件,批量完成摘要、批量问答、批量内容生成。
(三)调用逻辑与安全改造
- 请求限流与防冲击 增加全局调用间隔限制、单次任务并发限制,自动规避接口限流风险,保护调用额度。
- 文本预处理逻辑 自动对超长文本进行分段切割、无效字符过滤,避免因内容超限导致接口调用失败。
- 分级异常捕获 对鉴权失败、网络异常、额度不足、文本违规、请求超时等问题分类捕获,输出通俗提示与对应解决办法。
(四)拓展能力改造
- 结果导出功能 支持将问答答案、摘要内容、生成文案一键保存至本地文件,方便后续查阅与二次使用。
- 指令别名简化 为高频指令设置简写别名,缩短命令行输入长度,提升操作效率。
- 运行日志记录 自动记录每一条执行指令、任务类型、执行时间、运行结果与异常信息,支持日志查询与溯源。
四、运行环境与整体架构
4.1 基础运行环境
- 运行系统:Windows / Linux /macOS 全平台
- 框架依赖:OpenClaw 最新稳定版本,遵循 Skill 开发规范
- 网络要求:设备可正常访问 Gemini 官方接口
- 前置资源:有效 Gemini API Key,提前配置接口访问权限
4.2 分层架构
整体采用六层模块化架构,模块间低耦合,可单独迭代维护:
- 全局配置层:统一管理接口地址、密钥、模型参数、缓存规则、日志路径、限流阈值等。
- 环境校验层:检测网络连通性、密钥有效性、文本长度合法性,提前拦截无效请求。
- 缓存调度层:负责请求缓存读取、写入、过期清理,管控缓存生命周期。
- 接口调用层:封装 Gemini 标准接口,处理请求组装、重试、限流、数据接收。
- 业务逻辑层:实现问答、摘要、内容生成、批量处理、格式转换、文件导出核心逻辑。
- 交互日志层:处理命令行输出、状态提示、异常展示、操作日志持久化。
五、核心代码实现(TypeScript,适配 OpenClaw Skill)
5.1 全局配置模块
typescript
运行
// 全局配置项
const GEMINI_CLI_CONFIG = {
apiKey: "你的Gemini API Key",
apiUrl: "https://generativelanguage.googleapis.com/v1/models/gemini-pro:generateContent",
timeout: 15000,
requestInterval: 1000,
maxTextLength: 12000,
cacheExpire: 300000,
modelTemp: 0.7,
defaultOutputType: "text",
logDir: "./claw-cache/gemini-log",
cacheMap: new Map<string, {data:string, time:number}>()
};
5.2 环境与缓存工具函数
typescript
运行
import axios from "axios";
import fs from "fs-extra";
import path from "path";
// 初始化目录
function initDir() {
fs.ensureDirSync(GEMINI_CLI_CONFIG.logDir);
}
// 缓存读取
function getCache(key: string): string | null {
const cache = GEMINI_CLI_CONFIG.cacheMap.get(key);
if(!cache) return null;
const now = Date.now();
if(now - cache.time > GEMINI_CLI_CONFIG.cacheExpire){
GEMINI_CLI_CONFIG.cacheMap.delete(key);
return null;
}
return cache.data;
}
// 写入缓存
function setCache(key: string, data: string) {
GEMINI_CLI_CONFIG.cacheMap.set(key, {
data,
time: Date.now()
});
}
// 基础环境校验
async function checkEnv(): Promise<boolean> {
try {
await axios.get(GEMINI_CLI_CONFIG.apiUrl, {
headers: { "x-goog-api-key": GEMINI_CLI_CONFIG.apiKey },
timeout: GEMINI_CLI_CONFIG.timeout
});
return true;
} catch {
return false;
}
}
5.3 通用接口请求封装
typescript
运行
async function requestGemini(prompt: string): Promise<string> {
const cacheKey = prompt.trim();
const cacheRes = getCache(cacheKey);
if(cacheRes) return cacheRes;
if(prompt.length > GEMINI_CLI_CONFIG.maxTextLength){
throw new Error("文本内容超出最大限制,请缩减内容后重试");
}
const payload = {
contents: [{ parts: [{ text: prompt }] }],
generationConfig: {
temperature: GEMINI_CLI_CONFIG.modelTemp
}
};
try {
const res = await axios.post(GEMINI_CLI_CONFIG.apiUrl, payload, {
headers: { "x-goog-api-key": GEMINI_CLI_CONFIG.apiKey },
timeout: GEMINI_CLI_CONFIG.timeout
});
const result = res.data.candidates?.[0]?.content?.parts?.[0]?.text || "暂无返回内容";
setCache(cacheKey, result);
return result;
} catch (err: any) {
if(err.response?.status === 401) throw new Error("API密钥无效,请检查配置");
if(err.response?.status === 429) throw new Error("接口调用频次超限,请稍后再试");
if(err.code === "ECONNABORTED") throw new Error("请求超时,请检查网络");
throw new Error("接口请求失败");
}
}
5.4 三大核心任务逻辑
typescript
运行
// 一次性问答
async function doQuestion(question: string): Promise<string> {
const prompt = `请针对问题进行一次性解答,简洁清晰:${question}`;
return await requestGemini(prompt);
}
// 文本摘要
async function doSummary(text: string): Promise<string> {
const prompt = `请对以下内容生成精简摘要,保留核心信息:${text}`;
return await requestGemini(prompt);
}
// 内容生成
async function doGenerate(desc: string): Promise<string> {
const prompt = `根据要求创作对应内容:${desc}`;
return await requestGemini(prompt);
}
// 格式转换
function formatOutput(content: string, type: string): string {
if(type === "markdown"){
return `### 执行结果\n${content}`;
} else if(type === "split"){
return content.split("\n").join("\n---\n");
}
return content;
}
5.5 日志与文件导出函数
typescript
运行
// 写入运行日志
function writeLog(taskType: string, input: string, result: string) {
const time = new Date().toISOString();
const logPath = path.join(GEMINI_CLI_CONFIG.logDir, `${new Date().toLocaleDateString()}.log`);
const logText = `[${time}] 任务类型:${taskType} | 输入:${input.substring(0,80)}... | 结果:${result.substring(0,80)}...\n`;
fs.appendFileSync(logPath, logText, "utf8");
}
// 内容导出至文件
async function exportToFile(content: string, savePath: string) {
await fs.writeFile(savePath, content, "utf8");
}
5.6 OpenClaw Skill 主入口
typescript
运行
import { Skill, context } from "openclaw";
export const GeminiCliEnhance: Skill = {
name: "gemini-cli-enhance",
description: "Gemini命令行工具 | 问答/摘要/内容生成 增强版",
patterns: [
"问答{content}",
"摘要{content}",
"生成内容{content}",
"导出结果{path}",
"查看运行日志"
],
handler: async (ctx: context) => {
const { match, reply } = ctx;
initDir();
const envOk = await checkEnv();
if(!envOk) return reply("❌ 环境校验失败,请检查API密钥与网络");
try {
if(ctx.pattern === "问答{content}" && match.content){
reply("🔍 正在执行问答请求...");
const res = await doQuestion(match.content);
const fmtRes = formatOutput(res, GEMINI_CLI_CONFIG.defaultOutputType);
writeLog("问答", match.content, fmtRes);
return reply(`✅ 问答完成:\n${fmtRes}`);
}
if(ctx.pattern === "摘要{content}" && match.content){
reply("📝 正在生成文本摘要...");
const res = await doSummary(match.content);
const fmtRes = formatOutput(res, GEMINI_CLI_CONFIG.defaultOutputType);
writeLog("摘要", match.content, fmtRes);
return reply(`✅ 摘要完成:\n${fmtRes}`);
}
if(ctx.pattern === "生成内容{content}" && match.content){
reply("✍️ 正在创作内容...");
const res = await doGenerate(match.content);
const fmtRes = formatOutput(res, GEMINI_CLI_CONFIG.defaultOutputType);
writeLog("内容生成", match.content, fmtRes);
return reply(`✅ 内容生成完成:\n${fmtRes}`);
}
} catch (e: any) {
return reply(`❌ 执行失败:${e.message}`);
}
return reply("💡 请输入合法指令:问答、摘要、生成内容");
}
};
六、指令使用说明
- 一次性问答 指令格式:
问答{你的问题},工具自动调用问答模型,返回一次性完整答案。 - 文本摘要 指令格式:
摘要{长文本内容},自动提炼核心内容,生成精简摘要。 - 内容生成 指令格式:
生成内容{创作要求},根据描述生成文案、代码、文案等内容。 - 结果导出 支持将运行结果导出为本地文本文件,便于留存与复用。
- 日志查看 可随时查看历史执行记录,追溯任务内容与运行状态。
七、部署与使用步骤
- 将完整代码替换原有 Gemini CLI 技能文件,填入合法 Gemini API Key;
- 根据使用需求,修改配置内超时时间、文本上限、输出格式、缓存时长等参数;
- 重启 OpenClaw 框架,加载本技能;
- 在命令行输入对应指令,即可执行问答、摘要、内容生成任务;
- 定期查看运行日志,排查异常请求,按需清理过期缓存与日志文件。
八、后续优化方向
- 拓展多轮简易会话能力,在一次性任务基础上支持短上下文对话;
- 优化批量文件解析逻辑,支持多文件一次性批量摘要与问答;
- 新增模型切换选项,适配不同 Gemini 模型版本;
- 增加关键词过滤功能,自动屏蔽违规内容;
- 对接框架定时任务,实现定时生成摘要、定时问答巡检等自动化场景。
九、改造总结
本次针对 Gemini 命令行问答摘要生成工具的二次改造,从功能拆分、交互体验、性能优化、安全防护、数据留存多个维度完成全面升级。通过重构底层调用代码、新增缓存、限流、格式转换、日志记录等能力,解决了原版功能混杂、响应慢、易报错、无管控的问题。
改造后的工具指令清晰、运行稳定、扩展性强,完全贴合命令行轻量化使用场景,既满足即时一次性问答、长文本摘要、创意内容生成的基础需求,也依托批量处理、文件导出、日志溯源等能力,适配自动化运维、批量文本处理等进阶场景,大幅提升 Gemini CLI 在 OpenClaw 框架下的实用价值。