diff --git a/.github/workflows/sync-skills.yml b/.github/workflows/sync-skills.yml new file mode 100644 index 0000000..97bc0fe --- /dev/null +++ b/.github/workflows/sync-skills.yml @@ -0,0 +1,90 @@ +name: Sync agent skills from sei-skill + +# The installable agent skills at .mintlify/skills//SKILL.md are GENERATED +# from the canonical sei-skill repo (github.com/sei-protocol/sei-skill) by +# scripts/build-mintlify-skills.mjs — they are never hand-authored here. This +# workflow regenerates them and opens a PR for review (generation is LLM-assisted +# and non-deterministic, so a human reviews before merge). +# +# Triggers: +# - workflow_dispatch (manual; optionally pass a sei-skill ref) +# - repository_dispatch (sei-skill's release workflow sends type: sei-skill-release +# with client_payload.ref = the released tag/sha) +# +# Requires repo secret: ANTHROPIC_API_KEY + +on: + workflow_dispatch: + inputs: + ref: + description: 'sei-skill ref to generate from' + required: false + default: 'main' + repository_dispatch: + types: [sei-skill-release] + +permissions: + contents: write + pull-requests: write + +defaults: + run: + shell: bash + +jobs: + sync: + runs-on: ubuntu-latest + timeout-minutes: 20 + steps: + - name: Checkout docs + uses: actions/checkout@v4 + + - name: Checkout sei-skill (canonical source) + uses: actions/checkout@v4 + with: + repository: sei-protocol/sei-skill + ref: ${{ github.event.client_payload.ref || inputs.ref || 'main' }} + path: .sei-skill-src + + - name: Set up Node + uses: actions/setup-node@v4 + with: + node-version: '20' + + - name: Install generator dependency + run: npm install --no-save @anthropic-ai/sdk + + - name: Record sei-skill revision + id: src + run: echo "ref=$(git -C .sei-skill-src rev-parse --short HEAD)" >> "$GITHUB_OUTPUT" + + - name: Regenerate skills from sei-skill + env: + ANTHROPIC_API_KEY: ${{ secrets.ANTHROPIC_API_KEY }} + SEI_SKILL_DIR: ${{ github.workspace }}/.sei-skill-src/skill + SEI_SKILL_REF: ${{ steps.src.outputs.ref }} + run: node scripts/build-mintlify-skills.mjs --write + + - name: Clean up source + build dirs + run: rm -rf .sei-skill-src dist + + - name: Open PR if skills changed + env: + GH_TOKEN: ${{ github.token }} + run: | + set -euo pipefail + if git diff --quiet -- .mintlify/skills; then + echo 'No skill changes; nothing to do.' + exit 0 + fi + BRANCH="chore/sync-skills-${{ steps.src.outputs.ref }}" + git config user.name 'github-actions[bot]' + git config user.email '41898282+github-actions[bot]@users.noreply.github.com' + git checkout -b "$BRANCH" + git add .mintlify/skills + git commit -m "chore(skills): regenerate from sei-skill@${{ steps.src.outputs.ref }}" + git push -f origin "$BRANCH" + gh pr create \ + --title "chore(skills): regenerate from sei-skill@${{ steps.src.outputs.ref }}" \ + --body "Automated regeneration of \`.mintlify/skills/\` from [sei-protocol/sei-skill](https://github.com/sei-protocol/sei-skill)@${{ steps.src.outputs.ref }} via \`scripts/build-mintlify-skills.mjs\`. These are generated artifacts — review for quality before merge." \ + || echo 'PR already exists for this branch; pushed update.' diff --git a/.gitignore b/.gitignore index ab946a3..ef6266d 100644 --- a/.gitignore +++ b/.gitignore @@ -1,6 +1,9 @@ .DS_Store node_modules/ -.mintlify/ +# Mintlify uses .mintlify/ as a local build cache, but .mintlify/skills/ holds +# the hosted agent skills (SKILL.md) that must ship — keep that subtree tracked. +.mintlify/* +!.mintlify/skills/ .next/ .vercel/ dist/ diff --git a/ai/sei-skill/index.mdx b/ai/sei-skill/index.mdx index 23b6f7c..fd40027 100644 --- a/ai/sei-skill/index.mdx +++ b/ai/sei-skill/index.mdx @@ -44,7 +44,7 @@ sei-skill covers three areas. You can install all three or just the ones you nee **Ecosystem** — infrastructure and integrations: - RPC endpoints (public, community, paid SaaS) -- Bridges (LayerZero V2, Wormhole, Axelar, CCTP) +- Bridges (LayerZero V2, Wormhole, CCTP) - Oracles (Chainlink, Pyth, API3, RedStone) - Indexers (The Graph, Goldsky, Dune, Moralis) - DeFi protocols (DragonSwap, Yei, Takara, Saphyre) diff --git a/ai/skills.mdx b/ai/skills.mdx new file mode 100644 index 0000000..1509290 --- /dev/null +++ b/ai/skills.mdx @@ -0,0 +1,70 @@ +--- +title: 'Skills Registry' +sidebarTitle: 'Skills Registry' +description: 'Install Sei Foundation agent skills into your AI coding assistant with one command. Each skill teaches your assistant a focused slice of Sei — contracts, frontend, precompiles, nodes, payments, security, bridges, or migration.' +keywords: ['sei skills', 'agent skills', 'skill.md', 'npx skills add', 'claude code', 'cursor', 'windsurf', 'ai coding assistant'] +--- + +import { SkillsRegistry } from '/snippets/skills-registry.jsx'; + +Sei Foundation publishes a set of **agent skills** — focused, installable knowledge packs that make your AI coding assistant Sei-aware. They're hosted directly on this docs site and follow the open [`skill.md`](https://www.mintlify.com/blog/skill-md) standard, so any compatible assistant (Claude Code, Cursor, Windsurf, and others) can install them. + +## Install + +Install the complete Foundation set with one command — the CLI detects your installed assistants and lets you pick which to install into: + +```bash +npx skills add https://docs.sei.io +``` + + + This fetches every skill served at `docs.sei.io/.well-known/skills/` and installs the ones you select. Skills stay current on every docs deploy — no manual updates. + + +## Foundation skills + +Filter by domain to find what fits your project. Every card copies the same command — `npx skills add https://docs.sei.io` — which then lets you pick exactly which skills to install, so you can keep your assistant's context lean. + + + +## How skills work + +Each Foundation skill is a single `SKILL.md` file with YAML frontmatter describing **when** an assistant should reach for it and a focused playbook of Sei-specific facts, code, and pitfalls. Because they're served from this site, they're also discoverable by autonomous agents: + + + + Agents can enumerate every skill at `docs.sei.io/.well-known/skills/` and fetch any `SKILL.md` directly — no install step required. + + + Skills are versioned in [`sei-protocol/sei-docs`](https://github.com/sei-protocol/sei-docs) under `.mintlify/skills/` and redeploy with the docs. + + + +## Foundation vs. the full sei-skill + +The skills above are **focused** — one domain each, ideal when you want to keep your assistant's context tight. If you'd rather load a single comprehensive knowledge base covering every domain at once, use the full [**sei-skill**](/ai/sei-skill) instead. + +| Use a Foundation skill when… | Use the full [sei-skill](/ai/sei-skill) when… | +|---|---| +| You work mostly in one area (e.g. contracts only) | You want all-domain coverage in one install | +| You want to keep assistant context lean | You're starting a new Sei project from scratch | +| You're composing your own skill set | You want the editor-resident Claude Code skill | + +## Community skills + +The skills registry is open. Ecosystem teams — DEXs, lending protocols, oracles, infra providers — can publish their own skills so developers building on top of them get accurate, integration-specific guidance from their AI assistant. + + + Host a `SKILL.md` in your own docs (any Mintlify site serves `/.well-known/skills/` automatically) or contribute one to `sei-protocol/sei-docs`. Community skills will be listed here as they ship. + + +## Next steps + + + + The full multi-domain knowledge base, with per-assistant install instructions and example prompts. + + + Give your assistant live on-chain access — read balances, send transactions, and query network state. + + diff --git a/docs.json b/docs.json index e1bc9ea..c0c7175 100644 --- a/docs.json +++ b/docs.json @@ -207,6 +207,7 @@ "pages": [ "evm/sei-js/index", "evm/sei-js/create-sei", + "evm/templates", "evm/sei-js/ledger", "evm/sei-js/registry" ] @@ -352,6 +353,7 @@ "group": "AI", "pages": [ "ai/index", + "ai/skills", { "group": "Agent Skills", "pages": [ @@ -1655,6 +1657,16 @@ "source": "/llms/skill.md", "destination": "/skill.md", "permanent": true + }, + { + "source": "/skills", + "destination": "/ai/skills", + "permanent": true + }, + { + "source": "/templates", + "destination": "/evm/templates", + "permanent": true } ], "interaction": { diff --git a/evm/sei-js/create-sei.mdx b/evm/sei-js/create-sei.mdx index f7d44f7..ccb067a 100644 --- a/evm/sei-js/create-sei.mdx +++ b/evm/sei-js/create-sei.mdx @@ -67,7 +67,7 @@ The CLI automatically configures TypeScript, Next.js, Tailwind CSS, Biome format The default template creates a **Next.js + Wagmi (EVM)** application — a production-ready Next.js app with Wagmi for type-safe Ethereum wallet connections and blockchain interactions. Includes built-in support for MetaMask, WalletConnect, Coinbase Wallet, and other popular wallets. -**Tech Stack:** Next.js 14, Wagmi v2, Viem, TanStack Query, Tailwind CSS +**Tech Stack:** Next.js 15, React 19, Wagmi v2, Viem, RainbowKit, TanStack Query, Tailwind CSS v4, Mantine UI, Biome, TypeScript ```bash npx @sei-js/create-sei app --name my-sei-app diff --git a/evm/templates.mdx b/evm/templates.mdx new file mode 100644 index 0000000..f654595 --- /dev/null +++ b/evm/templates.mdx @@ -0,0 +1,96 @@ +--- +title: 'Templates' +sidebarTitle: 'Templates' +description: 'Production-ready Sei dApp templates you can scaffold in one command with @sei-js/create-sei — wallet connections, contract interactions, and TypeScript wired up out of the box.' +keywords: ['sei templates', 'create-sei', 'scaffold', 'starter', 'nextjs', 'wagmi', 'viem', 'precompiles', 'dapp template'] +--- + +Start a new Sei dApp from a working, production-ready template instead of a blank folder. The [`@sei-js/create-sei`](/evm/sei-js/create-sei) CLI scaffolds a fully wired project — wallet connections, contract interactions, TypeScript, and styling — in seconds. + +## Scaffold in one command + + + +```bash npm +npx @sei-js/create-sei app --name my-sei-app +``` + +```bash pnpm +pnpm create @sei-js/sei app --name my-sei-app +``` + + + +Then install and run: + +```bash +cd my-sei-app +npm install +npm run dev +``` + +## Templates + + + + The default starter — a production-ready **Next.js 15** app (React 19) with type-safe wallet connections and contract reads/writes. + + **Stack:** Next.js 15 · React 19 · wagmi v2 · viem · RainbowKit · TanStack Query · Tailwind CSS v4 · Mantine UI · Biome · TypeScript + + **Includes:** RainbowKit wallet connection (MetaMask / WalletConnect / Coinbase Wallet), organized components/hooks/utilities, and Sei network config. + + ```bash + npx @sei-js/create-sei app --name my-sei-app + ``` + + + + The default template plus working examples that query Sei's native [precompiles](/evm/precompiles/example-usage) — Bank, Staking, and Governance — directly from the frontend. + + **Adds:** native token supply, staking info, and governance proposal reads via `@sei-js/precompiles`. + + ```bash + npx @sei-js/create-sei app --name my-app --extension precompiles + ``` + + + + + See every available extension with `npx @sei-js/create-sei list-extensions`. Full CLI options and the interactive setup flow are documented on the [Scaffold Sei](/evm/sei-js/create-sei) page. + + +## What every template gives you + + + + Pre-configured wallet connections and React hooks — connect, read balances, and send transactions without boilerplate. + + + Mainnet (`pacific-1`, 1329) and testnet (`atlantic-2`, 1328) wired up, with contract-interaction examples. + + + End-to-end TypeScript with wagmi + viem, so contract calls and ABIs are typed. + + + Tailwind CSS, Mantine UI, Biome formatting, and Git initialized — ready to build on. + + + + + **Prerequisites:** Node.js v18 or higher (`node --version` to check). + + +## More templates are coming + +This gallery grows as new starters ship. Building a template the ecosystem should know about — a DeFi starter, an NFT mint, an x402-payments app, or an AI agent? Contribute it to [`sei-protocol/sei-js`](https://github.com/sei-protocol/sei-js/tree/main/packages/create-sei) and it can be listed here. + +## Next steps + + + + Full `create-sei` options, extensions, and troubleshooting. + + + Wire wagmi + viem and a wallet into a Sei dApp from first principles. + + diff --git a/learn/sip-03-migration.mdx b/learn/sip-03-migration.mdx index 5edaad0..a667add 100644 --- a/learn/sip-03-migration.mdx +++ b/learn/sip-03-migration.mdx @@ -26,9 +26,9 @@ For the full proposal text, see: - Governance [Proposal #99](https://www.mintscan.io/sei/proposals/99) — initiated the migration -- Governance [Proposal #115](https://www.mintscan.io/sei/proposals/115) — disables CosmWasm code uploads and contract instantiations. After this passes, no new CosmWasm contracts can be deployed on Sei. +- Governance [Proposal #115](https://www.mintscan.io/sei/proposals/115) (pacific-1 mainnet; the atlantic-2 testnet equivalent is #246) — disables CosmWasm code uploads and contract instantiations. No new CosmWasm contracts can be deployed on Sei. -- Governance [Proposal #116](https://www.mintscan.io/sei/proposals/116) — disables inbound IBC transfers. After this passes and is activated, IBC assets bridged from Cosmos chains can no longer arrive on Sei. +- Governance [Proposal #116](https://www.mintscan.io/sei/proposals/116) (pacific-1 mainnet; the atlantic-2 testnet equivalent is #247) — disables inbound IBC transfers. IBC assets bridged from Cosmos chains can no longer arrive on Sei. diff --git a/node/node-operators.mdx b/node/node-operators.mdx index 04e2fc6..853c604 100644 --- a/node/node-operators.mdx +++ b/node/node-operators.mdx @@ -213,19 +213,16 @@ sc-enable = true # Defines the SC store directory, if not explicitly set, default to application home directory sc-directory = "" -# WriteMode defines how EVM data writes are routed between backends. -# Valid values: cosmos_only, dual_write, split_write, evm_only -# defaults to cosmos_only -sc-write-mode = "cosmos_only" +# WriteMode defines the write routing mode for EVM data in the SC layer. +# Valid values: memiavl_only, migrate_evm, evm_migrated, migrate_all_but_bank, +# all_migrated_but_bank, migrate_bank, flatkv_only, test_only_dual_write +# defaults to memiavl_only +sc-write-mode = "memiavl_only" -# ReadMode defines how EVM data reads are routed between backends. -# Valid values: cosmos_only, evm_first, split_read -# defaults to cosmos_only -sc-read-mode = "cosmos_only" - -# EnableLatticeHash controls whether the FlatKV lattice hash participates -# in the final app hash. Default: false. -sc-enable-lattice-hash = false +# KeysToMigratePerBlock controls how many EVM keys the in-flight migration +# (sc-write-mode = migrate_evm / migrate_bank / migrate_all_but_bank) drains +# from memiavl into flatkv per block. Must be > 0; ignored when not migrating. +sc-keys-to-migrate-per-block = 1024 # Max concurrent historical proof queries (RPC /store path) sc-historical-proof-max-inflight = 1 @@ -1376,9 +1373,9 @@ legacy single-database IAVL store with separate hot- and historical-data tiers: memory-mapped Merkle tree (`memiavl`) ported from Cronos. EVM state can additionally be routed through **FlatKV**, an EVM-tuned PebbleDB store with per-type sub-databases (`account`, `code`, `storage`, `legacy`, - `metadata`). Routing is controlled by `sc-write-mode` / `sc-read-mode` - and defaults to memiavl-only — FlatKV is only opened when one of those - modes is set to a non-default value. + `metadata`). Routing is controlled by `sc-write-mode` (default + `memiavl_only`) — FlatKV is only opened once a migration mode such as + `migrate_evm` is set. 2. **State Store (SS)** — versioned raw key/value pairs used for historical queries. Required for any node that serves RPC. The default backend is **PebbleDB**; **RocksDB** is available for iteration-heavy workloads such @@ -1418,17 +1415,22 @@ sc-snapshot-min-time-interval = 3600 # Cap on snapshot write throughput across all trees (MB/s). 0 = unlimited. sc-snapshot-write-rate-mbps = 100 -# EVM data routing between the Cosmos memiavl tree and FlatKV. -# Default: cosmos_only / cosmos_only — all EVM state lives in memiavl. See -# the Giga Storage section below for the dual_write + split_read setup. -sc-write-mode = "cosmos_only" -sc-read-mode = "cosmos_only" -sc-enable-lattice-hash = false +# EVM data routing for the SC layer. Default memiavl_only — all SC state +# lives in the memiavl tree. Valid values: memiavl_only, migrate_evm, +# evm_migrated, migrate_all_but_bank, all_migrated_but_bank, migrate_bank, +# flatkv_only (test_only_dual_write is test-only — never run in production). +# There is no sc-read-mode; the evm_lattice app-hash handling is internal. +# See the Giga Storage section below for the FlatKV migration. +sc-write-mode = "memiavl_only" + +# Keys drained from memiavl into FlatKV per block while in a migration mode +# (migrate_evm / migrate_bank / migrate_all_but_bank). Ignored otherwise. +sc-keys-to-migrate-per-block = 1024 [state-commit.flatkv] # FlatKV is the EVM-optimized commit store (PebbleDB). It is only opened -# when sc-write-mode is dual_write or split_write — otherwise these -# settings have no effect. WAL crash recovery is idempotent, so fsync +# once sc-write-mode enters a migration mode (e.g. migrate_evm) — otherwise +# these settings have no effect. WAL crash recovery is idempotent, so fsync # stays off by default. fsync = false async-write-buffer = 0 @@ -1450,10 +1452,11 @@ ss-keep-recent = 100000 # snapshot creation. ss-prune-interval = 600 -# Optional EVM SS routing — same semantics as the SC modes above. Leave on -# cosmos_only unless you have completed the Giga SS Store migration. -evm-ss-write-mode = "cosmos_only" -evm-ss-read-mode = "cosmos_only" +# Optional EVM SS routing. Leave false unless you have completed the Giga SS +# Store migration. When true, EVM state is routed to a dedicated EVM SS backend +# under data/evm_ss/. (Older releases used per-key evm-ss-write-mode / +# evm-ss-read-mode toggles — replaced by this single bool in v6.5+.) +evm-ss-split = false evm-ss-separate-dbs = false [receipt-store] @@ -1482,18 +1485,20 @@ write amplification. ```toml -[state-commit] -sc-write-mode = "dual_write" # write EVM data to memiavl AND FlatKV -sc-read-mode = "split_read" # read EVM data from FlatKV -sc-enable-lattice-hash = true # required for split-mode app-hash equality - [state-store] -evm-ss-write-mode = "split_write" -evm-ss-read-mode = "split_read" +# Route EVM State Store into a dedicated EVM SS backend (data/evm_ss/) — the +# setting the supported Giga SS Store migration flips. Requires a fresh state sync. +evm-ss-split = true + +[state-commit] +# (Advanced) The SC layer can separately route EVM State Commit data into +# FlatKV via the migration modes (memiavl_only -> migrate_evm -> evm_migrated). +# The SS-store migration guide below leaves SC config on its default. +sc-write-mode = "memiavl_only" ``` -Enabling Giga Storage requires a fresh state sync — flipping the EVM SS -modes on a node with existing data fails the startup safety checks because +Enabling Giga Storage requires a fresh state sync — flipping `evm-ss-split` +on a node with existing data fails the startup safety checks because the new EVM SS DB starts empty while Cosmos SS already has history. The full procedure is in the [Giga SS Store Migration Guide](/node/giga-storage-migration) and is diff --git a/scripts/build-mintlify-skills.mjs b/scripts/build-mintlify-skills.mjs new file mode 100644 index 0000000..d93fb55 --- /dev/null +++ b/scripts/build-mintlify-skills.mjs @@ -0,0 +1,127 @@ +#!/usr/bin/env node +/** + * Generate the docs single-file skills (.mintlify/skills//SKILL.md) from the + * canonical sei-skill source (github.com/sei-protocol/sei-skill). + * + * Each docs skill is a FLATTENED projection of one or more sei-skill domains: + * self-contained, <= ~5k tokens, linking to live docs.sei.io pages instead of + * bundling references/ (Mintlify serves only a single SKILL.md per skill — its + * discovery manifest lists files: ["SKILL.md"], no references/ subtree). + * + * sei-skill is the source of truth; these docs skills are derived. Reconcile any + * docs-side fixes back into sei-skill FIRST, then regenerate — generating from a + * stale source would regress the docs. + * + * Modes: + * - ANTHROPIC_API_KEY set -> condenses each skill via the model, writes SKILL.md. + * - no key -> emits SOURCE_BUNDLE.md + PROMPT.md per skill to dist/ + * for a human/LLM to run. + * + * The current docs skill (if present) is fed in as the QUALITY BAR so generation + * matches-or-beats it. Output lands in dist/ (gitignored) — review before copying + * into .mintlify/skills//. + * + * Paths (override via env): + * SEI_SKILL_DIR default ../../sei-skill/skill (sibling checkout) + * + * Usage: + * node scripts/build-mintlify-skills.mjs [--skill sei-bridges] + * SEI_SKILL_DIR=/abs/path/sei-skill/skill node scripts/build-mintlify-skills.mjs + */ +import { readFileSync, writeFileSync, mkdirSync, existsSync } from 'fs'; +import { resolve, dirname, join } from 'path'; +import { fileURLToPath } from 'url'; + +const __dirname = dirname(fileURLToPath(import.meta.url)); +const REPO = resolve(__dirname, '..'); // sei-docs root +const SKILL = process.env.SEI_SKILL_DIR || resolve(REPO, '..', 'sei-skill', 'skill'); +const DOCS_SKILLS = resolve(REPO, '.mintlify', 'skills'); +const DIST = resolve(REPO, 'dist', 'mintlify-skills'); + +const R = (p) => readFileSync(p, 'utf8'); +const has = (p) => existsSync(p); + +if (!has(SKILL)) { + console.error(`! sei-skill source not found at ${SKILL}`); + console.error(' Clone github.com/sei-protocol/sei-skill next to sei-docs, or set SEI_SKILL_DIR.'); + process.exit(1); +} + +// docs skill -> canonical sei-skill sources (master/variant + references). +const MAP = [ + { name: 'sei-contracts', sources: ['SKILL-CONTRACTS.md', 'references/evm/overview.md', 'references/evm/foundry.md', 'references/evm/hardhat.md', 'references/contracts/gas-optimization-sei.md', 'references/contracts/occ-aware-design.md', 'references/contracts/upgradeability.md', 'references/contracts/account-abstraction.md', 'references/contracts/contract-verification.md'] }, + { name: 'sei-precompiles', sources: ['references/precompiles/overview.md', 'references/precompiles/staking-distribution.md', 'references/precompiles/governance.md', 'references/precompiles/json-p256.md', 'references/pointers/overview.md', 'references/pointers/token-factory.md'] }, + { name: 'sei-frontend', sources: ['SKILL-FRONTEND.md', 'references/frontend/frontend-stack.md', 'references/addresses-wallets.md'] }, + { name: 'sei-security', sources: ['references/contracts/security.md', 'references/ecosystem/ai-tooling.md'] }, + { name: 'sei-nodes', sources: ['references/ecosystem/node-operations.md', 'references/ecosystem/validators.md', 'references/architecture.md'] }, + { name: 'sei-payments', sources: ['references/ecosystem/payments.md'] }, + { name: 'sei-bridges', sources: ['references/ecosystem/bridges.md', 'references/ecosystem/ibc-bridging.md'] }, + { name: 'sei-migration', sources: ['references/migration/from-ethereum.md', 'references/migration/from-solana.md'] }, +]; + +const PROMPT = (name, bar) => `You are flattening the canonical Sei skill source below into ONE self-contained Mintlify skill file for docs.sei.io. + +Produce a single SKILL.md for the skill "${name}": +- YAML frontmatter: name (= "${name}"), description (a ">"-folded "Use when ..." trigger paragraph), license: MIT, compatibility, metadata { author: Sei, version, intended-host: docs.sei.io, domain }. +- Body <= ~5000 tokens. Dense and Sei-specific: "Critical facts", code, "Common pitfalls", and a "Key docs" table. +- Link to live https://docs.sei.io/... pages (NOT references/*.md). Keep every canonical constant (addresses, chain IDs, EIDs, gas values, governance proposal numbers) verbatim; never invent an address or proposal number. +- Match or exceed the QUALITY BAR (the current docs skill) in correctness and concision. Do not reintroduce anything the source dropped (e.g. Axelar, LayerZero v1 API, native-oracle endorsement, overconfident Wormhole-EVM examples). + +${bar ? '== QUALITY BAR (current docs skill — match this) ==\n' + bar + '\n' : ''}== CANONICAL SOURCE (flatten this) ==\n`; + +const args = process.argv.slice(2); +const only = args.includes('--skill') ? args[args.indexOf('--skill') + 1] : null; +const write = args.includes('--write'); // also write generated SKILL.md into .mintlify/skills// +const SRC_REF = process.env.SEI_SKILL_REF || ''; + +// Stamp a GENERATED marker after the frontmatter so the artifact is clearly +// machine-generated. The skills-generated guard (CI) enforces this marker's presence, +// which is how "no hand-authored skill content in the docs" is kept true. +function stampGenerated(md) { + const banner = ``; + const fm = md.match(/^---\n[\s\S]*?\n---\n/); + return fm ? fm[0] + banner + '\n' + md.slice(fm[0].length) : banner + '\n' + md; +} + +mkdirSync(DIST, { recursive: true }); + +for (const m of MAP) { + if (only && m.name !== only) continue; + const present = m.sources.filter((s) => has(join(SKILL, s))); + const missing = m.sources.filter((s) => !has(join(SKILL, s))); + const bundle = present.map((s) => `\n\n<<< ${s} >>>\n` + R(join(SKILL, s))).join('\n'); + const barPath = join(DOCS_SKILLS, m.name, 'SKILL.md'); + const bar = has(barPath) ? R(barPath) : ''; + const outDir = join(DIST, m.name); + mkdirSync(outDir, { recursive: true }); + writeFileSync(join(outDir, 'SOURCE_BUNDLE.md'), bundle); + writeFileSync(join(outDir, 'PROMPT.md'), PROMPT(m.name, bar)); + console.log(`• ${m.name}: ${present.length} source(s)${missing.length ? `, ${missing.length} missing (${missing.join(', ')})` : ''}${bar ? ', quality-bar found' : ''}`); +} + +if (process.env.ANTHROPIC_API_KEY) { + console.log('\nANTHROPIC_API_KEY detected — generating SKILL.md per skill (review before copying)...'); + const { default: Anthropic } = await import('@anthropic-ai/sdk'); + const client = new Anthropic(); + for (const m of MAP) { + if (only && m.name !== only) continue; + const prompt = R(join(DIST, m.name, 'PROMPT.md')) + R(join(DIST, m.name, 'SOURCE_BUNDLE.md')); + const msg = await client.messages.create({ model: 'claude-opus-4-8', max_tokens: 8000, messages: [{ role: 'user', content: prompt }] }); + const text = msg.content.map((b) => (b.type === 'text' ? b.text : '')).join(''); + const skillMd = stampGenerated(text.replace(/^```(markdown)?\n?/, '').replace(/\n?```$/, '')); + writeFileSync(join(DIST, m.name, 'SKILL.md'), skillMd); + if (write) { + const dest = join(DOCS_SKILLS, m.name, 'SKILL.md'); + mkdirSync(dirname(dest), { recursive: true }); + writeFileSync(dest, skillMd); + } + console.log(` ✓ ${m.name}/SKILL.md${write ? ' (written into .mintlify/skills/)' : ''}`); + } +} else { + console.log('\nNo ANTHROPIC_API_KEY — emitted SOURCE_BUNDLE.md + PROMPT.md per skill.'); + console.log('Set ANTHROPIC_API_KEY to auto-generate (add --write to emit straight into .mintlify/skills/), or hand PROMPT.md + SOURCE_BUNDLE.md to an LLM.'); +} +console.log(`\nOutput: ${DIST}`); +console.log(write + ? 'Generated skills written into .mintlify/skills/ — review the diff before committing.' + : 'Review each dist/mintlify-skills//SKILL.md, then re-run with --write (or copy into .mintlify/skills//).'); diff --git a/snippets/skills-registry.jsx b/snippets/skills-registry.jsx new file mode 100644 index 0000000..a65297c --- /dev/null +++ b/snippets/skills-registry.jsx @@ -0,0 +1,321 @@ +export const SkillsRegistry = () => { + // --- Foundation skills hosted on docs.sei.io (.mintlify/skills//SKILL.md). + // All install together via `npx skills add https://docs.sei.io`. Keep this list in + // sync with the .mintlify/skills/ directory. --- + const SKILLS = [ + { + id: 'sei-contracts', + title: 'Smart Contracts', + domain: 'Contracts', + href: '/evm/evm-general', + desc: 'Foundry and Hardhat setup, the Sei gas model, OCC-aware contract design, and verifying on Seiscan via Sourcify.' + }, + { + id: 'sei-frontend', + title: 'Frontend', + domain: 'Frontend', + href: '/evm/building-a-frontend', + desc: 'wagmi + viem chain config, Sei Global Wallet, dual-address UX, and fast-finality patterns for 400ms blocks.' + }, + { + id: 'sei-precompiles', + title: 'Precompiles', + domain: 'Precompiles', + href: '/evm/precompiles/example-usage', + desc: 'Call Sei native precompiles — Bank, Staking, Governance, Oracle, and more — from Solidity and viem.' + }, + { + id: 'sei-nodes', + title: 'Nodes & Validators', + domain: 'Infrastructure', + href: '/node', + desc: 'Run full nodes and validators: state sync, snapshots, monitoring, and the SeiDB storage backend.' + }, + { + id: 'sei-payments', + title: 'Payments', + domain: 'Payments', + href: '/ai/x402', + desc: 'Accept and send payments on Sei with USDC and x402 HTTP-native micropayments.' + }, + { + id: 'sei-security', + title: 'Security', + domain: 'Security', + href: '/evm/debugging-contracts', + desc: 'Simulate-before-write, safe randomness, address-association checks, and AI-agent safety guardrails.' + }, + { + id: 'sei-bridges', + title: 'Bridges', + domain: 'Bridges', + href: '/evm/bridging/layerzero', + desc: 'Bridge assets to and from Sei — LayerZero V2 OFTs, Wormhole, and Circle CCTP v2 for native USDC.' + }, + { + id: 'sei-migration', + title: 'Migration', + domain: 'Migration', + href: '/evm/migrate-from-other-evms', + desc: 'Port EVM and Solana apps to Sei — the behavioral deltas that break a naive port, plus a Solana-to-Sei concept map.' + } + ]; + + const INSTALL_CMD = 'npx skills add https://docs.sei.io'; + const FILTERS = ['All', 'Contracts', 'Frontend', 'Precompiles', 'Infrastructure', 'Payments', 'Security', 'Bridges', 'Migration']; + + // --- Dark mode detection (Mintlify toggles a `dark` class on ) --- + const [isDark, setIsDark] = useState(false); + useEffect(() => { + const el = document.documentElement; + const update = () => setIsDark(el.classList.contains('dark')); + update(); + const obs = new MutationObserver(update); + obs.observe(el, { attributes: true, attributeFilter: ['class'] }); + return () => obs.disconnect(); + }, []); + + const [filter, setFilter] = useState('All'); + const [filterHover, setFilterHover] = useState(null); + + // --- Per-domain inline SVG icons (stateless; no images, so re-creation on + // render is harmless). currentColor inherits the maroon brand tint. --- + const Icon = ({ domain, size = 22 }) => { + const common = { + xmlns: 'http://www.w3.org/2000/svg', + width: size, + height: size, + viewBox: '0 0 24 24', + fill: 'none', + stroke: 'currentColor', + strokeWidth: 1.8, + strokeLinecap: 'round', + strokeLinejoin: 'round', + 'aria-hidden': true + }; + if (domain === 'Contracts') + return ( + + + + + ); + if (domain === 'Frontend') + return ( + + + + + ); + if (domain === 'Precompiles') + return ( + + + + + ); + if (domain === 'Infrastructure') + return ( + + + + + + ); + if (domain === 'Payments') + return ( + + + + + ); + if (domain === 'Security') + return ( + + + + + ); + if (domain === 'Bridges') + return ( + + + + + ); + if (domain === 'Migration') + return ( + + + + + ); + return ( + + + + ); + }; + + const CopyIcon = ({ size = 14 }) => ( + + ); + + const CheckIcon = ({ size = 14 }) => ( + + ); + + const ArrowRightIcon = ({ size = 14, style }) => ( + + ); + + // --- Skill card. Created once via lazy initializer so its identity is stable + // across parent re-renders (theme toggle / filter change), preserving the + // card's own hover + copy state. `isDark` arrives as a prop. See + // mintlify-jsx-snippet-rules. --- + const [SkillCard] = useState(() => ({ skill, isDark }) => { + const [hover, setHover] = useState(false); + const [copied, setCopied] = useState(false); + const [copyHover, setCopyHover] = useState(false); + const [linkHover, setLinkHover] = useState(false); + + const copy = async () => { + try { + await navigator.clipboard.writeText(INSTALL_CMD); + setCopied(true); + setTimeout(() => setCopied(false), 1600); + } catch (e) { + /* clipboard unavailable — no-op */ + } + }; + + const accent = isDark ? 'var(--sei-maroon-25)' : 'var(--sei-maroon-100)'; + const linkColor = isDark ? (linkHover ? 'var(--sei-cream)' : 'var(--sei-maroon-25)') : 'var(--sei-maroon-100)'; + + return ( +
setHover(true)} + onMouseLeave={() => setHover(false)} + className='flex flex-col h-full p-5 transition-all duration-200' + style={{ + backgroundColor: hover ? 'rgba(128,128,128,0.10)' : 'rgba(128,128,128,0.05)', + border: '1px solid rgba(128,128,128,0.20)', + borderRadius: '12px', + transform: hover ? 'translateY(-2px)' : 'none' + }}> +
+ + + +
+

+ {skill.title} +

+ + {skill.id} + +
+
+ +

+ {skill.desc} +

+ + + + +
+ ); + }); + + const visible = filter === 'All' ? SKILLS : SKILLS.filter((s) => s.domain === filter); + + return ( +
+ {/* --- Filter pills --- */} +
+ {FILTERS.map((f) => { + const active = filter === f; + const hovered = filterHover === f; + return ( + + ); + })} +
+ + {/* --- Grid --- */} +
+ {visible.map((skill) => ( + + ))} +
+ + {visible.length === 0 &&
No skills in this category yet.
} +
+ ); +};