gennady 0.6.0 → 0.6.1
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/.ai/agents/agent-resolve-conflicts.xml +148 -0
- package/dist/chunks/{index-C0andxna.js → index-B3r-YFvt.js} +1 -1
- package/dist/chunks/{index-B5bA2T7A.js → index-Bh0p7rJg.js} +2 -2
- package/dist/chunks/{index-iqg0w_pE.js → index-BrobNwbS.js} +1 -1
- package/dist/chunks/{index-5xIgwwKx.js → index-Bx_P7mlL.js} +1 -1
- package/dist/chunks/{index-CNbmXK8M.js → index-C4jt5WBP.js} +1 -1
- package/dist/chunks/{index-B4m0-PAT.js → index-D1Hurfwu.js} +2 -2
- package/dist/chunks/{index-Dqe1TdW4.js → index-DgAmONSz.js} +1 -1
- package/dist/chunks/{index-B63fYXL2.js → index-Gy1n7hRU.js} +1 -1
- package/dist/chunks/{run-review-command.logic-a_M3CkeZ.js → run-review-command.logic-BQDGxh0f.js} +1 -1
- package/dist/chunks/{shared-BgLzFWMH.js → shared-D0kSJB49.js} +134 -110
- package/dist/gennady.js +7 -7
- package/dist/index.js +2 -2
- package/package.json +1 -1
|
@@ -0,0 +1,148 @@
|
|
|
1
|
+
<!--
|
|
2
|
+
ENTRY POINT: Это не документ, а исполняемый манифест.
|
|
3
|
+
Ты — агент разрешения merge-конфликтов. Начинай немедленно.
|
|
4
|
+
-->
|
|
5
|
+
<Agent_Execution_Manifest id="ResolveConflicts_Master_v1" schema_version="2026.2">
|
|
6
|
+
<Configuration>
|
|
7
|
+
<Agent_Identity>
|
|
8
|
+
<Role>ResolveConflicts</Role>
|
|
9
|
+
<Mission>
|
|
10
|
+
Разрешить merge-конфликты так, чтобы сохранить намерения обеих веток.
|
|
11
|
+
При высокой уверенности — завершить задачу до готового staged-состояния.
|
|
12
|
+
При риске ошибки — остановиться и перейти в управляемый диалог с пользователем.
|
|
13
|
+
</Mission>
|
|
14
|
+
</Agent_Identity>
|
|
15
|
+
<Belief_State>
|
|
16
|
+
<Axiom id="AX_INTENT_OVER_MARKERS">
|
|
17
|
+
Конфликтные маркеры — это симптом. Решение должно опираться на цель изменений в обеих ветках.
|
|
18
|
+
</Axiom>
|
|
19
|
+
<Axiom id="AX_EVIDENCE_FIRST">
|
|
20
|
+
Любое решение обосновывается фактами: история коммитов, итоговые diff от merge-base, контекст использования кода.
|
|
21
|
+
</Axiom>
|
|
22
|
+
<Axiom id="AX_OPERATOR_LANGUAGE">
|
|
23
|
+
Все сообщения оператору (вопросы, план, отчёты, итоговые решения) формулируй на русском языке.
|
|
24
|
+
Английский допустим только для кода, команд, идентификаторов и технических терминов.
|
|
25
|
+
</Axiom>
|
|
26
|
+
<Axiom id="AX_CONFIDENCE_GATE">
|
|
27
|
+
Применяй изменения автоматически только при достаточной уверенности и отсутствии критичных сомнений.
|
|
28
|
+
</Axiom>
|
|
29
|
+
<Axiom id="AX_SAFE_VERIFY">
|
|
30
|
+
После автоматического разрешения обязательно проверь код: используй <!--ai:verify-axiom-hint-->.
|
|
31
|
+
</Axiom>
|
|
32
|
+
<Axiom id="AX_USER_DIALOG">
|
|
33
|
+
Если есть неоднозначность, влияние на архитектуру или риск регрессии — переходи в диалог и не форсируй auto-resolve.
|
|
34
|
+
</Axiom>
|
|
35
|
+
</Belief_State>
|
|
36
|
+
<Tool_Usage_Policy>
|
|
37
|
+
<Priority_Matrix>
|
|
38
|
+
<Primary_Tools>
|
|
39
|
+
Native IDE tools для чтения/редактирования/поиска — основной режим.
|
|
40
|
+
</Primary_Tools>
|
|
41
|
+
<Secondary_Tools>
|
|
42
|
+
Terminal для git-анализа и верификации: <!--ai:verify-tools-example-->.
|
|
43
|
+
</Secondary_Tools>
|
|
44
|
+
</Priority_Matrix>
|
|
45
|
+
</Tool_Usage_Policy>
|
|
46
|
+
</Configuration>
|
|
47
|
+
<Input_Data>
|
|
48
|
+
<!--Resolve_Conflicts_Artifact-->
|
|
49
|
+
</Input_Data>
|
|
50
|
+
<Execution_Plan>
|
|
51
|
+
<Step id="STEP_1_INGEST_CONTEXT">
|
|
52
|
+
<Goal>Понять merge-контекст и список конфликтов.</Goal>
|
|
53
|
+
<Action>
|
|
54
|
+
<!--ai:first-->
|
|
55
|
+
Прочитай `<Merge_Conflict_Context>`.
|
|
56
|
+
Зафиксируй:
|
|
57
|
+
- `current_branch`, `incoming_branch`, `merge_base`;
|
|
58
|
+
- список `<Conflict_Files><File ... />` и их `path`, `status`, `kind`, `conflictRegions`, `binary`.
|
|
59
|
+
Если `binary=true`, не пытайся редактировать бинарный файл автоматически: пометь как manual.
|
|
60
|
+
</Action>
|
|
61
|
+
</Step>
|
|
62
|
+
<Step id="STEP_2_BRANCH_INTENT_ANALYSIS">
|
|
63
|
+
<Goal>Построить понимание, зачем меняли каждый конфликтующий файл в обеих ветках.</Goal>
|
|
64
|
+
<Action>
|
|
65
|
+
Для каждого конфликтующего текстового файла:
|
|
66
|
+
1. Найди unique commits incoming-ветки для файла: от `merge_base..incoming`.
|
|
67
|
+
2. Найди unique commits current-ветки для файла: от `merge_base..current`.
|
|
68
|
+
3. Для каждой стороны зафиксируй:
|
|
69
|
+
- краткий intent;
|
|
70
|
+
- критичность (low/medium/high/critical);
|
|
71
|
+
- масштаб (localized/global);
|
|
72
|
+
- ключевые изменения.
|
|
73
|
+
4. Если commit history слишком большая, сначала возьми последние релевантные изменения, но не теряй критические правки (security/hotfix).
|
|
74
|
+
</Action>
|
|
75
|
+
</Step>
|
|
76
|
+
<Step id="STEP_3_CONFLICT_DECISION">
|
|
77
|
+
<Goal>Принять решение по каждому конфликтному региону.</Goal>
|
|
78
|
+
<Action>
|
|
79
|
+
Для каждого конфликтного региона выбери стратегию:
|
|
80
|
+
- `take-current`
|
|
81
|
+
- `take-incoming`
|
|
82
|
+
- `merge-both`
|
|
83
|
+
- `rewrite`
|
|
84
|
+
|
|
85
|
+
Для каждого региона сформируй:
|
|
86
|
+
- `analysis`: почему возник конфликт;
|
|
87
|
+
- `strategy`: выбранный подход;
|
|
88
|
+
- `resolvedCode`: итоговый код без маркеров;
|
|
89
|
+
- `confidence` (0-100);
|
|
90
|
+
- `riskFlags`: список рисков (архитектура, безопасность, API-совместимость, тестовый пробел).
|
|
91
|
+
|
|
92
|
+
Общие правила приоритета:
|
|
93
|
+
1. Критичный hotfix/security не теряется.
|
|
94
|
+
2. Рефакторинг не должен ломать исправления багов.
|
|
95
|
+
3. Если изменения совместимы — объединяй, а не отбрасывай.
|
|
96
|
+
</Action>
|
|
97
|
+
</Step>
|
|
98
|
+
<Step id="STEP_4_CONFIDENCE_SWITCH">
|
|
99
|
+
<Goal>Выбрать режим: автоматическое применение или диалог с пользователем.</Goal>
|
|
100
|
+
<Action>
|
|
101
|
+
<Switch exclusive="true" purpose="Выбор режима по уровню уверенности и рискам">
|
|
102
|
+
<Case when="Для каждого конфликтного региона confidence >= 85 и нет riskFlags высокого уровня">
|
|
103
|
+
- Примени resolvedCode ко всем регионам.
|
|
104
|
+
- Удали конфликтные маркеры.
|
|
105
|
+
- Выполни `git add` только для файлов, полностью разрешённых без сомнений.
|
|
106
|
+
- Перейди к STEP_5.
|
|
107
|
+
</Case>
|
|
108
|
+
<Case when="Есть регионы с confidence 60-84 или есть значимые riskFlags">
|
|
109
|
+
- Не выполняй auto-apply для спорных регионов.
|
|
110
|
+
- Перейди в диалог с пользователем.
|
|
111
|
+
- Покажи 1-3 точечных вопроса по развилке и предложи рекомендуемый вариант.
|
|
112
|
+
- Для каждого спорного региона дай краткое сравнение вариантов (`current`, `incoming`, `merge`) и ожидаемые последствия.
|
|
113
|
+
- Остановись и жди ответа пользователя.
|
|
114
|
+
</Case>
|
|
115
|
+
<Case when="Есть регионы с confidence < 60 или не хватает фактов для безопасного выбора">
|
|
116
|
+
- Не вноси автоматические изменения в спорные участки.
|
|
117
|
+
- Сформируй план ручного разрешения с приоритетами и рисками.
|
|
118
|
+
- Запроси решение пользователя по каждому блокирующему региону.
|
|
119
|
+
- Остановись и жди ответа пользователя.
|
|
120
|
+
</Case>
|
|
121
|
+
</Switch>
|
|
122
|
+
</Action>
|
|
123
|
+
</Step>
|
|
124
|
+
<Step id="STEP_5_VERIFY_AND_REPORT">
|
|
125
|
+
<Precondition>STEP_4 выбрал auto-apply для всех регионов или спорные регионы уже подтверждены пользователем.</Precondition>
|
|
126
|
+
<Goal>Проверить результат и отчитаться прозрачно.</Goal>
|
|
127
|
+
<Action>
|
|
128
|
+
1. Verify: <!--ai:verify-step-commands-->
|
|
129
|
+
2. Сформируй отчёт:
|
|
130
|
+
- какие файлы разрешены автоматически;
|
|
131
|
+
- какие стратегии применены;
|
|
132
|
+
- итоговый confidence по файлам;
|
|
133
|
+
- какие команды проверки выполнены и их результат.
|
|
134
|
+
3. Если проверки упали — покажи причину и предложи дальнейшие шаги.
|
|
135
|
+
4. Не выполняй `git commit` автоматически.
|
|
136
|
+
</Action>
|
|
137
|
+
</Step>
|
|
138
|
+
</Execution_Plan>
|
|
139
|
+
<Output_Contracts>
|
|
140
|
+
<Contract id="REPORT_FORMAT">
|
|
141
|
+
Итог должен содержать:
|
|
142
|
+
- `Resolved Automatically` (список файлов и стратегии),
|
|
143
|
+
- `Needs User Decision` (если есть),
|
|
144
|
+
- `Verification` (какие команды и статус),
|
|
145
|
+
- `Next Steps` (что сделать пользователю дальше).
|
|
146
|
+
</Contract>
|
|
147
|
+
</Output_Contracts>
|
|
148
|
+
</Agent_Execution_Manifest>
|
|
@@ -1,5 +1,5 @@
|
|
|
1
|
-
import { p as j, s as e, g as x } from "./shared-
|
|
2
|
-
import { p as T, A as E } from "./index-
|
|
1
|
+
import { p as j, s as e, g as x } from "./shared-D0kSJB49.js";
|
|
2
|
+
import { p as T, A as E } from "./index-BrobNwbS.js";
|
|
3
3
|
import { readdirSync as G, readFileSync as P } from "node:fs";
|
|
4
4
|
import { join as h, dirname as k } from "node:path";
|
|
5
5
|
import { fileURLToPath as N } from "node:url";
|
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
import { AiLegacyModel as h } from "../index.js";
|
|
2
|
-
import { G as f, u as c } from "./shared-
|
|
2
|
+
import { G as f, u as c } from "./shared-D0kSJB49.js";
|
|
3
3
|
import { l as p } from "./services-Sb7TwLxt.js";
|
|
4
4
|
import { readFileSync as l } from "node:fs";
|
|
5
5
|
import { dirname as _, join as m } from "node:path";
|
|
@@ -7,7 +7,7 @@ import it from "stream";
|
|
|
7
7
|
import bn from "events";
|
|
8
8
|
import Ft from "fs";
|
|
9
9
|
import { l as Qt } from "./services-Sb7TwLxt.js";
|
|
10
|
-
import { p as Pn, s as ie } from "./shared-
|
|
10
|
+
import { p as Pn, s as ie } from "./shared-D0kSJB49.js";
|
|
11
11
|
var Cn = typeof globalThis < "u" ? globalThis : typeof window < "u" ? window : typeof global < "u" ? global : typeof self < "u" ? self : {};
|
|
12
12
|
function Tn(u) {
|
|
13
13
|
return u && u.__esModule && Object.prototype.hasOwnProperty.call(u, "default") ? u.default : u;
|
|
@@ -2,8 +2,8 @@ import u from "node:fs";
|
|
|
2
2
|
import v from "node:os";
|
|
3
3
|
import P from "node:path";
|
|
4
4
|
import { execSync as _ } from "node:child_process";
|
|
5
|
-
import { p as d, A as E } from "./index-
|
|
6
|
-
import { g as H, s as t, x as D, p as F } from "./shared-
|
|
5
|
+
import { p as d, A as E } from "./index-BrobNwbS.js";
|
|
6
|
+
import { g as H, s as t, x as D, p as F } from "./shared-D0kSJB49.js";
|
|
7
7
|
import { l as N } from "./services-Sb7TwLxt.js";
|
|
8
8
|
class U {
|
|
9
9
|
init;
|
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import { p as D, e as o, b as M, a as H, c as B, l as U, d as O, f as k, s as F } from "./shared-
|
|
1
|
+
import { p as D, e as o, b as M, a as H, c as B, l as U, d as O, f as k, s as F } from "./shared-D0kSJB49.js";
|
|
2
2
|
import a from "node:fs";
|
|
3
3
|
import P from "node:path";
|
|
4
4
|
function C(e) {
|
package/dist/chunks/{run-review-command.logic-a_M3CkeZ.js → run-review-command.logic-BQDGxh0f.js}
RENAMED
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import { p as v, a as g, b, c as R, l as j, d as y, f as _, s as u } from "./shared-
|
|
1
|
+
import { p as v, a as g, b, c as R, l as j, d as y, f as _, s as u } from "./shared-D0kSJB49.js";
|
|
2
2
|
import { V as A } from "./services-Sb7TwLxt.js";
|
|
3
3
|
function H(r) {
|
|
4
4
|
const e = v(r, {
|
|
@@ -1,8 +1,8 @@
|
|
|
1
|
-
import { execSync as
|
|
2
|
-
import { l as
|
|
3
|
-
import
|
|
4
|
-
import
|
|
5
|
-
import { fileURLToPath as
|
|
1
|
+
import { execSync as A } from "node:child_process";
|
|
2
|
+
import { l as x } from "./services-Sb7TwLxt.js";
|
|
3
|
+
import u, { existsSync as _, readFileSync as v } from "node:fs";
|
|
4
|
+
import m, { join as L } from "node:path";
|
|
5
|
+
import { fileURLToPath as N } from "node:url";
|
|
6
6
|
const p = ["plain", "nocolor", "noColor", "no-color", "color=no", "color=never"].some(
|
|
7
7
|
(r) => process.argv.includes(`-${r}`) || process.argv.includes(`--${r}`)
|
|
8
8
|
), d = {
|
|
@@ -51,7 +51,7 @@ const p = ["plain", "nocolor", "noColor", "no-color", "color=no", "color=never"]
|
|
|
51
51
|
bgCyanBright: "\x1B[106m",
|
|
52
52
|
bgWhiteBright: "\x1B[107m"
|
|
53
53
|
};
|
|
54
|
-
function
|
|
54
|
+
function $(r = []) {
|
|
55
55
|
const s = (n) => p ? n : r.join("") + n + d.reset;
|
|
56
56
|
return new Proxy(s, {
|
|
57
57
|
get(n, t) {
|
|
@@ -59,7 +59,7 @@ function j(r = []) {
|
|
|
59
59
|
return () => p ? "%s" : r.join("") + "%s" + d.reset;
|
|
60
60
|
if (t in d) {
|
|
61
61
|
const a = d[t];
|
|
62
|
-
return
|
|
62
|
+
return $(p ? [] : [...r, a].filter(Boolean));
|
|
63
63
|
}
|
|
64
64
|
},
|
|
65
65
|
apply(n, t, a) {
|
|
@@ -68,7 +68,7 @@ function j(r = []) {
|
|
|
68
68
|
}
|
|
69
69
|
});
|
|
70
70
|
}
|
|
71
|
-
const
|
|
71
|
+
const st = $(), rt = (r, s = {}) => {
|
|
72
72
|
const n = { _: [] };
|
|
73
73
|
return r.slice(2).forEach((a) => {
|
|
74
74
|
if (a.startsWith("-")) {
|
|
@@ -82,7 +82,7 @@ const Z = j(), tt = (r, s = {}) => {
|
|
|
82
82
|
} else
|
|
83
83
|
n._.push(a);
|
|
84
84
|
}), n;
|
|
85
|
-
},
|
|
85
|
+
}, T = {
|
|
86
86
|
js: "JavaScript",
|
|
87
87
|
jsx: "JavaScript",
|
|
88
88
|
ts: "TypeScript",
|
|
@@ -108,16 +108,16 @@ const Z = j(), tt = (r, s = {}) => {
|
|
|
108
108
|
sass: "Sass",
|
|
109
109
|
md: "Markdown",
|
|
110
110
|
mdc: "Markdown"
|
|
111
|
-
},
|
|
111
|
+
}, b = (r) => T[r] ?? void 0, nt = () => {
|
|
112
112
|
try {
|
|
113
|
-
return
|
|
113
|
+
return A("osascript -e 'user locale of (get system info)'").toString().trim().toLowerCase().split("_").filter((n) => n !== "en" && n !== "us")[0] ?? "en";
|
|
114
114
|
} catch {
|
|
115
115
|
return "en";
|
|
116
116
|
}
|
|
117
|
-
},
|
|
117
|
+
}, w = (r) => {
|
|
118
118
|
const s = r.match(/[\p{L}\p{N}_]+|[^\s\p{L}\p{N}_]/gu);
|
|
119
119
|
return s ? s.length : 0;
|
|
120
|
-
},
|
|
120
|
+
}, M = [
|
|
121
121
|
"^package\\.json",
|
|
122
122
|
"^tsconfig\\.json",
|
|
123
123
|
"^babel\\.config\\.json",
|
|
@@ -127,7 +127,7 @@ const Z = j(), tt = (r, s = {}) => {
|
|
|
127
127
|
"^\\.env(?:\\.[\\w]+)?",
|
|
128
128
|
"^\\..+",
|
|
129
129
|
".*\\.(?:yml|yaml|rc|ini|conf)"
|
|
130
|
-
],
|
|
130
|
+
], D = [
|
|
131
131
|
"^package-lock\\.json",
|
|
132
132
|
"^npm-shrinkwrap\\.json",
|
|
133
133
|
"^yarn(?:-lock)?\\.(?:yaml|yml|toml)",
|
|
@@ -136,24 +136,24 @@ const Z = j(), tt = (r, s = {}) => {
|
|
|
136
136
|
"^podfile\\.lock",
|
|
137
137
|
"^go\\.sum",
|
|
138
138
|
"^gemfile\\.lock"
|
|
139
|
-
],
|
|
139
|
+
], F = {
|
|
140
140
|
doc: /\.(md|markdown|txt|rst)$/i,
|
|
141
|
-
cfg: new RegExp(
|
|
141
|
+
cfg: new RegExp(M.join("|"), "i"),
|
|
142
142
|
img: /\.(png|jpe?g|gif|svg|bmp|tiff|ico)$/i,
|
|
143
143
|
css: /\.(css|less|scss|sass|styl)$/i,
|
|
144
144
|
html: /\.(html?)$/i,
|
|
145
145
|
code: /\.(js|jsx|ts|tsx|java|py|c|cpp|cs|rb|php|go|swift|m|mm|kt|sh|bash)$/i,
|
|
146
146
|
bin: /^(exe|dll|so|bin)\b/i,
|
|
147
|
-
lock: new RegExp(
|
|
147
|
+
lock: new RegExp(D.join("|"), "i"),
|
|
148
148
|
json: /\.json$/i
|
|
149
|
-
},
|
|
149
|
+
}, B = (r, s) => {
|
|
150
150
|
if (s?.extra && Array.isArray(s.extra)) {
|
|
151
151
|
for (const t of s.extra)
|
|
152
152
|
if (/^Binary files? /i.test(t) || /GIT binary patch/i.test(t))
|
|
153
153
|
return "bin";
|
|
154
154
|
}
|
|
155
|
-
return Object.entries(
|
|
156
|
-
},
|
|
155
|
+
return Object.entries(F).find(([, t]) => t.test(r))?.[0] ?? "other";
|
|
156
|
+
}, O = (r) => {
|
|
157
157
|
const s = r.split(`
|
|
158
158
|
`), n = [];
|
|
159
159
|
let t = null, a = null;
|
|
@@ -161,14 +161,14 @@ const Z = j(), tt = (r, s = {}) => {
|
|
|
161
161
|
if (e.startsWith("diff --git")) {
|
|
162
162
|
if (t) {
|
|
163
163
|
t.diff.tokens = t.diff.hunks.reduce(
|
|
164
|
-
(g,
|
|
164
|
+
(g, R) => g + R.tokens,
|
|
165
165
|
0
|
|
166
166
|
), t.tokens = t.diff.tokens;
|
|
167
167
|
const l = t.filename.match(/\.([^.]+)$/);
|
|
168
|
-
t.ext = l?.[1]?.toLowerCase() ?? "", t.category =
|
|
168
|
+
t.ext = l?.[1]?.toLowerCase() ?? "", t.category = B(
|
|
169
169
|
t.filename,
|
|
170
170
|
t.metadata
|
|
171
|
-
), t.programmingLanguage =
|
|
171
|
+
), t.programmingLanguage = b(t.ext), n.push(t);
|
|
172
172
|
}
|
|
173
173
|
const i = e.match(/^diff --git a\/(.+?) b\/(.+)$/), o = i?.[1] ?? null;
|
|
174
174
|
t = {
|
|
@@ -213,31 +213,31 @@ const Z = j(), tt = (r, s = {}) => {
|
|
|
213
213
|
} else t && e.startsWith("index") ? t.metadata.index = e.substring(5).trim() : t && (e.startsWith("--- ") || e.startsWith("+++ ")) ? e.startsWith("--- ") ? t.metadata.oldFileMarker = e : t.metadata.newFileMarker = e : t && e.startsWith("@@") ? (a = {
|
|
214
214
|
header: e,
|
|
215
215
|
changes: [e],
|
|
216
|
-
tokens:
|
|
217
|
-
}, t.diff.hunks.push(a)) : a && (e.startsWith("+") || e.startsWith("-") || e.startsWith(" ")) ? (a.changes.push(e), a.tokens +=
|
|
216
|
+
tokens: w(e)
|
|
217
|
+
}, t.diff.hunks.push(a)) : a && (e.startsWith("+") || e.startsWith("-") || e.startsWith(" ")) ? (a.changes.push(e), a.tokens += w(e)) : t && (Array.isArray(t.metadata.extra) || (t.metadata.extra = []), t.metadata.extra.push(e));
|
|
218
218
|
}), t) {
|
|
219
219
|
const e = t, i = e.filename.match(/\.([^.]+)$/);
|
|
220
220
|
e.diff.tokens = e.diff.hunks.reduce(
|
|
221
221
|
(o, c) => o + c.tokens,
|
|
222
222
|
0
|
|
223
|
-
), e.tokens = e.diff.tokens, e.ext = i?.[1]?.toLowerCase() ?? "", e.category =
|
|
223
|
+
), e.tokens = e.diff.tokens, e.ext = i?.[1]?.toLowerCase() ?? "", e.category = B(e.filename, e.metadata), e.programmingLanguage = b(e.ext), n.push(e);
|
|
224
224
|
}
|
|
225
225
|
return n;
|
|
226
|
-
},
|
|
226
|
+
}, f = (r) => {
|
|
227
227
|
try {
|
|
228
|
-
return
|
|
228
|
+
return A(r, { encoding: "utf-8" });
|
|
229
229
|
} catch (s) {
|
|
230
|
-
return
|
|
230
|
+
return x.error("[execSyncSafe] [running → failed] Command failed", { cause: s }), "";
|
|
231
231
|
}
|
|
232
|
-
},
|
|
233
|
-
const s = (
|
|
232
|
+
}, E = (r) => /\.(test|spec)s?\./.test(r), G = () => f("git branch --list 2>/dev/null")?.match(/\s*\*?\s*(master|main)$/m)?.[1] ?? "master", at = () => f("git rev-parse --abbrev-ref HEAD 2>/dev/null").trim() || "HEAD", it = () => {
|
|
233
|
+
const s = (f("git config --get remote.origin.url 2>/dev/null").trim() || f("git remote get-url origin 2>/dev/null").trim() || "").trim();
|
|
234
234
|
if (!s) return null;
|
|
235
235
|
if (/^[a-z]+:\/\//i.test(s))
|
|
236
236
|
try {
|
|
237
237
|
const t = new URL(s), a = (t.hostname || "").toLowerCase(), e = (t.protocol || "").replace(/:$/, "").toLowerCase(), i = (t.pathname || "").replace(/^\/+/, "").replace(/\.git$/i, "");
|
|
238
238
|
return !a || !i ? null : { host: a, project: i, scheme: e };
|
|
239
239
|
} catch (t) {
|
|
240
|
-
|
|
240
|
+
x.debug("[getGitRemote] [parsing → skip] URL parse failed", { cause: t });
|
|
241
241
|
}
|
|
242
242
|
const n = s.match(/^[\w.-]+@([^:\/]+)[:\/](.+)$/);
|
|
243
243
|
if (n) {
|
|
@@ -245,20 +245,20 @@ const Z = j(), tt = (r, s = {}) => {
|
|
|
245
245
|
return !t || !a ? null : { host: t, project: a, scheme: e };
|
|
246
246
|
}
|
|
247
247
|
return null;
|
|
248
|
-
},
|
|
248
|
+
}, P = () => {
|
|
249
249
|
try {
|
|
250
|
-
const r =
|
|
250
|
+
const r = f(`git rev-list --count HEAD ^${G()} 2>/dev/null`);
|
|
251
251
|
return parseInt(r, 10) || 0;
|
|
252
252
|
} catch (r) {
|
|
253
|
-
return
|
|
253
|
+
return x.debug("[getGitCommitCount] [counting → fallback] Using 0", { cause: r }), 0;
|
|
254
254
|
}
|
|
255
|
-
},
|
|
256
|
-
const s =
|
|
257
|
-
(o) => !o.isDeleted && !o.isRenamed && !
|
|
255
|
+
}, W = (r) => f(r ? `git diff ${r}` : "git diff HEAD"), ot = (r) => {
|
|
256
|
+
const s = W(r), n = O(s).sort((o, c) => o.tokens - c.tokens), t = n.filter(
|
|
257
|
+
(o) => !o.isDeleted && !o.isRenamed && !E(o.filename) && (o.category === "config" || o.programmingLanguage)
|
|
258
258
|
);
|
|
259
259
|
t.length || t.push(
|
|
260
260
|
...n.filter(
|
|
261
|
-
(o) => !o.isDeleted && !o.isRenamed && (o.category === "doc" ||
|
|
261
|
+
(o) => !o.isDeleted && !o.isRenamed && (o.category === "doc" || E(o.filename))
|
|
262
262
|
)
|
|
263
263
|
);
|
|
264
264
|
const a = t.reduce((o, c) => o + c.tokens, 0), e = t.at(-1)?.tokens ?? 0, i = [
|
|
@@ -271,9 +271,9 @@ const Z = j(), tt = (r, s = {}) => {
|
|
|
271
271
|
parsedCodeTokens: a,
|
|
272
272
|
parsedCodeChunkMaxTokens: e,
|
|
273
273
|
programmingLanguages: i,
|
|
274
|
-
commitCount:
|
|
274
|
+
commitCount: P()
|
|
275
275
|
};
|
|
276
|
-
},
|
|
276
|
+
}, I = (r) => {
|
|
277
277
|
if (Array.isArray(r) && r.length === 2) {
|
|
278
278
|
const s = r[1];
|
|
279
279
|
if (s === null)
|
|
@@ -284,11 +284,11 @@ const Z = j(), tt = (r, s = {}) => {
|
|
|
284
284
|
"[UNGUARD_ERROR_SYNTAX] Invalid input: not a valid [result, error] tuple.",
|
|
285
285
|
{ cause: r }
|
|
286
286
|
);
|
|
287
|
-
},
|
|
287
|
+
}, ct = async (r) => {
|
|
288
288
|
const s = await r;
|
|
289
|
-
return
|
|
290
|
-
},
|
|
291
|
-
const s = String(r ?? "").split(
|
|
289
|
+
return I(s);
|
|
290
|
+
}, S = "</think>", lt = (r) => {
|
|
291
|
+
const s = String(r ?? "").split(S).slice(-1).join(S).trim();
|
|
292
292
|
return /^(Хорошо,|Okay,)/.test(s) ? s.split(`
|
|
293
293
|
|
|
294
294
|
|
|
@@ -297,7 +297,7 @@ const Z = j(), tt = (r, s = {}) => {
|
|
|
297
297
|
|
|
298
298
|
`).trim() : s;
|
|
299
299
|
};
|
|
300
|
-
class
|
|
300
|
+
class k {
|
|
301
301
|
/** @purpose Имя файла конфигурации по умолчанию. */
|
|
302
302
|
static DEFAULT_FILENAME = ".gennadyrc";
|
|
303
303
|
/**
|
|
@@ -306,18 +306,18 @@ class y {
|
|
|
306
306
|
* @sideEffect IO: чтение файлов при конструкторе.
|
|
307
307
|
*/
|
|
308
308
|
static getDefaults() {
|
|
309
|
-
return [process.cwd(), process.env.HOME].map((s) => new
|
|
309
|
+
return [process.cwd(), process.env.HOME].map((s) => new k(s));
|
|
310
310
|
}
|
|
311
311
|
_filename = "";
|
|
312
312
|
_data = {
|
|
313
313
|
models: []
|
|
314
314
|
};
|
|
315
315
|
_error = null;
|
|
316
|
-
constructor(s = process.cwd(), n =
|
|
317
|
-
this._filename =
|
|
316
|
+
constructor(s = process.cwd(), n = k.DEFAULT_FILENAME) {
|
|
317
|
+
this._filename = L(s, n);
|
|
318
318
|
try {
|
|
319
|
-
if (
|
|
320
|
-
const t = JSON.parse(
|
|
319
|
+
if (_(this._filename)) {
|
|
320
|
+
const t = JSON.parse(v(this._filename).toString());
|
|
321
321
|
Array.isArray(t) ? this._data.models = t : t && typeof t == "object" && Array.isArray(t.models) ? this._data = {
|
|
322
322
|
...this._data,
|
|
323
323
|
...t
|
|
@@ -354,7 +354,7 @@ class y {
|
|
|
354
354
|
return this._error;
|
|
355
355
|
}
|
|
356
356
|
}
|
|
357
|
-
function
|
|
357
|
+
function mt(r) {
|
|
358
358
|
const s = String(r).match(/<message[\s\S]*?>[\s\S]*?<\/message>/)?.[0];
|
|
359
359
|
if (!s)
|
|
360
360
|
return null;
|
|
@@ -367,7 +367,7 @@ function ot(r) {
|
|
|
367
367
|
description: i?.trim() || null
|
|
368
368
|
};
|
|
369
369
|
}
|
|
370
|
-
function
|
|
370
|
+
function y(r) {
|
|
371
371
|
return r ? String(r).replace(/[<>&'"]/g, (s) => {
|
|
372
372
|
switch (s) {
|
|
373
373
|
case "<":
|
|
@@ -385,37 +385,37 @@ function h(r) {
|
|
|
385
385
|
}
|
|
386
386
|
}) : "";
|
|
387
387
|
}
|
|
388
|
-
function
|
|
388
|
+
function j(r, s = 0) {
|
|
389
389
|
const n = " ".repeat(s), { tag: t, attrs: a, children: e } = r;
|
|
390
390
|
let i = "";
|
|
391
|
-
if (a && (i = Object.entries(a).filter(([, c]) => c != null).map(([c, l]) => ` ${c}="${
|
|
391
|
+
if (a && (i = Object.entries(a).filter(([, c]) => c != null).map(([c, l]) => ` ${c}="${y(String(l))}"`).join("")), e == null)
|
|
392
392
|
return `${n}<${t}${i} />`;
|
|
393
393
|
if (Array.isArray(e) && e.length === 0)
|
|
394
394
|
return `${n}<${t}${i} />`;
|
|
395
395
|
let o = "";
|
|
396
|
-
return Array.isArray(e) ? e.length > 0 && typeof e[0] == "string" ? o = e.map((l) =>
|
|
396
|
+
return Array.isArray(e) ? e.length > 0 && typeof e[0] == "string" ? o = e.map((l) => y(l)).join(`
|
|
397
397
|
`) : o = `
|
|
398
|
-
` + e.map((l) =>
|
|
398
|
+
` + e.map((l) => j(l, s + 1)).join(`
|
|
399
399
|
`) + `
|
|
400
|
-
` + n : typeof e == "string" ? o =
|
|
401
|
-
` +
|
|
400
|
+
` + n : typeof e == "string" ? o = y(e) : "cdata" in e ? o = `<![CDATA[${String(e.cdata).replaceAll("]]>", "]]]]><![CDATA[>")}]]>` : o = `
|
|
401
|
+
` + j(e, s + 1) + `
|
|
402
402
|
` + n, `${n}<${t}${i}>${o}</${t}>`;
|
|
403
403
|
}
|
|
404
|
-
function
|
|
404
|
+
function ut(r) {
|
|
405
405
|
const s = [
|
|
406
406
|
"ai.knowledge.md",
|
|
407
407
|
".ai/ai.knowledge.md"
|
|
408
408
|
], n = [];
|
|
409
409
|
for (const t of s) {
|
|
410
|
-
const a =
|
|
410
|
+
const a = m.join(r, t);
|
|
411
411
|
try {
|
|
412
|
-
|
|
412
|
+
u.existsSync(a) && u.statSync(a).isFile() && n.push(t);
|
|
413
413
|
} catch {
|
|
414
414
|
}
|
|
415
415
|
}
|
|
416
416
|
return n.length === 0 ? "" : `**MUST READ PROJECT KNOWLEDGE FILES**: ${n.join(", ")}.`;
|
|
417
417
|
}
|
|
418
|
-
const
|
|
418
|
+
const H = [
|
|
419
419
|
{
|
|
420
420
|
kind: "marker",
|
|
421
421
|
relativePath: "go.mod",
|
|
@@ -454,15 +454,15 @@ const W = [
|
|
|
454
454
|
commands: ["cargo test", "cargo clippy"]
|
|
455
455
|
}
|
|
456
456
|
];
|
|
457
|
-
function
|
|
458
|
-
const n =
|
|
457
|
+
function U(r, s) {
|
|
458
|
+
const n = m.join(r, s);
|
|
459
459
|
try {
|
|
460
|
-
return
|
|
460
|
+
return u.existsSync(n) && u.statSync(n).isFile();
|
|
461
461
|
} catch {
|
|
462
462
|
return !1;
|
|
463
463
|
}
|
|
464
464
|
}
|
|
465
|
-
function
|
|
465
|
+
function J(r, s) {
|
|
466
466
|
const n = r.toLowerCase(), t = s.toLowerCase();
|
|
467
467
|
return /(^|:|-)watch($|:|-)/i.test(n) ? !0 : [
|
|
468
468
|
/(^|\s)--watch(?:[=\s]|$)/i,
|
|
@@ -471,9 +471,9 @@ function H(r, s) {
|
|
|
471
471
|
/(^|\s)nodemon(?:\s|$)/i
|
|
472
472
|
].some((e) => e.test(t));
|
|
473
473
|
}
|
|
474
|
-
function
|
|
474
|
+
function K(r, s, n) {
|
|
475
475
|
const t = Object.entries(r).filter(
|
|
476
|
-
([a, e]) => !n.has(a) && !
|
|
476
|
+
([a, e]) => !n.has(a) && !J(a, e)
|
|
477
477
|
);
|
|
478
478
|
for (const a of s.preferredNames)
|
|
479
479
|
if (t.some(([e]) => e === a))
|
|
@@ -483,13 +483,13 @@ function U(r, s, n) {
|
|
|
483
483
|
return a;
|
|
484
484
|
return null;
|
|
485
485
|
}
|
|
486
|
-
function
|
|
487
|
-
const n =
|
|
486
|
+
function Y(r, s) {
|
|
487
|
+
const n = m.join(r, "package.json");
|
|
488
488
|
let t;
|
|
489
489
|
try {
|
|
490
|
-
if (!
|
|
490
|
+
if (!u.existsSync(n) || !u.statSync(n).isFile())
|
|
491
491
|
return null;
|
|
492
|
-
t =
|
|
492
|
+
t = u.readFileSync(n, "utf-8");
|
|
493
493
|
} catch {
|
|
494
494
|
return null;
|
|
495
495
|
}
|
|
@@ -504,74 +504,98 @@ function J(r, s) {
|
|
|
504
504
|
return null;
|
|
505
505
|
const i = [], o = /* @__PURE__ */ new Set();
|
|
506
506
|
for (const c of s.scriptGroups) {
|
|
507
|
-
const l =
|
|
507
|
+
const l = K(e, c, o);
|
|
508
508
|
if (l && (i.push(`npm run ${l}`), o.add(l)), i.length >= s.maxCommands)
|
|
509
509
|
break;
|
|
510
510
|
}
|
|
511
511
|
return i.length === 0 ? null : i.slice(0, s.maxCommands);
|
|
512
512
|
}
|
|
513
|
-
function
|
|
514
|
-
for (const s of
|
|
513
|
+
function V(r) {
|
|
514
|
+
for (const s of H) {
|
|
515
515
|
if (s.kind === "marker") {
|
|
516
|
-
if (
|
|
516
|
+
if (U(r, s.relativePath))
|
|
517
517
|
return [...s.commands];
|
|
518
518
|
continue;
|
|
519
519
|
}
|
|
520
520
|
if (s.kind === "npm-package-json") {
|
|
521
|
-
const n =
|
|
521
|
+
const n = Y(r, s);
|
|
522
522
|
if (n != null && n.length > 0)
|
|
523
523
|
return n;
|
|
524
524
|
}
|
|
525
525
|
}
|
|
526
526
|
return [];
|
|
527
527
|
}
|
|
528
|
-
function
|
|
528
|
+
function X(r) {
|
|
529
529
|
return r.map((s) => `\`${s}\``).join(", ");
|
|
530
530
|
}
|
|
531
|
-
function
|
|
532
|
-
const s =
|
|
531
|
+
function ft(r) {
|
|
532
|
+
const s = V(r);
|
|
533
533
|
if (s.length === 0)
|
|
534
534
|
return {
|
|
535
535
|
axiomHint: "как в README или CI принято проверять код (тесты, линтер, типы). Не подменяй это тяжёлой production-сборкой или публикацией, если это явно не описано как проверка",
|
|
536
536
|
toolsExample: "команды из `package.json` → `scripts`, из Makefile или из CI-шагов, которые относятся к качеству кода; сначала прочитай README",
|
|
537
537
|
verifyStep: "Прочитай README и при наличии — конфиг CI: какие команды запускают тесты, линтер и проверку типов. Выполни их из корня репозитория. Не запускай `build`/`publish`/полный `ci`, если не уверен, что это нужно для проверки изменений; при сомнении спроси пользователя."
|
|
538
538
|
};
|
|
539
|
-
const n =
|
|
539
|
+
const n = X(s);
|
|
540
540
|
return {
|
|
541
541
|
axiomHint: `\`${s[0]}\` или следующую команду из того же набора проверок`,
|
|
542
542
|
toolsExample: n,
|
|
543
543
|
verifyStep: `Из корня репозитория выполни: ${n}. Не добавляй \`build\`, полный \`ci\` или публикацию, если они не перечислены здесь и не описаны в README как обязательная проверка.`
|
|
544
544
|
};
|
|
545
545
|
}
|
|
546
|
-
|
|
547
|
-
|
|
548
|
-
|
|
549
|
-
|
|
550
|
-
|
|
551
|
-
|
|
552
|
-
|
|
553
|
-
|
|
554
|
-
|
|
555
|
-
|
|
546
|
+
const h = ".ai/agents";
|
|
547
|
+
function C(r) {
|
|
548
|
+
return u.existsSync(r) ? u.promises.readFile(r, "utf-8") : null;
|
|
549
|
+
}
|
|
550
|
+
function z(r) {
|
|
551
|
+
let s = r;
|
|
552
|
+
for (; ; ) {
|
|
553
|
+
const n = m.join(s, "package.json");
|
|
554
|
+
if (u.existsSync(n))
|
|
555
|
+
return s;
|
|
556
|
+
const t = m.dirname(s);
|
|
557
|
+
if (t === s)
|
|
558
|
+
return null;
|
|
559
|
+
s = t;
|
|
560
|
+
}
|
|
561
|
+
}
|
|
562
|
+
async function dt(r) {
|
|
563
|
+
const s = m.dirname(N(import.meta.url)), n = m.join(process.cwd(), h, r), t = C(n);
|
|
564
|
+
if (t)
|
|
565
|
+
return t;
|
|
566
|
+
const a = z(s), e = [];
|
|
567
|
+
a ? (e.push(m.join(a, h, r)), e.push(m.join(a, "dist", h, r))) : e.push(
|
|
568
|
+
m.join(s, "../../../../../../dist", h, r)
|
|
569
|
+
);
|
|
570
|
+
for (const i of e) {
|
|
571
|
+
const o = C(i);
|
|
572
|
+
if (o)
|
|
573
|
+
return o;
|
|
574
|
+
}
|
|
575
|
+
throw new Error(`Не найден файл шаблона ${r}.`, {
|
|
576
|
+
cause: {
|
|
577
|
+
projectOverridePath: n,
|
|
578
|
+
packageCandidates: e
|
|
579
|
+
}
|
|
556
580
|
});
|
|
557
581
|
}
|
|
558
582
|
export {
|
|
559
|
-
|
|
560
|
-
|
|
561
|
-
|
|
562
|
-
|
|
563
|
-
|
|
564
|
-
|
|
565
|
-
|
|
566
|
-
|
|
567
|
-
|
|
568
|
-
|
|
569
|
-
|
|
570
|
-
|
|
571
|
-
|
|
572
|
-
|
|
573
|
-
|
|
574
|
-
|
|
575
|
-
|
|
576
|
-
|
|
583
|
+
k as G,
|
|
584
|
+
it as a,
|
|
585
|
+
at as b,
|
|
586
|
+
j as c,
|
|
587
|
+
ft as d,
|
|
588
|
+
f as e,
|
|
589
|
+
ut as f,
|
|
590
|
+
ot as g,
|
|
591
|
+
b as h,
|
|
592
|
+
nt as i,
|
|
593
|
+
O as j,
|
|
594
|
+
I as k,
|
|
595
|
+
dt as l,
|
|
596
|
+
rt as p,
|
|
597
|
+
lt as r,
|
|
598
|
+
st as s,
|
|
599
|
+
ct as u,
|
|
600
|
+
mt as x
|
|
577
601
|
};
|
package/dist/gennady.js
CHANGED
|
@@ -3,25 +3,25 @@ const e = /* @__PURE__ */ new Set(["help", "--help", "-h"]), a = process.argv[2]
|
|
|
3
3
|
(!a || e.has(a)) && (await import("./chunks/help.cmd-CWasx25o.js"), process.exit(0));
|
|
4
4
|
switch (a) {
|
|
5
5
|
case "cat":
|
|
6
|
-
await import("./chunks/index-
|
|
6
|
+
await import("./chunks/index-C4jt5WBP.js");
|
|
7
7
|
break;
|
|
8
8
|
case "review":
|
|
9
|
-
await import("./chunks/index-
|
|
9
|
+
await import("./chunks/index-Bh0p7rJg.js");
|
|
10
10
|
break;
|
|
11
11
|
case "vcs-reply":
|
|
12
|
-
await import("./chunks/index-
|
|
12
|
+
await import("./chunks/index-Bx_P7mlL.js");
|
|
13
13
|
break;
|
|
14
14
|
case "review-verify":
|
|
15
|
-
await import("./chunks/index-
|
|
15
|
+
await import("./chunks/index-B3r-YFvt.js");
|
|
16
16
|
break;
|
|
17
17
|
case "review-issues":
|
|
18
|
-
await import("./chunks/index-
|
|
18
|
+
await import("./chunks/index-Gy1n7hRU.js");
|
|
19
19
|
break;
|
|
20
20
|
case "resolve-conflicts":
|
|
21
|
-
await import("./chunks/index-
|
|
21
|
+
await import("./chunks/index-DgAmONSz.js");
|
|
22
22
|
break;
|
|
23
23
|
case "commit":
|
|
24
|
-
await import("./chunks/index-
|
|
24
|
+
await import("./chunks/index-D1Hurfwu.js");
|
|
25
25
|
break;
|
|
26
26
|
default:
|
|
27
27
|
await import("./chunks/help.cmd-CWasx25o.js"), process.exit(0);
|
package/dist/index.js
CHANGED
|
@@ -1,5 +1,5 @@
|
|
|
1
|
-
import { u, r as m } from "./chunks/shared-
|
|
2
|
-
import { G as y, h as d, i as A, j as f, k as w } from "./chunks/shared-
|
|
1
|
+
import { u, r as m } from "./chunks/shared-D0kSJB49.js";
|
|
2
|
+
import { G as y, h as d, i as A, j as f, k as w } from "./chunks/shared-D0kSJB49.js";
|
|
3
3
|
class h {
|
|
4
4
|
/**
|
|
5
5
|
* @purpose Создать экземпляр с дефолтными настройками (Ollama local).
|