Skill: hzheigege/math-arithmetic-orc (version 1.0.0)

--- name: math-arithmetic-ocr description: | 识别图片中的K12算式（加减乘除、竖式计算、分数、方程等），返回结构化文本结果。 支持手写体和印刷体，可拒绝非算式图片。 触发条件：用户要求识别算式、数学题、计算题图片，或上传数学题图片时调用。 关键词：算式识别、数学题、OCR、竖式计算、ArithmeticOCR --- # 数学算式识别技能 使用腾讯云 ArithmeticOCR API，精准识别图片中的数学算式，返回识别出的文本内容和结构化信息。 ## 使用场景 ✅ **适用：** - 用户上传数学题图片（如竖式计算、分数方程、四则运算） - 用户说“识别这张图里的算式”、“帮我读出这道数学题” - 需要将手写或印刷的数学题转为可编辑文本 ❌ **不适用：** - 识别普通文档文字（请用通用OCR） - 识别非数学内容的图片（风景、人物等，除非开启拒绝模式） ## 执行流程 ### 1. 获取图片 从用户输入中获取图片： - 优先使用 `imageBase64` 参数（图片的 Base64 编码） - 其次使用 `imageUrl` 参数（图片的 URL 地址） ### 2. 调用腾讯云 API 使用 Node.js 脚本 `index.js` 调用腾讯云 `ArithmeticOCR` 接口，传入： - 图片数据 - 可选参数：`rejectNonArithmetic`（是否拒绝非算式图） - 可选参数：`enableDispMidResult`（是否显示竖式中间结果） ### 3. 处理返回结果 API 返回包含以下信息： - `TextDetections`：识别的文本区域列表（每个区域包含文本内容、置信度、位置坐标） - `Angle`：图片旋转角度 - `RequestId`：请求ID ### 4. 向用户返回结果 - 如果成功：返回所有识别出的文本（拼接成一句）和详细检测信息 - 如果失败：返回错误信息（如“图片中未检测到文本”、“API调用失败”等） ## 权限要求 此技能需要以下权限： - `network.request`：访问腾讯云 API - `file.read`：如果用户提供本地图片路径（需先读取文件） ## 配置说明 使用前需要在 OpenClaw 中配置腾讯云密钥： **方式一：环境变量** - TENCENTCLOUD_SECRET_ID=你的SecretId - TENCENTCLOUD_SECRET_KEY=你的SecretKey **方式二：OpenClaw 配置** - openclaw config set tencentcloud.secretId "你的SecretId" - openclaw config set tencentcloud.secretKey "你的SecretKey"

path: index.js
content: const axios = require('axios');
const crypto = require('crypto');

/**
 * 腾讯云 API v3 签名计算
 * @param {string} secretId - 腾讯云 SecretId
 * @param {string} secretKey - 腾讯云 SecretKey
 * @param {string} service - 服务名，固定为 "ocr"
 * @param {string} action - API 动作，固定为 "ArithmeticOCR"
 * @param {string} version - API 版本，固定为 "2018-11-19"
 * @param {string} region - 地域，可选 "ap-guangzhou"
 * @param {string} timestamp - 当前时间戳（秒）
 * @param {string} body - 请求体 JSON 字符串
 * @returns {string} Authorization 头
 */
function signV3(secretId, secretKey, service, action, version, region, timestamp, body) {
  const date = new Date(timestamp * 1000).toISOString().slice(0, 10).replace(/-/g, '');
  
  // 1. 拼接 CanonicalRequest
  const canonicalRequest = [
    'POST',
    '/',
    '',
    'content-type:application/json',
    'host:ocr.tencentcloudapi.com',
    '',
    'content-type;host',
    crypto.createHash('sha256').update(body).digest('hex')
  ].join('\n');

  // 2. 拼接待签名字符串
  const credentialScope = `${date}/${service}/tc3_request`;
  const hashedCanonicalRequest = crypto.createHash('sha256').update(canonicalRequest).digest('hex');
  const stringToSign = [
    'TC3-HMAC-SHA256',
    timestamp,
    credentialScope,
    hashedCanonicalRequest
  ].join('\n');

  // 3. 计算签名
  const secretDate = crypto.createHmac('sha256', 'TC3' + secretKey).update(date).digest();
  const secretService = crypto.createHmac('sha256', secretDate).update(service).digest();
  const secretSigning = crypto.createHmac('sha256', secretService).update('tc3_request').digest();
  const signature = crypto.createHmac('sha256', secretSigning).update(stringToSign).digest('hex');

  // 4. 拼接 Authorization
  return `TC3-HMAC-SHA256 Credential=${secretId}/${credentialScope}, SignedHeaders=content-type;host, Signature=${signature}`;
}

/**
 * 调用腾讯云 ArithmeticOCR API
 * @param {Object} params - 输入参数
 * @param {string} params.secretId - 腾讯云 SecretId
 * @param {string} params.secretKey - 腾讯云 SecretKey
 * @param {string} params.imageBase64 - 图片 Base64（可选）
 * @param {string} params.imageUrl - 图片 URL（可选）
 * @param {boolean} params.rejectNonArithmetic - 是否拒绝非算式图
 * @param {boolean} params.enableDispMidResult - 是否显示竖式中间结果
 * @returns {Promise<Object>} API 返回结果
 */
