Skip to content
Closed
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
11 changes: 11 additions & 0 deletions .github/workflows/ci.yml
Original file line number Diff line number Diff line change
Expand Up @@ -26,6 +26,17 @@ jobs:
- name: TypeScript typecheck
run: bun run typecheck

- name: Set up Python
uses: actions/setup-python@v5
with:
python-version: '3.12'

- name: Install skills-ref (required by bun run validate for tier-1 spec checks)
run: |
pip install click strictyaml
echo "skills-ref==0.1.1 --hash=sha256:d35db5bb8de71ae301daf5ca9cb71f8a555e8c6f83a6d40e46a5bc09f8f461b5" > /tmp/skills-ref-req.txt
pip install --no-deps --require-hashes -r /tmp/skills-ref-req.txt

- name: Validate skill frontmatter
run: bun run validate

Expand Down
7 changes: 5 additions & 2 deletions aibtc-news/aibtc-news.ts
Original file line number Diff line number Diff line change
Expand Up @@ -354,13 +354,14 @@ program

const body: Record<string, unknown> = {
beat_slug: opts.beatId,
btc_address: headers["X-BTC-Address"],
content: opts.content,
};

if (opts.headline) body.headline = opts.headline;
if (sources.length > 0) body.sources = sources;
if (tags.length > 0) body.tags = tags;
if (disclosure !== undefined) body.disclosure = disclosure;
if (disclosure !== undefined) body.disclosure = typeof disclosure === "string" ? disclosure : JSON.stringify(disclosure);

// Step 1: POST with auth headers — may return 200 (free) or 402 (x402 payment required)
const signalsUrl = `${NEWS_API_BASE}/signals`;
Expand Down Expand Up @@ -413,7 +414,7 @@ program
const { getStacksNetwork } = await import("../src/lib/config/networks.js");
const { createFungiblePostCondition } = await import("../src/lib/transactions/post-conditions.js");
const { getHiroApi } = await import("../src/lib/services/hiro-api.js");
const { getAccount } = await import("../src/lib/services/wallet-manager.js");
const { getAccount } = await import("../src/lib/services/x402.service.js");

const paymentRequired = decodePaymentRequired(paymentHeader);
if (!paymentRequired?.accepts?.length) {
Expand Down Expand Up @@ -645,6 +646,8 @@ program

const body: Record<string, unknown> = {
beat_slug: opts.beatId,
slug: opts.beatId,
created_by: headers["X-BTC-Address"],
};

if (opts.name) body.name = opts.name;
Expand Down
2 changes: 1 addition & 1 deletion package.json
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,7 @@
"description": "Claude Code skills for Bitcoin/Stacks blockchain operations — flat SKILL.md + colocated TypeScript CLI scripts.",
"type": "module",
"scripts": {
"build": "bun build src/lib/index.ts --outdir dist",
"build": "bun build src/lib/index.ts --outdir dist --target bun",
"typecheck": "tsc --noEmit",
"manifest": "bun run scripts/generate-manifest.ts",
"validate": "bun run scripts/validate-frontmatter.ts",
Expand Down
13 changes: 7 additions & 6 deletions scripts/validate-frontmatter.ts
Original file line number Diff line number Diff line change
Expand Up @@ -10,18 +10,19 @@ const repoRoot = dirname(scriptsDir);
// CLI flags
const skipSpec = process.argv.includes("--skip-spec");

// Find the skills-ref binary: prefer local venv, fall back to PATH
// Find the agentskills binary: prefer local venv, fall back to PATH
// Note: skills-ref PyPI package >= 0.1.1 installs the CLI as `agentskills` (renamed from `skills-ref`)
async function findSkillsRef(): Promise<string | null> {
const localBin = join(repoRoot, ".venv-skills-ref/bin/skills-ref");
const localBin = join(repoRoot, ".venv-skills-ref/bin/agentskills");
try {
const stat = await Bun.file(localBin).stat();
if (stat.size > 0) return localBin;
} catch {
// not found locally
}
// Fall back to PATH (cross-platform)
const pathResult = Bun.which("skills-ref");
if (pathResult) return "skills-ref";
const pathResult = Bun.which("agentskills");
if (pathResult) return "agentskills";
return null;
}

Expand Down Expand Up @@ -145,15 +146,15 @@ if (!skipSpec) {
skillsRefBin = await findSkillsRef();
if (skillsRefBin === null) {
process.stderr.write(
"WARNING: skills-ref not found. Skipping tier-1 spec validation. Install with: pip install skills-ref\n"
"WARNING: agentskills not found. Skipping tier-1 spec validation. Install with: pip install skills-ref\n"
);
}
}

// Print active tiers
const tier1Active = !skipSpec && skillsRefBin !== null;
console.log(
`Validation tiers: ${tier1Active ? "[tier-1: skills-ref]" : "[tier-1: SKIPPED]"} [tier-2: Zod]`
`Validation tiers: ${tier1Active ? "[tier-1: agentskills]" : "[tier-1: SKIPPED]"} [tier-2: Zod]`
);
console.log("");

Expand Down
Loading