mirror of
https://github.com/sveltejs/ai-tools.git
synced 2026-07-06 12:50:53 +08:00
Compare commits
234 Commits
@sveltejs/
...
improve-us
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
62c5865ae9 | ||
|
|
6b63f1565c | ||
|
|
4ba6ab893c | ||
|
|
931d959e2a | ||
|
|
d690939222 | ||
|
|
8b80666572 | ||
|
|
dc0e8428e5 | ||
|
|
e1e8476771 | ||
|
|
a91c80e44b | ||
|
|
6f7b24c584 | ||
|
|
b5ea3c10db | ||
|
|
504413c951 | ||
|
|
48230e8c47 | ||
|
|
e72a3d2c4a | ||
|
|
ea4ae25035 | ||
|
|
4c98732f5f | ||
|
|
1f88817cf0 | ||
|
|
87af64f4bc | ||
|
|
b55db13ac9 | ||
|
|
3e8ad5c47d | ||
|
|
78be819cbe | ||
|
|
0e7d5c3724 | ||
|
|
ca578583f2 | ||
|
|
9208570fe2 | ||
|
|
28aee8eea6 | ||
|
|
c05346626c | ||
|
|
add959fd02 | ||
|
|
cdb2a3eea8 | ||
|
|
a4bbdf92e1 | ||
|
|
d5570e23d1 | ||
|
|
f81c7a2dd5 | ||
|
|
b11cbbccb5 | ||
|
|
b17f1e75ce | ||
|
|
19a6c90ebb | ||
|
|
af573abb82 | ||
|
|
f27a7778c7 | ||
|
|
ff64389c68 | ||
|
|
ea0624cf41 | ||
|
|
4079808b03 | ||
|
|
43af0ac413 | ||
|
|
94d56fcaf5 | ||
|
|
4d0c1fdf3d | ||
|
|
5ddd4c11a9 | ||
|
|
31cc38e1c1 | ||
|
|
1fe5383582 | ||
|
|
a22bd3df84 | ||
|
|
0b846a8ae5 | ||
|
|
cac9adf8cb | ||
|
|
9045e618c2 | ||
|
|
42b2a44b4b | ||
|
|
71eb1f770f | ||
|
|
0482033c84 | ||
|
|
8d5382d50d | ||
|
|
ed1b018260 | ||
|
|
9289421cd7 | ||
|
|
60610c6ebf | ||
|
|
1672ef7f94 | ||
|
|
34ae757b74 | ||
|
|
ea9e3f425a | ||
|
|
3e991787f8 | ||
|
|
253f545c4d | ||
|
|
d9a45a38b8 | ||
|
|
b0d387ff36 | ||
|
|
daec272ff8 | ||
|
|
f2bda80b06 | ||
|
|
1c9fc91c21 | ||
|
|
24b9351a92 | ||
|
|
e70db40d3c | ||
|
|
7053cfcc2d | ||
|
|
2a640ba716 | ||
|
|
8273c6cba7 | ||
|
|
dc039665d8 | ||
|
|
9d4bf59b0c | ||
|
|
e528324785 | ||
|
|
bb41d4a4cc | ||
|
|
24d22979ce | ||
|
|
d4fe086517 | ||
|
|
30dc2eba84 | ||
|
|
ae92b84ffa | ||
|
|
eecaf8cd5a | ||
|
|
f1c72ae73c | ||
|
|
02172d68cf | ||
|
|
efd1d94c01 | ||
|
|
e347cc8caa | ||
|
|
15677b8ca4 | ||
|
|
3a8e488a73 | ||
|
|
1555c67a0f | ||
|
|
4cbe859322 | ||
|
|
a100bbb9be | ||
|
|
4344e09ce3 | ||
|
|
5fc108cf76 | ||
|
|
740a08eb35 | ||
|
|
d054d48d6b | ||
|
|
4cdd419cd9 | ||
|
|
f1ff4d5862 | ||
|
|
6cbc72247e | ||
|
|
98be540b18 | ||
|
|
2082ce91bc | ||
|
|
9e2db4a7fa | ||
|
|
fe869d7a2c | ||
|
|
31ce09551c | ||
|
|
20bfbe09e3 | ||
|
|
e3794491a4 | ||
|
|
c1678b2f36 | ||
|
|
a8af3c72ca | ||
|
|
534a72cae7 | ||
|
|
3b301d7d9c | ||
|
|
33a0e17ee1 | ||
|
|
bf5f31c867 | ||
|
|
62abaacbd3 | ||
|
|
87fab2d884 | ||
|
|
9cf50c9b62 | ||
|
|
9a43aaf100 | ||
|
|
c0477385b8 | ||
|
|
db283da593 | ||
|
|
7d7547f6e2 | ||
|
|
0360d00955 | ||
|
|
65d403af1e | ||
|
|
d794d6bec3 | ||
|
|
ec9c5b3415 | ||
|
|
b508a4ea49 | ||
|
|
044f0988b9 | ||
|
|
c5c6ba6580 | ||
|
|
fb2240d60c | ||
|
|
469b2071e7 | ||
|
|
fc39b44859 | ||
|
|
e12a0c90ab | ||
|
|
7234e64967 | ||
|
|
ef5241cbc2 | ||
|
|
9a74df198d | ||
|
|
f1280b9876 | ||
|
|
132943db3b | ||
|
|
5ed1454e2c | ||
|
|
bd072bd324 | ||
|
|
c35be898da | ||
|
|
b960301ced | ||
|
|
43408f5504 | ||
|
|
bf4dcda7e1 | ||
|
|
35691c464b | ||
|
|
a5decb4cf3 | ||
|
|
cb9764c234 | ||
|
|
3fbc786383 | ||
|
|
3b680232a0 | ||
|
|
c5c08ccd13 | ||
|
|
4ac35bf258 | ||
|
|
ecbbf70d98 | ||
|
|
aaac49cdef | ||
|
|
558d964919 | ||
|
|
73d7625b3c | ||
|
|
c7060c8bdb | ||
|
|
ef2d569934 | ||
|
|
7ba57b45ae | ||
|
|
fe393bf480 | ||
|
|
a63deba99d | ||
|
|
668a2e4481 | ||
|
|
04c82875f3 | ||
|
|
84601f9ab0 | ||
|
|
e01a050017 | ||
|
|
5920f7482f | ||
|
|
fa90a2be8d | ||
|
|
73bf0c3782 | ||
|
|
11cd2447fc | ||
|
|
8785ad224c | ||
|
|
75e676d928 | ||
|
|
5b16bdd80b | ||
|
|
f3ee4ed59c | ||
|
|
725f785766 | ||
|
|
485e60e245 | ||
|
|
480bfca557 | ||
|
|
06f9fc6d63 | ||
|
|
f1f85d2445 | ||
|
|
b9c0a011e2 | ||
|
|
b92dd95dee | ||
|
|
99537cfa25 | ||
|
|
f93a6cee60 | ||
|
|
e8989db548 | ||
|
|
cb316c5b3e | ||
|
|
7c762109b6 | ||
|
|
e3dbb5c098 | ||
|
|
03ce6c50c0 | ||
|
|
273c78092d | ||
|
|
891fae8127 | ||
|
|
fa969feb28 | ||
|
|
1dbd93a1ce | ||
|
|
3bb71f3963 | ||
|
|
a881cb5938 | ||
|
|
03859141ed | ||
|
|
f747c4ac65 | ||
|
|
1916c410e6 | ||
|
|
1e7ebeaf5b | ||
|
|
f82ceac79d | ||
|
|
cde6d700e6 | ||
|
|
522fae6017 | ||
|
|
1f94d33dc9 | ||
|
|
7ada706deb | ||
|
|
796c38ee23 | ||
|
|
937216e1de | ||
|
|
6a23b9c87f | ||
|
|
8064a4f5cf | ||
|
|
005b9d45bd | ||
|
|
12a80515a0 | ||
|
|
7acbaad478 | ||
|
|
55f9009a77 | ||
|
|
02042daa02 | ||
|
|
eb5444e3b6 | ||
|
|
c3134bdfde | ||
|
|
334f9330e7 | ||
|
|
b16448b6df | ||
|
|
b0888d6ac3 | ||
|
|
6fc0419fc5 | ||
|
|
d138349c46 | ||
|
|
e1a1cb1d84 | ||
|
|
e723198db0 | ||
|
|
7dedb277be | ||
|
|
de45c1b015 | ||
|
|
94f12964cb | ||
|
|
7366dad0e9 | ||
|
|
22aaad43f3 | ||
|
|
1332513847 | ||
|
|
988da97816 | ||
|
|
b086e634fe | ||
|
|
fd72afc2a3 | ||
|
|
5736e853e6 | ||
|
|
0f2747423b | ||
|
|
a49773f0ff | ||
|
|
56b47f1108 | ||
|
|
207d1f80bf | ||
|
|
0cda036ab6 | ||
|
|
8483bd672d | ||
|
|
8414ffbcc8 | ||
|
|
5798b50ceb | ||
|
|
e560932211 | ||
|
|
9504e6bac9 | ||
|
|
7086e8e55f |
5
.changeset/clear-buckets-remain.md
Normal file
5
.changeset/clear-buckets-remain.md
Normal file
@@ -0,0 +1,5 @@
|
||||
---
|
||||
'@sveltejs/mcp': patch
|
||||
---
|
||||
|
||||
fix: prevent `imported_runes` suggestion from being added for libs that are not svelte
|
||||
@@ -7,5 +7,5 @@
|
||||
"access": "public",
|
||||
"baseBranch": "main",
|
||||
"updateInternalDependencies": "patch",
|
||||
"ignore": []
|
||||
"ignore": ["!@sveltejs/mcp"]
|
||||
}
|
||||
|
||||
5
.changeset/thirty-fans-stay.md
Normal file
5
.changeset/thirty-fans-stay.md
Normal file
@@ -0,0 +1,5 @@
|
||||
---
|
||||
'@sveltejs/mcp': minor
|
||||
---
|
||||
|
||||
Adds LLM-condensed documentation for smaller context usage
|
||||
@@ -1,2 +1,4 @@
|
||||
.claude
|
||||
.github
|
||||
.github
|
||||
.vscode
|
||||
documentation/
|
||||
4
.cocominify
Normal file
4
.cocominify
Normal file
@@ -0,0 +1,4 @@
|
||||
packages/mcp-server/src/use_cases.json
|
||||
packages/mcp-server/src/mcp/autofixers
|
||||
packages/mcp-server/src/distilled.json
|
||||
packages/mcp-server/src/distilled-verification.json
|
||||
6
.github/workflows/check.yml
vendored
6
.github/workflows/check.yml
vendored
@@ -13,15 +13,15 @@ jobs:
|
||||
|
||||
steps:
|
||||
- name: Checkout Repository
|
||||
uses: actions/checkout@v4
|
||||
uses: actions/checkout@v5
|
||||
|
||||
- name: Setup pnpm
|
||||
uses: pnpm/action-setup@v4
|
||||
with:
|
||||
version: 10.17.1
|
||||
version: 10.18.2
|
||||
|
||||
- name: Setup Node.js
|
||||
uses: actions/setup-node@v4
|
||||
uses: actions/setup-node@v6
|
||||
with:
|
||||
node-version: '22'
|
||||
cache: 'pnpm'
|
||||
|
||||
6
.github/workflows/lint.yml
vendored
6
.github/workflows/lint.yml
vendored
@@ -13,15 +13,15 @@ jobs:
|
||||
|
||||
steps:
|
||||
- name: Checkout Repository
|
||||
uses: actions/checkout@v4
|
||||
uses: actions/checkout@v5
|
||||
|
||||
- name: Setup pnpm
|
||||
uses: pnpm/action-setup@v4
|
||||
with:
|
||||
version: 10.17.1
|
||||
version: 10.18.2
|
||||
|
||||
- name: Setup Node.js
|
||||
uses: actions/setup-node@v4
|
||||
uses: actions/setup-node@v6
|
||||
with:
|
||||
node-version: '22'
|
||||
cache: 'pnpm'
|
||||
|
||||
40
.github/workflows/publish-mcp.yml
vendored
Normal file
40
.github/workflows/publish-mcp.yml
vendored
Normal file
@@ -0,0 +1,40 @@
|
||||
name: Publish to MCP Registry
|
||||
|
||||
on:
|
||||
workflow_call:
|
||||
secrets:
|
||||
MCP_KEY:
|
||||
required: true
|
||||
|
||||
jobs:
|
||||
publish-mcp:
|
||||
name: Publish to MCP Registry
|
||||
runs-on: ubuntu-latest
|
||||
steps:
|
||||
- name: checkout
|
||||
uses: actions/checkout@v5
|
||||
|
||||
- name: Publish to MCP Registry
|
||||
working-directory: packages/mcp-stdio
|
||||
env:
|
||||
MCP_KEY: ${{ secrets.MCP_KEY }}
|
||||
run: |
|
||||
NAME=mcp-publisher_1.2.3_$(uname -s | tr '[:upper:]' '[:lower:]')_$(uname -m | sed 's/x86_64/amd64/;s/aarch64/arm64/').tar.gz
|
||||
# Download MCP Publisher pinned to v1.2.3 using latest https for security and save it to a file named mcp-publisher.tar.gz
|
||||
curl --proto '=https' --proto-redir '=https' --tlsv1.2 -fL "https://github.com/modelcontextprotocol/registry/releases/download/v1.2.3/$NAME" -O
|
||||
|
||||
# Verify the SHA256 checksum of the downloaded file
|
||||
sha256sum --ignore-missing -c ./checksums/registry_1.2.3_checksums.txt
|
||||
|
||||
# Extract the tarball
|
||||
mkdir tmp
|
||||
tar -xzf $NAME --no-same-owner --no-same-permissions -C tmp
|
||||
|
||||
# Install the MCP Publisher binary
|
||||
install -m 0755 tmp/mcp-publisher .
|
||||
|
||||
# Login using DNS
|
||||
./mcp-publisher login dns --domain svelte.dev --private-key "${MCP_KEY}"
|
||||
|
||||
# Publish to MCP Registry
|
||||
./mcp-publisher publish
|
||||
15
.github/workflows/release.yml
vendored
15
.github/workflows/release.yml
vendored
@@ -16,6 +16,8 @@ jobs:
|
||||
if: github.repository == 'sveltejs/mcp'
|
||||
name: Release
|
||||
runs-on: ${{ matrix.os }}
|
||||
outputs:
|
||||
published: ${{ steps.changesets.outputs.published }}
|
||||
strategy:
|
||||
matrix:
|
||||
# pseudo-matrix for convenience, NEVER use more than a single combination
|
||||
@@ -27,7 +29,7 @@ jobs:
|
||||
with:
|
||||
# This makes Actions fetch all Git history so that Changesets can generate changelogs with the correct commits
|
||||
fetch-depth: 0
|
||||
- uses: actions/setup-node@v5
|
||||
- uses: actions/setup-node@v6
|
||||
with:
|
||||
node-version: ${{ matrix.node }}
|
||||
package-manager-cache: false # pnpm is not installed yet
|
||||
@@ -37,7 +39,7 @@ jobs:
|
||||
PNPM_VER=$(jq -r '.packageManager | if .[0:5] == "pnpm@" then .[5:] else "packageManager in package.json does not start with pnpm@\n" | halt_error(1) end' package.json)
|
||||
echo installing pnpm version $PNPM_VER
|
||||
npm i -g pnpm@$PNPM_VER
|
||||
- uses: actions/setup-node@v5
|
||||
- uses: actions/setup-node@v6
|
||||
with:
|
||||
node-version: ${{ matrix.node }}
|
||||
package-manager-cache: true # caches pnpm via packageManager field in package.json
|
||||
@@ -51,8 +53,17 @@ jobs:
|
||||
# pinned for security, always review third party action code before updating
|
||||
uses: changesets/action@e0145edc7d9d8679003495b11f87bd8ef63c0cba # v1.5.3
|
||||
with:
|
||||
# This expects you to have a script called changeset:version version that calls changeset version and updated what it needs to be updated
|
||||
version: pnpm changeset:version
|
||||
# This expects you to have a script called release which does a build for your packages and calls changeset publish
|
||||
publish: pnpm release
|
||||
env:
|
||||
GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}
|
||||
NPM_CONFIG_PROVENANCE: true
|
||||
|
||||
publish-mcp:
|
||||
needs: release
|
||||
if: needs.release.outputs.published == 'true'
|
||||
uses: ./.github/workflows/publish-mcp.yml
|
||||
secrets:
|
||||
MCP_KEY: ${{ secrets.MCP_KEY }}
|
||||
|
||||
6
.github/workflows/test.yml
vendored
6
.github/workflows/test.yml
vendored
@@ -13,15 +13,15 @@ jobs:
|
||||
|
||||
steps:
|
||||
- name: Checkout Repository
|
||||
uses: actions/checkout@v4
|
||||
uses: actions/checkout@v5
|
||||
|
||||
- name: Setup pnpm
|
||||
uses: pnpm/action-setup@v4
|
||||
with:
|
||||
version: 10.17.1
|
||||
version: 10.18.2
|
||||
|
||||
- name: Setup Node.js
|
||||
uses: actions/setup-node@v4
|
||||
uses: actions/setup-node@v6
|
||||
with:
|
||||
node-version: '22'
|
||||
cache: 'pnpm'
|
||||
|
||||
78
.github/workflows/update-prompt-docs.yml
vendored
Normal file
78
.github/workflows/update-prompt-docs.yml
vendored
Normal file
@@ -0,0 +1,78 @@
|
||||
name: Update Prompt Documentation
|
||||
|
||||
on:
|
||||
push:
|
||||
branches:
|
||||
- main
|
||||
paths:
|
||||
- 'packages/mcp-server/src/mcp/handlers/prompts/**'
|
||||
|
||||
permissions:
|
||||
contents: write
|
||||
pull-requests: write
|
||||
|
||||
jobs:
|
||||
update-docs:
|
||||
# prevents this action from running on forks
|
||||
if: github.repository == 'sveltejs/mcp'
|
||||
name: Update Prompt Documentation
|
||||
runs-on: ubuntu-latest
|
||||
steps:
|
||||
- name: Checkout
|
||||
uses: actions/checkout@v5
|
||||
with:
|
||||
fetch-depth: 0
|
||||
|
||||
- name: Setup Node.js
|
||||
uses: actions/setup-node@v6
|
||||
with:
|
||||
node-version: 24
|
||||
package-manager-cache: false # pnpm is not installed yet
|
||||
|
||||
- name: Install pnpm
|
||||
shell: bash
|
||||
run: |
|
||||
PNPM_VER=$(jq -r '.packageManager | if .[0:5] == "pnpm@" then .[5:] else "packageManager in package.json does not start with pnpm@\n" | halt_error(1) end' package.json)
|
||||
echo installing pnpm version $PNPM_VER
|
||||
npm i -g pnpm@$PNPM_VER
|
||||
|
||||
- name: Setup Node.js with pnpm cache
|
||||
uses: actions/setup-node@v6
|
||||
with:
|
||||
node-version: 24
|
||||
package-manager-cache: true # caches pnpm via packageManager field in package.json
|
||||
|
||||
- name: Install dependencies
|
||||
run: pnpm install --frozen-lockfile --prefer-offline --ignore-scripts
|
||||
|
||||
- name: Generate prompt documentation
|
||||
run: pnpm generate-prompt-docs
|
||||
|
||||
- name: Check for changes
|
||||
id: git-check
|
||||
run: |
|
||||
git diff --exit-code documentation/docs/30-capabilities/30-prompts.md || echo "changed=true" >> $GITHUB_OUTPUT
|
||||
|
||||
- name: Create Pull Request
|
||||
if: steps.git-check.outputs.changed == 'true'
|
||||
uses: peter-evans/create-pull-request@v7
|
||||
with:
|
||||
token: ${{ secrets.GITHUB_TOKEN }}
|
||||
commit-message: 'docs: update prompts documentation'
|
||||
branch: docs/update-prompt-docs
|
||||
delete-branch: true
|
||||
title: 'docs: update prompt documentation'
|
||||
body: |
|
||||
## Summary
|
||||
Automatically generated documentation update for MCP prompts.
|
||||
|
||||
This PR was triggered by changes to the prompts folder in `packages/mcp-server/src/mcp/handlers/prompts/`.
|
||||
|
||||
## Changes
|
||||
- Updated `documentation/docs/30-capabilities/30-prompts.md` with latest prompt definitions
|
||||
|
||||
## Generated by
|
||||
GitHub Action: Update Prompt Documentation
|
||||
labels: |
|
||||
documentation
|
||||
automated
|
||||
@@ -11,4 +11,7 @@ bun.lockb
|
||||
/**/.svelte-kit/*
|
||||
|
||||
# Claude Code
|
||||
.claude/
|
||||
.claude/
|
||||
|
||||
# MCP Server Markdown Files
|
||||
packages/mcp-server/**/*.md
|
||||
60
.vscode/mcp-snippets.code-snippets
vendored
60
.vscode/mcp-snippets.code-snippets
vendored
@@ -23,11 +23,69 @@
|
||||
"scope": "javascript,typescript",
|
||||
"prefix": "!autofixer",
|
||||
"body": [
|
||||
"import type { Autofixer } from '.';",
|
||||
"import type { Autofixer } from './index.js';",
|
||||
"export const ${1:autofixer_name}: Autofixer = {",
|
||||
"\t$0",
|
||||
"};",
|
||||
],
|
||||
"description": "Create a setup export for an autofixer",
|
||||
},
|
||||
"Prompt Generator": {
|
||||
"scope": "javascript,typescript",
|
||||
"prefix": "!prompt",
|
||||
"body": [
|
||||
"import type { SvelteMcp } from '../../index.js';",
|
||||
"",
|
||||
"/**",
|
||||
" * Function that actually generates the prompt string. You can use this in the MCP server handler to generate the prompt, it can accept arguments",
|
||||
" * if needed (it will always be invoked manually so it's up to you to provide the arguments).",
|
||||
" */",
|
||||
"function ${1:prompt_name}() {",
|
||||
"\treturn `$0`;",
|
||||
"}",
|
||||
"",
|
||||
"/**",
|
||||
" * This function is used to generate the prompt to update the docs in the script `/scripts/update-docs-prompts.ts` it should use the default export",
|
||||
" * function and pass in the arguments. Since it will be included in the documentation if it's an argument that the MCP will expose it should",
|
||||
" * be in the format [NAME_OF_THE_ARGUMENT] to signal the user that it can substitute it.",
|
||||
" * ",
|
||||
" * The name NEEDS to be `generate_for_docs`.",
|
||||
" */",
|
||||
"export async function generate_for_docs() {",
|
||||
"\treturn ${1:prompt_name}();",
|
||||
"}",
|
||||
"",
|
||||
"/**",
|
||||
" * Human readable description of what the prompt does. It will be included in the documentation.",
|
||||
" * ",
|
||||
" * The name NEEDS to be `docs_description`.",
|
||||
" */",
|
||||
"export const docs_description = '';",
|
||||
"",
|
||||
"export function setup_${1:prompt_name}(server: SvelteMcp) {",
|
||||
"\tserver.prompt(",
|
||||
"\t\t{",
|
||||
"\t\t\tname: '${1:prompt_name}',",
|
||||
"\t\t\ttitle: '${2:title}',",
|
||||
"\t\t\tdescription:",
|
||||
"\t\t\t\t'${3:llm_description}',",
|
||||
"\t\t},",
|
||||
"\t\tasync () => {",
|
||||
"\t\t\treturn {",
|
||||
"\t\t\t\tmessages: [",
|
||||
"\t\t\t\t\t{",
|
||||
"\t\t\t\t\t\trole: 'assistant',",
|
||||
"\t\t\t\t\t\tcontent: {",
|
||||
"\t\t\t\t\t\t\ttype: 'text',",
|
||||
"\t\t\t\t\t\t\ttext: ${1:prompt_name}(),",
|
||||
"\t\t\t\t\t\t},",
|
||||
"\t\t\t\t\t},",
|
||||
"\t\t\t\t],",
|
||||
"\t\t\t};",
|
||||
"\t\t},",
|
||||
"\t);",
|
||||
"}",
|
||||
],
|
||||
"description": "Create a setup export for a prompt generator",
|
||||
},
|
||||
}
|
||||
|
||||
302
CLAUDE.md
302
CLAUDE.md
@@ -2,72 +2,234 @@
|
||||
|
||||
This file provides guidance to Claude Code (claude.ai/code) when working with code in this repository.
|
||||
|
||||
## Development Commands
|
||||
## Project Structure
|
||||
|
||||
This is a Svelte MCP (Model Context Protocol) server implementation that includes both SvelteKit web interface and MCP server functionality.
|
||||
This is a monorepo containing the official Svelte MCP (Model Context Protocol) server implementation with multiple packages:
|
||||
|
||||
- **`packages/mcp-server/`** - Core MCP server logic with tools, prompts, and autofixers
|
||||
- **`packages/mcp-stdio/`** - CLI wrapper for running MCP server via stdio transport (`@sveltejs/mcp` on npm)
|
||||
- **`packages/mcp-schema/`** - Shared database schema definitions using Drizzle ORM
|
||||
- **`apps/mcp-remote/`** - SvelteKit web application for remote HTTP MCP access and documentation comparison
|
||||
|
||||
## Development Commands
|
||||
|
||||
### Setup
|
||||
|
||||
```bash
|
||||
pnpm i
|
||||
cp .env.example .env
|
||||
# Set the VOYAGE_API_KEY for embeddings support in .env
|
||||
cp apps/mcp-remote/.env.example apps/mcp-remote/.env
|
||||
# Set DATABASE_URL, DATABASE_TOKEN, and VOYAGE_API_KEY (optional) in apps/mcp-remote/.env
|
||||
pnpm dev
|
||||
```
|
||||
|
||||
### Common Commands
|
||||
|
||||
- `pnpm dev` - Start SvelteKit development server
|
||||
- `pnpm build` - Build the application for production
|
||||
- `pnpm start` - Run the MCP server (Node.js entry point)
|
||||
- `pnpm check` - Run Svelte type checking
|
||||
- `pnpm check:watch` - Run type checking in watch mode
|
||||
- `pnpm dev` - Start SvelteKit development server (apps/mcp-remote)
|
||||
- `pnpm build` - Build all packages
|
||||
- `pnpm check` - Run type checking across all packages
|
||||
- `pnpm lint` - Run prettier check and eslint
|
||||
- `pnpm lint:fix` - Auto-fix linting issues
|
||||
- `pnpm format` - Format code with prettier
|
||||
- `pnpm test` - Run unit tests with vitest
|
||||
- `pnpm test:watch` - Run tests in watch mode
|
||||
|
||||
### Database Commands (Drizzle ORM)
|
||||
### Database Commands (apps/mcp-remote)
|
||||
|
||||
- `pnpm db:push` - Push schema changes to database
|
||||
- `pnpm db:push` - Push schema changes to Turso database
|
||||
- `pnpm db:generate` - Generate migration files
|
||||
- `pnpm db:migrate` - Run migrations
|
||||
- `pnpm db:studio` - Open Drizzle Studio
|
||||
|
||||
### Documentation Generation Commands (packages/mcp-server)
|
||||
|
||||
#### Generate Use Case Summaries
|
||||
|
||||
Generate short descriptions of when each documentation section would be useful:
|
||||
|
||||
- `pnpm generate-summaries` - Generate use case summaries for all sections
|
||||
- `pnpm generate-summaries:dry-run` - Preview what would be generated without making API calls
|
||||
- `pnpm generate-summaries:debug` - Process only 2 sections for debugging
|
||||
|
||||
#### Generate Distilled Documentation
|
||||
|
||||
Generate condensed versions of the documentation to reduce context size:
|
||||
|
||||
- `pnpm generate-distilled` - Generate distilled versions for all sections
|
||||
- `pnpm generate-distilled:dry-run` - Preview what would be generated without making API calls
|
||||
- `pnpm generate-distilled:debug` - Process only 2 sections for debugging
|
||||
|
||||
#### Verify Distilled Documentation
|
||||
|
||||
Verify the accuracy of distilled summaries against original documentation:
|
||||
|
||||
- `pnpm verify-distilled` - Verify all distilled summaries for accuracy
|
||||
- `pnpm show-verification-errors` - Display all sections that failed verification
|
||||
|
||||
The verification workflow:
|
||||
|
||||
1. Run `pnpm verify-distilled` to verify all distilled summaries
|
||||
- Loads `distilled.json` containing summaries and original content
|
||||
- Uses the Anthropic Batch API to send each summary and original content to Claude
|
||||
- Claude evaluates whether the summary is accurate or contains errors/omissions
|
||||
- Generates `distilled-verification.json` with results (ACCURATE/NOT_ACCURATE) and reasoning
|
||||
- Outputs statistics about accuracy rates
|
||||
2. Run `pnpm show-verification-errors` to see detailed list of all sections that are NOT_ACCURATE
|
||||
- Displays each problematic section with its reasoning
|
||||
- Shows summary statistics
|
||||
|
||||
**Note:** All documentation generation and verification commands require `ANTHROPIC_API_KEY` to be set in `packages/mcp-server/.env`
|
||||
|
||||
### Documentation Updates
|
||||
|
||||
- `pnpm generate-prompt-docs` - Update documentation/docs/30-capabilities/30-prompts.md based on prompt handlers
|
||||
|
||||
### Publishing Commands
|
||||
|
||||
- `pnpm release` - Build and publish to npm using changesets
|
||||
- `pnpm changeset:version` - Update versions and sync package.json with server.json
|
||||
|
||||
### Development Tools
|
||||
|
||||
- `pnpm inspect` - Launch MCP inspector at http://localhost:6274/ for testing tools and prompts
|
||||
|
||||
## Architecture
|
||||
|
||||
### MCP Server Implementation
|
||||
### MCP Server Implementation (`packages/mcp-server/src/mcp/`)
|
||||
|
||||
The core MCP server is implemented in `src/lib/mcp/index.ts` using the `tmcp` library with:
|
||||
The core MCP server is implemented using the `tmcp` library with:
|
||||
|
||||
- **Transport Layers**: Both HTTP (`HttpTransport`) and STDIO (`StdioTransport`) support
|
||||
- **Transport Layers**: Both HTTP (`@tmcp/transport-http`) and STDIO (`@tmcp/transport-stdio`) support
|
||||
- **Schema Validation**: Uses Valibot with `ValibotJsonSchemaAdapter`
|
||||
- **Main Tool**: `svelte-autofixer` - analyzes Svelte code and provides suggestions/fixes
|
||||
- **Server Definition**: `packages/mcp-server/src/mcp/index.ts` exports the configured server instance
|
||||
|
||||
### Code Analysis Engine
|
||||
### MCP Tools (`packages/mcp-server/src/mcp/handlers/tools/`)
|
||||
|
||||
Located in `src/lib/server/analyze/`:
|
||||
#### get-documentation
|
||||
|
||||
- **Parser** (`parse.ts`): Uses `svelte-eslint-parser` and TypeScript parser to analyze Svelte components
|
||||
Retrieves documentation content for Svelte 5 or SvelteKit sections. Supports:
|
||||
|
||||
- Single or multiple section names
|
||||
- Search by title (e.g., "$state") or file path (e.g., "cli/overview")
|
||||
- Optional distilled versions to optimize context size (default: true)
|
||||
- Automatically loads distilled content from `distilled.json` when available
|
||||
|
||||
#### list-sections
|
||||
|
||||
Lists all available Svelte 5 and SvelteKit documentation sections with:
|
||||
|
||||
- Section titles and file paths
|
||||
- "use_cases" metadata describing when each section is useful
|
||||
- Helps LLMs determine which documentation to fetch
|
||||
|
||||
#### svelte-autofixer
|
||||
|
||||
Analyzes Svelte component or module code and returns suggestions/fixes:
|
||||
|
||||
- Runs compilation checks
|
||||
- Runs ESLint checks
|
||||
- Runs custom autofixer visitors
|
||||
- Requires `code`, `desired_svelte_version` (4 or 5), and optional `filename`
|
||||
- Returns issues, suggestions, and whether another tool call is needed
|
||||
|
||||
#### playground-link
|
||||
|
||||
Generates a Svelte Playground link from code snippets:
|
||||
|
||||
- Accepts multiple files (must include `App.svelte` as entry point)
|
||||
- Optional Tailwind CSS support
|
||||
- Compresses and encodes files into URL hash
|
||||
|
||||
### MCP Prompts (`packages/mcp-server/src/mcp/handlers/prompts/`)
|
||||
|
||||
#### svelte-task
|
||||
|
||||
A prompt template that instructs LLMs on how to:
|
||||
|
||||
- Query available documentation sections
|
||||
- Use the autofixer iteratively until no issues remain
|
||||
- Generate playground links when appropriate
|
||||
- Follows best practices for Svelte development
|
||||
|
||||
Prompts are defined with:
|
||||
|
||||
- `generate_for_docs()` - Function to generate prompt text for documentation
|
||||
- `docs_description` - Human-readable description
|
||||
- Prompt handler - Server registration logic with schema and completions
|
||||
|
||||
### MCP Resources (`packages/mcp-server/src/mcp/handlers/resources/`)
|
||||
|
||||
#### Svelte-Doc-Section
|
||||
|
||||
URI template: `svelte://{/slug*}.md`
|
||||
|
||||
Lists and fetches individual documentation sections:
|
||||
|
||||
- Lists all sections with metadata (title, use_cases, URI)
|
||||
- Provides completions for slug parameter
|
||||
- Fetches content from svelte.dev/docs/
|
||||
|
||||
### Code Analysis & Parsing (`packages/mcp-server/src/parse/`)
|
||||
|
||||
- **Parser** (`parse.ts`): Uses `svelte-eslint-parser` and TypeScript parser
|
||||
- **Scope Analysis**: Tracks variables, references, and scopes across the AST
|
||||
- **Rune Detection**: Identifies Svelte 5 runes (`$state`, `$effect`, `$derived`, etc.)
|
||||
|
||||
### Autofixer System
|
||||
### Autofixer System (`packages/mcp-server/src/mcp/autofixers/`)
|
||||
|
||||
- **Autofixers** (`src/lib/mcp/autofixers.ts`): Visitor pattern implementations for code analysis
|
||||
- **Walker Utility** (`src/lib/index.ts`): Enhanced AST walking with visitor mixing capabilities
|
||||
- **Current Autofixer**: `assign_in_effect` - detects assignments to `$state` variables inside `$effect` blocks
|
||||
The autofixer system uses a visitor pattern to analyze Svelte components:
|
||||
|
||||
### Database Layer
|
||||
#### Core Autofixer Files
|
||||
|
||||
- **ORM**: Drizzle with SQLite backend
|
||||
- **Schema** (`src/lib/server/db/schema.ts`): Vector table for embeddings support
|
||||
- **Utils** (`src/lib/server/db/utils.ts`): Custom float32 array type for vectors
|
||||
- **`add-compile-issues.ts`** - Runs Svelte compiler and adds compilation errors
|
||||
- **`add-eslint-issues.ts`** - Runs ESLint with svelte-eslint-parser
|
||||
- **`add-autofixers-issues.ts`** - Orchestrates all custom autofixer visitors
|
||||
|
||||
### SvelteKit Integration
|
||||
#### AST Walking (`ast/`)
|
||||
|
||||
- **`walk.ts`** - Enhanced AST walking with visitor mixing capabilities using zimmerframe
|
||||
- **`utils.ts`** - Utility functions for AST manipulation
|
||||
|
||||
#### Autofixer Visitors (`visitors/`)
|
||||
|
||||
Each visitor checks for specific issues:
|
||||
|
||||
- **`assign-in-effect.ts`** - Detects assignments to `$state` variables inside `$effect` blocks
|
||||
- **`derived-with-function.ts`** - Suggests using `$derived.by()` when passing a function to `$derived()`
|
||||
- **`imported-runes.ts`** - Detects attempts to import runes (they're globals)
|
||||
- **`read-state-with-dollar.ts`** - Detects reading `$state` variables with `$` prefix in Svelte 5
|
||||
- **`suggest-attachments.ts`** - Suggests attachments API for bind:this and actions
|
||||
- **`use-runes-instead-of-store.ts`** - Suggests migrating from stores to runes in Svelte 5
|
||||
- **`wrong-property-access-state.ts`** - Detects incorrect property access patterns on `$state` variables
|
||||
|
||||
### Database Layer (`packages/mcp-schema/`)
|
||||
|
||||
- **ORM**: Drizzle with LibSQL/Turso backend
|
||||
- **Schema** (`src/schema.js`):
|
||||
- `content` - Original documentation with embeddings
|
||||
- `content_distilled` - Distilled/condensed documentation with embeddings
|
||||
- `distillations` - Stored distilled documentation versions
|
||||
- `distillation_jobs` - Batch processing job tracking
|
||||
- **Utils** (`src/utils.js`): Custom `float_32_array` type for vector embeddings
|
||||
|
||||
### SvelteKit Web App (`apps/mcp-remote/`)
|
||||
|
||||
Remote HTTP MCP server with documentation comparison interface:
|
||||
|
||||
- **Hooks** (`src/hooks.server.ts`): Integrates MCP HTTP transport with SvelteKit requests
|
||||
- **Routes**: Basic web interface for the MCP server
|
||||
- **Routes**:
|
||||
- `/` - Landing page
|
||||
- `/compare/use_cases` - Compare use case summaries with original docs
|
||||
- `/compare/distilled` - Compare distilled docs with original docs
|
||||
- **MCP Setup** (`src/lib/mcp/index.ts`): HTTP transport configuration
|
||||
|
||||
### CLI Package (`packages/mcp-stdio/`)
|
||||
|
||||
Standalone npm package (`@sveltejs/mcp`) that:
|
||||
|
||||
- Runs the MCP server via stdio transport
|
||||
- Built with tsdown for optimal bundling
|
||||
- Externalizes `eslint` dependency (required at runtime)
|
||||
- Published to npm registry and MCP registry
|
||||
|
||||
## Key Dependencies
|
||||
|
||||
@@ -75,27 +237,87 @@ Located in `src/lib/server/analyze/`:
|
||||
- **@tmcp/transport-http** & **@tmcp/transport-stdio**: Transport layers
|
||||
- **@tmcp/adapter-valibot**: Schema validation adapter
|
||||
- **svelte-eslint-parser**: Svelte component parsing
|
||||
- **typescript-eslint**: TypeScript AST parsing
|
||||
- **zimmerframe**: AST walking utilities
|
||||
- **drizzle-orm**: Database ORM with SQLite
|
||||
- **drizzle-orm**: Database ORM with LibSQL
|
||||
- **valibot**: Schema validation library
|
||||
- **@anthropic-ai/sdk**: Anthropic Batch API for documentation processing
|
||||
- **tsdown**: TypeScript bundler for CLI package
|
||||
|
||||
## Environment Configuration
|
||||
|
||||
Required environment variables:
|
||||
### apps/mcp-remote/.env
|
||||
|
||||
- `DATABASE_URL`: SQLite database path (default: `file:test.db`)
|
||||
- `VOYAGE_API_KEY`: API key for embeddings support (optional)
|
||||
Required for the remote MCP server:
|
||||
|
||||
When connected to the svelte-llm MCP server, you have access to comprehensive Svelte 5 and SvelteKit documentation. Here's how to use the available tools effectively:
|
||||
- `DATABASE_URL`: LibSQL/Turso database URL (e.g., `libsql://db-name.turso.io`)
|
||||
- `DATABASE_TOKEN`: Turso authentication token
|
||||
- `VOYAGE_API_KEY`: API key for embeddings support (optional, for vector search features)
|
||||
|
||||
## Available MCP Tools:
|
||||
### packages/mcp-server/.env
|
||||
|
||||
### 1. list-sections
|
||||
Required for documentation generation scripts:
|
||||
|
||||
Use this FIRST to discover all available documentation sections. Returns a structured list with titles and paths.
|
||||
When asked about Svelte or SvelteKit topics, ALWAYS use this tool at the start of the chat to find relevant sections.
|
||||
- `ANTHROPIC_API_KEY`: API key for generating and verifying distilled documentation
|
||||
|
||||
### 2. get-documentation
|
||||
## Using the MCP Server
|
||||
|
||||
Retrieves full documentation content for specific sections. Accepts single or multiple sections.
|
||||
After calling the list-sections tool, you MUST analyze the returned documentation sections and then use the get_documentation tool to fetch ALL documentation sections that are relevant for the users task.
|
||||
### Available MCP Tools
|
||||
|
||||
1. **list-sections** - ALWAYS call this FIRST to discover available documentation
|
||||
- Returns structured list with titles, paths, and use_cases metadata
|
||||
- Use the use_cases field to determine relevant sections
|
||||
|
||||
2. **get-documentation** - Retrieves documentation content
|
||||
- Accepts single section name or array of section names
|
||||
- Searches by title or file path
|
||||
- Optional `use_distilled` parameter (default: true) for condensed versions
|
||||
- After calling list-sections, fetch ALL relevant sections at once
|
||||
|
||||
3. **svelte-autofixer** - Analyzes Svelte code
|
||||
- MUST be used whenever writing Svelte code before returning to user
|
||||
- Keep calling until no issues/suggestions remain
|
||||
- Provides compilation errors, ESLint issues, and custom suggestions
|
||||
|
||||
4. **playground-link** - Generates Svelte Playground URLs
|
||||
- Only use after code is finalized and user confirms
|
||||
- Requires App.svelte as entry point
|
||||
- Can include multiple files
|
||||
|
||||
### Available MCP Prompts
|
||||
|
||||
- **svelte-task** - Use for any Svelte-related task
|
||||
- Instructs LLM on proper tool usage
|
||||
- Enforces iterative autofixer workflow
|
||||
- Guides documentation querying
|
||||
|
||||
## Constants & Configuration
|
||||
|
||||
### Svelte Runes (`packages/mcp-server/src/constants.ts`)
|
||||
|
||||
Base runes:
|
||||
|
||||
- `$state`, `$effect`, `$derived`, `$inspect`, `$props`, `$bindable`, `$host`
|
||||
|
||||
Nested runes:
|
||||
|
||||
- `$state.raw`, `$state.snapshot`, `$effect.pre`, `$effect.tracking`, `$effect.pending`, `$effect.root`, `$derived.by`, `$inspect.trace`, `$props.id`
|
||||
|
||||
## Code Style & Standards
|
||||
|
||||
- **Naming**: Use `snake_case` for variables and functions
|
||||
- **Types**: Prefer TypeScript type imports with JSDoc where needed
|
||||
- **Formatting**: Tabs for indentation, single quotes, trailing commas
|
||||
- **File Extensions**: Include `.js` extension in imports even for TypeScript files
|
||||
- **Linting**: Run `pnpm lint:fix` before committing
|
||||
|
||||
## Testing
|
||||
|
||||
- Unit tests use Vitest
|
||||
- Test files use `.test.ts` or `.spec.ts` suffix
|
||||
- Run `pnpm test` to execute all tests
|
||||
- Run `pnpm test:watch` for watch mode
|
||||
- Test coverage includes:
|
||||
- Documentation generation and verification
|
||||
- Autofixer visitors
|
||||
- Parsing and AST analysis
|
||||
|
||||
@@ -39,15 +39,15 @@
|
||||
"devDependencies": {
|
||||
"@eslint/compat": "^1.3.2",
|
||||
"@eslint/js": "^9.36.0",
|
||||
"@libsql/client": "^0.14.0",
|
||||
"@modelcontextprotocol/inspector": "^0.16.7",
|
||||
"@libsql/client": "^0.15.0",
|
||||
"@modelcontextprotocol/inspector": "^0.17.0",
|
||||
"@sveltejs/adapter-vercel": "^5.6.3",
|
||||
"@sveltejs/kit": "^2.22.0",
|
||||
"@sveltejs/vite-plugin-svelte": "^6.0.0",
|
||||
"@types/node": "^24.3.1",
|
||||
"@typescript-eslint/parser": "^8.44.0",
|
||||
"drizzle-kit": "^0.30.2",
|
||||
"drizzle-orm": "^0.40.0",
|
||||
"drizzle-kit": "^0.31.0",
|
||||
"drizzle-orm": "^0.44.0",
|
||||
"eslint-config-prettier": "^10.0.1",
|
||||
"eslint-plugin-svelte": "^3.12.3",
|
||||
"globals": "^16.0.0",
|
||||
|
||||
@@ -7,7 +7,10 @@ export async function handle({ event, resolve }) {
|
||||
const accept = event.request.headers.get('accept');
|
||||
if (accept) {
|
||||
const accepts = accept.split(',');
|
||||
if (!accepts.includes('text/event-stream')) {
|
||||
if (
|
||||
!accepts.includes('text/event-stream') &&
|
||||
(event.url.pathname.startsWith('/mcp') || event.url.pathname === '/')
|
||||
) {
|
||||
// the request it's a browser request, not an MCP client request
|
||||
// it means someone probably opened it from the docs...we should redirect to the docs
|
||||
redirect(302, 'https://svelte.dev/docs/mcp/overview');
|
||||
|
||||
@@ -1 +0,0 @@
|
||||
<h1>Official Svelte MCP</h1>
|
||||
73
apps/mcp-remote/src/routes/compare/[type]/+page.server.ts
Normal file
73
apps/mcp-remote/src/routes/compare/[type]/+page.server.ts
Normal file
@@ -0,0 +1,73 @@
|
||||
import { error } from '@sveltejs/kit';
|
||||
import type { PageServerLoad } from './$types';
|
||||
import distilled_data from '@sveltejs/mcp-server/distilled.json';
|
||||
import use_cases_data from '@sveltejs/mcp-server/use-cases.json';
|
||||
|
||||
interface SummaryData {
|
||||
generated_at: string;
|
||||
model: string;
|
||||
total_sections: number;
|
||||
successful_summaries: number;
|
||||
summaries: Record<string, string>;
|
||||
content: Record<string, string>;
|
||||
}
|
||||
|
||||
const VALID_TYPES = ['use_cases', 'distilled'] as const;
|
||||
type ValidType = (typeof VALID_TYPES)[number];
|
||||
|
||||
function is_valid_type(type: string): type is ValidType {
|
||||
return VALID_TYPES.includes(type as ValidType);
|
||||
}
|
||||
|
||||
export const load: PageServerLoad = async ({ params }) => {
|
||||
const { type } = params;
|
||||
|
||||
if (!is_valid_type(type)) {
|
||||
throw error(404, 'Comparison type not found');
|
||||
}
|
||||
|
||||
const data = (type === 'use_cases' ? use_cases_data : distilled_data) as SummaryData;
|
||||
|
||||
const sections = Object.keys(data.summaries).map((slug) => {
|
||||
const summary = data.summaries[slug] || '';
|
||||
const content = data.content[slug] || '';
|
||||
const original_length = content.length;
|
||||
const distilled_length = summary.length;
|
||||
const space_savings =
|
||||
original_length > 0 ? ((original_length - distilled_length) / original_length) * 100 : 0;
|
||||
|
||||
return {
|
||||
slug,
|
||||
summary,
|
||||
content,
|
||||
original_length,
|
||||
distilled_length,
|
||||
space_savings,
|
||||
};
|
||||
});
|
||||
|
||||
const total_original_length = sections.reduce((sum, s) => sum + s.original_length, 0);
|
||||
const total_distilled_length = sections.reduce((sum, s) => sum + s.distilled_length, 0);
|
||||
const total_space_savings =
|
||||
total_original_length > 0
|
||||
? ((total_original_length - total_distilled_length) / total_original_length) * 100
|
||||
: 0;
|
||||
|
||||
const title =
|
||||
type === 'use_cases' ? 'Use Cases Comparison' : 'Distilled Documentation Comparison';
|
||||
|
||||
return {
|
||||
type,
|
||||
title,
|
||||
metadata: {
|
||||
generated_at: data.generated_at,
|
||||
model: data.model,
|
||||
total_sections: data.total_sections,
|
||||
successful_summaries: data.successful_summaries,
|
||||
total_original_length,
|
||||
total_distilled_length,
|
||||
total_space_savings,
|
||||
},
|
||||
sections,
|
||||
};
|
||||
};
|
||||
427
apps/mcp-remote/src/routes/compare/[type]/+page.svelte
Normal file
427
apps/mcp-remote/src/routes/compare/[type]/+page.svelte
Normal file
@@ -0,0 +1,427 @@
|
||||
<script lang="ts">
|
||||
import type { PageData } from './$types';
|
||||
|
||||
let { data }: { data: PageData } = $props();
|
||||
|
||||
let selected_slug = $state<string | null>(null);
|
||||
let search_query = $state('');
|
||||
let sort_order = $state<'default' | 'largest' | 'smallest'>('default');
|
||||
|
||||
let filtered_sections = $derived.by(() => {
|
||||
// First, filter sections
|
||||
const filtered = data.sections.filter(
|
||||
(section) =>
|
||||
section.slug.toLowerCase().includes(search_query.toLowerCase()) ||
|
||||
section.summary.toLowerCase().includes(search_query.toLowerCase()),
|
||||
);
|
||||
|
||||
// Then, sort based on selected sort order
|
||||
if (sort_order === 'largest') {
|
||||
return [...filtered].sort((a, b) => b.space_savings - a.space_savings);
|
||||
} else if (sort_order === 'smallest') {
|
||||
return [...filtered].sort((a, b) => a.space_savings - b.space_savings);
|
||||
}
|
||||
|
||||
return filtered;
|
||||
});
|
||||
|
||||
let selected_section = $derived(
|
||||
selected_slug ? data.sections.find((s) => s.slug === selected_slug) : null,
|
||||
);
|
||||
|
||||
let summary_title = $derived(
|
||||
data.type === 'use_cases' ? 'Use Cases Summary' : 'Distilled Version',
|
||||
);
|
||||
let is_distilled = $derived(data.type === 'distilled');
|
||||
|
||||
function select_section(slug: string) {
|
||||
selected_slug = selected_slug === slug ? null : slug;
|
||||
}
|
||||
</script>
|
||||
|
||||
<svelte:head>
|
||||
<title>{data.title}</title>
|
||||
</svelte:head>
|
||||
|
||||
<div class="container">
|
||||
<header>
|
||||
<h1>{data.title}</h1>
|
||||
<div class="metadata">
|
||||
<span>Generated: {new Date(data.metadata.generated_at).toLocaleString()}</span>
|
||||
<span>Model: {data.metadata.model}</span>
|
||||
<span>Sections: {data.metadata.successful_summaries}/{data.metadata.total_sections}</span>
|
||||
<span
|
||||
>Space Savings: {data.metadata.total_distilled_length.toLocaleString()}/{data.metadata.total_original_length.toLocaleString()}
|
||||
chars ({data.metadata.total_space_savings.toFixed(1)}% reduction)</span
|
||||
>
|
||||
</div>
|
||||
</header>
|
||||
|
||||
<div class="main-content">
|
||||
<aside class="sidebar">
|
||||
<div class="sort-controls">
|
||||
<span class="sort-label">Sort by:</span>
|
||||
<div class="sort-buttons">
|
||||
<button
|
||||
class="sort-button"
|
||||
class:active={sort_order === 'default'}
|
||||
onclick={() => (sort_order = 'default')}
|
||||
>
|
||||
Default
|
||||
</button>
|
||||
<button
|
||||
class="sort-button"
|
||||
class:active={sort_order === 'largest'}
|
||||
onclick={() => (sort_order = 'largest')}
|
||||
>
|
||||
Largest Reduction
|
||||
</button>
|
||||
<button
|
||||
class="sort-button"
|
||||
class:active={sort_order === 'smallest'}
|
||||
onclick={() => (sort_order = 'smallest')}
|
||||
>
|
||||
Smallest Reduction
|
||||
</button>
|
||||
</div>
|
||||
</div>
|
||||
<div class="search-box">
|
||||
<input
|
||||
type="search"
|
||||
bind:value={search_query}
|
||||
placeholder="Search sections..."
|
||||
class="search-input"
|
||||
/>
|
||||
</div>
|
||||
<ul class="section-list">
|
||||
{#each filtered_sections as section (section.slug)}
|
||||
<li>
|
||||
<button
|
||||
class="section-item"
|
||||
class:active={selected_slug === section.slug}
|
||||
onclick={() => select_section(section.slug)}
|
||||
>
|
||||
<div class="section-header">
|
||||
<div class="section-title">{section.slug}</div>
|
||||
<div class="section-savings" class:negative={section.space_savings < 0}>
|
||||
{section.space_savings.toFixed(1)}%
|
||||
</div>
|
||||
</div>
|
||||
<div class="section-preview">
|
||||
{is_distilled
|
||||
? section.summary.slice(0, 100) + (section.summary.length > 100 ? '...' : '')
|
||||
: section.summary}
|
||||
</div>
|
||||
</button>
|
||||
</li>
|
||||
{/each}
|
||||
</ul>
|
||||
</aside>
|
||||
|
||||
<main class="comparison-view">
|
||||
{#if selected_section}
|
||||
<div class="comparison-grid">
|
||||
<div class="comparison-column">
|
||||
<h2>
|
||||
Original Content
|
||||
<span class="char-count"
|
||||
>{selected_section.original_length.toLocaleString()} chars</span
|
||||
>
|
||||
</h2>
|
||||
<div class="content-box">
|
||||
<pre>{selected_section.content}</pre>
|
||||
</div>
|
||||
</div>
|
||||
<div class="comparison-column">
|
||||
<h2>
|
||||
{summary_title}
|
||||
<span class="char-count"
|
||||
>{selected_section.distilled_length.toLocaleString()} chars ({selected_section.space_savings.toFixed(
|
||||
1,
|
||||
)}% savings)</span
|
||||
>
|
||||
</h2>
|
||||
<div class="content-box">
|
||||
<pre>{selected_section.summary}</pre>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
{:else}
|
||||
<div class="empty-state">
|
||||
<p>Select a section from the list to view the comparison</p>
|
||||
</div>
|
||||
{/if}
|
||||
</main>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<style>
|
||||
.container {
|
||||
max-width: 100%;
|
||||
height: 100vh;
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
}
|
||||
|
||||
header {
|
||||
background: white;
|
||||
border-bottom: 1px solid #e0e0e0;
|
||||
padding: 1.5rem 2rem;
|
||||
}
|
||||
|
||||
h1 {
|
||||
margin: 0 0 0.5rem 0;
|
||||
font-size: 1.875rem;
|
||||
font-weight: 600;
|
||||
color: #1a1a1a;
|
||||
}
|
||||
|
||||
.metadata {
|
||||
display: flex;
|
||||
gap: 1.5rem;
|
||||
font-size: 0.9375rem;
|
||||
color: #666;
|
||||
flex-wrap: wrap;
|
||||
}
|
||||
|
||||
.main-content {
|
||||
display: flex;
|
||||
flex: 1;
|
||||
overflow: hidden;
|
||||
}
|
||||
|
||||
.sidebar {
|
||||
width: 350px;
|
||||
background: white;
|
||||
border-right: 1px solid #e0e0e0;
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
}
|
||||
|
||||
.sort-controls {
|
||||
padding: 1rem;
|
||||
border-bottom: 1px solid #e0e0e0;
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
gap: 0.5rem;
|
||||
}
|
||||
|
||||
.sort-label {
|
||||
font-size: 0.8125rem;
|
||||
font-weight: 500;
|
||||
color: #666;
|
||||
}
|
||||
|
||||
.sort-buttons {
|
||||
display: flex;
|
||||
gap: 0.5rem;
|
||||
flex-wrap: wrap;
|
||||
}
|
||||
|
||||
.sort-button {
|
||||
padding: 0.375rem 0.75rem;
|
||||
border: 1px solid #e0e0e0;
|
||||
border-radius: 4px;
|
||||
background: white;
|
||||
font-size: 0.8125rem;
|
||||
font-family: inherit;
|
||||
cursor: pointer;
|
||||
transition: all 0.15s;
|
||||
color: #666;
|
||||
}
|
||||
|
||||
.sort-button:hover {
|
||||
background: #f9fafb;
|
||||
border-color: #d0d0d0;
|
||||
}
|
||||
|
||||
.sort-button.active {
|
||||
background: #3b82f6;
|
||||
border-color: #3b82f6;
|
||||
color: white;
|
||||
}
|
||||
|
||||
.search-box {
|
||||
padding: 1rem;
|
||||
border-bottom: 1px solid #e0e0e0;
|
||||
}
|
||||
|
||||
.search-input {
|
||||
width: 100%;
|
||||
padding: 0.5rem 0.75rem;
|
||||
border: 1px solid #e0e0e0;
|
||||
border-radius: 4px;
|
||||
font-size: 0.9375rem;
|
||||
font-family: inherit;
|
||||
}
|
||||
|
||||
.search-input:focus {
|
||||
outline: none;
|
||||
border-color: #3b82f6;
|
||||
}
|
||||
|
||||
.section-list {
|
||||
list-style: none;
|
||||
margin: 0;
|
||||
padding: 0;
|
||||
overflow-y: auto;
|
||||
flex: 1;
|
||||
}
|
||||
|
||||
.section-item {
|
||||
width: 100%;
|
||||
text-align: left;
|
||||
padding: 0.75rem 1rem;
|
||||
border: none;
|
||||
border-bottom: 1px solid #f0f0f0;
|
||||
background: white;
|
||||
cursor: pointer;
|
||||
transition: background-color 0.15s;
|
||||
font-family: inherit;
|
||||
}
|
||||
|
||||
.section-item:hover {
|
||||
background: #f9fafb;
|
||||
}
|
||||
|
||||
.section-item.active {
|
||||
background: #eff6ff;
|
||||
border-left: 3px solid #3b82f6;
|
||||
}
|
||||
|
||||
.section-header {
|
||||
display: flex;
|
||||
justify-content: space-between;
|
||||
align-items: center;
|
||||
gap: 0.5rem;
|
||||
margin-bottom: 0.25rem;
|
||||
}
|
||||
|
||||
.section-title {
|
||||
font-size: 0.9375rem;
|
||||
font-weight: 500;
|
||||
color: #1a1a1a;
|
||||
flex: 1;
|
||||
overflow: hidden;
|
||||
text-overflow: ellipsis;
|
||||
white-space: nowrap;
|
||||
}
|
||||
|
||||
.section-savings {
|
||||
font-size: 0.75rem;
|
||||
font-weight: 600;
|
||||
color: #10b981;
|
||||
padding: 0.125rem 0.375rem;
|
||||
background: #d1fae5;
|
||||
border-radius: 3px;
|
||||
white-space: nowrap;
|
||||
}
|
||||
|
||||
.section-savings.negative {
|
||||
color: #ef4444;
|
||||
background: #fee2e2;
|
||||
}
|
||||
|
||||
.section-preview {
|
||||
font-size: 0.8125rem;
|
||||
color: #666;
|
||||
overflow: hidden;
|
||||
text-overflow: ellipsis;
|
||||
white-space: nowrap;
|
||||
}
|
||||
|
||||
.comparison-view {
|
||||
flex: 1;
|
||||
overflow: auto;
|
||||
background: #fafafa;
|
||||
}
|
||||
|
||||
.comparison-grid {
|
||||
display: grid;
|
||||
grid-template-columns: 1fr 1fr;
|
||||
gap: 1rem;
|
||||
padding: 1rem;
|
||||
height: 100%;
|
||||
}
|
||||
|
||||
.comparison-column {
|
||||
background: white;
|
||||
border: 1px solid #e0e0e0;
|
||||
border-radius: 4px;
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
overflow: hidden;
|
||||
}
|
||||
|
||||
.comparison-column h2 {
|
||||
margin: 0;
|
||||
padding: 1rem;
|
||||
font-size: 1.125rem;
|
||||
font-weight: 600;
|
||||
color: #1a1a1a;
|
||||
border-bottom: 1px solid #e0e0e0;
|
||||
background: #fafafa;
|
||||
display: flex;
|
||||
justify-content: space-between;
|
||||
align-items: center;
|
||||
gap: 1rem;
|
||||
}
|
||||
|
||||
.char-count {
|
||||
font-size: 0.8125rem;
|
||||
font-weight: 400;
|
||||
color: #666;
|
||||
white-space: nowrap;
|
||||
}
|
||||
|
||||
.content-box {
|
||||
padding: 1rem;
|
||||
overflow: auto;
|
||||
flex: 1;
|
||||
font-size: 0.9375rem;
|
||||
line-height: 1.6;
|
||||
}
|
||||
|
||||
.content-box pre {
|
||||
margin: 0;
|
||||
white-space: pre-wrap;
|
||||
word-wrap: break-word;
|
||||
font-family: 'Monaco', 'Menlo', 'Ubuntu Mono', 'Courier New', monospace;
|
||||
font-size: 0.875rem;
|
||||
color: #333;
|
||||
}
|
||||
|
||||
.empty-state {
|
||||
display: flex;
|
||||
align-items: center;
|
||||
justify-content: center;
|
||||
height: 100%;
|
||||
color: #666;
|
||||
font-size: 0.9375rem;
|
||||
}
|
||||
|
||||
@media (max-width: 768px) {
|
||||
.comparison-grid {
|
||||
grid-template-columns: 1fr;
|
||||
}
|
||||
|
||||
.sidebar {
|
||||
width: 100%;
|
||||
max-height: 25vh;
|
||||
}
|
||||
|
||||
.main-content {
|
||||
flex-direction: column;
|
||||
}
|
||||
|
||||
.comparison-column h2 {
|
||||
flex-direction: column;
|
||||
align-items: flex-start;
|
||||
gap: 0.5rem;
|
||||
}
|
||||
|
||||
.char-count {
|
||||
font-size: 0.75rem;
|
||||
}
|
||||
}
|
||||
</style>
|
||||
@@ -9,11 +9,11 @@ The Svelte MCP ([Model Context Protocol](https://modelcontextprotocol.io/docs/ge
|
||||
The setup varies based on the version of the MCP you prefer — remote or local — and your chosen MCP client (e.g. Claude Code, Codex CLI or GitHub Copilot):
|
||||
|
||||
- [local setup](local-setup) using `@sveltejs/mcp`
|
||||
- [remote setup](remote-setup) using [mcp.svelte.dev/mcp](https://mcp.svelte.dev/mcp)
|
||||
- [remote setup](remote-setup) using `https://mcp.svelte.dev/mcp`
|
||||
|
||||
## Usage
|
||||
|
||||
To get the most out of the MCP server we recommend including the following prompt in your `AGENTS.md` (or `CLAUDE.md`, if using Claude Code). This will tell the LLM which tools are available and when it's appropriate to use them.
|
||||
To get the most out of the MCP server we recommend including the following prompt in your [`AGENTS.md`](https://agents.md) (or [`CLAUDE.md`](https://docs.claude.com/en/docs/claude-code/memory#claude-md-imports), if using Claude Code). This will tell the LLM which tools are available and when it's appropriate to use them.
|
||||
|
||||
```md
|
||||
You are able to use the Svelte MCP server, where you have access to comprehensive Svelte 5 and SvelteKit documentation. Here's how to use the available tools effectively:
|
||||
|
||||
@@ -15,7 +15,7 @@ Here's how to set it up in some common MCP clients:
|
||||
To include the local MCP version in Claude Code, simply run the following command:
|
||||
|
||||
```bash
|
||||
claude mcp add -t stdio -s [scope] svelte npx -y @sveltejs/mcp
|
||||
claude mcp add -t stdio -s [scope] svelte -- npx -y @sveltejs/mcp
|
||||
```
|
||||
|
||||
The `[scope]` must be `user`, `project` or `local`.
|
||||
@@ -108,6 +108,25 @@ It will open a file with your MCP servers where you can add the following config
|
||||
}
|
||||
```
|
||||
|
||||
## Zed
|
||||
|
||||
- Open the command palette
|
||||
- Search and select "agent:open settings"
|
||||
- In settings panel look for `Model Context Protocol (MCP) Servers`
|
||||
- Click on "Add Server"
|
||||
- Select: "Add Custom Server"
|
||||
|
||||
It will open a popup with MCP server config where you can add the following configuration:
|
||||
|
||||
```json
|
||||
{
|
||||
"svelte": {
|
||||
"command": "npx",
|
||||
"args": ["-y", "@sveltejs/mcp"]
|
||||
}
|
||||
}
|
||||
```
|
||||
|
||||
## Other clients
|
||||
|
||||
If we didn't include the MCP client you are using, refer to their documentation for `stdio` servers and use `npx` as the command and `-y @sveltejs/mcp` as the arguments.
|
||||
|
||||
@@ -2,7 +2,7 @@
|
||||
title: Remote setup
|
||||
---
|
||||
|
||||
The remote version of the MCP server is available on `https://mcp.svelte.dev/mcp`.
|
||||
The remote version of the MCP server is available at `https://mcp.svelte.dev/mcp`.
|
||||
|
||||
Here's how to set it up in some common MCP clients:
|
||||
|
||||
|
||||
@@ -2,7 +2,7 @@
|
||||
title: Tools
|
||||
---
|
||||
|
||||
The following tools are provided by the MCP server to the model, which can decide to call one or more of them during a session:
|
||||
The following tools are provided by the MCP server to the model you are using, which can decide to call one or more of them during a session:
|
||||
|
||||
## list-sections
|
||||
|
||||
@@ -14,7 +14,7 @@ Allows the model to get the full (and up-to-date) documentation for the requeste
|
||||
|
||||
## svelte-autofixer
|
||||
|
||||
Uses static analysis to provide suggestions for the generated code. It should be invoked in a loop by the model until all issues and suggestions are resolved.
|
||||
Uses static analysis to provide suggestions for code that your LLM generates. It can be invoked in an agentic loop by your model until all issues and suggestions are resolved.
|
||||
|
||||
## playground-link
|
||||
|
||||
|
||||
@@ -6,21 +6,200 @@ This is the list of available prompts provided by the MCP server. Prompts are se
|
||||
|
||||
## svelte-task
|
||||
|
||||
This prompt should be used whenever you are asking the model to work on some Svelte-related task. It will instruct the LLM on which documentation sections are available, which tool to invoke, when to invoke it, and how to interpret the result. It will ask you for the description of the task and the returned value will look like this:
|
||||
This prompt should be used whenever you are asking the model to work on a Svelte-related task. It will instruct the LLM which documentation sections are available, which tools to invoke, when to invoke them, and how to interpret the results.
|
||||
|
||||
```
|
||||
You are a Svelte expert tasked to build components and utilities for Svelte developers. If you need documentation for anything related to Svelte you can invoke the tool \`get-documentation\` with one of the following paths:
|
||||
<available-docs-paths>
|
||||
[all available docs]
|
||||
</available-docs-paths>
|
||||
<details>
|
||||
<summary>Copy the prompt</summary>
|
||||
|
||||
Every time you write a Svelte component or a Svelte module you MUST invoke the \`svelte-autofixer\` tool providing the code. The tool will return a list of issues or suggestions. If there are any issues or suggestions you MUST fix them and call the tool again with the updated code. You MUST keep doing this until the tool returns no issues or suggestions. Only then you can return the code to the user.
|
||||
```md
|
||||
You are a Svelte expert tasked to build components and utilities for Svelte developers. If you need documentation for anything related to Svelte you can invoke the tool `get_documentation` with one of the following paths:
|
||||
<available-docs>
|
||||
|
||||
- title: Overview, use_cases: project setup, creating new svelte apps, scaffolding, cli tools, initializing projects, path: cli/overview
|
||||
- title: Frequently asked questions, use_cases: project setup, initializing new svelte projects, troubleshooting cli installation, package manager configuration, path: cli/faq
|
||||
- title: sv create, use_cases: project setup, starting new sveltekit app, initializing project, creating from playground, choosing project template, path: cli/sv-create
|
||||
- title: sv add, use_cases: project setup, adding features to existing projects, integrating tools, testing setup, styling setup, authentication, database setup, deployment adapters, path: cli/sv-add
|
||||
- title: sv check, use_cases: code quality, ci/cd pipelines, error checking, typescript projects, pre-commit hooks, finding unused css, accessibility auditing, production builds, path: cli/sv-check
|
||||
- title: sv migrate, use_cases: migration, upgrading svelte versions, upgrading sveltekit versions, modernizing codebase, svelte 3 to 4, svelte 4 to 5, sveltekit 1 to 2, adopting runes, refactoring deprecated apis, path: cli/sv-migrate
|
||||
- title: devtools-json, use_cases: development setup, chrome devtools integration, browser-based editing, local development workflow, debugging setup, path: cli/devtools-json
|
||||
- title: drizzle, use_cases: database setup, sql queries, orm integration, data modeling, postgresql, mysql, sqlite, server-side data access, database migrations, type-safe queries, path: cli/drizzle
|
||||
- title: eslint, use_cases: code quality, linting, error detection, project setup, code standards, team collaboration, typescript projects, path: cli/eslint
|
||||
- title: lucia, use_cases: authentication, login systems, user management, registration pages, session handling, auth setup, path: cli/lucia
|
||||
- title: mdsvex, use_cases: blog, content sites, markdown rendering, documentation sites, technical writing, cms integration, article pages, path: cli/mdsvex
|
||||
- title: paraglide, use_cases: internationalization, multi-language sites, i18n, translation, localization, language switching, global apps, multilingual content, path: cli/paraglide
|
||||
- title: playwright, use_cases: browser testing, e2e testing, integration testing, test automation, quality assurance, ci/cd pipelines, testing user flows, path: cli/playwright
|
||||
- title: prettier, use_cases: code formatting, project setup, code style consistency, team collaboration, linting configuration, path: cli/prettier
|
||||
- title: storybook, use_cases: component development, design systems, ui library, isolated component testing, documentation, visual testing, component showcase, path: cli/storybook
|
||||
- title: sveltekit-adapter, use_cases: deployment, production builds, hosting setup, choosing deployment platform, configuring adapters, static site generation, node server, vercel, cloudflare, netlify, path: cli/sveltekit-adapter
|
||||
- title: tailwindcss, use_cases: project setup, styling, css framework, rapid prototyping, utility-first css, design systems, responsive design, adding tailwind to svelte, path: cli/tailwind
|
||||
- title: vitest, use_cases: testing, unit tests, component testing, test setup, quality assurance, ci/cd pipelines, test-driven development, path: cli/vitest
|
||||
- title: Introduction, use_cases: learning sveltekit, project setup, understanding framework basics, choosing between svelte and sveltekit, getting started with full-stack apps, path: kit/introduction
|
||||
- title: Creating a project, use_cases: project setup, starting new sveltekit app, initial development environment, first-time sveltekit users, scaffolding projects, path: kit/creating-a-project
|
||||
- title: Project types, use_cases: deployment, project setup, choosing adapters, ssg, spa, ssr, serverless, mobile apps, desktop apps, pwa, offline apps, browser extensions, separate backend, docker containers, path: kit/project-types
|
||||
- title: Project structure, use_cases: project setup, understanding file structure, organizing code, starting new project, learning sveltekit basics, path: kit/project-structure
|
||||
- title: Web standards, use_cases: always, any sveltekit project, data fetching, forms, api routes, server-side rendering, deployment to various platforms, path: kit/web-standards
|
||||
- title: Routing, use_cases: routing, navigation, multi-page apps, project setup, file structure, api endpoints, data loading, layouts, error pages, always, path: kit/routing
|
||||
- title: Loading data, use_cases: data fetching, api calls, database queries, dynamic routes, page initialization, loading states, authentication checks, ssr data, form data, content rendering, path: kit/load
|
||||
- title: Form actions, use_cases: forms, user input, data submission, authentication, login systems, user registration, progressive enhancement, validation errors, path: kit/form-actions
|
||||
- title: Page options, use_cases: prerendering static sites, ssr configuration, spa setup, client-side rendering control, url trailing slash handling, adapter deployment config, build optimization, path: kit/page-options
|
||||
- title: State management, use_cases: sveltekit, server-side rendering, ssr, state management, authentication, data persistence, load functions, context api, navigation, component lifecycle, path: kit/state-management
|
||||
- title: Remote functions, use_cases: data fetching, server-side logic, database queries, type-safe client-server communication, forms, user input, mutations, authentication, crud operations, optimistic updates, path: kit/remote-functions
|
||||
- title: Building your app, use_cases: production builds, deployment preparation, build process optimization, adapter configuration, preview before deployment, path: kit/building-your-app
|
||||
- title: Adapters, use_cases: deployment, production builds, hosting setup, choosing deployment platform, configuring adapters, path: kit/adapters
|
||||
- title: Zero-config deployments, use_cases: deployment, production builds, hosting setup, choosing deployment platform, ci/cd configuration, path: kit/adapter-auto
|
||||
- title: Node servers, use_cases: deployment, production builds, node.js hosting, custom server setup, environment configuration, reverse proxy setup, docker deployment, systemd services, path: kit/adapter-node
|
||||
- title: Static site generation, use_cases: static site generation, ssg, prerendering, deployment, github pages, spa mode, blogs, documentation sites, marketing sites, path: kit/adapter-static
|
||||
- title: Single-page apps, use_cases: spa mode, single-page apps, client-only rendering, static hosting, mobile app wrappers, no server-side logic, adapter-static setup, fallback pages, path: kit/single-page-apps
|
||||
- title: Cloudflare, use_cases: deployment, cloudflare workers, cloudflare pages, hosting setup, production builds, serverless deployment, edge computing, path: kit/adapter-cloudflare
|
||||
- title: Cloudflare Workers, use_cases: deploying to cloudflare workers, cloudflare workers sites deployment, legacy cloudflare adapter, wrangler configuration, cloudflare platform bindings, path: kit/adapter-cloudflare-workers
|
||||
- title: Netlify, use_cases: deployment, netlify hosting, production builds, serverless functions, edge functions, static site hosting, path: kit/adapter-netlify
|
||||
- title: Vercel, use_cases: deployment, vercel hosting, production builds, serverless functions, edge functions, isr, image optimization, environment variables, path: kit/adapter-vercel
|
||||
- title: Writing adapters, use_cases: custom deployment, building adapters, unsupported platforms, adapter development, custom hosting environments, path: kit/writing-adapters
|
||||
- title: Advanced routing, use_cases: advanced routing, dynamic routes, file viewers, nested paths, custom 404 pages, url validation, route parameters, multi-level navigation, path: kit/advanced-routing
|
||||
- title: Hooks, use_cases: authentication, logging, error tracking, request interception, api proxying, custom routing, internationalization, database initialization, middleware logic, session management, path: kit/hooks
|
||||
- title: Errors, use_cases: error handling, custom error pages, 404 pages, api error responses, production error logging, error tracking, type-safe errors, path: kit/errors
|
||||
- title: Link options, use_cases: routing, navigation, multi-page apps, performance optimization, link preloading, forms with get method, search functionality, focus management, scroll behavior, path: kit/link-options
|
||||
- title: Service workers, use_cases: offline support, pwa, caching strategies, performance optimization, precaching assets, network resilience, progressive web apps, path: kit/service-workers
|
||||
- title: Server-only modules, use_cases: api keys, environment variables, sensitive data protection, backend security, preventing data leaks, server-side code isolation, path: kit/server-only-modules
|
||||
- title: Snapshots, use_cases: forms, user input, preserving form data, multi-step forms, navigation state, preventing data loss, textarea content, input fields, comment systems, surveys, path: kit/snapshots
|
||||
- title: Shallow routing, use_cases: modals, dialogs, image galleries, overlays, history-driven ui, mobile-friendly navigation, photo viewers, lightboxes, drawer menus, path: kit/shallow-routing
|
||||
- title: Observability, use_cases: performance monitoring, debugging, observability, tracing requests, production diagnostics, analyzing slow requests, finding bottlenecks, monitoring server-side operations, path: kit/observability
|
||||
- title: Packaging, use_cases: building component libraries, publishing npm packages, creating reusable svelte components, library development, package distribution, path: kit/packaging
|
||||
- title: Auth, use_cases: authentication, login systems, user management, session handling, jwt tokens, protected routes, user credentials, authorization checks, path: kit/auth
|
||||
- title: Performance, use_cases: performance optimization, slow loading pages, production deployment, debugging performance issues, reducing bundle size, improving load times, path: kit/performance
|
||||
- title: Icons, use_cases: icons, ui components, styling, css frameworks, tailwind, unocss, performance optimization, dependency management, path: kit/icons
|
||||
- title: Images, use_cases: image optimization, responsive images, performance, hero images, product photos, galleries, cms integration, cdn setup, asset management, path: kit/images
|
||||
- title: Accessibility, use_cases: always, any sveltekit project, screen reader support, keyboard navigation, multi-page apps, client-side routing, internationalization, multilingual sites, path: kit/accessibility
|
||||
- title: SEO, use_cases: seo optimization, search engine ranking, content sites, blogs, marketing sites, public-facing apps, sitemaps, amp pages, meta tags, performance optimization, path: kit/seo
|
||||
- title: Frequently asked questions, use_cases: troubleshooting package imports, library compatibility issues, client-side code execution, external api integration, middleware setup, database configuration, view transitions, yarn configuration, path: kit/faq
|
||||
- title: Integrations, use_cases: project setup, css preprocessors, postcss, scss, sass, less, stylus, typescript setup, adding integrations, tailwind, testing, auth, linting, formatting, path: kit/integrations
|
||||
- title: Breakpoint Debugging, use_cases: debugging, breakpoints, development workflow, troubleshooting issues, vscode setup, ide configuration, inspecting code execution, path: kit/debugging
|
||||
- title: Migrating to SvelteKit v2, use_cases: migration, upgrading from sveltekit 1 to 2, breaking changes, version updates, path: kit/migrating-to-sveltekit-2
|
||||
- title: Migrating from Sapper, use_cases: migrating from sapper, upgrading legacy projects, sapper to sveltekit conversion, project modernization, path: kit/migrating
|
||||
- title: Additional resources, use_cases: troubleshooting, getting help, finding examples, learning sveltekit, project templates, common issues, community support, path: kit/additional-resources
|
||||
- title: Glossary, use_cases: rendering strategies, performance optimization, deployment configuration, seo requirements, static sites, spas, server-side rendering, prerendering, edge deployment, pwa development, path: kit/glossary
|
||||
- title: @sveltejs/kit, use_cases: forms, form actions, server-side validation, form submission, error handling, redirects, json responses, http errors, server utilities, path: kit/@sveltejs-kit
|
||||
- title: @sveltejs/kit/hooks, use_cases: middleware, request processing, authentication chains, logging, multiple hooks, request/response transformation, path: kit/@sveltejs-kit-hooks
|
||||
- title: @sveltejs/kit/node/polyfills, use_cases: node.js environments, custom servers, non-standard runtimes, ssr setup, web api compatibility, polyfill requirements, path: kit/@sveltejs-kit-node-polyfills
|
||||
- title: @sveltejs/kit/node, use_cases: node.js adapter, custom server setup, http integration, streaming files, node deployment, server-side rendering with node, path: kit/@sveltejs-kit-node
|
||||
- title: @sveltejs/kit/vite, use_cases: project setup, vite configuration, initial sveltekit setup, build tooling, path: kit/@sveltejs-kit-vite
|
||||
- title: $app/environment, use_cases: always, conditional logic, client-side code, server-side code, build-time logic, prerendering, development vs production, environment detection, path: kit/$app-environment
|
||||
- title: $app/forms, use_cases: forms, user input, data submission, progressive enhancement, custom form handling, form validation, path: kit/$app-forms
|
||||
- title: $app/navigation, use_cases: routing, navigation, multi-page apps, programmatic navigation, data reloading, preloading, shallow routing, navigation lifecycle, scroll handling, view transitions, path: kit/$app-navigation
|
||||
- title: $app/paths, use_cases: static assets, images, fonts, public files, base path configuration, subdirectory deployment, cdn setup, asset urls, links, navigation, path: kit/$app-paths
|
||||
- title: $app/server, use_cases: remote functions, server-side logic, data fetching, form handling, api endpoints, client-server communication, prerendering, file reading, batch queries, path: kit/$app-server
|
||||
- title: $app/state, use_cases: routing, navigation, multi-page apps, loading states, url parameters, form handling, error states, version updates, page metadata, shallow routing, path: kit/$app-state
|
||||
- title: $app/stores, use_cases: legacy projects, sveltekit pre-2.12, migration from stores to runes, maintaining older codebases, accessing page data, navigation state, app version updates, path: kit/$app-stores
|
||||
- title: $app/types, use_cases: routing, navigation, type safety, route parameters, dynamic routes, link generation, pathname validation, multi-page apps, path: kit/$app-types
|
||||
- title: $env/dynamic/private, use_cases: api keys, secrets management, server-side config, environment variables, backend logic, deployment-specific settings, private data handling, path: kit/$env-dynamic-private
|
||||
- title: $env/dynamic/public, use_cases: environment variables, client-side config, runtime configuration, public api keys, deployment-specific settings, multi-environment apps, path: kit/$env-dynamic-public
|
||||
- title: $env/static/private, use_cases: server-side api keys, backend secrets, database credentials, private configuration, build-time optimization, server endpoints, authentication tokens, path: kit/$env-static-private
|
||||
- title: $env/static/public, use_cases: environment variables, public config, client-side data, api endpoints, build-time configuration, public constants, path: kit/$env-static-public
|
||||
- title: $lib, use_cases: project setup, component organization, importing shared components, reusable ui elements, code structure, path: kit/$lib
|
||||
- title: $service-worker, use_cases: offline support, pwa, service workers, caching strategies, progressive web apps, offline-first apps, path: kit/$service-worker
|
||||
- title: Configuration, use_cases: project setup, configuration, adapters, deployment, build settings, environment variables, routing customization, prerendering, csp security, csrf protection, path configuration, typescript setup, path: kit/configuration
|
||||
- title: Command Line Interface, use_cases: project setup, typescript configuration, generated types, ./$types imports, initial project configuration, path: kit/cli
|
||||
- title: Types, use_cases: typescript, type safety, route parameters, api endpoints, load functions, form actions, generated types, jsconfig setup, path: kit/types
|
||||
- title: Overview, use_cases: use title and path to estimate use case, path: mcp/overview
|
||||
- title: Local setup, use_cases: use title and path to estimate use case, path: mcp/local-setup
|
||||
- title: Remote setup, use_cases: use title and path to estimate use case, path: mcp/remote-setup
|
||||
- title: Tools, use_cases: use title and path to estimate use case, path: mcp/tools
|
||||
- title: Resources, use_cases: use title and path to estimate use case, path: mcp/resources
|
||||
- title: Prompts, use_cases: use title and path to estimate use case, path: mcp/prompts
|
||||
- title: Overview, use_cases: always, any svelte project, getting started, learning svelte, introduction, project setup, understanding framework basics, path: svelte/overview
|
||||
- title: Getting started, use_cases: project setup, starting new svelte project, initial installation, choosing between sveltekit and vite, editor configuration, path: svelte/getting-started
|
||||
- title: .svelte files, use_cases: always, any svelte project, component creation, project setup, learning svelte basics, path: svelte/svelte-files
|
||||
- title: .svelte.js and .svelte.ts files, use_cases: shared reactive state, reusable reactive logic, state management across components, global stores, custom reactive utilities, path: svelte/svelte-js-files
|
||||
- title: What are runes?, use_cases: always, any svelte 5 project, understanding core syntax, learning svelte 5, migration from svelte 4, path: svelte/what-are-runes
|
||||
- title: $state, use_cases: always, any svelte project, core reactivity, state management, counters, forms, todo apps, interactive ui, data updates, class-based components, path: svelte/$state
|
||||
- title: $derived, use_cases: always, any svelte project, computed values, reactive calculations, derived data, transforming state, dependent values, path: svelte/$derived
|
||||
- title: $effect, use_cases: canvas drawing, third-party library integration, dom manipulation, side effects, intervals, timers, network requests, analytics tracking, path: svelte/$effect
|
||||
- title: $props, use_cases: always, any svelte project, passing data to components, component communication, reusable components, component props, path: svelte/$props
|
||||
- title: $bindable, use_cases: forms, user input, two-way data binding, custom input components, parent-child communication, reusable form fields, path: svelte/$bindable
|
||||
- title: $inspect, use_cases: debugging, development, tracking state changes, reactive state monitoring, troubleshooting reactivity issues, path: svelte/$inspect
|
||||
- title: $host, use_cases: custom elements, web components, dispatching custom events, component library, framework-agnostic components, path: svelte/$host
|
||||
- title: Basic markup, use_cases: always, any svelte project, basic markup, html templating, component structure, attributes, events, props, text rendering, path: svelte/basic-markup
|
||||
- title: {#if ...}, use_cases: always, conditional rendering, showing/hiding content, dynamic ui, user permissions, loading states, error handling, form validation, path: svelte/if
|
||||
- title: {#each ...}, use_cases: always, lists, arrays, iteration, product listings, todos, tables, grids, dynamic content, shopping carts, user lists, comments, feeds, path: svelte/each
|
||||
- title: {#key ...}, use_cases: animations, transitions, component reinitialization, forcing component remount, value-based ui updates, resetting component state, path: svelte/key
|
||||
- title: {#await ...}, use_cases: async data fetching, api calls, loading states, promises, error handling, lazy loading components, dynamic imports, path: svelte/await
|
||||
- title: {#snippet ...}, use_cases: reusable markup, component composition, passing content to components, table rows, list items, conditional rendering, reducing duplication, path: svelte/snippet
|
||||
- title: {@render ...}, use_cases: reusable ui patterns, component composition, conditional rendering, fallback content, layout components, slot alternatives, template reuse, path: svelte/@render
|
||||
- title: {@html ...}, use_cases: rendering html strings, cms content, rich text editors, markdown to html, blog posts, wysiwyg output, sanitized html injection, dynamic html content, path: svelte/@html
|
||||
- title: {@attach ...}, use_cases: tooltips, popovers, dom manipulation, third-party libraries, canvas drawing, element lifecycle, interactive ui, custom directives, wrapper components, path: svelte/@attach
|
||||
- title: {@const ...}, use_cases: computed values in loops, derived calculations in blocks, local variables in each iterations, complex list rendering, path: svelte/@const
|
||||
- title: {@debug ...}, use_cases: debugging, development, troubleshooting, tracking state changes, monitoring variables, reactive data inspection, path: svelte/@debug
|
||||
- title: bind:, use_cases: forms, user input, two-way data binding, interactive ui, media players, file uploads, checkboxes, radio buttons, select dropdowns, contenteditable, dimension tracking, path: svelte/bind
|
||||
- title: use:, use_cases: custom directives, dom manipulation, third-party library integration, tooltips, click outside, gestures, focus management, element lifecycle hooks, path: svelte/use
|
||||
- title: transition:, use_cases: animations, interactive ui, modals, dropdowns, notifications, conditional content, show/hide elements, smooth state changes, path: svelte/transition
|
||||
- title: in: and out:, use_cases: animation, transitions, interactive ui, conditional rendering, independent enter/exit effects, modals, tooltips, notifications, path: svelte/in-and-out
|
||||
- title: animate:, use_cases: sortable lists, drag and drop, reorderable items, todo lists, kanban boards, playlist editors, priority queues, animated list reordering, path: svelte/animate
|
||||
- title: style:, use_cases: dynamic styling, conditional styles, theming, dark mode, responsive design, interactive ui, component styling, path: svelte/style
|
||||
- title: class, use_cases: always, conditional styling, dynamic classes, tailwind css, component styling, reusable components, responsive design, path: svelte/class
|
||||
- title: await, use_cases: async data fetching, loading states, server-side rendering, awaiting promises in components, async validation, concurrent data loading, path: svelte/await-expressions
|
||||
- title: Scoped styles, use_cases: always, styling components, scoped css, component-specific styles, preventing style conflicts, animations, keyframes, path: svelte/scoped-styles
|
||||
- title: Global styles, use_cases: global styles, third-party libraries, css resets, animations, styling body/html, overriding component styles, shared keyframes, base styles, path: svelte/global-styles
|
||||
- title: Custom properties, use_cases: theming, custom styling, reusable components, design systems, dynamic colors, component libraries, ui customization, path: svelte/custom-properties
|
||||
- title: Nested <style> elements, use_cases: component styling, scoped styles, dynamic styles, conditional styling, nested style tags, custom styling logic, path: svelte/nested-style-elements
|
||||
- title: <svelte:boundary>, use_cases: error handling, async data loading, loading states, error recovery, flaky components, error reporting, resilient ui, path: svelte/svelte-boundary
|
||||
- title: <svelte:window>, use_cases: keyboard shortcuts, scroll tracking, window resize handling, responsive layouts, online/offline detection, viewport dimensions, global event listeners, path: svelte/svelte-window
|
||||
- title: <svelte:document>, use_cases: document events, visibility tracking, fullscreen detection, pointer lock, focus management, document-level interactions, path: svelte/svelte-document
|
||||
- title: <svelte:body>, use_cases: mouse tracking, hover effects, cursor interactions, global body events, drag and drop, custom cursors, interactive backgrounds, body-level actions, path: svelte/svelte-body
|
||||
- title: <svelte:head>, use_cases: seo optimization, page titles, meta tags, social media sharing, dynamic head content, multi-page apps, blog posts, product pages, path: svelte/svelte-head
|
||||
- title: <svelte:element>, use_cases: dynamic content, cms integration, user-generated content, configurable ui, runtime element selection, flexible components, path: svelte/svelte-element
|
||||
- title: <svelte:options>, use_cases: migration, custom elements, web components, legacy mode compatibility, runes mode setup, svg components, mathml components, css injection control, path: svelte/svelte-options
|
||||
- title: Stores, use_cases: shared state, cross-component data, reactive values, async data streams, manual control over updates, rxjs integration, extracting logic, path: svelte/stores
|
||||
- title: Context, use_cases: shared state, avoiding prop drilling, component communication, theme providers, user context, authentication state, configuration sharing, deeply nested components, path: svelte/context
|
||||
- title: Lifecycle hooks, use_cases: component initialization, cleanup tasks, timers, subscriptions, dom measurements, chat windows, autoscroll features, migration from svelte 4, path: svelte/lifecycle-hooks
|
||||
- title: Imperative component API, use_cases: project setup, client-side rendering, server-side rendering, ssr, hydration, testing, programmatic component creation, tooltips, dynamic mounting, path: svelte/imperative-component-api
|
||||
- title: Testing, use_cases: testing, quality assurance, unit tests, integration tests, component tests, e2e tests, vitest setup, playwright setup, test automation, path: svelte/testing
|
||||
- title: TypeScript, use_cases: typescript setup, type safety, component props typing, generic components, wrapper components, dom type augmentation, project configuration, path: svelte/typescript
|
||||
- title: Custom elements, use_cases: web components, custom elements, component library, design system, framework-agnostic components, embedding svelte in non-svelte apps, shadow dom, path: svelte/custom-elements
|
||||
- title: Svelte 4 migration guide, use_cases: upgrading svelte 3 to 4, version migration, updating dependencies, breaking changes, legacy project maintenance, path: svelte/v4-migration-guide
|
||||
- title: Svelte 5 migration guide, use_cases: migrating from svelte 4 to 5, upgrading projects, learning svelte 5 syntax changes, runes migration, event handler updates, path: svelte/v5-migration-guide
|
||||
- title: Frequently asked questions, use_cases: getting started, learning svelte, beginner setup, project initialization, vs code setup, formatting, testing, routing, mobile apps, troubleshooting, community support, path: svelte/faq
|
||||
- title: svelte, use_cases: migration from svelte 4 to 5, upgrading legacy code, component lifecycle hooks, context api, mounting components, event dispatchers, typescript component types, path: svelte/svelte
|
||||
- title: svelte/action, use_cases: typescript types, actions, use directive, dom manipulation, element lifecycle, custom behaviors, third-party library integration, path: svelte/svelte-action
|
||||
- title: svelte/animate, use_cases: animated lists, sortable items, drag and drop, reordering elements, todo lists, kanban boards, playlist management, smooth position transitions, path: svelte/svelte-animate
|
||||
- title: svelte/attachments, use_cases: library development, component libraries, programmatic element manipulation, migrating from actions to attachments, spreading props onto elements, path: svelte/svelte-attachments
|
||||
- title: svelte/compiler, use_cases: build tools, custom compilers, ast manipulation, preprocessors, code transformation, migration scripts, syntax analysis, bundler plugins, dev tools, path: svelte/svelte-compiler
|
||||
- title: svelte/easing, use_cases: animations, transitions, custom easing, smooth motion, interactive ui, modals, dropdowns, carousels, page transitions, scroll effects, path: svelte/svelte-easing
|
||||
- title: svelte/events, use_cases: window events, document events, global event listeners, event delegation, programmatic event handling, cleanup functions, media queries, path: svelte/svelte-events
|
||||
- title: svelte/legacy, use_cases: migration from svelte 4 to svelte 5, upgrading legacy code, event modifiers, class components, imperative component instantiation, path: svelte/svelte-legacy
|
||||
- title: svelte/motion, use_cases: animation, smooth transitions, interactive ui, sliders, counters, physics-based motion, drag gestures, accessibility, reduced motion, path: svelte/svelte-motion
|
||||
- title: svelte/reactivity/window, use_cases: responsive design, viewport tracking, scroll effects, window resize handling, online/offline detection, zoom level tracking, path: svelte/svelte-reactivity-window
|
||||
- title: svelte/reactivity, use_cases: reactive data structures, state management with maps/sets, game boards, selection tracking, url manipulation, query params, real-time clocks, media queries, responsive design, path: svelte/svelte-reactivity
|
||||
- title: svelte/server, use_cases: server-side rendering, ssr, static site generation, seo optimization, initial page load, pre-rendering, node.js server, custom server setup, path: svelte/svelte-server
|
||||
- title: svelte/store, use_cases: state management, shared data, reactive stores, cross-component communication, global state, computed values, data synchronization, legacy svelte projects, path: svelte/svelte-store
|
||||
- title: svelte/transition, use_cases: animations, transitions, interactive ui, modals, dropdowns, tooltips, notifications, svg animations, list animations, page transitions, path: svelte/svelte-transition
|
||||
- title: Compiler errors, use_cases: animation, transitions, keyed each blocks, list animations, path: svelte/compiler-errors
|
||||
- title: Compiler warnings, use_cases: accessibility, a11y compliance, wcag standards, screen readers, keyboard navigation, aria attributes, semantic html, interactive elements, path: svelte/compiler-warnings
|
||||
- title: Runtime errors, use_cases: debugging errors, error handling, troubleshooting runtime issues, migration to svelte 5, component binding, effects and reactivity, path: svelte/runtime-errors
|
||||
- title: Runtime warnings, use_cases: debugging state proxies, console logging reactive values, inspecting state changes, development troubleshooting, path: svelte/runtime-warnings
|
||||
- title: Overview, use_cases: migrating from svelte 3/4 to svelte 5, maintaining legacy components, understanding deprecated features, gradual upgrade process, path: svelte/legacy-overview
|
||||
- title: Reactive let/var declarations, use_cases: migration, legacy svelte projects, upgrading from svelte 4, understanding old reactivity, maintaining existing code, learning runes differences, path: svelte/legacy-let
|
||||
- title: Reactive $: statements, use_cases: legacy mode, migration from svelte 4, reactive statements, computed values, derived state, side effects, path: svelte/legacy-reactive-assignments
|
||||
- title: export let, use_cases: legacy mode, migration from svelte 4, maintaining older projects, component props without runes, exporting component methods, renaming reserved word props, path: svelte/legacy-export-let
|
||||
- title: $$props and $$restProps, use_cases: legacy mode migration, component wrappers, prop forwarding, button components, reusable ui components, spreading props to child elements, path: svelte/legacy-$$props-and-$$restProps
|
||||
- title: on:, use_cases: legacy mode, event handling, button clicks, forms, user interactions, component communication, event forwarding, event modifiers, path: svelte/legacy-on
|
||||
- title: <slot>, use_cases: legacy mode, migrating from svelte 4, component composition, reusable components, passing content to components, modals, layouts, wrappers, path: svelte/legacy-slots
|
||||
- title: $$slots, use_cases: legacy mode, conditional slot rendering, optional content sections, checking if slots provided, migrating from legacy to runes, path: svelte/legacy-$$slots
|
||||
- title: <svelte:fragment>, use_cases: named slots, component composition, layout systems, avoiding wrapper divs, legacy svelte projects, slot content organization, path: svelte/legacy-svelte-fragment
|
||||
- title: <svelte:component>, use_cases: dynamic components, component switching, conditional rendering, legacy mode migration, tabbed interfaces, multi-step forms, path: svelte/legacy-svelte-component
|
||||
- title: <svelte:self>, use_cases: recursive components, tree structures, nested menus, file explorers, comment threads, hierarchical data, path: svelte/legacy-svelte-self
|
||||
- title: Imperative component API, use_cases: migration from svelte 3/4 to 5, legacy component api, maintaining old projects, understanding deprecated patterns, path: svelte/legacy-component-api
|
||||
|
||||
</available-docs>
|
||||
|
||||
Every time you write a Svelte component or a Svelte module you MUST invoke the `svelte-autofixer` tool providing the code. The tool will return a list of issues or suggestions. If there are any issues or suggestions you MUST fix them and call the tool again with the updated code. You MUST keep doing this until the tool returns no issues or suggestions. Only then you can return the code to the user.
|
||||
|
||||
This is the task you will work on:
|
||||
|
||||
<task>
|
||||
[your task here]
|
||||
[YOUR TASK HERE]
|
||||
</task>
|
||||
|
||||
If you are not writing the code into a file, once you have the final version of the code ask the user if they want to generate a playground link to quickly check the code in it and if they answer yes call the \`playground-link\` tool and return the url to the user nicely formatted. The playground link MUST be generated only once you have the final version of the code and you are ready to share it, it MUST include an entry point file called \`App.svelte\` where the main component should live. If you have multiple files to include in the playground link you can include them all at the root.
|
||||
If you are not writing the code into a file, once you have the final version of the code ask the user if it wants to generate a playground link to quickly check the code in it and if it answer yes call the `playground-link` tool and return the url to the user nicely formatted. The playground link MUST be generated only once you have the final version of the code and you are ready to share it, it MUST include an entry point file called `App.svelte` where the main component should live. If you have multiple files to include in the playground link you can include them all at the root.
|
||||
```
|
||||
|
||||
</details>
|
||||
|
||||
@@ -37,6 +37,13 @@ export default /** @type {import("eslint").Linter.Config} */ ([
|
||||
leadingUnderscore: 'allow',
|
||||
},
|
||||
],
|
||||
'@typescript-eslint/no-unused-vars': [
|
||||
'error',
|
||||
{
|
||||
varsIgnorePattern: '^_',
|
||||
ignoreRestSiblings: true,
|
||||
},
|
||||
],
|
||||
'func-style': ['error', 'declaration', { allowTypeAnnotation: true }],
|
||||
'import/no-unresolved': 'off', // this doesn't work well with typescript path mapping
|
||||
'import/extensions': [
|
||||
@@ -50,6 +57,7 @@ export default /** @type {import("eslint").Linter.Config} */ ([
|
||||
svelte: 'always',
|
||||
},
|
||||
],
|
||||
'svelte/no-navigation-without-resolve': 'off',
|
||||
},
|
||||
},
|
||||
{
|
||||
|
||||
19
package.json
19
package.json
@@ -3,7 +3,7 @@
|
||||
"version": "0.0.1",
|
||||
"description": "The official Svelte MCP server implementation",
|
||||
"type": "module",
|
||||
"packageManager": "pnpm@10.17.1",
|
||||
"packageManager": "pnpm@10.18.2",
|
||||
"scripts": {
|
||||
"build": "pnpm -r run build",
|
||||
"dev": "pnpm --filter @sveltejs/mcp-remote run dev",
|
||||
@@ -16,7 +16,18 @@
|
||||
"test": "npm run test:unit -- --run",
|
||||
"test:watch": "npm run test:unit -- --watch",
|
||||
"inspect": "pnpm mcp-inspector",
|
||||
"release": "pnpm --filter @sveltejs/mcp run build && changeset publish"
|
||||
"generate-summaries": "pnpm --filter @sveltejs/mcp-server run generate-summaries",
|
||||
"generate-summaries:dry-run": "pnpm --filter @sveltejs/mcp-server run generate-summaries:dry-run",
|
||||
"generate-summaries:debug": "pnpm --filter @sveltejs/mcp-server run generate-summaries:debug",
|
||||
"generate-distilled": "pnpm --filter @sveltejs/mcp-server run generate-distilled",
|
||||
"generate-distilled:dry-run": "pnpm --filter @sveltejs/mcp-server run generate-distilled:dry-run",
|
||||
"generate-distilled:debug": "pnpm --filter @sveltejs/mcp-server run generate-distilled:debug",
|
||||
"verify-distilled": "pnpm --filter @sveltejs/mcp-server run verify-distilled",
|
||||
"show-verification-errors": "pnpm --filter @sveltejs/mcp-server run show-verification-errors",
|
||||
"export-summaries": "pnpm --filter @sveltejs/mcp-server run export-summaries",
|
||||
"generate-prompt-docs": "node --import node-resolve-ts/register scripts/update-docs-prompts.ts",
|
||||
"release": "pnpm --filter @sveltejs/mcp run build && changeset publish",
|
||||
"changeset:version": "changeset version && pnpm --filter @sveltejs/mcp run update:version && git add --all"
|
||||
},
|
||||
"keywords": [
|
||||
"svelte",
|
||||
@@ -29,18 +40,20 @@
|
||||
"@changesets/cli": "^2.29.7",
|
||||
"@eslint/compat": "^1.3.2",
|
||||
"@eslint/js": "^9.36.0",
|
||||
"@modelcontextprotocol/inspector": "^0.16.7",
|
||||
"@modelcontextprotocol/inspector": "^0.17.0",
|
||||
"@svitejs/changesets-changelog-github-compact": "^1.2.0",
|
||||
"eslint": "^9.36.0",
|
||||
"eslint-config-prettier": "^10.0.1",
|
||||
"eslint-plugin-import": "^2.32.0",
|
||||
"eslint-plugin-svelte": "^3.12.3",
|
||||
"globals": "^16.0.0",
|
||||
"node-resolve-ts": "^1.0.2",
|
||||
"prettier": "^3.4.2",
|
||||
"prettier-plugin-svelte": "^3.3.3",
|
||||
"publint": "^0.3.13",
|
||||
"typescript": "^5.0.0",
|
||||
"typescript-eslint": "^8.44.1",
|
||||
"vite-node": "^3.2.4",
|
||||
"vitest": "^3.2.3"
|
||||
},
|
||||
"pnpm": {
|
||||
|
||||
@@ -14,6 +14,6 @@
|
||||
"license": "ISC",
|
||||
"type": "module",
|
||||
"dependencies": {
|
||||
"drizzle-orm": "^0.40.1"
|
||||
"drizzle-orm": "^0.44.0"
|
||||
}
|
||||
}
|
||||
|
||||
2
packages/mcp-server/.env.example
Normal file
2
packages/mcp-server/.env.example
Normal file
@@ -0,0 +1,2 @@
|
||||
# Anthropic API Key from: https://console.anthropic.com/
|
||||
ANTHROPIC_API_KEY=your_api_key_here
|
||||
@@ -9,13 +9,24 @@
|
||||
"license": "ISC",
|
||||
"type": "module",
|
||||
"scripts": {
|
||||
"test": "vitest"
|
||||
"test": "vitest",
|
||||
"generate-summaries": "node --import node-resolve-ts/register scripts/generate-summaries.ts && prettier --write --log-level silent 'src/**/*.{js,ts,json}'",
|
||||
"generate-summaries:dry-run": "node --import node-resolve-ts/register scripts/generate-summaries.ts --dry-run && prettier --write --log-level silent 'src/**/*.{js,ts,json}'",
|
||||
"generate-summaries:debug": "DEBUG_MODE=1 node --import node-resolve-ts/register scripts/generate-summaries.ts && prettier --write --log-level silent 'src/**/*.{js,ts,json}'",
|
||||
"generate-distilled": "node --import node-resolve-ts/register scripts/generate-summaries.ts --prompt-type distilled && prettier --write --log-level silent 'src/**/*.{js,ts,json}'",
|
||||
"generate-distilled:dry-run": "node --import node-resolve-ts/register scripts/generate-summaries.ts --prompt-type distilled --dry-run && prettier --write --log-level silent 'src/**/*.{js,ts,json}'",
|
||||
"generate-distilled:debug": "DEBUG_MODE=1 node --import node-resolve-ts/register scripts/generate-summaries.ts --prompt-type distilled && prettier --write --log-level silent 'src/**/*.{js,ts,json}'",
|
||||
"verify-distilled": "node --import node-resolve-ts/register scripts/verify-distilled.ts",
|
||||
"show-verification-errors": "node --import node-resolve-ts/register scripts/show-verification-errors.ts",
|
||||
"export-summaries": "node --import node-resolve-ts/register scripts/export-summaries.ts && prettier --write --log-level silent 'src/**/*.{js,ts,json}'"
|
||||
},
|
||||
"exports": {
|
||||
".": "./src/index.ts"
|
||||
".": "./src/index.ts",
|
||||
"./distilled.json": "./src/distilled.json",
|
||||
"./use-cases.json": "./src/use_cases.json"
|
||||
},
|
||||
"peerDependencies": {
|
||||
"drizzle-orm": "^0.40.0"
|
||||
"drizzle-orm": "^0.44.0"
|
||||
},
|
||||
"dependencies": {
|
||||
"@sveltejs/mcp-schema": "workspace:^",
|
||||
@@ -26,15 +37,19 @@
|
||||
"svelte": "^5.39.2",
|
||||
"svelte-eslint-parser": "^1.3.2",
|
||||
"tmcp": "^1.13.0",
|
||||
"ts-blank-space": "^0.6.2",
|
||||
"typescript-eslint": "^8.44.0",
|
||||
"valibot": "^1.1.0",
|
||||
"vitest": "^3.2.4",
|
||||
"zimmerframe": "^1.1.4"
|
||||
},
|
||||
"devDependencies": {
|
||||
"@anthropic-ai/sdk": "^0.65.0",
|
||||
"@sveltejs/kit": "^2.42.2",
|
||||
"@types/eslint-scope": "^8.3.2",
|
||||
"@types/estree": "^1.0.8",
|
||||
"@typescript-eslint/types": "^8.44.0"
|
||||
"@typescript-eslint/types": "^8.44.0",
|
||||
"commander": "^13.1.0",
|
||||
"dotenv": "^17.2.3"
|
||||
}
|
||||
}
|
||||
|
||||
108
packages/mcp-server/scripts/export-summaries.ts
Normal file
108
packages/mcp-server/scripts/export-summaries.ts
Normal file
@@ -0,0 +1,108 @@
|
||||
#!/usr/bin/env node
|
||||
import 'dotenv/config';
|
||||
import { readFile, access } from 'node:fs/promises';
|
||||
import path from 'node:path';
|
||||
import { fileURLToPath } from 'node:url';
|
||||
import { Command } from 'commander';
|
||||
import * as v from 'valibot';
|
||||
import { summary_data_schema, type SummaryData } from '../src/lib/schemas.ts';
|
||||
import { export_summaries_to_markdown } from './lib/export-markdown.ts';
|
||||
|
||||
interface CliOptions {
|
||||
type: 'use_cases' | 'distilled' | 'both';
|
||||
}
|
||||
|
||||
const current_filename = fileURLToPath(import.meta.url);
|
||||
const current_dirname = path.dirname(current_filename);
|
||||
|
||||
const program = new Command();
|
||||
|
||||
program
|
||||
.name('export-summaries')
|
||||
.description('Export summaries from JSON files to individual markdown files')
|
||||
.version('1.0.0')
|
||||
.option('-t, --type <type>', 'Type to export: "use_cases", "distilled", or "both"', 'both');
|
||||
|
||||
async function read_file_as_string(
|
||||
file_path: string,
|
||||
encoding: BufferEncoding = 'utf-8',
|
||||
): Promise<string> {
|
||||
const content = await readFile(file_path, encoding);
|
||||
return v.parse(v.string(), content);
|
||||
}
|
||||
|
||||
async function load_summaries_json(output_path: string): Promise<SummaryData | null> {
|
||||
try {
|
||||
await access(output_path);
|
||||
} catch {
|
||||
return null;
|
||||
}
|
||||
|
||||
const content = await read_file_as_string(output_path, 'utf-8');
|
||||
const data = JSON.parse(content);
|
||||
|
||||
const validated = v.safeParse(summary_data_schema, data);
|
||||
if (!validated.success) {
|
||||
throw new Error(
|
||||
`File has invalid schema: ${output_path}\n` +
|
||||
`Validation errors: ${JSON.stringify(validated.issues, null, 2)}`,
|
||||
);
|
||||
}
|
||||
|
||||
return validated.output;
|
||||
}
|
||||
|
||||
async function export_summaries_for_type(type: 'use_cases' | 'distilled'): Promise<void> {
|
||||
const json_filename = type === 'distilled' ? 'distilled.json' : 'use_cases.json';
|
||||
const input_path = path.join(current_dirname, `../src/${json_filename}`);
|
||||
|
||||
console.log(`\n📁 Processing ${type.toUpperCase()}...`);
|
||||
console.log(` Input: ${json_filename}`);
|
||||
|
||||
// Load the JSON file
|
||||
console.log(` 📂 Loading ${json_filename}...`);
|
||||
const data = await load_summaries_json(input_path);
|
||||
|
||||
if (!data) {
|
||||
console.error(` ❌ Error: Could not load ${json_filename}`);
|
||||
return;
|
||||
}
|
||||
|
||||
const summaries = data.summaries;
|
||||
console.log(` ✅ Found ${Object.keys(summaries).length} summaries`);
|
||||
|
||||
// Use shared export function
|
||||
await export_summaries_to_markdown(summaries, type, path.join(current_dirname, '../summaries'));
|
||||
}
|
||||
|
||||
async function main() {
|
||||
program.parse();
|
||||
const options = program.opts<CliOptions>();
|
||||
|
||||
console.log('🚀 Starting summary export...');
|
||||
|
||||
// Validate type option
|
||||
if (!['use_cases', 'distilled', 'both'].includes(options.type)) {
|
||||
console.error('❌ Error: --type must be "use_cases", "distilled", or "both"');
|
||||
process.exit(1);
|
||||
}
|
||||
|
||||
// Export based on type option
|
||||
if (options.type === 'both') {
|
||||
await export_summaries_for_type('use_cases');
|
||||
await export_summaries_for_type('distilled');
|
||||
} else {
|
||||
await export_summaries_for_type(options.type);
|
||||
}
|
||||
|
||||
console.log('\n✅ Export complete!');
|
||||
console.log(
|
||||
'\n📊 Summary files have been written to:',
|
||||
path.join(current_dirname, '../summaries/'),
|
||||
);
|
||||
}
|
||||
|
||||
main().catch((error) => {
|
||||
console.error('❌ Fatal error:', error);
|
||||
process.exit(1);
|
||||
});
|
||||
447
packages/mcp-server/scripts/generate-summaries.ts
Normal file
447
packages/mcp-server/scripts/generate-summaries.ts
Normal file
@@ -0,0 +1,447 @@
|
||||
#!/usr/bin/env node
|
||||
import 'dotenv/config';
|
||||
import { writeFile, mkdir, readFile, access } from 'node:fs/promises';
|
||||
import path from 'node:path';
|
||||
import { fileURLToPath } from 'node:url';
|
||||
import { Command } from 'commander';
|
||||
import { get_sections } from '../src/mcp/utils.ts';
|
||||
import { AnthropicProvider } from '../src/lib/anthropic.ts';
|
||||
import {
|
||||
type AnthropicBatchRequest,
|
||||
type SummaryData,
|
||||
summary_data_schema,
|
||||
} from '../src/lib/schemas.ts';
|
||||
import * as v from 'valibot';
|
||||
import { DISTILLED_PROMPT, USE_CASES_PROMPT } from '../src/mcp/handlers/tools/prompts.ts';
|
||||
import { export_summaries_to_markdown } from './lib/export-markdown.ts';
|
||||
|
||||
interface CliOptions {
|
||||
force: boolean;
|
||||
dryRun: boolean;
|
||||
debug: boolean;
|
||||
promptType: 'use-cases' | 'distilled';
|
||||
}
|
||||
|
||||
interface SectionChange {
|
||||
slug: string;
|
||||
title: string;
|
||||
url: string;
|
||||
change_type: 'new' | 'changed' | 'removed';
|
||||
}
|
||||
|
||||
const current_filename = fileURLToPath(import.meta.url);
|
||||
const current_dirname = path.dirname(current_filename);
|
||||
|
||||
async function read_file_as_string(
|
||||
file_path: string,
|
||||
encoding: BufferEncoding = 'utf-8',
|
||||
): Promise<string> {
|
||||
const content = await readFile(file_path, encoding);
|
||||
return v.parse(v.string(), content);
|
||||
}
|
||||
|
||||
const program = new Command();
|
||||
|
||||
program
|
||||
.name('generate-summaries')
|
||||
.description('Generate use case summaries for Svelte documentation sections')
|
||||
.version('1.0.0')
|
||||
.option('-f, --force', 'Force regeneration of all summaries', false)
|
||||
.option('-d, --dry-run', 'Show what would be changed without making API calls', false)
|
||||
.option('--debug', 'Debug mode: process only 2 sections', false)
|
||||
.option(
|
||||
'-p, --prompt-type <type>',
|
||||
'Prompt type to use: "use-cases" or "distilled"',
|
||||
'use-cases',
|
||||
);
|
||||
|
||||
async function fetch_section_content(url: string) {
|
||||
const response = await fetch(url, { signal: AbortSignal.timeout(30000) });
|
||||
if (!response.ok) {
|
||||
throw new Error(`Failed to fetch ${url}: ${response.status} ${response.statusText}`);
|
||||
}
|
||||
return await response.text();
|
||||
}
|
||||
|
||||
export async function load_existing_summaries(output_path: string): Promise<SummaryData | null> {
|
||||
try {
|
||||
await access(output_path);
|
||||
} catch {
|
||||
return null;
|
||||
}
|
||||
|
||||
const content = await read_file_as_string(output_path, 'utf-8');
|
||||
const data = JSON.parse(content);
|
||||
|
||||
const validated = v.safeParse(summary_data_schema, data);
|
||||
if (!validated.success) {
|
||||
throw new Error(
|
||||
`Existing file has invalid schema. Please fix or delete the file at: ${output_path}\n` +
|
||||
`Validation errors: ${JSON.stringify(validated.issues, null, 2)}`,
|
||||
);
|
||||
}
|
||||
|
||||
return validated.output;
|
||||
}
|
||||
|
||||
function detect_changes(
|
||||
current_sections: Array<{ slug: string; title: string; url: string }>,
|
||||
existing_data: SummaryData | null,
|
||||
current_content: Map<string, string>,
|
||||
force: boolean,
|
||||
): {
|
||||
to_process: Array<{ slug: string; title: string; url: string }>;
|
||||
to_remove: string[];
|
||||
changes: SectionChange[];
|
||||
} {
|
||||
if (!existing_data || force) {
|
||||
// First run or force regeneration
|
||||
return {
|
||||
to_process: current_sections,
|
||||
to_remove: [],
|
||||
changes: current_sections.map((s) => ({
|
||||
...s,
|
||||
change_type: force ? 'changed' : 'new',
|
||||
})),
|
||||
};
|
||||
}
|
||||
|
||||
const existing_summaries = existing_data.summaries;
|
||||
const existing_content = existing_data.content;
|
||||
const existing_slugs = new Set(Object.keys(existing_summaries));
|
||||
const current_slugs = new Set(current_sections.map((s) => s.slug));
|
||||
|
||||
const sections_to_process: typeof current_sections = [];
|
||||
const changes: SectionChange[] = [];
|
||||
|
||||
// Check for new and changed sections
|
||||
for (const section of current_sections) {
|
||||
const content = current_content.get(section.slug);
|
||||
if (!content) {
|
||||
throw new Error(`No content found for section: ${section.slug}`);
|
||||
}
|
||||
|
||||
if (!existing_slugs.has(section.slug)) {
|
||||
// New section
|
||||
sections_to_process.push(section);
|
||||
changes.push({ ...section, change_type: 'new' });
|
||||
} else {
|
||||
// Existing section - check if content changed
|
||||
const stored_content = existing_content[section.slug] ?? '';
|
||||
|
||||
if (content !== stored_content) {
|
||||
// Content has changed
|
||||
sections_to_process.push(section);
|
||||
changes.push({ ...section, change_type: 'changed' });
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// Find removed sections
|
||||
const removed_slugs: string[] = [];
|
||||
for (const slug of existing_slugs) {
|
||||
if (!current_slugs.has(slug)) {
|
||||
removed_slugs.push(slug);
|
||||
changes.push({
|
||||
slug,
|
||||
title: '<removed>',
|
||||
url: '',
|
||||
change_type: 'removed',
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
return {
|
||||
to_process: sections_to_process,
|
||||
to_remove: removed_slugs,
|
||||
changes,
|
||||
};
|
||||
}
|
||||
|
||||
async function main() {
|
||||
program.parse();
|
||||
const options = program.opts<CliOptions>();
|
||||
|
||||
// Allow DEBUG_MODE env var as well
|
||||
const debug = options.debug || process.env.DEBUG_MODE === '1';
|
||||
|
||||
console.log('🚀 Starting use cases generation...');
|
||||
|
||||
// Determine output file based on prompt type
|
||||
const output_filename = options.promptType === 'distilled' ? 'distilled.json' : 'use_cases.json';
|
||||
const output_path = path.join(current_dirname, `../src/${output_filename}`);
|
||||
|
||||
// Select prompt based on prompt type
|
||||
const selected_prompt = options.promptType === 'distilled' ? DISTILLED_PROMPT : USE_CASES_PROMPT;
|
||||
|
||||
// Display mode information
|
||||
console.log(`📝 PROMPT MODE: ${options.promptType.toUpperCase()} → ${output_filename}\n`);
|
||||
if (options.dryRun) {
|
||||
console.log('🔍 DRY RUN MODE - No API calls will be made\n');
|
||||
}
|
||||
if (options.force) {
|
||||
console.log('⚡ FORCE MODE - Regenerating all summaries\n');
|
||||
}
|
||||
if (debug) {
|
||||
console.log('🐛 DEBUG MODE - Will process only 2 sections\n');
|
||||
}
|
||||
|
||||
// Load existing summaries
|
||||
console.log('📂 Loading existing summaries...');
|
||||
const existing_data = await load_existing_summaries(output_path);
|
||||
|
||||
if (existing_data) {
|
||||
console.log(
|
||||
`✅ Found existing summaries with ${Object.keys(existing_data.summaries).length} entries`,
|
||||
);
|
||||
} else {
|
||||
console.log('📝 No existing summaries found - will process all sections');
|
||||
}
|
||||
|
||||
console.log('📚 Fetching documentation sections...');
|
||||
const all_sections = await get_sections();
|
||||
console.log(`Found ${all_sections.length} sections from API`);
|
||||
|
||||
// Download content for ALL sections (needed to compute hashes)
|
||||
console.log('\n📥 Downloading section content...');
|
||||
const section_content = new Map<string, string>();
|
||||
|
||||
for (let i = 0; i < all_sections.length; i++) {
|
||||
const section = all_sections[i]!;
|
||||
console.log(` Fetching ${i + 1}/${all_sections.length}: ${section.title}`);
|
||||
const content = await fetch_section_content(section.url);
|
||||
section_content.set(section.slug, content);
|
||||
}
|
||||
|
||||
console.log(`✅ Successfully downloaded ${section_content.size} sections`);
|
||||
|
||||
// Detect what needs to be processed
|
||||
console.log('\n🔍 Checking for content changes...');
|
||||
const { to_process, to_remove, changes } = detect_changes(
|
||||
all_sections,
|
||||
existing_data,
|
||||
section_content,
|
||||
options.force,
|
||||
);
|
||||
|
||||
// Display changes
|
||||
console.log('\n📊 Change Summary:');
|
||||
const new_count = changes.filter((c) => c.change_type === 'new').length;
|
||||
const changed_count = changes.filter((c) => c.change_type === 'changed').length;
|
||||
const removed_count = changes.filter((c) => c.change_type === 'removed').length;
|
||||
|
||||
console.log(` ✨ New sections: ${new_count}`);
|
||||
console.log(` 🔄 Changed sections: ${changed_count}`);
|
||||
console.log(` ❌ Removed sections: ${removed_count}`);
|
||||
console.log(` 📝 To process: ${to_process.length}`);
|
||||
|
||||
if (changes.length > 0) {
|
||||
console.log('\n📋 Detailed changes:');
|
||||
for (const change of changes) {
|
||||
const emoji =
|
||||
change.change_type === 'new' ? ' ✨' : change.change_type === 'changed' ? ' 🔄' : ' ❌';
|
||||
console.log(`${emoji} [${change.change_type.toUpperCase()}] ${change.slug}`);
|
||||
}
|
||||
}
|
||||
|
||||
// Exit early if nothing to do
|
||||
if (to_process.length === 0 && to_remove.length === 0) {
|
||||
console.log('\n✅ No changes detected - everything is up to date!');
|
||||
return;
|
||||
}
|
||||
|
||||
// Debug mode: limit sections
|
||||
let sections_to_process = to_process;
|
||||
if (debug) {
|
||||
console.log('\n🐛 Processing only 2 sections for debugging');
|
||||
sections_to_process = to_process.slice(0, 2);
|
||||
}
|
||||
|
||||
// Dry run mode: exit before API calls
|
||||
if (options.dryRun) {
|
||||
console.log('\n🔍 DRY RUN complete - no changes were made');
|
||||
console.log(`Would have processed ${sections_to_process.length} sections`);
|
||||
console.log(`Would have removed ${to_remove.length} sections`);
|
||||
return;
|
||||
}
|
||||
|
||||
// Process with Anthropic API if we have sections to process
|
||||
const new_summaries: Record<string, string> = {};
|
||||
const sections_with_content: Array<{
|
||||
section: (typeof sections_to_process)[number];
|
||||
content: string;
|
||||
index: number;
|
||||
}> = [];
|
||||
|
||||
if (sections_to_process.length === 0) {
|
||||
console.log('\n📦 Only removing old sections, no API calls needed');
|
||||
} else {
|
||||
// Check for API key
|
||||
const api_key = process.env.ANTHROPIC_API_KEY;
|
||||
if (!api_key) {
|
||||
console.error('❌ Error: ANTHROPIC_API_KEY environment variable is required');
|
||||
console.error('Please set it in packages/mcp-server/.env file or export it:');
|
||||
console.error('export ANTHROPIC_API_KEY=your_api_key_here');
|
||||
process.exit(1);
|
||||
}
|
||||
|
||||
// Build sections_with_content from already-downloaded content
|
||||
console.log('\n📦 Preparing sections for processing...');
|
||||
|
||||
for (let i = 0; i < sections_to_process.length; i++) {
|
||||
const section = sections_to_process[i]!;
|
||||
const content = section_content.get(section.slug);
|
||||
|
||||
if (!content) {
|
||||
throw new Error(`No content available for ${section.title}`);
|
||||
}
|
||||
|
||||
sections_with_content.push({
|
||||
section,
|
||||
content,
|
||||
index: i,
|
||||
});
|
||||
}
|
||||
|
||||
console.log(`✅ Prepared ${sections_with_content.length} sections for processing`);
|
||||
|
||||
console.log('\n🤖 Initializing Anthropic API...');
|
||||
const anthropic = new AnthropicProvider('claude-sonnet-4-5-20250929', api_key);
|
||||
|
||||
// Prepare batch requests
|
||||
console.log('📦 Preparing batch requests...');
|
||||
const batch_requests: AnthropicBatchRequest[] = sections_with_content.map(
|
||||
({ content, index }) => ({
|
||||
custom_id: `section-${index}`,
|
||||
params: {
|
||||
model: anthropic.get_model_identifier(),
|
||||
max_tokens: 8192,
|
||||
messages: [
|
||||
{
|
||||
role: 'user',
|
||||
content:
|
||||
`<instructions>${selected_prompt}</instructions>` +
|
||||
`<documentation>${content}</documentation>`,
|
||||
},
|
||||
],
|
||||
temperature: 0,
|
||||
},
|
||||
}),
|
||||
);
|
||||
|
||||
// Create and process batch
|
||||
console.log('🚀 Creating batch job...');
|
||||
const batch_response = await anthropic.create_batch(batch_requests);
|
||||
console.log(`✅ Batch created with ID: ${batch_response.id}`);
|
||||
|
||||
// Poll for completion
|
||||
console.log('⏳ Waiting for batch to complete...');
|
||||
let batch_status = await anthropic.get_batch_status(batch_response.id);
|
||||
|
||||
while (batch_status.processing_status === 'in_progress') {
|
||||
const { succeeded, processing, errored } = batch_status.request_counts;
|
||||
console.log(
|
||||
` Progress: ${succeeded} succeeded, ${processing} processing, ${errored} errored`,
|
||||
);
|
||||
await new Promise((resolve) => setTimeout(resolve, 5000));
|
||||
batch_status = await anthropic.get_batch_status(batch_response.id);
|
||||
}
|
||||
|
||||
console.log('✅ Batch processing completed!');
|
||||
|
||||
// Get results
|
||||
if (!batch_status.results_url) {
|
||||
throw new Error('Batch completed but no results URL available');
|
||||
}
|
||||
|
||||
console.log('📥 Downloading results...');
|
||||
const results = await anthropic.get_batch_results(batch_status.results_url);
|
||||
|
||||
// Process results
|
||||
console.log('📊 Processing results...');
|
||||
|
||||
for (const result of results) {
|
||||
const index = parseInt(result.custom_id.split('-')[1] ?? '0');
|
||||
const section_data = sections_with_content.find((s) => s.index === index);
|
||||
|
||||
if (!section_data) {
|
||||
throw new Error(`Could not find section for index ${index}`);
|
||||
}
|
||||
|
||||
const { section } = section_data;
|
||||
|
||||
if (result.result.type !== 'succeeded' || !result.result.message) {
|
||||
const error_msg = result.result.error?.message || 'Failed or no message';
|
||||
throw new Error(`Failed to generate summary for ${section.title}: ${error_msg}`);
|
||||
}
|
||||
|
||||
const output_content = result.result.message.content[0]?.text;
|
||||
if (!output_content) {
|
||||
throw new Error(`No text content in result for ${section.title}`);
|
||||
}
|
||||
|
||||
new_summaries[section.slug] = output_content.trim();
|
||||
console.log(` ✅ ${section.title}`);
|
||||
}
|
||||
|
||||
// Merge with existing summaries
|
||||
console.log('\n📦 Merging results...');
|
||||
}
|
||||
|
||||
// Start with existing summaries or empty object
|
||||
const merged_summaries: Record<string, string> = existing_data
|
||||
? { ...existing_data.summaries }
|
||||
: {};
|
||||
|
||||
// Add/update new summaries
|
||||
Object.assign(merged_summaries, new_summaries);
|
||||
|
||||
// Remove deleted sections from summaries
|
||||
for (const slug of to_remove) {
|
||||
delete merged_summaries[slug];
|
||||
console.log(` 🗑️ Removed: ${slug}`);
|
||||
}
|
||||
|
||||
// Write output
|
||||
console.log('\n💾 Writing results to file...');
|
||||
const output_dir = path.dirname(output_path);
|
||||
await mkdir(output_dir, { recursive: true });
|
||||
|
||||
const summary_data: SummaryData = {
|
||||
generated_at: new Date().toISOString(),
|
||||
model: 'claude-sonnet-4-5-20250929',
|
||||
total_sections: all_sections.length,
|
||||
successful_summaries: Object.keys(merged_summaries).length,
|
||||
summaries: merged_summaries,
|
||||
content: Object.fromEntries(section_content),
|
||||
};
|
||||
|
||||
await writeFile(output_path, JSON.stringify(summary_data, null, 2), 'utf-8');
|
||||
|
||||
// Export summaries to markdown files
|
||||
console.log('\n📁 Exporting summaries to markdown files...');
|
||||
const markdown_type = options.promptType === 'distilled' ? 'distilled' : 'use_cases';
|
||||
const markdown_files_created = await export_summaries_to_markdown(
|
||||
merged_summaries,
|
||||
markdown_type,
|
||||
path.join(current_dirname, '../summaries'),
|
||||
);
|
||||
|
||||
// Print summary
|
||||
console.log('\n📊 Final Summary:');
|
||||
console.log(` Total sections in API: ${all_sections.length}`);
|
||||
console.log(` Sections processed: ${sections_with_content.length}`);
|
||||
console.log(` New summaries generated: ${Object.keys(new_summaries).length}`);
|
||||
console.log(` Sections removed: ${to_remove.length}`);
|
||||
console.log(` Total summaries in file: ${Object.keys(merged_summaries).length}`);
|
||||
console.log(` Markdown files created: ${markdown_files_created}`);
|
||||
console.log(`\n✅ Results written to: ${output_path}`);
|
||||
console.log(
|
||||
`✅ Markdown files written to: ${path.join(current_dirname, `../summaries/${markdown_type}/`)}`,
|
||||
);
|
||||
}
|
||||
|
||||
main().catch((error) => {
|
||||
console.error('❌ Fatal error:', error);
|
||||
process.exit(1);
|
||||
});
|
||||
54
packages/mcp-server/scripts/lib/export-markdown.ts
Normal file
54
packages/mcp-server/scripts/lib/export-markdown.ts
Normal file
@@ -0,0 +1,54 @@
|
||||
import { writeFile, mkdir, rm } from 'node:fs/promises';
|
||||
import path from 'node:path';
|
||||
|
||||
/**
|
||||
* Export summaries to markdown files in nested directory structure
|
||||
* @param summaries - Record of slug -> content mappings
|
||||
* @param type - Type of summaries ('use_cases' or 'distilled')
|
||||
* @param base_dir - Base directory for summaries (e.g., 'packages/mcp-server/summaries')
|
||||
* @returns Number of files created
|
||||
*/
|
||||
export async function export_summaries_to_markdown(
|
||||
summaries: Record<string, string>,
|
||||
type: 'use_cases' | 'distilled',
|
||||
base_dir: string,
|
||||
): Promise<number> {
|
||||
const output_base_dir = path.join(base_dir, type);
|
||||
const summary_count = Object.keys(summaries).length;
|
||||
|
||||
console.log(` 📁 Target: summaries/${type}/`);
|
||||
console.log(` 📊 Total summaries: ${summary_count}`);
|
||||
|
||||
// Clean existing directory for this type
|
||||
console.log(` 🧹 Cleaning ${type} directory...`);
|
||||
try {
|
||||
await rm(output_base_dir, { recursive: true, force: true });
|
||||
} catch {
|
||||
// Directory might not exist, that's okay
|
||||
}
|
||||
|
||||
// Create base output directory
|
||||
await mkdir(output_base_dir, { recursive: true });
|
||||
|
||||
let created_count = 0;
|
||||
|
||||
// Write each summary to a markdown file
|
||||
for (const [slug, content] of Object.entries(summaries)) {
|
||||
const file_path = path.join(output_base_dir, `${slug}.md`);
|
||||
const file_dir = path.dirname(file_path);
|
||||
|
||||
// Create nested directories if needed
|
||||
await mkdir(file_dir, { recursive: true });
|
||||
|
||||
// Write the markdown file
|
||||
await writeFile(file_path, content, 'utf-8');
|
||||
created_count++;
|
||||
|
||||
if (created_count % 10 === 0) {
|
||||
console.log(` 📝 Created ${created_count}/${summary_count} files...`);
|
||||
}
|
||||
}
|
||||
|
||||
console.log(` ✅ Successfully created ${created_count} markdown files`);
|
||||
return created_count;
|
||||
}
|
||||
91
packages/mcp-server/scripts/show-verification-errors.ts
Normal file
91
packages/mcp-server/scripts/show-verification-errors.ts
Normal file
@@ -0,0 +1,91 @@
|
||||
#!/usr/bin/env node
|
||||
import { readFile } from 'node:fs/promises';
|
||||
import path from 'node:path';
|
||||
import { fileURLToPath } from 'node:url';
|
||||
import * as v from 'valibot';
|
||||
|
||||
const current_filename = fileURLToPath(import.meta.url);
|
||||
const current_dirname = path.dirname(current_filename);
|
||||
|
||||
const verification_output_schema = v.object({
|
||||
generated_at: v.string(),
|
||||
model: v.string(),
|
||||
total_sections: v.number(),
|
||||
verified_sections: v.number(),
|
||||
accurate_count: v.number(),
|
||||
not_accurate_count: v.number(),
|
||||
results: v.array(
|
||||
v.object({
|
||||
slug: v.string(),
|
||||
status: v.union([v.literal('ACCURATE'), v.literal('NOT_ACCURATE')]),
|
||||
reasoning: v.string(),
|
||||
}),
|
||||
),
|
||||
});
|
||||
|
||||
async function main() {
|
||||
const verification_path = path.join(current_dirname, '../src/distilled-verification.json');
|
||||
|
||||
console.log('📂 Reading verification results...\n');
|
||||
|
||||
let content: string;
|
||||
try {
|
||||
content = await readFile(verification_path, 'utf-8');
|
||||
} catch {
|
||||
console.error('❌ Error: Could not find distilled-verification.json');
|
||||
console.error('Please run `pnpm verify-distilled` first to generate the file.');
|
||||
process.exit(1);
|
||||
}
|
||||
|
||||
const data = JSON.parse(content);
|
||||
const validated = v.safeParse(verification_output_schema, data);
|
||||
|
||||
if (!validated.success) {
|
||||
console.error('❌ Error: Invalid verification file format');
|
||||
console.error(JSON.stringify(validated.issues, null, 2));
|
||||
process.exit(1);
|
||||
}
|
||||
|
||||
const verification_data = validated.output;
|
||||
|
||||
// Filter for NOT_ACCURATE results
|
||||
const not_accurate = verification_data.results.filter((r) => r.status === 'NOT_ACCURATE');
|
||||
|
||||
// Print header
|
||||
console.log('📊 Verification Results Summary');
|
||||
console.log('═'.repeat(80));
|
||||
console.log(`Generated: ${new Date(verification_data.generated_at).toLocaleString()}`);
|
||||
console.log(`Model: ${verification_data.model}`);
|
||||
console.log(`Total Sections: ${verification_data.total_sections}`);
|
||||
console.log(`Verified: ${verification_data.verified_sections}`);
|
||||
console.log(
|
||||
`✅ Accurate: ${verification_data.accurate_count} (${((verification_data.accurate_count / verification_data.verified_sections) * 100).toFixed(1)}%)`,
|
||||
);
|
||||
console.log(
|
||||
`❌ Not Accurate: ${verification_data.not_accurate_count} (${((verification_data.not_accurate_count / verification_data.verified_sections) * 100).toFixed(1)}%)`,
|
||||
);
|
||||
console.log('═'.repeat(80));
|
||||
|
||||
if (not_accurate.length === 0) {
|
||||
console.log('\n🎉 All sections are accurate! No issues found.');
|
||||
return;
|
||||
}
|
||||
|
||||
// Print all NOT_ACCURATE entries
|
||||
console.log(`\n❌ NOT ACCURATE SECTIONS (${not_accurate.length}):\n`);
|
||||
|
||||
for (let i = 0; i < not_accurate.length; i++) {
|
||||
const result = not_accurate[i]!;
|
||||
console.log(`${i + 1}. ${result.slug}`);
|
||||
console.log(` Reasoning: ${result.reasoning}`);
|
||||
console.log('');
|
||||
}
|
||||
|
||||
console.log('═'.repeat(80));
|
||||
console.log(`\nFound ${not_accurate.length} section(s) that need review or regeneration.`);
|
||||
}
|
||||
|
||||
main().catch((error) => {
|
||||
console.error('❌ Fatal error:', error);
|
||||
process.exit(1);
|
||||
});
|
||||
6
packages/mcp-server/scripts/tsconfig.json
Normal file
6
packages/mcp-server/scripts/tsconfig.json
Normal file
@@ -0,0 +1,6 @@
|
||||
{
|
||||
"extends": "../../../tsconfig.json",
|
||||
"compilerOptions": {
|
||||
"allowImportingTsExtensions": true
|
||||
}
|
||||
}
|
||||
292
packages/mcp-server/scripts/verify-distilled.ts
Normal file
292
packages/mcp-server/scripts/verify-distilled.ts
Normal file
@@ -0,0 +1,292 @@
|
||||
#!/usr/bin/env node
|
||||
import 'dotenv/config';
|
||||
import { writeFile, mkdir } from 'node:fs/promises';
|
||||
import path from 'node:path';
|
||||
import { fileURLToPath } from 'node:url';
|
||||
import { AnthropicProvider } from '../src/lib/anthropic.ts';
|
||||
import type { AnthropicBatchRequest } from '../src/lib/schemas.ts';
|
||||
import distilled_data from '../src/distilled.json' with { type: 'json' };
|
||||
import * as v from 'valibot';
|
||||
|
||||
interface VerificationResult {
|
||||
slug: string;
|
||||
status: 'ACCURATE' | 'NOT_ACCURATE';
|
||||
reasoning: string;
|
||||
}
|
||||
|
||||
interface VerificationOutput {
|
||||
generated_at: string;
|
||||
model: string;
|
||||
total_sections: number;
|
||||
verified_sections: number;
|
||||
accurate_count: number;
|
||||
not_accurate_count: number;
|
||||
results: VerificationResult[];
|
||||
}
|
||||
|
||||
const current_filename = fileURLToPath(import.meta.url);
|
||||
const current_dirname = path.dirname(current_filename);
|
||||
|
||||
const verification_output_schema = v.object({
|
||||
generated_at: v.string(),
|
||||
model: v.string(),
|
||||
total_sections: v.number(),
|
||||
verified_sections: v.number(),
|
||||
accurate_count: v.number(),
|
||||
not_accurate_count: v.number(),
|
||||
results: v.array(
|
||||
v.object({
|
||||
slug: v.string(),
|
||||
status: v.union([v.literal('ACCURATE'), v.literal('NOT_ACCURATE')]),
|
||||
reasoning: v.string(),
|
||||
}),
|
||||
),
|
||||
});
|
||||
|
||||
const VERIFICATION_PROMPT = `You are tasked with verifying the accuracy of a distilled/condensed version of documentation against the original content.
|
||||
|
||||
Your task:
|
||||
1. Read both the ORIGINAL documentation and the DISTILLED version provided below
|
||||
2. Determine if the distilled version accurately represents the key information from the original
|
||||
3. Check for any factual errors, misleading statements, or critical omissions
|
||||
4. Return your verdict as either "ACCURATE" or "NOT_ACCURATE"
|
||||
|
||||
Guidelines for determining accuracy:
|
||||
- ACCURATE: The distilled version correctly captures the essential information, even if shortened
|
||||
- ACCURATE: Minor formatting changes or reasonable simplifications are acceptable
|
||||
- ACCURATE: Examples may be condensed as long as the core concept is preserved
|
||||
- NOT_ACCURATE: Any factual errors or contradictions with the original
|
||||
- NOT_ACCURATE: Missing critical information that would mislead developers
|
||||
- NOT_ACCURATE: Incorrect code examples or API usage
|
||||
|
||||
You must respond in exactly this format:
|
||||
|
||||
STATUS: [ACCURATE or NOT_ACCURATE]
|
||||
REASONING: [Brief explanation of your decision in one sentence]
|
||||
|
||||
Do not include any other text, formatting, or markdown in your response.`;
|
||||
|
||||
function parse_verification_response(text: string): {
|
||||
status: 'ACCURATE' | 'NOT_ACCURATE';
|
||||
reasoning: string;
|
||||
} | null {
|
||||
// Try to extract STATUS and REASONING using regex
|
||||
const status_match = text.match(/STATUS:\s*(ACCURATE|NOT_ACCURATE)/i);
|
||||
const reasoning_match = text.match(/REASONING:\s*(.+?)(?:\n|$)/i);
|
||||
|
||||
if (status_match && reasoning_match) {
|
||||
return {
|
||||
status: status_match[1]!.toUpperCase() as 'ACCURATE' | 'NOT_ACCURATE',
|
||||
reasoning: reasoning_match[1]!.trim(),
|
||||
};
|
||||
}
|
||||
|
||||
// Fallback: try to find just "ACCURATE" or "NOT_ACCURATE" anywhere in the response
|
||||
const accurate_match = text.match(/\b(NOT_ACCURATE|ACCURATE)\b/i);
|
||||
if (accurate_match) {
|
||||
// Extract some context as reasoning
|
||||
const lines = text.split('\n').filter((line) => line.trim());
|
||||
const reasoning = lines.slice(0, 3).join(' ').slice(0, 200);
|
||||
|
||||
return {
|
||||
status: accurate_match[1]!.toUpperCase() as 'ACCURATE' | 'NOT_ACCURATE',
|
||||
reasoning: reasoning || 'Could not extract detailed reasoning',
|
||||
};
|
||||
}
|
||||
|
||||
return null;
|
||||
}
|
||||
|
||||
async function main() {
|
||||
console.log('🔍 Starting distilled verification...\n');
|
||||
|
||||
const output_path = path.join(current_dirname, '../src/distilled-verification.json');
|
||||
|
||||
// Load distilled data
|
||||
console.log('📂 Loading distilled.json...');
|
||||
const { summaries, content } = distilled_data;
|
||||
|
||||
const sections = Object.keys(summaries);
|
||||
console.log(`Found ${sections.length} sections to verify\n`);
|
||||
|
||||
// Check for API key
|
||||
const api_key = process.env.ANTHROPIC_API_KEY;
|
||||
if (!api_key) {
|
||||
console.error('❌ Error: ANTHROPIC_API_KEY environment variable is required');
|
||||
console.error('Please set it in packages/mcp-server/.env file or export it:');
|
||||
console.error('export ANTHROPIC_API_KEY=your_api_key_here');
|
||||
process.exit(1);
|
||||
}
|
||||
|
||||
// Initialize Anthropic API
|
||||
console.log('🤖 Initializing Anthropic API...');
|
||||
const anthropic = new AnthropicProvider('claude-sonnet-4-5-20250929', api_key);
|
||||
|
||||
// Prepare batch requests
|
||||
console.log('📦 Preparing batch requests...');
|
||||
const batch_requests: AnthropicBatchRequest[] = sections.map((slug, index) => {
|
||||
const original = content[slug] || '';
|
||||
const distilled = summaries[slug] || '';
|
||||
|
||||
return {
|
||||
custom_id: `verify-${index}`,
|
||||
params: {
|
||||
model: anthropic.get_model_identifier(),
|
||||
max_tokens: 4096,
|
||||
messages: [
|
||||
{
|
||||
role: 'user',
|
||||
content:
|
||||
`${VERIFICATION_PROMPT}\n\n` +
|
||||
`<original>${original}</original>\n\n` +
|
||||
`<distilled>${distilled}</distilled>`,
|
||||
},
|
||||
],
|
||||
temperature: 0,
|
||||
},
|
||||
};
|
||||
});
|
||||
|
||||
// Create and process batch
|
||||
console.log('🚀 Creating batch job...');
|
||||
const batch_response = await anthropic.create_batch(batch_requests);
|
||||
console.log(`✅ Batch created with ID: ${batch_response.id}`);
|
||||
|
||||
// Poll for completion
|
||||
console.log('⏳ Waiting for batch to complete...');
|
||||
let batch_status = await anthropic.get_batch_status(batch_response.id);
|
||||
|
||||
while (batch_status.processing_status === 'in_progress') {
|
||||
const { succeeded, processing, errored } = batch_status.request_counts;
|
||||
console.log(` Progress: ${succeeded} succeeded, ${processing} processing, ${errored} errored`);
|
||||
await new Promise((resolve) => setTimeout(resolve, 5000));
|
||||
batch_status = await anthropic.get_batch_status(batch_response.id);
|
||||
}
|
||||
|
||||
console.log('✅ Batch processing completed!');
|
||||
|
||||
// Get results
|
||||
if (!batch_status.results_url) {
|
||||
throw new Error('Batch completed but no results URL available');
|
||||
}
|
||||
|
||||
console.log('📥 Downloading results...');
|
||||
const results = await anthropic.get_batch_results(batch_status.results_url);
|
||||
|
||||
// Process results
|
||||
console.log('📊 Processing results...');
|
||||
const verification_results: VerificationResult[] = [];
|
||||
|
||||
for (const result of results) {
|
||||
const index = parseInt(result.custom_id.split('-')[1] ?? '0');
|
||||
const slug = sections[index];
|
||||
|
||||
if (!slug) {
|
||||
throw new Error(`Could not find slug for index ${index}`);
|
||||
}
|
||||
|
||||
if (result.result.type !== 'succeeded' || !result.result.message) {
|
||||
const error_msg = result.result.error?.message || 'Failed or no message';
|
||||
console.error(` ❌ Failed to verify ${slug}: ${error_msg}`);
|
||||
verification_results.push({
|
||||
slug,
|
||||
status: 'NOT_ACCURATE',
|
||||
reasoning: `Verification failed: ${error_msg}`,
|
||||
});
|
||||
continue;
|
||||
}
|
||||
|
||||
const output_content = result.result.message.content[0]?.text;
|
||||
if (!output_content) {
|
||||
console.error(` ❌ No text content in result for ${slug}`);
|
||||
verification_results.push({
|
||||
slug,
|
||||
status: 'NOT_ACCURATE',
|
||||
reasoning: 'No response from verification',
|
||||
});
|
||||
continue;
|
||||
}
|
||||
|
||||
// Parse using regex instead of strict JSON parsing
|
||||
const parsed = parse_verification_response(output_content);
|
||||
|
||||
if (!parsed) {
|
||||
console.error(` ❌ Failed to parse response for ${slug}`);
|
||||
console.error(` Raw response: ${output_content.slice(0, 200)}...`);
|
||||
verification_results.push({
|
||||
slug,
|
||||
status: 'NOT_ACCURATE',
|
||||
reasoning: `Failed to parse verification response: ${output_content.slice(0, 100)}`,
|
||||
});
|
||||
continue;
|
||||
}
|
||||
|
||||
verification_results.push({
|
||||
slug,
|
||||
status: parsed.status,
|
||||
reasoning: parsed.reasoning,
|
||||
});
|
||||
|
||||
const emoji = parsed.status === 'ACCURATE' ? '✅' : '❌';
|
||||
console.log(` ${emoji} ${slug}: ${parsed.status}`);
|
||||
}
|
||||
|
||||
// Calculate statistics
|
||||
const accurate_count = verification_results.filter((r) => r.status === 'ACCURATE').length;
|
||||
const not_accurate_count = verification_results.filter((r) => r.status === 'NOT_ACCURATE').length;
|
||||
|
||||
// Write output
|
||||
console.log('\n💾 Writing results to file...');
|
||||
const output_dir = path.dirname(output_path);
|
||||
await mkdir(output_dir, { recursive: true });
|
||||
|
||||
const output_data: VerificationOutput = {
|
||||
generated_at: new Date().toISOString(),
|
||||
model: 'claude-sonnet-4-5-20250929',
|
||||
total_sections: sections.length,
|
||||
verified_sections: sections.length,
|
||||
accurate_count,
|
||||
not_accurate_count,
|
||||
results: verification_results,
|
||||
};
|
||||
|
||||
// Validate output before writing
|
||||
const validated = v.safeParse(verification_output_schema, output_data);
|
||||
if (!validated.success) {
|
||||
throw new Error(`Output validation failed: ${JSON.stringify(validated.issues, null, 2)}`);
|
||||
}
|
||||
|
||||
await writeFile(output_path, JSON.stringify(output_data, null, 2), 'utf-8');
|
||||
|
||||
// Print summary
|
||||
console.log('\n📊 Verification Summary:');
|
||||
console.log(` Total sections: ${sections.length}`);
|
||||
console.log(` Verified sections: ${sections.length}`);
|
||||
console.log(
|
||||
` ✅ Accurate: ${accurate_count} (${((accurate_count / sections.length) * 100).toFixed(1)}%)`,
|
||||
);
|
||||
console.log(
|
||||
` ❌ Not Accurate: ${not_accurate_count} (${((not_accurate_count / sections.length) * 100).toFixed(1)}%)`,
|
||||
);
|
||||
|
||||
if (not_accurate_count > 0) {
|
||||
console.log('\n⚠️ Sections with issues (first 10):');
|
||||
verification_results
|
||||
.filter((r) => r.status === 'NOT_ACCURATE')
|
||||
.slice(0, 10)
|
||||
.forEach((r) => {
|
||||
console.log(` - ${r.slug}: ${r.reasoning}`);
|
||||
});
|
||||
if (not_accurate_count > 10) {
|
||||
console.log(` ... and ${not_accurate_count - 10} more`);
|
||||
}
|
||||
console.log('\n💡 Run `pnpm show-verification-errors` to see all issues');
|
||||
}
|
||||
|
||||
console.log(`\n✅ Results written to: ${output_path}`);
|
||||
}
|
||||
|
||||
main().catch((error) => {
|
||||
console.error('❌ Fatal error:', error);
|
||||
process.exit(1);
|
||||
});
|
||||
875
packages/mcp-server/src/distilled-verification.json
Normal file
875
packages/mcp-server/src/distilled-verification.json
Normal file
@@ -0,0 +1,875 @@
|
||||
{
|
||||
"generated_at": "2025-10-12T22:35:10.647Z",
|
||||
"model": "claude-sonnet-4-5-20250929",
|
||||
"total_sections": 173,
|
||||
"verified_sections": 173,
|
||||
"accurate_count": 159,
|
||||
"not_accurate_count": 14,
|
||||
"results": [
|
||||
{
|
||||
"slug": "cli/overview",
|
||||
"status": "ACCURATE",
|
||||
"reasoning": "The distilled version correctly captures the essential information about the sv CLI tool, its usage with npx/pnpx, and the behavior of using local vs. downloaded versions, with only the acknowledgements section reasonably omitted."
|
||||
},
|
||||
{
|
||||
"slug": "cli/faq",
|
||||
"status": "ACCURATE",
|
||||
"reasoning": "The distilled version correctly captures all essential information including commands for each package manager, troubleshooting context, and references to the same GitHub issues, with only formatting changes and reasonable condensation."
|
||||
},
|
||||
{
|
||||
"slug": "cli/sv-create",
|
||||
"status": "ACCURATE",
|
||||
"reasoning": "The distilled version correctly captures all essential information, options, and examples from the original documentation with appropriate condensation and no factual errors or critical omissions."
|
||||
},
|
||||
{
|
||||
"slug": "cli/sv-add",
|
||||
"status": "ACCURATE",
|
||||
"reasoning": "The distilled version correctly captures all essential information including usage, options, and add-ons list, with only minor acceptable simplifications in wording and removal of non-critical elements like links and HTML comments."
|
||||
},
|
||||
{
|
||||
"slug": "cli/sv-check",
|
||||
"status": "ACCURATE",
|
||||
"reasoning": "The distilled version correctly captures all essential information, options, and examples from the original documentation with appropriate condensation and no factual errors or critical omissions."
|
||||
},
|
||||
{
|
||||
"slug": "cli/sv-migrate",
|
||||
"status": "ACCURATE",
|
||||
"reasoning": "The distilled version correctly captures all essential information including usage, migration types, and their purposes, with only minor formatting simplifications and no factual errors or critical omissions."
|
||||
},
|
||||
{
|
||||
"slug": "cli/devtools-json",
|
||||
"status": "ACCURATE",
|
||||
"reasoning": "The distilled version correctly captures all essential information including the plugin's purpose, security note, alternatives, usage, and code example, with only minor formatting simplifications that preserve the core content."
|
||||
},
|
||||
{
|
||||
"slug": "cli/drizzle",
|
||||
"status": "ACCURATE",
|
||||
"reasoning": "The distilled version correctly captures all essential information including setup commands, features, database options, client options, and Docker configuration while maintaining factual accuracy through reasonable condensation."
|
||||
},
|
||||
{
|
||||
"slug": "cli/eslint",
|
||||
"status": "ACCURATE",
|
||||
"reasoning": "The distilled version correctly captures all essential information including the tool's purpose, installation command, and key components installed, with only minor simplification of wording."
|
||||
},
|
||||
{
|
||||
"slug": "cli/lucia",
|
||||
"status": "ACCURATE",
|
||||
"reasoning": "The distilled version correctly captures all essential information including the command, what it provides (SvelteKit + Drizzle auth setup following Lucia), and the demo option, with only minor formatting changes and reasonable simplifications."
|
||||
},
|
||||
{
|
||||
"slug": "cli/mdsvex",
|
||||
"status": "ACCURATE",
|
||||
"reasoning": "The distilled version correctly captures all essential information including the definition, comparison to MDX, installation command, and configuration details, with only minor simplification of wording."
|
||||
},
|
||||
{
|
||||
"slug": "cli/paraglide",
|
||||
"status": "ACCURATE",
|
||||
"reasoning": "The distilled version correctly captures all essential information including the library description, installation command, included features, and configuration options, with only minor formatting simplifications that preserve the original meaning."
|
||||
},
|
||||
{
|
||||
"slug": "cli/playwright",
|
||||
"status": "ACCURATE",
|
||||
"reasoning": "The distilled version correctly captures all essential information from the original, with only minor formatting changes and reasonable simplification of the bullet points."
|
||||
},
|
||||
{
|
||||
"slug": "cli/prettier",
|
||||
"status": "ACCURATE",
|
||||
"reasoning": "The distilled version correctly captures all essential information including the tool description, installation command, and what gets added to the project, with only minor rewording that preserves meaning."
|
||||
},
|
||||
{
|
||||
"slug": "cli/storybook",
|
||||
"status": "ACCURATE",
|
||||
"reasoning": "The distilled version correctly captures all essential information including the installation command, automatic initialization, framework options, and key features like module mocking and link handling."
|
||||
},
|
||||
{
|
||||
"slug": "cli/sveltekit-adapter",
|
||||
"status": "ACCURATE",
|
||||
"reasoning": "The distilled version correctly captures all essential information including usage, adapter options with their purposes, and the example command, with only minor formatting simplifications and no factual errors or critical omissions."
|
||||
},
|
||||
{
|
||||
"slug": "cli/tailwind",
|
||||
"status": "ACCURATE",
|
||||
"reasoning": "The distilled version correctly captures all essential information including setup command, installed components, prettier integration, and plugin options, with only minor formatting changes and reasonable simplifications."
|
||||
},
|
||||
{
|
||||
"slug": "cli/vitest",
|
||||
"status": "ACCURATE",
|
||||
"reasoning": "The distilled version correctly captures all essential information including the framework description, installation command, and the four key outcomes of running the command, with only minor rewording for brevity."
|
||||
},
|
||||
{
|
||||
"slug": "kit/introduction",
|
||||
"status": "ACCURATE",
|
||||
"reasoning": "The distilled version correctly captures all essential technical information, features, and links from the original, with only the introductory notes and some explanatory prose reasonably condensed."
|
||||
},
|
||||
{
|
||||
"slug": "kit/creating-a-project",
|
||||
"status": "ACCURATE",
|
||||
"reasoning": "The distilled version correctly captures all essential information including the setup commands, core concepts of pages/routing/rendering, and editor recommendations, with only minor formatting changes and reasonable condensation of explanatory text."
|
||||
},
|
||||
{
|
||||
"slug": "kit/project-types",
|
||||
"status": "ACCURATE",
|
||||
"reasoning": "The distilled version correctly captures all essential information from the original, preserving key concepts, links, and technical details while appropriately condensing explanations and formatting for brevity."
|
||||
},
|
||||
{
|
||||
"slug": "kit/project-structure",
|
||||
"status": "NOT_ACCURATE",
|
||||
"reasoning": "The distilled version incorrectly names the file as \"instrumentation.server.js\" when the original clearly states it is \"tracing.server.js\" in the directory structure, though the description section does mention \"instrumentation.server.js\" creating ambiguity that should have been preserved."
|
||||
},
|
||||
{
|
||||
"slug": "kit/web-standards",
|
||||
"status": "ACCURATE",
|
||||
"reasoning": "The distilled version correctly captures all essential information including the special fetch behavior, API interfaces, code examples, and usage contexts, with only minor formatting simplifications that preserve the original meaning."
|
||||
},
|
||||
{
|
||||
"slug": "kit/routing",
|
||||
"status": "ACCURATE",
|
||||
"reasoning": "The distilled version correctly captures all essential information including routing concepts, file types, code examples, and key behaviors, with appropriate condensation and no factual errors or critical omissions."
|
||||
},
|
||||
{
|
||||
"slug": "kit/load",
|
||||
"status": "ACCURATE",
|
||||
"reasoning": "The distilled version correctly captures all essential information including load function types, data flow, URL handling, fetch behavior, cookies, headers, parent data access, errors, redirects, streaming, parallel loading, rerunning logic, authentication implications, and getRequestEvent usage, with appropriate code examples preserved."
|
||||
},
|
||||
{
|
||||
"slug": "kit/form-actions",
|
||||
"status": "ACCURATE",
|
||||
"reasoning": "The distilled version accurately captures all key concepts, code examples, and important notes from the original documentation, with appropriate condensation and no factual errors or misleading omissions."
|
||||
},
|
||||
{
|
||||
"slug": "kit/page-options",
|
||||
"status": "ACCURATE",
|
||||
"reasoning": "The distilled version correctly captures all essential information including the five main page options (prerender, entries, ssr, csr, trailingSlash, config), their usage, code examples, and important warnings, with appropriate condensation but no factual errors or critical omissions."
|
||||
},
|
||||
{
|
||||
"slug": "kit/state-management",
|
||||
"status": "ACCURATE",
|
||||
"reasoning": "The distilled version correctly captures all essential information, preserves critical warnings and code examples, maintains accurate technical details, and only condenses explanatory text while keeping all key concepts intact."
|
||||
},
|
||||
{
|
||||
"slug": "kit/remote-functions",
|
||||
"status": "ACCURATE",
|
||||
"reasoning": "The distilled version accurately captures all essential information including setup, all four function types (query, form, command, prerender), their usage patterns, validation, and key features like batching, single-flight mutations, and error handling, with no factual errors or critical omissions."
|
||||
},
|
||||
{
|
||||
"slug": "kit/building-your-app",
|
||||
"status": "ACCURATE",
|
||||
"reasoning": "The distilled version correctly captures all essential information including the two-stage build process, the building flag usage with accurate code example, and preview limitations, with only minor formatting simplifications."
|
||||
},
|
||||
{
|
||||
"slug": "kit/adapters",
|
||||
"status": "ACCURATE",
|
||||
"reasoning": "The distilled version correctly captures all essential information including the purpose of adapters, the list of official adapters, configuration method with code example, and platform-specific context details, with only minor formatting simplifications that don't alter meaning."
|
||||
},
|
||||
{
|
||||
"slug": "kit/adapter-auto",
|
||||
"status": "ACCURATE",
|
||||
"reasoning": "The distilled version correctly captures all essential information including the adapter list, best practices, configuration limitations, and extension process, with appropriate simplification and no factual errors."
|
||||
},
|
||||
{
|
||||
"slug": "kit/adapter-node",
|
||||
"status": "ACCURATE",
|
||||
"reasoning": "The distilled version accurately captures all essential information including installation, deployment, environment variables, options, graceful shutdown, socket activation, and custom server setup, with appropriate condensation of explanatory text while preserving critical technical details and code examples."
|
||||
},
|
||||
{
|
||||
"slug": "kit/adapter-static",
|
||||
"status": "ACCURATE",
|
||||
"reasoning": "The distilled version correctly captures all essential information including installation, configuration, options, and GitHub Pages setup, with appropriate condensation of explanatory text while preserving critical technical details and code examples."
|
||||
},
|
||||
{
|
||||
"slug": "kit/single-page-apps",
|
||||
"status": "ACCURATE",
|
||||
"reasoning": "The distilled version correctly captures all essential information including SPA setup, performance warnings, configuration steps, prerendering options, and Apache configuration, with appropriate simplifications and no factual errors."
|
||||
},
|
||||
{
|
||||
"slug": "kit/adapter-cloudflare",
|
||||
"status": "ACCURATE",
|
||||
"reasoning": "The distilled version accurately captures all essential information, configuration options, code examples, and key concepts from the original documentation with appropriate condensation and no factual errors or critical omissions."
|
||||
},
|
||||
{
|
||||
"slug": "kit/adapter-cloudflare-workers",
|
||||
"status": "ACCURATE",
|
||||
"reasoning": "The distilled version correctly captures all essential information including deprecation notice, installation, configuration, deployment, runtime APIs, testing, and troubleshooting, with appropriate simplifications and no factual errors."
|
||||
},
|
||||
{
|
||||
"slug": "kit/adapter-netlify",
|
||||
"status": "ACCURATE",
|
||||
"reasoning": "The distilled version correctly captures all essential information including installation, configuration options, edge functions, Netlify-specific features, and troubleshooting, with only minor formatting simplifications and no factual errors or critical omissions."
|
||||
},
|
||||
{
|
||||
"slug": "kit/adapter-vercel",
|
||||
"status": "ACCURATE",
|
||||
"reasoning": "The distilled version accurately captures all essential information, configuration options, warnings, and troubleshooting steps from the original, with appropriate condensation and formatting changes that preserve the core technical content."
|
||||
},
|
||||
{
|
||||
"slug": "kit/writing-adapters",
|
||||
"status": "ACCURATE",
|
||||
"reasoning": "The distilled version correctly captures all essential information including the API structure, required/optional fields, adapt method tasks, and recommendations, with appropriate condensation and reorganization for clarity."
|
||||
},
|
||||
{
|
||||
"slug": "kit/advanced-routing",
|
||||
"status": "ACCURATE",
|
||||
"reasoning": "The distilled version accurately captures all key concepts including rest parameters, optional parameters, matchers, sorting rules, encoding, and advanced layouts with correct code examples and essential notes, though condensed for brevity."
|
||||
},
|
||||
{
|
||||
"slug": "kit/hooks",
|
||||
"status": "ACCURATE",
|
||||
"reasoning": "The distilled version accurately captures all key hooks, their purposes, parameters, and code examples while appropriately condensing explanatory text and preserving critical technical details."
|
||||
},
|
||||
{
|
||||
"slug": "kit/errors",
|
||||
"status": "ACCURATE",
|
||||
"reasoning": "The distilled version correctly captures all essential information including expected/unexpected errors, error handling, responses, type safety, and code examples, with only minor formatting simplifications that preserve the core concepts."
|
||||
},
|
||||
{
|
||||
"slug": "kit/link-options",
|
||||
"status": "ACCURATE",
|
||||
"reasoning": "The distilled version correctly captures all key information, attribute values, code examples, and important warnings from the original documentation, with appropriate condensation but no factual errors or critical omissions."
|
||||
},
|
||||
{
|
||||
"slug": "kit/service-workers",
|
||||
"status": "ACCURATE",
|
||||
"reasoning": "The distilled version correctly captures all essential information including setup, the $service-worker module exports, the complete code example, development considerations, and alternative solutions, with only minor formatting changes and reasonable condensation of explanatory text."
|
||||
},
|
||||
{
|
||||
"slug": "kit/server-only-modules",
|
||||
"status": "ACCURATE",
|
||||
"reasoning": "The distilled version correctly captures all essential information including the two methods for creating server-only modules, how the protection works, the import chain example, dynamic imports support, and the testing exception, with no factual errors or critical omissions."
|
||||
},
|
||||
{
|
||||
"slug": "kit/snapshots",
|
||||
"status": "ACCURATE",
|
||||
"reasoning": "The distilled version correctly captures all essential information including the purpose, usage pattern, timing of capture/restore functions, serialization requirements, and the warning about large objects, with only minor formatting simplifications."
|
||||
},
|
||||
{
|
||||
"slug": "kit/shallow-routing",
|
||||
"status": "NOT_ACCURATE",
|
||||
"reasoning": "The distilled version incorrectly states that shallow routing allows you to \"Navigate without triggering `load` functions or replacing page components\" when the original clearly states that navigating through history entries \"re-runs any `load` functions and replaces page components as necessary\" - shallow routing creates history entries WITHOUT navigating, not a way to navigate differently."
|
||||
},
|
||||
{
|
||||
"slug": "kit/observability",
|
||||
"status": "ACCURATE",
|
||||
"reasoning": "The distilled version correctly captures all essential information including setup, traced components, code examples, and important warnings, with only reasonable condensation of explanatory text."
|
||||
},
|
||||
{
|
||||
"slug": "kit/packaging",
|
||||
"status": "ACCURATE",
|
||||
"reasoning": "The distilled version correctly captures all essential information including package.json configuration, TypeScript handling, CLI options, and caveats, with appropriate condensation of examples while preserving technical accuracy."
|
||||
},
|
||||
{
|
||||
"slug": "kit/auth",
|
||||
"status": "ACCURATE",
|
||||
"reasoning": "The distilled version correctly captures all essential information including the definitions, session vs token tradeoffs, integration points, and Lucia implementation details without any factual errors or critical omissions."
|
||||
},
|
||||
{
|
||||
"slug": "kit/performance",
|
||||
"status": "ACCURATE",
|
||||
"reasoning": "The distilled version correctly captures all essential information, performance tips, and technical details from the original, with appropriate condensation and formatting changes that preserve the core concepts and critical guidance."
|
||||
},
|
||||
{
|
||||
"slug": "kit/icons",
|
||||
"status": "ACCURATE",
|
||||
"reasoning": "The distilled version correctly captures the key points about CSS-based icons via Iconify and the warning against per-icon Svelte component libraries that slow down Vite, with appropriate links preserved."
|
||||
},
|
||||
{
|
||||
"slug": "kit/images",
|
||||
"status": "ACCURATE",
|
||||
"reasoning": "The distilled version correctly captures all essential information including setup, usage patterns, configuration details, and best practices, with appropriate condensation of explanatory text while preserving critical technical details and code examples."
|
||||
},
|
||||
{
|
||||
"slug": "kit/accessibility",
|
||||
"status": "ACCURATE",
|
||||
"reasoning": "The distilled version correctly captures all essential information including route announcements, focus management, lang attribute configuration, and further reading resources, with appropriate condensation but no factual errors or critical omissions."
|
||||
},
|
||||
{
|
||||
"slug": "kit/seo",
|
||||
"status": "ACCURATE",
|
||||
"reasoning": "The distilled version correctly captures all essential information including SSR defaults, performance considerations, URL normalization, manual setup requirements, and complete AMP implementation steps with accurate code examples, though reasonably condensed."
|
||||
},
|
||||
{
|
||||
"slug": "kit/faq",
|
||||
"status": "ACCURATE",
|
||||
"reasoning": "The distilled version accurately captures all essential information, code examples, and key concepts from the original while appropriately condensing explanatory text and maintaining technical accuracy."
|
||||
},
|
||||
{
|
||||
"slug": "kit/integrations",
|
||||
"status": "ACCURATE",
|
||||
"reasoning": "The distilled version correctly captures all essential information including vitePreprocess functionality, TypeScript requirements, add-ons list, svelte-preprocess differences, and Vite plugins, with appropriate condensation and no factual errors."
|
||||
},
|
||||
{
|
||||
"slug": "kit/debugging",
|
||||
"status": "ACCURATE",
|
||||
"reasoning": "The distilled version correctly captures all essential information including setup steps, code examples, limitations, and references, with only minor formatting simplifications that preserve the core content."
|
||||
},
|
||||
{
|
||||
"slug": "kit/migrating-to-sveltekit-2",
|
||||
"status": "ACCURATE",
|
||||
"reasoning": "The distilled version correctly captures all key breaking changes, code examples, and migration steps from the original documentation, with appropriate simplifications and no factual errors or critical omissions."
|
||||
},
|
||||
{
|
||||
"slug": "kit/migrating",
|
||||
"status": "ACCURATE",
|
||||
"reasoning": "The distilled version accurately captures all key migration steps, API changes, file renames, and code examples from the original documentation without introducing factual errors or omitting critical information."
|
||||
},
|
||||
{
|
||||
"slug": "kit/additional-resources",
|
||||
"status": "ACCURATE",
|
||||
"reasoning": "The distilled version preserves all key information including FAQ links, example repositories, community resources, and support channels with appropriate guidance about searching first, using reasonable condensation without factual errors or critical omissions."
|
||||
},
|
||||
{
|
||||
"slug": "kit/glossary",
|
||||
"status": "ACCURATE",
|
||||
"reasoning": "The distilled version correctly captures all essential information, key concepts, default behaviors, configuration options, and important warnings from the original documentation without introducing factual errors or misleading statements."
|
||||
},
|
||||
{
|
||||
"slug": "kit/@sveltejs-kit",
|
||||
"status": "ACCURATE",
|
||||
"reasoning": "The distilled version accurately captures all essential information from the original documentation, including function signatures, type definitions, important warnings, and version availability notes, with appropriate condensation of verbose descriptions while preserving critical technical details."
|
||||
},
|
||||
{
|
||||
"slug": "kit/@sveltejs-kit-hooks",
|
||||
"status": "ACCURATE",
|
||||
"reasoning": "The distilled version correctly captures all essential information including the behavior of each option, the complete code example, expected output, and type signature with appropriate simplifications in formatting and structure."
|
||||
},
|
||||
{
|
||||
"slug": "kit/@sveltejs-kit-node-polyfills",
|
||||
"status": "ACCURATE",
|
||||
"reasoning": "The distilled version correctly captures all essential information including the import path, function purpose, the specific APIs (crypto and File), and the TypeScript definition, with only minor formatting changes."
|
||||
},
|
||||
{
|
||||
"slug": "kit/@sveltejs-kit-node",
|
||||
"status": "ACCURATE",
|
||||
"reasoning": "The distilled version correctly captures all essential information including function signatures, parameters, and the version availability note, with only minor formatting changes and reasonable additions of clarifying descriptions."
|
||||
},
|
||||
{
|
||||
"slug": "kit/@sveltejs-kit-vite",
|
||||
"status": "ACCURATE",
|
||||
"reasoning": "The distilled version preserves all essential information including the import statement, function description, and TypeScript signature, with only minor formatting changes that don't affect accuracy."
|
||||
},
|
||||
{
|
||||
"slug": "kit/$app-environment",
|
||||
"status": "ACCURATE",
|
||||
"reasoning": "The distilled version correctly captures all essential information including the import statement, the meaning of each exported constant, their types, and important caveats, with only minor wording simplifications that preserve accuracy."
|
||||
},
|
||||
{
|
||||
"slug": "kit/$app-forms",
|
||||
"status": "ACCURATE",
|
||||
"reasoning": "The distilled version correctly captures all essential information including function purposes, parameters, return types, code examples, and the detailed behavior of the enhance function's default and custom callback options."
|
||||
},
|
||||
{
|
||||
"slug": "kit/$app-navigation",
|
||||
"status": "ACCURATE",
|
||||
"reasoning": "The distilled version accurately captures all key information, function signatures, and important behavioral details from the original documentation, with appropriate condensation that preserves essential meaning."
|
||||
},
|
||||
{
|
||||
"slug": "kit/$app-paths",
|
||||
"status": "ACCURATE",
|
||||
"reasoning": "The distilled version correctly captures all essential information including function signatures, usage examples, and deprecation notices, with only minor formatting simplifications that preserve the core content."
|
||||
},
|
||||
{
|
||||
"slug": "kit/$app-server",
|
||||
"status": "ACCURATE",
|
||||
"reasoning": "The distilled version accurately captures all key information including function signatures, version availability, descriptions, and code examples, with only minor formatting simplifications that preserve the essential content."
|
||||
},
|
||||
{
|
||||
"slug": "kit/$app-state",
|
||||
"status": "ACCURATE",
|
||||
"reasoning": "The distilled version correctly captures all essential information including the three state objects, their properties, usage examples, the critical runes vs legacy reactivity distinction, and server/browser behavior differences, with only minor formatting simplifications."
|
||||
},
|
||||
{
|
||||
"slug": "kit/$app-stores",
|
||||
"status": "ACCURATE",
|
||||
"reasoning": "The distilled version correctly captures all essential information including deprecation notices, functionality of each store, server/browser subscription constraints, and type signatures, with only minor formatting simplifications."
|
||||
},
|
||||
{
|
||||
"slug": "kit/$app-types",
|
||||
"status": "NOT_ACCURATE",
|
||||
"reasoning": "The LayoutParams type definition incorrectly shows \"RouteParams\" instead of \"LayoutParams\" in the distilled version, which is a factual error copied from the original."
|
||||
},
|
||||
{
|
||||
"slug": "kit/$env-dynamic-private",
|
||||
"status": "ACCURATE",
|
||||
"reasoning": "The distilled version correctly captures all essential information including the key rules about prefix filtering, client-side restriction, usage example, and the dev/prod behavior note."
|
||||
},
|
||||
{
|
||||
"slug": "kit/$env-dynamic-public",
|
||||
"status": "ACCURATE",
|
||||
"reasoning": "The distilled version correctly captures all essential information including the public prefix requirement, client-side safety, network payload concern, recommendation to prefer static version, and preserves the accurate code example."
|
||||
},
|
||||
{
|
||||
"slug": "kit/$env-static-private",
|
||||
"status": "ACCURATE",
|
||||
"reasoning": "The distilled version correctly captures all essential information including the static injection behavior, prefix filtering rules, server-only nature, and best practices, with appropriate simplification and reformatting."
|
||||
},
|
||||
{
|
||||
"slug": "kit/$env-static-public",
|
||||
"status": "ACCURATE",
|
||||
"reasoning": "The distilled version correctly captures all essential information including the PUBLIC_ prefix requirement, configurability, client-side safety, build-time replacement, and preserves the code example accurately."
|
||||
},
|
||||
{
|
||||
"slug": "kit/$lib",
|
||||
"status": "ACCURATE",
|
||||
"reasoning": "The distilled version correctly captures the essential information about the $lib import alias, its default location, configurability, and includes the same code examples demonstrating its usage."
|
||||
},
|
||||
{
|
||||
"slug": "kit/$service-worker",
|
||||
"status": "ACCURATE",
|
||||
"reasoning": "The distilled version correctly captures all essential information including the module availability, each export's type and purpose, development behavior, and configuration references without introducing factual errors or omitting critical details."
|
||||
},
|
||||
{
|
||||
"slug": "kit/configuration",
|
||||
"status": "ACCURATE",
|
||||
"reasoning": "The distilled version correctly captures all essential configuration options, defaults, code examples, and important notes from the original documentation, with appropriate condensation and no factual errors or critical omissions."
|
||||
},
|
||||
{
|
||||
"slug": "kit/cli",
|
||||
"status": "ACCURATE",
|
||||
"reasoning": "The distilled version correctly captures all essential information including Vite CLI commands, svelte-kit sync functionality, and automatic execution, with only minor simplifications that preserve meaning."
|
||||
},
|
||||
{
|
||||
"slug": "kit/types",
|
||||
"status": "ACCURATE",
|
||||
"reasoning": "The distilled version correctly captures all essential information including generated types, helper types, setup requirements, $lib aliases, and app.d.ts interfaces, with appropriate code examples and version-specific details preserved."
|
||||
},
|
||||
{
|
||||
"slug": "mcp/overview",
|
||||
"status": "ACCURATE",
|
||||
"reasoning": "The distilled version preserves all critical information including setup options, the complete usage prompt, and tool descriptions, with only minor formatting simplifications that don't alter meaning."
|
||||
},
|
||||
{
|
||||
"slug": "mcp/local-setup",
|
||||
"status": "ACCURATE",
|
||||
"reasoning": "The distilled version correctly captures all essential information including installation commands, configuration examples for each client, and maintains factual accuracy with appropriate condensation of instructional text."
|
||||
},
|
||||
{
|
||||
"slug": "mcp/remote-setup",
|
||||
"status": "ACCURATE",
|
||||
"reasoning": "The distilled version correctly preserves all essential setup instructions, commands, and configuration details for each client while appropriately condensing explanatory text and formatting."
|
||||
},
|
||||
{
|
||||
"slug": "mcp/tools",
|
||||
"status": "ACCURATE",
|
||||
"reasoning": "The distilled version correctly captures all four tools and their essential functions, with only minor formatting changes and reasonable condensation of descriptions."
|
||||
},
|
||||
{
|
||||
"slug": "mcp/resources",
|
||||
"status": "ACCURATE",
|
||||
"reasoning": "The distilled version correctly captures the essential information about the doc-section resource including URI format, return type, and use case, with only minor formatting changes and reasonable simplification."
|
||||
},
|
||||
{
|
||||
"slug": "mcp/prompts",
|
||||
"status": "NOT_ACCURATE",
|
||||
"reasoning": "The distilled version omits critical information about the extensive list of available documentation paths with their specific use cases, which is essential for the LLM to know when to invoke the get_documentation tool with the correct path parameter."
|
||||
},
|
||||
{
|
||||
"slug": "svelte/overview",
|
||||
"status": "ACCURATE",
|
||||
"reasoning": "The distilled version correctly captures the essential information about Svelte being a compiler-based framework, preserves the complete code example, and accurately notes the key syntax detail about event handlers and SvelteKit usage."
|
||||
},
|
||||
{
|
||||
"slug": "svelte/getting-started",
|
||||
"status": "ACCURATE",
|
||||
"reasoning": "The distilled version correctly captures all essential information including setup commands, alternatives, tooling options, and help resources without introducing factual errors or omitting critical details."
|
||||
},
|
||||
{
|
||||
"slug": "svelte/svelte-files",
|
||||
"status": "ACCURATE",
|
||||
"reasoning": "The distilled version correctly captures all essential information including component structure, script behaviors, module-level logic, scoping rules, and includes the key code examples, with only minor formatting simplifications and removal of non-critical notes."
|
||||
},
|
||||
{
|
||||
"slug": "svelte/svelte-js-files",
|
||||
"status": "ACCURATE",
|
||||
"reasoning": "The distilled version correctly captures all essential information including the file types, their behavior, use cases, and the critical limitation about exporting reassigned state."
|
||||
},
|
||||
{
|
||||
"slug": "svelte/what-are-runes",
|
||||
"status": "ACCURATE",
|
||||
"reasoning": "The distilled version correctly captures all essential information about runes including their purpose, syntax, and three key characteristics, with only the etymology note and legacy information reasonably omitted."
|
||||
},
|
||||
{
|
||||
"slug": "svelte/$state",
|
||||
"status": "ACCURATE",
|
||||
"reasoning": "The distilled version correctly captures all essential information including key concepts, code examples, gotchas, and the two options for sharing state across modules, with appropriate simplifications and no factual errors."
|
||||
},
|
||||
{
|
||||
"slug": "svelte/$derived",
|
||||
"status": "ACCURATE",
|
||||
"reasoning": "The distilled version accurately captures all key concepts including $derived, $derived.by, dependencies, overriding values, reactivity behavior, destructuring, and update propagation with correct code examples and essential details preserved."
|
||||
},
|
||||
{
|
||||
"slug": "svelte/$effect",
|
||||
"status": "ACCURATE",
|
||||
"reasoning": "The distilled version accurately captures all key concepts, correctly represents the code examples, maintains critical warnings about when not to use effects, and preserves the essential technical details about lifecycle, dependencies, and the various effect runes."
|
||||
},
|
||||
{
|
||||
"slug": "svelte/$props",
|
||||
"status": "ACCURATE",
|
||||
"reasoning": "The distilled version correctly captures all essential information including props usage, fallback values, renaming, rest props, updating behavior with warnings about mutation, type safety examples, and $props.id() functionality, with appropriate condensation of examples while preserving core concepts."
|
||||
},
|
||||
{
|
||||
"slug": "svelte/$bindable",
|
||||
"status": "ACCURATE",
|
||||
"reasoning": "The distilled version correctly captures all essential information including the bidirectional data flow concept, $bindable syntax, usage examples, fallback values, and the warning about sparing use, with only minor formatting changes."
|
||||
},
|
||||
{
|
||||
"slug": "svelte/$inspect",
|
||||
"status": "ACCURATE",
|
||||
"reasoning": "The distilled version correctly captures all essential information including development-only behavior, deep reactivity tracking, the `.with()` method signature, `$inspect.trace()` requirements, and preserves critical details like the first-statement requirement and optional label parameter."
|
||||
},
|
||||
{
|
||||
"slug": "svelte/$host",
|
||||
"status": "ACCURATE",
|
||||
"reasoning": "The distilled version correctly captures the essential information about the $host rune, preserves the code examples accurately, and adds helpful key points without introducing any factual errors or contradictions."
|
||||
},
|
||||
{
|
||||
"slug": "svelte/basic-markup",
|
||||
"status": "ACCURATE",
|
||||
"reasoning": "The distilled version correctly captures all essential information including tags, attributes, props, events, delegation, text expressions, and comments with accurate technical details and no misleading omissions."
|
||||
},
|
||||
{
|
||||
"slug": "svelte/if",
|
||||
"status": "ACCURATE",
|
||||
"reasoning": "The distilled version correctly captures all essential information including syntax, examples, and the note about blocks wrapping elements or text, with only minor formatting improvements."
|
||||
},
|
||||
{
|
||||
"slug": "svelte/each",
|
||||
"status": "ACCURATE",
|
||||
"reasoning": "The distilled version correctly captures all essential information including syntax, keyed blocks, destructuring, itemless iteration, and else clauses with appropriate examples and explanations."
|
||||
},
|
||||
{
|
||||
"slug": "svelte/key",
|
||||
"status": "ACCURATE",
|
||||
"reasoning": "The distilled version correctly captures all essential information including syntax, core behavior (destroy/recreate on change), and both key use cases (component reinstantiation and transition replay) with accurate code examples."
|
||||
},
|
||||
{
|
||||
"slug": "svelte/await",
|
||||
"status": "NOT_ACCURATE",
|
||||
"reasoning": "The distilled version incorrectly states that omitting the catch block is a \"shorthand pattern\" when the original shows this requires omitting the initial pending block as well, and it fails to mention that the catch block can be omitted while keeping the pending block."
|
||||
},
|
||||
{
|
||||
"slug": "svelte/snippet",
|
||||
"status": "ACCURATE",
|
||||
"reasoning": "The distilled version correctly captures all essential information including syntax, scope rules, component passing methods, TypeScript typing, exporting capabilities, and the key restrictions, with appropriate condensation of examples while preserving core concepts."
|
||||
},
|
||||
{
|
||||
"slug": "svelte/@render",
|
||||
"status": "ACCURATE",
|
||||
"reasoning": "The distilled version preserves all key information including syntax, code examples, optional chaining usage, and fallback patterns with only minor formatting changes and reasonable simplifications."
|
||||
},
|
||||
{
|
||||
"slug": "svelte/@html",
|
||||
"status": "NOT_ACCURATE",
|
||||
"reasoning": "The distilled version incorrectly shows `article :global` (with a space) instead of `article :global(*)` or the nested syntax shown in the original, which would target different elements than intended."
|
||||
},
|
||||
{
|
||||
"slug": "svelte/@attach",
|
||||
"status": "ACCURATE",
|
||||
"reasoning": "The distilled version correctly captures all essential information including basic usage, attachment factories, inline attachments, component passing, reactivity control, and utility functions, with appropriate code examples and key concepts preserved."
|
||||
},
|
||||
{
|
||||
"slug": "svelte/@const",
|
||||
"status": "ACCURATE",
|
||||
"reasoning": "The distilled version correctly captures the essential information about {@const} tag usage, its purpose, code example, and placement restrictions, with only minor formatting differences."
|
||||
},
|
||||
{
|
||||
"slug": "svelte/@debug",
|
||||
"status": "ACCURATE",
|
||||
"reasoning": "The distilled version correctly captures all essential information including the core functionality, syntax rules, valid/invalid examples, and the no-arguments behavior, with only minor formatting improvements."
|
||||
},
|
||||
{
|
||||
"slug": "svelte/bind",
|
||||
"status": "ACCURATE",
|
||||
"reasoning": "The distilled version correctly captures all essential information including syntax, binding types, version-specific features, and important notes/warnings, with appropriate condensation of examples while preserving core concepts."
|
||||
},
|
||||
{
|
||||
"slug": "svelte/use",
|
||||
"status": "ACCURATE",
|
||||
"reasoning": "The distilled version correctly captures all essential information including the note about attachments, action syntax, argument usage, the key behavior that actions don't re-run on argument changes, and typing details, with only minor formatting simplifications."
|
||||
},
|
||||
{
|
||||
"slug": "svelte/transition",
|
||||
"status": "ACCURATE",
|
||||
"reasoning": "The distilled version correctly captures all essential information including transition behavior, local vs global distinctions, parameters, custom functions with css/tick details, and transition events, with appropriate condensation but no factual errors or critical omissions."
|
||||
},
|
||||
{
|
||||
"slug": "svelte/in-and-out",
|
||||
"status": "ACCURATE",
|
||||
"reasoning": "The distilled version correctly captures the key concepts of non-bidirectional behavior, simultaneous play of in/out transitions, and restart behavior when aborted, with the same code example preserved."
|
||||
},
|
||||
{
|
||||
"slug": "svelte/animate",
|
||||
"status": "ACCURATE",
|
||||
"reasoning": "The distilled version correctly captures all essential information including animation triggers, usage patterns, custom function signatures, and the distinction between css and tick methods, with appropriate simplifications and no factual errors."
|
||||
},
|
||||
{
|
||||
"slug": "svelte/style",
|
||||
"status": "ACCURATE",
|
||||
"reasoning": "The distilled version correctly captures all essential information including basic usage, expressions, shorthand form, multiple styles, important modifier, and precedence rules with accurate code examples."
|
||||
},
|
||||
{
|
||||
"slug": "svelte/class",
|
||||
"status": "ACCURATE",
|
||||
"reasoning": "The distilled version correctly captures all essential information including the two ways to set classes, version-specific features, code examples, and the recommendation to prefer the class attribute over the class: directive."
|
||||
},
|
||||
{
|
||||
"slug": "svelte/await-expressions",
|
||||
"status": "ACCURATE",
|
||||
"reasoning": "The distilled version correctly captures all essential information including the experimental flag configuration, synchronized updates behavior, concurrency rules, loading state handling, error handling, SSR support, and caveats, with appropriate code examples preserved."
|
||||
},
|
||||
{
|
||||
"slug": "svelte/scoped-styles",
|
||||
"status": "ACCURATE",
|
||||
"reasoning": "The distilled version correctly captures all essential information including scoped styles, specificity increases, :where() usage, and scoped keyframes with accurate technical details and preserved code examples."
|
||||
},
|
||||
{
|
||||
"slug": "svelte/global-styles",
|
||||
"status": "ACCURATE",
|
||||
"reasoning": "The distilled version preserves all essential information including syntax, examples, and key concepts about global styling and keyframes, with only minor formatting changes and removal of a non-critical note about alternative selector syntax."
|
||||
},
|
||||
{
|
||||
"slug": "svelte/custom-properties",
|
||||
"status": "ACCURATE",
|
||||
"reasoning": "The distilled version correctly captures all essential information including syntax, desugaring behavior, SVG handling, var() usage with fallbacks, inheritance, and the CSS selector gotcha, with only minor formatting changes."
|
||||
},
|
||||
{
|
||||
"slug": "svelte/nested-style-elements",
|
||||
"status": "ACCURATE",
|
||||
"reasoning": "The distilled version correctly captures all key information including the one top-level style tag limit, nested style tag behavior, lack of scoping/processing for nested tags, and preserves the illustrative code example."
|
||||
},
|
||||
{
|
||||
"slug": "svelte/svelte-boundary",
|
||||
"status": "NOT_ACCURATE",
|
||||
"reasoning": "The distilled version incorrectly states that boundaries only catch errors during \"top-level $effect\" when the original says \"running effects\" more broadly, and it omits the critical note about the playground's built-in boundary behavior for the pending snippet."
|
||||
},
|
||||
{
|
||||
"slug": "svelte/svelte-window",
|
||||
"status": "ACCURATE",
|
||||
"reasoning": "The distilled version correctly captures all essential information including syntax, rules, event listener usage, bindable properties with their readonly/writable distinctions, and the important scrolling behavior note."
|
||||
},
|
||||
{
|
||||
"slug": "svelte/svelte-document",
|
||||
"status": "ACCURATE",
|
||||
"reasoning": "The distilled version correctly captures all essential information including syntax, usage constraints, event handling, actions support, and the four readonly bindable properties without any factual errors or critical omissions."
|
||||
},
|
||||
{
|
||||
"slug": "svelte/svelte-body",
|
||||
"status": "ACCURATE",
|
||||
"reasoning": "The distilled version correctly captures all essential information including syntax, usage, supported features (events and actions), and the critical constraint about top-level placement."
|
||||
},
|
||||
{
|
||||
"slug": "svelte/svelte-head",
|
||||
"status": "ACCURATE",
|
||||
"reasoning": "The distilled version correctly captures all essential information including functionality, SSR behavior, placement restrictions, and preserves the code example accurately."
|
||||
},
|
||||
{
|
||||
"slug": "svelte/svelte-element",
|
||||
"status": "ACCURATE",
|
||||
"reasoning": "The distilled version correctly captures all essential information including usage, limitations, void element behavior, nullish handling, namespace requirements, and valid tag restrictions without any factual errors or critical omissions."
|
||||
},
|
||||
{
|
||||
"slug": "svelte/svelte-options",
|
||||
"status": "NOT_ACCURATE",
|
||||
"reasoning": "The distilled version omits critical information about deprecated Svelte 4 options (immutable and accessors) and removes important reference links to the compiler section, Legacy APIs section, and custom elements component options documentation."
|
||||
},
|
||||
{
|
||||
"slug": "svelte/stores",
|
||||
"status": "ACCURATE",
|
||||
"reasoning": "The distilled version accurately captures all essential information including the $ prefix syntax, when to use stores vs runes in Svelte 5, all API methods with correct examples, and the store contract requirements without any factual errors or critical omissions."
|
||||
},
|
||||
{
|
||||
"slug": "svelte/context",
|
||||
"status": "NOT_ACCURATE",
|
||||
"reasoning": "The distilled version incorrectly shows `counter.count = 0` in the \"Correct\" example when the original uses `+++counter.count = 0+++` (which appears to be markup indicating emphasis, but the actual code should be `counter.count = 0`), and more critically, it omits the important context about when Parent.svelte renders Child.svelte as part of a children snippet, which is described as \"particularly useful\" in the original."
|
||||
},
|
||||
{
|
||||
"slug": "svelte/lifecycle-hooks",
|
||||
"status": "ACCURATE",
|
||||
"reasoning": "The distilled version correctly captures all essential information including lifecycle concepts, API usage, server-side behavior notes, cleanup patterns, the deprecation of beforeUpdate/afterUpdate, and the chat autoscroll example with accurate code."
|
||||
},
|
||||
{
|
||||
"slug": "svelte/imperative-component-api",
|
||||
"status": "ACCURATE",
|
||||
"reasoning": "The distilled version correctly captures all essential information including API signatures, key behavioral differences from Svelte 4, return values, and critical notes about effects and flushSync, with only minor formatting improvements."
|
||||
},
|
||||
{
|
||||
"slug": "svelte/testing",
|
||||
"status": "ACCURATE",
|
||||
"reasoning": "The distilled version preserves all critical information, code examples, and key concepts from the original while appropriately condensing explanatory text and maintaining technical accuracy."
|
||||
},
|
||||
{
|
||||
"slug": "svelte/typescript",
|
||||
"status": "ACCURATE",
|
||||
"reasoning": "The distilled version correctly captures all essential information including TypeScript setup, limitations, configuration requirements, typing patterns, and code examples, with appropriate condensation but no factual errors or critical omissions."
|
||||
},
|
||||
{
|
||||
"slug": "svelte/custom-elements",
|
||||
"status": "ACCURATE",
|
||||
"reasoning": "The distilled version accurately captures all essential information including lifecycle behavior, component options, usage patterns, and caveats, with appropriate condensation and preserved code examples."
|
||||
},
|
||||
{
|
||||
"slug": "svelte/v4-migration-guide",
|
||||
"status": "ACCURATE",
|
||||
"reasoning": "The distilled version accurately captures all key migration information, requirements, code examples, and breaking changes from the original documentation, with appropriate condensation and formatting that preserves the essential technical details."
|
||||
},
|
||||
{
|
||||
"slug": "svelte/v5-migration-guide",
|
||||
"status": "ACCURATE",
|
||||
"reasoning": "The distilled version accurately captures all key migration information, breaking changes, and code examples from the original documentation, with appropriate condensation while preserving critical technical details and warnings."
|
||||
},
|
||||
{
|
||||
"slug": "svelte/faq",
|
||||
"status": "ACCURATE",
|
||||
"reasoning": "The distilled version correctly captures all essential information from the original, with appropriate condensation of explanations while preserving key facts, links, code examples, and critical details like the Svelte Native limitation in Svelte 5."
|
||||
},
|
||||
{
|
||||
"slug": "svelte/svelte",
|
||||
"status": "ACCURATE",
|
||||
"reasoning": "The distilled version correctly captures all essential information, properly marks deprecated features, preserves critical code examples and type signatures, and accurately represents the migration guidance from Svelte 4 to Svelte 5."
|
||||
},
|
||||
{
|
||||
"slug": "svelte/svelte-action",
|
||||
"status": "NOT_ACCURATE",
|
||||
"reasoning": "The distilled version incorrectly states \"Use `use:` directive to apply them\" which is not mentioned in the original documentation and could be misleading since the original explicitly states actions have been superseded by attachments."
|
||||
},
|
||||
{
|
||||
"slug": "svelte/svelte-animate",
|
||||
"status": "ACCURATE",
|
||||
"reasoning": "The distilled version correctly preserves all key information including the flip function signature, its purpose, the FLIP acronym explanation, and complete interface definitions for AnimationConfig and FlipParams."
|
||||
},
|
||||
{
|
||||
"slug": "svelte/svelte-attachments",
|
||||
"status": "NOT_ACCURATE",
|
||||
"reasoning": "The distilled version omits the critical \"Available since 5.29\" version information for createAttachmentKey, which is essential for developers to know compatibility requirements."
|
||||
},
|
||||
{
|
||||
"slug": "svelte/svelte-compiler",
|
||||
"status": "ACCURATE",
|
||||
"reasoning": "The distilled version correctly captures all essential information including function signatures, key options with defaults, type definitions, and important notes about deprecations and version changes, with appropriate simplifications that preserve meaning."
|
||||
},
|
||||
{
|
||||
"slug": "svelte/svelte-easing",
|
||||
"status": "ACCURATE",
|
||||
"reasoning": "The distilled version correctly captures all essential information including the import path, function signature, all available easing functions with their variants, and adds helpful context about the parameter/return value ranges and easing types without introducing any factual errors."
|
||||
},
|
||||
{
|
||||
"slug": "svelte/svelte-events",
|
||||
"status": "ACCURATE",
|
||||
"reasoning": "The distilled version correctly captures the essential functionality, key benefit, and API usage, with the type signatures reasonably simplified into a single generic form that encompasses all the specific overloads shown in the original."
|
||||
},
|
||||
{
|
||||
"slug": "svelte/svelte-legacy",
|
||||
"status": "ACCURATE",
|
||||
"reasoning": "The distilled version correctly captures all key functions, their purposes, and type signatures while appropriately condensing descriptions and maintaining the deprecated/temporary nature of the module."
|
||||
},
|
||||
{
|
||||
"slug": "svelte/svelte-motion",
|
||||
"status": "ACCURATE",
|
||||
"reasoning": "The distilled version correctly captures all essential information including API signatures, key properties, methods, availability dates, deprecation notices, and code examples, with appropriate simplifications that preserve the core concepts."
|
||||
},
|
||||
{
|
||||
"slug": "svelte/svelte-reactivity-window",
|
||||
"status": "ACCURATE",
|
||||
"reasoning": "The distilled version correctly captures all essential information including the reactive nature, usage examples, all exports, server-side behavior, and critical implementation details like browser differences and requestAnimationFrame updates."
|
||||
},
|
||||
{
|
||||
"slug": "svelte/svelte-reactivity",
|
||||
"status": "ACCURATE",
|
||||
"reasoning": "The distilled version accurately captures all key information, including API signatures, critical warnings (SSR/hydration, deep reactivity), and complete code examples, with only minor formatting simplifications."
|
||||
},
|
||||
{
|
||||
"slug": "svelte/svelte-server",
|
||||
"status": "NOT_ACCURATE",
|
||||
"reasoning": "The distilled version incorrectly simplifies the type signature by removing the conditional types that make props required when the component has required props (the `{} extends Props` conditional logic and the two different function overloads)."
|
||||
},
|
||||
{
|
||||
"slug": "svelte/svelte-store",
|
||||
"status": "ACCURATE",
|
||||
"reasoning": "The distilled version correctly captures all essential functions, their signatures, and key type definitions with appropriate simplifications to descriptions while maintaining technical accuracy."
|
||||
},
|
||||
{
|
||||
"slug": "svelte/svelte-transition",
|
||||
"status": "ACCURATE",
|
||||
"reasoning": "The distilled version correctly captures all essential information including function signatures, parameters, behavior descriptions, and type definitions, with only minor formatting simplifications and reasonable condensation of explanatory text."
|
||||
},
|
||||
{
|
||||
"slug": "svelte/compiler-errors",
|
||||
"status": "ACCURATE",
|
||||
"reasoning": "The distilled version accurately captures all key error messages, their meanings, and critical code examples while appropriately condensing the content without introducing factual errors or misleading information."
|
||||
},
|
||||
{
|
||||
"slug": "svelte/compiler-warnings",
|
||||
"status": "ACCURATE",
|
||||
"reasoning": "The distilled version accurately captures all key warnings with their essential information, code examples, and solutions, using appropriate condensation while preserving critical details for developers."
|
||||
},
|
||||
{
|
||||
"slug": "svelte/runtime-errors",
|
||||
"status": "NOT_ACCURATE",
|
||||
"reasoning": "The distilled version contains a syntax error in the effect_update_depth_exceeded section with an extra closing brace (`});` appears twice), which would mislead developers trying to understand the code example."
|
||||
},
|
||||
{
|
||||
"slug": "svelte/runtime-warnings",
|
||||
"status": "ACCURATE",
|
||||
"reasoning": "The distilled version correctly captures all key warnings with their essential explanations and code examples, using reasonable condensation while preserving critical technical details and fixes."
|
||||
},
|
||||
{
|
||||
"slug": "svelte/legacy-overview",
|
||||
"status": "ACCURATE",
|
||||
"reasoning": "The distilled version correctly captures the key information about Svelte 5 changes, the two modes, and the reference to v4 documentation, with only minor simplifications that preserve the essential meaning."
|
||||
},
|
||||
{
|
||||
"slug": "svelte/legacy-let",
|
||||
"status": "ACCURATE",
|
||||
"reasoning": "The distilled version correctly captures all essential information including the auto-reactive nature of top-level variables, the array methods gotcha, and preserves the code examples accurately, with only minor formatting changes for condensation."
|
||||
},
|
||||
{
|
||||
"slug": "svelte/legacy-reactive-assignments",
|
||||
"status": "ACCURATE",
|
||||
"reasoning": "The distilled version correctly captures all essential information including basic usage, topological ordering, dependencies, gotchas, and browser-only code, with appropriate simplifications and no factual errors."
|
||||
},
|
||||
{
|
||||
"slug": "svelte/legacy-export-let",
|
||||
"status": "ACCURATE",
|
||||
"reasoning": "The distilled version correctly captures all essential information including prop declaration syntax, default value behavior, the critical difference about undefined values not reverting, component exports, and prop renaming, with appropriate code examples preserved."
|
||||
},
|
||||
{
|
||||
"slug": "svelte/legacy-$$props-and-$$restProps",
|
||||
"status": "ACCURATE",
|
||||
"reasoning": "The distilled version correctly captures all essential information including the distinction between legacy and runes mode, the definitions of $$props and $$restProps, the complete code example, and the performance warning."
|
||||
},
|
||||
{
|
||||
"slug": "svelte/legacy-on",
|
||||
"status": "NOT_ACCURATE",
|
||||
"reasoning": "The distilled version omits the legacy createEventDispatcher implementation details and example usage that are still part of the current documentation, which could mislead developers who need to work with existing code using that pattern."
|
||||
},
|
||||
{
|
||||
"slug": "svelte/legacy-slots",
|
||||
"status": "ACCURATE",
|
||||
"reasoning": "The distilled version correctly captures all essential information including basic slots, named slots, fallback content, and passing data to slots, with appropriate code examples and no factual errors or critical omissions."
|
||||
},
|
||||
{
|
||||
"slug": "svelte/legacy-$$slots",
|
||||
"status": "ACCURATE",
|
||||
"reasoning": "The distilled version correctly captures the essential information about $$slots in legacy mode, preserves the code examples intact, and appropriately notes the runes mode alternative, with only minor formatting changes."
|
||||
},
|
||||
{
|
||||
"slug": "svelte/legacy-svelte-fragment",
|
||||
"status": "ACCURATE",
|
||||
"reasoning": "The distilled version correctly captures the essential functionality, preserves the complete code examples, and accurately conveys the Svelte 5+ obsolescence note, with only minor acceptable formatting changes."
|
||||
},
|
||||
{
|
||||
"slug": "svelte/legacy-svelte-component",
|
||||
"status": "ACCURATE",
|
||||
"reasoning": "The distilled version correctly captures all key information including the legacy mode behavior, runes mode alternative, and the falsy condition, with appropriate reorganization for clarity."
|
||||
},
|
||||
{
|
||||
"slug": "svelte/legacy-svelte-self",
|
||||
"status": "ACCURATE",
|
||||
"reasoning": "The distilled version correctly captures all essential information including the recursive functionality, the requirement to prevent infinite loops, the code example, and the obsolescence note with the self-import alternative."
|
||||
},
|
||||
{
|
||||
"slug": "svelte/legacy-component-api",
|
||||
"status": "ACCURATE",
|
||||
"reasoning": "The distilled version correctly captures all essential information including API methods, options tables, key behaviors (async vs sync updates), and Svelte 5 migration notes, with appropriate condensation of explanatory text while preserving critical technical details."
|
||||
}
|
||||
]
|
||||
}
|
||||
356
packages/mcp-server/src/distilled.json
Normal file
356
packages/mcp-server/src/distilled.json
Normal file
File diff suppressed because one or more lines are too long
172
packages/mcp-server/src/lib/anthropic.ts
Normal file
172
packages/mcp-server/src/lib/anthropic.ts
Normal file
@@ -0,0 +1,172 @@
|
||||
import { Anthropic } from '@anthropic-ai/sdk';
|
||||
import type { Model } from '@anthropic-ai/sdk/resources/messages/messages.js';
|
||||
import * as v from 'valibot';
|
||||
import {
|
||||
anthropic_batch_response_schema,
|
||||
anthropic_batch_result_schema,
|
||||
type AnthropicBatchRequest,
|
||||
} from './schemas.js';
|
||||
|
||||
export class AnthropicProvider {
|
||||
private client: Anthropic;
|
||||
private modelId: Model;
|
||||
private baseUrl: string;
|
||||
private apiKey: string;
|
||||
name = 'Anthropic';
|
||||
|
||||
constructor(model_id: Model, api_key: string) {
|
||||
if (!api_key) {
|
||||
throw new Error('ANTHROPIC_API_KEY is required');
|
||||
}
|
||||
this.apiKey = api_key;
|
||||
this.client = new Anthropic({ apiKey: api_key, timeout: 1800000 });
|
||||
this.modelId = model_id;
|
||||
this.baseUrl = 'https://api.anthropic.com/v1';
|
||||
}
|
||||
|
||||
get_client(): Anthropic {
|
||||
return this.client;
|
||||
}
|
||||
|
||||
get_model_identifier(): Model {
|
||||
return this.modelId;
|
||||
}
|
||||
|
||||
async create_batch(requests: AnthropicBatchRequest[]) {
|
||||
try {
|
||||
const response = await fetch(`${this.baseUrl}/messages/batches`, {
|
||||
method: 'POST',
|
||||
headers: {
|
||||
'x-api-key': this.apiKey,
|
||||
'anthropic-version': '2023-06-01',
|
||||
'content-type': 'application/json',
|
||||
},
|
||||
body: JSON.stringify({ requests }),
|
||||
});
|
||||
|
||||
if (!response.ok) {
|
||||
const error_text = await response.text();
|
||||
throw new Error(
|
||||
`Failed to create batch: ${response.status} ${response.statusText} - ${error_text}`,
|
||||
);
|
||||
}
|
||||
|
||||
const json_data = await response.json();
|
||||
const validated_response = v.safeParse(anthropic_batch_response_schema, json_data);
|
||||
|
||||
if (!validated_response.success) {
|
||||
throw new Error(
|
||||
`Invalid batch response from Anthropic API: ${JSON.stringify(validated_response.issues)}`,
|
||||
);
|
||||
}
|
||||
|
||||
return validated_response.output;
|
||||
} catch (error) {
|
||||
console.error('Error creating batch with Anthropic:', error);
|
||||
throw new Error(
|
||||
`Failed to create batch: ${error instanceof Error ? error.message : String(error)}`,
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
async get_batch_status(batch_id: string, max_retries = 10, retry_delay = 30000) {
|
||||
let retry_count = 0;
|
||||
|
||||
while (retry_count <= max_retries) {
|
||||
try {
|
||||
const response = await fetch(`${this.baseUrl}/messages/batches/${batch_id}`, {
|
||||
method: 'GET',
|
||||
headers: {
|
||||
'x-api-key': this.apiKey,
|
||||
'anthropic-version': '2023-06-01',
|
||||
},
|
||||
});
|
||||
|
||||
if (!response.ok) {
|
||||
const error_text = await response.text();
|
||||
throw new Error(
|
||||
`Failed to get batch status: ${response.status} ${response.statusText} - ${error_text}`,
|
||||
);
|
||||
}
|
||||
|
||||
const json_data = await response.json();
|
||||
const validated_response = v.safeParse(anthropic_batch_response_schema, json_data);
|
||||
|
||||
if (!validated_response.success) {
|
||||
throw new Error(
|
||||
`Invalid batch status response from Anthropic API: ${JSON.stringify(validated_response.issues)}`,
|
||||
);
|
||||
}
|
||||
|
||||
return validated_response.output;
|
||||
} catch (error) {
|
||||
retry_count++;
|
||||
|
||||
if (retry_count > max_retries) {
|
||||
console.error(
|
||||
`Error getting batch status for ${batch_id} after ${max_retries} retries:`,
|
||||
error,
|
||||
);
|
||||
throw new Error(
|
||||
`Failed to get batch status after ${max_retries} retries: ${
|
||||
error instanceof Error ? error.message : String(error)
|
||||
}`,
|
||||
);
|
||||
}
|
||||
|
||||
console.warn(
|
||||
`Error getting batch status for ${batch_id} (attempt ${retry_count}/${max_retries}):`,
|
||||
error,
|
||||
);
|
||||
console.log(`Retrying in ${retry_delay / 1000} seconds...`);
|
||||
|
||||
await new Promise((resolve) => setTimeout(resolve, retry_delay));
|
||||
}
|
||||
}
|
||||
|
||||
// This should never be reached due to the throw in the catch block, but TypeScript needs a return
|
||||
throw new Error(`Failed to get batch status for ${batch_id} after ${max_retries} retries`);
|
||||
}
|
||||
|
||||
async get_batch_results(results_url: string) {
|
||||
try {
|
||||
const response = await fetch(results_url, {
|
||||
method: 'GET',
|
||||
headers: {
|
||||
'x-api-key': this.apiKey,
|
||||
'anthropic-version': '2023-06-01',
|
||||
},
|
||||
});
|
||||
|
||||
if (!response.ok) {
|
||||
const error_text = await response.text();
|
||||
throw new Error(
|
||||
`Failed to get batch results: ${response.status} ${response.statusText} - ${error_text}`,
|
||||
);
|
||||
}
|
||||
|
||||
const text = await response.text();
|
||||
// Parse JSONL format (one JSON object per line)
|
||||
const parsed_results = text
|
||||
.split('\n')
|
||||
.filter((line) => line.trim())
|
||||
.map((line) => JSON.parse(line));
|
||||
|
||||
// Validate all results
|
||||
const validated_results = v.safeParse(v.array(anthropic_batch_result_schema), parsed_results);
|
||||
|
||||
if (!validated_results.success) {
|
||||
throw new Error(
|
||||
`Invalid batch results from Anthropic API: ${JSON.stringify(validated_results.issues)}`,
|
||||
);
|
||||
}
|
||||
|
||||
return validated_results.output;
|
||||
} catch (error) {
|
||||
console.error(`Error getting batch results:`, error);
|
||||
throw new Error(
|
||||
`Failed to get batch results: ${error instanceof Error ? error.message : String(error)}`,
|
||||
);
|
||||
}
|
||||
}
|
||||
}
|
||||
106
packages/mcp-server/src/lib/schemas.ts
Normal file
106
packages/mcp-server/src/lib/schemas.ts
Normal file
@@ -0,0 +1,106 @@
|
||||
import * as v from 'valibot';
|
||||
|
||||
export const documentation_sections_schema = v.record(
|
||||
v.string(),
|
||||
v.object({
|
||||
metadata: v.object({
|
||||
title: v.string(),
|
||||
use_cases: v.optional(v.string()),
|
||||
}),
|
||||
slug: v.string(),
|
||||
}),
|
||||
);
|
||||
|
||||
// Valibot schemas for Batch API
|
||||
export const summary_data_schema = v.object({
|
||||
generated_at: v.string(),
|
||||
model: v.string(),
|
||||
total_sections: v.number(),
|
||||
successful_summaries: v.number(),
|
||||
summaries: v.record(v.string(), v.string()),
|
||||
content: v.record(v.string(), v.string()),
|
||||
});
|
||||
|
||||
export const anthropic_batch_request_schema = v.object({
|
||||
custom_id: v.string(),
|
||||
params: v.object({
|
||||
model: v.string(),
|
||||
max_tokens: v.number(),
|
||||
messages: v.array(
|
||||
v.object({
|
||||
role: v.union([v.literal('user'), v.literal('assistant')]),
|
||||
content: v.union([
|
||||
v.string(),
|
||||
v.array(
|
||||
v.object({
|
||||
type: v.string(),
|
||||
text: v.string(),
|
||||
}),
|
||||
),
|
||||
]),
|
||||
}),
|
||||
),
|
||||
}),
|
||||
});
|
||||
|
||||
export const anthropic_batch_response_schema = v.object({
|
||||
id: v.string(),
|
||||
type: v.string(),
|
||||
processing_status: v.union([v.literal('in_progress'), v.literal('ended')]),
|
||||
request_counts: v.object({
|
||||
processing: v.number(),
|
||||
succeeded: v.number(),
|
||||
errored: v.number(),
|
||||
canceled: v.number(),
|
||||
expired: v.number(),
|
||||
}),
|
||||
ended_at: v.nullable(v.string()),
|
||||
created_at: v.string(),
|
||||
expires_at: v.string(),
|
||||
cancel_initiated_at: v.nullable(v.string()),
|
||||
results_url: v.nullable(v.string()),
|
||||
});
|
||||
|
||||
export const anthropic_batch_result_schema = v.object({
|
||||
custom_id: v.string(),
|
||||
result: v.object({
|
||||
type: v.union([
|
||||
v.literal('succeeded'),
|
||||
v.literal('errored'),
|
||||
v.literal('canceled'),
|
||||
v.literal('expired'),
|
||||
]),
|
||||
message: v.optional(
|
||||
v.object({
|
||||
id: v.string(),
|
||||
type: v.string(),
|
||||
role: v.string(),
|
||||
model: v.string(),
|
||||
content: v.array(
|
||||
v.object({
|
||||
type: v.string(),
|
||||
text: v.string(),
|
||||
}),
|
||||
),
|
||||
stop_reason: v.string(),
|
||||
stop_sequence: v.nullable(v.string()),
|
||||
usage: v.object({
|
||||
input_tokens: v.number(),
|
||||
output_tokens: v.number(),
|
||||
}),
|
||||
}),
|
||||
),
|
||||
error: v.optional(
|
||||
v.object({
|
||||
type: v.string(),
|
||||
message: v.string(),
|
||||
}),
|
||||
),
|
||||
}),
|
||||
});
|
||||
|
||||
// Export inferred types
|
||||
export type SummaryData = v.InferOutput<typeof summary_data_schema>;
|
||||
export type AnthropicBatchRequest = v.InferOutput<typeof anthropic_batch_request_schema>;
|
||||
export type AnthropicBatchResponse = v.InferOutput<typeof anthropic_batch_response_schema>;
|
||||
export type AnthropicBatchResult = v.InferOutput<typeof anthropic_batch_result_schema>;
|
||||
@@ -61,7 +61,7 @@ describe('add_autofixers_issues', () => {
|
||||
<script>
|
||||
const count = ${init}(0);
|
||||
</script>
|
||||
|
||||
|
||||
<button onclick={() => count = 43}>Increment</button>
|
||||
`);
|
||||
|
||||
@@ -74,7 +74,7 @@ describe('add_autofixers_issues', () => {
|
||||
const content = run_autofixers_on_code(`
|
||||
<script>
|
||||
const count = 0;
|
||||
|
||||
|
||||
$effect(() => {
|
||||
count = 43;
|
||||
});
|
||||
@@ -89,7 +89,7 @@ describe('add_autofixers_issues', () => {
|
||||
const content = run_autofixers_on_code(`
|
||||
<script>
|
||||
let count = ${init}(0);
|
||||
|
||||
|
||||
$effect(() => {
|
||||
count++;
|
||||
});
|
||||
@@ -105,7 +105,7 @@ describe('add_autofixers_issues', () => {
|
||||
const content = run_autofixers_on_code(`
|
||||
<script>
|
||||
let count = ${init}({ value: 0 });
|
||||
|
||||
|
||||
$effect(() => {
|
||||
count.value = 42;
|
||||
});
|
||||
@@ -116,6 +116,52 @@ describe('add_autofixers_issues', () => {
|
||||
'The stateful variable "count" is assigned inside an $effect which is generally consider a malpractice. Consider using $derived if possible.',
|
||||
);
|
||||
});
|
||||
|
||||
it(`should add a suggestion for variables that are mutated within an effect.pre`, () => {
|
||||
const content = run_autofixers_on_code(`
|
||||
<script>
|
||||
let count = ${init}({ value: 0 });
|
||||
|
||||
$effect.pre(() => {
|
||||
count.value = 42;
|
||||
});
|
||||
</script>
|
||||
`);
|
||||
|
||||
expect(content.suggestions).toContain(
|
||||
'The stateful variable "count" is assigned inside an $effect which is generally consider a malpractice. Consider using $derived if possible.',
|
||||
);
|
||||
});
|
||||
});
|
||||
|
||||
it('should add a suggestion when calling a function inside an effect', () => {
|
||||
const content = run_autofixers_on_code(`
|
||||
<script>
|
||||
import { fetch_data } from './data.js';
|
||||
$effect(() => {
|
||||
fetch_data();
|
||||
});
|
||||
</script>`);
|
||||
|
||||
expect(content.suggestions.length).toBeGreaterThanOrEqual(1);
|
||||
expect(content.suggestions).toContain(
|
||||
`You are calling the function \`fetch_data\` inside an $effect. Please check if the function is reassigning a stateful variable because that's considered malpractice and check if it could use \`$derived\` instead. Ignore this suggestion if you are sure this function is not assigning any stateful variable or if you can't check if it does.`,
|
||||
);
|
||||
});
|
||||
|
||||
it('should add a suggestion when calling a function inside an effect (with non identifier callee)', () => {
|
||||
const content = run_autofixers_on_code(`
|
||||
<script>
|
||||
import { fetch_data } from './data.js';
|
||||
$effect(() => {
|
||||
fetch_data.fetch();
|
||||
});
|
||||
</script>`);
|
||||
|
||||
expect(content.suggestions.length).toBeGreaterThanOrEqual(1);
|
||||
expect(content.suggestions).toContain(
|
||||
`You are calling a function inside an $effect. Please check if the function is reassigning a stateful variable because that's considered malpractice and check if it could use \`$derived\` instead. Ignore this suggestion if you are sure this function is not assigning any stateful variable or if you can't check if it does.`,
|
||||
);
|
||||
});
|
||||
});
|
||||
|
||||
@@ -366,6 +412,19 @@ describe('add_autofixers_issues', () => {
|
||||
});
|
||||
},
|
||||
);
|
||||
|
||||
describe.each(dollarless_runes)('importing $rune from external lib', ({ rune }) => {
|
||||
it(`should not add suggestions when importing from packages that are not svelte`, () => {
|
||||
const content = run_autofixers_on_code(`
|
||||
<script>
|
||||
import { ${rune} } from 'svelte-something-something';
|
||||
</script>`);
|
||||
|
||||
expect(content.suggestions).not.toContain(
|
||||
`You are importing "${rune}" from "svelte-something-something". This is not necessary, all runes are globally available. Please remove this import and use "$${rune}" directly.`,
|
||||
);
|
||||
});
|
||||
});
|
||||
});
|
||||
|
||||
describe('derived_with_function', () => {
|
||||
@@ -468,4 +527,229 @@ describe('add_autofixers_issues', () => {
|
||||
);
|
||||
});
|
||||
});
|
||||
|
||||
describe('suggest_attachments', () => {
|
||||
describe('bind:this', () => {
|
||||
it('should add suggestions when using bind:this on an element', () => {
|
||||
const content = run_autofixers_on_code(`
|
||||
<script>
|
||||
let a = $state();
|
||||
</script>
|
||||
|
||||
<a bind:this={a} />`);
|
||||
|
||||
expect(content.suggestions.length).toBeGreaterThanOrEqual(1);
|
||||
expect(content.suggestions).toContain(
|
||||
'The usage of `bind:this` can often be replaced with an easier to read `action` or even better an `attachment`. Consider using the latter if possible.',
|
||||
);
|
||||
});
|
||||
|
||||
it('should not add suggestions when using bind:this on a component', () => {
|
||||
const content = run_autofixers_on_code(`
|
||||
<script>
|
||||
import Child from './Child.svelte';
|
||||
let a = $state();
|
||||
</script>
|
||||
|
||||
<Child bind:this={a} />`);
|
||||
|
||||
expect(content.suggestions).not.toContain(
|
||||
'The usage of `bind:this` can often be replaced with an easier to read `action` or even better an `attachment`. Consider using the latter if possible.',
|
||||
);
|
||||
});
|
||||
|
||||
it('should not add suggestions when using bind:this on a component nested in an element', () => {
|
||||
const content = run_autofixers_on_code(`
|
||||
<script>
|
||||
import Child from './Child.svelte';
|
||||
let a = $state();
|
||||
</script>
|
||||
|
||||
<div>
|
||||
<Child bind:this={a} />
|
||||
</div>`);
|
||||
|
||||
expect(content.suggestions).not.toContain(
|
||||
'The usage of `bind:this` can often be replaced with an easier to read `action` or even better an `attachment`. Consider using the latter if possible.',
|
||||
);
|
||||
});
|
||||
|
||||
it('should add suggestions but not suggest attachments when using bind:this on an element and the desired svelte version is 4', () => {
|
||||
const content = run_autofixers_on_code(
|
||||
`
|
||||
<script>
|
||||
let a;
|
||||
</script>
|
||||
|
||||
<a bind:this={a} />`,
|
||||
4,
|
||||
);
|
||||
|
||||
expect(content.suggestions.length).toBeGreaterThanOrEqual(1);
|
||||
expect(content.suggestions).toContain(
|
||||
'The usage of `bind:this` can often be replaced with an easier to read `action`. Consider using the latter if possible.',
|
||||
);
|
||||
});
|
||||
});
|
||||
|
||||
describe('use:', () => {
|
||||
it('should add suggestions when using use: on an element and the action is declared as a function', () => {
|
||||
const content = run_autofixers_on_code(
|
||||
`<script>
|
||||
function my_action(node) {
|
||||
// do something with the node
|
||||
}
|
||||
</script>
|
||||
|
||||
<a use:my_action />`,
|
||||
);
|
||||
|
||||
expect(content.suggestions.length).toBeGreaterThanOrEqual(1);
|
||||
expect(content.suggestions).toContain(
|
||||
'Consider using an `attachment` instead of an `action` for "my_action".',
|
||||
);
|
||||
});
|
||||
|
||||
it('should add suggestions when using use: on an element and the action is declared as a variable', () => {
|
||||
const content = run_autofixers_on_code(
|
||||
`<script>
|
||||
const my_action = (node) => {
|
||||
// do something with the node
|
||||
}
|
||||
</script>
|
||||
|
||||
<a use:my_action />`,
|
||||
);
|
||||
|
||||
expect(content.suggestions.length).toBeGreaterThanOrEqual(1);
|
||||
expect(content.suggestions).toContain(
|
||||
'Consider using an `attachment` instead of an `action` for "my_action".',
|
||||
);
|
||||
});
|
||||
|
||||
it('should add suggestions when using use: on an element and the action is declared as an object', () => {
|
||||
const content = run_autofixers_on_code(
|
||||
`<script>
|
||||
const my_action = {
|
||||
action: (node) => {
|
||||
// do something with the node
|
||||
}
|
||||
};
|
||||
</script>
|
||||
|
||||
<a use:my_action.action />`,
|
||||
);
|
||||
|
||||
expect(content.suggestions.length).toBeGreaterThanOrEqual(1);
|
||||
expect(content.suggestions).toContain(
|
||||
'Consider using an `attachment` instead of an `action` for "my_action".',
|
||||
);
|
||||
});
|
||||
|
||||
it('should not add suggestions when using use: on an element and the desired svelte version is 4', () => {
|
||||
const content = run_autofixers_on_code(
|
||||
`<script>
|
||||
function my_action(node) {
|
||||
// do something with the node
|
||||
}
|
||||
</script>
|
||||
|
||||
<a use:my_action />`,
|
||||
4,
|
||||
);
|
||||
|
||||
expect(content.suggestions).not.toContain(
|
||||
'Consider using an `attachment` instead of an `action` for "my_action".',
|
||||
);
|
||||
});
|
||||
|
||||
it('should not add suggestions when using use: on an element and the action comes from an import', () => {
|
||||
const content = run_autofixers_on_code(
|
||||
`<script>
|
||||
import { my_action } from './actions.js';
|
||||
</script>
|
||||
|
||||
<a use:my_action />`,
|
||||
);
|
||||
|
||||
expect(content.suggestions).not.toContain(
|
||||
'Consider using an `attachment` instead of an `action` for "my_action".',
|
||||
);
|
||||
});
|
||||
|
||||
it('should not add suggestions when using use: on an element and the action comes from the props', () => {
|
||||
const content = run_autofixers_on_code(
|
||||
`<script>
|
||||
const { my_action } = $props();
|
||||
</script>
|
||||
|
||||
<a use:my_action />`,
|
||||
);
|
||||
|
||||
expect(content.suggestions).not.toContain(
|
||||
'Consider using an `attachment` instead of an `action` for "my_action".',
|
||||
);
|
||||
});
|
||||
|
||||
it('should not add suggestions when using use: on an element and the action comes from a global variable', () => {
|
||||
const content = run_autofixers_on_code(`<a use:my_action />`);
|
||||
|
||||
expect(content.suggestions).not.toContain(
|
||||
'Consider using an `attachment` instead of an `action` for "my_action".',
|
||||
);
|
||||
});
|
||||
});
|
||||
});
|
||||
describe('read_state_with_dollar', () => {
|
||||
with_possible_inits('($init)', ({ init }) => {
|
||||
it(`should add an issue when reading a stateful variable initialized with ${init} like if it was a store`, () => {
|
||||
const content = run_autofixers_on_code(`<script>
|
||||
let x = ${init}(()=> 43);
|
||||
$x;
|
||||
</script>
|
||||
`);
|
||||
|
||||
expect(content.issues).toContain(
|
||||
`You are reading the stateful variable "$x" with a "$" prefix. Stateful variables are not stores and should be read without the "$". Please read it as a normal variable "x"`,
|
||||
);
|
||||
});
|
||||
});
|
||||
|
||||
it(`should not add an issue when reading an imported variable like if it was a store`, () => {
|
||||
const content = run_autofixers_on_code(`<script>
|
||||
import { x } from "./my-stores.ts";
|
||||
$x;
|
||||
</script>
|
||||
`);
|
||||
|
||||
expect(content.issues).not.toContain(
|
||||
`You are reading the stateful variable "$x" with a "$" prefix. Stateful variables are not stores and should be read without the "$". Please read it as a normal variable "x"`,
|
||||
);
|
||||
});
|
||||
|
||||
it(`should not add an issue when reading a non-stateful variable like if it was a store`, () => {
|
||||
const content = run_autofixers_on_code(`<script>
|
||||
import { writable } from "svelte/store";
|
||||
const x = writable(0);
|
||||
$x;
|
||||
</script>
|
||||
`);
|
||||
|
||||
expect(content.issues).not.toContain(
|
||||
`You are reading the stateful variable "$x" with a "$" prefix. Stateful variables are not stores and should be read without the "$". Please read it as a normal variable "x"`,
|
||||
);
|
||||
});
|
||||
|
||||
it(`should not add an issue when reading a prop like if it was a store`, () => {
|
||||
const content = run_autofixers_on_code(`<script>
|
||||
const { x } = $props();
|
||||
$x;
|
||||
</script>
|
||||
`);
|
||||
|
||||
expect(content.issues).not.toContain(
|
||||
`You are reading the stateful variable "$x" with a "$" prefix. Stateful variables are not stores and should be read without the "$". Please read it as a normal variable "x"`,
|
||||
);
|
||||
});
|
||||
});
|
||||
});
|
||||
|
||||
@@ -1,4 +1,6 @@
|
||||
import { compile } from 'svelte/compiler';
|
||||
import { compile as compile_component, compileModule } from 'svelte/compiler';
|
||||
import { extname } from 'path';
|
||||
import ts from 'ts-blank-space';
|
||||
|
||||
export function add_compile_issues(
|
||||
content: { issues: string[]; suggestions: string[] },
|
||||
@@ -6,6 +8,21 @@ export function add_compile_issues(
|
||||
desired_svelte_version: number,
|
||||
filename = 'Component.svelte',
|
||||
) {
|
||||
let compile = compile_component;
|
||||
const extension = extname(filename);
|
||||
if (extension !== '.svelte') {
|
||||
compile = compileModule;
|
||||
// compile module doesn't accept .ts files so we need to transpile them first with ts-blank-space
|
||||
// a fast and lightweight typescript transpiler that can strips types replacing them with white spaces
|
||||
// so the code positions are not affected
|
||||
if (extension === '.ts') {
|
||||
code = ts(code, (node) => {
|
||||
content.issues.push(
|
||||
`The provided file is a module but it contains invalid TypeScript code: ${node.getText()} at ${node.getStart()}`,
|
||||
);
|
||||
});
|
||||
}
|
||||
}
|
||||
const compilation_result = compile(code, {
|
||||
filename: filename || 'Component.svelte',
|
||||
generate: false,
|
||||
|
||||
@@ -12,7 +12,7 @@ function base_config(svelte_config: Config): ESLint.Options['baseConfig'] {
|
||||
return [
|
||||
...svelte.configs.recommended,
|
||||
{
|
||||
files: ['*.svelte'],
|
||||
files: ['*.svelte', '*.svelte.ts', '*.svelte.js'],
|
||||
rules: {
|
||||
'no-self-assign': 'warn',
|
||||
'svelte/infinite-reactive-loop': 'warn',
|
||||
|
||||
@@ -1,4 +1,10 @@
|
||||
import type { AssignmentExpression, Identifier, Node, UpdateExpression } from 'estree';
|
||||
import type {
|
||||
AssignmentExpression,
|
||||
CallExpression,
|
||||
Identifier,
|
||||
Node,
|
||||
UpdateExpression,
|
||||
} from 'estree';
|
||||
import type { Autofixer, AutofixerState } from './index.js';
|
||||
import { left_most_id } from '../ast/utils.js';
|
||||
import type { AST } from 'svelte-eslint-parser';
|
||||
@@ -11,25 +17,17 @@ function run_if_in_effect(
|
||||
) {
|
||||
const in_effect = path.findLast(
|
||||
(node) =>
|
||||
node.type === 'CallExpression' &&
|
||||
node.callee.type === 'Identifier' &&
|
||||
node.callee.name === '$effect',
|
||||
node.type === 'CallExpression' && state.parsed.is_rune(node, ['$effect', '$effect.pre']),
|
||||
);
|
||||
|
||||
if (
|
||||
in_effect &&
|
||||
in_effect.type === 'CallExpression' &&
|
||||
(in_effect.callee.type === 'Identifier' || in_effect.callee.type === 'MemberExpression')
|
||||
) {
|
||||
if (state.parsed.is_rune(in_effect, ['$effect', '$effect.pre'])) {
|
||||
to_run();
|
||||
}
|
||||
if (in_effect) {
|
||||
to_run();
|
||||
}
|
||||
}
|
||||
|
||||
function visitor(
|
||||
function assign_or_update_visitor(
|
||||
node: UpdateExpression | AssignmentExpression,
|
||||
{ state, path }: Context<Node | AST.SvelteNode, AutofixerState>,
|
||||
{ state, path, next }: Context<Node | AST.SvelteNode, AutofixerState>,
|
||||
) {
|
||||
run_if_in_effect(path, state, () => {
|
||||
function check_if_stateful_id(id: Identifier) {
|
||||
@@ -58,9 +56,25 @@ function visitor(
|
||||
}
|
||||
}
|
||||
});
|
||||
next();
|
||||
}
|
||||
|
||||
function call_expression_visitor(
|
||||
node: CallExpression,
|
||||
{ state, path, next }: Context<Node | AST.SvelteNode, AutofixerState>,
|
||||
) {
|
||||
run_if_in_effect(path, state, () => {
|
||||
const function_name =
|
||||
node.callee.type === 'Identifier' ? `the function \`${node.callee.name}\`` : 'a function';
|
||||
state.output.suggestions.push(
|
||||
`You are calling ${function_name} inside an $effect. Please check if the function is reassigning a stateful variable because that's considered malpractice and check if it could use \`$derived\` instead. Ignore this suggestion if you are sure this function is not assigning any stateful variable or if you can't check if it does.`,
|
||||
);
|
||||
});
|
||||
next();
|
||||
}
|
||||
|
||||
export const assign_in_effect: Autofixer = {
|
||||
UpdateExpression: visitor,
|
||||
AssignmentExpression: visitor,
|
||||
UpdateExpression: assign_or_update_visitor,
|
||||
AssignmentExpression: assign_or_update_visitor,
|
||||
CallExpression: call_expression_visitor,
|
||||
};
|
||||
|
||||
@@ -6,7 +6,7 @@ const dollarless_runes = base_runes.map((r) => r.replace('$', ''));
|
||||
export const imported_runes: Autofixer = {
|
||||
ImportDeclaration(node, { state, next }) {
|
||||
const source = (node.source.value || node.source.raw?.slice(1, -1))?.toString();
|
||||
if (source && source.startsWith('svelte')) {
|
||||
if (source && (source === 'svelte' || source.startsWith('svelte/'))) {
|
||||
for (const specifier of node.specifiers) {
|
||||
const id =
|
||||
specifier.type === 'ImportDefaultSpecifier'
|
||||
|
||||
@@ -16,3 +16,5 @@ export * from './wrong-property-access-state.js';
|
||||
export * from './imported-runes.js';
|
||||
export * from './derived-with-function.js';
|
||||
export * from './use-runes-instead-of-store.js';
|
||||
export * from './suggest-attachments.js';
|
||||
export * from './read-state-with-dollar.js';
|
||||
|
||||
@@ -0,0 +1,22 @@
|
||||
import type { Autofixer } from './index.js';
|
||||
|
||||
export const read_state_with_dollar: Autofixer = {
|
||||
Identifier(node, { state }) {
|
||||
if (node.name.startsWith('$')) {
|
||||
const reference = state.parsed.find_reference_by_id(node);
|
||||
if (reference && reference.resolved && reference.resolved.defs[0]?.node?.init) {
|
||||
const is_state = state.parsed.is_rune(reference.resolved.defs[0].node.init, [
|
||||
'$state',
|
||||
'$state.raw',
|
||||
'$derived',
|
||||
'$derived.by',
|
||||
]);
|
||||
if (is_state) {
|
||||
state.output.issues.push(
|
||||
`You are reading the stateful variable "${node.name}" with a "$" prefix. Stateful variables are not stores and should be read without the "$". Please read it as a normal variable "${node.name.substring(1)}"`,
|
||||
);
|
||||
}
|
||||
}
|
||||
}
|
||||
},
|
||||
};
|
||||
@@ -0,0 +1,46 @@
|
||||
import type { Identifier } from 'estree';
|
||||
import type { Autofixer } from './index.js';
|
||||
import { left_most_id } from '../ast/utils.js';
|
||||
|
||||
export const suggest_attachments: Autofixer = {
|
||||
SvelteDirective(node, { state, next, path }) {
|
||||
if (node.kind === 'Binding' && node.key.name.name === 'this') {
|
||||
const parent_element = path.findLast((p) => p.type === 'SvelteElement');
|
||||
if (parent_element?.kind === 'html' && parent_element.startTag.attributes.includes(node)) {
|
||||
let better_an_attachment = ` or even better an \`attachment\``;
|
||||
if (state.desired_svelte_version === 4) {
|
||||
better_an_attachment = ``;
|
||||
}
|
||||
state.output.suggestions.push(
|
||||
`The usage of \`bind:this\` can often be replaced with an easier to read \`action\`${better_an_attachment}. Consider using the latter if possible.`,
|
||||
);
|
||||
}
|
||||
} else if (node.kind === 'Action' && state.desired_svelte_version === 5) {
|
||||
let id: Identifier | null = null;
|
||||
if (node.key.name.type === 'Identifier') {
|
||||
id = node.key.name;
|
||||
} else if (node.key.name.type === 'MemberExpression') {
|
||||
id = left_most_id(node.key.name);
|
||||
}
|
||||
if (id) {
|
||||
const reference = state.parsed.find_reference_by_id(id);
|
||||
const definition = reference?.resolved?.defs[0];
|
||||
if (
|
||||
definition &&
|
||||
(definition.type === 'Variable' ||
|
||||
!(definition.type === 'ImportBinding' || definition.type === 'Parameter')) &&
|
||||
!(
|
||||
definition.type === 'Variable' &&
|
||||
definition.node.init?.type === 'CallExpression' &&
|
||||
state.parsed.is_rune(definition.node.init, ['$props'])
|
||||
)
|
||||
) {
|
||||
state.output.suggestions.push(
|
||||
`Consider using an \`attachment\` instead of an \`action\` for "${id.name}".`,
|
||||
);
|
||||
}
|
||||
}
|
||||
}
|
||||
next();
|
||||
},
|
||||
};
|
||||
@@ -1 +1 @@
|
||||
export * from './svelte-task.js';
|
||||
export { setup_svelte_task } from './svelte-task.js';
|
||||
|
||||
@@ -1,31 +1,18 @@
|
||||
import type { SvelteMcp } from '../../index.js';
|
||||
import * as v from 'valibot';
|
||||
import { get_sections } from '../../utils.js';
|
||||
import { format_sections_list } from '../../utils.js';
|
||||
|
||||
export function setup_svelte_task(server: SvelteMcp) {
|
||||
server.prompt(
|
||||
{
|
||||
name: 'svelte-task-prompt',
|
||||
title: 'Svelte Task Prompt',
|
||||
description:
|
||||
'Use this Prompt to ask for any svelte related task. It will automatically instruct the LLM on how to best use the autofixer and how to query for documentation pages.',
|
||||
schema: v.object({
|
||||
task: v.pipe(v.string(), v.description('The task to be performed')),
|
||||
}),
|
||||
},
|
||||
async ({ task }) => {
|
||||
const available_docs: string[] = (await get_sections()).map((s) => s.title);
|
||||
/**
|
||||
* Function that actually generates the prompt string. You can use this in the MCP server handler to generate the prompt, it can accept arguments
|
||||
* if needed (it will always be invoked manually so it's up to you to provide the arguments).
|
||||
*/
|
||||
function svelte_task(available_docs: string, task: string) {
|
||||
return `You are a Svelte expert tasked to build components and utilities for Svelte developers. If you need documentation for anything related to Svelte you can invoke the tool \`get_documentation\` with one of the following paths:
|
||||
<available-docs>
|
||||
|
||||
return {
|
||||
messages: [
|
||||
{
|
||||
role: 'user',
|
||||
content: {
|
||||
type: 'text',
|
||||
text: `You are a Svelte expert tasked to build components and utilities for Svelte developers. If you need documentation for anything related to Svelte you can invoke the tool \`get-documentation\` with one of the following paths:
|
||||
<available-docs-paths>
|
||||
${JSON.stringify(available_docs, null, 2)}
|
||||
</available-docs-paths>
|
||||
${available_docs}
|
||||
|
||||
</available-docs>
|
||||
|
||||
Every time you write a Svelte component or a Svelte module you MUST invoke the \`svelte-autofixer\` tool providing the code. The tool will return a list of issues or suggestions. If there are any issues or suggestions you MUST fix them and call the tool again with the updated code. You MUST keep doing this until the tool returns no issues or suggestions. Only then you can return the code to the user.
|
||||
|
||||
@@ -35,8 +22,59 @@ This is the task you will work on:
|
||||
${task}
|
||||
</task>
|
||||
|
||||
If you are not writing the code into a file, once you have the final version of the code ask the user if it wants to generate a playground link to quickly check the code in it and if it answer yes call the \`playground-link\` tool and return the url to the user nicely formatted. The playground link MUST be generated only once you have the final version of the code and you are ready to share it, it MUST include an entry point file called \`App.svelte\` where the main component should live. If you have multiple files to include in the playground link you can include them all at the root.
|
||||
`,
|
||||
If you are not writing the code into a file, once you have the final version of the code ask the user if it wants to generate a playground link to quickly check the code in it and if it answer yes call the \`playground-link\` tool and return the url to the user nicely formatted. The playground link MUST be generated only once you have the final version of the code and you are ready to share it, it MUST include an entry point file called \`App.svelte\` where the main component should live. If you have multiple files to include in the playground link you can include them all at the root.`;
|
||||
}
|
||||
|
||||
/**
|
||||
* This function is used to generate the prompt to update the docs in the script `/scripts/update-docs-prompts.ts` it should use the default export
|
||||
* function and pass in the arguments. Since it will be included in the documentation if it's an argument that the MCP will expose it should
|
||||
* be in the format [NAME_OF_THE_ARGUMENT] to signal the user that it can substitute it.
|
||||
*
|
||||
* The name NEEDS to be `generate_for_docs`.
|
||||
*/
|
||||
export async function generate_for_docs() {
|
||||
const available_docs = await format_sections_list();
|
||||
return svelte_task(available_docs, '[YOUR TASK HERE]');
|
||||
}
|
||||
|
||||
/**
|
||||
* Human readable description of what the prompt does. It will be included in the documentation.
|
||||
*
|
||||
* The name NEEDS to be `docs_description`.
|
||||
*/
|
||||
export const docs_description =
|
||||
'This prompt should be used whenever you are asking the model to work on a Svelte-related task. It will instruct the LLM which documentation sections are available, which tools to invoke, when to invoke them, and how to interpret the results.';
|
||||
|
||||
export function setup_svelte_task(server: SvelteMcp) {
|
||||
server.prompt(
|
||||
{
|
||||
name: 'svelte-task',
|
||||
title: 'Svelte-Task-Prompt',
|
||||
description:
|
||||
'Use this Prompt to ask for any svelte related task. It will automatically instruct the LLM on how to best use the autofixer and how to query for documentation pages.',
|
||||
schema: v.object({
|
||||
task: v.pipe(v.string(), v.description('The task to be performed')),
|
||||
}),
|
||||
complete: {
|
||||
task() {
|
||||
return {
|
||||
completion: {
|
||||
values: [''],
|
||||
},
|
||||
};
|
||||
},
|
||||
},
|
||||
},
|
||||
async ({ task }) => {
|
||||
const available_docs = await format_sections_list();
|
||||
|
||||
return {
|
||||
messages: [
|
||||
{
|
||||
role: 'user',
|
||||
content: {
|
||||
type: 'text',
|
||||
text: svelte_task(available_docs, task),
|
||||
},
|
||||
},
|
||||
],
|
||||
|
||||
@@ -6,7 +6,7 @@ export async function list_sections(server: SvelteMcp) {
|
||||
|
||||
server.template(
|
||||
{
|
||||
name: 'Svelte Doc Section',
|
||||
name: 'Svelte-Doc-Section',
|
||||
description: 'A single documentation section',
|
||||
list() {
|
||||
return sections.map((section) => {
|
||||
|
||||
@@ -1,25 +1,38 @@
|
||||
import type { SvelteMcp } from '../../index.js';
|
||||
import * as v from 'valibot';
|
||||
import { get_sections, fetch_with_timeout } from '../../utils.js';
|
||||
import {
|
||||
get_sections,
|
||||
fetch_with_timeout,
|
||||
format_sections_list,
|
||||
get_distilled_content,
|
||||
} from '../../utils.js';
|
||||
import { SECTIONS_LIST_INTRO, SECTIONS_LIST_OUTRO } from './prompts.js';
|
||||
|
||||
export function get_documentation(server: SvelteMcp) {
|
||||
server.tool(
|
||||
{
|
||||
name: 'get-documentation',
|
||||
enabled: () => false,
|
||||
description:
|
||||
'Retrieves full documentation content for Svelte 5 or SvelteKit sections. Supports flexible search by title (e.g., "$state", "routing") or file path (e.g., "docs/svelte/state.md"). Can accept a single section name or an array of sections. Before running this, make sure to analyze the users query, as well as the output from list-sections (which should be called first). Then ask for ALL relevant sections the user might require. For example, if the user asks to build anything interactive, you will need to fetch all relevant runes, and so on.',
|
||||
'Retrieves documentation content for Svelte 5 or SvelteKit sections. Supports flexible search by title (e.g., "$state", "routing") or file path (e.g., "cli/overview"). Can accept a single section name or an array of sections. Before running this, make sure to analyze the users query, as well as the output from list-sections (which should be called first). Then ask for ALL relevant sections the user might require. For example, if the user asks to build anything interactive, you will need to fetch all relevant runes, and so on.',
|
||||
schema: v.object({
|
||||
section: v.pipe(
|
||||
v.union([v.string(), v.array(v.string())]),
|
||||
v.description(
|
||||
'The section name(s) to retrieve. Can search by title (e.g., "$state", "load functions") or file path (e.g., "docs/svelte/state.md"). Supports single string and array of strings',
|
||||
'The section name(s) to retrieve. Can search by title (e.g., "$state", "load functions") or file path (e.g., "cli/overview"). Supports single string and array of strings',
|
||||
),
|
||||
),
|
||||
use_distilled: v.optional(
|
||||
v.pipe(
|
||||
v.boolean(),
|
||||
v.description(
|
||||
'If true (default), returns condensed distilled versions of the documentation to optimize context size. Set to false ONLY if the user asks to fetch full documentation.',
|
||||
),
|
||||
),
|
||||
true,
|
||||
),
|
||||
}),
|
||||
},
|
||||
async ({ section }) => {
|
||||
async ({ section, use_distilled = true }) => {
|
||||
let sections: string[];
|
||||
|
||||
if (Array.isArray(section)) {
|
||||
@@ -47,15 +60,47 @@ export function get_documentation(server: SvelteMcp) {
|
||||
|
||||
const available_sections = await get_sections();
|
||||
|
||||
// Sections that are never distilled, since they contain reference information where things might go missing in distillation
|
||||
const ALWAYS_FULL_SECTIONS = [
|
||||
'kit/@sveltejs-kit',
|
||||
'svelte/v5-migration-guide',
|
||||
'kit/remote-functions',
|
||||
'kit/configuration',
|
||||
'mcp/prompts',
|
||||
'svelte/compiler-warnings',
|
||||
'svelte/svelte-compiler',
|
||||
'svelte/compiler-errors',
|
||||
'svelte/svelte',
|
||||
];
|
||||
|
||||
const settled_results = await Promise.allSettled(
|
||||
sections.map(async (requested_section) => {
|
||||
const matched_section = available_sections.find(
|
||||
(s) =>
|
||||
s.title.toLowerCase() === requested_section.toLowerCase() ||
|
||||
s.slug === requested_section ||
|
||||
s.url === requested_section,
|
||||
);
|
||||
|
||||
if (matched_section) {
|
||||
// Force full documentation for specific sections
|
||||
const should_use_distilled =
|
||||
use_distilled && !ALWAYS_FULL_SECTIONS.includes(matched_section.slug);
|
||||
|
||||
console.log(
|
||||
`Fetching documentation for section "${matched_section.title}" (${should_use_distilled ? 'distilled' : 'full'})`,
|
||||
);
|
||||
if (should_use_distilled) {
|
||||
const distilled = get_distilled_content(matched_section.slug);
|
||||
if (distilled) {
|
||||
return {
|
||||
success: true,
|
||||
content: `## ${matched_section.title}\n\n${distilled}`,
|
||||
};
|
||||
}
|
||||
// If no distilled content, fall through to fetch full content
|
||||
}
|
||||
|
||||
try {
|
||||
const response = await fetch_with_timeout(matched_section.url);
|
||||
if (response.ok) {
|
||||
@@ -97,12 +142,7 @@ export function get_documentation(server: SvelteMcp) {
|
||||
let final_text = results.map((r) => r.content).join('\n\n---\n\n');
|
||||
|
||||
if (!has_any_success) {
|
||||
const formatted_sections = available_sections
|
||||
.map(
|
||||
(section) =>
|
||||
`* title: ${section.title}, use_cases: ${section.use_cases}, path: ${section.url}`,
|
||||
)
|
||||
.join('\n');
|
||||
const formatted_sections = await format_sections_list();
|
||||
|
||||
final_text += `\n\n---\n\n${SECTIONS_LIST_INTRO}\n\n${formatted_sections}\n\n${SECTIONS_LIST_OUTRO}`;
|
||||
}
|
||||
|
||||
@@ -1,23 +1,16 @@
|
||||
import type { SvelteMcp } from '../../index.js';
|
||||
import { get_sections } from '../../utils.js';
|
||||
import { format_sections_list } from '../../utils.js';
|
||||
import { SECTIONS_LIST_INTRO, SECTIONS_LIST_OUTRO } from './prompts.js';
|
||||
|
||||
export function list_sections(server: SvelteMcp) {
|
||||
server.tool(
|
||||
{
|
||||
name: 'list-sections',
|
||||
enabled: () => false,
|
||||
description:
|
||||
'Lists all available Svelte 5 and SvelteKit documentation sections in a structured format. Returns sections as a list of "* title: [section_title], use_cases: [use_cases], path: [file_path]" - you can use either the title or path when querying a specific section via the get_documentation tool. Always run list-sections first for any query related to Svelte development to discover available content.',
|
||||
'Lists all available Svelte 5 and SvelteKit documentation sections in a structured format. Each section includes a "use_cases" field that describes WHEN this documentation would be useful. You should carefully analyze the use_cases field to determine which sections are relevant for the user\'s query. The use_cases contain comma-separated keywords describing project types (e.g., "e-commerce", "blog"), features (e.g., "authentication", "forms"), components (e.g., "slider", "modal"), development stages (e.g., "deployment", "testing"), or "always" for fundamental concepts. Match these use_cases against the user\'s intent - for example, if building an e-commerce site, fetch sections with use_cases containing "e-commerce", "product listings", "shopping cart", etc. If building a slider, look for "slider", "carousel", "animation", etc. Returns sections as "* title: [section_title], use_cases: [use_cases], path: [file_path]". Always run list-sections FIRST for any Svelte query, then analyze ALL use_cases to identify relevant sections, and finally use get_documentation to fetch ALL relevant sections at once.',
|
||||
},
|
||||
async () => {
|
||||
const sections = await get_sections();
|
||||
const formatted_sections = sections
|
||||
.map(
|
||||
(section) =>
|
||||
`* title: ${section.title}, use_cases: ${section.use_cases}, path: ${section.url}`,
|
||||
)
|
||||
.join('\n');
|
||||
const formatted_sections = await format_sections_list();
|
||||
|
||||
return {
|
||||
content: [
|
||||
|
||||
@@ -1,5 +1,82 @@
|
||||
export const SECTIONS_LIST_INTRO =
|
||||
'List of available Svelte documentation sections and its inteneded uses:';
|
||||
'List of available Svelte documentation sections with their intended use cases. The "use_cases" field describes WHEN each section would be useful - analyze these carefully to determine which sections match the user\'s query:';
|
||||
|
||||
export const SECTIONS_LIST_OUTRO =
|
||||
'Use the title or path with the get-documentation tool to get more details about a specific section.';
|
||||
"Carefully analyze the use_cases field for each section to identify which documentation is relevant for the user's specific query. The use_cases contain keywords for project types, features, components, and development stages. After identifying relevant sections, use the get-documentation tool with ALL relevant section titles or paths at once (can pass multiple sections as an array).";
|
||||
|
||||
export const USE_CASES_PROMPT = `You are tasked with analyzing Svelte 5 and SvelteKit documentation pages to identify when they would be useful.
|
||||
|
||||
Your task:
|
||||
1. Read the documentation page content provided
|
||||
2. Identify the main use cases, scenarios, or queries where this documentation would be relevant
|
||||
3. Create a VERY SHORT, comma-separated list of use cases (maximum 200 characters total)
|
||||
4. Think about what a developer might be trying to build or accomplish when they need this documentation
|
||||
|
||||
Guidelines:
|
||||
- Focus on WHEN this documentation would be needed, not WHAT it contains
|
||||
- Consider specific project types (e.g., "e-commerce site", "blog", "dashboard", "social media app")
|
||||
- Consider specific features (e.g., "authentication", "forms", "data fetching", "animations")
|
||||
- Consider specific components (e.g., "slider", "modal", "dropdown", "card")
|
||||
- Consider development stages (e.g., "project setup", "deployment", "testing", "migration")
|
||||
- Use "always" for fundamental concepts that apply to virtually all Svelte projects
|
||||
- Be concise but specific
|
||||
- Use lowercase
|
||||
- Separate multiple use cases with commas
|
||||
|
||||
Examples of good use_cases:
|
||||
- "always, any svelte project, core reactivity"
|
||||
- "authentication, login systems, user management"
|
||||
- "e-commerce, product listings, shopping carts"
|
||||
- "forms, user input, data submission"
|
||||
- "deployment, production builds, hosting setup"
|
||||
- "animation, transitions, interactive ui"
|
||||
- "routing, navigation, multi-page apps"
|
||||
- "blog, content sites, markdown rendering"
|
||||
|
||||
Requirements:
|
||||
- Maximum 200 characters (including spaces and commas)
|
||||
- Lowercase only
|
||||
- Comma-separated list of use cases
|
||||
- Focus on WHEN/WHY someone would need this, not what it is
|
||||
- Be specific about project types, features, or components when applicable
|
||||
- Use "always" sparingly, only for truly universal concepts
|
||||
- Do not include quotes or special formatting in your response
|
||||
- Respond with ONLY the use cases text, no additional text
|
||||
|
||||
Here is the documentation page content to analyze:
|
||||
`;
|
||||
|
||||
export const DISTILLED_PROMPT = `You are an expert in web development, specifically Svelte 5 and SvelteKit. Your task is to condense and distill a section of the Svelte documentation that will be provided inside the "<documentation>" tag below, into a concise format while preserving the most important information.
|
||||
Shorten the text information AS MUCH AS POSSIBLE while covering key concepts.
|
||||
|
||||
Focus on:
|
||||
1. Code examples with short explanations of how they work
|
||||
2. Key concepts and APIs with their usage patterns
|
||||
3. Important gotchas and best practices
|
||||
4. Patterns that developers commonly use
|
||||
|
||||
Remove:
|
||||
1. Redundant explanations
|
||||
2. Verbose content that can be simplified
|
||||
3. Marketing language
|
||||
4. Legacy or deprecated content
|
||||
5. Anything else that is not strictly necessary
|
||||
|
||||
Keep your output in markdown format. Preserve code blocks with their language annotations.
|
||||
Maintain headings but feel free to combine or restructure sections to improve clarity.
|
||||
|
||||
Make sure all code examples use Svelte 5 runes syntax ($state, $derived, $effect, etc.)
|
||||
|
||||
Keep the following Svelte 5 syntax rules in mind whend distilling the documentation:
|
||||
* There is no colon (:) in event modifiers. You MUST use "onclick" instead of "on:click".
|
||||
* Runes do not need to be imported, they are globals.
|
||||
* $state() runes are always declared using let, never with const.
|
||||
* When passing a function to $derived, you must always use $derived.by(() => ...).
|
||||
* Error boundaries can only catch errors during component rendering and at the top level of an $effect inside the error boundary.
|
||||
* Error boundaries do not catch errors in onclick or other event handlers.
|
||||
|
||||
IMPORTANT: All code examples MUST come from the documentation verbatim, do NOT create new code examples. Do NOT modify existing code examples.
|
||||
IMPORTANT: Because of changes in Svelte 5 syntax, do not include content from your existing knowledge, you may only use knowledge from the <documentation> tag below.
|
||||
|
||||
Here is the documentation you must condense:
|
||||
`;
|
||||
|
||||
@@ -15,7 +15,7 @@ export function svelte_autofixer(server: SvelteMcp) {
|
||||
schema: v.object({
|
||||
code: v.string(),
|
||||
desired_svelte_version: v.pipe(
|
||||
v.union([v.literal(4), v.literal(5), v.literal('4'), v.literal('5')]),
|
||||
v.union([v.string(), v.number()]),
|
||||
v.description(
|
||||
'The desired svelte version...if possible read this from the package.json of the user project, otherwise use some hint from the wording (if the user asks for runes it wants version 5). Default to 5 in case of doubt.',
|
||||
),
|
||||
@@ -39,7 +39,30 @@ export function svelte_autofixer(server: SvelteMcp) {
|
||||
openWorldHint: false,
|
||||
},
|
||||
},
|
||||
async ({ code, filename: filename_or_path, desired_svelte_version }) => {
|
||||
async ({
|
||||
code,
|
||||
filename: filename_or_path,
|
||||
desired_svelte_version: desired_svelte_version_unchecked,
|
||||
}) => {
|
||||
// we validate manually because some clients don't support union in the input schema (looking at you cursor)
|
||||
const parsed_version = v.safeParse(
|
||||
v.union([v.literal(4), v.literal(5), v.literal('4'), v.literal('5')]),
|
||||
desired_svelte_version_unchecked,
|
||||
);
|
||||
if (parsed_version.success === false) {
|
||||
return {
|
||||
isError: true,
|
||||
content: [
|
||||
{
|
||||
type: 'text',
|
||||
text: `The desired_svelte_version MUST be either 4 or 5 but received "${desired_svelte_version_unchecked}"`,
|
||||
},
|
||||
],
|
||||
};
|
||||
}
|
||||
|
||||
const desired_svelte_version = parsed_version.output;
|
||||
|
||||
const content: {
|
||||
issues: string[];
|
||||
suggestions: string[];
|
||||
|
||||
@@ -1,12 +0,0 @@
|
||||
import * as v from 'valibot';
|
||||
|
||||
export const documentation_sections_schema = v.record(
|
||||
v.string(),
|
||||
v.object({
|
||||
metadata: v.object({
|
||||
title: v.string(),
|
||||
use_cases: v.optional(v.string()),
|
||||
}),
|
||||
slug: v.string(),
|
||||
}),
|
||||
);
|
||||
@@ -1,5 +1,7 @@
|
||||
import * as v from 'valibot';
|
||||
import { documentation_sections_schema } from '../mcp/schemas/index.js';
|
||||
import { documentation_sections_schema } from '../lib/schemas.js';
|
||||
import summary_data from '../use_cases.json' with { type: 'json' };
|
||||
import distilled_data from '../distilled.json' with { type: 'json' };
|
||||
|
||||
export async function fetch_with_timeout(
|
||||
url: string,
|
||||
@@ -16,16 +18,50 @@ export async function fetch_with_timeout(
|
||||
}
|
||||
}
|
||||
|
||||
const summaries = (summary_data.summaries || {}) as Record<string, string>;
|
||||
const distilled_summaries = (distilled_data.summaries || {}) as Record<string, string>;
|
||||
const full_data = (distilled_data.content || {}) as Record<string, string>;
|
||||
|
||||
export function get_distilled_content(slug: string): string | null {
|
||||
return distilled_summaries[slug] ?? null;
|
||||
}
|
||||
|
||||
export function get_cached_content(slug: string): string | null {
|
||||
return full_data[slug] ?? null;
|
||||
}
|
||||
|
||||
export async function get_sections() {
|
||||
const sections = await fetch_with_timeout(
|
||||
'https://svelte.dev/docs/experimental/sections.json',
|
||||
).then((res) => res.json());
|
||||
const validated_sections = v.safeParse(documentation_sections_schema, sections);
|
||||
if (!validated_sections.success) return [];
|
||||
return Object.entries(validated_sections.output).map(([, section]) => ({
|
||||
title: section.metadata.title,
|
||||
use_cases: section.metadata.use_cases ?? 'read document for use cases',
|
||||
slug: section.slug,
|
||||
url: `https://svelte.dev/${section.slug}/llms.txt`,
|
||||
}));
|
||||
|
||||
const mapped_sections = Object.entries(validated_sections.output).map(([, section]) => {
|
||||
const original_slug = section.slug;
|
||||
const cleaned_slug = original_slug.startsWith('docs/')
|
||||
? original_slug.slice('docs/'.length)
|
||||
: original_slug;
|
||||
|
||||
return {
|
||||
title: section.metadata.title,
|
||||
use_cases:
|
||||
section.metadata.use_cases ??
|
||||
summaries[original_slug] ??
|
||||
summaries[cleaned_slug] ??
|
||||
'use title and path to estimate use case',
|
||||
slug: cleaned_slug,
|
||||
// Use original slug in URL to ensure it still works
|
||||
url: `https://svelte.dev/${original_slug}/llms.txt`,
|
||||
};
|
||||
});
|
||||
|
||||
return mapped_sections;
|
||||
}
|
||||
|
||||
export async function format_sections_list() {
|
||||
const sections = await get_sections();
|
||||
return sections
|
||||
.map((s) => `- title: ${s.title}, use_cases: ${s.use_cases}, path: ${s.slug}`)
|
||||
.join('\n');
|
||||
}
|
||||
|
||||
@@ -36,8 +36,18 @@ export function parse(code: string, file_path: string) {
|
||||
}
|
||||
return all_scopes;
|
||||
}
|
||||
// walking the ast will also walk all the tokens if we don't remove them so we return them separately
|
||||
// we also remove the parent which as a circular reference to the ast itself (and it's not needed since we use zimmerframe to walk the ast)
|
||||
const {
|
||||
ast: { tokens, ...ast },
|
||||
} = parsed;
|
||||
|
||||
// @ts-expect-error we also have to delete it from the object or the circular reference remains
|
||||
delete parsed.ast.tokens;
|
||||
|
||||
return {
|
||||
ast: parsed.ast,
|
||||
ast,
|
||||
tokens,
|
||||
scope_manager: parsed.scopeManager as ScopeManager,
|
||||
visitor_keys: parsed.visitorKeys,
|
||||
get all_scopes() {
|
||||
|
||||
356
packages/mcp-server/src/use_cases.json
Normal file
356
packages/mcp-server/src/use_cases.json
Normal file
File diff suppressed because one or more lines are too long
33
packages/mcp-server/summaries/distilled/cli/devtools-json.md
Normal file
33
packages/mcp-server/summaries/distilled/cli/devtools-json.md
Normal file
@@ -0,0 +1,33 @@
|
||||
# devtools-json Add-on
|
||||
|
||||
Installs [`vite-plugin-devtools-json`](https://github.com/ChromeDevTools/vite-plugin-devtools-json/) - a Vite plugin that generates a Chromium DevTools settings file at `/.well-known/appspecific/com.chrome.devtools.json`. Enables [workspaces feature](https://developer.chrome.com/docs/devtools/workspaces) to edit source files directly in Chromium browsers.
|
||||
|
||||
> [!NOTE]
|
||||
> Enables feature for all dev server users with Chromium browsers. Allows browser to read/write all files in directory. Chrome's AI Assistance may send data to Google.
|
||||
|
||||
## Alternatives
|
||||
|
||||
**Disable in browser:** Visit `chrome://flags` and disable "DevTools Project Settings" and "DevTools Automatic Workspace Folders".
|
||||
|
||||
**Handle request manually:** Create `.well-known/appspecific/com.chrome.devtools.json` file or add to `handle` hook:
|
||||
|
||||
```js
|
||||
/// file: src/hooks.server.js
|
||||
import { dev } from '$app/environment';
|
||||
|
||||
export function handle({ event, resolve }) {
|
||||
if (dev && event.url.pathname === '/.well-known/appspecific/com.chrome.devtools.json') {
|
||||
return new Response(undefined, { status: 404 });
|
||||
}
|
||||
|
||||
return resolve(event);
|
||||
}
|
||||
```
|
||||
|
||||
## Usage
|
||||
|
||||
```sh
|
||||
npx sv add devtools-json
|
||||
```
|
||||
|
||||
Adds `vite-plugin-devtools-json` to Vite config.
|
||||
46
packages/mcp-server/summaries/distilled/cli/drizzle.md
Normal file
46
packages/mcp-server/summaries/distilled/cli/drizzle.md
Normal file
@@ -0,0 +1,46 @@
|
||||
# Drizzle ORM
|
||||
|
||||
TypeScript ORM with relational and SQL-like query APIs, serverless-ready.
|
||||
|
||||
## Setup
|
||||
|
||||
```sh
|
||||
npx sv add drizzle
|
||||
```
|
||||
|
||||
**Includes:**
|
||||
- Database access in SvelteKit server files
|
||||
- `.env` for credentials
|
||||
- Lucia auth compatibility
|
||||
- Optional Docker config for local database
|
||||
|
||||
## Options
|
||||
|
||||
### database
|
||||
Choose database variant:
|
||||
- `postgresql` — popular open source
|
||||
- `mysql` — popular open source
|
||||
- `sqlite` — file-based, no server needed
|
||||
|
||||
```sh
|
||||
npx sv add drizzle=database:postgresql
|
||||
```
|
||||
|
||||
### client
|
||||
SQL client (depends on database):
|
||||
- **postgresql**: `postgres.js`, `neon`
|
||||
- **mysql**: `mysql2`, `planetscale`
|
||||
- **sqlite**: `better-sqlite3`, `libsql`, `turso`
|
||||
|
||||
```sh
|
||||
npx sv add drizzle=database:postgresql+client:postgres.js
|
||||
```
|
||||
|
||||
*Note: Can swap for [other Drizzle-compatible drivers](https://orm.drizzle.team/docs/connect-overview#next-steps) after setup*
|
||||
|
||||
### docker
|
||||
Add Docker Compose config (postgresql/mysql only):
|
||||
|
||||
```sh
|
||||
npx sv add drizzle=database:postgresql+client:postgres.js+docker:yes
|
||||
```
|
||||
15
packages/mcp-server/summaries/distilled/cli/eslint.md
Normal file
15
packages/mcp-server/summaries/distilled/cli/eslint.md
Normal file
@@ -0,0 +1,15 @@
|
||||
# ESLint
|
||||
|
||||
Lints and fixes code problems.
|
||||
|
||||
## Setup
|
||||
|
||||
```sh
|
||||
npx sv add eslint
|
||||
```
|
||||
|
||||
Installs:
|
||||
- `eslint-plugin-svelte`
|
||||
- `eslint.config.js`
|
||||
- Updated `.vscode/settings.json`
|
||||
- Auto-configured for TypeScript and Prettier if present
|
||||
20
packages/mcp-server/summaries/distilled/cli/faq.md
Normal file
20
packages/mcp-server/summaries/distilled/cli/faq.md
Normal file
@@ -0,0 +1,20 @@
|
||||
# sv CLI
|
||||
|
||||
## Running sv CLI
|
||||
|
||||
```bash
|
||||
npm: npx sv create
|
||||
pnpm: pnpx sv create / pnpm dlx sv create
|
||||
bun: bunx sv create
|
||||
deno: deno run npm:sv create
|
||||
yarn: yarn dlx sv create
|
||||
```
|
||||
|
||||
## Troubleshooting
|
||||
|
||||
If `npx sv` doesn't work, package managers may prioritize local tools over registry packages. Common issues:
|
||||
- Command does nothing
|
||||
- Name collision with `runit`
|
||||
- Windows PowerShell conflict with `Set-Variable`
|
||||
|
||||
See: [GitHub issues #472](https://github.com/sveltejs/cli/issues/472), [#259](https://github.com/sveltejs/cli/issues/259), [#317](https://github.com/sveltejs/cli/issues/317)
|
||||
18
packages/mcp-server/summaries/distilled/cli/lucia.md
Normal file
18
packages/mcp-server/summaries/distilled/cli/lucia.md
Normal file
@@ -0,0 +1,18 @@
|
||||
# Lucia Auth
|
||||
|
||||
Auth setup following [Lucia auth guide](https://lucia-auth.com/).
|
||||
|
||||
## Usage
|
||||
|
||||
```sh
|
||||
npx sv add lucia
|
||||
```
|
||||
|
||||
Adds auth setup for SvelteKit + Drizzle following Lucia best practices.
|
||||
|
||||
## Options
|
||||
|
||||
**demo** - Include demo registration/login pages:
|
||||
```sh
|
||||
npx sv add lucia=demo:yes
|
||||
```
|
||||
11
packages/mcp-server/summaries/distilled/cli/mdsvex.md
Normal file
11
packages/mcp-server/summaries/distilled/cli/mdsvex.md
Normal file
@@ -0,0 +1,11 @@
|
||||
# mdsvex
|
||||
|
||||
[mdsvex](https://mdsvex.pngwn.io) is a markdown preprocessor for Svelte - allows using Svelte components in markdown and vice versa.
|
||||
|
||||
## Installation
|
||||
|
||||
```sh
|
||||
npx sv add mdsvex
|
||||
```
|
||||
|
||||
Installs and configures mdsvex in `svelte.config.js`.
|
||||
13
packages/mcp-server/summaries/distilled/cli/overview.md
Normal file
13
packages/mcp-server/summaries/distilled/cli/overview.md
Normal file
@@ -0,0 +1,13 @@
|
||||
# CLI (`sv`)
|
||||
|
||||
Toolkit for creating and maintaining Svelte applications.
|
||||
|
||||
## Usage
|
||||
|
||||
Run with `npx` (or `pnpx` for pnpm):
|
||||
|
||||
```sh
|
||||
npx sv <command> <args>
|
||||
```
|
||||
|
||||
Uses local installation if available, otherwise downloads latest version without installing.
|
||||
30
packages/mcp-server/summaries/distilled/cli/paraglide.md
Normal file
30
packages/mcp-server/summaries/distilled/cli/paraglide.md
Normal file
@@ -0,0 +1,30 @@
|
||||
# Paraglide i18n
|
||||
|
||||
Compiler-based i18n library with tree-shakable messages, small bundles, type-safety.
|
||||
|
||||
## Installation
|
||||
|
||||
```sh
|
||||
npx sv add paraglide
|
||||
```
|
||||
|
||||
## Includes
|
||||
|
||||
- Inlang project settings
|
||||
- Paraglide Vite plugin
|
||||
- SvelteKit `reroute` and `handle` hooks
|
||||
- `text-direction` and `lang` attributes in `app.html`
|
||||
- Updated `.gitignore`
|
||||
- Optional demo page
|
||||
|
||||
## Options
|
||||
|
||||
**languageTags** - IETF BCP 47 language tags:
|
||||
```sh
|
||||
npx sv add paraglide="languageTags:en,es"
|
||||
```
|
||||
|
||||
**demo** - Generate demo page:
|
||||
```sh
|
||||
npx sv add paraglide="demo:yes"
|
||||
```
|
||||
15
packages/mcp-server/summaries/distilled/cli/playwright.md
Normal file
15
packages/mcp-server/summaries/distilled/cli/playwright.md
Normal file
@@ -0,0 +1,15 @@
|
||||
# Playwright
|
||||
|
||||
Browser testing with [Playwright](https://playwright.dev).
|
||||
|
||||
## Usage
|
||||
|
||||
```sh
|
||||
npx sv add playwright
|
||||
```
|
||||
|
||||
Adds:
|
||||
- Test scripts to `package.json`
|
||||
- Playwright config file
|
||||
- Updated `.gitignore`
|
||||
- Demo test
|
||||
15
packages/mcp-server/summaries/distilled/cli/prettier.md
Normal file
15
packages/mcp-server/summaries/distilled/cli/prettier.md
Normal file
@@ -0,0 +1,15 @@
|
||||
# Prettier
|
||||
|
||||
Opinionated code formatter for Svelte projects.
|
||||
|
||||
## Usage
|
||||
|
||||
```sh
|
||||
npx sv add prettier
|
||||
```
|
||||
|
||||
## Adds
|
||||
|
||||
- `package.json` scripts
|
||||
- `.prettierignore` and `.prettierrc` config files
|
||||
- ESLint config updates (if ESLint installed)
|
||||
15
packages/mcp-server/summaries/distilled/cli/storybook.md
Normal file
15
packages/mcp-server/summaries/distilled/cli/storybook.md
Normal file
@@ -0,0 +1,15 @@
|
||||
# Storybook
|
||||
|
||||
Component workshop for Svelte/SvelteKit.
|
||||
|
||||
## Installation
|
||||
|
||||
```sh
|
||||
npx sv add storybook
|
||||
```
|
||||
|
||||
## Features
|
||||
|
||||
- Runs `npx storybook init` automatically
|
||||
- Configures either [Storybook for SvelteKit](https://storybook.js.org/docs/get-started/frameworks/sveltekit) or [Storybook for Svelte & Vite](https://storybook.js.org/docs/get-started/frameworks/svelte-vite)
|
||||
- Includes SvelteKit module mocking and automatic link handling
|
||||
37
packages/mcp-server/summaries/distilled/cli/sv-add.md
Normal file
37
packages/mcp-server/summaries/distilled/cli/sv-add.md
Normal file
@@ -0,0 +1,37 @@
|
||||
# sv add
|
||||
|
||||
Adds functionality to existing Svelte projects.
|
||||
|
||||
## Usage
|
||||
|
||||
```sh
|
||||
npx sv add
|
||||
```
|
||||
|
||||
```sh
|
||||
npx sv add [add-ons]
|
||||
```
|
||||
|
||||
Select multiple space-separated add-ons or use interactive prompt.
|
||||
|
||||
## Options
|
||||
|
||||
- `-C`, `--cwd` — path to project root
|
||||
- `--no-git-check` — skip dirty files prompt
|
||||
- `--install` — install dependencies with specified package manager
|
||||
- `--no-install` — skip dependency installation
|
||||
|
||||
## Official add-ons
|
||||
|
||||
- `devtools-json`
|
||||
- `drizzle`
|
||||
- `eslint`
|
||||
- `lucia`
|
||||
- `mdsvex`
|
||||
- `paraglide`
|
||||
- `playwright`
|
||||
- `prettier`
|
||||
- `storybook`
|
||||
- `sveltekit-adapter`
|
||||
- `tailwindcss`
|
||||
- `vitest`
|
||||
109
packages/mcp-server/summaries/distilled/cli/sv-check.md
Normal file
109
packages/mcp-server/summaries/distilled/cli/sv-check.md
Normal file
@@ -0,0 +1,109 @@
|
||||
# sv check
|
||||
|
||||
Finds errors and warnings in your project: unused CSS, accessibility hints, JS/TS compiler errors.
|
||||
|
||||
Requires Node 16+.
|
||||
|
||||
## Installation
|
||||
|
||||
```sh
|
||||
npm i -D svelte-check
|
||||
```
|
||||
|
||||
## Usage
|
||||
|
||||
```sh
|
||||
npx sv check
|
||||
```
|
||||
|
||||
## Options
|
||||
|
||||
### `--workspace <path>`
|
||||
Path to workspace. Checks all subdirectories except `node_modules` and ignored paths.
|
||||
|
||||
### `--output <format>`
|
||||
Display format: `human`, `human-verbose`, `machine`, `machine-verbose`
|
||||
|
||||
### `--watch`
|
||||
Watch mode for changes.
|
||||
|
||||
### `--preserveWatchOutput`
|
||||
Don't clear screen in watch mode.
|
||||
|
||||
### `--tsconfig <path>`
|
||||
Path to `tsconfig`/`jsconfig`. Only files matched by config's `files`/`include`/`exclude` are checked. Reports errors from TS/JS files. If not provided, searches upward from project directory.
|
||||
|
||||
### `--no-tsconfig`
|
||||
Only check Svelte files, ignore `.js`/`.ts` files.
|
||||
|
||||
### `--ignore <paths>`
|
||||
Comma-separated quoted paths relative to workspace root:
|
||||
|
||||
```sh
|
||||
npx sv check --ignore "dist,build"
|
||||
```
|
||||
|
||||
Only effective with `--no-tsconfig` for diagnostics. With `--tsconfig`, only affects watched files.
|
||||
|
||||
### `--fail-on-warnings`
|
||||
Exit with error code on warnings.
|
||||
|
||||
### `--compiler-warnings <warnings>`
|
||||
Comma-separated `code:behaviour` pairs (`ignore` or `error`):
|
||||
|
||||
```sh
|
||||
npx sv check --compiler-warnings "css_unused_selector:ignore,a11y_missing_attribute:error"
|
||||
```
|
||||
|
||||
### `--diagnostic-sources <sources>`
|
||||
Comma-separated sources (default: all active):
|
||||
- `js` (includes TypeScript)
|
||||
- `svelte`
|
||||
- `css`
|
||||
|
||||
```sh
|
||||
npx sv check --diagnostic-sources "js,svelte"
|
||||
```
|
||||
|
||||
### `--threshold <level>`
|
||||
Filter diagnostics:
|
||||
- `warning` (default) — errors and warnings
|
||||
- `error` — only errors
|
||||
|
||||
## Machine-readable output
|
||||
|
||||
`--output machine` or `machine-verbose` formats output for CI/automation.
|
||||
|
||||
Each row: columns separated by single space. First column: timestamp (ms). Second column: row type.
|
||||
|
||||
**START row:** workspace folder (quoted)
|
||||
```
|
||||
1590680325583 START "/home/user/language-tools/packages/language-server/test/plugins/typescript/testfiles"
|
||||
```
|
||||
|
||||
**machine format:** filename, line, column, message (quoted)
|
||||
```
|
||||
1590680326283 ERROR "codeactions.svelte" 1:16 "Cannot find module 'blubb' or its corresponding type declarations."
|
||||
1590680326778 WARNING "imported-file.svelte" 0:37 "Component has unused export property 'prop'. If it is for external reference only, please consider using `export const prop`"
|
||||
```
|
||||
|
||||
**machine-verbose format:** ndjson with timestamp prefix
|
||||
```
|
||||
1590680326283 {"type":"ERROR","fn":"codeaction.svelte","start":{"line":1,"character":16},"end":{"line":1,"character":23},"message":"Cannot find module 'blubb' or its corresponding type declarations.","code":2307,"source":"js"}
|
||||
1590680326778 {"type":"WARNING","filename":"imported-file.svelte","start":{"line":0,"character":37},"end":{"line":0,"character":51},"message":"Component has unused export property 'prop'. If it is for external reference only, please consider using `export const prop`","code":"unused-export-let","source":"svelte"}
|
||||
```
|
||||
|
||||
**COMPLETED row:** summary
|
||||
```
|
||||
1590680326807 COMPLETED 20 FILES 21 ERRORS 1 WARNINGS 3 FILES_WITH_PROBLEMS
|
||||
```
|
||||
|
||||
**FAILURE row:** runtime errors
|
||||
```
|
||||
1590680328921 FAILURE "Connection closed"
|
||||
```
|
||||
|
||||
## FAQ
|
||||
|
||||
**Why no option to check only specific files?**
|
||||
`svelte-check` needs the whole project for valid checks. Partial checks miss errors in unchanged files (e.g., renamed prop not updated at usage sites).
|
||||
39
packages/mcp-server/summaries/distilled/cli/sv-create.md
Normal file
39
packages/mcp-server/summaries/distilled/cli/sv-create.md
Normal file
@@ -0,0 +1,39 @@
|
||||
# sv create
|
||||
|
||||
Sets up a new SvelteKit project with optional additional functionality.
|
||||
|
||||
## Usage
|
||||
|
||||
```sh
|
||||
npx sv create [options] [path]
|
||||
```
|
||||
|
||||
## Options
|
||||
|
||||
### `--from-playground <url>`
|
||||
Create project from a [playground](/playground) URL. Downloads files, detects dependencies, and sets up complete project structure.
|
||||
|
||||
```sh
|
||||
npx sv create --from-playground="https://svelte.dev/playground/hello-world"
|
||||
```
|
||||
|
||||
### `--template <name>`
|
||||
- `minimal` — barebones scaffolding
|
||||
- `demo` — showcase app with word guessing game (works without JS)
|
||||
- `library` — Svelte library template with `svelte-package`
|
||||
|
||||
### `--types <option>`
|
||||
- `ts` — `.ts` files and `lang="ts"` in `.svelte` components
|
||||
- `jsdoc` — [JSDoc syntax](https://www.typescriptlang.org/docs/handbook/jsdoc-supported-types.html) for types
|
||||
|
||||
### `--no-types`
|
||||
Disable typechecking (not recommended)
|
||||
|
||||
### `--no-add-ons`
|
||||
Skip interactive add-ons prompt
|
||||
|
||||
### `--install <package-manager>`
|
||||
Install dependencies with: `npm`, `pnpm`, `yarn`, `bun`, or `deno`
|
||||
|
||||
### `--no-install`
|
||||
Skip dependency installation
|
||||
39
packages/mcp-server/summaries/distilled/cli/sv-migrate.md
Normal file
39
packages/mcp-server/summaries/distilled/cli/sv-migrate.md
Normal file
@@ -0,0 +1,39 @@
|
||||
# sv migrate
|
||||
|
||||
CLI tool for migrating Svelte(Kit) codebases. Delegates to [`svelte-migrate`](https://www.npmjs.com/package/svelte-migrate).
|
||||
|
||||
May add `@migration` task annotations in code for manual completion.
|
||||
|
||||
## Usage
|
||||
|
||||
```sh
|
||||
npx sv migrate
|
||||
```
|
||||
|
||||
Or specify migration:
|
||||
```sh
|
||||
npx sv migrate [migration]
|
||||
```
|
||||
|
||||
## Migrations
|
||||
|
||||
### `app-state`
|
||||
Migrates `$app/stores` → `$app/state` in `.svelte` files. [Details](/docs/kit/migrating-to-sveltekit-2#SvelteKit-2.12:-$app-stores-deprecated)
|
||||
|
||||
### `svelte-5`
|
||||
Upgrades Svelte 4 → 5, converts components to [runes](../svelte/what-are-runes) syntax. [Migration guide](../svelte/v5-migration-guide)
|
||||
|
||||
### `self-closing-tags`
|
||||
Replaces self-closing non-void elements. [PR](https://github.com/sveltejs/kit/pull/12128)
|
||||
|
||||
### `svelte-4`
|
||||
Upgrades Svelte 3 → 4. [Migration guide](../svelte/v4-migration-guide)
|
||||
|
||||
### `sveltekit-2`
|
||||
Upgrades SvelteKit 1 → 2. [Migration guide](../kit/migrating-to-sveltekit-2)
|
||||
|
||||
### `package`
|
||||
Upgrades `@sveltejs/package` v1 → v2. [PR](https://github.com/sveltejs/kit/pull/8922)
|
||||
|
||||
### `routes`
|
||||
Upgrades pre-release SvelteKit to v1 filesystem routing. [Discussion](https://github.com/sveltejs/kit/discussions/5774)
|
||||
@@ -0,0 +1,24 @@
|
||||
# SvelteKit Adapters
|
||||
|
||||
Adapters enable deployment to various platforms.
|
||||
|
||||
## Usage
|
||||
|
||||
```sh
|
||||
npx sv add sveltekit-adapter
|
||||
```
|
||||
|
||||
Installs and configures chosen adapter in `svelte.config.js`.
|
||||
|
||||
## Adapter Options
|
||||
|
||||
- `auto` — [`@sveltejs/adapter-auto`](/docs/kit/adapter-auto) - auto-selects adapter, less configurable
|
||||
- `node` — [`@sveltejs/adapter-node`](/docs/kit/adapter-node) - standalone Node server
|
||||
- `static` — [`@sveltejs/adapter-static`](/docs/kit/adapter-static) - static site generator (SSG)
|
||||
- `vercel` — [`@sveltejs/adapter-vercel`](/docs/kit/adapter-vercel) - Vercel deployment
|
||||
- `cloudflare` — [`@sveltejs/adapter-cloudflare`](/docs/kit/adapter-cloudflare) - Cloudflare deployment
|
||||
- `netlify` — [`@sveltejs/adapter-netlify`](/docs/kit/adapter-netlify) - Netlify deployment
|
||||
|
||||
```sh
|
||||
npx sv add sveltekit-adapter=adapter:node
|
||||
```
|
||||
26
packages/mcp-server/summaries/distilled/cli/tailwind.md
Normal file
26
packages/mcp-server/summaries/distilled/cli/tailwind.md
Normal file
@@ -0,0 +1,26 @@
|
||||
# Tailwind CSS
|
||||
|
||||
## Setup
|
||||
|
||||
```sh
|
||||
npx sv add tailwindcss
|
||||
```
|
||||
|
||||
## What's Installed
|
||||
|
||||
- Tailwind config following SvelteKit guide
|
||||
- Tailwind Vite plugin
|
||||
- Updated `app.css` and `+layout.svelte` (SvelteKit) or `App.svelte` (Vite)
|
||||
- Prettier integration (if installed)
|
||||
|
||||
## Options
|
||||
|
||||
Add plugins via CLI:
|
||||
|
||||
```sh
|
||||
npx sv add tailwindcss="plugins:typography"
|
||||
```
|
||||
|
||||
Available plugins:
|
||||
- `typography` — [@tailwindcss/typography](https://github.com/tailwindlabs/tailwindcss-typography)
|
||||
- `forms` — [@tailwindcss/forms](https://github.com/tailwindlabs/tailwindcss-forms)
|
||||
11
packages/mcp-server/summaries/distilled/cli/vitest.md
Normal file
11
packages/mcp-server/summaries/distilled/cli/vitest.md
Normal file
@@ -0,0 +1,11 @@
|
||||
# Vitest
|
||||
|
||||
Vite-native testing framework for SvelteKit.
|
||||
|
||||
## Setup
|
||||
|
||||
```sh
|
||||
npx sv add vitest
|
||||
```
|
||||
|
||||
Installs packages, adds scripts to `package.json`, configures client/server-aware Svelte testing in Vite config, and includes demo tests.
|
||||
@@ -0,0 +1,33 @@
|
||||
# $app/environment
|
||||
|
||||
```js
|
||||
import { browser, building, dev, version } from '$app/environment';
|
||||
```
|
||||
|
||||
## browser
|
||||
`true` if app is running in the browser.
|
||||
|
||||
```dts
|
||||
const browser: boolean;
|
||||
```
|
||||
|
||||
## building
|
||||
`true` during the build step and prerendering.
|
||||
|
||||
```dts
|
||||
const building: boolean;
|
||||
```
|
||||
|
||||
## dev
|
||||
Whether dev server is running. Not guaranteed to match `NODE_ENV` or `MODE`.
|
||||
|
||||
```dts
|
||||
const dev: boolean;
|
||||
```
|
||||
|
||||
## version
|
||||
The value of `config.kit.version.name`.
|
||||
|
||||
```dts
|
||||
const version: string;
|
||||
```
|
||||
75
packages/mcp-server/summaries/distilled/kit/$app-forms.md
Normal file
75
packages/mcp-server/summaries/distilled/kit/$app-forms.md
Normal file
@@ -0,0 +1,75 @@
|
||||
# $app/forms
|
||||
|
||||
```js
|
||||
import { applyAction, deserialize, enhance } from '$app/forms';
|
||||
```
|
||||
|
||||
## applyAction
|
||||
|
||||
Updates `form` property and `page.status` of current page with given data. Redirects to nearest error page on error.
|
||||
|
||||
```dts
|
||||
function applyAction<
|
||||
Success extends Record<string, unknown> | undefined,
|
||||
Failure extends Record<string, unknown> | undefined
|
||||
>(
|
||||
result: import('@sveltejs/kit').ActionResult<Success, Failure>
|
||||
): Promise<void>;
|
||||
```
|
||||
|
||||
## deserialize
|
||||
|
||||
Deserializes form submission response.
|
||||
|
||||
```js
|
||||
// @errors: 7031
|
||||
import { deserialize } from '$app/forms';
|
||||
|
||||
async function handleSubmit(event) {
|
||||
const response = await fetch('/form?/action', {
|
||||
method: 'POST',
|
||||
body: new FormData(event.target)
|
||||
});
|
||||
|
||||
const result = deserialize(await response.text());
|
||||
// ...
|
||||
}
|
||||
```
|
||||
|
||||
```dts
|
||||
function deserialize<
|
||||
Success extends Record<string, unknown> | undefined,
|
||||
Failure extends Record<string, unknown> | undefined
|
||||
>(
|
||||
result: string
|
||||
): import('@sveltejs/kit').ActionResult<Success, Failure>;
|
||||
```
|
||||
|
||||
## enhance
|
||||
|
||||
Progressive enhancement for `<form>` elements.
|
||||
|
||||
**`submit` function**: Called on submission with FormData and `action`. Call `cancel` to prevent submission. Use abort `controller` to cancel if another submission starts. Return a function to handle server response, or return nothing for default behavior.
|
||||
|
||||
**Default behavior**:
|
||||
- Updates `form` prop if action is on same page
|
||||
- Updates `page.status`
|
||||
- Resets form and invalidates all data on successful submission (no redirect)
|
||||
- Redirects on redirect response
|
||||
- Redirects to error page on unexpected error
|
||||
|
||||
**Custom callback**: Call `update` for default behavior with options:
|
||||
- `reset: false` - don't reset form values after success
|
||||
- `invalidateAll: false` - don't call `invalidateAll` after submission
|
||||
|
||||
```dts
|
||||
function enhance<
|
||||
Success extends Record<string, unknown> | undefined,
|
||||
Failure extends Record<string, unknown> | undefined
|
||||
>(
|
||||
form_element: HTMLFormElement,
|
||||
submit?: import('@sveltejs/kit').SubmitFunction<Success, Failure>
|
||||
): {
|
||||
destroy(): void;
|
||||
};
|
||||
```
|
||||
160
packages/mcp-server/summaries/distilled/kit/$app-navigation.md
Normal file
160
packages/mcp-server/summaries/distilled/kit/$app-navigation.md
Normal file
@@ -0,0 +1,160 @@
|
||||
# $app/navigation
|
||||
|
||||
```js
|
||||
import {
|
||||
afterNavigate,
|
||||
beforeNavigate,
|
||||
disableScrollHandling,
|
||||
goto,
|
||||
invalidate,
|
||||
invalidateAll,
|
||||
onNavigate,
|
||||
preloadCode,
|
||||
preloadData,
|
||||
pushState,
|
||||
refreshAll,
|
||||
replaceState
|
||||
} from '$app/navigation';
|
||||
```
|
||||
|
||||
## afterNavigate
|
||||
|
||||
Runs callback when component mounts and on every navigation. Must be called during component initialization. Active while component is mounted.
|
||||
|
||||
```dts
|
||||
function afterNavigate(
|
||||
callback: (navigation: import('@sveltejs/kit').AfterNavigate) => void
|
||||
): void;
|
||||
```
|
||||
|
||||
## beforeNavigate
|
||||
|
||||
Intercepts navigation before it happens (links, `goto()`, browser back/forward). Call `cancel()` to prevent navigation. For `'leave'` navigations (closing tab/navigating away), `cancel()` triggers native browser confirmation dialog.
|
||||
|
||||
- `navigation.to.route.id` is `null` for non-SvelteKit routes
|
||||
- `navigation.willUnload` is `true` for `'leave'` navigations and `'link'` navigations where `navigation.to.route === null`
|
||||
|
||||
Must be called during component initialization. Active while component is mounted.
|
||||
|
||||
```dts
|
||||
function beforeNavigate(
|
||||
callback: (navigation: import('@sveltejs/kit').BeforeNavigate) => void
|
||||
): void;
|
||||
```
|
||||
|
||||
## disableScrollHandling
|
||||
|
||||
Disables SvelteKit's built-in scroll handling when called during page update (in `onMount`, `afterNavigate`, or actions). Discouraged as it breaks user expectations.
|
||||
|
||||
```dts
|
||||
function disableScrollHandling(): void;
|
||||
```
|
||||
|
||||
## goto
|
||||
|
||||
Navigate programmatically. Returns Promise that resolves on navigation completion. For external URLs, use `window.location = url` instead.
|
||||
|
||||
```dts
|
||||
function goto(
|
||||
url: string | URL,
|
||||
opts?: {
|
||||
replaceState?: boolean | undefined;
|
||||
noScroll?: boolean | undefined;
|
||||
keepFocus?: boolean | undefined;
|
||||
invalidateAll?: boolean | undefined;
|
||||
invalidate?: (string | URL | ((url: URL) => boolean))[] | undefined;
|
||||
state?: App.PageState | undefined;
|
||||
}
|
||||
): Promise<void>;
|
||||
```
|
||||
|
||||
## invalidate
|
||||
|
||||
Re-runs `load` functions that depend on the URL (via `fetch` or `depends`). Returns Promise that resolves when page updates.
|
||||
|
||||
- String/URL must match exactly what was passed to `fetch`/`depends` (including query params)
|
||||
- Custom identifiers: use format `[a-z]+:` (e.g. `custom:state`)
|
||||
- Function predicate receives full URL, re-runs if returns `true`
|
||||
|
||||
```ts
|
||||
// Match '/path' regardless of query parameters
|
||||
import { invalidate } from '$app/navigation';
|
||||
|
||||
invalidate((url) => url.pathname === '/path');
|
||||
```
|
||||
|
||||
```dts
|
||||
function invalidate(
|
||||
resource: string | URL | ((url: URL) => boolean)
|
||||
): Promise<void>;
|
||||
```
|
||||
|
||||
## invalidateAll
|
||||
|
||||
Re-runs all `load` functions for current page. Returns Promise that resolves when page updates.
|
||||
|
||||
```dts
|
||||
function invalidateAll(): Promise<void>;
|
||||
```
|
||||
|
||||
## onNavigate
|
||||
|
||||
Runs callback immediately before navigation (except full-page navigations). Return Promise to delay navigation completion (useful for `document.startViewTransition`). Avoid slow promises as navigation appears stalled.
|
||||
|
||||
Returning a function (or Promise resolving to function) calls it after DOM updates.
|
||||
|
||||
Must be called during component initialization. Active while component is mounted.
|
||||
|
||||
```dts
|
||||
function onNavigate(
|
||||
callback: (navigation: import('@sveltejs/kit').OnNavigate) =>
|
||||
MaybePromise<(() => void) | void>
|
||||
): void;
|
||||
```
|
||||
|
||||
## preloadCode
|
||||
|
||||
Imports code for routes not yet fetched. Specify routes by pathname: `/about` or `/blog/*`. Doesn't call `load` functions. Returns Promise resolving when modules imported.
|
||||
|
||||
```dts
|
||||
function preloadCode(pathname: string): Promise<void>;
|
||||
```
|
||||
|
||||
## preloadData
|
||||
|
||||
Preloads page: imports code and calls `load` functions. Same as hovering/tapping `<a>` with `data-sveltekit-preload-data`. Makes navigation instantaneous if next navigation is to `href`. Returns Promise with `load` results.
|
||||
|
||||
```dts
|
||||
function preloadData(href: string): Promise<
|
||||
| { type: 'loaded'; status: number; data: Record<string, any>; }
|
||||
| { type: 'redirect'; location: string; }
|
||||
>;
|
||||
```
|
||||
|
||||
## pushState
|
||||
|
||||
Creates new history entry with given `page.state`. Pass `''` for current URL. Used for shallow routing.
|
||||
|
||||
```dts
|
||||
function pushState(url: string | URL, state: App.PageState): void;
|
||||
```
|
||||
|
||||
## refreshAll
|
||||
|
||||
Refreshes all active remote functions and re-runs `load` functions (unless disabled). Returns Promise resolving when page updates.
|
||||
|
||||
```dts
|
||||
function refreshAll({
|
||||
includeLoadFunctions
|
||||
}?: {
|
||||
includeLoadFunctions?: boolean;
|
||||
}): Promise<void>;
|
||||
```
|
||||
|
||||
## replaceState
|
||||
|
||||
Replaces current history entry with given `page.state`. Pass `''` for current URL. Used for shallow routing.
|
||||
|
||||
```dts
|
||||
function replaceState(url: string | URL, state: App.PageState): void;
|
||||
```
|
||||
54
packages/mcp-server/summaries/distilled/kit/$app-paths.md
Normal file
54
packages/mcp-server/summaries/distilled/kit/$app-paths.md
Normal file
@@ -0,0 +1,54 @@
|
||||
# $app/paths
|
||||
|
||||
```js
|
||||
import { asset, assets, base, resolve, resolveRoute } from '$app/paths';
|
||||
```
|
||||
|
||||
## asset
|
||||
|
||||
Resolve URL of an asset in `static` directory by prefixing with `config.kit.paths.assets` or base path.
|
||||
|
||||
During SSR, base path is relative and depends on current page.
|
||||
|
||||
```svelte
|
||||
<script>
|
||||
import { asset } from '$app/paths';
|
||||
</script>
|
||||
|
||||
<img alt="a potato" src={asset('/potato.jpg')} />
|
||||
```
|
||||
|
||||
```dts
|
||||
function asset(file: Asset): string;
|
||||
```
|
||||
|
||||
## resolve
|
||||
|
||||
Resolve pathname by prefixing with base path, or resolve route ID by populating dynamic segments with parameters.
|
||||
|
||||
During SSR, base path is relative and depends on current page.
|
||||
|
||||
```js
|
||||
// @errors: 7031
|
||||
import { resolve } from '$app/paths';
|
||||
|
||||
// using a pathname
|
||||
const resolved = resolve(`/blog/hello-world`);
|
||||
|
||||
// using a route ID plus parameters
|
||||
const resolved = resolve('/blog/[slug]', {
|
||||
slug: 'hello-world'
|
||||
});
|
||||
```
|
||||
|
||||
```dts
|
||||
function resolve<T extends RouteId | Pathname>(
|
||||
...args: ResolveArgs<T>
|
||||
): ResolvedPathname;
|
||||
```
|
||||
|
||||
## Deprecated
|
||||
|
||||
- **assets**: Use `asset(...)` instead. Absolute path matching `config.kit.paths.assets`.
|
||||
- **base**: Use `resolve(...)` instead. String matching `config.kit.paths.base`.
|
||||
- **resolveRoute**: Use `resolve(...)` instead.
|
||||
148
packages/mcp-server/summaries/distilled/kit/$app-server.md
Normal file
148
packages/mcp-server/summaries/distilled/kit/$app-server.md
Normal file
@@ -0,0 +1,148 @@
|
||||
# $app/server
|
||||
|
||||
```js
|
||||
import {
|
||||
command,
|
||||
form,
|
||||
getRequestEvent,
|
||||
prerender,
|
||||
query,
|
||||
read
|
||||
} from '$app/server';
|
||||
```
|
||||
|
||||
## command
|
||||
*Available since 2.27*
|
||||
|
||||
Creates a remote command. When called from browser, invokes function on server via `fetch`.
|
||||
|
||||
```dts
|
||||
function command<Output>(fn: () => Output): RemoteCommand<void, Output>;
|
||||
|
||||
function command<Input, Output>(
|
||||
validate: 'unchecked',
|
||||
fn: (arg: Input) => Output
|
||||
): RemoteCommand<Input, Output>;
|
||||
|
||||
function command<Schema extends StandardSchemaV1, Output>(
|
||||
validate: Schema,
|
||||
fn: (arg: StandardSchemaV1.InferOutput<Schema>) => Output
|
||||
): RemoteCommand<StandardSchemaV1.InferInput<Schema>, Output>;
|
||||
```
|
||||
|
||||
See [Remote functions](/docs/kit/remote-functions#command).
|
||||
|
||||
## form
|
||||
*Available since 2.27*
|
||||
|
||||
Creates a form object that can be spread onto a `<form>` element.
|
||||
|
||||
```dts
|
||||
function form<Output>(
|
||||
fn: (invalid: Invalid<void>) => MaybePromise<Output>
|
||||
): RemoteForm<void, Output>;
|
||||
|
||||
function form<Input extends RemoteFormInput, Output>(
|
||||
validate: 'unchecked',
|
||||
fn: (data: Input, invalid: Invalid<Input>) => MaybePromise<Output>
|
||||
): RemoteForm<Input, Output>;
|
||||
|
||||
function form<Schema extends StandardSchemaV1<RemoteFormInput, Record<string, any>>, Output>(
|
||||
validate: Schema,
|
||||
fn: (data: StandardSchemaV1.InferOutput<Schema>, invalid: Invalid<StandardSchemaV1.InferOutput<Schema>>) => MaybePromise<Output>
|
||||
): RemoteForm<StandardSchemaV1.InferInput<Schema>, Output>;
|
||||
```
|
||||
|
||||
See [Remote functions](/docs/kit/remote-functions#form).
|
||||
|
||||
## getRequestEvent
|
||||
*Available since 2.20.0*
|
||||
|
||||
Returns current `RequestEvent`. Use in server hooks, server `load` functions, actions, and endpoints.
|
||||
|
||||
**Important:** In environments without `AsyncLocalStorage`, must be called synchronously (not after `await`).
|
||||
|
||||
```dts
|
||||
function getRequestEvent(): RequestEvent;
|
||||
```
|
||||
|
||||
## prerender
|
||||
*Available since 2.27*
|
||||
|
||||
Creates a remote prerender function. When called from browser, invokes function on server via `fetch`.
|
||||
|
||||
```dts
|
||||
function prerender<Output>(
|
||||
fn: () => MaybePromise<Output>,
|
||||
options?: { inputs?: RemotePrerenderInputsGenerator<void>; dynamic?: boolean; }
|
||||
): RemotePrerenderFunction<void, Output>;
|
||||
|
||||
function prerender<Input, Output>(
|
||||
validate: 'unchecked',
|
||||
fn: (arg: Input) => MaybePromise<Output>,
|
||||
options?: { inputs?: RemotePrerenderInputsGenerator<Input>; dynamic?: boolean; }
|
||||
): RemotePrerenderFunction<Input, Output>;
|
||||
|
||||
function prerender<Schema extends StandardSchemaV1, Output>(
|
||||
schema: Schema,
|
||||
fn: (arg: StandardSchemaV1.InferOutput<Schema>) => MaybePromise<Output>,
|
||||
options?: { inputs?: RemotePrerenderInputsGenerator<StandardSchemaV1.InferInput<Schema>>; dynamic?: boolean; }
|
||||
): RemotePrerenderFunction<StandardSchemaV1.InferInput<Schema>, Output>;
|
||||
```
|
||||
|
||||
See [Remote functions](/docs/kit/remote-functions#prerender).
|
||||
|
||||
## query
|
||||
*Available since 2.27*
|
||||
|
||||
Creates a remote query. When called from browser, invokes function on server via `fetch`.
|
||||
|
||||
```dts
|
||||
function query<Output>(fn: () => MaybePromise<Output>): RemoteQueryFunction<void, Output>;
|
||||
|
||||
function query<Input, Output>(
|
||||
validate: 'unchecked',
|
||||
fn: (arg: Input) => MaybePromise<Output>
|
||||
): RemoteQueryFunction<Input, Output>;
|
||||
|
||||
function query<Schema extends StandardSchemaV1, Output>(
|
||||
schema: Schema,
|
||||
fn: (arg: StandardSchemaV1.InferOutput<Schema>) => MaybePromise<Output>
|
||||
): RemoteQueryFunction<StandardSchemaV1.InferInput<Schema>, Output>;
|
||||
```
|
||||
|
||||
### query.batch
|
||||
*Available since 2.35*
|
||||
|
||||
Collects multiple calls and executes them in a single request.
|
||||
|
||||
```dts
|
||||
function batch<Input, Output>(
|
||||
validate: 'unchecked',
|
||||
fn: (args: Input[]) => MaybePromise<(arg: Input, idx: number) => Output>
|
||||
): RemoteQueryFunction<Input, Output>;
|
||||
|
||||
function batch<Schema extends StandardSchemaV1, Output>(
|
||||
schema: Schema,
|
||||
fn: (args: StandardSchemaV1.InferOutput<Schema>[]) => MaybePromise<(arg: StandardSchemaV1.InferOutput<Schema>, idx: number) => Output>
|
||||
): RemoteQueryFunction<StandardSchemaV1.InferInput<Schema>, Output>;
|
||||
```
|
||||
|
||||
See [Remote functions](/docs/kit/remote-functions#query) and [query.batch](/docs/kit/remote-functions#query.batch).
|
||||
|
||||
## read
|
||||
*Available since 2.4.0*
|
||||
|
||||
Reads contents of an imported asset from filesystem.
|
||||
|
||||
```js
|
||||
import { read } from '$app/server';
|
||||
import somefile from './somefile.txt';
|
||||
|
||||
const asset = read(somefile);
|
||||
const text = await asset.text();
|
||||
```
|
||||
|
||||
```dts
|
||||
function read(asset: string): Response;
|
||||
```
|
||||
78
packages/mcp-server/summaries/distilled/kit/$app-state.md
Normal file
78
packages/mcp-server/summaries/distilled/kit/$app-state.md
Normal file
@@ -0,0 +1,78 @@
|
||||
# $app/state
|
||||
|
||||
Three read-only state objects for SvelteKit apps. Added in 2.12 (use `$app/stores` for earlier versions).
|
||||
|
||||
```js
|
||||
import { navigating, page, updated } from '$app/state';
|
||||
```
|
||||
|
||||
## navigating
|
||||
|
||||
Read-only object representing in-progress navigation. `null` when no navigation occurring or during SSR.
|
||||
|
||||
```dts
|
||||
const navigating:
|
||||
| import('@sveltejs/kit').Navigation
|
||||
| {
|
||||
from: null;
|
||||
to: null;
|
||||
type: null;
|
||||
willUnload: null;
|
||||
delta: null;
|
||||
complete: null;
|
||||
};
|
||||
```
|
||||
|
||||
Properties: `from`, `to`, `type`, and `delta` (if `type === 'popstate'`).
|
||||
|
||||
## page
|
||||
|
||||
Read-only reactive object with current page info:
|
||||
- Combined `data` from all pages/layouts
|
||||
- Current `form` prop value
|
||||
- Page state from `goto`, `pushState`, `replaceState`
|
||||
- Metadata: URL, route, params, error status
|
||||
|
||||
```svelte
|
||||
<!--- file: +layout.svelte --->
|
||||
<script>
|
||||
import { page } from '$app/state';
|
||||
</script>
|
||||
|
||||
<p>Currently at {page.url.pathname}</p>
|
||||
|
||||
{#if page.error}
|
||||
<span class="red">Problem detected</span>
|
||||
{:else}
|
||||
<span class="small">All systems operational</span>
|
||||
{/if}
|
||||
```
|
||||
|
||||
**Important:** Changes only work with runes, not legacy reactivity:
|
||||
|
||||
```svelte
|
||||
<!--- file: +page.svelte --->
|
||||
<script>
|
||||
import { page } from '$app/state';
|
||||
const id = $derived(page.params.id); // ✓ Updates correctly
|
||||
$: badId = page.params.id; // ✗ Never updates after initial load
|
||||
</script>
|
||||
```
|
||||
|
||||
Server: read only during rendering (not in `load` functions).
|
||||
Browser: read anytime.
|
||||
|
||||
```dts
|
||||
const page: import('@sveltejs/kit').Page;
|
||||
```
|
||||
|
||||
## updated
|
||||
|
||||
Read-only reactive value, initially `false`. Becomes `true` when new app version detected (if `version.pollInterval` configured). `updated.check()` forces immediate check.
|
||||
|
||||
```dts
|
||||
const updated: {
|
||||
get current(): boolean;
|
||||
check(): Promise<boolean>;
|
||||
};
|
||||
```
|
||||
63
packages/mcp-server/summaries/distilled/kit/$app-stores.md
Normal file
63
packages/mcp-server/summaries/distilled/kit/$app-stores.md
Normal file
@@ -0,0 +1,63 @@
|
||||
# $app/stores
|
||||
|
||||
**DEPRECATED**: Use `$app/state` instead (SvelteKit 2.12+). Store-based equivalents for legacy support.
|
||||
|
||||
```js
|
||||
import { getStores, navigating, page, updated } from '$app/stores';
|
||||
```
|
||||
|
||||
## getStores
|
||||
|
||||
```dts
|
||||
function getStores(): {
|
||||
page: typeof page;
|
||||
navigating: typeof navigating;
|
||||
updated: typeof updated;
|
||||
};
|
||||
```
|
||||
|
||||
## navigating
|
||||
|
||||
**Readable store** for navigation state.
|
||||
|
||||
- **During navigation**: `Navigation` object with `from`, `to`, `type`, and `delta` (if `type === 'popstate'`)
|
||||
- **When idle**: `null`
|
||||
|
||||
**Server**: Subscribe only during component initialization
|
||||
**Browser**: Subscribe anytime
|
||||
|
||||
```dts
|
||||
const navigating: import('svelte/store').Readable<
|
||||
import('@sveltejs/kit').Navigation | null
|
||||
>;
|
||||
```
|
||||
|
||||
## page
|
||||
|
||||
**Readable store** containing page data.
|
||||
|
||||
**Server**: Subscribe only during component initialization
|
||||
**Browser**: Subscribe anytime
|
||||
|
||||
```dts
|
||||
const page: import('svelte/store').Readable<
|
||||
import('@sveltejs/kit').Page
|
||||
>;
|
||||
```
|
||||
|
||||
## updated
|
||||
|
||||
**Readable store** for app version updates.
|
||||
|
||||
- Initial value: `false`
|
||||
- Becomes `true` when new version detected (if `version.pollInterval` configured)
|
||||
- `updated.check()`: Force immediate version check
|
||||
|
||||
**Server**: Subscribe only during component initialization
|
||||
**Browser**: Subscribe anytime
|
||||
|
||||
```dts
|
||||
const updated: import('svelte/store').Readable<boolean> & {
|
||||
check(): Promise<boolean>;
|
||||
};
|
||||
```
|
||||
59
packages/mcp-server/summaries/distilled/kit/$app-types.md
Normal file
59
packages/mcp-server/summaries/distilled/kit/$app-types.md
Normal file
@@ -0,0 +1,59 @@
|
||||
# $app/types
|
||||
|
||||
Generated types for routes in your app (available since SvelteKit 2.26).
|
||||
|
||||
```js
|
||||
import type { RouteId, RouteParams, LayoutParams } from '$app/types';
|
||||
```
|
||||
|
||||
## Asset
|
||||
|
||||
Union of all filenames in `static` directory + wildcard for imported asset paths.
|
||||
|
||||
```dts
|
||||
type Asset = '/favicon.png' | '/robots.txt' | (string & {});
|
||||
```
|
||||
|
||||
## RouteId
|
||||
|
||||
Union of all route IDs. Used for `page.route.id` and `event.route.id`.
|
||||
|
||||
```dts
|
||||
type RouteId = '/' | '/my-route' | '/my-other-route/[param]';
|
||||
```
|
||||
|
||||
## Pathname
|
||||
|
||||
Union of all valid pathnames.
|
||||
|
||||
```dts
|
||||
type Pathname = '/' | '/my-route' | `/my-other-route/${string}` & {};
|
||||
```
|
||||
|
||||
## ResolvedPathname
|
||||
|
||||
Like `Pathname` but possibly prefixed with base path. Used for `page.url.pathname`.
|
||||
|
||||
```dts
|
||||
type ResolvedPathname = `${'' | `/${string}`}/` | `${'' | `/${string}`}/my-route` | `${'' | `/${string}`}/my-other-route/${string}` | {};
|
||||
```
|
||||
|
||||
## RouteParams
|
||||
|
||||
Get parameters for a route.
|
||||
|
||||
```ts
|
||||
type BlogParams = RouteParams<'/blog/[slug]'>; // { slug: string }
|
||||
```
|
||||
|
||||
```dts
|
||||
type RouteParams<T extends RouteId> = { /* generated */ } | Record<string, never>;
|
||||
```
|
||||
|
||||
## LayoutParams
|
||||
|
||||
Get parameters for a layout, including optional parameters from child routes.
|
||||
|
||||
```dts
|
||||
type RouteParams<T extends RouteId> = { /* generated */ } | Record<string, never>;
|
||||
```
|
||||
@@ -0,0 +1,15 @@
|
||||
# $env/dynamic/private
|
||||
|
||||
Access to runtime environment variables from the platform (e.g., `process.env` in adapter-node).
|
||||
|
||||
**Rules:**
|
||||
- Only includes variables that do NOT start with `config.kit.env.publicPrefix`
|
||||
- Only includes variables that DO start with `config.kit.env.privatePrefix` (if configured)
|
||||
- **Cannot be imported in client-side code**
|
||||
|
||||
```ts
|
||||
import { env } from '$env/dynamic/private';
|
||||
console.log(env.DEPLOYMENT_SPECIFIC_VARIABLE);
|
||||
```
|
||||
|
||||
**Note:** In dev, always includes `.env` variables. In prod, depends on adapter.
|
||||
@@ -0,0 +1,13 @@
|
||||
# $env/dynamic/public
|
||||
|
||||
Runtime access to public environment variables (prefixed with `PUBLIC_` by default via `config.kit.env.publicPrefix`).
|
||||
|
||||
**Key differences:**
|
||||
- Only includes variables with public prefix (safe for client-side)
|
||||
- All public dynamic env vars sent server→client (increases network payload)
|
||||
- **Prefer `$env/static/public`** when possible to avoid larger requests
|
||||
|
||||
```ts
|
||||
import { env } from '$env/dynamic/public';
|
||||
console.log(env.PUBLIC_DEPLOYMENT_SPECIFIC_VARIABLE);
|
||||
```
|
||||
@@ -0,0 +1,29 @@
|
||||
# $env/static/private
|
||||
|
||||
Server-only module for private environment variables loaded from `.env` files and `process.env`.
|
||||
|
||||
**Key characteristics:**
|
||||
- Cannot be imported in client-side code
|
||||
- Includes variables that do NOT begin with `config.kit.env.publicPrefix`
|
||||
- Optionally filtered by `config.kit.env.privatePrefix`
|
||||
- Values are **statically injected at build time** (enables dead code elimination)
|
||||
|
||||
## Usage
|
||||
|
||||
```ts
|
||||
import { API_KEY } from '$env/static/private';
|
||||
```
|
||||
|
||||
## Best practices
|
||||
|
||||
Declare all referenced env vars (even if empty) in `.env`:
|
||||
|
||||
```
|
||||
MY_FEATURE_FLAG=""
|
||||
```
|
||||
|
||||
Override from command line:
|
||||
|
||||
```sh
|
||||
MY_FEATURE_FLAG="enabled" npm run dev
|
||||
```
|
||||
@@ -0,0 +1,7 @@
|
||||
# $env/static/public
|
||||
|
||||
Environment variables with `PUBLIC_` prefix (configurable via `config.kit.env.publicPrefix`). Safe for client-side code. Values replaced at build time.
|
||||
|
||||
```ts
|
||||
import { PUBLIC_BASE_URL } from '$env/static/public';
|
||||
```
|
||||
17
packages/mcp-server/summaries/distilled/kit/$lib.md
Normal file
17
packages/mcp-server/summaries/distilled/kit/$lib.md
Normal file
@@ -0,0 +1,17 @@
|
||||
# $lib Import Alias
|
||||
|
||||
SvelteKit provides `$lib` alias for importing from `src/lib`. Configure via [config file](configuration#files).
|
||||
|
||||
```svelte
|
||||
<!--- file: src/lib/Component.svelte --->
|
||||
A reusable component
|
||||
```
|
||||
|
||||
```svelte
|
||||
<!--- file: src/routes/+page.svelte --->
|
||||
<script>
|
||||
import Component from '$lib/Component.svelte';
|
||||
</script>
|
||||
|
||||
<Component />
|
||||
```
|
||||
@@ -0,0 +1,49 @@
|
||||
# $service-worker
|
||||
|
||||
```js
|
||||
import { base, build, files, prerendered, version } from '$service-worker';
|
||||
```
|
||||
|
||||
Only available to [service workers](/docs/kit/service-workers).
|
||||
|
||||
## base
|
||||
|
||||
```ts
|
||||
const base: string;
|
||||
```
|
||||
|
||||
Base path of deployment. Equivalent to `config.kit.paths.base`, calculated from `location.pathname`. Works correctly in subdirectories.
|
||||
|
||||
Note: No `assets` export since service workers can't be used if `config.kit.paths.assets` is specified.
|
||||
|
||||
## build
|
||||
|
||||
```ts
|
||||
const build: string[];
|
||||
```
|
||||
|
||||
Array of URLs for Vite-generated files. Use with `cache.addAll(build)`. Empty during development.
|
||||
|
||||
## files
|
||||
|
||||
```ts
|
||||
const files: string[];
|
||||
```
|
||||
|
||||
Array of URLs from static directory (`config.kit.files.assets`). Customize via [`config.kit.serviceWorker.files`](/docs/kit/configuration#serviceWorker).
|
||||
|
||||
## prerendered
|
||||
|
||||
```ts
|
||||
const prerendered: string[];
|
||||
```
|
||||
|
||||
Array of prerendered page/endpoint pathnames. Empty during development.
|
||||
|
||||
## version
|
||||
|
||||
```ts
|
||||
const version: string;
|
||||
```
|
||||
|
||||
From [`config.kit.version`](/docs/kit/configuration#version). Use for unique cache names to invalidate old caches on deployment.
|
||||
@@ -0,0 +1,81 @@
|
||||
# sequence
|
||||
|
||||
Helper for chaining multiple `handle` functions in middleware-like manner.
|
||||
|
||||
```js
|
||||
import { sequence } from '@sveltejs/kit/hooks';
|
||||
```
|
||||
|
||||
## Behavior
|
||||
|
||||
- `transformPageChunk`: applied in **reverse order**, merged
|
||||
- `preload`: applied in **forward order**, first wins (subsequent calls skipped)
|
||||
- `filterSerializedResponseHeaders`: same as `preload` (first wins)
|
||||
|
||||
## Example
|
||||
|
||||
```js
|
||||
/// file: src/hooks.server.js
|
||||
import { sequence } from '@sveltejs/kit/hooks';
|
||||
|
||||
/** @type {import('@sveltejs/kit').Handle} */
|
||||
async function first({ event, resolve }) {
|
||||
console.log('first pre-processing');
|
||||
const result = await resolve(event, {
|
||||
transformPageChunk: ({ html }) => {
|
||||
// transforms are applied in reverse order
|
||||
console.log('first transform');
|
||||
return html;
|
||||
},
|
||||
preload: () => {
|
||||
// this one wins as it's the first defined in the chain
|
||||
console.log('first preload');
|
||||
return true;
|
||||
}
|
||||
});
|
||||
console.log('first post-processing');
|
||||
return result;
|
||||
}
|
||||
|
||||
/** @type {import('@sveltejs/kit').Handle} */
|
||||
async function second({ event, resolve }) {
|
||||
console.log('second pre-processing');
|
||||
const result = await resolve(event, {
|
||||
transformPageChunk: ({ html }) => {
|
||||
console.log('second transform');
|
||||
return html;
|
||||
},
|
||||
preload: () => {
|
||||
console.log('second preload');
|
||||
return true;
|
||||
},
|
||||
filterSerializedResponseHeaders: () => {
|
||||
// this one wins as it's the first defined in the chain
|
||||
console.log('second filterSerializedResponseHeaders');
|
||||
return true;
|
||||
}
|
||||
});
|
||||
console.log('second post-processing');
|
||||
return result;
|
||||
}
|
||||
|
||||
export const handle = sequence(first, second);
|
||||
```
|
||||
|
||||
**Output:**
|
||||
```
|
||||
first pre-processing
|
||||
first preload
|
||||
second pre-processing
|
||||
second filterSerializedResponseHeaders
|
||||
second transform
|
||||
first transform
|
||||
second post-processing
|
||||
first post-processing
|
||||
```
|
||||
|
||||
## Type
|
||||
|
||||
```dts
|
||||
function sequence(...handlers: Handle[]): Handle;
|
||||
```
|
||||
@@ -0,0 +1,11 @@
|
||||
# installPolyfills
|
||||
|
||||
Makes web APIs available as globals: `crypto`, `File`
|
||||
|
||||
```js
|
||||
import { installPolyfills } from '@sveltejs/kit/node/polyfills';
|
||||
```
|
||||
|
||||
```dts
|
||||
function installPolyfills(): void;
|
||||
```
|
||||
@@ -0,0 +1,40 @@
|
||||
# @sveltejs/kit/node
|
||||
|
||||
Node.js adapter utilities for converting between Node.js and Web APIs.
|
||||
|
||||
## createReadableStream
|
||||
|
||||
Converts a file on disk to a readable stream.
|
||||
|
||||
```ts
|
||||
function createReadableStream(file: string): ReadableStream;
|
||||
```
|
||||
|
||||
*Available since 2.4.0*
|
||||
|
||||
## getRequest
|
||||
|
||||
Converts Node.js `IncomingMessage` to Web `Request`.
|
||||
|
||||
```ts
|
||||
function getRequest({
|
||||
request,
|
||||
base,
|
||||
bodySizeLimit
|
||||
}: {
|
||||
request: import('http').IncomingMessage;
|
||||
base: string;
|
||||
bodySizeLimit?: number;
|
||||
}): Promise<Request>;
|
||||
```
|
||||
|
||||
## setResponse
|
||||
|
||||
Converts Web `Response` to Node.js `ServerResponse`.
|
||||
|
||||
```ts
|
||||
function setResponse(
|
||||
res: import('http').ServerResponse,
|
||||
response: Response
|
||||
): Promise<void>;
|
||||
```
|
||||
@@ -0,0 +1,11 @@
|
||||
# sveltekit
|
||||
|
||||
Returns the SvelteKit Vite plugins.
|
||||
|
||||
```js
|
||||
import { sveltekit } from '@sveltejs/kit/vite';
|
||||
```
|
||||
|
||||
```ts
|
||||
function sveltekit(): Promise<import('vite').Plugin[]>;
|
||||
```
|
||||
418
packages/mcp-server/summaries/distilled/kit/@sveltejs-kit.md
Normal file
418
packages/mcp-server/summaries/distilled/kit/@sveltejs-kit.md
Normal file
@@ -0,0 +1,418 @@
|
||||
# @sveltejs/kit Server APIs
|
||||
|
||||
## Core Functions
|
||||
|
||||
### error
|
||||
Throws HTTP error with status code and optional message. Stops request handling and returns error response.
|
||||
|
||||
```ts
|
||||
function error(status: number, body: App.Error): never;
|
||||
function error(status: number, body?: { message: string }): never;
|
||||
```
|
||||
|
||||
**Important**: Don't catch the thrown error - it prevents SvelteKit from handling it.
|
||||
|
||||
### redirect
|
||||
Redirects a request. Common status codes:
|
||||
- `303`: GET redirect (often after form POST)
|
||||
- `307`: Temporary redirect (keeps method)
|
||||
- `308`: Permanent redirect (keeps method, SEO transfer)
|
||||
|
||||
```ts
|
||||
function redirect(
|
||||
status: 300 | 301 | 302 | 303 | 304 | 305 | 306 | 307 | 308,
|
||||
location: string | URL
|
||||
): never;
|
||||
```
|
||||
|
||||
**Important**: Don't catch the thrown redirect.
|
||||
|
||||
### fail
|
||||
Creates `ActionFailure` for failed form submissions.
|
||||
|
||||
```ts
|
||||
function fail(status: number): ActionFailure<undefined>;
|
||||
function fail<T>(status: number, data: T): ActionFailure<T>;
|
||||
```
|
||||
|
||||
### json / text
|
||||
Create Response objects:
|
||||
|
||||
```ts
|
||||
function json(data: any, init?: ResponseInit): Response;
|
||||
function text(body: string, init?: ResponseInit): Response;
|
||||
```
|
||||
|
||||
### normalizeUrl
|
||||
Strips SvelteKit-internal suffixes and trailing slashes. Available since 2.18.0.
|
||||
|
||||
```ts
|
||||
const { url, denormalize } = normalizeUrl('/blog/post/__data.json');
|
||||
console.log(url.pathname); // /blog/post
|
||||
console.log(denormalize('/blog/post/a')); // /blog/post/a/__data.json
|
||||
```
|
||||
|
||||
## Type Checkers
|
||||
|
||||
```ts
|
||||
function isActionFailure(e: unknown): e is ActionFailure;
|
||||
function isHttpError(e: unknown, status?: number): e is HttpError;
|
||||
function isRedirect(e: unknown): e is Redirect;
|
||||
```
|
||||
|
||||
## Server Class
|
||||
|
||||
```ts
|
||||
class Server {
|
||||
constructor(manifest: SSRManifest);
|
||||
init(options: ServerInitOptions): Promise<void>;
|
||||
respond(request: Request, options: RequestOptions): Promise<Response>;
|
||||
}
|
||||
```
|
||||
|
||||
## Hooks
|
||||
|
||||
### Handle
|
||||
Runs on every request. Receives `event` and `resolve` function.
|
||||
|
||||
```ts
|
||||
type Handle = (input: {
|
||||
event: RequestEvent;
|
||||
resolve: (event: RequestEvent, opts?: ResolveOptions) => MaybePromise<Response>;
|
||||
}) => MaybePromise<Response>;
|
||||
```
|
||||
|
||||
### HandleFetch
|
||||
Modifies `event.fetch()` calls on server/during prerendering.
|
||||
|
||||
```ts
|
||||
type HandleFetch = (input: {
|
||||
event: RequestEvent;
|
||||
request: Request;
|
||||
fetch: typeof fetch;
|
||||
}) => MaybePromise<Response>;
|
||||
```
|
||||
|
||||
### HandleError
|
||||
|
||||
**Client-side**: Runs on unexpected navigation errors. Must never throw.
|
||||
|
||||
```ts
|
||||
type HandleClientError = (input: {
|
||||
error: unknown;
|
||||
event: NavigationEvent;
|
||||
status: number;
|
||||
message: string;
|
||||
}) => MaybePromise<void | App.Error>;
|
||||
```
|
||||
|
||||
**Server-side**: Runs on unexpected request errors. Must never throw.
|
||||
|
||||
```ts
|
||||
type HandleServerError = (input: {
|
||||
error: unknown;
|
||||
event: RequestEvent;
|
||||
status: number;
|
||||
message: string;
|
||||
}) => MaybePromise<void | App.Error>;
|
||||
```
|
||||
|
||||
### HandleValidationError
|
||||
Runs when remote function argument validation fails.
|
||||
|
||||
```ts
|
||||
type HandleValidationError = (input: {
|
||||
issues: StandardSchemaV1.Issue[];
|
||||
event: RequestEvent;
|
||||
}) => MaybePromise<App.Error>;
|
||||
```
|
||||
|
||||
### Reroute
|
||||
Modifies URL before route determination. Available since 2.3.0.
|
||||
|
||||
```ts
|
||||
type Reroute = (event: {
|
||||
url: URL;
|
||||
fetch: typeof fetch;
|
||||
}) => MaybePromise<void | string>;
|
||||
```
|
||||
|
||||
### Init Hooks
|
||||
Available since 2.10.0.
|
||||
|
||||
```ts
|
||||
type ClientInit = () => MaybePromise<void>; // Runs when app starts in browser
|
||||
type ServerInit = () => MaybePromise<void>; // Runs before first request
|
||||
```
|
||||
|
||||
### Transport
|
||||
Custom type serialization across server/client. Available since 2.11.0.
|
||||
|
||||
```ts
|
||||
type Transport = Record<string, Transporter>;
|
||||
|
||||
interface Transporter<T, U> {
|
||||
encode: (value: T) => false | U;
|
||||
decode: (data: U) => T;
|
||||
}
|
||||
```
|
||||
|
||||
## RequestEvent
|
||||
|
||||
Core event object for server-side code:
|
||||
|
||||
```ts
|
||||
interface RequestEvent<Params, RouteId> {
|
||||
cookies: Cookies;
|
||||
fetch: typeof fetch; // Enhanced with cookie/auth inheritance, relative URLs, direct internal calls
|
||||
getClientAddress: () => string;
|
||||
locals: App.Locals;
|
||||
params: Params;
|
||||
platform: App.Platform | undefined;
|
||||
request: Request;
|
||||
route: { id: RouteId };
|
||||
setHeaders: (headers: Record<string, string>) => void;
|
||||
url: URL;
|
||||
isDataRequest: boolean; // True for +page/layout.server.js data requests
|
||||
isSubRequest: boolean; // True for same-origin fetch without HTTP overhead
|
||||
isRemoteRequest: boolean; // True for remote function calls
|
||||
tracing: { enabled: boolean; root: Span; current: Span }; // Since 2.31.0
|
||||
}
|
||||
```
|
||||
|
||||
## Cookies
|
||||
|
||||
```ts
|
||||
interface Cookies {
|
||||
get(name: string, opts?: CookieParseOptions): string | undefined;
|
||||
getAll(opts?: CookieParseOptions): Array<{ name: string; value: string }>;
|
||||
set(name: string, value: string, opts: CookieSerializeOptions & { path: string }): void;
|
||||
delete(name: string, opts: CookieSerializeOptions & { path: string }): void;
|
||||
serialize(name: string, value: string, opts: CookieSerializeOptions & { path: string }): string;
|
||||
}
|
||||
```
|
||||
|
||||
**Defaults**: `httpOnly` and `secure` are `true` (except on http://localhost). `sameSite` defaults to `lax`.
|
||||
|
||||
**Important**: Must specify `path` (usually `path: '/'`). Can't set `set-cookie` via `setHeaders` - use `cookies` API in server-only `load`.
|
||||
|
||||
## Load Functions
|
||||
|
||||
### LoadEvent (Client/Universal)
|
||||
|
||||
```ts
|
||||
interface LoadEvent<Params, Data, ParentData, RouteId> {
|
||||
fetch: typeof fetch; // Enhanced with cookie inheritance, relative URLs, inlining
|
||||
data: Data; // From server load
|
||||
params: Params;
|
||||
route: { id: RouteId };
|
||||
url: URL;
|
||||
setHeaders: (headers: Record<string, string>) => void; // No effect in browser
|
||||
parent: () => Promise<ParentData>;
|
||||
depends: (...deps: Array<`${string}:${string}`>) => void;
|
||||
untrack: <T>(fn: () => T) => T;
|
||||
tracing: { enabled: boolean; root: Span; current: Span }; // Since 2.31.0
|
||||
}
|
||||
```
|
||||
|
||||
### ServerLoadEvent
|
||||
|
||||
Extends `RequestEvent` with:
|
||||
|
||||
```ts
|
||||
interface ServerLoadEvent<Params, ParentData, RouteId> extends RequestEvent<Params, RouteId> {
|
||||
parent: () => Promise<ParentData>;
|
||||
depends: (...deps: string[]) => void;
|
||||
untrack: <T>(fn: () => T) => T;
|
||||
tracing: { enabled: boolean; root: Span; current: Span }; // Since 2.31.0
|
||||
}
|
||||
```
|
||||
|
||||
**Gotcha**: Call `parent()` after fetching other data to avoid waterfalls.
|
||||
|
||||
## Actions
|
||||
|
||||
### Action Type
|
||||
|
||||
```ts
|
||||
type Action<Params, OutputData, RouteId> = (
|
||||
event: RequestEvent<Params, RouteId>
|
||||
) => MaybePromise<OutputData>;
|
||||
|
||||
type Actions<Params, OutputData, RouteId> = Record<string, Action<Params, OutputData, RouteId>>;
|
||||
```
|
||||
|
||||
### ActionResult
|
||||
|
||||
```ts
|
||||
type ActionResult<Success, Failure> =
|
||||
| { type: 'success'; status: number; data?: Success }
|
||||
| { type: 'failure'; status: number; data?: Failure }
|
||||
| { type: 'redirect'; status: number; location: string }
|
||||
| { type: 'error'; status?: number; error: any };
|
||||
```
|
||||
|
||||
### SubmitFunction
|
||||
|
||||
```ts
|
||||
type SubmitFunction<Success, Failure> = (input: {
|
||||
action: URL;
|
||||
formData: FormData;
|
||||
formElement: HTMLFormElement;
|
||||
controller: AbortController;
|
||||
submitter: HTMLElement | null;
|
||||
cancel: () => void;
|
||||
}) => MaybePromise<void | ((opts: {
|
||||
formData: FormData;
|
||||
formElement: HTMLFormElement;
|
||||
action: URL;
|
||||
result: ActionResult<Success, Failure>;
|
||||
update: (options?: { reset?: boolean; invalidateAll?: boolean }) => Promise<void>;
|
||||
}) => MaybePromise<void>)>;
|
||||
```
|
||||
|
||||
## Remote Functions
|
||||
|
||||
### RemoteQuery
|
||||
|
||||
```ts
|
||||
type RemoteQuery<T> = RemoteResource<T> & {
|
||||
set(value: T): void;
|
||||
refresh(): Promise<void>;
|
||||
withOverride(update: (current: Awaited<T>) => Awaited<T>): RemoteQueryOverride;
|
||||
};
|
||||
|
||||
type RemoteQueryFunction<Input, Output> = (arg: Input) => RemoteQuery<Output>;
|
||||
```
|
||||
|
||||
### RemoteCommand
|
||||
|
||||
```ts
|
||||
type RemoteCommand<Input, Output> = {
|
||||
(arg: Input): Promise<Awaited<Output>> & {
|
||||
updates(...queries: Array<RemoteQuery<any> | RemoteQueryOverride>): Promise<Awaited<Output>>;
|
||||
};
|
||||
get pending(): number;
|
||||
};
|
||||
```
|
||||
|
||||
### RemoteForm
|
||||
|
||||
```ts
|
||||
type RemoteForm<Input, Output> = {
|
||||
[attachment: symbol]: (node: HTMLFormElement) => void;
|
||||
method: 'POST';
|
||||
action: string;
|
||||
enhance(callback: (opts: { form: HTMLFormElement; data: Input; submit: () => Promise<void> }) => void): { ... };
|
||||
for(id: ExtractId<Input>): Omit<RemoteForm<Input, Output>, 'for'>;
|
||||
preflight(schema: StandardSchemaV1<Input, any>): RemoteForm<Input, Output>;
|
||||
validate(options?: { includeUntouched?: boolean; submitter?: HTMLButtonElement }): Promise<void>;
|
||||
get result(): Output | undefined;
|
||||
get pending(): number;
|
||||
fields: RemoteFormFields<Input>;
|
||||
buttonProps: { ... };
|
||||
};
|
||||
```
|
||||
|
||||
### RemotePrerenderFunction
|
||||
|
||||
```ts
|
||||
type RemotePrerenderFunction<Input, Output> = (arg: Input) => RemoteResource<Output>;
|
||||
```
|
||||
|
||||
### RemoteResource
|
||||
|
||||
```ts
|
||||
type RemoteResource<T> = Promise<Awaited<T>> & {
|
||||
get error(): any;
|
||||
get loading(): boolean;
|
||||
} & ({ get current(): undefined; ready: false } | { get current(): Awaited<T>; ready: true });
|
||||
```
|
||||
|
||||
## Navigation Types
|
||||
|
||||
### NavigationType
|
||||
|
||||
```ts
|
||||
type NavigationType = 'enter' | 'form' | 'leave' | 'link' | 'goto' | 'popstate';
|
||||
```
|
||||
|
||||
### AfterNavigate
|
||||
|
||||
```ts
|
||||
type AfterNavigate = (Navigation | NavigationEnter) & {
|
||||
type: Exclude<NavigationType, 'leave'>;
|
||||
willUnload: false;
|
||||
};
|
||||
```
|
||||
|
||||
### BeforeNavigate
|
||||
|
||||
```ts
|
||||
type BeforeNavigate = Navigation & {
|
||||
cancel: () => void;
|
||||
};
|
||||
```
|
||||
|
||||
### OnNavigate
|
||||
|
||||
```ts
|
||||
type OnNavigate = Navigation & {
|
||||
type: Exclude<NavigationType, 'enter' | 'leave'>;
|
||||
willUnload: false;
|
||||
};
|
||||
```
|
||||
|
||||
## Page
|
||||
|
||||
```ts
|
||||
interface Page<Params, RouteId> {
|
||||
url: URL & { pathname: ResolvedPathname };
|
||||
params: Params;
|
||||
route: { id: RouteId };
|
||||
status: number;
|
||||
error: App.Error | null;
|
||||
data: App.PageData & Record<string, any>;
|
||||
state: App.PageState;
|
||||
form: any; // Filled after form submission
|
||||
}
|
||||
```
|
||||
|
||||
## Adapter
|
||||
|
||||
```ts
|
||||
interface Adapter {
|
||||
name: string;
|
||||
adapt: (builder: Builder) => MaybePromise<void>;
|
||||
supports?: {
|
||||
read?: (details: { config: any; route: { id: string } }) => boolean;
|
||||
instrumentation?: () => boolean; // Since 2.31.0
|
||||
};
|
||||
emulate?: () => MaybePromise<Emulator>;
|
||||
}
|
||||
```
|
||||
|
||||
### Builder
|
||||
|
||||
Key methods:
|
||||
- `writeClient(dest: string): string[]`
|
||||
- `writeServer(dest: string): string[]`
|
||||
- `writePrerendered(dest: string): string[]`
|
||||
- `generateManifest(opts: { relativePath: string; routes?: RouteDefinition[] }): string`
|
||||
- `compress(directory: string): Promise<void>`
|
||||
- `instrument(args: { entrypoint: string; instrumentation: string; ... }): void` (Since 2.31.0)
|
||||
|
||||
## Snapshot
|
||||
|
||||
```ts
|
||||
interface Snapshot<T> {
|
||||
capture: () => T;
|
||||
restore: (snapshot: T) => void;
|
||||
}
|
||||
```
|
||||
|
||||
## Constants
|
||||
|
||||
```ts
|
||||
const VERSION: string; // SvelteKit version
|
||||
```
|
||||
73
packages/mcp-server/summaries/distilled/kit/accessibility.md
Normal file
73
packages/mcp-server/summaries/distilled/kit/accessibility.md
Normal file
@@ -0,0 +1,73 @@
|
||||
# Accessibility
|
||||
|
||||
SvelteKit provides accessible defaults. You're responsible for ensuring your application code is accessible.
|
||||
|
||||
## Route Announcements
|
||||
|
||||
SvelteKit injects a [live region](https://developer.mozilla.org/en-US/docs/Web/Accessibility/ARIA/ARIA_Live_Regions) that announces page changes during client-side navigation by reading the `<title>` element.
|
||||
|
||||
**Every page needs a unique, descriptive title:**
|
||||
|
||||
```svelte
|
||||
<!--- file: src/routes/+page.svelte --->
|
||||
<svelte:head>
|
||||
<title>Todo List</title>
|
||||
</svelte:head>
|
||||
```
|
||||
|
||||
## Focus Management
|
||||
|
||||
After each navigation and enhanced form submission, SvelteKit focuses `<body>` (or an element with `autofocus` if present).
|
||||
|
||||
**Customize focus with `afterNavigate`:**
|
||||
|
||||
```js
|
||||
import { afterNavigate } from '$app/navigation';
|
||||
|
||||
afterNavigate(() => {
|
||||
/** @type {HTMLElement | null} */
|
||||
const to_focus = document.querySelector('.focus-me');
|
||||
to_focus?.focus();
|
||||
});
|
||||
```
|
||||
|
||||
**`goto` with `keepFocus` option:** Preserves current focus instead of resetting. Ensure the focused element still exists after navigation.
|
||||
|
||||
## Lang Attribute
|
||||
|
||||
Default is English. Update `src/app.html` for other languages:
|
||||
|
||||
```html
|
||||
/// file: src/app.html
|
||||
<html lang="de">
|
||||
```
|
||||
|
||||
**For multiple languages, use a placeholder and `handle` hook:**
|
||||
|
||||
```html
|
||||
/// file: src/app.html
|
||||
<html lang="%lang%">
|
||||
```
|
||||
|
||||
```js
|
||||
/// file: src/hooks.server.js
|
||||
/**
|
||||
* @param {import('@sveltejs/kit').RequestEvent} event
|
||||
*/
|
||||
function get_lang(event) {
|
||||
return 'en';
|
||||
}
|
||||
// ---cut---
|
||||
/** @type {import('@sveltejs/kit').Handle} */
|
||||
export function handle({ event, resolve }) {
|
||||
return resolve(event, {
|
||||
transformPageChunk: ({ html }) => html.replace('%lang%', get_lang(event))
|
||||
});
|
||||
}
|
||||
```
|
||||
|
||||
## Further Reading
|
||||
|
||||
- [MDN Web Docs: Accessibility](https://developer.mozilla.org/en-US/docs/Learn/Accessibility)
|
||||
- [The A11y Project](https://www.a11yproject.com/)
|
||||
- [How to Meet WCAG](https://www.w3.org/WAI/WCAG21/quickref/)
|
||||
20
packages/mcp-server/summaries/distilled/kit/adapter-auto.md
Normal file
20
packages/mcp-server/summaries/distilled/kit/adapter-auto.md
Normal file
@@ -0,0 +1,20 @@
|
||||
# adapter-auto
|
||||
|
||||
`adapter-auto` is installed by default with `npx sv create`. It automatically detects and uses the correct adapter for supported platforms at deploy time:
|
||||
|
||||
- `@sveltejs/adapter-cloudflare` - Cloudflare Pages
|
||||
- `@sveltejs/adapter-netlify` - Netlify
|
||||
- `@sveltejs/adapter-vercel` - Vercel
|
||||
- `svelte-adapter-azure-swa` - Azure Static Web Apps
|
||||
- `svelte-kit-sst` - AWS via SST
|
||||
- `@sveltejs/adapter-node` - Google Cloud Run
|
||||
|
||||
**Best practice:** Install the specific adapter to `devDependencies` once you've chosen a platform for better lockfile management and faster CI installs.
|
||||
|
||||
## Configuration
|
||||
|
||||
`adapter-auto` accepts no options. To configure adapter-specific options (e.g., `{ edge: true }` for Vercel/Netlify), install and use the underlying adapter directly.
|
||||
|
||||
## Extending
|
||||
|
||||
Add support for more adapters by editing [adapters.js](https://github.com/sveltejs/kit/blob/main/packages/adapter-auto/adapters.js) and submitting a PR.
|
||||
@@ -0,0 +1,114 @@
|
||||
# adapter-cloudflare-workers
|
||||
|
||||
> **DEPRECATED**: Use [`adapter-cloudflare`](adapter-cloudflare) instead. Cloudflare Workers Sites is being deprecated in favor of Workers with Static Assets.
|
||||
|
||||
Deploys to [Cloudflare Workers](https://workers.cloudflare.com/) with [Workers Sites](https://developers.cloudflare.com/workers/configuration/sites/).
|
||||
|
||||
## Installation
|
||||
|
||||
```js
|
||||
/// file: svelte.config.js
|
||||
import adapter from '@sveltejs/adapter-cloudflare-workers';
|
||||
|
||||
/** @type {import('@sveltejs/kit').Config} */
|
||||
const config = {
|
||||
kit: {
|
||||
adapter: adapter({
|
||||
// see options below
|
||||
})
|
||||
}
|
||||
};
|
||||
|
||||
export default config;
|
||||
```
|
||||
|
||||
## Options
|
||||
|
||||
- **`config`**: Path to Wrangler config file (if not using default `wrangler.jsonc`, `wrangler.json`, or `wrangler.toml`)
|
||||
- **`platformProxy`**: Preferences for emulated `platform.env` local bindings. See [getPlatformProxy docs](https://developers.cloudflare.com/workers/wrangler/api/#parameters-1)
|
||||
|
||||
## Configuration
|
||||
|
||||
Create Wrangler config in project root:
|
||||
|
||||
```jsonc
|
||||
/// file: wrangler.jsonc
|
||||
{
|
||||
"name": "<your-service-name>",
|
||||
"account_id": "<your-account-id>",
|
||||
"main": "./.cloudflare/worker.js",
|
||||
"site": {
|
||||
"bucket": "./.cloudflare/public"
|
||||
},
|
||||
"build": {
|
||||
"command": "npm run build"
|
||||
},
|
||||
"compatibility_date": "2021-11-12"
|
||||
}
|
||||
```
|
||||
|
||||
Get `<your-account-id>` from `wrangler whoami` or Cloudflare dashboard URL.
|
||||
|
||||
Add `.cloudflare` and `.wrangler` to `.gitignore`.
|
||||
|
||||
## Deploy
|
||||
|
||||
```sh
|
||||
npm i -D wrangler
|
||||
wrangler login
|
||||
wrangler deploy
|
||||
```
|
||||
|
||||
## Runtime APIs
|
||||
|
||||
Access Cloudflare bindings (KV, DO, etc.) via `platform` in hooks and endpoints:
|
||||
|
||||
```js
|
||||
/// file: +server.js
|
||||
/** @type {import('./$types').RequestHandler} */
|
||||
export async function POST({ request, platform }) {
|
||||
const x = platform?.env.YOUR_DURABLE_OBJECT_NAMESPACE.idFromName('x');
|
||||
}
|
||||
```
|
||||
|
||||
**Type definitions:**
|
||||
|
||||
```ts
|
||||
/// file: src/app.d.ts
|
||||
import { KVNamespace, DurableObjectNamespace } from '@cloudflare/workers-types';
|
||||
|
||||
declare global {
|
||||
namespace App {
|
||||
interface Platform {
|
||||
env?: {
|
||||
YOUR_KV_NAMESPACE: KVNamespace;
|
||||
YOUR_DURABLE_OBJECT_NAMESPACE: DurableObjectNamespace;
|
||||
};
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
export {};
|
||||
```
|
||||
|
||||
Use SvelteKit's `$env` module for environment variables.
|
||||
|
||||
## Local Testing
|
||||
|
||||
`platform` values are emulated in dev/preview using Wrangler config bindings. Configure via `platformProxy` option.
|
||||
|
||||
For testing builds, use Wrangler v4: `wrangler dev`
|
||||
|
||||
## Troubleshooting
|
||||
|
||||
**Node.js compatibility**: Add to Wrangler config:
|
||||
```jsonc
|
||||
/// file: wrangler.jsonc
|
||||
{
|
||||
"compatibility_flags": ["nodejs_compat"]
|
||||
}
|
||||
```
|
||||
|
||||
**Worker size limits**: If bundle exceeds [size limits](https://developers.cloudflare.com/workers/platform/limits/#worker-size), import large libraries client-side only.
|
||||
|
||||
**File system**: `fs` unavailable — [prerender](page-options#prerender) routes that need it.
|
||||
@@ -0,0 +1,209 @@
|
||||
# Cloudflare Adapter
|
||||
|
||||
Deploy to Cloudflare Workers or Cloudflare Pages using `adapter-cloudflare`.
|
||||
|
||||
## Comparisons
|
||||
|
||||
- `adapter-cloudflare` – all SvelteKit features; builds for Workers Static Assets and Pages
|
||||
- `adapter-cloudflare-workers` – deprecated
|
||||
- `adapter-static` – client-side only; compatible with Workers Static Assets and Pages
|
||||
|
||||
## Usage
|
||||
|
||||
```bash
|
||||
npm i -D @sveltejs/adapter-cloudflare
|
||||
```
|
||||
|
||||
```js
|
||||
/// file: svelte.config.js
|
||||
import adapter from '@sveltejs/adapter-cloudflare';
|
||||
|
||||
/** @type {import('@sveltejs/kit').Config} */
|
||||
const config = {
|
||||
kit: {
|
||||
adapter: adapter({
|
||||
config: undefined,
|
||||
platformProxy: {
|
||||
configPath: undefined,
|
||||
environment: undefined,
|
||||
persist: undefined
|
||||
},
|
||||
fallback: 'plaintext',
|
||||
routes: {
|
||||
include: ['/*'],
|
||||
exclude: ['<all>']
|
||||
}
|
||||
})
|
||||
}
|
||||
};
|
||||
|
||||
export default config;
|
||||
```
|
||||
|
||||
## Options
|
||||
|
||||
### config
|
||||
Path to Wrangler config file (if not using default `wrangler.jsonc`, `wrangler.json`, or `wrangler.toml`).
|
||||
|
||||
### platformProxy
|
||||
Preferences for emulated `platform.env` local bindings. See [getPlatformProxy docs](https://developers.cloudflare.com/workers/wrangler/api/#parameters-1).
|
||||
|
||||
### fallback
|
||||
Render `plaintext` or `spa` 404 page for non-matching assets. Default `plaintext` is usually sufficient. Use `spa` if using `routes.exclude` to avoid unstyled 404s.
|
||||
|
||||
### routes
|
||||
**Cloudflare Pages only.** Customizes `_routes.json`:
|
||||
- `include` – routes that invoke a function (default `['/*']`)
|
||||
- `exclude` – routes that don't invoke a function (faster/cheaper for static assets)
|
||||
- `<build>` – Vite build artifacts
|
||||
- `<files>` – `static` directory contents
|
||||
- `<prerendered>` – prerendered pages
|
||||
- `<all>` – all above (default)
|
||||
|
||||
Max 100 combined rules. Useful if `<prerendered>` exceeds limit (e.g., use `'/articles/*'` instead of individual paths).
|
||||
|
||||
## Cloudflare Workers
|
||||
|
||||
### Basic Configuration
|
||||
|
||||
```jsonc
|
||||
/// file: wrangler.jsonc
|
||||
{
|
||||
"name": "<any-name-you-want>",
|
||||
"main": ".svelte-kit/cloudflare/_worker.js",
|
||||
"compatibility_date": "2025-01-01",
|
||||
"assets": {
|
||||
"binding": "ASSETS",
|
||||
"directory": ".svelte-kit/cloudflare",
|
||||
}
|
||||
}
|
||||
```
|
||||
|
||||
### Deployment
|
||||
Follow [Cloudflare Workers framework guide](https://developers.cloudflare.com/workers/frameworks/framework-guides/svelte/).
|
||||
|
||||
## Cloudflare Pages
|
||||
|
||||
### Deployment
|
||||
Follow [Get Started Guide](https://developers.cloudflare.com/pages/get-started/).
|
||||
|
||||
**Git integration build settings:**
|
||||
- Framework preset: SvelteKit
|
||||
- Build command: `npm run build` or `vite build`
|
||||
- Build output directory: `.svelte-kit/cloudflare`
|
||||
|
||||
### Notes
|
||||
Functions in `/functions` directory are ignored. Use SvelteKit [server endpoints](routing#server) instead (compiled to single `_worker.js`).
|
||||
|
||||
## Runtime APIs
|
||||
|
||||
Access `env` (bindings), `ctx`, `caches`, and `cf` via `platform` in hooks and endpoints:
|
||||
|
||||
```js
|
||||
// @filename: ambient.d.ts
|
||||
import { DurableObjectNamespace } from '@cloudflare/workers-types';
|
||||
|
||||
declare global {
|
||||
namespace App {
|
||||
interface Platform {
|
||||
env: {
|
||||
YOUR_DURABLE_OBJECT_NAMESPACE: DurableObjectNamespace;
|
||||
};
|
||||
}
|
||||
}
|
||||
}
|
||||
// @filename: +server.js
|
||||
// ---cut---
|
||||
// @errors: 2355 2322
|
||||
/// file: +server.js
|
||||
/** @type {import('./$types').RequestHandler} */
|
||||
export async function POST({ request, platform }) {
|
||||
const x = platform?.env.YOUR_DURABLE_OBJECT_NAMESPACE.idFromName('x');
|
||||
}
|
||||
```
|
||||
|
||||
> [!NOTE] Use SvelteKit's `$env` module for environment variables.
|
||||
|
||||
**Type definitions:**
|
||||
|
||||
```ts
|
||||
/// file: src/app.d.ts
|
||||
+++import { KVNamespace, DurableObjectNamespace } from '@cloudflare/workers-types';+++
|
||||
|
||||
declare global {
|
||||
namespace App {
|
||||
interface Platform {
|
||||
+++ env: {
|
||||
YOUR_KV_NAMESPACE: KVNamespace;
|
||||
YOUR_DURABLE_OBJECT_NAMESPACE: DurableObjectNamespace;
|
||||
};+++
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
export {};
|
||||
```
|
||||
|
||||
### Testing Locally
|
||||
|
||||
`platform` values are emulated in dev/preview using Wrangler config bindings. Use `platformProxy` option to customize.
|
||||
|
||||
For build testing, use Wrangler 4:
|
||||
- Workers: `wrangler dev .svelte-kit/cloudflare`
|
||||
- Pages: `wrangler pages dev .svelte-kit/cloudflare`
|
||||
|
||||
## Headers and Redirects
|
||||
|
||||
`_headers` and `_redirects` files (in project root) only affect static assets. For dynamic responses, use server endpoints or `handle` hook.
|
||||
|
||||
## Troubleshooting
|
||||
|
||||
### Node.js Compatibility
|
||||
|
||||
```jsonc
|
||||
/// file: wrangler.jsonc
|
||||
{
|
||||
"compatibility_flags": ["nodejs_compat"]
|
||||
}
|
||||
```
|
||||
|
||||
### Worker Size Limits
|
||||
|
||||
If exceeding [size limits](https://developers.cloudflare.com/workers/platform/limits/#worker-size), import large libraries client-side only. See [FAQ](./faq#How-do-I-use-a-client-side-library-accessing-document-or-window).
|
||||
|
||||
### Accessing File System
|
||||
|
||||
Can't use `fs`. Use [`read`]($app-server#read) from `$app/server` (fetches from deployed assets) or [prerender](page-options#prerender) routes.
|
||||
|
||||
## Migrating from Workers Sites
|
||||
|
||||
Replace `adapter-cloudflare-workers` with `adapter-cloudflare`. Update config:
|
||||
|
||||
```js
|
||||
// @errors: 2307
|
||||
/// file: svelte.config.js
|
||||
---import adapter from '@sveltejs/adapter-cloudflare-workers';---
|
||||
+++import adapter from '@sveltejs/adapter-cloudflare';+++
|
||||
|
||||
/** @type {import('@sveltejs/kit').Config} */
|
||||
const config = {
|
||||
kit: {
|
||||
adapter: adapter()
|
||||
}
|
||||
};
|
||||
|
||||
export default config;
|
||||
```
|
||||
|
||||
```jsonc
|
||||
/// file: wrangler.jsonc
|
||||
{
|
||||
--- "site": {
|
||||
"bucket": ".cloudflare/public"
|
||||
},---
|
||||
+++ "assets": {
|
||||
"directory": ".cloudflare/public",
|
||||
"binding": "ASSETS" // Exclude this if you don't have a `main` key configured.
|
||||
}+++
|
||||
}
|
||||
```
|
||||
117
packages/mcp-server/summaries/distilled/kit/adapter-netlify.md
Normal file
117
packages/mcp-server/summaries/distilled/kit/adapter-netlify.md
Normal file
@@ -0,0 +1,117 @@
|
||||
# Netlify Adapter
|
||||
|
||||
Deploy to Netlify using [`adapter-netlify`](https://github.com/sveltejs/kit/tree/main/packages/adapter-netlify). Auto-installed with `adapter-auto`.
|
||||
|
||||
## Usage
|
||||
|
||||
Install: `npm i -D @sveltejs/adapter-netlify`
|
||||
|
||||
```js
|
||||
/// file: svelte.config.js
|
||||
import adapter from '@sveltejs/adapter-netlify';
|
||||
|
||||
/** @type {import('@sveltejs/kit').Config} */
|
||||
const config = {
|
||||
kit: {
|
||||
// default options are shown
|
||||
adapter: adapter({
|
||||
// if true, will create a Netlify Edge Function rather
|
||||
// than using standard Node-based functions
|
||||
edge: false,
|
||||
|
||||
// if true, will split your app into multiple functions
|
||||
// instead of creating a single one for the entire app.
|
||||
// if `edge` is true, this option cannot be used
|
||||
split: false
|
||||
})
|
||||
}
|
||||
};
|
||||
|
||||
export default config;
|
||||
```
|
||||
|
||||
Requires `netlify.toml` in project root:
|
||||
|
||||
```toml
|
||||
[build]
|
||||
command = "npm run build"
|
||||
publish = "build"
|
||||
```
|
||||
|
||||
Default publish directory is `"build"` if not specified.
|
||||
|
||||
## Edge Functions
|
||||
|
||||
Set `edge: true` for Deno-based edge functions (deployed close to visitors). Default `false` uses Node-based functions.
|
||||
|
||||
```js
|
||||
/// file: svelte.config.js
|
||||
import adapter from '@sveltejs/adapter-netlify';
|
||||
|
||||
/** @type {import('@sveltejs/kit').Config} */
|
||||
const config = {
|
||||
kit: {
|
||||
adapter: adapter({
|
||||
// will create a Netlify Edge Function using Deno-based
|
||||
// rather than using standard Node-based functions
|
||||
edge: true
|
||||
})
|
||||
}
|
||||
};
|
||||
|
||||
export default config;
|
||||
```
|
||||
|
||||
## Netlify-Specific Features
|
||||
|
||||
### Headers & Redirects
|
||||
|
||||
Place `_headers` and `_redirects` files in project root for static assets.
|
||||
|
||||
**Gotchas:**
|
||||
- `_redirects` has higher priority than `[[redirects]]` in `netlify.toml`
|
||||
- Don't add catch-all rules like `/* /foobar/:splat` - they'll prevent auto-appended rules from working
|
||||
- Only first matching rule is processed
|
||||
|
||||
### Forms
|
||||
|
||||
1. Create HTML form with hidden `form-name` input
|
||||
2. Prerender the page (`export const prerender = true`) - Netlify's bot parses HTML at deploy time
|
||||
3. Prerender custom success pages if specified
|
||||
|
||||
### Functions
|
||||
|
||||
Access Netlify context (including Identity info) via `event.platform.context`:
|
||||
|
||||
```js
|
||||
// @errors: 2339
|
||||
// @filename: ambient.d.ts
|
||||
/// <reference types="@sveltejs/adapter-netlify" />
|
||||
// @filename: +page.server.js
|
||||
// ---cut---
|
||||
/// file: +page.server.js
|
||||
/** @type {import('./$types').PageServerLoad} */
|
||||
export const load = async (event) => {
|
||||
const context = event.platform?.context;
|
||||
console.log(context); // shows up in your functions log in the Netlify app
|
||||
};
|
||||
```
|
||||
|
||||
Add custom functions via `netlify.toml`:
|
||||
|
||||
```toml
|
||||
[build]
|
||||
command = "npm run build"
|
||||
publish = "build"
|
||||
|
||||
[functions]
|
||||
directory = "functions"
|
||||
```
|
||||
|
||||
## Troubleshooting
|
||||
|
||||
**File system access:**
|
||||
- `fs` doesn't work in edge deployments
|
||||
- In serverless, files aren't copied to deployment
|
||||
- Use `read()` from `$app/server` instead (works in both edge and serverless)
|
||||
- Or prerender the routes
|
||||
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user