async function callArithmeticOCR(params) {
  const {
    secretId,
    secretKey,
    imageBase64,
    imageUrl,
    rejectNonArithmetic = false,
    enableDispMidResult = false
  } = params;

  if (!secretId || !secretKey) {
    throw new Error('请配置腾讯云 SecretId 和 SecretKey');
  }

  if (!imageBase64 && !imageUrl) {
    throw new Error('必须提供 imageBase64 或 imageUrl');
  }

  const timestamp = Math.floor(Date.now() / 1000);
  const service = 'ocr';
  const action = 'ArithmeticOCR';
  const version = '2018-11-19';
  const region = 'ap-guangzhou';

  // 构建请求体
  const payload = {
    ImageBase64: imageBase64,
    ImageUrl: imageUrl,
    RejectNonArithmeticPic: rejectNonArithmetic,
    EnableDispMidResult: enableDispMidResult
  };

  // 移除 undefined 字段
  Object.keys(payload).forEach(key => payload[key] === undefined && delete payload[key]);

  const body = JSON.stringify(payload);
  const authorization = signV3(secretId, secretKey, service, action, version, region, timestamp, body);

  try {
    const response = await axios({
      method: 'POST',
      url: 'https://ocr.tencentcloudapi.com',
      headers: {
        'Authorization': authorization,
        'Content-Type': 'application/json',
        'Host': 'ocr.tencentcloudapi.com',
        'X-TC-Action': action,
        'X-TC-Version': version,
        'X-TC-Timestamp': timestamp,
        'X-TC-Region': region,
        'X-TC-RequestClient': 'OpenClaw-Skill'
      },
      data: body,
      timeout: 10000
    });

    return response.data;
  } catch (error) {
    if (error.response) {
      throw new Error(`API 调用失败: ${JSON.stringify(error.response.data)}`);
    }
    throw error;
  }
}

/**
 * Skill 核心执行函数
 */
export default async function run(action, params) {
  try {
    if (action !== 'recognize-arithmetic') {
      return {
        success: false,
        message: `不支持的动作：${action}`,
        data: null
      };
    }

    // 从配置中读取腾讯云密钥（需要在 OpenClaw 配置中设置）
    const secretId = process.env.TENCENTCLOUD_SECRET_ID || params.secretId;
    const secretKey = process.env.TENCENTCLOUD_SECRET_KEY || params.secretKey;

    const {
      imageBase64,
      imageUrl,
      rejectNonArithmetic,
      enableDispMidResult
    } = params;

    // 调用 API
    const result = await callArithmeticOCR({
      secretId,
      secretKey,
      imageBase64,
      imageUrl,
      rejectNonArithmetic,
      enableDispMidResult
    });

    // 检查 API 返回是否有错误
    if (result.Response?.Error) {
      return {
        success: false,
        message: `腾讯云 API 错误: ${result.Response.Error.Message} (Code: ${result.Response.Error.Code})`,
        data: result.Response
      };
    }

    // 提取识别结果
    const textDetections = result.Response?.TextDetections || [];
    
    // 格式化输出，便于 AI 理解
    const formattedResults = textDetections.map(item => ({
      text: item.DetectedText,
      confidence: item.Confidence,
      polygon: item.Polygon,
      advancedInfo: item.AdvancedInfo ? JSON.parse(item.AdvancedInfo) : null
    }));

    // 提取所有识别出的文本（用于快速查看）
    const allText = textDetections.map(t => t.DetectedText).join(' ');

    return {
      success: true,
      message: `成功识别算式，共检测到 ${textDetections.length} 个文本区域`,
      data: {
        raw: result.Response,
        textDetections: formattedResults,
        allText: allText,
        angle: result.Response?.Angle || 0,
        requestId: result.Response?.RequestId
      }
    };

  } catch (error) {
    return {
      success: false,
      message: `执行失败：${error.message}`,
      data: null
    };
  }
}


path: plugin.json
content: {
  "name": "math-arithmetic-ocr",
  "version": "1.0.0",
  "description": "识别图片中的K12算式（加减乘除、竖式、分数、方程等），返回结构化结果",
  "author": "Your Name",
  "skills": [
    {
      "action": "recognize-arithmetic",
      "description": "识别算式图片，返回文本检测结果和结构化信息",
      "parameters": [
        {
          "name": "imageBase64",
          "type": "string",
          "required": false,
          "description": "图片的 Base64 编码（不含 data:image/xxx;base64, 前缀）"
        },
        {
          "name": "imageUrl",
          "type": "string",
          "required": false,
          "description": "图片的 URL 地址（优先使用，如果同时提供 imageBase64 则忽略此项）"
        },
        {
          "name": "rejectNonArithmetic",
          "type": "boolean",
          "required": false,
          "default": false,
          "description": "是否拒绝非算式图片（设为 true 时，风景人物等非算式图会返回错误）"
        },
        {
          "name": "enableDispMidResult",
          "type": "boolean",
          "required": false,
          "default": false,
          "description": "是否展示竖式算式的中间结果和格式控制字符"
        }
      ],
      "permissions": [
        "network.request"      // 需要访问腾讯云 API
      ]
    }
  ]
}



path: package.json
content: {
  "name": "math-arithmetic-ocr",
  "version": "1.0.0",
  "description": "腾讯云算式识别 Skill for OpenClaw",
  "main": "index.js",
  "dependencies": {
    "axios": "^1.6.0"
  },
  "author": "yuejian chen",
  "license": "MIT"
}



Security scan verdicts — ClawScan: clean | static analysis: suspicious | VirusTotal: clean | SkillSpector: suspicious (HIGH)