Skip to content
Merged
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
39 changes: 39 additions & 0 deletions .github/workflows/update-ai.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1,39 @@
name: Update AI indexes

on:
schedule:
- cron: "30 8 1 * *"
workflow_dispatch:

permissions:
contents: write
pull-requests: write

jobs:
update-subnets:
runs-on: ubuntu-latest
steps:
- name: Checkout
uses: actions/checkout@v4

- name: Prepare
uses: ./.github/actions/prepare

- name: Update
run: npm run docs:ai

- name: Check for Changes
run: |
if ! git diff --quiet; then
echo "CHANGES_DETECTED=true" >> $GITHUB_ENV
fi

# This action creates a PR only if there are changes.
- name: Create Pull Request
if: env.CHANGES_DETECTED == 'true'
uses: ./.github/actions/create-pr
with:
branch: bot-cli-docs-update
title: "docs: Update AI indexes"
body: |
Modifications have been made to the AI skills.
1 change: 1 addition & 0 deletions package.json
Original file line number Diff line number Diff line change
Expand Up @@ -16,6 +16,7 @@
"dev": "npm run start",
"start": "docusaurus start",
"build": "docusaurus build",
"docs:ai": "./scripts/ai.mjs && npm run format",
"docs:cli": "scripts/cli-to-md.sh",
"docs:subnets": "./scripts/subnets.mjs && npm run format",
"swizzle": "docusaurus swizzle",
Expand Down
63 changes: 63 additions & 0 deletions scripts/ai.mjs
Original file line number Diff line number Diff line change
@@ -0,0 +1,63 @@
#!/usr/bin/env node

import { mkdir, writeFile } from "node:fs/promises";
import { join } from "node:path";

// Generate /.well-known/agent-skills/index.json for AI discovery as defined by Cloudflare
// @see https://github.com/cloudflare/agent-skills-discovery-rfc
// @see https://isitagentready.com/.well-known/agent-skills/agent-skills/SKILL.md
// test: https://isitagentready.com/juno.build

const TEMPLATE_SKILL_WITHOUT_DIGEST = {
name: "juno",
type: "skill-md",
description:
"Up-to-date knowledge about Juno's CLI, SDK, and serverless functions for AI coding agents.",
url: "https://raw.githubusercontent.com/junobuild/skills/main/SKILL.md"
};

const TEMPLATE = {
$schema: "https://schemas.agentskills.io/discovery/0.2.0/schema.json",
skills: []
};

const OUTPUT_DIR = join("static", ".well-known", "agent-skills");
const OUTPUT_FILE_PATH = join(OUTPUT_DIR, "index.json");

await mkdir(OUTPUT_DIR, { recursive: true });

const computeSkillSha256 = async () => {
const response = await fetch(
"https://raw.githubusercontent.com/junobuild/skills/main/SKILL.md"
);

if (!response.ok) {
throw new Error("Fetching the current SKILL.md failed!");
}

const md = await response.text();

const encoder = new TextEncoder();
const hash = await crypto.subtle.digest("SHA-256", encoder.encode(md));

const sha256ToHex = (hashBuffer) => {
const hashArray = Array.from(new Uint8Array(hashBuffer));
return hashArray.map((b) => b.toString(16).padStart(2, "0")).join("");
};

return sha256ToHex(hash);
};

const sha256 = await computeSkillSha256();

const skill = {
...TEMPLATE_SKILL_WITHOUT_DIGEST,
digest: `sha256:${sha256}`
};

const json = {
...TEMPLATE,
skills: [skill]
};

await writeFile(OUTPUT_FILE_PATH, JSON.stringify(json, null, 2), "utf8");
12 changes: 12 additions & 0 deletions static/.well-known/agent-skills/index.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,12 @@
{
"$schema": "https://schemas.agentskills.io/discovery/0.2.0/schema.json",
"skills": [
{
"name": "juno",
"type": "skill-md",
"description": "Up-to-date knowledge about Juno's CLI, SDK, and serverless functions for AI coding agents.",
"url": "https://raw.githubusercontent.com/junobuild/skills/main/SKILL.md",
"digest": "sha256:18b7fec3e46664b67bdf5bd66f4f36fd9fca138a8749ddc2638f61fed4c23483"
}
]
}
Loading