Publish Agent Skills discovery metadata

This commit is contained in:
sergeych committed 2026-08-19 19:46:19 +04:00
1 parent 8799cee0ca
commit 3d7254aaf0
7 files changed
+193 -4

No files matched your search

+62
View File
@@ -0,0 +1,62 @@
#!/usr/bin/env node
'use strict';
const crypto = require('node:crypto');
const fs = require('node:fs');
const path = require('node:path');
const projectRoot = path.resolve(__dirname, '..');
const source = path.join(projectRoot, 'skills', 'crypstie', 'SKILL.md');
const outputRoot = path.resolve(process.argv[2] || path.join(projectRoot, 'build', 'agent-skills'));
const skillDirectory = path.join(outputRoot, 'crypstie');
const skillTarget = path.join(skillDirectory, 'SKILL.md');
const indexTarget = path.join(outputRoot, 'index.json');
const llmsTarget = path.join(outputRoot, 'llms.txt');
const skill = fs.readFileSync(source);
const text = skill.toString('utf8');
const description = text.match(/^description:\s*(.+)$/m)?.[1]?.trim();
if (!description) {
throw new Error('skills/crypstie/SKILL.md has no description in its frontmatter');
}
fs.mkdirSync(skillDirectory, { recursive: true });
fs.writeFileSync(skillTarget, skill);
const digest = crypto.createHash('sha256').update(skill).digest('hex');
const index = {
$schema: 'https://schemas.agentskills.io/discovery/0.2.0/schema.json',
skills: [
{
name: 'crypstie',
type: 'skill-md',
description,
url: '/.well-known/agent-skills/crypstie/SKILL.md',
digest: `sha256:${digest}`,
},
],
};
fs.writeFileSync(indexTarget, `${JSON.stringify(index, null, 2)}\n`);
fs.writeFileSync(
llmsTarget,
[
'# Crypstie',
'',
'> End-to-end encrypted links for text and files.',
'',
'## Agent skill',
'',
'- [Crypstie skill](https://crypstie.com/.well-known/agent-skills/crypstie/SKILL.md): Create and open Crypstie links with the npm CLI.',
'- [Skill discovery index](https://crypstie.com/.well-known/agent-skills/index.json): Machine-readable Agent Skills index with integrity metadata.',
'',
'## Package',
'',
'- [crypstie on npm](https://www.npmjs.com/package/crypstie): Node.js library and command-line client.',
'',
].join('\n'),
);
console.log(outputRoot);
Executable
+63
View File
@@ -0,0 +1,63 @@
#!/usr/bin/env bash
set -euo pipefail
PROJECT_ROOT=$(cd "$(dirname "$0")/.." && pwd)
SSH_HOST=${CRYPSTIE_DEPLOY_HOST:-crypstie@sergeych.net}
REMOTE_ROOT=${CRYPSTIE_SKILLS_ROOT:-/home/crypstie/agent-skills}
TOKEN_FILE=${CRYPSTIE_NPM_TOKEN_FILE:-${PROJECT_ROOT}/.node_token}
DEPLOY_NPM=1
DEPLOY_SKILLS=1
usage() {
echo "Usage: scripts/deploy [--npm-only | --skills-only]"
}
case "${1:-}" in
"") ;;
--npm-only) DEPLOY_SKILLS=0 ;;
--skills-only) DEPLOY_NPM=0 ;;
-h|--help) usage; exit 0 ;;
*) usage >&2; exit 2 ;;
esac
cd "$PROJECT_ROOT"
npm test
STAGING=$(mktemp -d)
trap 'rm -rf -- "$STAGING"' EXIT
if [[ "$DEPLOY_NPM" == 1 ]]; then
PACKAGE_NAME=$(node -p "require('./package.json').name")
PACKAGE_VERSION=$(node -p "require('./package.json').version")
if npm view "${PACKAGE_NAME}@${PACKAGE_VERSION}" version --json >/dev/null 2>&1; then
echo "npm: ${PACKAGE_NAME}@${PACKAGE_VERSION} is already published; skipping"
else
if [[ ! -r "$TOKEN_FILE" ]]; then
echo "npm: token file is not readable: $TOKEN_FILE" >&2
exit 1
fi
TOKEN=$(tr -d '\r\n' < "$TOKEN_FILE")
if [[ -z "$TOKEN" ]]; then
echo "npm: token file is empty: $TOKEN_FILE" >&2
exit 1
fi
NPMRC="$STAGING/npmrc"
(umask 077; printf '//registry.npmjs.org/:_authToken=%s\n' "$TOKEN" > "$NPMRC")
npm publish --access public --userconfig "$NPMRC"
unset TOKEN
rm -f -- "$NPMRC"
fi
fi
if [[ "$DEPLOY_SKILLS" == 1 ]]; then
DISCOVERY="$STAGING/discovery"
node scripts/build-skill-discovery.js "$DISCOVERY" >/dev/null
REMOTE_STAGING="${REMOTE_ROOT}.incoming"
ssh "$SSH_HOST" "mkdir -p '$REMOTE_STAGING'"
rsync -az --delete "$DISCOVERY/" "$SSH_HOST:$REMOTE_STAGING/"
ssh "$SSH_HOST" "set -e; chmod -R a+rX '$REMOTE_STAGING'; rm -rf '${REMOTE_ROOT}.previous'; if [ -d '$REMOTE_ROOT' ]; then mv '$REMOTE_ROOT' '${REMOTE_ROOT}.previous'; fi; mv '$REMOTE_STAGING' '$REMOTE_ROOT'"
echo "skills: deployed to https://crypstie.com/.well-known/agent-skills/index.json"
fi