@nitra/cursor 1.8.151 → 1.8.152
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/AGENTS.template.md +8 -0
- package/README.md +7 -2
- package/bin/n-cursor.js +8 -3
- package/package.json +1 -1
- package/scripts/build-agents-commands.mjs +88 -0
package/AGENTS.template.md
CHANGED
|
@@ -18,6 +18,14 @@ The primary development rules are stored in the Cursor rules directory:
|
|
|
18
18
|
{{name}}
|
|
19
19
|
{{/skills}}
|
|
20
20
|
|
|
21
|
+
## Commands
|
|
22
|
+
|
|
23
|
+
Generated from the root `package.json` on each `npx @nitra/cursor` sync. Prefer `bun run <script>` for project scripts.
|
|
24
|
+
|
|
25
|
+
{{#commands}}
|
|
26
|
+
{{name}}
|
|
27
|
+
{{/commands}}
|
|
28
|
+
|
|
21
29
|
## Instructions for all agents
|
|
22
30
|
|
|
23
31
|
Before making changes, read the relevant rule files for the area you are working on.
|
package/README.md
CHANGED
|
@@ -63,7 +63,7 @@ CLI автоматично (команда завантаження правил
|
|
|
63
63
|
1. Знайде або створить `.n-cursor.json` у поточній директорії (із полем `$schema` на JSON Schema пакету; якщо файл уже є без коректного `$schema`, поле буде додано або оновлено при зчитуванні конфігу)
|
|
64
64
|
2. Створить директорію `.cursor/rules/`, якщо її ще немає
|
|
65
65
|
3. Скопіює кожне з перелічених у конфігу правило з `mdc/` установленого пакету і збереже файли з префіксом `n-`
|
|
66
|
-
4. Після оновлення файлів на диску згенерує в корені проєкту **`AGENTS.md`**: повний вміст береться з шаблону пакету `AGENTS.template.md`, а список правил у шаблоні формується з **усіх наявних файлів `*.mdc`** у `.cursor/rules/` (відсортовано за ім’ям)
|
|
66
|
+
4. Після оновлення файлів на диску згенерує в корені проєкту **`AGENTS.md`**: повний вміст береться з шаблону пакету `AGENTS.template.md`, а список правил у шаблоні формується з **усіх наявних файлів `*.mdc`** у `.cursor/rules/` (відсортовано за ім’ям); секція команд — з **`package.json`** кореня (див. `{{#commands}}` у шаблоні).
|
|
67
67
|
|
|
68
68
|
## Приклад виводу
|
|
69
69
|
|
|
@@ -114,13 +114,18 @@ npm/
|
|
|
114
114
|
|
|
115
115
|
Під час запуску CLI тіло між `{{#services}}` і `{{/services}}` повторюється для кожного `*.mdc` у `.cursor/rules/`; у `{{name}}` підставляється вже готовий markdown-рядок (наприклад `- .cursor/rules/n-text.mdc`).
|
|
116
116
|
|
|
117
|
-
3.
|
|
117
|
+
3. Для секції **Skills** використовуйте блок **`{{#skills}}` … `{{/skills}}`** з тим самим `{{name}}`: рядки формуються з каталогів у `.cursor/skills/` (див. також `buildSkillBulletItems` у `bin/n-cursor.js`).
|
|
118
|
+
|
|
119
|
+
4. Для секції **Commands** використовуйте **`{{#commands}}` … `{{/commands}}`**: список генерується з кореневого **`package.json`** (поле `scripts` — відомі ключі у фіксованому порядку, плюс додаткові `lint-*`) та завжди доповнюється рядками про **`npx @nitra/cursor`** і **`npx @nitra/cursor check`**. Логіка винесена в **`npm/scripts/build-agents-commands.mjs`**.
|
|
120
|
+
|
|
121
|
+
5. Після змін у шаблоні перевірте локально: у тестовому репозиторії з `.n-cursor.json` виконайте `npx`/`bunx` на зібраному пакеті або `node npm/bin/n-cursor.js` з кореня того репозиторію і переконайтеся, що **`AGENTS.md`** виглядає як очікується.
|
|
118
122
|
|
|
119
123
|
### Логіка в коді CLI
|
|
120
124
|
|
|
121
125
|
- Шлях до шаблону: поруч із `mdc/`, тобто `…/node_modules/@nitra/cursor/AGENTS.template.md` після встановлення пакету.
|
|
122
126
|
- Оновлення **`AGENTS.md`** виконується **після** циклу завантаження правил, щоб список відображав актуальний вміст `.cursor/rules/` на диску.
|
|
123
127
|
- Якщо каталогу `.cursor/rules/` немає або в ньому немає `*.mdc`, блок `{{#services}}` стає порожнім; решта шаблону все одно записується в **`AGENTS.md`**.
|
|
128
|
+
- Секція **`commands`** залежить лише від **`package.json` у корені cwd**; якщо файлу немає або `scripts` відсутній, у блоці лишаються мінімальні рядки (`bun i`, виклики CLI).
|
|
124
129
|
|
|
125
130
|
## Мета проекту
|
|
126
131
|
|
package/bin/n-cursor.js
CHANGED
|
@@ -18,6 +18,7 @@
|
|
|
18
18
|
*
|
|
19
19
|
* Файл AGENTS.md у корені: щоразу повністю перезаписується змістом з AGENTS.template.md
|
|
20
20
|
* пакету; список правил у шаблоні будується з файлів *.mdc у .cursor/rules поточного проєкту.
|
|
21
|
+
* Секція команд — з кореневого package.json (scripts) та фіксовані рядки про CLI синхрону/перевірок.
|
|
21
22
|
*
|
|
22
23
|
* Після завантаження: у .cursor/rules видаляються файли *.mdc з префіксом «n-» (керовані
|
|
23
24
|
* пакетом), яких немає у списку rules у .n-cursor.json. Інші .mdc у цій директорії залишаються.
|
|
@@ -45,6 +46,7 @@ import { basename, dirname, join } from 'node:path'
|
|
|
45
46
|
import { cwd } from 'node:process'
|
|
46
47
|
import { fileURLToPath } from 'node:url'
|
|
47
48
|
|
|
49
|
+
import { buildAgentsCommandBulletItems } from '../scripts/build-agents-commands.mjs'
|
|
48
50
|
import { detectAutoRulesAndSkills, mergeConfigWithAutoDetected, normalizeIdList } from '../scripts/auto-rules.mjs'
|
|
49
51
|
import { ensureNitraCursorInRootDevDependencies } from '../scripts/ensure-nitra-cursor-dev-dependencies.mjs'
|
|
50
52
|
import { upgradeNitraCursorToLatestAndBunInstall } from '../scripts/upgrade-nitra-cursor-and-install.mjs'
|
|
@@ -424,19 +426,21 @@ function expandMustacheSection(template, section, items, prop) {
|
|
|
424
426
|
}
|
|
425
427
|
|
|
426
428
|
/**
|
|
427
|
-
* Підставляє у вміст AGENTS.template.md список шляхів до файлів
|
|
429
|
+
* Підставляє у вміст AGENTS.template.md список шляхів до файлів правил, skills і команд з package.json
|
|
428
430
|
* @param {string} templateText вміст AGENTS.template.md
|
|
429
431
|
* @param {string[]} mdcBasenames імена файлів (*.mdc) з .cursor/rules
|
|
430
432
|
* @param {{ name: string }[]} skillItems рядки для секції Skills
|
|
433
|
+
* @param {{ name: string }[]} commandItems рядки для секції commands
|
|
431
434
|
* @returns {string} готовий markdown для AGENTS.md
|
|
432
435
|
*/
|
|
433
|
-
function renderAgentsTemplate(templateText, mdcBasenames, skillItems) {
|
|
436
|
+
function renderAgentsTemplate(templateText, mdcBasenames, skillItems, commandItems) {
|
|
434
437
|
let result = templateText
|
|
435
438
|
const serviceItems = mdcBasenames.map(mdcName => ({
|
|
436
439
|
name: `- ${RULES_DIR}/${mdcName}`
|
|
437
440
|
}))
|
|
438
441
|
result = expandMustacheSection(result, 'services', serviceItems, 'name')
|
|
439
442
|
result = expandMustacheSection(result, 'skills', skillItems, 'name')
|
|
443
|
+
result = expandMustacheSection(result, 'commands', commandItems, 'name')
|
|
440
444
|
return result
|
|
441
445
|
}
|
|
442
446
|
|
|
@@ -650,7 +654,8 @@ async function syncAgentsMd(agentsTemplatePath = BUNDLED_AGENTS_TEMPLATE_PATH) {
|
|
|
650
654
|
const templateText = await readFile(agentsTemplatePath, 'utf8')
|
|
651
655
|
const mdcFiles = await listProjectRulesMdcFiles()
|
|
652
656
|
const skillItems = await buildSkillBulletItems()
|
|
653
|
-
const
|
|
657
|
+
const commandItems = await buildAgentsCommandBulletItems(cwd())
|
|
658
|
+
const body = renderAgentsTemplate(templateText, mdcFiles, skillItems, commandItems)
|
|
654
659
|
const agentsPath = join(cwd(), AGENTS_FILE)
|
|
655
660
|
const hadFile = existsSync(agentsPath)
|
|
656
661
|
const out = body.endsWith('\n') ? body : `${body}\n`
|
package/package.json
CHANGED
|
@@ -0,0 +1,88 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Формує markdown-рядки для секції «Команди» у AGENTS.md.
|
|
3
|
+
*
|
|
4
|
+
* Джерело істини — `package.json` у корені цільового репозиторію: з поля `scripts` беруться відомі ключі
|
|
5
|
+
* у стабільному порядку, додатково — усі `lint-*`, яких не було в основному списку.
|
|
6
|
+
*
|
|
7
|
+
* Наприкінці завжди додаються рядки про CLI `@nitra/cursor` (синхрон правил / programmatic check),
|
|
8
|
+
* на початку — рекомендована команда `bun i` за конвенціями monorepo.
|
|
9
|
+
*/
|
|
10
|
+
import { existsSync } from 'node:fs'
|
|
11
|
+
import { readFile } from 'node:fs/promises'
|
|
12
|
+
import { join } from 'node:path'
|
|
13
|
+
|
|
14
|
+
const PACKAGE_NAME = '@nitra/cursor'
|
|
15
|
+
const AGENTS_MD = 'AGENTS.md'
|
|
16
|
+
|
|
17
|
+
/** Порядок виводу скриптів із `package.json` (лише ті, що реально існують). */
|
|
18
|
+
const SCRIPT_KEYS_ORDER = /** @type {const} */ ([
|
|
19
|
+
'test',
|
|
20
|
+
'lint',
|
|
21
|
+
'lint-js',
|
|
22
|
+
'lint-text',
|
|
23
|
+
'lint-ga',
|
|
24
|
+
'lint-k8s',
|
|
25
|
+
'lint-docker',
|
|
26
|
+
'start',
|
|
27
|
+
'dev',
|
|
28
|
+
'build'
|
|
29
|
+
])
|
|
30
|
+
|
|
31
|
+
/**
|
|
32
|
+
* Зчитує `scripts` з `package.json` у `projectRoot` або повертає порожній об'єкт.
|
|
33
|
+
* @param {string} projectRoot абсолютний шлях до кореня репозиторію
|
|
34
|
+
* @returns {Promise<Record<string, string>>} об'єкт скриптів
|
|
35
|
+
*/
|
|
36
|
+
async function readPackageScripts(projectRoot) {
|
|
37
|
+
const pkgPath = join(projectRoot, 'package.json')
|
|
38
|
+
if (!existsSync(pkgPath)) {
|
|
39
|
+
return {}
|
|
40
|
+
}
|
|
41
|
+
try {
|
|
42
|
+
const raw = await readFile(pkgPath, 'utf8')
|
|
43
|
+
const pkg = JSON.parse(raw)
|
|
44
|
+
if (pkg && typeof pkg === 'object' && pkg.scripts && typeof pkg.scripts === 'object') {
|
|
45
|
+
return /** @type {Record<string, string>} */ (pkg.scripts)
|
|
46
|
+
}
|
|
47
|
+
} catch {
|
|
48
|
+
// некоректний JSON або IO — секція команд лишиться з мінімумом (bun i + npx)
|
|
49
|
+
}
|
|
50
|
+
return {}
|
|
51
|
+
}
|
|
52
|
+
|
|
53
|
+
/**
|
|
54
|
+
* Повертає елементи для Mustache-секції `commands` у AGENTS.template.md.
|
|
55
|
+
* @param {string} projectRoot абсолютний шлях до кореня репозиторію (зазвичай `process.cwd()`)
|
|
56
|
+
* @returns {Promise<{ name: string }[]>} рядки з полем `name` для `expandMustacheSection`
|
|
57
|
+
*/
|
|
58
|
+
export async function buildAgentsCommandBulletItems(projectRoot) {
|
|
59
|
+
const scripts = await readPackageScripts(projectRoot)
|
|
60
|
+
const items = /** @type {{ name: string }[]} */ ([])
|
|
61
|
+
|
|
62
|
+
items.push({ name: `- **Залежності**: \`bun i\`` })
|
|
63
|
+
|
|
64
|
+
const added = new Set()
|
|
65
|
+
|
|
66
|
+
for (const key of SCRIPT_KEYS_ORDER) {
|
|
67
|
+
if (typeof scripts[key] === 'string' && scripts[key].length > 0) {
|
|
68
|
+
items.push({ name: `- **${key}**: \`bun run ${key}\`` })
|
|
69
|
+
added.add(key)
|
|
70
|
+
}
|
|
71
|
+
}
|
|
72
|
+
|
|
73
|
+
const lintExtraKeys = Object.keys(scripts)
|
|
74
|
+
.filter(k => k.startsWith('lint-') && !added.has(k) && typeof scripts[k] === 'string')
|
|
75
|
+
.toSorted((a, b) => a.localeCompare(b))
|
|
76
|
+
|
|
77
|
+
for (const key of lintExtraKeys) {
|
|
78
|
+
items.push({ name: `- **${key}**: \`bun run ${key}\`` })
|
|
79
|
+
added.add(key)
|
|
80
|
+
}
|
|
81
|
+
|
|
82
|
+
items.push({
|
|
83
|
+
name: `- **Оновити правила та ${AGENTS_MD}** (після змін у правилах/шаблоні CLI): \`npx ${PACKAGE_NAME}\``
|
|
84
|
+
})
|
|
85
|
+
items.push({ name: `- **Перевірки правил (programmatic)**: \`npx ${PACKAGE_NAME} check\`` })
|
|
86
|
+
|
|
87
|
+
return items
|
|
88
|
+
}
|