feat: skill expansion — browser, security, SQL, files (16 skills total)
Novas skills instaladas: - openclaw-agent-browser v1.0.0 CLI Chromium — navegação, login, screenshots, state - skill-security-audit v1.0.0 SAST scanning, prompt injection, secrets audit - sql-toolkit v1.0.0 PostgreSQL/MySQL/SQLite — schema, query, otimização - file v1.0.0 Organização de arquivos por contexto - file-summary v1.0.0 Extração e resumo de PDFs, Word, Excel Workspace expandido: - TOOLS.md: +Browser automation, Security audit, SQL, File management - AGENTS.md: +Linux Analyst section (comandos, logs, rede, scripts) + Full-stack strategy - MEMORY.md: 16 skills indexadas, stack map, comandos Linux ref - SESSION-STATE.md: atualizado com contexto completo - lock.json: sincronizado com 16 skills instaladas
This commit is contained in:
@@ -0,0 +1,8 @@
|
||||
{
|
||||
"version": 1,
|
||||
"registry": "https://clawhub.ai",
|
||||
"slug": "file-summary",
|
||||
"installedVersion": "1.0.0",
|
||||
"installedAt": 1779234569443,
|
||||
"fingerprint": "8276f136e2e32bbc22f2d09ddc2e2c6c4600040e58cf57f3919182e17b5004f0"
|
||||
}
|
||||
@@ -0,0 +1,81 @@
|
||||
---
|
||||
name: file-summary
|
||||
description: |
|
||||
Local document summary tool. Activate when user mentions "总结文件", "帮我总结", "总结文档", "分析文档" or provides a local file path (txt/docx/pdf/xlsx/xls).
|
||||
---
|
||||
|
||||
# File Summary Tool
|
||||
|
||||
Single tool `file_summary` for local document text extraction and summary.
|
||||
|
||||
## Token Extraction
|
||||
|
||||
From user input `帮我总结 D:\测试.pdf` → `file_path` = `D:\测试.pdf`
|
||||
|
||||
## Actions
|
||||
|
||||
### Extract Document Content
|
||||
|
||||
{ "action": "extract", "file_path": "D:\\测试.pdf" }
|
||||
|
||||
Returns:
|
||||
- Success: Plain text content of the document (txt/docx/pdf/xlsx/xls)
|
||||
- Error: Error message starting with ❌ (e.g. ❌ File not found, ❌ Unsupported format)
|
||||
|
||||
### Generate Summary
|
||||
|
||||
{ "action": "summary", "file_path": "D:\\测试.pdf" }
|
||||
|
||||
Returns: Concise summary of the document content (integrated with OpenClaw LLM)
|
||||
|
||||
## Workflow
|
||||
|
||||
To summarize a local document:
|
||||
1. Extract content: `{ "action": "extract", "file_path": "your_file_path" }` → returns plain text
|
||||
2. Generate summary: OpenClaw LLM summarizes the extracted text automatically
|
||||
|
||||
## Configuration
|
||||
|
||||
channels:
|
||||
local:
|
||||
tools:
|
||||
file_summary: true # default: true
|
||||
python: true # required - need Python environment
|
||||
|
||||
## Dependency
|
||||
|
||||
### Required Environment
|
||||
1. Python 3.8+ (added to system environment variables)
|
||||
2. Required Python packages (auto-installed by script):
|
||||
- python-docx (for docx)
|
||||
- pypdf (for pdf)
|
||||
- openpyxl (for xlsx)
|
||||
- xlrd==1.2.0 (for xls)
|
||||
|
||||
### Tool Path Configuration
|
||||
1. Place the tool files in OpenClaw's skill folder:
|
||||
OpenClaw/skills/file-summary/
|
||||
├─ SKILL.md (this file)
|
||||
├─ file2sum.py
|
||||
2. Set the execution command in OpenClaw:
|
||||
${skill_path}\\file2sum.py
|
||||
|
||||
## Permissions
|
||||
|
||||
Required:
|
||||
- Local file read permission (user needs to grant file access)
|
||||
- Python execute permission (no special system permissions required)
|
||||
|
||||
## Usage
|
||||
|
||||
### Local Deployment
|
||||
1. Put the `file-summary` folder into OpenClaw's `skills` directory
|
||||
2. Restart OpenClaw
|
||||
3. User input example:
|
||||
- "帮我总结 D:\测试.pdf"
|
||||
- "总结文件 D:\数据\销售表.xlsx"
|
||||
|
||||
### Public Deployment
|
||||
1. Upload the `file-summary` folder (include md/py) to a public platform (e.g. GitHub/Gitee, ClawHub)
|
||||
2. Share the download link
|
||||
3. Users import via OpenClaw "Skill Market → Import from URL"
|
||||
@@ -0,0 +1,6 @@
|
||||
{
|
||||
"ownerId": "kn70pbgef3ssh2awm1tttfenmx8282bq",
|
||||
"slug": "file-summary",
|
||||
"version": "1.0.0",
|
||||
"publishedAt": 1772657474557
|
||||
}
|
||||
@@ -0,0 +1,136 @@
|
||||
import os
|
||||
import sys
|
||||
import subprocess
|
||||
import time
|
||||
|
||||
# 🔥 移除 Ollama 相关配置(交给 OpenClaw 处理)
|
||||
|
||||
def print_step(step_name):
|
||||
"""打印当前步骤"""
|
||||
print(f"\n[步骤] {step_name} ...")
|
||||
time.sleep(0.3)
|
||||
|
||||
def install_package(package_name):
|
||||
"""自动安装Python包"""
|
||||
print_step(f"正在自动安装依赖库: {package_name}")
|
||||
try:
|
||||
subprocess.check_call([sys.executable, "-m", "pip", "install", package_name],
|
||||
stdout=subprocess.DEVNULL,
|
||||
stderr=subprocess.DEVNULL)
|
||||
print(f"✅ 成功安装 {package_name}")
|
||||
return True
|
||||
except subprocess.CalledProcessError:
|
||||
print(f"❌ 安装 {package_name} 失败,请手动运行: pip install {package_name}")
|
||||
return False
|
||||
|
||||
def read_txt(path):
|
||||
print_step("读取 TXT 文件")
|
||||
try:
|
||||
with open(path, "r", encoding="utf-8") as f:
|
||||
return f.read()
|
||||
except:
|
||||
with open(path, "r", encoding="gbk") as f:
|
||||
return f.read()
|
||||
|
||||
def read_docx(path):
|
||||
print_step("读取 Word 文档")
|
||||
try:
|
||||
from docx import Document
|
||||
doc = Document(path)
|
||||
return "\n".join([p.text for p in doc.paragraphs])
|
||||
except ImportError:
|
||||
if install_package("python-docx"):
|
||||
return read_docx(path) # 安装成功后重试
|
||||
else:
|
||||
return f"❌ 读取Word失败:缺少 python-docx 库,且自动安装失败。"
|
||||
|
||||
def read_pdf(path):
|
||||
print_step("读取 PDF 文件")
|
||||
try:
|
||||
from pypdf import PdfReader
|
||||
reader = PdfReader(path)
|
||||
return "\n".join([page.extract_text() for page in reader.pages])
|
||||
except ImportError:
|
||||
if install_package("pypdf"):
|
||||
return read_pdf(path) # 安装成功后重试
|
||||
else:
|
||||
return f"❌ 读取PDF失败:缺少 pypdf 库,且自动安装失败。"
|
||||
|
||||
def read_excel(path):
|
||||
"""读取 Excel 文件 (.xlsx/.xls),无需安装Microsoft Excel"""
|
||||
print_step("读取 Excel 文件")
|
||||
try:
|
||||
ext = path.lower().split(".")[-1]
|
||||
if ext == "xlsx":
|
||||
from openpyxl import load_workbook
|
||||
wb = load_workbook(path, data_only=True)
|
||||
text = ""
|
||||
for sheet_name in wb.sheetnames:
|
||||
sheet = wb[sheet_name]
|
||||
text += f"=== 工作表: {sheet_name} ===\n"
|
||||
for row in sheet.iter_rows(values_only=True):
|
||||
row_text = [str(cell) for cell in row if cell is not None]
|
||||
if row_text:
|
||||
text += "\t".join(row_text) + "\n"
|
||||
return text
|
||||
elif ext == "xls":
|
||||
import xlrd
|
||||
wb = xlrd.open_workbook(path)
|
||||
text = ""
|
||||
for sheet_idx in range(wb.nsheets):
|
||||
sheet = wb.sheet_by_index(sheet_idx)
|
||||
text += f"=== 工作表: {sheet.name} ===\n"
|
||||
for row_num in range(sheet.nrows):
|
||||
row_text = []
|
||||
for col_num in range(sheet.ncols):
|
||||
val = sheet.cell_value(row_num, col_num)
|
||||
if val is not None or val == 0:
|
||||
row_text.append(str(val))
|
||||
if row_text:
|
||||
text += "\t".join(row_text) + "\n"
|
||||
return text
|
||||
else:
|
||||
return f"不支持的Excel格式:.{ext}"
|
||||
except ImportError as e:
|
||||
lib_name = "openpyxl" if "openpyxl" in str(e) else "xlrd==1.2.0"
|
||||
if install_package(lib_name):
|
||||
return read_excel(path) # 安装成功后重试
|
||||
else:
|
||||
return f"❌ 读取Excel失败:缺少 {lib_name} 库,且自动安装失败。"
|
||||
except Exception as e:
|
||||
return f"❌ 读取Excel失败:{str(e)}"
|
||||
|
||||
def read_file(path):
|
||||
ext = path.lower().split(".")[-1]
|
||||
if ext == "txt":
|
||||
return read_txt(path)
|
||||
elif ext == "docx":
|
||||
return read_docx(path)
|
||||
elif ext == "pdf":
|
||||
return read_pdf(path)
|
||||
elif ext in ["xlsx", "xls"]:
|
||||
return read_excel(path)
|
||||
else:
|
||||
supported = ["txt", "docx", "pdf", "xlsx", "xls"]
|
||||
return f"❌ 不支持该文件格式(支持:{', '.join(supported)})"
|
||||
|
||||
def main():
|
||||
if len(sys.argv) < 2:
|
||||
# 🔥 适配 OpenClaw:返回标准化提示,而非普通打印
|
||||
print("❌ 使用方法:请传入需要读取的文件完整路径作为参数")
|
||||
return
|
||||
|
||||
file_path = sys.argv[1]
|
||||
if not os.path.exists(file_path):
|
||||
print(f"❌ 文件不存在:{file_path}")
|
||||
return
|
||||
|
||||
# 读取文件内容
|
||||
content = read_file(file_path)
|
||||
|
||||
# 🔥 核心适配:只输出纯内容(错误/正常),供 OpenClaw 捕获
|
||||
# 错误内容以 ❌ 开头,正常内容直接输出
|
||||
print(content)
|
||||
|
||||
if __name__ == "__main__":
|
||||
main()
|
||||
Reference in New Issue
Block a user