Skill: 447992399/llava-vision (version 1.0.1)

--- name: llava-vision-local version: 0.1.0 description: Call a local llama.cpp server with the LLaVA model to analyze images. license: MIT metadata: openclaw: emoji: "🧠" requires: bins: [] os: - linux - darwin - win32 --- # LLaVA Vision Skill > This skill forwards an image to a locally running **llama.cpp** server that hosts a LLaVA model and returns the model’s text description of the image. It accepts either a local file path or a remote image URL. ## Usage ```sh clawhub llava-vision --image /path/to/photo.jpg # or clawhub llava-vision --image https://example.com/photo.jpg ``` The skill uses the built‑in **vision_analyze** tool, which expects an image file path. If the image cannot be read or the server is unreachable, an error message will be returned. ## Dependencies - Node.js (the skill itself) - A local **llama.cpp** server with the LLaVA model exposed at the default endpoint. ## Example ```sh $ clawhub run llava-vision --image ./cat.png The image contains a cat sitting on a windowsill, looking out at a sunny garden. ```

path: index.js
content: 
// Execute LLaVA Vision Skill directly
const { skills } = require('./tool');
const ctx = { tools: skills };
const argv = {};
for (let i = 2; i < process.argv.length; i++) {
  const arg = process.argv[i];
  if (arg.startsWith('--')) {
    const key = arg.slice(2);
    argv[key] = process.argv[i + 1];
    i++;
  }
}
const imagePath = argv.image || argv.file;
if (!imagePath) {
  console.log('⚠️ Please provide an image path using --image <path>');
  process.exit(1);
}
(async () => {
  try {
    const result = await ctx.tools.vision_analyze({ imagePathOrUrl: imagePath });
    console.log('Result:', result);
    if (result && typeof result === 'object') {
      if (result.ok && result.text) console.log(result.text);
      else if (result.output) console.log(result.output);
      else if (result.text) console.log(result.text);
      else console.log(result);
    } else {
      console.log(result);
    }
  } catch (e) {
    console.error(`❌ Error analyzing image: ${e.message}`);
  }
})();


path: tool.js
content: /**
 * LLaVA Vision Skill (OpenClaw Compatible)
 * - calls local llama-server (OpenAI-like API)
 */

const LLAMA_SERVER_URL = "http://127.0.0.1:8081/v1/chat/completions";

/**
 * imageBase64: string (required)
 * prompt: string (optional)
 */
export const skills = {
  async vision_analyze({ imagePathOrUrl, prompt = "Describe this image in detail" }) {
    try {
      const fs = await import("node:fs");
      let imageBase64;
      if (imagePathOrUrl.startsWith("http://") || imagePathOrUrl.startsWith("https://")) {
        const res = await fetch(imagePathOrUrl);
        if (!res.ok) throw new Error(`Failed to fetch image: ${res.statusText}`);
        const buffer = await res.arrayBuffer();
        imageBase64 = Buffer.from(buffer).toString("base64");
      } else {
        const buffer = await fs.promises.readFile(imagePathOrUrl);
        imageBase64 = buffer.toString("base64");
      }
      const payload = {
        model: "llava",
        messages: [
          {
            role: "user",
            content: [
              {
                type: "text",
                text: prompt
              },
              {
                type: "image_url",
                image_url: {
                  url: `data:image/jpeg;base64,${imageBase64}`
                }
              }
            ]
          }
        ],
        temperature: 0.2
      };

      const res = await fetch(LLAMA_SERVER_URL, {
        method: "POST",
        headers: {
          "Content-Type": "application/json"
        },
        body: JSON.stringify(payload)
      });

      if (!res.ok) {
        const err = await res.text();
        return {
          ok: false,
          error: "LLAMA_SERVER_ERROR",
          detail: err
        };
      }

      const data = await res.json();

      const text =
        data?.choices?.[0]?.message?.content ??
        "No response from model";

      return {
        ok: true,
        text
      };
    } catch (e) {
      return {
        ok: false,
        error: "SKILL_RUNTIME_ERROR",
        detail: String(e)
      };
    }
  }
};

path: _meta.json
content: name: test

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