Skip to content

Commit ecbf55b

Browse files
authored
reduce prompt token size by reorganizing the knowledge (#64)
1 parent 257d9ad commit ecbf55b

Some content is hidden

Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.

50 files changed

+295
-385
lines changed
Lines changed: 6 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,4 @@
1-
name: Type Check
1+
name: CI
22

33
on:
44
pull_request:
@@ -9,7 +9,7 @@ on:
99
- main
1010

1111
jobs:
12-
typecheck:
12+
test:
1313
runs-on: ubuntu-latest
1414
steps:
1515
- name: Checkout code
@@ -29,3 +29,7 @@ jobs:
2929

3030
- name: Run type check
3131
run: pnpm run typecheck
32+
33+
- name: Run tests
34+
run: pnpm test
35+

package.json

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -26,7 +26,8 @@
2626
"prepublishOnly": "pnpm run clean && pnpm run build",
2727
"clean": "rm -rf dist",
2828
"start": "node dist/stdio.js",
29-
"test": "vitest run --exclude '**/upgrade.test.ts'",
29+
"test": "vitest run --exclude 'test/e2e/**'",
30+
"test:e2e": "vitest run test/e2e",
3031
"eval": "vitest run test/e2e/upgrade.test.ts",
3132
"typecheck": "tsc --noEmit"
3233
},

scripts/copy-resources.js

Lines changed: 45 additions & 54 deletions
Original file line numberDiff line numberDiff line change
@@ -1,90 +1,81 @@
11
#!/usr/bin/env node
22
/**
33
* Copy resources script
4-
* Scans all .md files in src/ and copies them to a flat dist/resources/ directory
5-
* Ensures all .md filenames are unique
4+
* Preserves directory structure from src/resources/ to dist/resources/
5+
* Copies .md files from src/prompts/ to dist/resources/prompts/
66
*
77
* Usage: node scripts/copy-resources.js
88
*/
99

1010
const fs = require('fs')
1111
const path = require('path')
1212

13-
const SRC_DIR = 'src'
13+
const SRC_RESOURCES_DIR = 'src/resources'
14+
const SRC_PROMPTS_DIR = 'src/prompts'
1415
const DEST_DIR = 'dist/resources'
1516

