From a9cbf48f4824c2392598b350b85f32c520596aa3 Mon Sep 17 00:00:00 2001 From: tiennm99 Date: Tue, 14 Apr 2026 21:46:33 +0700 Subject: [PATCH] refactor(skills): convert mt-webfetch script to Node.js for project consistency --- .claude/skills/mt-webfetch/SKILL.md | 4 +- .../mt-webfetch/scripts/fetch-via-defuddle.js | 37 +++++++++++++++++++ .claude/skills/mt-webfetch/scripts/fetch.sh | 27 -------------- 3 files changed, 39 insertions(+), 29 deletions(-) create mode 100644 .claude/skills/mt-webfetch/scripts/fetch-via-defuddle.js delete mode 100644 .claude/skills/mt-webfetch/scripts/fetch.sh diff --git a/.claude/skills/mt-webfetch/SKILL.md b/.claude/skills/mt-webfetch/SKILL.md index f590d61..9a9d132 100644 --- a/.claude/skills/mt-webfetch/SKILL.md +++ b/.claude/skills/mt-webfetch/SKILL.md @@ -28,7 +28,7 @@ Use this skill only after a WebFetch attempt returned one of: 1. Confirm WebFetch already failed on the target URL 2. Run the fetch script: ```bash - bash .claude/skills/mt-webfetch/scripts/fetch.sh "" + node .claude/skills/mt-webfetch/scripts/fetch-via-defuddle.js "" ``` Alternatively, use WebFetch with the defuddle-prefixed URL: ``` @@ -70,7 +70,7 @@ Never loop. Never retry more than once. User wanted to extract content from https://example.com/article WebFetch returned: "Request failed with status code 403" → Trigger mt-webfetch -→ bash .claude/skills/mt-webfetch/scripts/fetch.sh "https://example.com/article" +→ node .claude/skills/mt-webfetch/scripts/fetch-via-defuddle.js "https://example.com/article" → Parse markdown output → Summarize as usual ``` diff --git a/.claude/skills/mt-webfetch/scripts/fetch-via-defuddle.js b/.claude/skills/mt-webfetch/scripts/fetch-via-defuddle.js new file mode 100644 index 0000000..2aedff6 --- /dev/null +++ b/.claude/skills/mt-webfetch/scripts/fetch-via-defuddle.js @@ -0,0 +1,37 @@ +#!/usr/bin/env node +// mt-webfetch fallback fetcher via defuddle.md +// Usage: node fetch.js +// Exit codes: 0 = content returned, 1 = empty/failed, 2 = bad args + +const url = process.argv[2]; +if (!url) { + console.error("Usage: node fetch.js "); + process.exit(2); +} + +const defuddleUrl = `https://defuddle.md/${url}`; + +async function main() { + const controller = new AbortController(); + const timeout = setTimeout(() => controller.abort(), 30000); + try { + const res = await fetch(defuddleUrl, { + redirect: "follow", + signal: controller.signal, + headers: { "User-Agent": "mt-webfetch/1.0" }, + }); + clearTimeout(timeout); + const body = await res.text(); + if (!res.ok || !body || body.trim().length === 0) { + console.error(`mt-webfetch: defuddle returned ${res.status} / empty body for ${url}`); + process.exit(1); + } + process.stdout.write(body); + } catch (err) { + clearTimeout(timeout); + console.error(`mt-webfetch: fetch failed for ${url}: ${err.message}`); + process.exit(1); + } +} + +main(); diff --git a/.claude/skills/mt-webfetch/scripts/fetch.sh b/.claude/skills/mt-webfetch/scripts/fetch.sh deleted file mode 100644 index 06741f1..0000000 --- a/.claude/skills/mt-webfetch/scripts/fetch.sh +++ /dev/null @@ -1,27 +0,0 @@ -#!/usr/bin/env bash -# mt-webfetch fallback fetcher via defuddle.md -# Usage: bash fetch.sh -# Exit codes: 0 = content returned, 1 = empty/failed, 2 = bad args - -set -euo pipefail - -URL="${1:-}" -if [[ -z "$URL" ]]; then - echo "Usage: fetch.sh " >&2 - exit 2 -fi - -# defuddle.md expects the target URL appended as path -DEFUDDLE="https://defuddle.md/${URL}" - -# -s silent, -L follow redirects, -f fail on HTTP errors, --max-time 30s -BODY=$(curl -sL --max-time 30 \ - -A "Mozilla/5.0 (compatible; mt-webfetch/1.0)" \ - "$DEFUDDLE" || true) - -if [[ -z "$BODY" ]]; then - echo "mt-webfetch: empty response from defuddle.md for $URL" >&2 - exit 1 -fi - -echo "$BODY"