2026-04-21 18:02:04 -07:00
|
|
|
#!/usr/bin/env node
|
docs: publish llms.txt and llms-full.txt for agent-friendly ingestion (#18276)
Two machine-readable entry points to the Hermes Agent docs:
/llms.txt curated index of every doc page, one link per page
with short descriptions. ~17 KB, safe to load into
an LLM context window.
/llms-full.txt every page under website/docs/ concatenated as markdown.
~1.8 MB. For one-shot ingestion by coding agents and
RAG pipelines.
Both files are also served from /docs/llms.txt and /docs/llms-full.txt
(Docusaurus serves website/static/ under baseUrl=/docs/). Some agents and
IDE plugins probe the classic site-root path; the deploy workflow now copies
both files to _site root so either URL works.
Conforms to the emerging llmstxt.org spec: H1 project name, blockquote
summary, short install command, GitHub link, then curated sections
mirroring the docs-site navigation (Getting Started, Using Hermes,
Features, Messaging, Integrations, Guides, Developer Guide, Reference).
Generated by website/scripts/generate-llms-txt.py. Wired into prebuild.mjs
so every 'npm run build' and 'npm run start' refreshes the files alongside
the existing skills.json extraction. Both outputs are gitignored (same
precedent as src/data/skills.json).
Descriptions in llms.txt are pulled from each page's frontmatter, so they
stay current automatically. All ~80 section slugs are validated against
the filesystem at generation time; an invalid slug would fail the prebuild.
2026-04-30 23:17:14 -07:00
|
|
|
// Runs website/scripts/extract-skills.py and generate-llms-txt.py before
|
|
|
|
|
// docusaurus build/start so that:
|
2026-05-28 03:41:43 -07:00
|
|
|
// - website/static/api/skills.json (lazy-fetched by src/pages/skills/index.tsx)
|
|
|
|
|
// - website/static/api/skills-meta.json (sidecar metadata for the Skills Hub)
|
docs: publish llms.txt and llms-full.txt for agent-friendly ingestion (#18276)
Two machine-readable entry points to the Hermes Agent docs:
/llms.txt curated index of every doc page, one link per page
with short descriptions. ~17 KB, safe to load into
an LLM context window.
/llms-full.txt every page under website/docs/ concatenated as markdown.
~1.8 MB. For one-shot ingestion by coding agents and
RAG pipelines.
Both files are also served from /docs/llms.txt and /docs/llms-full.txt
(Docusaurus serves website/static/ under baseUrl=/docs/). Some agents and
IDE plugins probe the classic site-root path; the deploy workflow now copies
both files to _site root so either URL works.
Conforms to the emerging llmstxt.org spec: H1 project name, blockquote
summary, short install command, GitHub link, then curated sections
mirroring the docs-site navigation (Getting Started, Using Hermes,
Features, Messaging, Integrations, Guides, Developer Guide, Reference).
Generated by website/scripts/generate-llms-txt.py. Wired into prebuild.mjs
so every 'npm run build' and 'npm run start' refreshes the files alongside
the existing skills.json extraction. Both outputs are gitignored (same
precedent as src/data/skills.json).
Descriptions in llms.txt are pulled from each page's frontmatter, so they
stay current automatically. All ~80 section slugs are validated against
the filesystem at generation time; an invalid slug would fail the prebuild.
2026-04-30 23:17:14 -07:00
|
|
|
// - website/static/llms.txt (agent-friendly short docs index)
|
|
|
|
|
// - website/static/llms-full.txt (full docs concat for LLM context)
|
|
|
|
|
// all exist without contributors remembering to run Python scripts manually.
|
|
|
|
|
// CI workflows still run the extraction explicitly, which is a no-op duplicate
|
|
|
|
|
// but matches their historical behaviour.
|
2026-04-21 18:02:04 -07:00
|
|
|
//
|
fix(skills-hub): show every catalog source on /docs/skills (skills.sh, ClawHub, browse.sh, OpenAI, …) (#32336)
The Skills Hub page was stuck on a stale Feb 25 snapshot, showing only Built-in
+ Optional + Anthropic + LobeHub. The unified index already has 2078 skills
from skills.sh / ClawHub / LobeHub / GitHub taps / Claude Marketplace, and
BrowseShSource adds another ~330 — none of it was reaching the page.
Changes:
- website/scripts/extract-skills.py: read website/static/api/skills-index.json
(the unified multi-source catalog, rebuilt twice daily) as the canonical
external source. Keep the legacy skills/index-cache/ fallback for offline
builds. Add friendly per-source labels (skills.sh, ClawHub, browse.sh,
OpenAI, HuggingFace, Anthropic, LobeHub, etc.) and per-entry installCmd.
- website/src/pages/skills/index.tsx: add source pills + ordering for the 11
new sources; render installCmd from the index entry.
- website/scripts/prebuild.mjs: when no local skills-index.json exists, fetch
the live one from hermes-agent.nousresearch.com so local 'npm run build'
matches production without burning GitHub API quota.
- scripts/build_skills_index.py: crawl BrowseShSource so browse.sh entries
land in the unified index. Adjust source_order.
- tools/skills_hub.py: GitHubSource.DEFAULT_TAPS — openai/skills moved its
skills into skills/.curated/ and skills/.system/, so add both as explicit
taps (the listing code skips dotted dirs by design). Drop
VoltAgent/awesome-agent-skills (README-only, no SKILL.md files) and
MiniMax-AI/cli (singular skill, not a tap directory). Net effect: github
source jumps from 83 → 143 skills, with OpenAI properly included.
- .github/workflows/deploy-site.yml: build the unified index BEFORE running
extract-skills.py — previous order meant extract-skills always fell back
to the legacy cache. Drop the 'skip if file exists' guard; the file is
gitignored and must be rebuilt every deploy.
- .github/workflows/skills-index.yml: drop the broken 'deploy-with-index'
job (it cp'd 'landingpage/\*' which no longer exists, failing every cron
run since the landingpage move). Replace it with a workflow_dispatch
trigger of deploy-site.yml so the index refresh still reaches production
on schedule.
- website/docs/user-guide/features/skills.md: drop VoltAgent from the
default-taps doc list to match the code.
Before: 695 skills (Built-in 90, Optional 84, Anthropic 16, LobeHub 505).
After: 2168 skills across 9 source pills, including the 1212 skills.sh
entries the user expected to see.
2026-05-25 18:34:54 -07:00
|
|
|
// We also try to pull a fresh copy of skills-index.json (the unified
|
|
|
|
|
// multi-source catalog) from the live docs site if it's not already on disk.
|
|
|
|
|
// That way local `npm run build` doesn't have to wait on
|
|
|
|
|
// scripts/build_skills_index.py crawling every skill source — which takes
|
|
|
|
|
// several minutes and burns GitHub API quota — but still gets the same
|
|
|
|
|
// 2000+ external skills the deployed site has.
|
|
|
|
|
//
|
2026-04-21 18:02:04 -07:00
|
|
|
// If python3 or its deps (pyyaml) aren't available on the local machine, we
|
|
|
|
|
// fall back to writing an empty skills.json so `npm run build` still
|
docs: publish llms.txt and llms-full.txt for agent-friendly ingestion (#18276)
Two machine-readable entry points to the Hermes Agent docs:
/llms.txt curated index of every doc page, one link per page
with short descriptions. ~17 KB, safe to load into
an LLM context window.
/llms-full.txt every page under website/docs/ concatenated as markdown.
~1.8 MB. For one-shot ingestion by coding agents and
RAG pipelines.
Both files are also served from /docs/llms.txt and /docs/llms-full.txt
(Docusaurus serves website/static/ under baseUrl=/docs/). Some agents and
IDE plugins probe the classic site-root path; the deploy workflow now copies
both files to _site root so either URL works.
Conforms to the emerging llmstxt.org spec: H1 project name, blockquote
summary, short install command, GitHub link, then curated sections
mirroring the docs-site navigation (Getting Started, Using Hermes,
Features, Messaging, Integrations, Guides, Developer Guide, Reference).
Generated by website/scripts/generate-llms-txt.py. Wired into prebuild.mjs
so every 'npm run build' and 'npm run start' refreshes the files alongside
the existing skills.json extraction. Both outputs are gitignored (same
precedent as src/data/skills.json).
Descriptions in llms.txt are pulled from each page's frontmatter, so they
stay current automatically. All ~80 section slugs are validated against
the filesystem at generation time; an invalid slug would fail the prebuild.
2026-04-30 23:17:14 -07:00
|
|
|
// succeeds — the Skills Hub page just shows an empty state, and llms.txt
|
|
|
|
|
// generation is skipped. CI always has the deps installed, so production
|
|
|
|
|
// deploys get real data.
|
2026-04-21 18:02:04 -07:00
|
|
|
|
|
|
|
|
import { spawnSync } from "node:child_process";
|
fix(skills-hub): show every catalog source on /docs/skills (skills.sh, ClawHub, browse.sh, OpenAI, …) (#32336)
The Skills Hub page was stuck on a stale Feb 25 snapshot, showing only Built-in
+ Optional + Anthropic + LobeHub. The unified index already has 2078 skills
from skills.sh / ClawHub / LobeHub / GitHub taps / Claude Marketplace, and
BrowseShSource adds another ~330 — none of it was reaching the page.
Changes:
- website/scripts/extract-skills.py: read website/static/api/skills-index.json
(the unified multi-source catalog, rebuilt twice daily) as the canonical
external source. Keep the legacy skills/index-cache/ fallback for offline
builds. Add friendly per-source labels (skills.sh, ClawHub, browse.sh,
OpenAI, HuggingFace, Anthropic, LobeHub, etc.) and per-entry installCmd.
- website/src/pages/skills/index.tsx: add source pills + ordering for the 11
new sources; render installCmd from the index entry.
- website/scripts/prebuild.mjs: when no local skills-index.json exists, fetch
the live one from hermes-agent.nousresearch.com so local 'npm run build'
matches production without burning GitHub API quota.
- scripts/build_skills_index.py: crawl BrowseShSource so browse.sh entries
land in the unified index. Adjust source_order.
- tools/skills_hub.py: GitHubSource.DEFAULT_TAPS — openai/skills moved its
skills into skills/.curated/ and skills/.system/, so add both as explicit
taps (the listing code skips dotted dirs by design). Drop
VoltAgent/awesome-agent-skills (README-only, no SKILL.md files) and
MiniMax-AI/cli (singular skill, not a tap directory). Net effect: github
source jumps from 83 → 143 skills, with OpenAI properly included.
- .github/workflows/deploy-site.yml: build the unified index BEFORE running
extract-skills.py — previous order meant extract-skills always fell back
to the legacy cache. Drop the 'skip if file exists' guard; the file is
gitignored and must be rebuilt every deploy.
- .github/workflows/skills-index.yml: drop the broken 'deploy-with-index'
job (it cp'd 'landingpage/\*' which no longer exists, failing every cron
run since the landingpage move). Replace it with a workflow_dispatch
trigger of deploy-site.yml so the index refresh still reaches production
on schedule.
- website/docs/user-guide/features/skills.md: drop VoltAgent from the
default-taps doc list to match the code.
Before: 695 skills (Built-in 90, Optional 84, Anthropic 16, LobeHub 505).
After: 2168 skills across 9 source pills, including the 1212 skills.sh
entries the user expected to see.
2026-05-25 18:34:54 -07:00
|
|
|
import { mkdirSync, writeFileSync, existsSync, statSync } from "node:fs";
|
2026-04-21 18:02:04 -07:00
|
|
|
import { dirname, join, resolve } from "node:path";
|
|
|
|
|
import { fileURLToPath } from "node:url";
|
|
|
|
|
|
|
|
|
|
const scriptDir = dirname(fileURLToPath(import.meta.url));
|
|
|
|
|
const websiteDir = resolve(scriptDir, "..");
|
|
|
|
|
const extractScript = join(scriptDir, "extract-skills.py");
|
docs: publish llms.txt and llms-full.txt for agent-friendly ingestion (#18276)
Two machine-readable entry points to the Hermes Agent docs:
/llms.txt curated index of every doc page, one link per page
with short descriptions. ~17 KB, safe to load into
an LLM context window.
/llms-full.txt every page under website/docs/ concatenated as markdown.
~1.8 MB. For one-shot ingestion by coding agents and
RAG pipelines.
Both files are also served from /docs/llms.txt and /docs/llms-full.txt
(Docusaurus serves website/static/ under baseUrl=/docs/). Some agents and
IDE plugins probe the classic site-root path; the deploy workflow now copies
both files to _site root so either URL works.
Conforms to the emerging llmstxt.org spec: H1 project name, blockquote
summary, short install command, GitHub link, then curated sections
mirroring the docs-site navigation (Getting Started, Using Hermes,
Features, Messaging, Integrations, Guides, Developer Guide, Reference).
Generated by website/scripts/generate-llms-txt.py. Wired into prebuild.mjs
so every 'npm run build' and 'npm run start' refreshes the files alongside
the existing skills.json extraction. Both outputs are gitignored (same
precedent as src/data/skills.json).
Descriptions in llms.txt are pulled from each page's frontmatter, so they
stay current automatically. All ~80 section slugs are validated against
the filesystem at generation time; an invalid slug would fail the prebuild.
2026-04-30 23:17:14 -07:00
|
|
|
const llmsScript = join(scriptDir, "generate-llms-txt.py");
|
2026-06-11 10:23:27 -07:00
|
|
|
const cronBlueprintsScript = join(scriptDir, "extract-automation-blueprints.py");
|
2026-05-28 03:41:43 -07:00
|
|
|
const outputFile = join(websiteDir, "static", "api", "skills.json");
|
fix(skills-hub): show every catalog source on /docs/skills (skills.sh, ClawHub, browse.sh, OpenAI, …) (#32336)
The Skills Hub page was stuck on a stale Feb 25 snapshot, showing only Built-in
+ Optional + Anthropic + LobeHub. The unified index already has 2078 skills
from skills.sh / ClawHub / LobeHub / GitHub taps / Claude Marketplace, and
BrowseShSource adds another ~330 — none of it was reaching the page.
Changes:
- website/scripts/extract-skills.py: read website/static/api/skills-index.json
(the unified multi-source catalog, rebuilt twice daily) as the canonical
external source. Keep the legacy skills/index-cache/ fallback for offline
builds. Add friendly per-source labels (skills.sh, ClawHub, browse.sh,
OpenAI, HuggingFace, Anthropic, LobeHub, etc.) and per-entry installCmd.
- website/src/pages/skills/index.tsx: add source pills + ordering for the 11
new sources; render installCmd from the index entry.
- website/scripts/prebuild.mjs: when no local skills-index.json exists, fetch
the live one from hermes-agent.nousresearch.com so local 'npm run build'
matches production without burning GitHub API quota.
- scripts/build_skills_index.py: crawl BrowseShSource so browse.sh entries
land in the unified index. Adjust source_order.
- tools/skills_hub.py: GitHubSource.DEFAULT_TAPS — openai/skills moved its
skills into skills/.curated/ and skills/.system/, so add both as explicit
taps (the listing code skips dotted dirs by design). Drop
VoltAgent/awesome-agent-skills (README-only, no SKILL.md files) and
MiniMax-AI/cli (singular skill, not a tap directory). Net effect: github
source jumps from 83 → 143 skills, with OpenAI properly included.
- .github/workflows/deploy-site.yml: build the unified index BEFORE running
extract-skills.py — previous order meant extract-skills always fell back
to the legacy cache. Drop the 'skip if file exists' guard; the file is
gitignored and must be rebuilt every deploy.
- .github/workflows/skills-index.yml: drop the broken 'deploy-with-index'
job (it cp'd 'landingpage/\*' which no longer exists, failing every cron
run since the landingpage move). Replace it with a workflow_dispatch
trigger of deploy-site.yml so the index refresh still reaches production
on schedule.
- website/docs/user-guide/features/skills.md: drop VoltAgent from the
default-taps doc list to match the code.
Before: 695 skills (Built-in 90, Optional 84, Anthropic 16, LobeHub 505).
After: 2168 skills across 9 source pills, including the 1212 skills.sh
entries the user expected to see.
2026-05-25 18:34:54 -07:00
|
|
|
const unifiedIndexFile = join(websiteDir, "static", "api", "skills-index.json");
|
|
|
|
|
const UNIFIED_INDEX_URL =
|
|
|
|
|
"https://hermes-agent.nousresearch.com/docs/api/skills-index.json";
|
|
|
|
|
const UNIFIED_INDEX_MAX_AGE_MS = 24 * 60 * 60 * 1000; // 24h
|
2026-04-21 18:02:04 -07:00
|
|
|
|
|
|
|
|
function writeEmptyFallback(reason) {
|
|
|
|
|
mkdirSync(dirname(outputFile), { recursive: true });
|
|
|
|
|
writeFileSync(outputFile, "[]\n");
|
|
|
|
|
console.warn(
|
|
|
|
|
`[prebuild] extract-skills.py skipped (${reason}); wrote empty skills.json. ` +
|
|
|
|
|
`Install python3 + pyyaml locally for a populated Skills Hub page.`,
|
|
|
|
|
);
|
|
|
|
|
}
|
|
|
|
|
|
docs: publish llms.txt and llms-full.txt for agent-friendly ingestion (#18276)
Two machine-readable entry points to the Hermes Agent docs:
/llms.txt curated index of every doc page, one link per page
with short descriptions. ~17 KB, safe to load into
an LLM context window.
/llms-full.txt every page under website/docs/ concatenated as markdown.
~1.8 MB. For one-shot ingestion by coding agents and
RAG pipelines.
Both files are also served from /docs/llms.txt and /docs/llms-full.txt
(Docusaurus serves website/static/ under baseUrl=/docs/). Some agents and
IDE plugins probe the classic site-root path; the deploy workflow now copies
both files to _site root so either URL works.
Conforms to the emerging llmstxt.org spec: H1 project name, blockquote
summary, short install command, GitHub link, then curated sections
mirroring the docs-site navigation (Getting Started, Using Hermes,
Features, Messaging, Integrations, Guides, Developer Guide, Reference).
Generated by website/scripts/generate-llms-txt.py. Wired into prebuild.mjs
so every 'npm run build' and 'npm run start' refreshes the files alongside
the existing skills.json extraction. Both outputs are gitignored (same
precedent as src/data/skills.json).
Descriptions in llms.txt are pulled from each page's frontmatter, so they
stay current automatically. All ~80 section slugs are validated against
the filesystem at generation time; an invalid slug would fail the prebuild.
2026-04-30 23:17:14 -07:00
|
|
|
function runPython(script, label) {
|
|
|
|
|
if (!existsSync(script)) {
|
|
|
|
|
console.warn(`[prebuild] ${label} skipped (script missing)`);
|
|
|
|
|
return false;
|
|
|
|
|
}
|
|
|
|
|
const r = spawnSync("python3", [script], { stdio: "inherit", cwd: websiteDir });
|
|
|
|
|
if (r.error && r.error.code === "ENOENT") {
|
|
|
|
|
console.warn(`[prebuild] ${label} skipped (python3 not found)`);
|
|
|
|
|
return false;
|
|
|
|
|
}
|
|
|
|
|
if (r.status !== 0) {
|
|
|
|
|
console.warn(`[prebuild] ${label} exited with status ${r.status}`);
|
|
|
|
|
return false;
|
|
|
|
|
}
|
|
|
|
|
return true;
|
2026-04-21 18:02:04 -07:00
|
|
|
}
|
|
|
|
|
|
fix(skills-hub): show every catalog source on /docs/skills (skills.sh, ClawHub, browse.sh, OpenAI, …) (#32336)
The Skills Hub page was stuck on a stale Feb 25 snapshot, showing only Built-in
+ Optional + Anthropic + LobeHub. The unified index already has 2078 skills
from skills.sh / ClawHub / LobeHub / GitHub taps / Claude Marketplace, and
BrowseShSource adds another ~330 — none of it was reaching the page.
Changes:
- website/scripts/extract-skills.py: read website/static/api/skills-index.json
(the unified multi-source catalog, rebuilt twice daily) as the canonical
external source. Keep the legacy skills/index-cache/ fallback for offline
builds. Add friendly per-source labels (skills.sh, ClawHub, browse.sh,
OpenAI, HuggingFace, Anthropic, LobeHub, etc.) and per-entry installCmd.
- website/src/pages/skills/index.tsx: add source pills + ordering for the 11
new sources; render installCmd from the index entry.
- website/scripts/prebuild.mjs: when no local skills-index.json exists, fetch
the live one from hermes-agent.nousresearch.com so local 'npm run build'
matches production without burning GitHub API quota.
- scripts/build_skills_index.py: crawl BrowseShSource so browse.sh entries
land in the unified index. Adjust source_order.
- tools/skills_hub.py: GitHubSource.DEFAULT_TAPS — openai/skills moved its
skills into skills/.curated/ and skills/.system/, so add both as explicit
taps (the listing code skips dotted dirs by design). Drop
VoltAgent/awesome-agent-skills (README-only, no SKILL.md files) and
MiniMax-AI/cli (singular skill, not a tap directory). Net effect: github
source jumps from 83 → 143 skills, with OpenAI properly included.
- .github/workflows/deploy-site.yml: build the unified index BEFORE running
extract-skills.py — previous order meant extract-skills always fell back
to the legacy cache. Drop the 'skip if file exists' guard; the file is
gitignored and must be rebuilt every deploy.
- .github/workflows/skills-index.yml: drop the broken 'deploy-with-index'
job (it cp'd 'landingpage/\*' which no longer exists, failing every cron
run since the landingpage move). Replace it with a workflow_dispatch
trigger of deploy-site.yml so the index refresh still reaches production
on schedule.
- website/docs/user-guide/features/skills.md: drop VoltAgent from the
default-taps doc list to match the code.
Before: 695 skills (Built-in 90, Optional 84, Anthropic 16, LobeHub 505).
After: 2168 skills across 9 source pills, including the 1212 skills.sh
entries the user expected to see.
2026-05-25 18:34:54 -07:00
|
|
|
async function ensureUnifiedIndex() {
|
|
|
|
|
// If we have a recent copy on disk, trust it.
|
|
|
|
|
if (existsSync(unifiedIndexFile)) {
|
|
|
|
|
try {
|
|
|
|
|
const age = Date.now() - statSync(unifiedIndexFile).mtimeMs;
|
|
|
|
|
if (age < UNIFIED_INDEX_MAX_AGE_MS) {
|
|
|
|
|
return true;
|
|
|
|
|
}
|
|
|
|
|
console.log(
|
|
|
|
|
`[prebuild] skills-index.json is ${(age / 3600000).toFixed(1)}h old; ` +
|
|
|
|
|
`refreshing from ${UNIFIED_INDEX_URL}`,
|
|
|
|
|
);
|
|
|
|
|
} catch {
|
|
|
|
|
// fall through to re-fetch
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
try {
|
|
|
|
|
const resp = await fetch(UNIFIED_INDEX_URL, {
|
|
|
|
|
headers: { accept: "application/json" },
|
|
|
|
|
});
|
|
|
|
|
if (!resp.ok) {
|
|
|
|
|
console.warn(
|
|
|
|
|
`[prebuild] skills-index.json fetch returned HTTP ${resp.status}; ` +
|
|
|
|
|
`using local copy if any`,
|
|
|
|
|
);
|
|
|
|
|
return existsSync(unifiedIndexFile);
|
|
|
|
|
}
|
|
|
|
|
const text = await resp.text();
|
|
|
|
|
// Sanity check: must be valid JSON with a skills array
|
|
|
|
|
try {
|
|
|
|
|
const parsed = JSON.parse(text);
|
|
|
|
|
if (!parsed || !Array.isArray(parsed.skills)) {
|
|
|
|
|
console.warn(
|
|
|
|
|
"[prebuild] skills-index.json from live site has no skills array; ignoring",
|
|
|
|
|
);
|
|
|
|
|
return existsSync(unifiedIndexFile);
|
|
|
|
|
}
|
|
|
|
|
} catch (e) {
|
|
|
|
|
console.warn(`[prebuild] skills-index.json from live site is not valid JSON: ${e}`);
|
|
|
|
|
return existsSync(unifiedIndexFile);
|
|
|
|
|
}
|
|
|
|
|
mkdirSync(dirname(unifiedIndexFile), { recursive: true });
|
|
|
|
|
writeFileSync(unifiedIndexFile, text);
|
|
|
|
|
console.log(
|
|
|
|
|
`[prebuild] downloaded skills-index.json from ${UNIFIED_INDEX_URL} ` +
|
|
|
|
|
`(${(text.length / 1024).toFixed(0)} KB)`,
|
|
|
|
|
);
|
|
|
|
|
return true;
|
|
|
|
|
} catch (e) {
|
|
|
|
|
console.warn(`[prebuild] skills-index.json fetch failed: ${e}`);
|
|
|
|
|
return existsSync(unifiedIndexFile);
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
// 0) Pull unified index if we don't have a fresh one.
|
|
|
|
|
await ensureUnifiedIndex();
|
|
|
|
|
|
docs: publish llms.txt and llms-full.txt for agent-friendly ingestion (#18276)
Two machine-readable entry points to the Hermes Agent docs:
/llms.txt curated index of every doc page, one link per page
with short descriptions. ~17 KB, safe to load into
an LLM context window.
/llms-full.txt every page under website/docs/ concatenated as markdown.
~1.8 MB. For one-shot ingestion by coding agents and
RAG pipelines.
Both files are also served from /docs/llms.txt and /docs/llms-full.txt
(Docusaurus serves website/static/ under baseUrl=/docs/). Some agents and
IDE plugins probe the classic site-root path; the deploy workflow now copies
both files to _site root so either URL works.
Conforms to the emerging llmstxt.org spec: H1 project name, blockquote
summary, short install command, GitHub link, then curated sections
mirroring the docs-site navigation (Getting Started, Using Hermes,
Features, Messaging, Integrations, Guides, Developer Guide, Reference).
Generated by website/scripts/generate-llms-txt.py. Wired into prebuild.mjs
so every 'npm run build' and 'npm run start' refreshes the files alongside
the existing skills.json extraction. Both outputs are gitignored (same
precedent as src/data/skills.json).
Descriptions in llms.txt are pulled from each page's frontmatter, so they
stay current automatically. All ~80 section slugs are validated against
the filesystem at generation time; an invalid slug would fail the prebuild.
2026-04-30 23:17:14 -07:00
|
|
|
// 1) skills.json — required for the Skills Hub page.
|
|
|
|
|
if (!existsSync(extractScript)) {
|
|
|
|
|
writeEmptyFallback("extract script missing");
|
|
|
|
|
} else {
|
|
|
|
|
const r = spawnSync("python3", [extractScript], {
|
|
|
|
|
stdio: "inherit",
|
|
|
|
|
cwd: websiteDir,
|
|
|
|
|
});
|
|
|
|
|
if (r.error && r.error.code === "ENOENT") {
|
|
|
|
|
writeEmptyFallback("python3 not found");
|
|
|
|
|
} else if (r.status !== 0) {
|
|
|
|
|
writeEmptyFallback(`extract-skills.py exited with status ${r.status}`);
|
|
|
|
|
}
|
2026-04-21 18:02:04 -07:00
|
|
|
}
|
|
|
|
|
|
docs: publish llms.txt and llms-full.txt for agent-friendly ingestion (#18276)
Two machine-readable entry points to the Hermes Agent docs:
/llms.txt curated index of every doc page, one link per page
with short descriptions. ~17 KB, safe to load into
an LLM context window.
/llms-full.txt every page under website/docs/ concatenated as markdown.
~1.8 MB. For one-shot ingestion by coding agents and
RAG pipelines.
Both files are also served from /docs/llms.txt and /docs/llms-full.txt
(Docusaurus serves website/static/ under baseUrl=/docs/). Some agents and
IDE plugins probe the classic site-root path; the deploy workflow now copies
both files to _site root so either URL works.
Conforms to the emerging llmstxt.org spec: H1 project name, blockquote
summary, short install command, GitHub link, then curated sections
mirroring the docs-site navigation (Getting Started, Using Hermes,
Features, Messaging, Integrations, Guides, Developer Guide, Reference).
Generated by website/scripts/generate-llms-txt.py. Wired into prebuild.mjs
so every 'npm run build' and 'npm run start' refreshes the files alongside
the existing skills.json extraction. Both outputs are gitignored (same
precedent as src/data/skills.json).
Descriptions in llms.txt are pulled from each page's frontmatter, so they
stay current automatically. All ~80 section slugs are validated against
the filesystem at generation time; an invalid slug would fail the prebuild.
2026-04-30 23:17:14 -07:00
|
|
|
// 2) llms.txt + llms-full.txt — agent-friendly docs entrypoints. Non-fatal.
|
|
|
|
|
runPython(llmsScript, "generate-llms-txt.py");
|
feat(cron): Cron Recipes — parameterized automation templates across every surface
A 'recipe' is a one-place definition of an automation that every surface
renders natively. The slot schema (cron/recipe_catalog.py) is the single
source of truth; four renderers consume it, and all paths end at the same
cron.jobs.create_job — no second job engine.
Form where there's a screen, conversation where there's a chat line:
- Dashboard / GUI app: a Recipes sub-tab on the Cron page renders each
recipe's typed slots as a form (time-picker, enum dropdown, free-text);
submit POSTs /api/cron/recipes/instantiate which fills + creates the job.
- CLI / TUI / messengers: /cron-recipe lists the catalog, shows a recipe's
fields, or fills + creates from a pasted 'key slot=val' command. The shared
handler (hermes_cli/cron_recipe_cmd.py) names any missing/invalid slot so
the agent can ask a targeted follow-up.
- Docs: a generated Cron Recipes catalog page (website, .mdx + React cards)
shows each recipe with a copy-paste command and a 'Send to App' button.
- Desktop: a hermes:// URL scheme (Electron single-instance lock +
setAsDefaultProtocolClient + open-url/second-instance) routes
hermes://cron-recipe/<key>?slot=val into the chat composer pre-filled.
Typed slots (time/enum/text/weekdays) with defaults: users never type raw
cron — recipes parameterize time-of-day and weekday sets and translate to
cron expressions; a free-text 'schedule' slot is the full-flexibility escape
hatch. Consent-first throughout: nothing schedules without an explicit submit
or send.
Core:
- cron/recipe_catalog.py — CronRecipe + RecipeSlot, 5 curated recipes,
recipe_form_schema / recipe_slash_command / recipe_deeplink /
recipe_catalog_entry renderers, fill_recipe (validate + translate to
create_job kwargs).
- hermes_cli/cron_recipe_cmd.py — shared /cron-recipe handler (CLI + TUI +
gateway never drift). CommandDef + dispatch in commands.py / cli.py /
gateway/run.py.
Dashboard: GET /api/cron/recipes + POST /api/cron/recipes/instantiate
(web_server.py), CronRecipes.tsx gallery+form, Segmented sub-tab on CronPage,
api.ts methods + types.
Desktop: hermes:// scheme end to end (main.cjs deep-link router + ready-queue,
preload onDeepLink/signalDeepLinkReady, global.d.ts types, desktop-controller
composer prefill, electron-builder protocols key).
Docs: extract-cron-recipes.py generator wired into prebuild.mjs,
cron-recipes-catalog.mdx + CronRecipesCatalog React component, sidebar entry.
Generated index json gitignored like skills.json.
Tests: 23 core (catalog/slots/schedule-resolution/validation/renderers/command
handler/generator) + 5 web_server endpoint tests. E2E verified end to end:
slot fill -> create_job -> persisted job with correct schedule/deliver/origin.
2026-06-07 18:49:09 -07:00
|
|
|
|
2026-06-11 10:23:27 -07:00
|
|
|
// 3) automation-blueprints-index.json — Automation Blueprints catalog page. Non-fatal; the page
|
feat(cron): Cron Recipes — parameterized automation templates across every surface
A 'recipe' is a one-place definition of an automation that every surface
renders natively. The slot schema (cron/recipe_catalog.py) is the single
source of truth; four renderers consume it, and all paths end at the same
cron.jobs.create_job — no second job engine.
Form where there's a screen, conversation where there's a chat line:
- Dashboard / GUI app: a Recipes sub-tab on the Cron page renders each
recipe's typed slots as a form (time-picker, enum dropdown, free-text);
submit POSTs /api/cron/recipes/instantiate which fills + creates the job.
- CLI / TUI / messengers: /cron-recipe lists the catalog, shows a recipe's
fields, or fills + creates from a pasted 'key slot=val' command. The shared
handler (hermes_cli/cron_recipe_cmd.py) names any missing/invalid slot so
the agent can ask a targeted follow-up.
- Docs: a generated Cron Recipes catalog page (website, .mdx + React cards)
shows each recipe with a copy-paste command and a 'Send to App' button.
- Desktop: a hermes:// URL scheme (Electron single-instance lock +
setAsDefaultProtocolClient + open-url/second-instance) routes
hermes://cron-recipe/<key>?slot=val into the chat composer pre-filled.
Typed slots (time/enum/text/weekdays) with defaults: users never type raw
cron — recipes parameterize time-of-day and weekday sets and translate to
cron expressions; a free-text 'schedule' slot is the full-flexibility escape
hatch. Consent-first throughout: nothing schedules without an explicit submit
or send.
Core:
- cron/recipe_catalog.py — CronRecipe + RecipeSlot, 5 curated recipes,
recipe_form_schema / recipe_slash_command / recipe_deeplink /
recipe_catalog_entry renderers, fill_recipe (validate + translate to
create_job kwargs).
- hermes_cli/cron_recipe_cmd.py — shared /cron-recipe handler (CLI + TUI +
gateway never drift). CommandDef + dispatch in commands.py / cli.py /
gateway/run.py.
Dashboard: GET /api/cron/recipes + POST /api/cron/recipes/instantiate
(web_server.py), CronRecipes.tsx gallery+form, Segmented sub-tab on CronPage,
api.ts methods + types.
Desktop: hermes:// scheme end to end (main.cjs deep-link router + ready-queue,
preload onDeepLink/signalDeepLinkReady, global.d.ts types, desktop-controller
composer prefill, electron-builder protocols key).
Docs: extract-cron-recipes.py generator wired into prebuild.mjs,
cron-recipes-catalog.mdx + CronRecipesCatalog React component, sidebar entry.
Generated index json gitignored like skills.json.
Tests: 23 core (catalog/slots/schedule-resolution/validation/renderers/command
handler/generator) + 5 web_server endpoint tests. E2E verified end to end:
slot fill -> create_job -> persisted job with correct schedule/deliver/origin.
2026-06-07 18:49:09 -07:00
|
|
|
// renders an empty state if the generator can't run.
|
2026-06-11 10:23:27 -07:00
|
|
|
runPython(cronBlueprintsScript, "extract-automation-blueprints.py");
|