1617
/**
17-
* Recursively find all .md files in a directory
18+
* Recursively copy .md files while preserving directory structure
1819
*/
19-
function findMarkdownFiles(dir, fileList = []) {
20-
const files = fs.readdirSync(dir)
20+
function copyMarkdownFiles(srcDir, destDir, relativePath = '') {
21+
if (!fs.existsSync(srcDir)) {
22+
return []
23+
}
24+
25+
const files = fs.readdirSync(srcDir)
26+
const copiedFiles = []
2127

2228
files.forEach(file => {
23-
const filePath = path.join(dir, file)
24-
const stat = fs.statSync(filePath)
29+
const srcPath = path.join(srcDir, file)
30+
const stat = fs.statSync(srcPath)
2531

2632
if (stat.isDirectory()) {
27-
findMarkdownFiles(filePath, fileList)
33+
// Recursively copy subdirectories
34+
const newRelativePath = path.join(relativePath, file)
35+
const copied = copyMarkdownFiles(srcPath, destDir, newRelativePath)
36+
copiedFiles.push(...copied)
2837
} else if (file.endsWith('.md')) {
29-
fileList.push(filePath)
38+
// Copy .md file preserving structure
39+
const destPath = path.join(destDir, relativePath, file)
40+
const destDirPath = path.dirname(destPath)
41+
42+
if (!fs.existsSync(destDirPath)) {
43+
fs.mkdirSync(destDirPath, { recursive: true })
44+
}
45+
46+
fs.copyFileSync(srcPath, destPath)
47+
const relativeDestPath = path.relative(destDir, destPath)
48+
copiedFiles.push(relativeDestPath)
3049
}
3150
})
3251

33-
return fileList
34-
}
35-
36-
/**
37-
* Check for duplicate filenames
38-
*/
39-
function checkDuplicates(files) {
40-
const filenames = new Map()
41-
const duplicates = []
42-
43-
files.forEach(filePath => {
44-
const filename = path.basename(filePath)
45-
if (filenames.has(filename)) {
46-
duplicates.push({
47-
filename,
48-
paths: [filenames.get(filename), filePath]
49-
})
50-
} else {
51-
filenames.set(filename, filePath)
52-
}
53-
})
54-
55-
return duplicates
52+
return copiedFiles
5653
}
5754

5855
/**
5956
* Main function
6057
*/
6158
function main() {
62-
console.log('📦 Scanning for markdown files in src/...\n')
63-
64-
const markdownFiles = findMarkdownFiles(SRC_DIR)
65-
console.log(`Found ${markdownFiles.length} markdown files\n`)
66-
67-
const duplicates = checkDuplicates(markdownFiles)
68-
if (duplicates.length > 0) {
69-
console.error('❌ Error: Duplicate markdown filenames found:\n')
70-
duplicates.forEach(({ filename, paths }) => {
71-
console.error(` ${filename}:`)
72-
paths.forEach(p => console.error(` - ${p}`))
73-
})
74-
console.error('\nAll .md files must have unique names.')
75-
process.exit(1)
76-
}
59+
console.log('📦 Copying markdown files with preserved structure...\n')
7760

61+
// Ensure destination directory exists
7862
if (!fs.existsSync(DEST_DIR)) {
7963
fs.mkdirSync(DEST_DIR, { recursive: true })
8064
}
8165

82-
console.log(`Copying to ${DEST_DIR}...\n`)
83-
markdownFiles.forEach(srcPath => {
84-
const filename = path.basename(srcPath)
85-
const destPath = path.join(DEST_DIR, filename)
86-
fs.copyFileSync(srcPath, destPath)
87-
console.log(` ✓ ${filename}`)
66+
// Copy resources with preserved structure
67+
console.log('Copying from src/resources/...')
68+
const resourceFiles = copyMarkdownFiles(SRC_RESOURCES_DIR, DEST_DIR)
69+
70+
// Copy prompt .md files to prompts/ subdirectory
71+
console.log('Copying from src/prompts/...')
72+
const promptFiles = copyMarkdownFiles(SRC_PROMPTS_DIR, DEST_DIR, 'prompts')
73+
74+
const allFiles = [...resourceFiles, ...promptFiles]
75+
76+
console.log(`\nCopied ${allFiles.length} files:\n`)
77+
allFiles.forEach(file => {
78+
console.log(` ✓ ${file}`)
8879
})
8980

9081
console.log('\n✅ Resources copied successfully!')

src/prompts/enable-cache-components-prompt.md

Lines changed: 23 additions & 23 deletions
Original file line numberDiff line numberDiff line change
@@ -10,44 +10,44 @@ PROJECT: {{PROJECT_PATH}}
1010

1111
The following resources are available from the Next.js MCP server. Load them on-demand to reduce token usage:
1212

13-
- `nextjs16://knowledge/overview` - Critical errors AI agents make, quick reference (START HERE)
14-
- `nextjs16://knowledge/core-mechanics` - Fundamental paradigm shift, cacheComponents
15-
- `nextjs16://knowledge/public-caches` - Public cache mechanics using 'use cache'
16-
- `nextjs16://knowledge/private-caches` - Private cache mechanics using 'use cache: private'
17-
- `nextjs16://knowledge/runtime-prefetching` - Prefetch configuration and stale time rules
18-
- `nextjs16://knowledge/request-apis` - Async params, searchParams, cookies(), headers()
19-
- `nextjs16://knowledge/cache-invalidation` - updateTag(), revalidateTag() patterns
20-
- `nextjs16://knowledge/advanced-patterns` - cacheLife(), cacheTag(), draft mode
21-
- `nextjs16://knowledge/build-behavior` - What gets prerendered, static shells
22-
- `nextjs16://knowledge/error-patterns` - Common errors and solutions
23-
- `nextjs16://knowledge/test-patterns` - Real test-driven patterns from 125+ fixtures
24-
- `nextjs16://knowledge/reference` - Mental models, API reference, checklists
13+
- `cache-components://overview` - Critical errors AI agents make, quick reference (START HERE)
14+
- `cache-components://core-mechanics` - Fundamental paradigm shift, cacheComponents
15+
- `cache-components://public-caches` - Public cache mechanics using 'use cache'
16+
- `cache-components://private-caches` - Private cache mechanics using 'use cache: private'
17+
- `cache-components://runtime-prefetching` - Prefetch configuration and stale time rules
18+
- `cache-components://request-apis` - Async params, searchParams, cookies(), headers()
19+
- `cache-components://cache-invalidation` - updateTag(), revalidateTag() patterns
20+
- `cache-components://advanced-patterns` - cacheLife(), cacheTag(), draft mode
21+
- `cache-components://build-behavior` - What gets prerendered, static shells
22+
- `cache-components://error-patterns` - Common errors and solutions
23+
- `cache-components://test-patterns` - Real test-driven patterns from 125+ fixtures
24+
- `cache-components://reference` - Mental models, API reference, checklists
2525

2626
**How to Access Resources (MANDATORY - ALWAYS LOAD):**
2727

28-
Resources use the URI scheme `nextjs16://knowledge/...` and are served by this MCP server.
28+
Resources use the URI scheme `cache-components://...` and are served by this MCP server.
2929

3030
**CRITICAL: You MUST load resources at each phase phase - this is not optional.**
3131

3232
To load a resource, use the ReadMcpResourceTool with:
3333
- server: `"next-devtools"` (or whatever your server is configured as)
34-
- uri: `"nextjs16://knowledge/[resource-name]"` from the list above
34+
- uri: `"cache-components://[resource-name]"` from the list above
3535

3636
**MANDATORY Resource Loading Schedule:**
3737

3838
You MUST load these resources at the specified phases:
3939

40-
- **BEFORE Phase 1-2:** ALWAYS load `nextjs16://knowledge/overview` first
40+
- **BEFORE Phase 1-2:** ALWAYS load `cache-components://overview` first
4141
- Provides critical context and error patterns AI agents make
4242
- Must be loaded before any configuration changes
4343

4444
- **During Phase 5 (Error Fixing):** ALWAYS load error-specific resources as needed
45-
- When fixing blocking route errors → Load `nextjs16://knowledge/error-patterns`
46-
- When configuring caching → Load `nextjs16://knowledge/advanced-patterns`
47-
- When using dynamic params → Load `nextjs16://knowledge/core-mechanics`
45+
- When fixing blocking route errors → Load `cache-components://error-patterns`
46+
- When configuring caching → Load `cache-components://advanced-patterns`
47+
- When using dynamic params → Load `cache-components://core-mechanics`
4848
- Do NOT guess or use generic patterns - load the specific resource
4949

50-
- **During Phase 6 (Verification):** ALWAYS load `nextjs16://knowledge/build-behavior`
50+
- **During Phase 6 (Verification):** ALWAYS load `cache-components://build-behavior`
5151
- Provides build verification strategies and troubleshooting
5252

5353
**Why This Matters:**
@@ -213,7 +213,7 @@ Then navigate to **"Cache Components Examples"** → **"Decision Guide: Static v
213213

214214
BEFORE doing anything, you MUST load:
215215
```
216-
ReadMcpResourceTool(server="next-devtools", uri="nextjs16://knowledge/overview")
216+
ReadMcpResourceTool(server="next-devtools", uri="cache-components://overview")
217217
```
218218

219219
This provides critical context about Cache Components and common mistakes.
@@ -428,8 +428,8 @@ Build verification is always reliable and doesn't require dev server or browser
428428

429429
You MUST load these resources to understand errors and fix them correctly:
430430
```
431-
ReadMcpResourceTool(server="next-devtools", uri="nextjs16://knowledge/error-patterns")
432-
ReadMcpResourceTool(server="next-devtools", uri="nextjs16://knowledge/advanced-patterns")
431+
ReadMcpResourceTool(server="next-devtools", uri="cache-components://error-patterns")
432+
ReadMcpResourceTool(server="next-devtools", uri="cache-components://advanced-patterns")
433433
```
434434

435435
Do NOT guess or apply generic patterns. Use the exact code examples and strategies from these resources.
@@ -926,7 +926,7 @@ Then:
926926

927927
You MUST load:
928928
```
929-
ReadMcpResourceTool(server="next-devtools", uri="nextjs16://knowledge/build-behavior")
929+
ReadMcpResourceTool(server="next-devtools", uri="cache-components://build-behavior")
930930
```
931931

932932
This provides build verification strategies and troubleshooting guidance.
Lines changed: 2 additions & 41 deletions
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,6 @@
11
import { type InferSchema, type PromptMetadata } from "xmcp"
22
import { z } from "zod"
33
import { readResourceFile } from "../_internal/resource-path"
4-
import { loadKnowledgeResources } from "../_internal/resource-loader"
54

65
export const schema = {
76
project_path: z
@@ -21,48 +20,10 @@ export const metadata: PromptMetadata = {
2120
export default function getEnableCacheComponentsPrompt(args: InferSchema<typeof schema>): string {
2221
const projectPath = args.project_path || process.cwd()
2322

24-
let promptTemplate = readResourceFile("enable-cache-components-prompt.md")
25-
26-
const resources = loadKnowledgeResources()
27-
28-
function toTitleCase(camelCase: string): string {
29-
return camelCase
30-
.replace(/([A-Z])/g, " $1")
31-
.replace(/^./, (str) => str.toUpperCase())
32-
.trim()
33-
}
34-
35-
const resourceEntries = Object.entries(resources)
36-
.map(
37-
([key, content], index) => `
38-
## 📚 Resource ${index + 1}: ${toTitleCase(key)}
39-
${content}
40-
41-
---`
42-
)
43-
.join("\n")
44-
45-
const embeddedKnowledge = `
46-
# ═══════════════════════════════════════════════════════════════════
47-
# EMBEDDED KNOWLEDGE BASE (Preloaded for Cache Components Enablement)
48-
# ═══════════════════════════════════════════════════════════════════
49-
${resourceEntries}
50-
51-
# ═══════════════════════════════════════════════════════════════════
52-
# END OF KNOWLEDGE BASE
53-
# ═══════════════════════════════════════════════════════════════════
54-
`
23+
let promptTemplate = readResourceFile("prompts/enable-cache-components-prompt.md")
5524

25+
// Replace template variables
5626
promptTemplate = promptTemplate.replace(/{{PROJECT_PATH}}/g, projectPath)
5727

58-
const insertionPoint = promptTemplate.indexOf("---\n\n# ENABLE WORKFLOW:")
59-
if (insertionPoint !== -1) {
60-
promptTemplate =
61-
promptTemplate.slice(0, insertionPoint) +
62-
embeddedKnowledge +
63-
"\n" +
64-
promptTemplate.slice(insertionPoint)
65-
}
66-
6728
return promptTemplate
6829
}

src/prompts/upgrade-nextjs-16.ts

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -40,7 +40,7 @@ export default function getUpgradeNextjs16Prompt(args: InferSchema<typeof schema
4040

4141
const codemodCommandNote = `**Note**: Next.js 16 stable (version ${version}) is now available.`
4242

43-
let promptTemplate = readResourceFile("upgrade-nextjs-16-prompt.md")
43+
let promptTemplate = readResourceFile("prompts/upgrade-nextjs-16-prompt.md")
4444

4545
// TODO: load next.js16 knowledge base resources
4646
promptTemplate = promptTemplate.replace(/{{PROJECT_PATH}}/g, projectPath)
File renamed without changes.

src/resources/(nextjs16)/knowledge/01-core-mechanics.md renamed to src/resources/(cache-components)/01-core-mechanics.md

File renamed without changes.
File renamed without changes.

src/resources/(nextjs16)/knowledge/03-private-caches.md renamed to src/resources/(cache-components)/03-private-caches.md

File renamed without changes.

0 commit comments

Comments
 (0)