@7n/rules 1.6.0 → 1.7.1
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/CHANGELOG.md +14 -0
- package/package.json +1 -2
- package/rules/abie/http_route_base/http_route_base.mdc +23 -1
- package/rules/adr/madr_format/concern.json +1 -0
- package/rules/adr/madr_format/madr_format.mdc +119 -0
- package/rules/bun/bunfig/bunfig.mdc +5 -0
- package/rules/bun/lint-surface/concern.json +3 -0
- package/rules/bun/lint-surface/lint-surface.mdc +13 -0
- package/rules/capacitor/platforms/docs/main.md +1 -1
- package/rules/capacitor/platforms/main.mjs +5 -1
- package/rules/capacitor/platforms/platforms.mdc +108 -0
- package/rules/changelog/consistency/comparison-models.mdc +46 -0
- package/rules/changelog/consistency/consistency.mdc +35 -0
- package/rules/docker/main.mdc +235 -2
- package/rules/image-avif/avif_generation/avif_generation.mdc +14 -0
- package/rules/js/check/check.mdc +26 -0
- package/rules/js/file-extensions/concern.json +3 -0
- package/rules/js/file-extensions/file-extensions.mdc +12 -0
- package/rules/js/jscpd_config/jscpd_config.mdc +28 -0
- package/rules/js/knip/knip.mdc +15 -0
- package/rules/js/utils_imports/utils_imports.mdc +15 -0
- package/rules/js-bun-db/connection/concern.json +3 -0
- package/rules/js-bun-db/connection/connection.mdc +42 -0
- package/rules/js-bun-db/package_json/package_json.mdc +15 -1
- package/rules/js-bun-db/pg_format_identifiers/concern.json +3 -0
- package/rules/js-bun-db/pg_format_identifiers/pg_format_identifiers.mdc +104 -0
- package/rules/js-bun-db/safety/safety.mdc +458 -0
- package/rules/js-mssql/main.mdc +130 -0
- package/rules/js-mssql/mssql-tvp/concern.json +3 -0
- package/rules/js-mssql/mssql-tvp/mssql-tvp.mdc +77 -0
- package/rules/js-run/configmap/configmap.mdc +6 -0
- package/rules/js-run/jsconfig/jsconfig.mdc +23 -0
- package/rules/js-run/package_json/package_json.mdc +6 -0
- package/rules/js-run/project-structure/concern.json +3 -0
- package/rules/js-run/project-structure/project-structure.mdc +11 -0
- package/rules/js-run/runtime/runtime.mdc +170 -0
- package/rules/js-run/scope/concern.json +3 -0
- package/rules/js-run/scope/scope.mdc +11 -0
- package/rules/k8s/hasura_configmap/hasura_configmap.mdc +6 -0
- package/rules/k8s/hpa_pdb/hpa_pdb.mdc +134 -0
- package/rules/k8s/kubeconform/kubeconform.mdc +38 -0
- package/rules/k8s/kustomization/kustomization.mdc +73 -0
- package/rules/k8s/main.mdc +68 -0
- package/rules/k8s/manifest/manifest.mdc +37 -0
- package/rules/k8s/manifests/docs/fix-manifests.md +3 -1
- package/rules/k8s/manifests/fix-manifests.mjs +11 -0
- package/rules/k8s/manifests/main.mjs +28 -0
- package/rules/k8s/network_policy/network_policy.mdc +33 -0
- package/rules/nginx-default-tpl/http-route/concern.json +1 -0
- package/rules/nginx-default-tpl/http-route/http-route.mdc +54 -0
- package/rules/nginx-default-tpl/template/template.mdc +152 -0
- package/rules/php/tooling/tooling.mdc +7 -6
- package/rules/python/pyproject_toml/pyproject_toml.mdc +17 -1
- package/rules/python/tooling/tooling.mdc +9 -10
- package/rules/rego/main.mdc +14 -0
- package/rules/rust/check/check.mdc +16 -0
- package/rules/style/admin_table/admin_table.mdc +88 -0
- package/rules/style/admin_table/concern.json +7 -0
- package/rules/style/admin_table/docs/index.md +9 -0
- package/rules/style/admin_table/docs/main.md +14 -0
- package/rules/style/admin_table/main.mjs +46 -0
- package/rules/style/colors/colors.mdc +21 -0
- package/rules/style/colors/concern.json +3 -0
- package/rules/style/gap/concern.json +7 -0
- package/rules/style/gap/docs/index.md +9 -0
- package/rules/style/gap/docs/main.md +15 -0
- package/rules/style/gap/gap.mdc +22 -0
- package/rules/style/gap/main.mjs +51 -0
- package/rules/style/quasar/concern.json +3 -0
- package/rules/style/quasar/quasar.mdc +7 -0
- package/rules/style/quasar_fixes/concern.json +7 -0
- package/rules/style/quasar_fixes/docs/index.md +9 -0
- package/rules/style/quasar_fixes/docs/main.md +16 -0
- package/rules/style/quasar_fixes/main.mjs +57 -0
- package/rules/style/quasar_fixes/quasar_fixes.mdc +32 -0
- package/rules/tauri/tool_surface/concern.json +16 -0
- package/rules/tauri/tool_surface/docs/index.md +9 -0
- package/rules/tauri/tool_surface/docs/main.md +24 -0
- package/rules/tauri/tool_surface/main.mjs +145 -0
- package/rules/tauri/tool_surface/tool_surface.mdc +29 -0
- package/rules/test/vitest-api-conventions/concern.json +7 -0
- package/rules/test/vitest-api-conventions/docs/index.md +9 -0
- package/rules/test/vitest-api-conventions/docs/main.md +40 -0
- package/rules/test/vitest-api-conventions/main.mjs +186 -0
- package/rules/test/vitest-api-conventions/vitest-api-conventions.mdc +129 -0
- package/rules/text/cspell/cspell.mdc +18 -0
- package/rules/text/markdownlint/markdownlint.mdc +4 -0
- package/rules/text/run-dotenv-linter/run-dotenv-linter.mdc +17 -0
- package/rules/text/run-shellcheck/run-shellcheck.mdc +17 -0
- package/rules/text/run-v8r/run-v8r.mdc +23 -0
- package/rules/vue/composition-api/composition-api.mdc +82 -0
- package/rules/vue/composition-api/concern.json +3 -0
- package/rules/vue/main.mdc +1 -1
- package/rules/vue/nheader-layout/concern.json +3 -0
- package/rules/vue/nheader-layout/nheader-layout.mdc +171 -0
- package/rules/vue/packages/packages.mdc +56 -0
- package/rules/vue/quasar-ui/concern.json +3 -0
- package/rules/vue/quasar-ui/quasar-ui.mdc +32 -0
- package/rules/vue/structure/concern.json +3 -0
- package/rules/vue/structure/structure.mdc +101 -0
- package/rules/vue/testing/concern.json +3 -0
- package/rules/vue/testing/testing.mdc +40 -0
- package/rules/vue/tfm-translations/concern.json +7 -0
- package/rules/vue/tfm-translations/docs/main.md +29 -0
- package/rules/vue/tfm-translations/main.mjs +55 -0
- package/rules/vue/tfm-translations/tfm-translations.mdc +32 -0
- package/rules/vue/vite-config/concern.json +3 -0
- package/rules/vue/vite-config/vite-config.mdc +153 -0
- package/rules/vue/vite-env/concern.json +3 -0
- package/rules/vue/vite-env/vite-env.mdc +61 -0
- package/scripts/docs/skills-cli.md +3 -3
- package/scripts/lib/acp-runner.mjs +23 -28
- package/scripts/skills-cli.mjs +35 -26
|
@@ -0,0 +1,153 @@
|
|
|
1
|
+
## Vite-конфігурація: VueMacros, AutoImport, Layouts
|
|
2
|
+
|
|
3
|
+
Потрібно використовувати **Vite версії 8.1 та вище** для frontend проекту на Vue.
|
|
4
|
+
|
|
5
|
+
Потрібно використовувати **`unplugin-auto-import`** для автоматичного імпортування компонентів, composables, utils та інших функцій і прибирати з файлів усередині Vite проектів відповідні ручні імпорти, зокрема рядки виду `import { … } from 'vue'` — API Vue (`ref`, `computed`, `watch` тощо) мають підставлятися через auto-import, а не дублюватися явним імпортом з модуля `vue`.
|
|
6
|
+
|
|
7
|
+
**Виняток — бібліотеки компонентів (`vue` у `peerDependencies`).** Увесь стек auto-import застосовується лише коли `vue` підключено як звичайну `dependencies`. Якщо ж пакет оголошує `vue` у `peerDependencies` — це проєкт-бібліотека компонентів: його джерела споживаються Vite-додатками і **не** проходять через `unplugin-auto-import` споживача. Тому до таких пакетів **не** застосовуються: заборона явних `import { ref, computed, … } from 'vue'` (вони обовʼязкові), вимога `'vue'` у `AutoImport.imports`, а також вимоги наявності `VueMacros` / `AutoImport` у `vite.config`. Решта перевірок (заборона `esbuild`, `process.env.npm_lifecycle_event` тощо) лишаються. Тригер винятку — `isVueComponentLibraryPkg` у `npm/rules/vue/packages/main.mjs`.
|
|
8
|
+
|
|
9
|
+
Потрібно використовувати **`vite-plugin-vue-layouts-next`** для автоматичного імпортування layout компонентів.
|
|
10
|
+
|
|
11
|
+
### Це вже перевіряється автоматично
|
|
12
|
+
|
|
13
|
+
Увесь зміст цього файлу — вже реалізовані, а не лише документовані, перевірки:
|
|
14
|
+
|
|
15
|
+
- **Обов'язкові залежності** (`vite` мажор ≥ 8 і мінор ≥ 1, `@vitejs/plugin-vue`, `vue-macros`, `unplugin-auto-import`, `vite-plugin-vue-layouts-next`) і **заборона** `esbuild`/`vitest`/`jsdom` у `package.json` — Rego-пакет `vue.package_json` (`npm/rules/vue/package_json/package_json.rego`, концерн `package_json`).
|
|
16
|
+
- **`vite.config.{js,ts,mjs}`**: наявність `VueMacros`, `AutoImport` (і `'vue'` у його `imports`, якщо застосовний), `css: { transformer: 'lightningcss' }`, заборона `esbuild`, заборона `process.env.npm_lifecycle_event` (Bun-сумісність) — JS-концерн `packages` (`npm/rules/vue/packages/main.mjs`, функція `checkViteConfig`).
|
|
17
|
+
- **`.vscode/extensions.json`** з рекомендацією `Vue.volar` — той самий концерн `packages` (`checkVueVolarRecommendation`).
|
|
18
|
+
|
|
19
|
+
Цей concern (`vite-config`) залишається **docs-only** — він не додає нової перевірки, а лише зберігає розгорнутий еталонний приклад `vite.config.js`/`package.json` і пояснення для людини; фактичний gate — вище.
|
|
20
|
+
|
|
21
|
+
### Еталонний `vite.config.js`
|
|
22
|
+
|
|
23
|
+
```javascript title="vite.config.js"
|
|
24
|
+
import Vue from '@vitejs/plugin-vue'
|
|
25
|
+
import VueMacros from 'vue-macros/vite'
|
|
26
|
+
import { defineConfig } from 'vite'
|
|
27
|
+
import AutoImport from 'unplugin-auto-import/vite'
|
|
28
|
+
import Layouts from 'vite-plugin-vue-layouts-next'
|
|
29
|
+
|
|
30
|
+
export default defineConfig({
|
|
31
|
+
plugins: [
|
|
32
|
+
AutoImport({
|
|
33
|
+
imports: [
|
|
34
|
+
// presets
|
|
35
|
+
'vue',
|
|
36
|
+
'vue-router',
|
|
37
|
+
'quasar',
|
|
38
|
+
'pinia',
|
|
39
|
+
// custom
|
|
40
|
+
{
|
|
41
|
+
'@nitra/vite-boot/apollo': [
|
|
42
|
+
// named imports
|
|
43
|
+
'gql',
|
|
44
|
+
'useQuery',
|
|
45
|
+
'useMutation',
|
|
46
|
+
'useSubscription'
|
|
47
|
+
],
|
|
48
|
+
'@nitra/consola': [
|
|
49
|
+
// named imports
|
|
50
|
+
'createLogger' // import { createLogger } from '@nitra/consola'
|
|
51
|
+
]
|
|
52
|
+
}
|
|
53
|
+
]
|
|
54
|
+
}),
|
|
55
|
+
VueMacros({
|
|
56
|
+
plugins: {
|
|
57
|
+
vue: Vue()
|
|
58
|
+
}
|
|
59
|
+
}),
|
|
60
|
+
Layouts()
|
|
61
|
+
]
|
|
62
|
+
})
|
|
63
|
+
```
|
|
64
|
+
|
|
65
|
+
### `npm_lifecycle_event` (Bun-сумісність)
|
|
66
|
+
|
|
67
|
+
У більшості проектів у файлі `vite.config.js` є конструкція виду:
|
|
68
|
+
|
|
69
|
+
```javascript
|
|
70
|
+
switch (process.env.npm_lifecycle_event) {
|
|
71
|
+
case 'start-remote-tr': {
|
|
72
|
+
```
|
|
73
|
+
|
|
74
|
+
Вона перестала працювати з новим Bun. Тепер її треба обрамити у функцію і передавати `mode`:
|
|
75
|
+
|
|
76
|
+
```javascript title="vite.config.js"
|
|
77
|
+
function getProxy(mode) {
|
|
78
|
+
const proxy = {}
|
|
79
|
+
|
|
80
|
+
switch (mode) {
|
|
81
|
+
case 'remote-tr': {
|
|
82
|
+
proxy['^/auth/.*'] = 'https://tr.efes.cloud'
|
|
83
|
+
proxy['/file-link/'] = 'https://tr.efes.cloud'
|
|
84
|
+
break
|
|
85
|
+
}
|
|
86
|
+
default: {
|
|
87
|
+
proxy['^/auth/.*'] = 'https://dev.efes.cloud'
|
|
88
|
+
proxy['/file-link/'] = 'https://dev.efes.cloud'
|
|
89
|
+
}
|
|
90
|
+
}
|
|
91
|
+
return proxy
|
|
92
|
+
}
|
|
93
|
+
```
|
|
94
|
+
|
|
95
|
+
```javascript title="vite.config.js"
|
|
96
|
+
export default defineConfig(({ mode, command }) => {
|
|
97
|
+
// ...
|
|
98
|
+
server: {
|
|
99
|
+
proxy: getProxy(mode)
|
|
100
|
+
}
|
|
101
|
+
})
|
|
102
|
+
```
|
|
103
|
+
|
|
104
|
+
### CSS-трансформер: lightningcss (обов'язково)
|
|
105
|
+
|
|
106
|
+
У `vite.config` має бути `css: { transformer: 'lightningcss' }`:
|
|
107
|
+
|
|
108
|
+
```javascript title="vite.config.js"
|
|
109
|
+
export default defineConfig({
|
|
110
|
+
css: {
|
|
111
|
+
transformer: 'lightningcss'
|
|
112
|
+
},
|
|
113
|
+
// ...
|
|
114
|
+
})
|
|
115
|
+
```
|
|
116
|
+
|
|
117
|
+
Lightningcss ~18% швидше за sass-трансформер на типовому Vue+Quasar-проєкті. Потрібний `lightningcss` у `devDependencies`.
|
|
118
|
+
|
|
119
|
+
**Виняток:** бібліотеки компонентів (`vue` у `peerDependencies`) від цієї вимоги звільнені — вони не збираються напряму.
|
|
120
|
+
|
|
121
|
+
### esbuild заборонено
|
|
122
|
+
|
|
123
|
+
У проєкті не має бути залежності `esbuild` і згадок `esbuild` у конфігах/коді. Якщо десь є налаштування або інструкції під `esbuild` — заміни на **rolldown**.
|
|
124
|
+
|
|
125
|
+
### Еталонний `package.json`
|
|
126
|
+
|
|
127
|
+
мінімальний повний `package.json` для Vite + Vue + `vue-macros` (версії підлаштуй під проєкт):
|
|
128
|
+
|
|
129
|
+
```json title="package.json"
|
|
130
|
+
{
|
|
131
|
+
"name": "my-vue-app",
|
|
132
|
+
"private": true,
|
|
133
|
+
"type": "module",
|
|
134
|
+
"dependencies": {
|
|
135
|
+
"vue": "^3.6.12"
|
|
136
|
+
},
|
|
137
|
+
"devDependencies": {
|
|
138
|
+
"vite": "^8.1.0",
|
|
139
|
+
"@vitejs/plugin-vue": "^6.0.0",
|
|
140
|
+
"vue-macros": "^3.1.2"
|
|
141
|
+
}
|
|
142
|
+
}
|
|
143
|
+
```
|
|
144
|
+
|
|
145
|
+
### VS Code розширення
|
|
146
|
+
|
|
147
|
+
У файлі `.vscode/extensions.json` потрібна рекомендація для Vue:
|
|
148
|
+
|
|
149
|
+
```json title=".vscode/extensions.json"
|
|
150
|
+
{
|
|
151
|
+
"recommendations": ["Vue.volar"]
|
|
152
|
+
}
|
|
153
|
+
```
|
|
@@ -0,0 +1,61 @@
|
|
|
1
|
+
## Vite client types (Volar, імпорти асетів)
|
|
2
|
+
|
|
3
|
+
Без типів **Vite** редактор (Volar / TypeScript) не знає, що імпорт статичного файлу (`import url from './hero.avif'`, `*.png`, `*.svg` тощо) відповідає модулю з `string` URL. Тоді у `.vue` з'являється помилка на кшталт **Cannot find module '…' or its corresponding type declarations**.
|
|
4
|
+
|
|
5
|
+
У **кожному** workspace-пакеті з **Vue + Vite** обов'язково:
|
|
6
|
+
|
|
7
|
+
1. **`src/vite-env.d.ts`** — рівно з посиланням на клієнтські типи Vite (одного рядка достатньо):
|
|
8
|
+
|
|
9
|
+
```ts title="src/vite-env.d.ts"
|
|
10
|
+
/// <reference types="vite/client" />
|
|
11
|
+
```
|
|
12
|
+
|
|
13
|
+
Так підтягуються декларації з `vite/client.d.ts` (`declare module '*.avif'`, `*.png`, …).
|
|
14
|
+
|
|
15
|
+
2. **Корінь пакета:** **`jsconfig.json`** із **`include`**, що охоплює `src` (наприклад `"include": ["src/**/*"]`), щоб мова служби бачила `vite-env.d.ts` і SFC.
|
|
16
|
+
|
|
17
|
+
Мінімальний приклад для JS-пакета:
|
|
18
|
+
|
|
19
|
+
```json title="jsconfig.json"
|
|
20
|
+
{
|
|
21
|
+
"compilerOptions": {
|
|
22
|
+
"target": "ESNext",
|
|
23
|
+
"module": "ESNext",
|
|
24
|
+
"moduleResolution": "bundler",
|
|
25
|
+
"lib": ["ESNext", "DOM", "DOM.Iterable"],
|
|
26
|
+
"jsx": "preserve",
|
|
27
|
+
"strict": true,
|
|
28
|
+
"noEmit": true,
|
|
29
|
+
"skipLibCheck": true,
|
|
30
|
+
"resolveJsonModule": true,
|
|
31
|
+
"isolatedModules": true,
|
|
32
|
+
"allowJs": true
|
|
33
|
+
},
|
|
34
|
+
"include": ["src/**/*"]
|
|
35
|
+
}
|
|
36
|
+
```
|
|
37
|
+
|
|
38
|
+
**Не** звужуй без потреби **`compilerOptions.types`** до `["vite/client"]`: це може відрізати інші пакети з `@types` і зламати інші підказки. Достатньо `/// <reference types="vite/client" />` у `vite-env.d.ts` і коректного `include`.
|
|
39
|
+
|
|
40
|
+
### Ця частина вже перевіряється автоматично
|
|
41
|
+
|
|
42
|
+
Наявність `src/vite-env.d.ts` з коректним `/// <reference types="vite/client" />` і наявність `jsconfig.json` у корені пакета — вже реалізований JS-концерн `packages` (`npm/rules/vue/packages/main.mjs`, функція `checkViteClientEnvAndEditorConfig`). Цей concern (`vite-env`) не дублює перевірку — лишається docs-only довідкою з еталонним прикладом.
|
|
43
|
+
|
|
44
|
+
## Статичні файли — BASE_URL
|
|
45
|
+
|
|
46
|
+
Для підключення статичних файлів не використовуй відносні шляхи. Завжди будуй URL через `import.meta.env.BASE_URL`:
|
|
47
|
+
|
|
48
|
+
```vue
|
|
49
|
+
<!-- Погано -->
|
|
50
|
+
<img src="/logo.png" />
|
|
51
|
+
<img src="./assets/logo.png" />
|
|
52
|
+
|
|
53
|
+
<!-- Добре -->
|
|
54
|
+
<img :src="baseUrl + 'logo.png'" />
|
|
55
|
+
```
|
|
56
|
+
|
|
57
|
+
```javascript
|
|
58
|
+
const baseUrl = import.meta.env.BASE_URL
|
|
59
|
+
```
|
|
60
|
+
|
|
61
|
+
Ця вимога **не** перевіряється механічно: рядок-специфікатор `src` може легітимно вказувати на зовнішній URL, дата-URI чи інший валідний шлях, і однозначно відрізнити «статичний асет проекту» від інших випадків без хибних спрацювань неможливо — залишається на розсуд ревʼю.
|
|
@@ -3,7 +3,7 @@ type: JS Module
|
|
|
3
3
|
title: skills-cli.mjs
|
|
4
4
|
resource: npm/scripts/skills-cli.mjs
|
|
5
5
|
docgen:
|
|
6
|
-
crc:
|
|
6
|
+
crc: 1a8f83e4
|
|
7
7
|
model: omlx/gemma-4-e4b-it-OptiQ-4bit
|
|
8
8
|
---
|
|
9
9
|
|
|
@@ -30,7 +30,7 @@ runSkillsCli виконує логіку командного інтерфейс
|
|
|
30
30
|
|
|
31
31
|
## Гарантії поведінки
|
|
32
32
|
|
|
33
|
-
- Сам модуль лише читає файли й збирає промпт; **виконання** делегується агенту: `pi` (вбудований, мутує дерево, запускає bash) або зовнішньому ACP-агенту `cursor`/`codex`/`claude` через `runAcpRunner` (`./lib/acp-runner.mjs`) — JSON-RPC поверх stdio (`cursor-agent acp`,
|
|
33
|
+
- Сам модуль лише читає файли й збирає промпт; **виконання** делегується агенту: `pi` (вбудований, мутує дерево, запускає bash) або зовнішньому ACP-агенту `cursor`/`codex`/`claude` через `runAcpRunner` (`./lib/acp-runner.mjs`) — JSON-RPC поверх stdio (`cursor-agent acp`, бандловані адаптери `@agentclientprotocol/codex-acp` і `@agentclientprotocol/claude-agent-acp`), а не сирий `stdin`/`stdout`-піпінг.
|
|
34
34
|
- Тира моделі для `pi`-runner береться з `main.json.tier` скіла (дефолт `max`).
|
|
35
|
-
- ACP-раннер
|
|
35
|
+
- ACP-раннер автоапрувляє `session/request_permission` (без інтерактивних питань) — паритет із колишнім non-interactive режимом; `Client`-реалізація читає/пише файли напряму через `node:fs`.
|
|
36
36
|
- Лише `claude` — deprecated: друкує попередження й лишається як fallback, доки не налаштовано pi-модель. `cursor`/`codex` — повноцінні раннери без попередження.
|
|
@@ -1,18 +1,18 @@
|
|
|
1
1
|
/**
|
|
2
|
-
*
|
|
3
|
-
* agentclientprotocol.com) — JSON-RPC поверх stdio
|
|
4
|
-
* `stdin`/`stdout`-передавання через pipe CLI.
|
|
2
|
+
* Deprecated JS ACP-шим для `skill claude` (Agent Client Protocol,
|
|
3
|
+
* agentclientprotocol.com) — JSON-RPC поверх stdio.
|
|
5
4
|
*
|
|
6
|
-
*
|
|
7
|
-
*
|
|
8
|
-
*
|
|
9
|
-
*
|
|
10
|
-
*
|
|
5
|
+
* `cursor`/`codex` мігрували на `@7n/llm-lib/acp` (napi-міст до
|
|
6
|
+
* `llm_cascade::acp` — та сама протокольна логіка, але в Rust, без
|
|
7
|
+
* дублювання в JS). `claude` лишається тут як окремий JS-шим, бо Rust-крейт
|
|
8
|
+
* `AcpAgentKind` його не моделює (лише `Cursor`/`Codex`); підʼєднання йде
|
|
9
|
+
* через офіційний TS SDK `@zed-industries/agent-client-protocol`, а дозволи
|
|
10
|
+
* на tool-calls (`session/request_permission`) автоматично схвалюються без
|
|
11
|
+
* участі людини — паритет із колишнім non-interactive `-p`-режимом
|
|
12
|
+
* (full user-trust, без write-guard, як задокументовано в `@7n/llm-lib/agent-skill`).
|
|
11
13
|
*
|
|
12
|
-
* `
|
|
13
|
-
* `
|
|
14
|
-
* `@agentclientprotocol/claude-agent-acp`), що вбудовують свій рушій — зовнішній
|
|
15
|
-
* бінарник `codex`/`claude` у PATH більше не потрібен.
|
|
14
|
+
* `claude` — офіційний адаптер (`@agentclientprotocol/claude-agent-acp`), що
|
|
15
|
+
* вбудовує свій рушій — зовнішній бінарник `claude` у PATH не потрібен.
|
|
16
16
|
*/
|
|
17
17
|
|
|
18
18
|
import { spawn } from 'node:child_process'
|
|
@@ -25,13 +25,11 @@ import { Readable, Writable } from 'node:stream'
|
|
|
25
25
|
const require = createRequire(import.meta.url)
|
|
26
26
|
|
|
27
27
|
/**
|
|
28
|
-
* Команда запуску ACP-агента на провайдер.
|
|
29
|
-
*
|
|
30
|
-
* @type {Record<'
|
|
28
|
+
* Команда запуску ACP-агента на провайдер. Резолвиться з `bin`-запису
|
|
29
|
+
* вбудованого npm-пакета-адаптера.
|
|
30
|
+
* @type {Record<'claude', { adapterPackage: string }>}
|
|
31
31
|
*/
|
|
32
32
|
export const ACP_AGENT_COMMANDS = {
|
|
33
|
-
cursor: { bin: 'cursor-agent', args: ['acp'] },
|
|
34
|
-
codex: { adapterPackage: '@agentclientprotocol/codex-acp' },
|
|
35
33
|
claude: { adapterPackage: '@agentclientprotocol/claude-agent-acp' }
|
|
36
34
|
}
|
|
37
35
|
|
|
@@ -46,7 +44,7 @@ export function stopReasonToExitCode(stopReason) {
|
|
|
46
44
|
|
|
47
45
|
/**
|
|
48
46
|
* Резолвить абсолютний шлях до bin-файлу вбудованого ACP-адаптера з його `package.json`.
|
|
49
|
-
* @param {string} adapterPackage назва npm-пакета адаптера (`@agentclientprotocol/
|
|
47
|
+
* @param {string} adapterPackage назва npm-пакета адаптера (`@agentclientprotocol/claude-agent-acp`)
|
|
50
48
|
* @returns {string} абсолютний шлях до виконуваного файлу адаптера
|
|
51
49
|
*/
|
|
52
50
|
export function resolveAdapterBin(adapterPackage) {
|
|
@@ -121,12 +119,13 @@ class AcpSkillClient {
|
|
|
121
119
|
}
|
|
122
120
|
|
|
123
121
|
/**
|
|
124
|
-
* Виконує скіл через зовнішнього ACP
|
|
125
|
-
*
|
|
122
|
+
* Виконує скіл через зовнішнього ACP-агента. Єдиний лишений провайдер —
|
|
123
|
+
* deprecated `claude` (`cursor`/`codex` — див. `@7n/llm-lib/acp`).
|
|
124
|
+
* @param {'claude'} kind провайдер
|
|
126
125
|
* @param {string} prompt готовий промпт скіла
|
|
127
126
|
* @param {string} projectDir робочий каталог сесії агента
|
|
128
127
|
* @param {(line: string) => void} logError вивід помилок
|
|
129
|
-
* @param {{ acp?: object, spawnFn?: typeof spawn, out?: (chunk: string) => void, resolveAdapterBin?: (pkg: string) => string
|
|
128
|
+
* @param {{ acp?: object, spawnFn?: typeof spawn, out?: (chunk: string) => void, resolveAdapterBin?: (pkg: string) => string }} [deps] інжекти для тестів
|
|
130
129
|
* @returns {Promise<number>} exit code (0 — `end_turn`, 1 — інакше)
|
|
131
130
|
*/
|
|
132
131
|
export async function runAcpRunner(kind, prompt, projectDir, logError, deps = {}) {
|
|
@@ -134,13 +133,9 @@ export async function runAcpRunner(kind, prompt, projectDir, logError, deps = {}
|
|
|
134
133
|
const out = deps.out ?? (chunk => stdout.write(chunk))
|
|
135
134
|
const resolveBin = deps.resolveAdapterBin ?? resolveAdapterBin
|
|
136
135
|
|
|
137
|
-
const
|
|
138
|
-
const
|
|
139
|
-
|
|
140
|
-
|
|
141
|
-
if ('bin' in command && deps.isBinaryInPath && !deps.isBinaryInPath(command.bin)) {
|
|
142
|
-
throw new Error(`\`${command.bin}\` not found in PATH. Install ${kind} CLI (ACP mode) or use \`skill pi\`.`)
|
|
143
|
-
}
|
|
136
|
+
const { adapterPackage } = ACP_AGENT_COMMANDS[kind]
|
|
137
|
+
const bin = process.execPath
|
|
138
|
+
const args = [resolveBin(adapterPackage)]
|
|
144
139
|
|
|
145
140
|
const acp = deps.acp ?? (await import('@zed-industries/agent-client-protocol'))
|
|
146
141
|
const child = spawnFn(bin, args, { cwd: projectDir, stdio: ['pipe', 'pipe', 'inherit'], env: process.env })
|
package/scripts/skills-cli.mjs
CHANGED
|
@@ -4,7 +4,9 @@
|
|
|
4
4
|
* Скіли читаються з `npm/skills/<id>/SKILL.md` установленого пакета (або кешу `npx`).
|
|
5
5
|
* Промпт збирає інструкцію скілу + контекст поточного CWD (`package.json`, `tsconfig.json`,
|
|
6
6
|
* `.n-rules.json`) — далі stdout або виконання через один з раннерів: вбудований
|
|
7
|
-
* pi-агент, чи зовнішній ACP
|
|
7
|
+
* pi-агент, чи зовнішній ACP-агент. `cursor`/`codex` — через `@7n/llm-lib/acp`
|
|
8
|
+
* (napi-міст до `llm_cascade::acp`, без власного JSON-RPC у JS); deprecated
|
|
9
|
+
* `claude` — окремий JS-шим (`./lib/acp-runner.mjs`), бо Rust-крейт його не моделює.
|
|
8
10
|
*
|
|
9
11
|
* Підтримувані формати:
|
|
10
12
|
* `npx \@7n/rules skill list`
|
|
@@ -12,14 +14,14 @@
|
|
|
12
14
|
* `npx \@7n/rules skill pi taze` — виконати через вбудований pi-агент (рекомендовано)
|
|
13
15
|
* `npx \@7n/rules skill pi taze "онови залежності"`
|
|
14
16
|
* `npx \@7n/rules skill cursor taze` — Cursor CLI через ACP (`cursor-agent acp`)
|
|
15
|
-
* `npx \@7n/rules skill codex taze` — Codex через ACP
|
|
17
|
+
* `npx \@7n/rules skill codex taze` — Codex через ACP (napi-міст `@7n/llm-lib/acp`, Rust спавнить `npx \@agentclientprotocol/codex-acp`)
|
|
16
18
|
* `npx \@7n/rules skill claude taze` — deprecated: Claude Code через ACP-адаптер
|
|
17
19
|
*/
|
|
18
20
|
|
|
19
|
-
import {
|
|
21
|
+
import { runAcpAgent } from '@7n/llm-lib/acp'
|
|
20
22
|
import { existsSync, readFileSync, readdirSync } from 'node:fs'
|
|
21
23
|
import { dirname, join } from 'node:path'
|
|
22
|
-
import { cwd } from 'node:process'
|
|
24
|
+
import { cwd, stdout } from 'node:process'
|
|
23
25
|
import { fileURLToPath } from 'node:url'
|
|
24
26
|
|
|
25
27
|
import { runAcpRunner } from './lib/acp-runner.mjs'
|
|
@@ -28,7 +30,11 @@ import { readSkillMetaRaw, skillTier } from './lib/skill-meta.mjs'
|
|
|
28
30
|
/** Виконавці скіла. `pi` — вбудований (рекомендований); `cursor`/`codex`/`claude` — зовнішні ACP-агенти (`claude` — deprecated). */
|
|
29
31
|
const RUNNERS = new Set(['pi', 'cursor', 'codex', 'claude'])
|
|
30
32
|
|
|
31
|
-
/**
|
|
33
|
+
/**
|
|
34
|
+
* Раннери, що йдуть через зовнішнього ACP-агента, і чи deprecated (друкує попередження
|
|
35
|
+
* перед запуском). `cursor`/`codex` — napi-міст `@7n/llm-lib/acp`; `claude` — окремий
|
|
36
|
+
* JS-шим `runAcpRunner` (Rust-крейт `llm_cascade::acp` `claude` не моделює).
|
|
37
|
+
*/
|
|
32
38
|
const ACP_RUNNERS = {
|
|
33
39
|
claude: { deprecated: true },
|
|
34
40
|
cursor: { deprecated: false },
|
|
@@ -47,17 +53,6 @@ const USAGE_LINES = [
|
|
|
47
53
|
'Skill id: каталог у пакеті (lint, taze, …) або з префіксом n- (n-lint → lint).'
|
|
48
54
|
]
|
|
49
55
|
|
|
50
|
-
/**
|
|
51
|
-
* @param {string} name ім'я бінарника
|
|
52
|
-
* @returns {boolean} чи знайдено бінарник у PATH
|
|
53
|
-
*/
|
|
54
|
-
function isBinaryInPath(name) {
|
|
55
|
-
// Явний `env: process.env` — Bun без нього дає дітям snapshot оточення зі старту процесу
|
|
56
|
-
// і не бачить runtime-змін `process.env.PATH` (та сама причина, що в resolve-cmd.mjs).
|
|
57
|
-
const probe = spawnSync('command', ['-v', name], { shell: true, encoding: 'utf8', env: process.env })
|
|
58
|
-
return probe.status === 0
|
|
59
|
-
}
|
|
60
|
-
|
|
61
56
|
/**
|
|
62
57
|
* @param {string} name ім'я скілу з CLI або каталогу `.cursor/skills/n-*`
|
|
63
58
|
* @returns {string} id каталогу в `npm/skills/<id>/`
|
|
@@ -170,27 +165,41 @@ async function runPiRunner(prompt, rawSkillName, skillsRoot, projectDir, logErro
|
|
|
170
165
|
}
|
|
171
166
|
|
|
172
167
|
/**
|
|
173
|
-
* Делегує виконання скіла зовнішньому ACP
|
|
174
|
-
*
|
|
175
|
-
*
|
|
176
|
-
*
|
|
177
|
-
*
|
|
168
|
+
* Делегує виконання скіла зовнішньому ACP-агенту. `cursor`/`codex` — через
|
|
169
|
+
* `@7n/llm-lib/acp` (napi-міст до `llm_cascade::acp`: спавн, `session/prompt`,
|
|
170
|
+
* автоапрув дозволів — усе в Rust, без JSON-RPC у JS). `claude` — deprecated
|
|
171
|
+
* JS-шим `runAcpRunner` (Rust його не моделює); буде прибрано (мігруй на `skill pi`).
|
|
172
|
+
* На відміну від колишнього стрімінгу по чанках, napi-шлях повертає повний текст
|
|
173
|
+
* лише по завершенню ходу — Rust-функція не стрімить проміжні токени в JS.
|
|
178
174
|
* @param {'claude' | 'cursor' | 'codex'} kind якого ACP-агента запускати
|
|
179
175
|
* @param {string} prompt промпт скіла
|
|
180
176
|
* @param {string} projectDir робочий каталог агента
|
|
181
177
|
* @param {(line: string) => void} logError вивід попередження/помилок
|
|
182
|
-
* @param {{ runAcpRunner?: typeof runAcpRunner }} [deps]
|
|
183
|
-
* @returns {Promise<number>} exit code (0 —
|
|
178
|
+
* @param {{ runAcpRunner?: typeof runAcpRunner, runAcpAgent?: typeof runAcpAgent, out?: (chunk: string) => void }} [deps] інжекти для тестів
|
|
179
|
+
* @returns {Promise<number>} exit code (0 — успіх, 1 — інакше)
|
|
184
180
|
*/
|
|
185
|
-
function runLlmCli(kind, prompt, projectDir, logError, deps = {}) {
|
|
181
|
+
async function runLlmCli(kind, prompt, projectDir, logError, deps = {}) {
|
|
186
182
|
const runner = ACP_RUNNERS[kind]
|
|
187
|
-
const runAcp = deps.runAcpRunner ?? runAcpRunner
|
|
188
183
|
|
|
189
184
|
if (runner.deprecated) {
|
|
190
185
|
logError(`[deprecated] skill ${kind} → use 'skill pi'; зовнішній ACP-агент буде прибрано`)
|
|
191
186
|
}
|
|
192
187
|
|
|
193
|
-
|
|
188
|
+
if (kind === 'claude') {
|
|
189
|
+
const runAcp = deps.runAcpRunner ?? runAcpRunner
|
|
190
|
+
return runAcp(kind, prompt, projectDir, logError)
|
|
191
|
+
}
|
|
192
|
+
|
|
193
|
+
const runNativeAcp = deps.runAcpAgent ?? runAcpAgent
|
|
194
|
+
const out = deps.out ?? (chunk => stdout.write(chunk))
|
|
195
|
+
|
|
196
|
+
try {
|
|
197
|
+
out(await runNativeAcp(kind, prompt, projectDir))
|
|
198
|
+
return 0
|
|
199
|
+
} catch (error) {
|
|
200
|
+
logError(error instanceof Error ? error.message : String(error))
|
|
201
|
+
return 1
|
|
202
|
+
}
|
|
194
203
|
}
|
|
195
204
|
|
|
196
205
|
/**
|