@rt-tools/agent-kit 0.8.2 → 0.9.0
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/README.md +13 -0
- package/assets/agents/rules-reviewer.md +83 -0
- package/assets/checks/board.github.mjs +48 -1
- package/assets/checks/check-board.github.mjs +84 -1
- package/assets/checks/check-dupes.mjs +66 -6
- package/assets/checks/check-lib-layers.mjs +13 -524
- package/assets/checks/check-specs.mjs +61 -747
- package/assets/checks/check-styles.mjs +185 -15
- package/assets/checks/lib-boundaries.mjs +143 -0
- package/assets/checks/lib-common.mjs +149 -0
- package/assets/checks/lib-domains.mjs +205 -0
- package/assets/checks/lib-manifests.mjs +60 -0
- package/assets/checks/lib-reexports.mjs +101 -0
- package/assets/checks/rt-kit-checks.config.mjs +26 -0
- package/assets/checks/spec-anchors.mjs +297 -0
- package/assets/checks/spec-common.mjs +222 -0
- package/assets/checks/spec-contract.mjs +152 -0
- package/assets/checks/spec-scenarios.mjs +201 -0
- package/assets/commands/feedback.md +95 -0
- package/assets/commands/rules-review.md +98 -0
- package/assets/commands/skill-curator.md +39 -22
- package/assets/defaults/project.sh +8 -0
- package/assets/docs/GLOSSARY.md +21 -20
- package/assets/hooks/git-guard-push-tests.sh +8 -4
- package/assets/hooks/reuse-first-guard.sh +16 -2
- package/assets/hooks/skill-gate.sh +1 -1
- package/assets/hooks/sql-guard-parse.sh +187 -0
- package/assets/hooks/sql-guard-request.sh +117 -0
- package/assets/hooks/sql-guard-target.sh +134 -0
- package/assets/hooks/sql-guard-write.sh +212 -0
- package/assets/hooks/sql-guard.sh +26 -596
- package/assets/hooks/task-flow-guard.sh +16 -2
- package/assets/hooks/waiting-turn-guard.sh +116 -0
- package/assets/laws/delivery.md +35 -0
- package/assets/laws/project-documentation.md +18 -0
- package/assets/laws/work-conduct.md +25 -0
- package/assets/patterns/admin-lists-screen.md +25 -14
- package/assets/patterns/admin-nav-item.md +1 -1
- package/assets/patterns/component-structure-new.md +1 -1
- package/assets/patterns/entity-aside.md +4 -2
- package/assets/patterns/git-workflow-commit.azure.md +74 -2
- package/assets/patterns/git-workflow-commit.github.md +75 -2
- package/assets/patterns/git-workflow-commit.gitlab.md +75 -4
- package/assets/patterns/git-workflow-docker.md +30 -0
- package/assets/patterns/observability-record.md +9 -0
- package/assets/patterns/shared-code-new.md +2 -2
- package/assets/patterns/task-flow-close.md +160 -47
- package/assets/patterns/task-flow-handoff.md +1 -1
- package/assets/patterns/task-flow-resume.md +3 -3
- package/assets/patterns/task-flow-start.md +32 -5
- package/assets/rules/angular-patterns.md +22 -0
- package/assets/rules/api-layer.md +25 -0
- package/assets/rules/browser-verification.md +32 -0
- package/assets/rules/component-structure.md +21 -0
- package/assets/rules/dependencies.md +22 -0
- package/assets/rules/doc-style.md +24 -0
- package/assets/rules/entity-conventions.needs-admin.md +21 -0
- package/assets/rules/entity-models.md +21 -0
- package/assets/rules/git-workflow.azure.md +57 -1
- package/assets/rules/git-workflow.github.md +89 -2
- package/assets/rules/git-workflow.gitlab.md +56 -1
- package/assets/rules/lib-layers.md +29 -0
- package/assets/rules/lists.md +37 -10
- package/assets/rules/navigation.md +21 -0
- package/assets/rules/observability.needs-app.md +23 -0
- package/assets/rules/permissions.md +23 -0
- package/assets/rules/platform-access.md +21 -0
- package/assets/rules/reuse-first.md +20 -0
- package/assets/rules/seo.md +19 -0
- package/assets/rules/shared-code.md +20 -1
- package/assets/rules/spec-driven.md +32 -0
- package/assets/rules/styling-bem.md +19 -0
- package/assets/rules/task-flow.md +148 -18
- package/assets/rules/testing.md +62 -0
- package/assets/rules/translations.md +21 -0
- package/assets/rules/typescript-conventions.md +28 -0
- package/assets/samples/specs/_template/spec.md +83 -0
- package/assets/samples/tasks/_template/grill.md +28 -0
- package/assets/samples/tasks/_template/plan.md +39 -0
- package/assets/samples/tasks/_template/progress.md +23 -0
- package/assets/skills/agent-kit.md +52 -2
- package/assets/templates/proposal.md +21 -0
- package/assets/templates/rule.md +31 -2
- package/bin/agent-kit.d.ts.map +1 -1
- package/bin/agent-kit.js +115 -87
- package/bin/agent-kit.js.map +1 -1
- package/index.d.ts +1 -0
- package/index.d.ts.map +1 -1
- package/index.js +1 -0
- package/index.js.map +1 -1
- package/lib/argv.d.ts.map +1 -1
- package/lib/argv.js +6 -4
- package/lib/argv.js.map +1 -1
- package/lib/assets.d.ts.map +1 -1
- package/lib/assets.js +2 -1
- package/lib/assets.js.map +1 -1
- package/lib/cargo.d.ts +20 -0
- package/lib/cargo.d.ts.map +1 -1
- package/lib/cargo.js.map +1 -1
- package/lib/cascade.d.ts +55 -0
- package/lib/cascade.d.ts.map +1 -0
- package/lib/cascade.js +131 -0
- package/lib/cascade.js.map +1 -0
- package/lib/catalog.d.ts +0 -75
- package/lib/catalog.d.ts.map +1 -1
- package/lib/catalog.js +44 -127
- package/lib/catalog.js.map +1 -1
- package/lib/commands.d.ts.map +1 -1
- package/lib/commands.js +153 -85
- package/lib/commands.js.map +1 -1
- package/lib/companion.d.ts.map +1 -1
- package/lib/companion.js +5 -5
- package/lib/companion.js.map +1 -1
- package/lib/config.d.ts +12 -1
- package/lib/config.d.ts.map +1 -1
- package/lib/config.js +11 -5
- package/lib/config.js.map +1 -1
- package/lib/enroll.d.ts +56 -0
- package/lib/enroll.d.ts.map +1 -0
- package/lib/enroll.js +123 -0
- package/lib/enroll.js.map +1 -0
- package/lib/freshness.d.ts.map +1 -1
- package/lib/freshness.js +31 -17
- package/lib/freshness.js.map +1 -1
- package/lib/hooks-map.d.ts +30 -0
- package/lib/hooks-map.d.ts.map +1 -1
- package/lib/hooks-map.js +80 -18
- package/lib/hooks-map.js.map +1 -1
- package/lib/integrity.d.ts +1 -2
- package/lib/integrity.d.ts.map +1 -1
- package/lib/integrity.js +0 -1
- package/lib/integrity.js.map +1 -1
- package/lib/observations.d.ts.map +1 -1
- package/lib/observations.js +25 -12
- package/lib/observations.js.map +1 -1
- package/lib/order.d.ts +10 -0
- package/lib/order.d.ts.map +1 -0
- package/lib/order.js +14 -0
- package/lib/order.js.map +1 -0
- package/lib/picker.d.ts.map +1 -1
- package/lib/picker.js +8 -2
- package/lib/picker.js.map +1 -1
- package/lib/plan.js +1 -1
- package/lib/plan.js.map +1 -1
- package/lib/proposals.d.ts.map +1 -1
- package/lib/proposals.js +25 -8
- package/lib/proposals.js.map +1 -1
- package/lib/sections.js +1 -1
- package/lib/sections.js.map +1 -1
- package/lib/ship.d.ts.map +1 -1
- package/lib/ship.js +9 -1
- package/lib/ship.js.map +1 -1
- package/lib/shipment.d.ts.map +1 -1
- package/lib/shipment.js +14 -10
- package/lib/shipment.js.map +1 -1
- package/lib/snapshot.d.ts.map +1 -1
- package/lib/snapshot.js +2 -1
- package/lib/snapshot.js.map +1 -1
- package/lib/stamp.js +1 -1
- package/lib/stamp.js.map +1 -1
- package/lib/sync.d.ts +12 -2
- package/lib/sync.d.ts.map +1 -1
- package/lib/sync.js +11 -10
- package/lib/sync.js.map +1 -1
- package/lib/vars.d.ts.map +1 -1
- package/lib/vars.js +2 -3
- package/lib/vars.js.map +1 -1
- package/package.json +1 -1
- package/rt-tools-agent-kit-0.9.0.tgz +0 -0
- package/rt-tools-agent-kit-0.8.2.tgz +0 -0
|
@@ -53,6 +53,16 @@ npx agent-kit stats # чем пользовались, чем ни ра
|
|
|
53
53
|
npx agent-kit propose # отправить груз в приём: сводку, предложения и разборы
|
|
54
54
|
```
|
|
55
55
|
|
|
56
|
+
Строкой запуска слой правил не исчерпывается: часть его команд исполняет агент, а не программа.
|
|
57
|
+
`/feedback` кладёт слово о правилах блоком в файл предложений, `/skill-curator` разбирает
|
|
58
|
+
закрытую задачу, `/next-session` закрывает заход, `/agent-kit-digest` сводит накопленное в правки
|
|
59
|
+
ресурсов, а `/rules-review` читает семью текстов — закон, его правила и паттерны при них — и ищет
|
|
60
|
+
то, чего не считает ни одна проверка: два текста, говорящих об одном разное, и случай, которого
|
|
61
|
+
не назвал ни один. Две последние зовутся в репозитории самого пакета: они правят его ресурсы и
|
|
62
|
+
судят их исходные тексты.
|
|
63
|
+
Считаемое ловит набор полноты текстов, и он же стоит перед пушем; ответ роли не повторяется от
|
|
64
|
+
запуска к запуску и ветку не отбивает.
|
|
65
|
+
|
|
56
66
|
## Обратная связь наверх
|
|
57
67
|
|
|
58
68
|
Слой правил правится не по памяти, а по тому, как им пользовались. Держится это тремя вещами.
|
|
@@ -64,8 +74,20 @@ npx agent-kit propose # отправить груз в приём: сво
|
|
|
64
74
|
**Сводка** — `agent-kit stats`. Самая ценная её строка не «чем пользовались», а **что разложено
|
|
65
75
|
и не загружено ни разу**: правило, которого никто не открыл, ничем себя не выдаёт.
|
|
66
76
|
|
|
67
|
-
**Предложения**
|
|
68
|
-
|
|
77
|
+
**Предложения** приходят двумя путями. Разбор закрытой задачи — командой `/skill-curator` —
|
|
78
|
+
приносит их пачкой, задним числом. Слово, сказанное посреди работы, кладёт командой `/feedback`
|
|
79
|
+
сам агент: до неё такое слово адреса не получало вовсе и умирало вместе с сессией. Оба пути
|
|
80
|
+
пишут в один файл дня и в одной форме; в сеть не ходит ни один — увозит их отправка.
|
|
81
|
+
|
|
82
|
+
Каждая запись несёт три строки: **место** — куда правка встаёт в ресурсе, **повод** — что пошло
|
|
83
|
+
не так без неё, и **чем закрывается** — какие надстройки и добавки этого дерева снимаются, когда
|
|
84
|
+
правка приедет редакцией пакета. Третья пишется затем, что предложение уезжает наружу, а
|
|
85
|
+
надстройка остаётся лежать здесь: без неё дерево не может сказать, какие из его надстроек
|
|
86
|
+
исправленная редакция закрыла, — снять наугад страшно, оставить дёшево, и надстройка остаётся
|
|
87
|
+
навсегда, молча замещая исправленный раздел пакета. Снимать нечего — так и пишется; пустой
|
|
88
|
+
третья строка не бывает.
|
|
89
|
+
|
|
90
|
+
Каждому предложению ставится адрес: «пакет», «компаньон» или «дерево». Выгружаются они файлом в `.claude/rt-kit/proposals/`
|
|
69
91
|
(форма — шаблон `proposal.md`), а `agent-kit propose` увозит в приём те, что адресованы
|
|
70
92
|
пакету, вместе со сводкой и разборами происшествий. Адрес дерева в сводке или в тексте
|
|
71
93
|
предложения отбивает отправку целиком.
|
|
@@ -136,6 +158,26 @@ npx agent-kit propose # отправить груз в приём: сво
|
|
|
136
158
|
|
|
137
159
|
## Ловушки
|
|
138
160
|
|
|
161
|
+
- **Надстройка замещает раздел целиком, и пакетные пункты в нём приходится держать копией.**
|
|
162
|
+
Дописать в раздел одну статью нечем: слияние идёт по заголовку `## `. Дерево, которому нужен
|
|
163
|
+
один свой пункт, копирует к нему все пакетные — и с этого дня правка любого из них,
|
|
164
|
+
приехавшая с новой версией, до этого дерева не доходит. Сверка разложенного молчит: она
|
|
165
|
+
считает расхождением правку на месте, а не замещённый раздел. Признак виден по самим
|
|
166
|
+
надстройкам — три из трёх прочитанных кончались абзацем о том, что перенос придётся делать
|
|
167
|
+
руками. Поэтому надстройкой берут раздел, у которого пакетных пунктов немного, а разросшийся
|
|
168
|
+
замещённый раздел — повод внести своё в пакет, а не держать его копией. Предложение, которым
|
|
169
|
+
своё вносят, называет эту надстройку строкой «чем закрывается»: иначе приехавшая редакция и
|
|
170
|
+
надстройка, которую она закрыла, не сопоставляются ничем, и надстройка остаётся замещать уже
|
|
171
|
+
исправленный раздел.
|
|
172
|
+
|
|
173
|
+
- **Готовый код пакета не называет имён одного дерева.** Префикс директив кита, ключи подписей
|
|
174
|
+
и имена сущностей принадлежат тому дереву, где паттерн писали; разложенные в соседнем, они
|
|
175
|
+
учат звать то, чего там нет вовсе. Имя директивы при этом отличается от имени в примере: по
|
|
176
|
+
примеру видно, что он пример, а `<префикс>TableRow` из чужого дерева выглядит рабочим кодом
|
|
177
|
+
и правится только после того, как продовая сборка упадёт. Тринадцать таких имён простояли в
|
|
178
|
+
четырёх ресурсах пакета, пока их не нашёл потребитель — и не своей сборкой, а надстройкой,
|
|
179
|
+
которой перекрыл раздел.
|
|
180
|
+
|
|
139
181
|
- **Правила и паттерны при отвергнутом законе в отказе не перечисляются.** Их снимает каскад, а
|
|
140
182
|
строка на них становится выводимой: раскладка называет её лишней вместе с законом, из-за
|
|
141
183
|
которого она перестала снимать. Отказ мерит слой законов, а не число файлов в пакете.
|
|
@@ -154,6 +196,14 @@ npx agent-kit propose # отправить груз в приём: сво
|
|
|
154
196
|
конструкции не видит: `case` теряет свою `esac`, файл остаётся синтаксически неверным, а
|
|
155
197
|
гард с ошибкой синтаксиса отвечает ненулевым кодом — то есть «правка отбита». Два раза за
|
|
156
198
|
заход, и оба раза это выглядело дефектом самого гарда.
|
|
199
|
+
- **Гард, подписанный не на то, что объявляет, выглядит работающим.** Событие и образец вызова
|
|
200
|
+
гард несёт сам, строкой `# rt-hook:`, а зовёт его образец в настройке агента — и эти двое
|
|
201
|
+
расходятся молча: путь гарда в настройке назван, файл разложен, набор сценариев зелёный.
|
|
202
|
+
Набор тут ничего не ловит намеренно — он зовёт гард напрямую с подставленным вводом и
|
|
203
|
+
объявления не читает вовсе. Так гейт правил и разбирал вызовы браузера веткой, которая не
|
|
204
|
+
исполнялась ни разу. Расхождение находит сверка раскладки: она сравнивает объявленный образец
|
|
205
|
+
с тем, под которым гард стоит, называет обе стороны и идёт в счёт расхождений. Правится
|
|
206
|
+
настройка, а верное значение лежит в гарде — тело его разбирает то, что объявлено.
|
|
157
207
|
- **Разложенный файл узнаётся по шапке, а не по каталогу.** Раскладка ложится в те же
|
|
158
208
|
`tools/`, `.claude/hooks/` и `.claude/skills/`, где лежит своё, поэтому карта гейта,
|
|
159
209
|
написанная по путям, требует под него доменное правило — а оно уводит править файл на месте.
|
|
@@ -21,12 +21,32 @@
|
|
|
21
21
|
В тексте предложения не бывает ни путей этого дерева, ни имён его доменов, ни его собственного
|
|
22
22
|
имени: файл уезжает в чужой репозиторий целиком. Найденный адрес дерева отбивает отправку с
|
|
23
23
|
номером строки — это проверка, а не напоминание.
|
|
24
|
+
|
|
25
|
+
Строк при заголовке три, и все три обязательны:
|
|
26
|
+
|
|
27
|
+
место — куда правка встаёт в ресурсе
|
|
28
|
+
повод — что пошло не так без неё
|
|
29
|
+
чем закрывается — какие надстройки и добавки этого дерева снимаются, когда правка приедет
|
|
30
|
+
редакцией пакета
|
|
31
|
+
|
|
32
|
+
Третья пишется затем, что предложение уезжает наружу, а надстройка, ради которой оно написано,
|
|
33
|
+
остаётся лежать в дереве, и связи между ними нет никакой. Пакет выпускает исправленную редакцию
|
|
34
|
+
— и сказать, какие надстройки она закрыла, дереву нечем: имя ресурса совпадает у десятка
|
|
35
|
+
предложений, а раздел надстройки называется тем же заголовком, что и пакетный. Снять наугад
|
|
36
|
+
страшно, оставить дёшево — и надстройка остаётся навсегда, молча замещая исправленный раздел
|
|
37
|
+
пакета.
|
|
38
|
+
|
|
39
|
+
Снимать нечего — так и пишется: «ничего, надстройки под это нет». Пустая строка третьей не
|
|
40
|
+
считается; машине она не видна вовсе — ни одна проверка тела предложения не читает, и держится
|
|
41
|
+
эта форма тем, кто пишет запись.
|
|
24
42
|
-->
|
|
25
43
|
|
|
26
44
|
## пакет · rules/<правило>.md
|
|
27
45
|
|
|
28
46
|
- **место:** раздел «<заголовок>», в конец
|
|
29
47
|
- **повод:** что в этой задаче пошло не так без этого правила
|
|
48
|
+
- **чем закрывается:** `.claude/rt-kit/overrides/rules/<правило>.md`, раздел «<заголовок>» —
|
|
49
|
+
снимается целиком, когда правка приедет редакцией пакета
|
|
30
50
|
|
|
31
51
|
> Готовый текст правки — ровно то, что вставить, в стиле соседних правил: по-русски,
|
|
32
52
|
> утверждением, без воды.
|
|
@@ -35,5 +55,6 @@
|
|
|
35
55
|
|
|
36
56
|
- **место:** ветка `edit`, рядом с соседним родом файлов
|
|
37
57
|
- **повод:** свой род файлов, которого у других деревьев нет
|
|
58
|
+
- **чем закрывается:** ничего, надстройки под это нет — правка и есть надстройка
|
|
38
59
|
|
|
39
60
|
> Готовый текст правки.
|
package/assets/templates/rule.md
CHANGED
|
@@ -11,9 +11,32 @@ description: Правило под закон «<Название закона>
|
|
|
11
11
|
приёмом это делается. Чем это названо в этом дереве и где лежит — `implementation.md` рядом:
|
|
12
12
|
правило переносится между репозиториями, имена — нет.
|
|
13
13
|
|
|
14
|
-
##
|
|
14
|
+
## Как это называется здесь
|
|
15
15
|
|
|
16
|
-
|
|
16
|
+
<Таблица «в законе — здесь»: закон говорит без имён, дерево называет свои. Правка, по которой
|
|
17
|
+
правило узнаётся, стоит в его `description`: гейт зовёт правило по этому признаку.>
|
|
18
|
+
|
|
19
|
+
## Где это лежит
|
|
20
|
+
|
|
21
|
+
В этом дереве — таблица в `implementation.md` рядом. Пути живут там, а не здесь: правило
|
|
22
|
+
переносится между репозиториями, раскладка — нет, и путь, названный в правиле, врёт в первом
|
|
23
|
+
же дереве, которое держит код иначе.
|
|
24
|
+
|
|
25
|
+
## Ход
|
|
26
|
+
|
|
27
|
+
Граф изображает тот же ход, что описан прозой ниже: с чего исполнитель начинает, где развилка и
|
|
28
|
+
чем каждая ветка кончается. Узлы называют шаги и условия, а не файлы: адреса живут в
|
|
29
|
+
`implementation.md` рядом, и в графе переносимого текста им места нет.
|
|
30
|
+
|
|
31
|
+
```mermaid
|
|
32
|
+
flowchart TD
|
|
33
|
+
A[<с чего начинается>] --> B{<условие>}
|
|
34
|
+
B -->|<да>| C[<что делается>]
|
|
35
|
+
B -->|<нет>| D[<что делается иначе>]
|
|
36
|
+
```
|
|
37
|
+
|
|
38
|
+
Правится он тем же изменением, что и проза: разойдясь, обе стороны остаются читаемыми как
|
|
39
|
+
действующие, и первым это замечает тот, кто пошёл по графу.
|
|
17
40
|
|
|
18
41
|
## Как закон применяется здесь
|
|
19
42
|
|
|
@@ -23,6 +46,12 @@ description: Правило под закон «<Название закона>
|
|
|
23
46
|
|
|
24
47
|
- **<Статья одной фразой.>** <Что сломается иначе — не больше двух предложений.>
|
|
25
48
|
|
|
49
|
+
## Чего из закона здесь нет
|
|
50
|
+
|
|
51
|
+
<Что закон требует, а это дерево не проверяет ничем. Раздел читается глазами и не сверяется
|
|
52
|
+
ничем — устаревшая неправда живёт в нём сколько угодно, поэтому перечитывается он целиком при
|
|
53
|
+
каждой правке правила.>
|
|
54
|
+
|
|
26
55
|
## Паттерны
|
|
27
56
|
|
|
28
57
|
- `<имя-правила>-<что>` — <когда брать>.
|
package/bin/agent-kit.d.ts.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"agent-kit.d.ts","sourceRoot":"","sources":["../../../projects/agent-kit/src/bin/agent-kit.ts"],"names":[],"mappings":";AAeA,OAAO,EAAqC,iBAAiB,EAAqB,MAAM,oBAAoB,CAAC;
|
|
1
|
+
{"version":3,"file":"agent-kit.d.ts","sourceRoot":"","sources":["../../../projects/agent-kit/src/bin/agent-kit.ts"],"names":[],"mappings":";AAeA,OAAO,EAAqC,iBAAiB,EAAqB,MAAM,oBAAoB,CAAC;AA4S7G,wBAAsB,IAAI,CAAC,IAAI,EAAE,SAAS,MAAM,EAAE,GAAG,OAAO,CAAC,iBAAiB,CAAC,CAU9E"}
|
package/bin/agent-kit.js
CHANGED
|
@@ -13,8 +13,10 @@ import process from 'node:process';
|
|
|
13
13
|
import { unknownFlagsIn } from '../lib/argv.js';
|
|
14
14
|
import { readCatalog, resolveSelection } from '../lib/catalog.js';
|
|
15
15
|
import { adopt, doctor, init, list, stats, sync } from '../lib/commands.js';
|
|
16
|
+
import { CONFIG_PATH, readConfig } from '../lib/config.js';
|
|
17
|
+
import { enroll, httpEnroll } from '../lib/enroll.js';
|
|
16
18
|
import { httpShip } from '../lib/ship.js';
|
|
17
|
-
import { propose } from '../lib/shipment.js';
|
|
19
|
+
import { propose, treeSlugOf } from '../lib/shipment.js';
|
|
18
20
|
import { DEFAULT_DAYS } from '../lib/observations.js';
|
|
19
21
|
import { staleBuild } from '../lib/freshness.js';
|
|
20
22
|
import { packageRootFrom } from '../lib/package-root.js';
|
|
@@ -34,6 +36,8 @@ const USAGE = [
|
|
|
34
36
|
' propose отправить груз в приём: сводку со снимком надстроек, предложения и разборы',
|
|
35
37
|
' propose --dry-run показать, что уехало бы, и ничего не отправлять',
|
|
36
38
|
' adopt [файлы] отдать пакету файлы, лежащие на его путях не от него',
|
|
39
|
+
' enroll --code <код> завести дерево по приглашению владельца и положить его токен',
|
|
40
|
+
' enroll --force перезаписать уже лежащий токен намеренно',
|
|
37
41
|
'',
|
|
38
42
|
' --root <путь> корень проекта; по умолчанию текущий каталог',
|
|
39
43
|
'',
|
|
@@ -79,6 +83,7 @@ function environmentOf(root) {
|
|
|
79
83
|
/** Чем это дерево себя выдаёт снаружи. Нет удалённого репозитория — нечем, и это не отказ. */
|
|
80
84
|
function remoteOf(root) {
|
|
81
85
|
try {
|
|
86
|
+
// eslint-disable-next-line sonarjs/no-os-command-from-path -- путь к git у каждой машины свой, и прибитый здесь сделал бы пакет непереносимым
|
|
82
87
|
return execFileSync('git', ['-C', root, 'remote', 'get-url', 'origin'], {
|
|
83
88
|
encoding: 'utf8',
|
|
84
89
|
stdio: ['ignore', 'pipe', 'ignore'],
|
|
@@ -137,39 +142,36 @@ async function selectionFor(argv, assetsDir) {
|
|
|
137
142
|
* отказ там означал бы, что пакет нельзя разложить без человека. Первый вид — умолчание, а не
|
|
138
143
|
* догадка: порядок в объявлении оси и есть порядок предпочтения.
|
|
139
144
|
*/
|
|
145
|
+
async function variantOfAxis(axis, argv) {
|
|
146
|
+
const spoken = optionOf(argv, `--${axis.name}`, '');
|
|
147
|
+
const values = axis.options.map((option) => option.value);
|
|
148
|
+
if (spoken) {
|
|
149
|
+
return values.includes(spoken)
|
|
150
|
+
? spoken
|
|
151
|
+
: {
|
|
152
|
+
code: 1,
|
|
153
|
+
lines: [`такого вида по оси «${axis.name}» пакет не везёт: ${spoken}`, `есть: ${values.join(', ')}`],
|
|
154
|
+
};
|
|
155
|
+
}
|
|
156
|
+
if (argv.includes('--all')) {
|
|
157
|
+
return axis.options[0]?.value ?? '';
|
|
158
|
+
}
|
|
159
|
+
if (!canAsk()) {
|
|
160
|
+
return {
|
|
161
|
+
code: 1,
|
|
162
|
+
lines: ['спросить некого: запуск без терминала', `назови вид флагом \`--${axis.name} <вид>\`: ${values.join(', ')}`],
|
|
163
|
+
};
|
|
164
|
+
}
|
|
165
|
+
return askOne(axis.options.map((option) => ({ id: option.value, name: option.value, title: option.title })), axis.question);
|
|
166
|
+
}
|
|
140
167
|
async function variantsFor(argv, assetsDir) {
|
|
141
168
|
const axes = readAxes(assetsDir);
|
|
142
169
|
const chosen = {};
|
|
143
170
|
for (const axis of axes) {
|
|
144
|
-
const
|
|
145
|
-
|
|
146
|
-
|
|
147
|
-
if (!known(spoken)) {
|
|
148
|
-
return {
|
|
149
|
-
code: 1,
|
|
150
|
-
lines: [
|
|
151
|
-
`такого вида по оси «${axis.name}» пакет не везёт: ${spoken}`,
|
|
152
|
-
`есть: ${axis.options.map((option) => option.value).join(', ')}`,
|
|
153
|
-
],
|
|
154
|
-
};
|
|
155
|
-
}
|
|
156
|
-
chosen[axis.name] = spoken;
|
|
157
|
-
continue;
|
|
158
|
-
}
|
|
159
|
-
if (argv.includes('--all')) {
|
|
160
|
-
chosen[axis.name] = axis.options[0]?.value ?? '';
|
|
161
|
-
continue;
|
|
171
|
+
const answer = await variantOfAxis(axis, argv);
|
|
172
|
+
if (isOutcome(answer)) {
|
|
173
|
+
return answer;
|
|
162
174
|
}
|
|
163
|
-
if (!canAsk()) {
|
|
164
|
-
return {
|
|
165
|
-
code: 1,
|
|
166
|
-
lines: [
|
|
167
|
-
'спросить некого: запуск без терминала',
|
|
168
|
-
`назови вид флагом \`--${axis.name} <вид>\`: ${axis.options.map((option) => option.value).join(', ')}`,
|
|
169
|
-
],
|
|
170
|
-
};
|
|
171
|
-
}
|
|
172
|
-
const answer = await askOne(axis.options.map((option) => ({ id: option.value, name: option.value, title: option.title })), axis.question);
|
|
173
175
|
if (answer === null) {
|
|
174
176
|
return null;
|
|
175
177
|
}
|
|
@@ -177,68 +179,94 @@ async function variantsFor(argv, assetsDir) {
|
|
|
177
179
|
}
|
|
178
180
|
return chosen;
|
|
179
181
|
}
|
|
182
|
+
/** Заведение настройки: выбор ресурсов и видов, брошенный выбор ничего не пишет. */
|
|
183
|
+
async function runInit(env, argv) {
|
|
184
|
+
const selection = await selectionFor(argv, env.assetsDir);
|
|
185
|
+
if (isOutcome(selection)) {
|
|
186
|
+
return selection;
|
|
187
|
+
}
|
|
188
|
+
if (selection === null) {
|
|
189
|
+
return { code: 1, lines: ['выбор брошен — ничего не заведено'] };
|
|
190
|
+
}
|
|
191
|
+
const variants = await variantsFor(argv, env.assetsDir);
|
|
192
|
+
if (isOutcome(variants)) {
|
|
193
|
+
return variants;
|
|
194
|
+
}
|
|
195
|
+
return variants === null
|
|
196
|
+
? { code: 1, lines: ['выбор брошен — ничего не заведено'] }
|
|
197
|
+
: init(env.root, selection, variants, env.assetsDir);
|
|
198
|
+
}
|
|
199
|
+
/** Сводка наблюдений: отрезок из флага, сегодняшний день — с края. */
|
|
200
|
+
function runStats(env, argv) {
|
|
201
|
+
const spoken = Number(optionOf(argv, '--days', ''));
|
|
202
|
+
return stats(env, {
|
|
203
|
+
days: Number.isFinite(spoken) && spoken > 0 ? Math.floor(spoken) : DEFAULT_DAYS,
|
|
204
|
+
// Сегодняшний день берётся здесь: у команды своих часов нет, иначе сводку за
|
|
205
|
+
// отрезок не проверить спекой — вчерашняя фикстура завтра станет позавчерашней.
|
|
206
|
+
today: new Date().toISOString().slice(0, 10),
|
|
207
|
+
json: argv.includes('--json'),
|
|
208
|
+
});
|
|
209
|
+
}
|
|
210
|
+
/**
|
|
211
|
+
* Отправка накопленного.
|
|
212
|
+
*
|
|
213
|
+
* Единственное действие этой команды необратимо и уходит наружу, поэтому незнакомый довод её
|
|
214
|
+
* кончает, а не пропускается молча: вызов ради списка режимов отправил в приём всё накопленное, и
|
|
215
|
+
* по выводу это не отличалось от «команда ничего не сделала». Прочие команды такого разбора не
|
|
216
|
+
* знают — их действие обратимо.
|
|
217
|
+
*/
|
|
218
|
+
async function runPropose(env, argv) {
|
|
219
|
+
const unknown = unknownFlagsIn(argv.slice(1), PROPOSE_FLAGS);
|
|
220
|
+
if (unknown.length) {
|
|
221
|
+
return {
|
|
222
|
+
code: 1,
|
|
223
|
+
lines: [`таких доводов у \`propose\` нет: ${unknown.join(', ')}`, '', ...PROPOSE_USAGE],
|
|
224
|
+
};
|
|
225
|
+
}
|
|
226
|
+
return propose(env, {
|
|
227
|
+
dryRun: argv.includes('--dry-run'),
|
|
228
|
+
ship: httpShip,
|
|
229
|
+
remote: remoteOf(env.root),
|
|
230
|
+
// Отрезок тот же, что у сводки по умолчанию: отправку зовут по свежей задаче.
|
|
231
|
+
days: DEFAULT_DAYS,
|
|
232
|
+
today: new Date().toISOString().slice(0, 10),
|
|
233
|
+
});
|
|
234
|
+
}
|
|
235
|
+
/** Приписка дерева к приёмнику по коду приглашения. */
|
|
236
|
+
async function runEnroll(env, argv) {
|
|
237
|
+
const config = readConfig(env.root);
|
|
238
|
+
if (!config) {
|
|
239
|
+
return { code: 1, lines: [`настройки дерева нет: ${CONFIG_PATH}. Заведите её командой \`init\``] };
|
|
240
|
+
}
|
|
241
|
+
return enroll({
|
|
242
|
+
root: env.root,
|
|
243
|
+
intake: config.intake,
|
|
244
|
+
code: optionOf(argv, '--code', ''),
|
|
245
|
+
tree: treeSlugOf(remoteOf(env.root), config.tree),
|
|
246
|
+
token: config.token,
|
|
247
|
+
force: argv.includes('--force'),
|
|
248
|
+
call: httpEnroll,
|
|
249
|
+
});
|
|
250
|
+
}
|
|
251
|
+
/** Что делает каждая команда строки запуска. Ключ — слово, которым её зовут. */
|
|
252
|
+
const COMMANDS = {
|
|
253
|
+
init: runInit,
|
|
254
|
+
list: (env) => list(env),
|
|
255
|
+
sync: (env, argv) => sync(env, argv.includes('--check')),
|
|
256
|
+
stats: runStats,
|
|
257
|
+
propose: runPropose,
|
|
258
|
+
enroll: runEnroll,
|
|
259
|
+
doctor: (env) => doctor(env),
|
|
260
|
+
adopt: (env, argv) => adopt(env, argv.slice(1).filter((value) => !value.startsWith('--') && value !== optionOf(argv, '--root', ''))),
|
|
261
|
+
};
|
|
180
262
|
export async function main(argv) {
|
|
181
263
|
const command = argv[0] ?? '';
|
|
182
264
|
const env = environmentOf(resolve(optionOf(argv, '--root', process.cwd())));
|
|
183
|
-
|
|
184
|
-
|
|
185
|
-
|
|
186
|
-
if (isOutcome(selection)) {
|
|
187
|
-
return selection;
|
|
188
|
-
}
|
|
189
|
-
if (selection === null) {
|
|
190
|
-
return { code: 1, lines: ['выбор брошен — ничего не заведено'] };
|
|
191
|
-
}
|
|
192
|
-
const variants = await variantsFor(argv, env.assetsDir);
|
|
193
|
-
if (isOutcome(variants)) {
|
|
194
|
-
return variants;
|
|
195
|
-
}
|
|
196
|
-
return variants === null
|
|
197
|
-
? { code: 1, lines: ['выбор брошен — ничего не заведено'] }
|
|
198
|
-
: init(env.root, selection, variants, env.assetsDir);
|
|
199
|
-
}
|
|
200
|
-
case 'list':
|
|
201
|
-
return list(env);
|
|
202
|
-
case 'sync':
|
|
203
|
-
return sync(env, argv.includes('--check'));
|
|
204
|
-
case 'stats': {
|
|
205
|
-
const spoken = Number(optionOf(argv, '--days', ''));
|
|
206
|
-
return stats(env, {
|
|
207
|
-
days: Number.isFinite(spoken) && spoken > 0 ? Math.floor(spoken) : DEFAULT_DAYS,
|
|
208
|
-
// Сегодняшний день берётся здесь: у команды своих часов нет, иначе сводку за
|
|
209
|
-
// отрезок не проверить спекой — вчерашняя фикстура завтра станет позавчерашней.
|
|
210
|
-
today: new Date().toISOString().slice(0, 10),
|
|
211
|
-
json: argv.includes('--json'),
|
|
212
|
-
});
|
|
213
|
-
}
|
|
214
|
-
case 'propose': {
|
|
215
|
-
// Единственное действие этой команды необратимо и уходит наружу, поэтому незнакомый
|
|
216
|
-
// довод её кончает, а не пропускается молча: вызов ради списка режимов отправил в
|
|
217
|
-
// приём всё накопленное, и по выводу это не отличалось от «команда ничего не
|
|
218
|
-
// сделала». Прочие команды такого разбора не знают — их действие обратимо.
|
|
219
|
-
const unknown = unknownFlagsIn(argv.slice(1), PROPOSE_FLAGS);
|
|
220
|
-
if (unknown.length) {
|
|
221
|
-
return {
|
|
222
|
-
code: 1,
|
|
223
|
-
lines: [`таких доводов у \`propose\` нет: ${unknown.join(', ')}`, '', ...PROPOSE_USAGE],
|
|
224
|
-
};
|
|
225
|
-
}
|
|
226
|
-
return propose(env, {
|
|
227
|
-
dryRun: argv.includes('--dry-run'),
|
|
228
|
-
ship: httpShip,
|
|
229
|
-
remote: remoteOf(env.root),
|
|
230
|
-
// Отрезок тот же, что у сводки по умолчанию: отправку зовут по свежей задаче.
|
|
231
|
-
days: DEFAULT_DAYS,
|
|
232
|
-
today: new Date().toISOString().slice(0, 10),
|
|
233
|
-
});
|
|
234
|
-
}
|
|
235
|
-
case 'doctor':
|
|
236
|
-
return doctor(env);
|
|
237
|
-
case 'adopt':
|
|
238
|
-
return adopt(env, argv.slice(1).filter((value) => !value.startsWith('--') && value !== optionOf(argv, '--root', '')));
|
|
239
|
-
default:
|
|
240
|
-
return { code: command ? 1 : 0, lines: command ? [`неизвестная команда «${command}»`, '', ...USAGE] : USAGE };
|
|
265
|
+
const run = Object.hasOwn(COMMANDS, command) ? COMMANDS[command] : undefined;
|
|
266
|
+
if (!run) {
|
|
267
|
+
return { code: command ? 1 : 0, lines: command ? [`неизвестная команда «${command}»`, '', ...USAGE] : USAGE };
|
|
241
268
|
}
|
|
269
|
+
return run(env, argv);
|
|
242
270
|
}
|
|
243
271
|
const outcome = await main(process.argv.slice(2));
|
|
244
272
|
for (const line of outcome.lines) {
|
package/bin/agent-kit.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"agent-kit.js","sourceRoot":"","sources":["../../../projects/agent-kit/src/bin/agent-kit.ts"],"names":[],"mappings":"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","sourcesContent":["#!/usr/bin/env node\n/**\n * Точка входа. Разбирает аргументы, добывает выбор проекта, зовёт команду и печатает то, что\n * она вернула. Своей работы у неё нет: всё, что решает, живёт в `commands.ts` и проверяется\n * спеками — кроме одного, чего команде знать не по чину: откуда взялся выбор законов. У строки\n * запуска это флаг, у терминала — вопрос, у прогона без терминала нет ни того ни другого.\n */\nimport { execFileSync } from 'node:child_process';\nimport { readFileSync } from 'node:fs';\nimport { dirname, join, resolve } from 'node:path';\nimport { fileURLToPath } from 'node:url';\nimport process from 'node:process';\n\nimport { unknownFlagsIn } from '../lib/argv.js';\nimport { IEntryOfCatalog, readCatalog, resolveSelection } from '../lib/catalog.js';\nimport { adopt, doctor, IEnvironment, init, IOutcomeOfCommand, list, stats, sync } from '../lib/commands.js';\nimport { httpShip } from '../lib/ship.js';\nimport { propose } from '../lib/shipment.js';\nimport { DEFAULT_DAYS } from '../lib/observations.js';\nimport { staleBuild } from '../lib/freshness.js';\nimport { packageRootFrom } from '../lib/package-root.js';\nimport { IChoice } from '../lib/picker.js';\nimport { IAxis, IOptionOfAxis, readAxes } from '../lib/variants.js';\nimport { ask, askOne, canAsk } from './prompt.js';\n\nconst USAGE: readonly string[] = [\n 'agent-kit <команда>',\n '',\n ' init завести .claude/rt-kit.json и каталог надстроек',\n ' list что везёт пакет и что из этого взято здесь',\n ' sync разложить ресурсы пакета в дерево проекта',\n ' sync --check ничего не писать, отказать при расхождении — для гейта пуша',\n ' doctor рассказать о состоянии раскладки, ничего не меняя',\n ' stats свести наблюдения: чем пользовались, чем ни разу, обо что спотыкались',\n ' stats --days N за сколько дней; без довода — за три',\n ' stats --json то же машиночитаемо — этим сводку прикладывают к предложению',\n ' propose отправить груз в приём: сводку со снимком надстроек, предложения и разборы',\n ' propose --dry-run показать, что уехало бы, и ничего не отправлять',\n ' adopt [файлы] отдать пакету файлы, лежащие на его путях не от него',\n '',\n ' --root <путь> корень проекта; по умолчанию текущий каталог',\n '',\n 'Выбор законов при `init`:',\n '',\n ' --all взять все законы, ни о чём не спрашивая',\n ' --laws a,b,c взять только названные; имена — из `agent-kit list`',\n ' без обоих спросить галочками; без терминала — отказ',\n '',\n 'Вид ресурсов при `init` — там, где один закон исполняется разными командами:',\n '',\n ' --<ось> <вид> например `--host gitlab`; оси и виды — из `agent-kit list`',\n ' без флага спросить; без терминала — отказ, кроме `--all`',\n];\n\n/**\n * Доводы отправки. Довод со значением помечен `<>`: за ним идёт отдельным словом путь, и без\n * пометки этот путь читался бы как ещё один незнакомый довод.\n */\nconst PROPOSE_FLAGS: readonly string[] = ['--dry-run', '--root <>'];\n\n/** Что печатает отказ на незнакомом доводе: режимы команды, а не весь свод. */\nconst PROPOSE_USAGE: readonly string[] = [\n ' propose отправить груз в приём',\n ' propose --dry-run показать, что уехало бы, и ничего не отправлять',\n ' --root <путь> корень проекта; по умолчанию текущий каталог',\n];\n\n/**\n * Единственное место, где пакет узнаёт собственное расположение. `import.meta` живёт только\n * здесь: библиотечные модули получают каталог ресурсов входным значением, и трансформ тестов,\n * разбирающий модули как CommonJS, на них уже не спотыкается.\n */\nfunction environmentOf(root: string): IEnvironment {\n const pkg: string = packageRootFrom(dirname(fileURLToPath(import.meta.url)));\n const manifest: { name: string; version: string } = JSON.parse(readFileSync(join(pkg, 'package.json'), 'utf8')) as {\n name: string;\n version: string;\n };\n\n return {\n root,\n version: manifest.version,\n assetsDir: join(pkg, 'assets'),\n // Сверка со своими исходниками возможна только отсюда: здесь пакет знает, где лежит сам.\n // У потребителя исходников рядом нет, и сверка молчит.\n stale: staleBuild(pkg, manifest.name),\n };\n}\n\n/** Чем это дерево себя выдаёт снаружи. Нет удалённого репозитория — нечем, и это не отказ. */\nfunction remoteOf(root: string): string {\n try {\n return execFileSync('git', ['-C', root, 'remote', 'get-url', 'origin'], {\n encoding: 'utf8',\n stdio: ['ignore', 'pipe', 'ignore'],\n }).trim();\n } catch {\n return '';\n }\n}\n\nfunction optionOf(argv: readonly string[], name: string, fallback: string): string {\n const index: number = argv.indexOf(name);\n\n return index >= 0 && argv[index + 1] ? argv[index + 1] : fallback;\n}\n\nconst isOutcome: (value: unknown) => value is IOutcomeOfCommand = (value: unknown): value is IOutcomeOfCommand =>\n typeof value === 'object' && value !== null && 'code' in value;\n\n/**\n * Выбор законов для `init`: список идентификаторов, `null` на брошенном выборе или готовый\n * отказ. Пустой список означает «взять всё», поэтому брошенный выбор отличается от него не\n * значением, а `null`: подставить «всё» вместо неотвеченного вопроса значило бы разложить\n * пятнадцать законов тому, кто как раз просил спросить.\n */\nasync function selectionFor(argv: readonly string[], assetsDir: string): Promise<readonly string[] | null | IOutcomeOfCommand> {\n if (argv.includes('--all')) {\n return [];\n }\n\n const catalog: readonly IEntryOfCatalog[] = readCatalog(assetsDir);\n const spoken: string = optionOf(argv, '--laws', '');\n\n if (spoken) {\n const named: string[] = spoken\n .split(',')\n .map((name: string): string => name.trim())\n .filter(Boolean);\n const { ids, unknown } = resolveSelection(named, 'laws', catalog);\n\n return unknown.length\n ? { code: 1, lines: [`таких законов пакет не везёт: ${unknown.join(', ')}`, 'что везёт — `agent-kit list`'] }\n : ids;\n }\n\n if (!canAsk()) {\n return {\n code: 1,\n lines: [\n 'спросить некого: запуск без терминала',\n 'назови законы флагом `--laws a,b,c` или возьми все флагом `--all`',\n 'что везёт пакет — `agent-kit list`',\n ],\n };\n }\n\n const choices: readonly IChoice[] = catalog\n .filter((entry: IEntryOfCatalog): boolean => entry.kind === 'laws')\n .map((entry: IEntryOfCatalog): IChoice => ({ id: entry.id, name: entry.name, title: entry.title }));\n\n return ask(choices, 'Какие законы разложить в этом проекте?');\n}\n\n/**\n * Виды для `init` по осям, объявленным пакетом: что взято из флага, что спрошено.\n *\n * `--all` берёт первый объявленный вид оси и **говорит об этом**: в CI спрашивать некого, а\n * отказ там означал бы, что пакет нельзя разложить без человека. Первый вид — умолчание, а не\n * догадка: порядок в объявлении оси и есть порядок предпочтения.\n */\nasync function variantsFor(argv: readonly string[], assetsDir: string): Promise<Record<string, string> | null | IOutcomeOfCommand> {\n const axes: readonly IAxis[] = readAxes(assetsDir);\n const chosen: Record<string, string> = {};\n\n for (const axis of axes) {\n const spoken: string = optionOf(argv, `--${axis.name}`, '');\n const known: (value: string) => boolean = (value: string): boolean =>\n axis.options.some((option: IOptionOfAxis): boolean => option.value === value);\n\n if (spoken) {\n if (!known(spoken)) {\n return {\n code: 1,\n lines: [\n `такого вида по оси «${axis.name}» пакет не везёт: ${spoken}`,\n `есть: ${axis.options.map((option: IOptionOfAxis): string => option.value).join(', ')}`,\n ],\n };\n }\n chosen[axis.name] = spoken;\n continue;\n }\n\n if (argv.includes('--all')) {\n chosen[axis.name] = axis.options[0]?.value ?? '';\n continue;\n }\n\n if (!canAsk()) {\n return {\n code: 1,\n lines: [\n 'спросить некого: запуск без терминала',\n `назови вид флагом \\`--${axis.name} <вид>\\`: ${axis.options.map((option: IOptionOfAxis): string => option.value).join(', ')}`,\n ],\n };\n }\n\n const answer: string | null = await askOne(\n axis.options.map((option: IOptionOfAxis): IChoice => ({ id: option.value, name: option.value, title: option.title })),\n axis.question\n );\n if (answer === null) {\n return null;\n }\n chosen[axis.name] = answer;\n }\n\n return chosen;\n}\n\nexport async function main(argv: readonly string[]): Promise<IOutcomeOfCommand> {\n const command: string = argv[0] ?? '';\n const env: IEnvironment = environmentOf(resolve(optionOf(argv, '--root', process.cwd())));\n\n switch (command) {\n case 'init': {\n const selection: readonly string[] | null | IOutcomeOfCommand = await selectionFor(argv, env.assetsDir);\n if (isOutcome(selection)) {\n return selection;\n }\n if (selection === null) {\n return { code: 1, lines: ['выбор брошен — ничего не заведено'] };\n }\n\n const variants: Record<string, string> | null | IOutcomeOfCommand = await variantsFor(argv, env.assetsDir);\n if (isOutcome(variants)) {\n return variants;\n }\n\n return variants === null\n ? { code: 1, lines: ['выбор брошен — ничего не заведено'] }\n : init(env.root, selection, variants, env.assetsDir);\n }\n case 'list':\n return list(env);\n case 'sync':\n return sync(env, argv.includes('--check'));\n case 'stats': {\n const spoken: number = Number(optionOf(argv, '--days', ''));\n\n return stats(env, {\n days: Number.isFinite(spoken) && spoken > 0 ? Math.floor(spoken) : DEFAULT_DAYS,\n // Сегодняшний день берётся здесь: у команды своих часов нет, иначе сводку за\n // отрезок не проверить спекой — вчерашняя фикстура завтра станет позавчерашней.\n today: new Date().toISOString().slice(0, 10),\n json: argv.includes('--json'),\n });\n }\n case 'propose': {\n // Единственное действие этой команды необратимо и уходит наружу, поэтому незнакомый\n // довод её кончает, а не пропускается молча: вызов ради списка режимов отправил в\n // приём всё накопленное, и по выводу это не отличалось от «команда ничего не\n // сделала». Прочие команды такого разбора не знают — их действие обратимо.\n const unknown: readonly string[] = unknownFlagsIn(argv.slice(1), PROPOSE_FLAGS);\n if (unknown.length) {\n return {\n code: 1,\n lines: [`таких доводов у \\`propose\\` нет: ${unknown.join(', ')}`, '', ...PROPOSE_USAGE],\n };\n }\n\n return propose(env, {\n dryRun: argv.includes('--dry-run'),\n ship: httpShip,\n remote: remoteOf(env.root),\n // Отрезок тот же, что у сводки по умолчанию: отправку зовут по свежей задаче.\n days: DEFAULT_DAYS,\n today: new Date().toISOString().slice(0, 10),\n });\n }\n case 'doctor':\n return doctor(env);\n case 'adopt':\n return adopt(\n env,\n argv.slice(1).filter((value: string): boolean => !value.startsWith('--') && value !== optionOf(argv, '--root', ''))\n );\n default:\n return { code: command ? 1 : 0, lines: command ? [`неизвестная команда «${command}»`, '', ...USAGE] : USAGE };\n }\n}\n\nconst outcome: IOutcomeOfCommand = await main(process.argv.slice(2));\nfor (const line of outcome.lines) {\n // eslint-disable-next-line no-console\n console.log(line);\n}\nprocess.exit(outcome.code);\n"]}
|
|
1
|
+
{"version":3,"file":"agent-kit.js","sourceRoot":"","sources":["../../../projects/agent-kit/src/bin/agent-kit.ts"],"names":[],"mappings":";AACA;;;;;GAKG;AACH,OAAO,EAAE,YAAY,EAAE,MAAM,oBAAoB,CAAC;AAClD,OAAO,EAAE,YAAY,EAAE,MAAM,SAAS,CAAC;AACvC,OAAO,EAAE,OAAO,EAAE,IAAI,EAAE,OAAO,EAAE,MAAM,WAAW,CAAC;AACnD,OAAO,EAAE,aAAa,EAAE,MAAM,UAAU,CAAC;AACzC,OAAO,OAAO,MAAM,cAAc,CAAC;AAEnC,OAAO,EAAE,cAAc,EAAE,MAAM,gBAAgB,CAAC;AAChD,OAAO,EAAmB,WAAW,EAAE,gBAAgB,EAAE,MAAM,mBAAmB,CAAC;AACnF,OAAO,EAAE,KAAK,EAAE,MAAM,EAAgB,IAAI,EAAqB,IAAI,EAAE,KAAK,EAAE,IAAI,EAAE,MAAM,oBAAoB,CAAC;AAC7G,OAAO,EAAE,WAAW,EAAW,UAAU,EAAE,MAAM,kBAAkB,CAAC;AACpE,OAAO,EAAE,MAAM,EAAE,UAAU,EAAE,MAAM,kBAAkB,CAAC;AACtD,OAAO,EAAE,QAAQ,EAAE,MAAM,gBAAgB,CAAC;AAC1C,OAAO,EAAE,OAAO,EAAE,UAAU,EAAE,MAAM,oBAAoB,CAAC;AACzD,OAAO,EAAE,YAAY,EAAE,MAAM,wBAAwB,CAAC;AACtD,OAAO,EAAE,UAAU,EAAE,MAAM,qBAAqB,CAAC;AACjD,OAAO,EAAE,eAAe,EAAE,MAAM,wBAAwB,CAAC;AAEzD,OAAO,EAAwB,QAAQ,EAAE,MAAM,oBAAoB,CAAC;AACpE,OAAO,EAAE,GAAG,EAAE,MAAM,EAAE,MAAM,EAAE,MAAM,aAAa,CAAC;AAElD,MAAM,KAAK,GAAsB;IAC7B,qBAAqB;IACrB,EAAE;IACF,mEAAmE;IACnE,8DAA8D;IAC9D,6DAA6D;IAC7D,+EAA+E;IAC/E,qEAAqE;IACrE,yFAAyF;IACzF,wDAAwD;IACxD,gFAAgF;IAChF,8FAA8F;IAC9F,uEAAuE;IACvE,wEAAwE;IACxE,qFAAqF;IACrF,iEAAiE;IACjE,EAAE;IACF,gEAAgE;IAChE,EAAE;IACF,2BAA2B;IAC3B,EAAE;IACF,6DAA6D;IAC7D,yEAAyE;IACzE,+DAA+D;IAC/D,EAAE;IACF,8EAA8E;IAC9E,EAAE;IACF,gFAAgF;IAChF,oEAAoE;CACvE,CAAC;AAEF;;;GAGG;AACH,MAAM,aAAa,GAAsB,CAAC,WAAW,EAAE,WAAW,CAAC,CAAC;AAEpE,+EAA+E;AAC/E,MAAM,aAAa,GAAsB;IACrC,8CAA8C;IAC9C,uEAAuE;IACvE,oEAAoE;CACvE,CAAC;AAEF;;;;GAIG;AACH,SAAS,aAAa,CAAC,IAAY;IAC/B,MAAM,GAAG,GAAW,eAAe,CAAC,OAAO,CAAC,aAAa,CAAC,MAAM,CAAC,IAAI,CAAC,GAAG,CAAC,CAAC,CAAC,CAAC;IAC7E,MAAM,QAAQ,GAAsC,IAAI,CAAC,KAAK,CAAC,YAAY,CAAC,IAAI,CAAC,GAAG,EAAE,cAAc,CAAC,EAAE,MAAM,CAAC,CAG7G,CAAC;IAEF,OAAO;QACH,IAAI;QACJ,OAAO,EAAE,QAAQ,CAAC,OAAO;QACzB,SAAS,EAAE,IAAI,CAAC,GAAG,EAAE,QAAQ,CAAC;QAC9B,yFAAyF;QACzF,uDAAuD;QACvD,KAAK,EAAE,UAAU,CAAC,GAAG,EAAE,QAAQ,CAAC,IAAI,CAAC;KACxC,CAAC;AACN,CAAC;AAED,8FAA8F;AAC9F,SAAS,QAAQ,CAAC,IAAY;IAC1B,IAAI,CAAC;QACD,8IAA8I;QAC9I,OAAO,YAAY,CAAC,KAAK,EAAE,CAAC,IAAI,EAAE,IAAI,EAAE,QAAQ,EAAE,SAAS,EAAE,QAAQ,CAAC,EAAE;YACpE,QAAQ,EAAE,MAAM;YAChB,KAAK,EAAE,CAAC,QAAQ,EAAE,MAAM,EAAE,QAAQ,CAAC;SACtC,CAAC,CAAC,IAAI,EAAE,CAAC;IACd,CAAC;IAAC,MAAM,CAAC;QACL,OAAO,EAAE,CAAC;IACd,CAAC;AACL,CAAC;AAED,SAAS,QAAQ,CAAC,IAAuB,EAAE,IAAY,EAAE,QAAgB;IACrE,MAAM,KAAK,GAAW,IAAI,CAAC,OAAO,CAAC,IAAI,CAAC,CAAC;IAEzC,OAAO,KAAK,IAAI,CAAC,IAAI,IAAI,CAAC,KAAK,GAAG,CAAC,CAAC,CAAC,CAAC,CAAC,IAAI,CAAC,KAAK,GAAG,CAAC,CAAC,CAAC,CAAC,CAAC,QAAQ,CAAC;AACtE,CAAC;AAED,MAAM,SAAS,GAAmD,CAAC,KAAc,EAA8B,EAAE,CAC7G,OAAO,KAAK,KAAK,QAAQ,IAAI,KAAK,KAAK,IAAI,IAAI,MAAM,IAAI,KAAK,CAAC;AAEnE;;;;;GAKG;AACH,KAAK,UAAU,YAAY,CAAC,IAAuB,EAAE,SAAiB;IAClE,IAAI,IAAI,CAAC,QAAQ,CAAC,OAAO,CAAC,EAAE,CAAC;QACzB,OAAO,EAAE,CAAC;IACd,CAAC;IAED,MAAM,OAAO,GAA+B,WAAW,CAAC,SAAS,CAAC,CAAC;IACnE,MAAM,MAAM,GAAW,QAAQ,CAAC,IAAI,EAAE,QAAQ,EAAE,EAAE,CAAC,CAAC;IAEpD,IAAI,MAAM,EAAE,CAAC;QACT,MAAM,KAAK,GAAa,MAAM;aACzB,KAAK,CAAC,GAAG,CAAC;aACV,GAAG,CAAC,CAAC,IAAY,EAAU,EAAE,CAAC,IAAI,CAAC,IAAI,EAAE,CAAC;aAC1C,MAAM,CAAC,OAAO,CAAC,CAAC;QACrB,MAAM,EAAE,GAAG,EAAE,OAAO,EAAE,GAAG,gBAAgB,CAAC,KAAK,EAAE,MAAM,EAAE,OAAO,CAAC,CAAC;QAElE,OAAO,OAAO,CAAC,MAAM;YACjB,CAAC,CAAC,EAAE,IAAI,EAAE,CAAC,EAAE,KAAK,EAAE,CAAC,iCAAiC,OAAO,CAAC,IAAI,CAAC,IAAI,CAAC,EAAE,EAAE,8BAA8B,CAAC,EAAE;YAC7G,CAAC,CAAC,GAAG,CAAC;IACd,CAAC;IAED,IAAI,CAAC,MAAM,EAAE,EAAE,CAAC;QACZ,OAAO;YACH,IAAI,EAAE,CAAC;YACP,KAAK,EAAE;gBACH,uCAAuC;gBACvC,mEAAmE;gBACnE,oCAAoC;aACvC;SACJ,CAAC;IACN,CAAC;IAED,MAAM,OAAO,GAAuB,OAAO;SACtC,MAAM,CAAC,CAAC,KAAsB,EAAW,EAAE,CAAC,KAAK,CAAC,IAAI,KAAK,MAAM,CAAC;SAClE,GAAG,CAAC,CAAC,KAAsB,EAAW,EAAE,CAAC,CAAC,EAAE,EAAE,EAAE,KAAK,CAAC,EAAE,EAAE,IAAI,EAAE,KAAK,CAAC,IAAI,EAAE,KAAK,EAAE,KAAK,CAAC,KAAK,EAAE,CAAC,CAAC,CAAC;IAExG,OAAO,GAAG,CAAC,OAAO,EAAE,wCAAwC,CAAC,CAAC;AAClE,CAAC;AAED;;;;;;GAMG;AACH,KAAK,UAAU,aAAa,CAAC,IAAW,EAAE,IAAuB;IAC7D,MAAM,MAAM,GAAW,QAAQ,CAAC,IAAI,EAAE,KAAK,IAAI,CAAC,IAAI,EAAE,EAAE,EAAE,CAAC,CAAC;IAC5D,MAAM,MAAM,GAAsB,IAAI,CAAC,OAAO,CAAC,GAAG,CAAC,CAAC,MAAqB,EAAU,EAAE,CAAC,MAAM,CAAC,KAAK,CAAC,CAAC;IAEpG,IAAI,MAAM,EAAE,CAAC;QACT,OAAO,MAAM,CAAC,QAAQ,CAAC,MAAM,CAAC;YAC1B,CAAC,CAAC,MAAM;YACR,CAAC,CAAC;gBACI,IAAI,EAAE,CAAC;gBACP,KAAK,EAAE,CAAC,uBAAuB,IAAI,CAAC,IAAI,qBAAqB,MAAM,EAAE,EAAE,SAAS,MAAM,CAAC,IAAI,CAAC,IAAI,CAAC,EAAE,CAAC;aACvG,CAAC;IACZ,CAAC;IAED,IAAI,IAAI,CAAC,QAAQ,CAAC,OAAO,CAAC,EAAE,CAAC;QACzB,OAAO,IAAI,CAAC,OAAO,CAAC,CAAC,CAAC,EAAE,KAAK,IAAI,EAAE,CAAC;IACxC,CAAC;IAED,IAAI,CAAC,MAAM,EAAE,EAAE,CAAC;QACZ,OAAO;YACH,IAAI,EAAE,CAAC;YACP,KAAK,EAAE,CAAC,uCAAuC,EAAE,yBAAyB,IAAI,CAAC,IAAI,aAAa,MAAM,CAAC,IAAI,CAAC,IAAI,CAAC,EAAE,CAAC;SACvH,CAAC;IACN,CAAC;IAED,OAAO,MAAM,CACT,IAAI,CAAC,OAAO,CAAC,GAAG,CAAC,CAAC,MAAqB,EAAW,EAAE,CAAC,CAAC,EAAE,EAAE,EAAE,MAAM,CAAC,KAAK,EAAE,IAAI,EAAE,MAAM,CAAC,KAAK,EAAE,KAAK,EAAE,MAAM,CAAC,KAAK,EAAE,CAAC,CAAC,EACrH,IAAI,CAAC,QAAQ,CAChB,CAAC;AACN,CAAC;AAED,KAAK,UAAU,WAAW,CAAC,IAAuB,EAAE,SAAiB;IACjE,MAAM,IAAI,GAAqB,QAAQ,CAAC,SAAS,CAAC,CAAC;IACnD,MAAM,MAAM,GAA2B,EAAE,CAAC;IAE1C,KAAK,MAAM,IAAI,IAAI,IAAI,EAAE,CAAC;QACtB,MAAM,MAAM,GAAsC,MAAM,aAAa,CAAC,IAAI,EAAE,IAAI,CAAC,CAAC;QAElF,IAAI,SAAS,CAAC,MAAM,CAAC,EAAE,CAAC;YACpB,OAAO,MAAM,CAAC;QAClB,CAAC;QAED,IAAI,MAAM,KAAK,IAAI,EAAE,CAAC;YAClB,OAAO,IAAI,CAAC;QAChB,CAAC;QAED,MAAM,CAAC,IAAI,CAAC,IAAI,CAAC,GAAG,MAAM,CAAC;IAC/B,CAAC;IAED,OAAO,MAAM,CAAC;AAClB,CAAC;AAED,oFAAoF;AACpF,KAAK,UAAU,OAAO,CAAC,GAAiB,EAAE,IAAuB;IAC7D,MAAM,SAAS,GAAiD,MAAM,YAAY,CAAC,IAAI,EAAE,GAAG,CAAC,SAAS,CAAC,CAAC;IACxG,IAAI,SAAS,CAAC,SAAS,CAAC,EAAE,CAAC;QACvB,OAAO,SAAS,CAAC;IACrB,CAAC;IACD,IAAI,SAAS,KAAK,IAAI,EAAE,CAAC;QACrB,OAAO,EAAE,IAAI,EAAE,CAAC,EAAE,KAAK,EAAE,CAAC,mCAAmC,CAAC,EAAE,CAAC;IACrE,CAAC;IAED,MAAM,QAAQ,GAAsD,MAAM,WAAW,CAAC,IAAI,EAAE,GAAG,CAAC,SAAS,CAAC,CAAC;IAC3G,IAAI,SAAS,CAAC,QAAQ,CAAC,EAAE,CAAC;QACtB,OAAO,QAAQ,CAAC;IACpB,CAAC;IAED,OAAO,QAAQ,KAAK,IAAI;QACpB,CAAC,CAAC,EAAE,IAAI,EAAE,CAAC,EAAE,KAAK,EAAE,CAAC,mCAAmC,CAAC,EAAE;QAC3D,CAAC,CAAC,IAAI,CAAC,GAAG,CAAC,IAAI,EAAE,SAAS,EAAE,QAAQ,EAAE,GAAG,CAAC,SAAS,CAAC,CAAC;AAC7D,CAAC;AAED,sEAAsE;AACtE,SAAS,QAAQ,CAAC,GAAiB,EAAE,IAAuB;IACxD,MAAM,MAAM,GAAW,MAAM,CAAC,QAAQ,CAAC,IAAI,EAAE,QAAQ,EAAE,EAAE,CAAC,CAAC,CAAC;IAE5D,OAAO,KAAK,CAAC,GAAG,EAAE;QACd,IAAI,EAAE,MAAM,CAAC,QAAQ,CAAC,MAAM,CAAC,IAAI,MAAM,GAAG,CAAC,CAAC,CAAC,CAAC,IAAI,CAAC,KAAK,CAAC,MAAM,CAAC,CAAC,CAAC,CAAC,YAAY;QAC/E,6EAA6E;QAC7E,gFAAgF;QAChF,KAAK,EAAE,IAAI,IAAI,EAAE,CAAC,WAAW,EAAE,CAAC,KAAK,CAAC,CAAC,EAAE,EAAE,CAAC;QAC5C,IAAI,EAAE,IAAI,CAAC,QAAQ,CAAC,QAAQ,CAAC;KAChC,CAAC,CAAC;AACP,CAAC;AAED;;;;;;;GAOG;AACH,KAAK,UAAU,UAAU,CAAC,GAAiB,EAAE,IAAuB;IAChE,MAAM,OAAO,GAAsB,cAAc,CAAC,IAAI,CAAC,KAAK,CAAC,CAAC,CAAC,EAAE,aAAa,CAAC,CAAC;IAChF,IAAI,OAAO,CAAC,MAAM,EAAE,CAAC;QACjB,OAAO;YACH,IAAI,EAAE,CAAC;YACP,KAAK,EAAE,CAAC,oCAAoC,OAAO,CAAC,IAAI,CAAC,IAAI,CAAC,EAAE,EAAE,EAAE,EAAE,GAAG,aAAa,CAAC;SAC1F,CAAC;IACN,CAAC;IAED,OAAO,OAAO,CAAC,GAAG,EAAE;QAChB,MAAM,EAAE,IAAI,CAAC,QAAQ,CAAC,WAAW,CAAC;QAClC,IAAI,EAAE,QAAQ;QACd,MAAM,EAAE,QAAQ,CAAC,GAAG,CAAC,IAAI,CAAC;QAC1B,8EAA8E;QAC9E,IAAI,EAAE,YAAY;QAClB,KAAK,EAAE,IAAI,IAAI,EAAE,CAAC,WAAW,EAAE,CAAC,KAAK,CAAC,CAAC,EAAE,EAAE,CAAC;KAC/C,CAAC,CAAC;AACP,CAAC;AAED,uDAAuD;AACvD,KAAK,UAAU,SAAS,CAAC,GAAiB,EAAE,IAAuB;IAC/D,MAAM,MAAM,GAAmB,UAAU,CAAC,GAAG,CAAC,IAAI,CAAC,CAAC;IAEpD,IAAI,CAAC,MAAM,EAAE,CAAC;QACV,OAAO,EAAE,IAAI,EAAE,CAAC,EAAE,KAAK,EAAE,CAAC,yBAAyB,WAAW,iCAAiC,CAAC,EAAE,CAAC;IACvG,CAAC;IAED,OAAO,MAAM,CAAC;QACV,IAAI,EAAE,GAAG,CAAC,IAAI;QACd,MAAM,EAAE,MAAM,CAAC,MAAM;QACrB,IAAI,EAAE,QAAQ,CAAC,IAAI,EAAE,QAAQ,EAAE,EAAE,CAAC;QAClC,IAAI,EAAE,UAAU,CAAC,QAAQ,CAAC,GAAG,CAAC,IAAI,CAAC,EAAE,MAAM,CAAC,IAAI,CAAC;QACjD,KAAK,EAAE,MAAM,CAAC,KAAK;QACnB,KAAK,EAAE,IAAI,CAAC,QAAQ,CAAC,SAAS,CAAC;QAC/B,IAAI,EAAE,UAAU;KACnB,CAAC,CAAC;AACP,CAAC;AAKD,gFAAgF;AAChF,MAAM,QAAQ,GAA0C;IACpD,IAAI,EAAE,OAAO;IACb,IAAI,EAAE,CAAC,GAAiB,EAAqB,EAAE,CAAC,IAAI,CAAC,GAAG,CAAC;IACzD,IAAI,EAAE,CAAC,GAAiB,EAAE,IAAuB,EAAqB,EAAE,CAAC,IAAI,CAAC,GAAG,EAAE,IAAI,CAAC,QAAQ,CAAC,SAAS,CAAC,CAAC;IAC5G,KAAK,EAAE,QAAQ;IACf,OAAO,EAAE,UAAU;IACnB,MAAM,EAAE,SAAS;IACjB,MAAM,EAAE,CAAC,GAAiB,EAAqB,EAAE,CAAC,MAAM,CAAC,GAAG,CAAC;IAC7D,KAAK,EAAE,CAAC,GAAiB,EAAE,IAAuB,EAAqB,EAAE,CACrE,KAAK,CACD,GAAG,EACH,IAAI,CAAC,KAAK,CAAC,CAAC,CAAC,CAAC,MAAM,CAAC,CAAC,KAAa,EAAW,EAAE,CAAC,CAAC,KAAK,CAAC,UAAU,CAAC,IAAI,CAAC,IAAI,KAAK,KAAK,QAAQ,CAAC,IAAI,EAAE,QAAQ,EAAE,EAAE,CAAC,CAAC,CACtH;CACR,CAAC;AAEF,MAAM,CAAC,KAAK,UAAU,IAAI,CAAC,IAAuB;IAC9C,MAAM,OAAO,GAAW,IAAI,CAAC,CAAC,CAAC,IAAI,EAAE,CAAC;IACtC,MAAM,GAAG,GAAiB,aAAa,CAAC,OAAO,CAAC,QAAQ,CAAC,IAAI,EAAE,QAAQ,EAAE,OAAO,CAAC,GAAG,EAAE,CAAC,CAAC,CAAC,CAAC;IAC1F,MAAM,GAAG,GAA4B,MAAM,CAAC,MAAM,CAAC,QAAQ,EAAE,OAAO,CAAC,CAAC,CAAC,CAAC,QAAQ,CAAC,OAAO,CAAC,CAAC,CAAC,CAAC,SAAS,CAAC;IAEtG,IAAI,CAAC,GAAG,EAAE,CAAC;QACP,OAAO,EAAE,IAAI,EAAE,OAAO,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,EAAE,KAAK,EAAE,OAAO,CAAC,CAAC,CAAC,CAAC,wBAAwB,OAAO,GAAG,EAAE,EAAE,EAAE,GAAG,KAAK,CAAC,CAAC,CAAC,CAAC,KAAK,EAAE,CAAC;IAClH,CAAC;IAED,OAAO,GAAG,CAAC,GAAG,EAAE,IAAI,CAAC,CAAC;AAC1B,CAAC;AAED,MAAM,OAAO,GAAsB,MAAM,IAAI,CAAC,OAAO,CAAC,IAAI,CAAC,KAAK,CAAC,CAAC,CAAC,CAAC,CAAC;AACrE,KAAK,MAAM,IAAI,IAAI,OAAO,CAAC,KAAK,EAAE,CAAC;IAC/B,sCAAsC;IACtC,OAAO,CAAC,GAAG,CAAC,IAAI,CAAC,CAAC;AACtB,CAAC;AACD,OAAO,CAAC,IAAI,CAAC,OAAO,CAAC,IAAI,CAAC,CAAC","sourcesContent":["#!/usr/bin/env node\n/**\n * Точка входа. Разбирает аргументы, добывает выбор проекта, зовёт команду и печатает то, что\n * она вернула. Своей работы у неё нет: всё, что решает, живёт в `commands.ts` и проверяется\n * спеками — кроме одного, чего команде знать не по чину: откуда взялся выбор законов. У строки\n * запуска это флаг, у терминала — вопрос, у прогона без терминала нет ни того ни другого.\n */\nimport { execFileSync } from 'node:child_process';\nimport { readFileSync } from 'node:fs';\nimport { dirname, join, resolve } from 'node:path';\nimport { fileURLToPath } from 'node:url';\nimport process from 'node:process';\n\nimport { unknownFlagsIn } from '../lib/argv.js';\nimport { IEntryOfCatalog, readCatalog, resolveSelection } from '../lib/catalog.js';\nimport { adopt, doctor, IEnvironment, init, IOutcomeOfCommand, list, stats, sync } from '../lib/commands.js';\nimport { CONFIG_PATH, IConfig, readConfig } from '../lib/config.js';\nimport { enroll, httpEnroll } from '../lib/enroll.js';\nimport { httpShip } from '../lib/ship.js';\nimport { propose, treeSlugOf } from '../lib/shipment.js';\nimport { DEFAULT_DAYS } from '../lib/observations.js';\nimport { staleBuild } from '../lib/freshness.js';\nimport { packageRootFrom } from '../lib/package-root.js';\nimport { IChoice } from '../lib/picker.js';\nimport { IAxis, IOptionOfAxis, readAxes } from '../lib/variants.js';\nimport { ask, askOne, canAsk } from './prompt.js';\n\nconst USAGE: readonly string[] = [\n 'agent-kit <команда>',\n '',\n ' init завести .claude/rt-kit.json и каталог надстроек',\n ' list что везёт пакет и что из этого взято здесь',\n ' sync разложить ресурсы пакета в дерево проекта',\n ' sync --check ничего не писать, отказать при расхождении — для гейта пуша',\n ' doctor рассказать о состоянии раскладки, ничего не меняя',\n ' stats свести наблюдения: чем пользовались, чем ни разу, обо что спотыкались',\n ' stats --days N за сколько дней; без довода — за три',\n ' stats --json то же машиночитаемо — этим сводку прикладывают к предложению',\n ' propose отправить груз в приём: сводку со снимком надстроек, предложения и разборы',\n ' propose --dry-run показать, что уехало бы, и ничего не отправлять',\n ' adopt [файлы] отдать пакету файлы, лежащие на его путях не от него',\n ' enroll --code <код> завести дерево по приглашению владельца и положить его токен',\n ' enroll --force перезаписать уже лежащий токен намеренно',\n '',\n ' --root <путь> корень проекта; по умолчанию текущий каталог',\n '',\n 'Выбор законов при `init`:',\n '',\n ' --all взять все законы, ни о чём не спрашивая',\n ' --laws a,b,c взять только названные; имена — из `agent-kit list`',\n ' без обоих спросить галочками; без терминала — отказ',\n '',\n 'Вид ресурсов при `init` — там, где один закон исполняется разными командами:',\n '',\n ' --<ось> <вид> например `--host gitlab`; оси и виды — из `agent-kit list`',\n ' без флага спросить; без терминала — отказ, кроме `--all`',\n];\n\n/**\n * Доводы отправки. Довод со значением помечен `<>`: за ним идёт отдельным словом путь, и без\n * пометки этот путь читался бы как ещё один незнакомый довод.\n */\nconst PROPOSE_FLAGS: readonly string[] = ['--dry-run', '--root <>'];\n\n/** Что печатает отказ на незнакомом доводе: режимы команды, а не весь свод. */\nconst PROPOSE_USAGE: readonly string[] = [\n ' propose отправить груз в приём',\n ' propose --dry-run показать, что уехало бы, и ничего не отправлять',\n ' --root <путь> корень проекта; по умолчанию текущий каталог',\n];\n\n/**\n * Единственное место, где пакет узнаёт собственное расположение. `import.meta` живёт только\n * здесь: библиотечные модули получают каталог ресурсов входным значением, и трансформ тестов,\n * разбирающий модули как CommonJS, на них уже не спотыкается.\n */\nfunction environmentOf(root: string): IEnvironment {\n const pkg: string = packageRootFrom(dirname(fileURLToPath(import.meta.url)));\n const manifest: { name: string; version: string } = JSON.parse(readFileSync(join(pkg, 'package.json'), 'utf8')) as {\n name: string;\n version: string;\n };\n\n return {\n root,\n version: manifest.version,\n assetsDir: join(pkg, 'assets'),\n // Сверка со своими исходниками возможна только отсюда: здесь пакет знает, где лежит сам.\n // У потребителя исходников рядом нет, и сверка молчит.\n stale: staleBuild(pkg, manifest.name),\n };\n}\n\n/** Чем это дерево себя выдаёт снаружи. Нет удалённого репозитория — нечем, и это не отказ. */\nfunction remoteOf(root: string): string {\n try {\n // eslint-disable-next-line sonarjs/no-os-command-from-path -- путь к git у каждой машины свой, и прибитый здесь сделал бы пакет непереносимым\n return execFileSync('git', ['-C', root, 'remote', 'get-url', 'origin'], {\n encoding: 'utf8',\n stdio: ['ignore', 'pipe', 'ignore'],\n }).trim();\n } catch {\n return '';\n }\n}\n\nfunction optionOf(argv: readonly string[], name: string, fallback: string): string {\n const index: number = argv.indexOf(name);\n\n return index >= 0 && argv[index + 1] ? argv[index + 1] : fallback;\n}\n\nconst isOutcome: (value: unknown) => value is IOutcomeOfCommand = (value: unknown): value is IOutcomeOfCommand =>\n typeof value === 'object' && value !== null && 'code' in value;\n\n/**\n * Выбор законов для `init`: список идентификаторов, `null` на брошенном выборе или готовый\n * отказ. Пустой список означает «взять всё», поэтому брошенный выбор отличается от него не\n * значением, а `null`: подставить «всё» вместо неотвеченного вопроса значило бы разложить\n * пятнадцать законов тому, кто как раз просил спросить.\n */\nasync function selectionFor(argv: readonly string[], assetsDir: string): Promise<readonly string[] | null | IOutcomeOfCommand> {\n if (argv.includes('--all')) {\n return [];\n }\n\n const catalog: readonly IEntryOfCatalog[] = readCatalog(assetsDir);\n const spoken: string = optionOf(argv, '--laws', '');\n\n if (spoken) {\n const named: string[] = spoken\n .split(',')\n .map((name: string): string => name.trim())\n .filter(Boolean);\n const { ids, unknown } = resolveSelection(named, 'laws', catalog);\n\n return unknown.length\n ? { code: 1, lines: [`таких законов пакет не везёт: ${unknown.join(', ')}`, 'что везёт — `agent-kit list`'] }\n : ids;\n }\n\n if (!canAsk()) {\n return {\n code: 1,\n lines: [\n 'спросить некого: запуск без терминала',\n 'назови законы флагом `--laws a,b,c` или возьми все флагом `--all`',\n 'что везёт пакет — `agent-kit list`',\n ],\n };\n }\n\n const choices: readonly IChoice[] = catalog\n .filter((entry: IEntryOfCatalog): boolean => entry.kind === 'laws')\n .map((entry: IEntryOfCatalog): IChoice => ({ id: entry.id, name: entry.name, title: entry.title }));\n\n return ask(choices, 'Какие законы разложить в этом проекте?');\n}\n\n/**\n * Виды для `init` по осям, объявленным пакетом: что взято из флага, что спрошено.\n *\n * `--all` берёт первый объявленный вид оси и **говорит об этом**: в CI спрашивать некого, а\n * отказ там означал бы, что пакет нельзя разложить без человека. Первый вид — умолчание, а не\n * догадка: порядок в объявлении оси и есть порядок предпочтения.\n */\nasync function variantOfAxis(axis: IAxis, argv: readonly string[]): Promise<string | null | IOutcomeOfCommand> {\n const spoken: string = optionOf(argv, `--${axis.name}`, '');\n const values: readonly string[] = axis.options.map((option: IOptionOfAxis): string => option.value);\n\n if (spoken) {\n return values.includes(spoken)\n ? spoken\n : {\n code: 1,\n lines: [`такого вида по оси «${axis.name}» пакет не везёт: ${spoken}`, `есть: ${values.join(', ')}`],\n };\n }\n\n if (argv.includes('--all')) {\n return axis.options[0]?.value ?? '';\n }\n\n if (!canAsk()) {\n return {\n code: 1,\n lines: ['спросить некого: запуск без терминала', `назови вид флагом \\`--${axis.name} <вид>\\`: ${values.join(', ')}`],\n };\n }\n\n return askOne(\n axis.options.map((option: IOptionOfAxis): IChoice => ({ id: option.value, name: option.value, title: option.title })),\n axis.question\n );\n}\n\nasync function variantsFor(argv: readonly string[], assetsDir: string): Promise<Record<string, string> | null | IOutcomeOfCommand> {\n const axes: readonly IAxis[] = readAxes(assetsDir);\n const chosen: Record<string, string> = {};\n\n for (const axis of axes) {\n const answer: string | null | IOutcomeOfCommand = await variantOfAxis(axis, argv);\n\n if (isOutcome(answer)) {\n return answer;\n }\n\n if (answer === null) {\n return null;\n }\n\n chosen[axis.name] = answer;\n }\n\n return chosen;\n}\n\n/** Заведение настройки: выбор ресурсов и видов, брошенный выбор ничего не пишет. */\nasync function runInit(env: IEnvironment, argv: readonly string[]): Promise<IOutcomeOfCommand> {\n const selection: readonly string[] | null | IOutcomeOfCommand = await selectionFor(argv, env.assetsDir);\n if (isOutcome(selection)) {\n return selection;\n }\n if (selection === null) {\n return { code: 1, lines: ['выбор брошен — ничего не заведено'] };\n }\n\n const variants: Record<string, string> | null | IOutcomeOfCommand = await variantsFor(argv, env.assetsDir);\n if (isOutcome(variants)) {\n return variants;\n }\n\n return variants === null\n ? { code: 1, lines: ['выбор брошен — ничего не заведено'] }\n : init(env.root, selection, variants, env.assetsDir);\n}\n\n/** Сводка наблюдений: отрезок из флага, сегодняшний день — с края. */\nfunction runStats(env: IEnvironment, argv: readonly string[]): IOutcomeOfCommand {\n const spoken: number = Number(optionOf(argv, '--days', ''));\n\n return stats(env, {\n days: Number.isFinite(spoken) && spoken > 0 ? Math.floor(spoken) : DEFAULT_DAYS,\n // Сегодняшний день берётся здесь: у команды своих часов нет, иначе сводку за\n // отрезок не проверить спекой — вчерашняя фикстура завтра станет позавчерашней.\n today: new Date().toISOString().slice(0, 10),\n json: argv.includes('--json'),\n });\n}\n\n/**\n * Отправка накопленного.\n *\n * Единственное действие этой команды необратимо и уходит наружу, поэтому незнакомый довод её\n * кончает, а не пропускается молча: вызов ради списка режимов отправил в приём всё накопленное, и\n * по выводу это не отличалось от «команда ничего не сделала». Прочие команды такого разбора не\n * знают — их действие обратимо.\n */\nasync function runPropose(env: IEnvironment, argv: readonly string[]): Promise<IOutcomeOfCommand> {\n const unknown: readonly string[] = unknownFlagsIn(argv.slice(1), PROPOSE_FLAGS);\n if (unknown.length) {\n return {\n code: 1,\n lines: [`таких доводов у \\`propose\\` нет: ${unknown.join(', ')}`, '', ...PROPOSE_USAGE],\n };\n }\n\n return propose(env, {\n dryRun: argv.includes('--dry-run'),\n ship: httpShip,\n remote: remoteOf(env.root),\n // Отрезок тот же, что у сводки по умолчанию: отправку зовут по свежей задаче.\n days: DEFAULT_DAYS,\n today: new Date().toISOString().slice(0, 10),\n });\n}\n\n/** Приписка дерева к приёмнику по коду приглашения. */\nasync function runEnroll(env: IEnvironment, argv: readonly string[]): Promise<IOutcomeOfCommand> {\n const config: IConfig | null = readConfig(env.root);\n\n if (!config) {\n return { code: 1, lines: [`настройки дерева нет: ${CONFIG_PATH}. Заведите её командой \\`init\\``] };\n }\n\n return enroll({\n root: env.root,\n intake: config.intake,\n code: optionOf(argv, '--code', ''),\n tree: treeSlugOf(remoteOf(env.root), config.tree),\n token: config.token,\n force: argv.includes('--force'),\n call: httpEnroll,\n });\n}\n\n/** Ветка команды: окружение и доводы строки запуска на входе, вывод и код возврата на выходе. */\ntype TCommandRun = (env: IEnvironment, argv: readonly string[]) => IOutcomeOfCommand | Promise<IOutcomeOfCommand>;\n\n/** Что делает каждая команда строки запуска. Ключ — слово, которым её зовут. */\nconst COMMANDS: Readonly<Record<string, TCommandRun>> = {\n init: runInit,\n list: (env: IEnvironment): IOutcomeOfCommand => list(env),\n sync: (env: IEnvironment, argv: readonly string[]): IOutcomeOfCommand => sync(env, argv.includes('--check')),\n stats: runStats,\n propose: runPropose,\n enroll: runEnroll,\n doctor: (env: IEnvironment): IOutcomeOfCommand => doctor(env),\n adopt: (env: IEnvironment, argv: readonly string[]): IOutcomeOfCommand =>\n adopt(\n env,\n argv.slice(1).filter((value: string): boolean => !value.startsWith('--') && value !== optionOf(argv, '--root', ''))\n ),\n};\n\nexport async function main(argv: readonly string[]): Promise<IOutcomeOfCommand> {\n const command: string = argv[0] ?? '';\n const env: IEnvironment = environmentOf(resolve(optionOf(argv, '--root', process.cwd())));\n const run: TCommandRun | undefined = Object.hasOwn(COMMANDS, command) ? COMMANDS[command] : undefined;\n\n if (!run) {\n return { code: command ? 1 : 0, lines: command ? [`неизвестная команда «${command}»`, '', ...USAGE] : USAGE };\n }\n\n return run(env, argv);\n}\n\nconst outcome: IOutcomeOfCommand = await main(process.argv.slice(2));\nfor (const line of outcome.lines) {\n // eslint-disable-next-line no-console\n console.log(line);\n}\nprocess.exit(outcome.code);\n"]}
|
package/index.d.ts
CHANGED
package/index.d.ts.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../projects/agent-kit/src/index.ts"],"names":[],"mappings":"AAAA,cAAc,iBAAiB,CAAC;AAChC,cAAc,gBAAgB,CAAC;AAC/B,cAAc,kBAAkB,CAAC;AACjC,cAAc,mBAAmB,CAAC;AAClC,cAAc,iBAAiB,CAAC;AAChC,cAAc,iBAAiB,CAAC;AAChC,cAAc,eAAe,CAAC;AAC9B,cAAc,mBAAmB,CAAC;AAClC,cAAc,gBAAgB,CAAC;AAC/B,cAAc,eAAe,CAAC;AAC9B,cAAc,eAAe,CAAC;AAC9B,cAAc,oBAAoB,CAAC"}
|
|
1
|
+
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../projects/agent-kit/src/index.ts"],"names":[],"mappings":"AAAA,cAAc,iBAAiB,CAAC;AAChC,cAAc,gBAAgB,CAAC;AAC/B,cAAc,kBAAkB,CAAC;AACjC,cAAc,kBAAkB,CAAC;AACjC,cAAc,mBAAmB,CAAC;AAClC,cAAc,iBAAiB,CAAC;AAChC,cAAc,iBAAiB,CAAC;AAChC,cAAc,eAAe,CAAC;AAC9B,cAAc,mBAAmB,CAAC;AAClC,cAAc,gBAAgB,CAAC;AAC/B,cAAc,eAAe,CAAC;AAC9B,cAAc,eAAe,CAAC;AAC9B,cAAc,oBAAoB,CAAC"}
|
package/index.js
CHANGED
package/index.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"index.js","sourceRoot":"","sources":["../../projects/agent-kit/src/index.ts"],"names":[],"mappings":"AAAA,cAAc,iBAAiB,CAAC;AAChC,cAAc,gBAAgB,CAAC;AAC/B,cAAc,kBAAkB,CAAC;AACjC,cAAc,mBAAmB,CAAC;AAClC,cAAc,iBAAiB,CAAC;AAChC,cAAc,iBAAiB,CAAC;AAChC,cAAc,eAAe,CAAC;AAC9B,cAAc,mBAAmB,CAAC;AAClC,cAAc,gBAAgB,CAAC;AAC/B,cAAc,eAAe,CAAC;AAC9B,cAAc,eAAe,CAAC;AAC9B,cAAc,oBAAoB,CAAC","sourcesContent":["export * from './lib/assets.js';\nexport * from './lib/cargo.js';\nexport * from './lib/catalog.js';\nexport * from './lib/commands.js';\nexport * from './lib/config.js';\nexport * from './lib/picker.js';\nexport * from './lib/plan.js';\nexport * from './lib/sections.js';\nexport * from './lib/stamp.js';\nexport * from './lib/sync.js';\nexport * from './lib/vars.js';\nexport * from './lib/freshness.js';\n"]}
|
|
1
|
+
{"version":3,"file":"index.js","sourceRoot":"","sources":["../../projects/agent-kit/src/index.ts"],"names":[],"mappings":"AAAA,cAAc,iBAAiB,CAAC;AAChC,cAAc,gBAAgB,CAAC;AAC/B,cAAc,kBAAkB,CAAC;AACjC,cAAc,kBAAkB,CAAC;AACjC,cAAc,mBAAmB,CAAC;AAClC,cAAc,iBAAiB,CAAC;AAChC,cAAc,iBAAiB,CAAC;AAChC,cAAc,eAAe,CAAC;AAC9B,cAAc,mBAAmB,CAAC;AAClC,cAAc,gBAAgB,CAAC;AAC/B,cAAc,eAAe,CAAC;AAC9B,cAAc,eAAe,CAAC;AAC9B,cAAc,oBAAoB,CAAC","sourcesContent":["export * from './lib/assets.js';\nexport * from './lib/cargo.js';\nexport * from './lib/cascade.js';\nexport * from './lib/catalog.js';\nexport * from './lib/commands.js';\nexport * from './lib/config.js';\nexport * from './lib/picker.js';\nexport * from './lib/plan.js';\nexport * from './lib/sections.js';\nexport * from './lib/stamp.js';\nexport * from './lib/sync.js';\nexport * from './lib/vars.js';\nexport * from './lib/freshness.js';\n"]}
|
package/lib/argv.d.ts.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"argv.d.ts","sourceRoot":"","sources":["../../../projects/agent-kit/src/lib/argv.ts"],"names":[],"mappings":"AAAA;;;;;;;GAOG;AAQH;;;;;;GAMG;AACH,wBAAgB,cAAc,CAAC,IAAI,EAAE,SAAS,MAAM,EAAE,EAAE,KAAK,EAAE,SAAS,MAAM,EAAE,GAAG,SAAS,MAAM,EAAE,
|
|
1
|
+
{"version":3,"file":"argv.d.ts","sourceRoot":"","sources":["../../../projects/agent-kit/src/lib/argv.ts"],"names":[],"mappings":"AAAA;;;;;;;GAOG;AAQH;;;;;;GAMG;AACH,wBAAgB,cAAc,CAAC,IAAI,EAAE,SAAS,MAAM,EAAE,EAAE,KAAK,EAAE,SAAS,MAAM,EAAE,GAAG,SAAS,MAAM,EAAE,CA8BnG"}
|
package/lib/argv.js
CHANGED
|
@@ -31,13 +31,15 @@ export function unknownFlagsIn(argv, known) {
|
|
|
31
31
|
const name = spoken.split('=')[0];
|
|
32
32
|
if (!names.has(name)) {
|
|
33
33
|
unknown.push(name);
|
|
34
|
-
continue;
|
|
35
34
|
}
|
|
36
|
-
|
|
37
|
-
|
|
38
|
-
|
|
35
|
+
else if (withValue.has(name) && !spoken.includes('=')) {
|
|
36
|
+
// Значение через пробел пропускается вместе со своим доводом: без этого путь, начатый
|
|
37
|
+
// с дефиса, читался бы как ещё один незнакомый довод.
|
|
39
38
|
index += 1;
|
|
40
39
|
}
|
|
40
|
+
else {
|
|
41
|
+
// Знакомый довод, у которого значения нет или оно написано через равенство
|
|
42
|
+
}
|
|
41
43
|
}
|
|
42
44
|
return unknown;
|
|
43
45
|
}
|