@rt-tools/agent-kit 0.4.0 → 0.5.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/assets/checks/board.github.mjs +45 -2
- package/assets/checks/check-board.github.mjs +7 -14
- package/assets/checks/check-specs.mjs +89 -10
- package/assets/defaults/gate-map.sh +8 -2
- package/assets/defaults/project.sh +25 -0
- package/assets/hooks/git-guard-delivery.sh +87 -4
- package/assets/hooks/grill-gate.sh +96 -0
- package/assets/hooks/task-flow-guard.sh +14 -3
- package/assets/laws/project-documentation.md +10 -0
- package/assets/laws/verifiability.md +13 -0
- package/assets/laws/work-conduct.md +11 -0
- package/assets/patterns/git-workflow-commit.github.md +4 -0
- package/assets/patterns/spec-driven-domain.md +16 -0
- package/assets/patterns/task-flow-close.md +71 -7
- package/assets/patterns/task-flow-start.md +14 -2
- package/assets/rules/angular-patterns.md +4 -0
- package/assets/rules/browser-verification.md +4 -3
- package/assets/rules/doc-style.md +14 -0
- package/assets/rules/spec-driven.md +11 -1
- package/assets/rules/task-flow.md +42 -2
- package/assets/skills/agent-kit.md +4 -0
- package/assets/templates/rule.md +1 -1
- package/lib/commands.d.ts.map +1 -1
- package/lib/commands.js +1 -1
- package/lib/commands.js.map +1 -1
- package/lib/hooks-map.d.ts +5 -2
- package/lib/hooks-map.d.ts.map +1 -1
- package/lib/hooks-map.js +11 -6
- package/lib/hooks-map.js.map +1 -1
- package/package.json +1 -1
- package/rt-tools-agent-kit-0.5.0.tgz +0 -0
- package/rt-tools-agent-kit-0.4.0.tgz +0 -0
package/lib/commands.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"commands.js","sourceRoot":"","sources":["../../../projects/agent-kit/src/lib/commands.ts"],"names":[],"mappings":"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","sourcesContent":["/**\n * Команды и их вывод. Печать отделена от работы: команда возвращает строки и код возврата,\n * а `process.exit` зовёт только точка входа — иначе ни одну из них нельзя было бы проверить\n * спекой, не перехватывая поток вывода.\n */\nimport { existsSync, mkdirSync, renameSync, writeFileSync } from 'node:fs';\nimport { join } from 'node:path';\n\nimport { collectAssets } from './assets.js';\nimport { IEntryOfCatalog, IGapOfVariant, isChosen, readCatalog } from './catalog.js';\nimport { ICompanion, isUnfilled, TCompanionState } from './companion.js';\nimport { CONFIG_PATH, DEFAULT_LAYOUT, IConfig, KINDS, OVERRIDES_DIR, readConfig, TKind } from './config.js';\nimport { IStaleBuild } from './freshness.js';\nimport { hooksSection, IHookBinding, SETTINGS_PATH } from './hooks-map.js';\nimport { IPlanned, isRefusal, TOutcome } from './plan.js';\nimport { ISyncResult, pendingOf, planSync, runSync } from './sync.js';\nimport { placeholdersOf } from './vars.js';\nimport { IAxis, IOptionOfAxis, readAxes, unansweredAxes } from './variants.js';\n\nexport interface IOutcomeOfCommand {\n readonly code: number;\n readonly lines: readonly string[];\n}\n\n/** Всё, что команда знает о мире: корень проекта, версия пакета и его каталог ресурсов. */\nexport interface IEnvironment {\n readonly root: string;\n readonly version: string;\n readonly assetsDir: string;\n /**\n * Ресурсы правлены позже, чем собран пакет, из которого идёт раскладка; `null` — сверять не с\n * чем. Считается на краю, где пакет знает своё расположение: библиотечные модули работают с\n * тем каталогом ресурсов, который им дали, и о существовании исходников не знают.\n */\n readonly stale?: IStaleBuild | null;\n}\n\n/** Что с файлом сделала раскладка. Прошедшее время здесь правда: `sync` уже записал. */\nconst DONE_WORD: Readonly<Record<TOutcome, string>> = {\n create: 'положен',\n update: 'переложен',\n drift: 'правлен руками',\n foreign: 'положен не пакетом',\n ok: 'без изменений',\n};\n\n/**\n * Что с файлом **сейчас**. Отдельно от прошедшего времени потому, что `doctor` и `list` ничего\n * не пишут: сказать «положен» о файле, которого в дереве нет, значит соврать читателю ровно там,\n * где он пришёл узнать состояние.\n */\nconst STATE_WORD: Readonly<Record<TOutcome, string>> = {\n create: 'нет в дереве',\n update: 'отстал от пакета',\n drift: 'правлен руками',\n foreign: 'положен не пакетом',\n ok: 'на месте',\n};\n\nconst NOT_CHOSEN: string = 'не выбран';\nconst SKIPPED: string = 'пропущен';\n/** Ресурс чужого вида: в этом дереве его не существует, а не «от него отказались». */\nconst OTHER_VARIANT: string = 'другой вид';\n\nconst KIND_TITLE: Readonly<Record<TKind, string>> = {\n laws: 'ЗАКОНЫ',\n rules: 'ПРАВИЛА',\n patterns: 'ПАТТЕРНЫ',\n skills: 'СКИЛЫ',\n hooks: 'ХУКИ',\n defaults: 'УМОЛЧАНИЯ',\n checks: 'ПРОВЕРКИ',\n agents: 'АГЕНТЫ',\n commands: 'КОМАНДЫ',\n workflows: 'ВОРКФЛОУ',\n templates: 'ШАБЛОНЫ',\n};\n\n/** Состояние компаньона словами. У заполненного слова нет: о нём говорить нечего. */\nconst COMPANION_WORD: Readonly<Record<TCompanionState, string>> = {\n missing: 'пропал',\n draft: 'остался черновиком',\n filled: 'заполнен',\n};\n\nconst NO_CONFIG: string = `нет \\`${CONFIG_PATH}\\` — начни с \\`agent-kit init\\``;\n\n/** Куда уезжает прежнее содержимое файла, отданного пакету. */\nexport const KEPT_SUFFIX: string = '.before-rt-kit';\n\nconst holes: (result: ISyncResult) => string[] = (result: ISyncResult): string[] =>\n [...result.missing].map(\n ([asset, names]: [string, readonly string[]]): string =>\n ` ${asset}: нет значений для ${names.map((name: string): string => `{{${name}}}`).join(', ')}`\n );\n\nconst unfilled: (result: ISyncResult) => readonly ICompanion[] = (result: ISyncResult): readonly ICompanion[] =>\n result.companions.filter(isUnfilled);\n\n/** Ось без ответа: чем её спрашивают и из чего выбирают. */\nconst axisLines: (axes: readonly IAxis[]) => string[] = (axes: readonly IAxis[]): string[] =>\n axes.flatMap((axis: IAxis): string[] => [\n ` ${axis.name} — ${axis.question}`,\n ...axis.options.map((option: IOptionOfAxis): string => ` ${option.value.padEnd(8)} ${option.title}`),\n ` выбор пишется в \\`variants\\` конфига: {\"${axis.name}\": \"${axis.options[0]?.value ?? ''}\"}`,\n ]);\n\n/**\n * Брошенное: файл лежит, а ресурс за ним больше не берут. Печатается отдельным списком и с\n * подсказкой — стереть его пакет не вправе, а промолчать не может: агент читает такой файл как\n * действующее правило.\n */\nconst abandonedLines: (result: ISyncResult) => string[] = (result: ISyncResult): string[] =>\n result.abandoned.length\n ? [\n `лежит от ресурсов, которые больше не берутся: ${result.abandoned.length}`,\n ...result.abandoned.map((path: string): string => ` ${path}`),\n ' их не стирает никто: рядом может лежать написанное проектом — убирать вручную',\n ]\n : [];\n\n/**\n * Ресурс, у которого нет вида под выбор дерева. Называется и то, чего не хватает, и оба способа\n * это снять: отказ без действия обходят, а не исполняют.\n */\nconst gapLines: (result: ISyncResult) => string[] = (result: ISyncResult): string[] =>\n result.gaps.flatMap((gap: IGapOfVariant): string[] => [\n ` ${gap.kind}/${gap.name} — есть только под ${gap.axis}: ${gap.available.join(', ')}, а выбран «${gap.chosen}»`,\n ` либо заведи вид под «${gap.chosen}», либо назови в skip: ${gap.ids.join(', ')}`,\n ]);\n\n/**\n * Гарды, которых нет в настройке агента, и готовый кусок для неё.\n *\n * Кусок печатается целиком, а не одними именами: правку в свою настройку делает проект, и\n * список «не хватает трёх» заставляет собирать JSON по памяти — там и теряется образец вызова.\n */\nconst unboundLines: (result: ISyncResult) => string[] = (result: ISyncResult): string[] =>\n result.unbound.length\n ? [\n `гарды разложены, но в \\`${SETTINGS_PATH}\\` их не зовёт никто: ${result.unbound.length}`,\n ...result.unbound.map((binding: IHookBinding): string => ` ${binding.path} — ${binding.event} ${binding.matcher}`),\n ` вставь в \\`${SETTINGS_PATH}\\` раздел \\`hooks\\` — готовый кусок ниже:`,\n ...JSON.stringify({ hooks: hooksSection(result.unbound) }, null, 4)\n .split('\\n')\n .map((line: string): string => ` ${line}`),\n ]\n : [];\n\nconst describe: (result: ISyncResult) => string[] = (result: ISyncResult): string[] => [\n ...holes(result),\n ...gapLines(result),\n ...unboundLines(result),\n ...pendingOf(result).map((entry: IPlanned): string => ` ${entry.path} — ${STATE_WORD[entry.outcome]}`),\n ...unfilled(result).map((entry: ICompanion): string => ` ${entry.path} — ${COMPANION_WORD[entry.state]}`),\n ...abandonedLines(result),\n];\n\n/** Имена дырок во всех ресурсах, которые дерево берёт. Без конфига — ни одной: выбор неизвестен. */\nfunction placeholdersIn(config: IConfig | null, assetsDir: string): readonly string[] {\n if (!config) {\n return [];\n }\n const names: string[] = [];\n for (const asset of collectAssets(config, assetsDir)) {\n for (const name of placeholdersOf(asset.text)) {\n if (!names.includes(name)) {\n names.push(name);\n }\n }\n }\n\n return names.sort();\n}\n\n/**\n * Что проект выбрал при заведении конфига. Пустой список — весь набор; выбор приходит сюда\n * готовым, потому что взять его негде, кроме края: у строки запуска флаг, у терминала вопрос,\n * а у неинтерактивного прогона нет ни того ни другого — и решать это команде не по чину.\n */\nexport function init(\n root: string,\n only: readonly string[] = [],\n variants: Readonly<Record<string, string>> = {},\n assetsDir: string = ''\n): IOutcomeOfCommand {\n const path: string = join(root, CONFIG_PATH);\n if (existsSync(path)) {\n return { code: 0, lines: [`${CONFIG_PATH} уже есть — оставлен как есть`] };\n }\n\n const config: object = { vars: {}, layout: DEFAULT_LAYOUT, variants, only, skip: [] };\n mkdirSync(join(root, OVERRIDES_DIR), { recursive: true });\n mkdirSync(join(root, CONFIG_PATH, '..'), { recursive: true });\n writeFileSync(path, `${JSON.stringify(config, null, 4)}\\n`, 'utf8');\n\n // Значения, которых пакет ждёт от дерева, называются здесь, а не отказом раскладки: узнать\n // о них на первом же `sync` значит начать установку с ошибки, притом что список известен\n // сразу — он вычитывается из текстов выбранных ресурсов.\n const wanted: readonly string[] = assetsDir ? placeholdersIn(readConfig(root), assetsDir) : [];\n\n return {\n code: 0,\n lines: [\n `заведён ${CONFIG_PATH}`,\n only.length ? `выбрано ресурсов: ${only.length}` : 'выбрано всё, что везёт пакет',\n ...Object.entries(variants).map(([axis, value]: [string, string]): string => `${axis}: ${value}`),\n `заведён ${OVERRIDES_DIR}/ — надстройки проекта кладутся сюда путём ресурса`,\n ...(wanted.length\n ? [\n `значения, которых ждут ресурсы, — впиши их в \\`vars\\` конфига: ${wanted.length}`,\n ...wanted.map((name: string): string => ` {{${name}}}`),\n ]\n : []),\n 'дальше: `agent-kit sync`, а своё дописывается в `.claude/rt-kit/gate-map.sh` и `project.sh`',\n ],\n };\n}\n\n/**\n * Отказ на устаревшей сборке. Раскладка из неё положила бы прежнюю редакцию ресурса и назвала\n * это сделанным: неправда дороже отказа — её замечают, когда правленое правило не действует.\n */\nconst staleRefusal: (stale: IStaleBuild) => IOutcomeOfCommand = (stale: IStaleBuild): IOutcomeOfCommand => ({\n code: 1,\n lines: [\n 'раскладка не начата: строка запуска читает собранное, а ресурсы правлены позже',\n ` правлено: ${stale.newest}`,\n ` исходные ресурсы: ${stale.source}`,\n ' собери пакет и повтори',\n ],\n});\n\nexport function sync(env: IEnvironment, check: boolean): IOutcomeOfCommand {\n const { root, version, assetsDir } = env;\n const config: IConfig | null = readConfig(root);\n if (!config) {\n return { code: 1, lines: [NO_CONFIG] };\n }\n if (env.stale) {\n return staleRefusal(env.stale);\n }\n\n // Ось без ответа отбивает раскладку целиком, а не пропускает свои ресурсы молча: правило\n // поставки бывает в трёх видах, и дерево, не назвавшее свой, осталось бы вовсе без правила\n // поставки — заметить это можно было бы только по тому, что гейт перестал его требовать.\n const unanswered: readonly IAxis[] = unansweredAxes(readAxes(assetsDir), config.variants);\n if (unanswered.length) {\n return { code: 1, lines: ['раскладка не начата: не выбран вид', ...axisLines(unanswered)] };\n }\n\n if (check) {\n const result: ISyncResult = planSync(config, root, version, assetsDir);\n const pending: readonly IPlanned[] = pendingOf(result);\n // Незаполненный компаньон — такое же расхождение, как отставший файл: правило разложено,\n // а имён этого дерева при нём нет, и агент читает указание, которому некуда примениться.\n const empty: readonly ICompanion[] = unfilled(result);\n // Гард, которого не зовёт настройка агента, — такое же расхождение, как отставший файл:\n // он разложен, он коммитится, и по дереву его не отличить от работающего.\n const count: number = result.missing.size + result.gaps.length + pending.length + empty.length + result.unbound.length;\n if (!count) {\n return { code: 0, lines: [`sync --check: разложенное сходится с пакетом v${version}`] };\n }\n\n return { code: 1, lines: [`sync --check: расхождений ${count}`, ...describe(result)] };\n }\n\n const result: ISyncResult = runSync(config, root, version, assetsDir);\n // Перечисляются только дырки: раскладка не начата, и назвать файл «положенным» значило бы\n // сказать неправду — на диске его нет.\n if (result.missing.size) {\n return { code: 1, lines: ['раскладка не начата: нечего подставить в дырки', ...holes(result)] };\n }\n\n // Ресурс без вида под выбор дерева отбивает раскладку целиком, а не выпадает из неё молча:\n // правило, разложенное без инструмента, который оно зовёт, читается как действующее.\n if (result.gaps.length) {\n return {\n code: 1,\n lines: ['раскладка не начата: у этих ресурсов нет вида под выбор дерева', ...gapLines(result)],\n };\n }\n\n const refused: readonly IPlanned[] = result.planned.filter((entry: IPlanned): boolean => isRefusal(entry.outcome));\n if (refused.length) {\n return {\n code: 1,\n lines: [\n 'раскладка не начата: эти файлы пакет переписывать не станет',\n ...refused.map((entry: IPlanned): string => ` ${entry.path} — ${DONE_WORD[entry.outcome]}`),\n 'правку надо либо перенести в надстройку, либо снять — и повторить',\n `положенное не пакетом отдаётся ему командой \\`agent-kit adopt\\`: прежнее содержимое ляжет рядом с пометкой \\`${KEPT_SUFFIX}\\``,\n ],\n };\n }\n\n // Раскладка удалась, а гарды могут остаться неподключёнными: настройка агента принадлежит\n // дереву, и пакет в неё не пишет. Код возврата остаётся нулевым — файлы легли, — но молчать\n // об этом нельзя: узнают иначе, когда что-нибудь пройдёт мимо гарда.\n return {\n code: 0,\n lines: [\n ...(result.written.length\n ? [`разложено файлов: ${result.written.length}`, ...result.written.map((path: string): string => ` ${path}`)]\n : ['всё уже разложено']),\n ...unboundLines(result),\n ],\n };\n}\n\n/**\n * Отдать пакету файл, который лежит в дереве не от него.\n *\n * Пока команды не было, `sync` отказывал на такой файл поимённо и предлагал «перенести правку в\n * надстройку или снять» — то есть работу, которую делают руками, и до неё же сводилась вся\n * установка в живое дерево. При этом один чужой файл останавливал раскладку целиком.\n *\n * Молчаливой перезаписи здесь нет и быть не может: в файле лежит то, чего в дереве больше нигде\n * нет. Поэтому переход — это переименование прежнего содержимого рядом и повторный `sync`:\n * пакет кладёт своё, а прежнее остаётся на диске под именем с пометкой и ждёт разбора.\n */\nexport function adopt(env: IEnvironment, names: readonly string[]): IOutcomeOfCommand {\n const { root, version, assetsDir } = env;\n const config: IConfig | null = readConfig(root);\n if (!config) {\n return { code: 1, lines: [NO_CONFIG] };\n }\n\n const foreign: readonly IPlanned[] = planSync(config, root, version, assetsDir).planned.filter(\n (entry: IPlanned): boolean => entry.outcome === 'foreign'\n );\n if (!foreign.length) {\n return { code: 0, lines: ['чужих файлов на путях пакета нет'] };\n }\n\n // Имена принимаются как их печатает `sync`: путём в дереве. Без имён отдаются все — на\n // свежей установке их бывает столько же, сколько ресурсов, и перечислять их руками значит\n // делать ту же работу, ради которой команда заведена.\n const wanted: readonly IPlanned[] = names.length\n ? foreign.filter((entry: IPlanned): boolean => names.some((name: string): boolean => entry.path.endsWith(name)))\n : foreign;\n if (!wanted.length) {\n return {\n code: 1,\n lines: ['ни одно имя не отвечает чужому файлу; чужие сейчас такие:', ...foreign.map((e: IPlanned): string => ` ${e.path}`)],\n };\n }\n\n const moved: string[] = [];\n const blocked: string[] = [];\n for (const entry of wanted) {\n const path: string = join(root, entry.path);\n const kept: string = `${path}${KEPT_SUFFIX}`;\n if (existsSync(kept)) {\n blocked.push(` ${entry.path}${KEPT_SUFFIX} — уже лежит, разбери его прежде`);\n continue;\n }\n renameSync(path, kept);\n moved.push(` ${entry.path} → ${entry.path}${KEPT_SUFFIX}`);\n }\n\n return {\n code: blocked.length ? 1 : 0,\n lines: [\n ...(moved.length ? [`прежнее содержимое отложено: ${moved.length}`, ...moved, 'дальше: `agent-kit sync`'] : []),\n ...(blocked.length ? ['не тронуто:', ...blocked] : []),\n ],\n };\n}\n\nexport function doctor(env: IEnvironment): IOutcomeOfCommand {\n const { root, version, assetsDir } = env;\n const config: IConfig | null = readConfig(root);\n if (!config) {\n return { code: 1, lines: [NO_CONFIG] };\n }\n\n const result: ISyncResult = planSync(config, root, version, assetsDir);\n const counted: Map<TOutcome, number> = new Map();\n for (const entry of result.planned) {\n counted.set(entry.outcome, (counted.get(entry.outcome) ?? 0) + 1);\n }\n\n const catalog: readonly IEntryOfCatalog[] = readCatalog(assetsDir);\n const taken: number = collectAssets(config, assetsDir).length;\n const unanswered: readonly IAxis[] = unansweredAxes(readAxes(assetsDir), config.variants);\n const chosen: string[] = Object.entries(config.variants).map(([axis, value]: [string, string]): string => `${axis}: ${value}`);\n // Ресурс чужого вида в «не выбрано» не идёт: проект от него не отказывался — его в этом\n // дереве не существует, как не существует второго правила поставки.\n const foreignVariant: readonly IEntryOfCatalog[] = catalog.filter(\n (entry: IEntryOfCatalog): boolean => entry.variant !== null && config.variants[entry.variant.axis] !== entry.variant.value\n );\n const other: number = foreignVariant.length;\n // Ресурс, названный и в отказе, и чужим видом, считается один раз — иначе «не выбрано»\n // уходит в минус, а минус в отчёте читается как поломка счёта, а не как двойной счёт.\n const skipped: number = config.skip.filter((id: string): boolean =>\n foreignVariant.every((entry: IEntryOfCatalog): boolean => entry.id !== id)\n ).length;\n\n const lines: string[] = [\n `пакет v${version}, везёт ресурсов ${catalog.length}, взято ${taken}`,\n `не выбрано: ${catalog.length - taken - skipped - other}, пропущено: ${skipped}, другой вид: ${other}`,\n `значений в конфиге: ${Object.keys(config.vars).length}`,\n ...chosen,\n ...[...counted].map(([outcome, count]: [TOutcome, number]): string => `${STATE_WORD[outcome]}: ${count}`),\n ...describe(result),\n ...(unanswered.length ? ['не выбран вид — раскладка не начнётся:', ...axisLines(unanswered)] : []),\n // Про устаревшую сборку `doctor` говорит, но отказом её не считает: он ничего не пишет,\n // и прочитать состояние дерева можно и из вчерашней сборки — знать бы, что она вчерашняя.\n ...(env.stale ? ['собранное отстало от исходников — раскладка откажет:', ` правлено: ${env.stale.newest}`] : []),\n ];\n\n return { code: 0, lines };\n}\n\n/**\n * Что пакет везёт и что из этого взято здесь.\n *\n * Работает и без конфига: посмотреть, из чего выбирать, нужно раньше, чем выбор сделан, — иначе\n * имена законов взять неоткуда, кроме исходников пакета.\n */\nexport function list(env: IEnvironment): IOutcomeOfCommand {\n const { root, version, assetsDir } = env;\n const config: IConfig | null = readConfig(root);\n const catalog: readonly IEntryOfCatalog[] = readCatalog(assetsDir);\n const planned: Map<string, TOutcome> = new Map();\n\n if (config) {\n for (const entry of planSync(config, root, version, assetsDir).planned) {\n planned.set(entry.asset, entry.outcome);\n }\n }\n\n const stateOf: (entry: IEntryOfCatalog) => string = (entry: IEntryOfCatalog): string => {\n if (!config) {\n return 'везёт пакет';\n }\n if (entry.variant && config.variants[entry.variant.axis] !== entry.variant.value) {\n return OTHER_VARIANT;\n }\n if (config.skip.includes(entry.id)) {\n return SKIPPED;\n }\n if (!isChosen(entry, config)) {\n return NOT_CHOSEN;\n }\n const outcome: TOutcome | undefined = planned.get(entry.id);\n\n // Ресурса нет среди запланированных ровно в одном случае: в нём осталась дырка без\n // значения, и до решения о судьбе файла раскладка не дошла.\n return outcome ? STATE_WORD[outcome] : 'дырка без значения';\n };\n\n const name: number = catalog.reduce((found: number, entry: IEntryOfCatalog): number => Math.max(found, entry.name.length), 0);\n const state: number = catalog.reduce((found: number, entry: IEntryOfCatalog): number => Math.max(found, stateOf(entry).length), 0);\n const lines: string[] = [config ? `пакет v${version}` : `пакет v${version}, ${CONFIG_PATH} ещё не заведён`];\n\n for (const kind of KINDS) {\n const entries: readonly IEntryOfCatalog[] = catalog.filter((entry: IEntryOfCatalog): boolean => entry.kind === kind);\n if (!entries.length) {\n continue;\n }\n lines.push('', KIND_TITLE[kind]);\n lines.push(\n ...entries.map(\n (entry: IEntryOfCatalog): string => ` ${entry.name.padEnd(name)} ${stateOf(entry).padEnd(state)} ${entry.title}`\n )\n );\n }\n\n return { code: 0, lines };\n}\n"]}
|
|
1
|
+
{"version":3,"file":"commands.js","sourceRoot":"","sources":["../../../projects/agent-kit/src/lib/commands.ts"],"names":[],"mappings":"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","sourcesContent":["/**\n * Команды и их вывод. Печать отделена от работы: команда возвращает строки и код возврата,\n * а `process.exit` зовёт только точка входа — иначе ни одну из них нельзя было бы проверить\n * спекой, не перехватывая поток вывода.\n */\nimport { existsSync, mkdirSync, renameSync, writeFileSync } from 'node:fs';\nimport { join } from 'node:path';\n\nimport { collectAssets } from './assets.js';\nimport { IEntryOfCatalog, IGapOfVariant, isChosen, readCatalog } from './catalog.js';\nimport { ICompanion, isUnfilled, TCompanionState } from './companion.js';\nimport { CONFIG_PATH, DEFAULT_LAYOUT, IConfig, KINDS, OVERRIDES_DIR, readConfig, TKind } from './config.js';\nimport { IStaleBuild } from './freshness.js';\nimport { hooksSection, IHookBinding, SETTINGS_PATH } from './hooks-map.js';\nimport { IPlanned, isRefusal, TOutcome } from './plan.js';\nimport { ISyncResult, pendingOf, planSync, runSync } from './sync.js';\nimport { placeholdersOf } from './vars.js';\nimport { IAxis, IOptionOfAxis, readAxes, unansweredAxes } from './variants.js';\n\nexport interface IOutcomeOfCommand {\n readonly code: number;\n readonly lines: readonly string[];\n}\n\n/** Всё, что команда знает о мире: корень проекта, версия пакета и его каталог ресурсов. */\nexport interface IEnvironment {\n readonly root: string;\n readonly version: string;\n readonly assetsDir: string;\n /**\n * Ресурсы правлены позже, чем собран пакет, из которого идёт раскладка; `null` — сверять не с\n * чем. Считается на краю, где пакет знает своё расположение: библиотечные модули работают с\n * тем каталогом ресурсов, который им дали, и о существовании исходников не знают.\n */\n readonly stale?: IStaleBuild | null;\n}\n\n/** Что с файлом сделала раскладка. Прошедшее время здесь правда: `sync` уже записал. */\nconst DONE_WORD: Readonly<Record<TOutcome, string>> = {\n create: 'положен',\n update: 'переложен',\n drift: 'правлен руками',\n foreign: 'положен не пакетом',\n ok: 'без изменений',\n};\n\n/**\n * Что с файлом **сейчас**. Отдельно от прошедшего времени потому, что `doctor` и `list` ничего\n * не пишут: сказать «положен» о файле, которого в дереве нет, значит соврать читателю ровно там,\n * где он пришёл узнать состояние.\n */\nconst STATE_WORD: Readonly<Record<TOutcome, string>> = {\n create: 'нет в дереве',\n update: 'отстал от пакета',\n drift: 'правлен руками',\n foreign: 'положен не пакетом',\n ok: 'на месте',\n};\n\nconst NOT_CHOSEN: string = 'не выбран';\nconst SKIPPED: string = 'пропущен';\n/** Ресурс чужого вида: в этом дереве его не существует, а не «от него отказались». */\nconst OTHER_VARIANT: string = 'другой вид';\n\nconst KIND_TITLE: Readonly<Record<TKind, string>> = {\n laws: 'ЗАКОНЫ',\n rules: 'ПРАВИЛА',\n patterns: 'ПАТТЕРНЫ',\n skills: 'СКИЛЫ',\n hooks: 'ХУКИ',\n defaults: 'УМОЛЧАНИЯ',\n checks: 'ПРОВЕРКИ',\n agents: 'АГЕНТЫ',\n commands: 'КОМАНДЫ',\n workflows: 'ВОРКФЛОУ',\n templates: 'ШАБЛОНЫ',\n};\n\n/** Состояние компаньона словами. У заполненного слова нет: о нём говорить нечего. */\nconst COMPANION_WORD: Readonly<Record<TCompanionState, string>> = {\n missing: 'пропал',\n draft: 'остался черновиком',\n filled: 'заполнен',\n};\n\nconst NO_CONFIG: string = `нет \\`${CONFIG_PATH}\\` — начни с \\`agent-kit init\\``;\n\n/** Куда уезжает прежнее содержимое файла, отданного пакету. */\nexport const KEPT_SUFFIX: string = '.before-rt-kit';\n\nconst holes: (result: ISyncResult) => string[] = (result: ISyncResult): string[] =>\n [...result.missing].map(\n ([asset, names]: [string, readonly string[]]): string =>\n ` ${asset}: нет значений для ${names.map((name: string): string => `{{${name}}}`).join(', ')}`\n );\n\nconst unfilled: (result: ISyncResult) => readonly ICompanion[] = (result: ISyncResult): readonly ICompanion[] =>\n result.companions.filter(isUnfilled);\n\n/** Ось без ответа: чем её спрашивают и из чего выбирают. */\nconst axisLines: (axes: readonly IAxis[]) => string[] = (axes: readonly IAxis[]): string[] =>\n axes.flatMap((axis: IAxis): string[] => [\n ` ${axis.name} — ${axis.question}`,\n ...axis.options.map((option: IOptionOfAxis): string => ` ${option.value.padEnd(8)} ${option.title}`),\n ` выбор пишется в \\`variants\\` конфига: {\"${axis.name}\": \"${axis.options[0]?.value ?? ''}\"}`,\n ]);\n\n/**\n * Брошенное: файл лежит, а ресурс за ним больше не берут. Печатается отдельным списком и с\n * подсказкой — стереть его пакет не вправе, а промолчать не может: агент читает такой файл как\n * действующее правило.\n */\nconst abandonedLines: (result: ISyncResult) => string[] = (result: ISyncResult): string[] =>\n result.abandoned.length\n ? [\n `лежит от ресурсов, которые больше не берутся: ${result.abandoned.length}`,\n ...result.abandoned.map((path: string): string => ` ${path}`),\n ' их не стирает никто: рядом может лежать написанное проектом — убирать вручную',\n ]\n : [];\n\n/**\n * Ресурс, у которого нет вида под выбор дерева. Называется и то, чего не хватает, и оба способа\n * это снять: отказ без действия обходят, а не исполняют.\n */\nconst gapLines: (result: ISyncResult) => string[] = (result: ISyncResult): string[] =>\n result.gaps.flatMap((gap: IGapOfVariant): string[] => [\n ` ${gap.kind}/${gap.name} — есть только под ${gap.axis}: ${gap.available.join(', ')}, а выбран «${gap.chosen}»`,\n ` либо заведи вид под «${gap.chosen}», либо назови в skip: ${gap.ids.join(', ')}`,\n ]);\n\n/**\n * Гарды, которых нет в настройке агента, и готовый кусок для неё.\n *\n * Кусок печатается целиком, а не одними именами: правку в свою настройку делает проект, и\n * список «не хватает трёх» заставляет собирать JSON по памяти — там и теряется образец вызова.\n */\nconst unboundLines: (result: ISyncResult) => string[] = (result: ISyncResult): string[] =>\n result.unbound.length\n ? [\n `гарды разложены, но в \\`${SETTINGS_PATH}\\` их не зовёт никто: ${result.unbound.length}`,\n ...result.unbound.map(\n (binding: IHookBinding): string => ` ${binding.path} — ${binding.event}${binding.matcher ? ` ${binding.matcher}` : ''}`\n ),\n ` вставь в \\`${SETTINGS_PATH}\\` раздел \\`hooks\\` — готовый кусок ниже:`,\n ...JSON.stringify({ hooks: hooksSection(result.unbound) }, null, 4)\n .split('\\n')\n .map((line: string): string => ` ${line}`),\n ]\n : [];\n\nconst describe: (result: ISyncResult) => string[] = (result: ISyncResult): string[] => [\n ...holes(result),\n ...gapLines(result),\n ...unboundLines(result),\n ...pendingOf(result).map((entry: IPlanned): string => ` ${entry.path} — ${STATE_WORD[entry.outcome]}`),\n ...unfilled(result).map((entry: ICompanion): string => ` ${entry.path} — ${COMPANION_WORD[entry.state]}`),\n ...abandonedLines(result),\n];\n\n/** Имена дырок во всех ресурсах, которые дерево берёт. Без конфига — ни одной: выбор неизвестен. */\nfunction placeholdersIn(config: IConfig | null, assetsDir: string): readonly string[] {\n if (!config) {\n return [];\n }\n const names: string[] = [];\n for (const asset of collectAssets(config, assetsDir)) {\n for (const name of placeholdersOf(asset.text)) {\n if (!names.includes(name)) {\n names.push(name);\n }\n }\n }\n\n return names.sort();\n}\n\n/**\n * Что проект выбрал при заведении конфига. Пустой список — весь набор; выбор приходит сюда\n * готовым, потому что взять его негде, кроме края: у строки запуска флаг, у терминала вопрос,\n * а у неинтерактивного прогона нет ни того ни другого — и решать это команде не по чину.\n */\nexport function init(\n root: string,\n only: readonly string[] = [],\n variants: Readonly<Record<string, string>> = {},\n assetsDir: string = ''\n): IOutcomeOfCommand {\n const path: string = join(root, CONFIG_PATH);\n if (existsSync(path)) {\n return { code: 0, lines: [`${CONFIG_PATH} уже есть — оставлен как есть`] };\n }\n\n const config: object = { vars: {}, layout: DEFAULT_LAYOUT, variants, only, skip: [] };\n mkdirSync(join(root, OVERRIDES_DIR), { recursive: true });\n mkdirSync(join(root, CONFIG_PATH, '..'), { recursive: true });\n writeFileSync(path, `${JSON.stringify(config, null, 4)}\\n`, 'utf8');\n\n // Значения, которых пакет ждёт от дерева, называются здесь, а не отказом раскладки: узнать\n // о них на первом же `sync` значит начать установку с ошибки, притом что список известен\n // сразу — он вычитывается из текстов выбранных ресурсов.\n const wanted: readonly string[] = assetsDir ? placeholdersIn(readConfig(root), assetsDir) : [];\n\n return {\n code: 0,\n lines: [\n `заведён ${CONFIG_PATH}`,\n only.length ? `выбрано ресурсов: ${only.length}` : 'выбрано всё, что везёт пакет',\n ...Object.entries(variants).map(([axis, value]: [string, string]): string => `${axis}: ${value}`),\n `заведён ${OVERRIDES_DIR}/ — надстройки проекта кладутся сюда путём ресурса`,\n ...(wanted.length\n ? [\n `значения, которых ждут ресурсы, — впиши их в \\`vars\\` конфига: ${wanted.length}`,\n ...wanted.map((name: string): string => ` {{${name}}}`),\n ]\n : []),\n 'дальше: `agent-kit sync`, а своё дописывается в `.claude/rt-kit/gate-map.sh` и `project.sh`',\n ],\n };\n}\n\n/**\n * Отказ на устаревшей сборке. Раскладка из неё положила бы прежнюю редакцию ресурса и назвала\n * это сделанным: неправда дороже отказа — её замечают, когда правленое правило не действует.\n */\nconst staleRefusal: (stale: IStaleBuild) => IOutcomeOfCommand = (stale: IStaleBuild): IOutcomeOfCommand => ({\n code: 1,\n lines: [\n 'раскладка не начата: строка запуска читает собранное, а ресурсы правлены позже',\n ` правлено: ${stale.newest}`,\n ` исходные ресурсы: ${stale.source}`,\n ' собери пакет и повтори',\n ],\n});\n\nexport function sync(env: IEnvironment, check: boolean): IOutcomeOfCommand {\n const { root, version, assetsDir } = env;\n const config: IConfig | null = readConfig(root);\n if (!config) {\n return { code: 1, lines: [NO_CONFIG] };\n }\n if (env.stale) {\n return staleRefusal(env.stale);\n }\n\n // Ось без ответа отбивает раскладку целиком, а не пропускает свои ресурсы молча: правило\n // поставки бывает в трёх видах, и дерево, не назвавшее свой, осталось бы вовсе без правила\n // поставки — заметить это можно было бы только по тому, что гейт перестал его требовать.\n const unanswered: readonly IAxis[] = unansweredAxes(readAxes(assetsDir), config.variants);\n if (unanswered.length) {\n return { code: 1, lines: ['раскладка не начата: не выбран вид', ...axisLines(unanswered)] };\n }\n\n if (check) {\n const result: ISyncResult = planSync(config, root, version, assetsDir);\n const pending: readonly IPlanned[] = pendingOf(result);\n // Незаполненный компаньон — такое же расхождение, как отставший файл: правило разложено,\n // а имён этого дерева при нём нет, и агент читает указание, которому некуда примениться.\n const empty: readonly ICompanion[] = unfilled(result);\n // Гард, которого не зовёт настройка агента, — такое же расхождение, как отставший файл:\n // он разложен, он коммитится, и по дереву его не отличить от работающего.\n const count: number = result.missing.size + result.gaps.length + pending.length + empty.length + result.unbound.length;\n if (!count) {\n return { code: 0, lines: [`sync --check: разложенное сходится с пакетом v${version}`] };\n }\n\n return { code: 1, lines: [`sync --check: расхождений ${count}`, ...describe(result)] };\n }\n\n const result: ISyncResult = runSync(config, root, version, assetsDir);\n // Перечисляются только дырки: раскладка не начата, и назвать файл «положенным» значило бы\n // сказать неправду — на диске его нет.\n if (result.missing.size) {\n return { code: 1, lines: ['раскладка не начата: нечего подставить в дырки', ...holes(result)] };\n }\n\n // Ресурс без вида под выбор дерева отбивает раскладку целиком, а не выпадает из неё молча:\n // правило, разложенное без инструмента, который оно зовёт, читается как действующее.\n if (result.gaps.length) {\n return {\n code: 1,\n lines: ['раскладка не начата: у этих ресурсов нет вида под выбор дерева', ...gapLines(result)],\n };\n }\n\n const refused: readonly IPlanned[] = result.planned.filter((entry: IPlanned): boolean => isRefusal(entry.outcome));\n if (refused.length) {\n return {\n code: 1,\n lines: [\n 'раскладка не начата: эти файлы пакет переписывать не станет',\n ...refused.map((entry: IPlanned): string => ` ${entry.path} — ${DONE_WORD[entry.outcome]}`),\n 'правку надо либо перенести в надстройку, либо снять — и повторить',\n `положенное не пакетом отдаётся ему командой \\`agent-kit adopt\\`: прежнее содержимое ляжет рядом с пометкой \\`${KEPT_SUFFIX}\\``,\n ],\n };\n }\n\n // Раскладка удалась, а гарды могут остаться неподключёнными: настройка агента принадлежит\n // дереву, и пакет в неё не пишет. Код возврата остаётся нулевым — файлы легли, — но молчать\n // об этом нельзя: узнают иначе, когда что-нибудь пройдёт мимо гарда.\n return {\n code: 0,\n lines: [\n ...(result.written.length\n ? [`разложено файлов: ${result.written.length}`, ...result.written.map((path: string): string => ` ${path}`)]\n : ['всё уже разложено']),\n ...unboundLines(result),\n ],\n };\n}\n\n/**\n * Отдать пакету файл, который лежит в дереве не от него.\n *\n * Пока команды не было, `sync` отказывал на такой файл поимённо и предлагал «перенести правку в\n * надстройку или снять» — то есть работу, которую делают руками, и до неё же сводилась вся\n * установка в живое дерево. При этом один чужой файл останавливал раскладку целиком.\n *\n * Молчаливой перезаписи здесь нет и быть не может: в файле лежит то, чего в дереве больше нигде\n * нет. Поэтому переход — это переименование прежнего содержимого рядом и повторный `sync`:\n * пакет кладёт своё, а прежнее остаётся на диске под именем с пометкой и ждёт разбора.\n */\nexport function adopt(env: IEnvironment, names: readonly string[]): IOutcomeOfCommand {\n const { root, version, assetsDir } = env;\n const config: IConfig | null = readConfig(root);\n if (!config) {\n return { code: 1, lines: [NO_CONFIG] };\n }\n\n const foreign: readonly IPlanned[] = planSync(config, root, version, assetsDir).planned.filter(\n (entry: IPlanned): boolean => entry.outcome === 'foreign'\n );\n if (!foreign.length) {\n return { code: 0, lines: ['чужих файлов на путях пакета нет'] };\n }\n\n // Имена принимаются как их печатает `sync`: путём в дереве. Без имён отдаются все — на\n // свежей установке их бывает столько же, сколько ресурсов, и перечислять их руками значит\n // делать ту же работу, ради которой команда заведена.\n const wanted: readonly IPlanned[] = names.length\n ? foreign.filter((entry: IPlanned): boolean => names.some((name: string): boolean => entry.path.endsWith(name)))\n : foreign;\n if (!wanted.length) {\n return {\n code: 1,\n lines: ['ни одно имя не отвечает чужому файлу; чужие сейчас такие:', ...foreign.map((e: IPlanned): string => ` ${e.path}`)],\n };\n }\n\n const moved: string[] = [];\n const blocked: string[] = [];\n for (const entry of wanted) {\n const path: string = join(root, entry.path);\n const kept: string = `${path}${KEPT_SUFFIX}`;\n if (existsSync(kept)) {\n blocked.push(` ${entry.path}${KEPT_SUFFIX} — уже лежит, разбери его прежде`);\n continue;\n }\n renameSync(path, kept);\n moved.push(` ${entry.path} → ${entry.path}${KEPT_SUFFIX}`);\n }\n\n return {\n code: blocked.length ? 1 : 0,\n lines: [\n ...(moved.length ? [`прежнее содержимое отложено: ${moved.length}`, ...moved, 'дальше: `agent-kit sync`'] : []),\n ...(blocked.length ? ['не тронуто:', ...blocked] : []),\n ],\n };\n}\n\nexport function doctor(env: IEnvironment): IOutcomeOfCommand {\n const { root, version, assetsDir } = env;\n const config: IConfig | null = readConfig(root);\n if (!config) {\n return { code: 1, lines: [NO_CONFIG] };\n }\n\n const result: ISyncResult = planSync(config, root, version, assetsDir);\n const counted: Map<TOutcome, number> = new Map();\n for (const entry of result.planned) {\n counted.set(entry.outcome, (counted.get(entry.outcome) ?? 0) + 1);\n }\n\n const catalog: readonly IEntryOfCatalog[] = readCatalog(assetsDir);\n const taken: number = collectAssets(config, assetsDir).length;\n const unanswered: readonly IAxis[] = unansweredAxes(readAxes(assetsDir), config.variants);\n const chosen: string[] = Object.entries(config.variants).map(([axis, value]: [string, string]): string => `${axis}: ${value}`);\n // Ресурс чужого вида в «не выбрано» не идёт: проект от него не отказывался — его в этом\n // дереве не существует, как не существует второго правила поставки.\n const foreignVariant: readonly IEntryOfCatalog[] = catalog.filter(\n (entry: IEntryOfCatalog): boolean => entry.variant !== null && config.variants[entry.variant.axis] !== entry.variant.value\n );\n const other: number = foreignVariant.length;\n // Ресурс, названный и в отказе, и чужим видом, считается один раз — иначе «не выбрано»\n // уходит в минус, а минус в отчёте читается как поломка счёта, а не как двойной счёт.\n const skipped: number = config.skip.filter((id: string): boolean =>\n foreignVariant.every((entry: IEntryOfCatalog): boolean => entry.id !== id)\n ).length;\n\n const lines: string[] = [\n `пакет v${version}, везёт ресурсов ${catalog.length}, взято ${taken}`,\n `не выбрано: ${catalog.length - taken - skipped - other}, пропущено: ${skipped}, другой вид: ${other}`,\n `значений в конфиге: ${Object.keys(config.vars).length}`,\n ...chosen,\n ...[...counted].map(([outcome, count]: [TOutcome, number]): string => `${STATE_WORD[outcome]}: ${count}`),\n ...describe(result),\n ...(unanswered.length ? ['не выбран вид — раскладка не начнётся:', ...axisLines(unanswered)] : []),\n // Про устаревшую сборку `doctor` говорит, но отказом её не считает: он ничего не пишет,\n // и прочитать состояние дерева можно и из вчерашней сборки — знать бы, что она вчерашняя.\n ...(env.stale ? ['собранное отстало от исходников — раскладка откажет:', ` правлено: ${env.stale.newest}`] : []),\n ];\n\n return { code: 0, lines };\n}\n\n/**\n * Что пакет везёт и что из этого взято здесь.\n *\n * Работает и без конфига: посмотреть, из чего выбирать, нужно раньше, чем выбор сделан, — иначе\n * имена законов взять неоткуда, кроме исходников пакета.\n */\nexport function list(env: IEnvironment): IOutcomeOfCommand {\n const { root, version, assetsDir } = env;\n const config: IConfig | null = readConfig(root);\n const catalog: readonly IEntryOfCatalog[] = readCatalog(assetsDir);\n const planned: Map<string, TOutcome> = new Map();\n\n if (config) {\n for (const entry of planSync(config, root, version, assetsDir).planned) {\n planned.set(entry.asset, entry.outcome);\n }\n }\n\n const stateOf: (entry: IEntryOfCatalog) => string = (entry: IEntryOfCatalog): string => {\n if (!config) {\n return 'везёт пакет';\n }\n if (entry.variant && config.variants[entry.variant.axis] !== entry.variant.value) {\n return OTHER_VARIANT;\n }\n if (config.skip.includes(entry.id)) {\n return SKIPPED;\n }\n if (!isChosen(entry, config)) {\n return NOT_CHOSEN;\n }\n const outcome: TOutcome | undefined = planned.get(entry.id);\n\n // Ресурса нет среди запланированных ровно в одном случае: в нём осталась дырка без\n // значения, и до решения о судьбе файла раскладка не дошла.\n return outcome ? STATE_WORD[outcome] : 'дырка без значения';\n };\n\n const name: number = catalog.reduce((found: number, entry: IEntryOfCatalog): number => Math.max(found, entry.name.length), 0);\n const state: number = catalog.reduce((found: number, entry: IEntryOfCatalog): number => Math.max(found, stateOf(entry).length), 0);\n const lines: string[] = [config ? `пакет v${version}` : `пакет v${version}, ${CONFIG_PATH} ещё не заведён`];\n\n for (const kind of KINDS) {\n const entries: readonly IEntryOfCatalog[] = catalog.filter((entry: IEntryOfCatalog): boolean => entry.kind === kind);\n if (!entries.length) {\n continue;\n }\n lines.push('', KIND_TITLE[kind]);\n lines.push(\n ...entries.map(\n (entry: IEntryOfCatalog): string => ` ${entry.name.padEnd(name)} ${stateOf(entry).padEnd(state)} ${entry.title}`\n )\n );\n }\n\n return { code: 0, lines };\n}\n"]}
|
package/lib/hooks-map.d.ts
CHANGED
|
@@ -1,9 +1,12 @@
|
|
|
1
1
|
/** Настройка агента, в которой живёт карта. Путь от корня дерева. */
|
|
2
2
|
export declare const SETTINGS_PATH: string;
|
|
3
3
|
export interface IHookBinding {
|
|
4
|
-
/** Событие агента: `PreToolUse`, `PostToolUse`, `SessionStart`. */
|
|
4
|
+
/** Событие агента: `PreToolUse`, `PostToolUse`, `SessionStart`, `Stop`. */
|
|
5
5
|
readonly event: string;
|
|
6
|
-
/**
|
|
6
|
+
/**
|
|
7
|
+
* Образец, по которому событие достаётся этому гарду. Пустой у события, которое не про
|
|
8
|
+
* инструмент: завершение хода приходит целиком, и выбирать в нём нечего.
|
|
9
|
+
*/
|
|
7
10
|
readonly matcher: string;
|
|
8
11
|
/** Путь разложенного гарда от корня дерева. */
|
|
9
12
|
readonly path: string;
|
package/lib/hooks-map.d.ts.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"hooks-map.d.ts","sourceRoot":"","sources":["../../../projects/agent-kit/src/lib/hooks-map.ts"],"names":[],"mappings":"AAmBA,qEAAqE;AACrE,eAAO,MAAM,aAAa,EAAE,MAAgC,CAAC;AAI7D,MAAM,WAAW,YAAY;IACzB,
|
|
1
|
+
{"version":3,"file":"hooks-map.d.ts","sourceRoot":"","sources":["../../../projects/agent-kit/src/lib/hooks-map.ts"],"names":[],"mappings":"AAmBA,qEAAqE;AACrE,eAAO,MAAM,aAAa,EAAE,MAAgC,CAAC;AAI7D,MAAM,WAAW,YAAY;IACzB,2EAA2E;IAC3E,QAAQ,CAAC,KAAK,EAAE,MAAM,CAAC;IACvB;;;OAGG;IACH,QAAQ,CAAC,OAAO,EAAE,MAAM,CAAC;IACzB,+CAA+C;IAC/C,QAAQ,CAAC,IAAI,EAAE,MAAM,CAAC;CACzB;AAED,2EAA2E;AAC3E,wBAAgB,SAAS,CAAC,IAAI,EAAE,MAAM,EAAE,IAAI,EAAE,MAAM,GAAG,YAAY,GAAG,IAAI,CAIzE;AAED;;;;;GAKG;AACH,wBAAgB,YAAY,CAAC,QAAQ,EAAE,SAAS,YAAY,EAAE,GAAG,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,CAwBvF;AAED,qFAAqF;AACrF,wBAAgB,eAAe,CAAC,IAAI,EAAE,MAAM,GAAG,SAAS,MAAM,EAAE,CAkB/D;AAED,4FAA4F;AAC5F,wBAAgB,YAAY,CAAC,QAAQ,EAAE,SAAS,YAAY,EAAE,EAAE,IAAI,EAAE,MAAM,GAAG,SAAS,YAAY,EAAE,CAIrG"}
|
package/lib/hooks-map.js
CHANGED
|
@@ -18,11 +18,11 @@ import { existsSync, readFileSync } from 'node:fs';
|
|
|
18
18
|
import { join } from 'node:path';
|
|
19
19
|
/** Настройка агента, в которой живёт карта. Путь от корня дерева. */
|
|
20
20
|
export const SETTINGS_PATH = '.claude/settings.json';
|
|
21
|
-
const DECLARATION = /^#\s*rt-hook:\s*(\S+)\
|
|
21
|
+
const DECLARATION = /^#\s*rt-hook:\s*(\S+)(?:[ \t]+(\S.*))?$/m;
|
|
22
22
|
/** Что гард говорит о себе. Молчит — он не подключается к агенту вовсе. */
|
|
23
23
|
export function bindingOf(text, path) {
|
|
24
24
|
const found = text.match(DECLARATION);
|
|
25
|
-
return found ? { event: found[1], matcher: found[2].trim(), path } : null;
|
|
25
|
+
return found ? { event: found[1], matcher: (found[2] ?? '').trim(), path } : null;
|
|
26
26
|
}
|
|
27
27
|
/**
|
|
28
28
|
* Раздел `hooks` для настройки агента: событие → образец → команда.
|
|
@@ -39,10 +39,15 @@ export function hooksSection(bindings) {
|
|
|
39
39
|
}
|
|
40
40
|
const section = {};
|
|
41
41
|
for (const [event, byMatcher] of [...events].sort()) {
|
|
42
|
-
section[event] = [...byMatcher].sort().map(([matcher, paths]) =>
|
|
43
|
-
|
|
44
|
-
|
|
45
|
-
|
|
42
|
+
section[event] = [...byMatcher].sort().map(([matcher, paths]) => {
|
|
43
|
+
const hooks = paths.map((path) => ({
|
|
44
|
+
type: 'command',
|
|
45
|
+
command: `$CLAUDE_PROJECT_DIR/${path}`,
|
|
46
|
+
}));
|
|
47
|
+
// Запись без образца — не запись с пустым образцом: агент читает пустую строку как
|
|
48
|
+
// образец, которому не соответствует ни один вызов, и гард молча не зовётся.
|
|
49
|
+
return matcher ? { matcher, hooks } : { hooks };
|
|
50
|
+
});
|
|
46
51
|
}
|
|
47
52
|
return section;
|
|
48
53
|
}
|
package/lib/hooks-map.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"hooks-map.js","sourceRoot":"","sources":["../../../projects/agent-kit/src/lib/hooks-map.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;GAeG;AACH,OAAO,EAAE,UAAU,EAAE,YAAY,EAAE,MAAM,SAAS,CAAC;AACnD,OAAO,EAAE,IAAI,EAAE,MAAM,WAAW,CAAC;AAEjC,qEAAqE;AACrE,MAAM,CAAC,MAAM,aAAa,GAAW,uBAAuB,CAAC;AAE7D,MAAM,WAAW,GAAW,
|
|
1
|
+
{"version":3,"file":"hooks-map.js","sourceRoot":"","sources":["../../../projects/agent-kit/src/lib/hooks-map.ts"],"names":[],"mappings":"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","sourcesContent":["/**\n * Карта хуков: чем разложенные гарды подключаются к агенту.\n *\n * Раскладка кладёт файлы, а зовёт их запись в настройке агента — чужом JSON, которым пакет не\n * владеет. Пока о ней молчали, свежее дерево получало два десятка гардов, ни один из которых не\n * срабатывал, и узнавало об этом, когда что-нибудь проходило мимо.\n *\n * Пакет не пишет в чужую настройку сам: файл держит проект, в нём лежит и то, о чём пакет не\n * знает вовсе, а слияние чужого JSON молча теряет несовпавшее. Вместо этого он собирает готовый\n * кусок и проверяет, что он вставлен. Это дешевле и честнее: правку в свою настройку делает тот,\n * кто за неё отвечает.\n *\n * Событие и образец вызова гард несёт сам — строкой `# rt-hook: <событие> <образец>` во второй\n * строке файла. Карта, выписанная отдельным списком, разошлась бы с набором гардов на первом же\n * добавленном, и заметить это было бы нечем: гард просто не звался бы.\n */\nimport { existsSync, readFileSync } from 'node:fs';\nimport { join } from 'node:path';\n\n/** Настройка агента, в которой живёт карта. Путь от корня дерева. */\nexport const SETTINGS_PATH: string = '.claude/settings.json';\n\nconst DECLARATION: RegExp = /^#\\s*rt-hook:\\s*(\\S+)(?:[ \\t]+(\\S.*))?$/m;\n\nexport interface IHookBinding {\n /** Событие агента: `PreToolUse`, `PostToolUse`, `SessionStart`, `Stop`. */\n readonly event: string;\n /**\n * Образец, по которому событие достаётся этому гарду. Пустой у события, которое не про\n * инструмент: завершение хода приходит целиком, и выбирать в нём нечего.\n */\n readonly matcher: string;\n /** Путь разложенного гарда от корня дерева. */\n readonly path: string;\n}\n\n/** Что гард говорит о себе. Молчит — он не подключается к агенту вовсе. */\nexport function bindingOf(text: string, path: string): IHookBinding | null {\n const found: RegExpMatchArray | null = text.match(DECLARATION);\n\n return found ? { event: found[1], matcher: (found[2] ?? '').trim(), path } : null;\n}\n\n/**\n * Раздел `hooks` для настройки агента: событие → образец → команда.\n *\n * Гарды с одинаковым образцом внутри события собираются в одну запись — так же, как это пишут\n * руками, и так же, как читает агент.\n */\nexport function hooksSection(bindings: readonly IHookBinding[]): Record<string, unknown> {\n const events: Map<string, Map<string, string[]>> = new Map();\n\n for (const binding of bindings) {\n const byMatcher: Map<string, string[]> = events.get(binding.event) ?? new Map();\n byMatcher.set(binding.matcher, [...(byMatcher.get(binding.matcher) ?? []), binding.path]);\n events.set(binding.event, byMatcher);\n }\n\n const section: Record<string, unknown> = {};\n for (const [event, byMatcher] of [...events].sort()) {\n section[event] = [...byMatcher].sort().map(([matcher, paths]: [string, readonly string[]]): unknown => {\n const hooks: unknown[] = paths.map((path: string): unknown => ({\n type: 'command',\n command: `$CLAUDE_PROJECT_DIR/${path}`,\n }));\n\n // Запись без образца — не запись с пустым образцом: агент читает пустую строку как\n // образец, которому не соответствует ни один вызов, и гард молча не зовётся.\n return matcher ? { matcher, hooks } : { hooks };\n });\n }\n\n return section;\n}\n\n/** Пути гардов, названные в настройке агента этого дерева. Нет файла — ни одного. */\nexport function boundInSettings(root: string): readonly string[] {\n const path: string = join(root, SETTINGS_PATH);\n if (!existsSync(path)) {\n return [];\n }\n let text: string;\n try {\n text = readFileSync(path, 'utf8');\n } catch {\n return [];\n }\n\n // Настройка читается текстом, а не разбором: у неё нет объявленной формы, и дерево вправе\n // держать её так, как ему удобно, — вплоть до комментариев, которых JSON не разбирает. Ищется\n // одно: назван ли путь гарда хоть где-нибудь в ней.\n return [...text.matchAll(/[\\w./$-]*\\.claude\\/hooks\\/[\\w.-]+\\.sh/g)].map((found: RegExpMatchArray): string =>\n found[0].replace(/^.*?(\\.claude\\/)/, '$1')\n );\n}\n\n/** Разложенные гарды, которых в настройке агента нет: они лежат, но их никто не позовёт. */\nexport function unboundHooks(bindings: readonly IHookBinding[], root: string): readonly IHookBinding[] {\n const bound: ReadonlySet<string> = new Set(boundInSettings(root));\n\n return bindings.filter((binding: IHookBinding): boolean => !bound.has(binding.path));\n}\n"]}
|
package/package.json
CHANGED
|
Binary file
|
|
Binary file
|