@wrongstack/plugins 0.317.0 → 0.317.2
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/accessibility-auditor.js +12 -10
- package/dist/agent-handoff.js +30 -10
- package/dist/auto-doc.js +22 -9
- package/dist/auto-escalate.js +17 -7
- package/dist/auto-i18n-extractor.js +19 -9
- package/dist/branch-guard.js +12 -9
- package/dist/changelog-writer/index.d.ts +3 -3
- package/dist/changelog-writer.js +59 -14
- package/dist/checkpoint.js +18 -7
- package/dist/code-metrics.js +17 -9
- package/dist/commit-validator.js +18 -11
- package/dist/config-validator.js +5 -3
- package/dist/context-pins.js +17 -6
- package/dist/cost-tracker.js +24 -16
- package/dist/cron.js +17 -13
- package/dist/dead-code-detector.js +5 -4
- package/dist/dep-guard.js +5 -4
- package/dist/dependency-vulnerability-gate.js +64 -24
- package/dist/diff-summary.js +6 -2
- package/dist/doc-sync-guard.js +12 -2
- package/dist/duplicate-code-detector.js +87 -15
- package/dist/error-lens.js +6 -5
- package/dist/feature-flag-tracker.js +43 -9
- package/dist/file-watcher.js +26 -3
- package/dist/format-on-save.js +9 -5
- package/dist/git-autocommit.js +20 -12
- package/dist/gitignore-guard.js +7 -4
- package/dist/import-organizer.js +9 -5
- package/dist/index.js +1675 -745
- package/dist/injection-shield/index.d.ts +1 -0
- package/dist/injection-shield.js +30 -5
- package/dist/interface-contract-guard.js +4 -2
- package/dist/knowledge-graph.js +40 -14
- package/dist/license-audit-gate.js +61 -8
- package/dist/lint-gate.js +13 -5
- package/dist/llm-cache.js +20 -6
- package/dist/loop-breaker.js +16 -8
- package/dist/migration-planner.js +80 -11
- package/dist/model-router.js +16 -9
- package/dist/notify-hub.js +14 -5
- package/dist/path-guard.js +7 -3
- package/dist/performance-regression-gate.js +12 -6
- package/dist/plugin-stack-observer.js +25 -3
- package/dist/pr-drafter.js +16 -7
- package/dist/process-guard.js +2 -1
- package/dist/prompt-firewall.js +9 -7
- package/dist/refactor-suggester.js +37 -8
- package/dist/release-notes-generator/index.d.ts +9 -0
- package/dist/release-notes-generator.js +50 -12
- package/dist/schema-evolution-guard.js +33 -6
- package/dist/secret-scanner.js +10 -7
- package/dist/security-hotspot-scanner.js +13 -8
- package/dist/semantic-search-indexer/index.d.ts +11 -0
- package/dist/semantic-search-indexer.js +67 -19
- package/dist/semver-bump/index.d.ts +3 -3
- package/dist/semver-bump.js +30 -15
- package/dist/session-recap/index.d.ts +16 -0
- package/dist/session-recap.js +18 -9
- package/dist/shell-check.js +27 -6
- package/dist/smart-rename.js +18 -9
- package/dist/spec-linker.js +70 -19
- package/dist/template-engine.js +24 -14
- package/dist/test-coverage-gate.js +1 -1
- package/dist/test-flake-detector.js +28 -5
- package/dist/test-generator/index.d.ts +10 -0
- package/dist/test-generator.js +35 -13
- package/dist/todo-listener.js +2 -2
- package/dist/todo-tracker.js +19 -11
- package/dist/token-budget.js +14 -9
- package/dist/token-throttle.js +8 -3
- package/dist/type-gate.js +9 -5
- package/package.json +5 -5
|
@@ -41,12 +41,16 @@ var DEFAULTS = {
|
|
|
41
41
|
function readConfig(raw) {
|
|
42
42
|
if (!raw || typeof raw !== "object") return { ...DEFAULTS };
|
|
43
43
|
const r = raw;
|
|
44
|
+
const rawExts = r["includeExtensions"] ?? r["include_extensions"] ?? r["extensions"];
|
|
45
|
+
const rawMax = r["maxFindings"] ?? r["max_findings"] ?? r["limit"];
|
|
46
|
+
const rawSeverity = typeof (r["severity"] ?? r["mode"] ?? r["action"]) === "string" ? String(r["severity"] ?? r["mode"] ?? r["action"]).trim().toLowerCase() : void 0;
|
|
47
|
+
const severity = rawSeverity === "block" ? "block" : DEFAULTS.severity;
|
|
44
48
|
return {
|
|
45
49
|
enabled: r["enabled"] !== false,
|
|
46
|
-
includeExtensions: Array.isArray(
|
|
47
|
-
maxFindings: typeof
|
|
48
|
-
severity
|
|
49
|
-
onWriteEdit: r["onWriteEdit"] !== false
|
|
50
|
+
includeExtensions: Array.isArray(rawExts) ? rawExts.filter((x) => typeof x === "string") : DEFAULTS.includeExtensions,
|
|
51
|
+
maxFindings: typeof rawMax === "number" && rawMax >= 1 && rawMax <= 500 ? rawMax : DEFAULTS.maxFindings,
|
|
52
|
+
severity,
|
|
53
|
+
onWriteEdit: (r["onWriteEdit"] ?? r["on_write_edit"] ?? r["onSave"]) !== false
|
|
50
54
|
};
|
|
51
55
|
}
|
|
52
56
|
function normalizeExtensions(exts) {
|
|
@@ -170,7 +174,7 @@ async function auditFile(filePath, projectRoot) {
|
|
|
170
174
|
SINGLE_FILE_LABEL_NOTE
|
|
171
175
|
);
|
|
172
176
|
}
|
|
173
|
-
if (ATTR_PLACEHOLDER.test(tag)) {
|
|
177
|
+
if (!hasPrimaryLabel && ATTR_PLACEHOLDER.test(tag)) {
|
|
174
178
|
add(lineNo, "low-contrast-placeholder", "warning", "<input> uses placeholder text (often low contrast and disappears on input)");
|
|
175
179
|
}
|
|
176
180
|
}
|
|
@@ -300,7 +304,7 @@ var plugin = {
|
|
|
300
304
|
if (!cfg.enabled || !cfg.onWriteEdit) return;
|
|
301
305
|
if (input.toolResult?.isError) return;
|
|
302
306
|
const inp = input.toolInput ?? {};
|
|
303
|
-
const rawPath = inp["path"] ?? inp["filePath"] ?? inp["file_path"];
|
|
307
|
+
const rawPath = inp["path"] ?? inp["TargetFile"] ?? inp["filePath"] ?? inp["targetFile"] ?? inp["file_path"] ?? inp["file"];
|
|
304
308
|
const sourcePath = typeof rawPath === "string" ? rawPath : void 0;
|
|
305
309
|
if (!sourcePath) return;
|
|
306
310
|
if (!(0, runtime_exports.withinProject)(sourcePath)) return;
|
|
@@ -343,10 +347,8 @@ var plugin = {
|
|
|
343
347
|
mutating: false,
|
|
344
348
|
async execute(input) {
|
|
345
349
|
if (!cfg.enabled) return { ok: false, error: "accessibility-auditor is disabled" };
|
|
346
|
-
const
|
|
347
|
-
|
|
348
|
-
return { ok: false, error: "path is required" };
|
|
349
|
-
}
|
|
350
|
+
const raw = input;
|
|
351
|
+
const rawPath = (typeof input.path === "string" && input.path.trim().length > 0 ? input.path.trim() : void 0) ?? (typeof raw["directory"] === "string" ? raw["directory"] : void 0) ?? (typeof raw["dir"] === "string" ? raw["dir"] : void 0) ?? (typeof raw["SearchDirectory"] === "string" ? raw["SearchDirectory"] : void 0) ?? (typeof raw["TargetFile"] === "string" ? raw["TargetFile"] : void 0) ?? (typeof raw["filePath"] === "string" ? raw["filePath"] : void 0) ?? (typeof raw["file_path"] === "string" ? raw["file_path"] : void 0) ?? (typeof raw["targetFile"] === "string" ? raw["targetFile"] : void 0) ?? (typeof raw["file"] === "string" ? raw["file"] : void 0) ?? ".";
|
|
350
352
|
if (!(0, runtime_exports.withinProject)(rawPath)) {
|
|
351
353
|
return { ok: false, error: "path must be inside the project" };
|
|
352
354
|
}
|
package/dist/agent-handoff.js
CHANGED
|
@@ -39,13 +39,16 @@ var DEFAULTS = {
|
|
|
39
39
|
function readConfig(raw) {
|
|
40
40
|
if (!raw || typeof raw !== "object") return { ...DEFAULTS };
|
|
41
41
|
const r = raw;
|
|
42
|
+
const rawPrefix = r["subjectPrefix"] ?? r["subject_prefix"] ?? r["prefix"];
|
|
43
|
+
const rawMax = r["maxBodyChars"] ?? r["max_body_chars"] ?? r["maxChars"];
|
|
44
|
+
const rawTo = r["to"] ?? r["recipient"] ?? r["target"];
|
|
42
45
|
return {
|
|
43
46
|
enabled: r["enabled"] !== false,
|
|
44
|
-
subjectPrefix: typeof
|
|
45
|
-
includeResult: r["includeResult"] !== false,
|
|
46
|
-
includeTodos: r["includeTodos"] !== false,
|
|
47
|
-
maxBodyChars: typeof
|
|
48
|
-
to: typeof
|
|
47
|
+
subjectPrefix: typeof rawPrefix === "string" ? rawPrefix : DEFAULTS.subjectPrefix,
|
|
48
|
+
includeResult: (r["includeResult"] ?? r["include_result"]) !== false,
|
|
49
|
+
includeTodos: (r["includeTodos"] ?? r["include_todos"]) !== false,
|
|
50
|
+
maxBodyChars: typeof rawMax === "number" && rawMax >= 500 ? rawMax : DEFAULTS.maxBodyChars,
|
|
51
|
+
to: typeof rawTo === "string" ? rawTo : DEFAULTS.to
|
|
49
52
|
};
|
|
50
53
|
}
|
|
51
54
|
function truncate(s, max) {
|
|
@@ -190,7 +193,21 @@ var plugin = {
|
|
|
190
193
|
state.skippedCount += 1;
|
|
191
194
|
return;
|
|
192
195
|
}
|
|
193
|
-
const
|
|
196
|
+
const raw = payload ?? {};
|
|
197
|
+
const asString = (v) => {
|
|
198
|
+
if (v === void 0 || v === null) return void 0;
|
|
199
|
+
return typeof v === "string" ? v : (0, runtime_exports.safeJsonStringify)(v) ?? void 0;
|
|
200
|
+
};
|
|
201
|
+
const rawTodos = raw["todos"];
|
|
202
|
+
const p = {
|
|
203
|
+
agentId: asString(raw["agentId"]),
|
|
204
|
+
agentName: asString(raw["agentName"]),
|
|
205
|
+
task: asString(raw["task"]),
|
|
206
|
+
status: asString(raw["status"]),
|
|
207
|
+
summary: asString(raw["summary"]),
|
|
208
|
+
result: raw["result"] ?? raw["output"] ?? raw["data"] ?? raw["toolResult"],
|
|
209
|
+
todos: Array.isArray(rawTodos) ? rawTodos : void 0
|
|
210
|
+
};
|
|
194
211
|
sendHandoff(cfg, mailbox, p).catch((err) => {
|
|
195
212
|
state.errorCount += 1;
|
|
196
213
|
api.log.warn("agent-handoff: mailbox.send failed", {
|
|
@@ -223,14 +240,17 @@ var plugin = {
|
|
|
223
240
|
async execute(input) {
|
|
224
241
|
if (!cfg.enabled) return { ok: false, error: "agent-handoff is disabled" };
|
|
225
242
|
if (!mailbox) return { ok: false, error: "mailbox not available" };
|
|
243
|
+
const raw = input;
|
|
244
|
+
const summary = (typeof raw["summary"] === "string" ? raw["summary"] : void 0) ?? (typeof raw["note"] === "string" ? raw["note"] : void 0) ?? (typeof raw["message"] === "string" ? raw["message"] : void 0) ?? (typeof raw["content"] === "string" ? raw["content"] : void 0) ?? (typeof raw["text"] === "string" ? raw["text"] : void 0) ?? (typeof raw["body"] === "string" ? raw["body"] : void 0);
|
|
245
|
+
const task = (typeof raw["task"] === "string" ? raw["task"] : void 0) ?? (typeof raw["title"] === "string" ? raw["title"] : void 0) ?? (typeof raw["subject"] === "string" ? raw["subject"] : void 0);
|
|
226
246
|
const payload = {
|
|
227
247
|
agentName: "manual",
|
|
228
|
-
task
|
|
229
|
-
summary
|
|
248
|
+
task,
|
|
249
|
+
summary,
|
|
230
250
|
result: input.result,
|
|
231
|
-
todos: Array.isArray(input.todos) ? input.todos : void 0
|
|
251
|
+
todos: Array.isArray(input.todos) ? input.todos : input.todos && typeof input.todos === "object" ? [input.todos] : void 0
|
|
232
252
|
};
|
|
233
|
-
const recipient =
|
|
253
|
+
const recipient = (typeof raw["to"] === "string" ? raw["to"] : void 0) ?? (typeof raw["recipient"] === "string" ? raw["recipient"] : void 0) ?? (typeof raw["target"] === "string" ? raw["target"] : void 0) ?? cfg.to;
|
|
234
254
|
try {
|
|
235
255
|
const body = buildBody(payload, cfg);
|
|
236
256
|
const result = await mailbox.send({
|
package/dist/auto-doc.js
CHANGED
|
@@ -161,7 +161,8 @@ function injectDocComment(content, entity, doc) {
|
|
|
161
161
|
return lines.join("\n");
|
|
162
162
|
}
|
|
163
163
|
async function runAutoDoc(input, api) {
|
|
164
|
-
|
|
164
|
+
const rawInput = input;
|
|
165
|
+
if (rawInput["files"] !== void 0 && !Array.isArray(rawInput["files"])) {
|
|
165
166
|
return {
|
|
166
167
|
ok: false,
|
|
167
168
|
error: "input.files must be an array of file paths",
|
|
@@ -169,7 +170,17 @@ async function runAutoDoc(input, api) {
|
|
|
169
170
|
changes: []
|
|
170
171
|
};
|
|
171
172
|
}
|
|
172
|
-
|
|
173
|
+
const rawFiles = rawInput["files"] ?? rawInput["file"] ?? rawInput["path"] ?? rawInput["filePath"] ?? rawInput["TargetFile"] ?? rawInput["targetFile"];
|
|
174
|
+
const files = Array.isArray(rawFiles) ? rawFiles.filter((f) => typeof f === "string" && f.trim().length > 0).map((f) => f.trim()) : typeof rawFiles === "string" && rawFiles.trim().length > 0 ? [rawFiles.trim()] : void 0;
|
|
175
|
+
if (!files || !Array.isArray(files)) {
|
|
176
|
+
return {
|
|
177
|
+
ok: false,
|
|
178
|
+
error: "input.files must be an array of file paths",
|
|
179
|
+
filesProcessed: 0,
|
|
180
|
+
changes: []
|
|
181
|
+
};
|
|
182
|
+
}
|
|
183
|
+
if (files.length === 0) {
|
|
173
184
|
return {
|
|
174
185
|
ok: false,
|
|
175
186
|
error: "input.files is empty \u2014 provide at least one file path",
|
|
@@ -179,11 +190,11 @@ async function runAutoDoc(input, api) {
|
|
|
179
190
|
}
|
|
180
191
|
const extConfig = api.config.extensions?.["auto-doc"] ?? {};
|
|
181
192
|
const includeTypes = extConfig["includeTypes"] ?? false;
|
|
182
|
-
const useLlm = (input.use_llm ?? extConfig["useLlm"] ?? false) === true && Boolean(api.llm);
|
|
193
|
+
const useLlm = (input.use_llm ?? rawInput["useLlm"] ?? extConfig["useLlm"] ?? false) === true && Boolean(api.llm);
|
|
183
194
|
const maxLlmEntities = typeof extConfig["maxLlmEntities"] === "number" && extConfig["maxLlmEntities"] >= 0 ? extConfig["maxLlmEntities"] : 25;
|
|
184
195
|
const results = [];
|
|
185
196
|
let llmBudget = maxLlmEntities;
|
|
186
|
-
for (const rawFile of
|
|
197
|
+
for (const rawFile of files) {
|
|
187
198
|
const safeFile = resolveProjectPath(rawFile);
|
|
188
199
|
if (!safeFile) {
|
|
189
200
|
api.log.warn(`auto-doc: skipped file outside project directory: ${rawFile}`);
|
|
@@ -200,8 +211,9 @@ async function runAutoDoc(input, api) {
|
|
|
200
211
|
}
|
|
201
212
|
const entities = parseSource(content);
|
|
202
213
|
let modified = content;
|
|
203
|
-
const
|
|
204
|
-
|
|
214
|
+
const reversedEntities = [...entities].reverse();
|
|
215
|
+
const fileChanges = [];
|
|
216
|
+
for (const entity of reversedEntities) {
|
|
205
217
|
if (!input.force && !needsDocComment(modified, entity)) continue;
|
|
206
218
|
let doc = null;
|
|
207
219
|
let source = "template";
|
|
@@ -224,9 +236,10 @@ async function runAutoDoc(input, api) {
|
|
|
224
236
|
}
|
|
225
237
|
if (!doc) doc = generateDocComment(entity, includeTypes);
|
|
226
238
|
modified = injectDocComment(modified, entity, doc);
|
|
227
|
-
|
|
239
|
+
fileChanges.push({ file: safeFile, entity: entity.name, source });
|
|
228
240
|
}
|
|
229
|
-
|
|
241
|
+
results.push(...fileChanges.reverse());
|
|
242
|
+
const changedThisFile = fileChanges.length > 0 && modified !== content;
|
|
230
243
|
if (!input.dry_run && changedThisFile) {
|
|
231
244
|
writeFileSync(safeFile, modified, "utf-8");
|
|
232
245
|
api.log.info(`auto-doc: updated ${safeFile}`);
|
|
@@ -237,7 +250,7 @@ async function runAutoDoc(input, api) {
|
|
|
237
250
|
}
|
|
238
251
|
return {
|
|
239
252
|
ok: true,
|
|
240
|
-
filesProcessed:
|
|
253
|
+
filesProcessed: files.length,
|
|
241
254
|
changes: results,
|
|
242
255
|
llm: useLlm ? { docs: state.llmDocs, fallbacks: state.llmFallbacks } : void 0
|
|
243
256
|
};
|
package/dist/auto-escalate.js
CHANGED
|
@@ -3,23 +3,33 @@ var DEFAULT_PATTERNS = [
|
|
|
3
3
|
"overload",
|
|
4
4
|
"rate.?limit",
|
|
5
5
|
"\\b429\\b",
|
|
6
|
-
"\\b50[
|
|
6
|
+
"\\b50[0234]\\b",
|
|
7
7
|
"timeout",
|
|
8
8
|
"ETIMEDOUT",
|
|
9
9
|
"ECONNRESET",
|
|
10
10
|
"ECONNREFUSED",
|
|
11
|
-
"temporarily unavailable"
|
|
11
|
+
"temporarily unavailable",
|
|
12
|
+
"resource.?exhausted",
|
|
13
|
+
"capacity",
|
|
14
|
+
"gateway"
|
|
12
15
|
];
|
|
16
|
+
var DEFAULTS = {
|
|
17
|
+
enabled: false,
|
|
18
|
+
escalation: [],
|
|
19
|
+
retryablePatterns: DEFAULT_PATTERNS.map((p) => new RegExp(p, "i"))
|
|
20
|
+
};
|
|
13
21
|
function readConfig(raw) {
|
|
14
22
|
const base = {
|
|
15
|
-
enabled:
|
|
16
|
-
escalation: [],
|
|
17
|
-
retryablePatterns:
|
|
23
|
+
enabled: DEFAULTS.enabled,
|
|
24
|
+
escalation: [...DEFAULTS.escalation],
|
|
25
|
+
retryablePatterns: [...DEFAULTS.retryablePatterns]
|
|
18
26
|
};
|
|
19
27
|
if (!raw || typeof raw !== "object") return base;
|
|
20
28
|
const r = raw;
|
|
21
|
-
const
|
|
22
|
-
const
|
|
29
|
+
const rawEscalation = r["escalation"] ?? r["ladder"] ?? r["models"];
|
|
30
|
+
const escalation = Array.isArray(rawEscalation) ? rawEscalation.filter((m) => typeof m === "string" && m.length > 0) : [];
|
|
31
|
+
const rawPatterns = r["retryablePatterns"] ?? r["retryable_patterns"] ?? r["patterns"];
|
|
32
|
+
const patterns = Array.isArray(rawPatterns) ? rawPatterns.filter((p) => typeof p === "string" && p.length > 0).flatMap((p) => {
|
|
23
33
|
try {
|
|
24
34
|
return [new RegExp(p, "i")];
|
|
25
35
|
} catch {
|
|
@@ -53,12 +53,16 @@ function readConfig(raw) {
|
|
|
53
53
|
if (!raw || typeof raw !== "object") return { ...DEFAULTS };
|
|
54
54
|
const r = raw;
|
|
55
55
|
const clamp = (n, min, max, fallback) => typeof n === "number" && Number.isFinite(n) && n >= min && n <= max ? Math.floor(n) : fallback;
|
|
56
|
+
const rawExts = r["fileExtensions"] ?? r["file_extensions"] ?? r["extensions"];
|
|
57
|
+
const rawMin = r["minLength"] ?? r["min_length"] ?? r["min"];
|
|
58
|
+
const rawMax = r["maxContextStrings"] ?? r["max_context_strings"] ?? r["maxStrings"] ?? r["limit"];
|
|
59
|
+
const rawExcl = r["excludeAttributes"] ?? r["exclude_attributes"];
|
|
56
60
|
return {
|
|
57
61
|
enabled: r["enabled"] !== false,
|
|
58
|
-
fileExtensions: Array.isArray(
|
|
59
|
-
minLength: clamp(
|
|
60
|
-
maxContextStrings: clamp(
|
|
61
|
-
excludeAttributes: Array.isArray(
|
|
62
|
+
fileExtensions: Array.isArray(rawExts) ? rawExts.filter((x) => typeof x === "string") : DEFAULTS.fileExtensions,
|
|
63
|
+
minLength: clamp(rawMin, 1, 500, DEFAULTS.minLength),
|
|
64
|
+
maxContextStrings: clamp(rawMax, 1, 100, DEFAULTS.maxContextStrings),
|
|
65
|
+
excludeAttributes: Array.isArray(rawExcl) ? rawExcl.filter((x) => typeof x === "string") : DEFAULTS.excludeAttributes
|
|
62
66
|
};
|
|
63
67
|
}
|
|
64
68
|
function fileExtension(p) {
|
|
@@ -66,8 +70,11 @@ function fileExtension(p) {
|
|
|
66
70
|
return dot > 0 ? p.slice(dot).toLowerCase() : "";
|
|
67
71
|
}
|
|
68
72
|
function generateKey(value) {
|
|
69
|
-
const base = value.toLowerCase().replace(/[
|
|
70
|
-
|
|
73
|
+
const base = value.toLowerCase().normalize("NFKD").replace(/[^\p{L}\p{N}]+/gu, "_").replace(/^_+|_+$/g, "").slice(0, 40);
|
|
74
|
+
if (base) return `t.${base}`;
|
|
75
|
+
let hash = 0;
|
|
76
|
+
for (let i = 0; i < value.length; i++) hash = hash * 31 + value.charCodeAt(i) >>> 0;
|
|
77
|
+
return `t.str_${hash.toString(36)}`;
|
|
71
78
|
}
|
|
72
79
|
function looksLikeUserText(value, minLength) {
|
|
73
80
|
if (value.length < minLength) return false;
|
|
@@ -180,7 +187,8 @@ var plugin = {
|
|
|
180
187
|
if (!cfg.enabled) return;
|
|
181
188
|
if (input.toolResult?.isError) return;
|
|
182
189
|
const inp = input.toolInput ?? {};
|
|
183
|
-
const
|
|
190
|
+
const rawPath = inp["path"] ?? inp["TargetFile"] ?? inp["filePath"] ?? inp["targetFile"] ?? inp["file_path"] ?? inp["file"];
|
|
191
|
+
const sourcePath = typeof rawPath === "string" && rawPath.trim() ? rawPath.trim() : void 0;
|
|
184
192
|
if (!sourcePath || typeof sourcePath !== "string") return;
|
|
185
193
|
if (!(0, runtime_exports.withinProject)(sourcePath)) return;
|
|
186
194
|
const ext = fileExtension(sourcePath);
|
|
@@ -231,8 +239,10 @@ ${lines.join("\n")}${more}`;
|
|
|
231
239
|
mutating: false,
|
|
232
240
|
async execute(input) {
|
|
233
241
|
if (!cfg.enabled) return { ok: false, error: "auto-i18n-extractor is disabled" };
|
|
234
|
-
const
|
|
235
|
-
|
|
242
|
+
const raw = input;
|
|
243
|
+
const rawPath = (typeof input.path === "string" && input.path.trim().length > 0 ? input.path.trim() : void 0) ?? (typeof raw["TargetFile"] === "string" && raw["TargetFile"].trim().length > 0 ? raw["TargetFile"].trim() : void 0) ?? (typeof raw["targetFile"] === "string" && raw["targetFile"].trim().length > 0 ? raw["targetFile"].trim() : void 0) ?? (typeof raw["filePath"] === "string" && raw["filePath"].trim().length > 0 ? raw["filePath"].trim() : void 0) ?? (typeof raw["file_path"] === "string" && raw["file_path"].trim().length > 0 ? raw["file_path"].trim() : void 0) ?? (typeof raw["file"] === "string" && raw["file"].trim().length > 0 ? raw["file"].trim() : void 0);
|
|
244
|
+
const filePath = typeof rawPath === "string" ? rawPath.trim() : "";
|
|
245
|
+
if (!filePath) {
|
|
236
246
|
return { ok: false, error: "path is required" };
|
|
237
247
|
}
|
|
238
248
|
if (!(0, runtime_exports.withinProject)(filePath)) {
|
package/dist/branch-guard.js
CHANGED
|
@@ -41,15 +41,17 @@ var DEFAULTS = {
|
|
|
41
41
|
function readConfig(raw) {
|
|
42
42
|
if (!raw || typeof raw !== "object") return { ...DEFAULTS };
|
|
43
43
|
const r = raw;
|
|
44
|
-
const
|
|
45
|
-
const
|
|
44
|
+
const rawBranches = r["branches"] ?? r["protectedBranches"] ?? r["protected_branches"] ?? r["protected"];
|
|
45
|
+
const branches = Array.isArray(rawBranches) ? rawBranches.filter((b) => typeof b === "string") : DEFAULTS.branches;
|
|
46
|
+
const rawMode = typeof (r["mode"] ?? r["action"]) === "string" ? String(r["mode"] ?? r["action"]).trim().toLowerCase() : void 0;
|
|
47
|
+
const mode = rawMode === "warn" ? "warn" : rawMode === "off" ? "off" : "block";
|
|
46
48
|
return {
|
|
47
49
|
enabled: r["enabled"] !== false && mode !== "off",
|
|
48
50
|
branches: branches.length > 0 ? branches : DEFAULTS.branches,
|
|
49
51
|
mode,
|
|
50
|
-
blockCommit: r["blockCommit"] !== false,
|
|
51
|
-
blockPush: r["blockPush"] !== false,
|
|
52
|
-
blockMerge: r["blockMerge"] !== false
|
|
52
|
+
blockCommit: (r["blockCommit"] ?? r["block_commit"]) !== false,
|
|
53
|
+
blockPush: (r["blockPush"] ?? r["block_push"]) !== false,
|
|
54
|
+
blockMerge: (r["blockMerge"] ?? r["block_merge"]) !== false
|
|
53
55
|
};
|
|
54
56
|
}
|
|
55
57
|
function readHostConfig(raw) {
|
|
@@ -200,12 +202,13 @@ var plugin = {
|
|
|
200
202
|
if (toolName === "git_autocommit") {
|
|
201
203
|
if (inp["dry_run"] === true) return;
|
|
202
204
|
gitOp = { type: "commit", snippet: "git_autocommit" };
|
|
203
|
-
} else if (toolName === "bash") {
|
|
204
|
-
const command = inp["command"];
|
|
205
|
-
if (typeof command !== "string") return;
|
|
206
|
-
gitOp = detectGitCommand(command);
|
|
207
205
|
} else if (toolName === "git") {
|
|
208
206
|
gitOp = detectStructuredGitCommand(inp);
|
|
207
|
+
} else {
|
|
208
|
+
const rawCmd = inp["command"] ?? inp["CommandLine"] ?? inp["cmd"] ?? inp["script"] ?? inp["input"];
|
|
209
|
+
const command = typeof rawCmd === "string" ? rawCmd : void 0;
|
|
210
|
+
if (typeof command !== "string") return;
|
|
211
|
+
gitOp = detectGitCommand(command);
|
|
209
212
|
}
|
|
210
213
|
if (!gitOp) return;
|
|
211
214
|
if (!shouldBlock(gitOp.type, cfg)) return;
|
|
@@ -61,9 +61,9 @@ export declare function commitSubjectFromCommand(command: string): string | null
|
|
|
61
61
|
export declare function renderUnreleasedBlock(entries: ChangelogEntry[]): string;
|
|
62
62
|
/**
|
|
63
63
|
* Merge a rendered Unreleased block into existing changelog content:
|
|
64
|
-
* inserted directly under `## [Unreleased]
|
|
65
|
-
*
|
|
66
|
-
*
|
|
64
|
+
* inserted directly under `## [Unreleased]`, merging section headings
|
|
65
|
+
* and deduplicating entries. Creates the standard header when the file
|
|
66
|
+
* has no Unreleased heading.
|
|
67
67
|
*/
|
|
68
68
|
export declare function mergeIntoChangelog(existing: string | null, block: string): string;
|
|
69
69
|
declare const plugin: Plugin;
|
package/dist/changelog-writer.js
CHANGED
|
@@ -134,13 +134,13 @@ ${block}
|
|
|
134
134
|
if (!m || m.index === void 0) {
|
|
135
135
|
const h1 = /^#\s.*$/m.exec(existing);
|
|
136
136
|
if (h1 && h1.index !== void 0) {
|
|
137
|
-
const
|
|
138
|
-
return `${existing.slice(0,
|
|
137
|
+
const insertAt = h1.index + h1[0].length;
|
|
138
|
+
return `${existing.slice(0, insertAt)}
|
|
139
139
|
|
|
140
140
|
## [Unreleased]
|
|
141
141
|
|
|
142
142
|
${block}
|
|
143
|
-
${existing.slice(
|
|
143
|
+
${existing.slice(insertAt)}`;
|
|
144
144
|
}
|
|
145
145
|
return `## [Unreleased]
|
|
146
146
|
|
|
@@ -148,11 +148,50 @@ ${block}
|
|
|
148
148
|
|
|
149
149
|
${existing}`;
|
|
150
150
|
}
|
|
151
|
-
const
|
|
152
|
-
|
|
151
|
+
const startIndex = m.index + m[0].length;
|
|
152
|
+
const nextSectionMatch = /^##\s+\[?[0-9v]/im.exec(existing.slice(startIndex));
|
|
153
|
+
const endIndex = nextSectionMatch ? startIndex + nextSectionMatch.index : existing.length;
|
|
154
|
+
const currentUnreleased = existing.slice(startIndex, endIndex);
|
|
155
|
+
const rest = existing.slice(endIndex);
|
|
156
|
+
const existingEntries = [];
|
|
157
|
+
let currentSection = "Changed";
|
|
158
|
+
for (const line of currentUnreleased.split(/\r?\n/)) {
|
|
159
|
+
const trimmed = line.trim();
|
|
160
|
+
if (trimmed.startsWith("### ")) {
|
|
161
|
+
const secName = trimmed.slice(4).trim();
|
|
162
|
+
if (SECTION_ORDER.includes(secName)) currentSection = secName;
|
|
163
|
+
} else if (trimmed.startsWith("- ")) {
|
|
164
|
+
existingEntries.push({
|
|
165
|
+
section: currentSection,
|
|
166
|
+
text: trimmed.slice(2).trim(),
|
|
167
|
+
origin: "manual",
|
|
168
|
+
when: (/* @__PURE__ */ new Date()).toISOString()
|
|
169
|
+
});
|
|
170
|
+
}
|
|
171
|
+
}
|
|
172
|
+
const newEntries = [];
|
|
173
|
+
let newSec = "Changed";
|
|
174
|
+
for (const line of block.split(/\r?\n/)) {
|
|
175
|
+
const trimmed = line.trim();
|
|
176
|
+
if (trimmed.startsWith("### ")) {
|
|
177
|
+
const secName = trimmed.slice(4).trim();
|
|
178
|
+
if (SECTION_ORDER.includes(secName)) newSec = secName;
|
|
179
|
+
} else if (trimmed.startsWith("- ")) {
|
|
180
|
+
newEntries.push({
|
|
181
|
+
section: newSec,
|
|
182
|
+
text: trimmed.slice(2).trim(),
|
|
183
|
+
origin: "manual",
|
|
184
|
+
when: (/* @__PURE__ */ new Date()).toISOString()
|
|
185
|
+
});
|
|
186
|
+
}
|
|
187
|
+
}
|
|
188
|
+
const combinedBlock = renderUnreleasedBlock([...newEntries, ...existingEntries]);
|
|
189
|
+
const formattedRest = rest.trim() ? `
|
|
153
190
|
|
|
154
|
-
${
|
|
155
|
-
|
|
191
|
+
${rest.trimStart()}` : "\n";
|
|
192
|
+
return `${existing.slice(0, startIndex)}
|
|
193
|
+
|
|
194
|
+
${combinedBlock}${formattedRest}`;
|
|
156
195
|
}
|
|
157
196
|
var plugin = {
|
|
158
197
|
name: "changelog-writer",
|
|
@@ -230,8 +269,8 @@ var plugin = {
|
|
|
230
269
|
if (p?.isError) return;
|
|
231
270
|
const toolName = p?.tool ?? p?.name ?? "";
|
|
232
271
|
const input = p?.input ?? {};
|
|
233
|
-
if (toolName === "write" || toolName === "edit") {
|
|
234
|
-
const raw = input["path"] ?? input["
|
|
272
|
+
if (toolName === "write" || toolName === "edit" || toolName === "write_to_file" || toolName === "replace_file_content") {
|
|
273
|
+
const raw = input["path"] ?? input["TargetFile"] ?? input["filePath"] ?? input["targetFile"] ?? input["file_path"] ?? input["file"];
|
|
235
274
|
if (typeof raw === "string" && raw) state.filesTouched.add(raw);
|
|
236
275
|
return;
|
|
237
276
|
}
|
|
@@ -248,7 +287,7 @@ var plugin = {
|
|
|
248
287
|
return;
|
|
249
288
|
}
|
|
250
289
|
if (toolName === "bash" || toolName === "exec") {
|
|
251
|
-
const command = typeof input["command"] === "string" ? input["command"] : "";
|
|
290
|
+
const command = typeof input["command"] === "string" ? input["command"] : typeof input["CommandLine"] === "string" ? input["CommandLine"] : typeof input["cmd"] === "string" ? input["cmd"] : "";
|
|
252
291
|
const subject = command ? commitSubjectFromCommand(command) : null;
|
|
253
292
|
if (subject) {
|
|
254
293
|
state.commitsSeen += 1;
|
|
@@ -280,7 +319,9 @@ var plugin = {
|
|
|
280
319
|
mutating: false,
|
|
281
320
|
async execute(input) {
|
|
282
321
|
if (!cfg.enabled) return { ok: false, error: "changelog-writer is disabled" };
|
|
283
|
-
const
|
|
322
|
+
const raw = input ?? {};
|
|
323
|
+
const rawText = input.text ?? raw["message"] ?? raw["entry"] ?? raw["content"] ?? raw["description"] ?? raw["desc"] ?? raw["summary"] ?? raw["body"] ?? raw["note"] ?? raw["item"];
|
|
324
|
+
const text = String(rawText ?? "").trim();
|
|
284
325
|
if (!text) return { ok: false, error: "entry text must not be empty" };
|
|
285
326
|
const section = SECTION_ORDER.includes(input.section) ? input.section : "Changed";
|
|
286
327
|
addEntry({ section, text, origin: "manual", when: (/* @__PURE__ */ new Date()).toISOString() });
|
|
@@ -303,8 +344,10 @@ var plugin = {
|
|
|
303
344
|
category: "Docs",
|
|
304
345
|
mutating: false,
|
|
305
346
|
async execute(input) {
|
|
347
|
+
const rawInput = input ?? {};
|
|
348
|
+
const shouldPolish = input.polish === true || rawInput["use_llm"] === true || rawInput["useLlm"] === true || rawInput["ai"] === true || rawInput["use_ai"] === true;
|
|
306
349
|
const raw = renderUnreleasedBlock(state.entries);
|
|
307
|
-
const markdown = raw ? await maybePolish(raw,
|
|
350
|
+
const markdown = raw ? await maybePolish(raw, shouldPolish) : "";
|
|
308
351
|
return {
|
|
309
352
|
ok: true,
|
|
310
353
|
enabled: cfg.enabled,
|
|
@@ -312,7 +355,7 @@ var plugin = {
|
|
|
312
355
|
pendingEntries: state.entries.length,
|
|
313
356
|
filesTouched: [...state.filesTouched].slice(0, 50),
|
|
314
357
|
commitsSeen: state.commitsSeen,
|
|
315
|
-
polished:
|
|
358
|
+
polished: shouldPolish && markdown !== raw,
|
|
316
359
|
llmAvailable: Boolean(api.llm),
|
|
317
360
|
markdown: markdown || "(no pending entries)"
|
|
318
361
|
};
|
|
@@ -341,9 +384,11 @@ var plugin = {
|
|
|
341
384
|
if (state.entries.length === 0) {
|
|
342
385
|
return { ok: false, error: "no pending entries \u2014 add some with changelog_add first" };
|
|
343
386
|
}
|
|
387
|
+
const rawInput = input ?? {};
|
|
388
|
+
const shouldPolish = input.polish === true || rawInput["use_llm"] === true || rawInput["useLlm"] === true || rawInput["ai"] === true || rawInput["use_ai"] === true;
|
|
344
389
|
const block = await maybePolish(
|
|
345
390
|
renderUnreleasedBlock(state.entries),
|
|
346
|
-
|
|
391
|
+
shouldPolish
|
|
347
392
|
);
|
|
348
393
|
let existing = null;
|
|
349
394
|
try {
|
package/dist/checkpoint.js
CHANGED
|
@@ -29,6 +29,7 @@ function readConfig(raw) {
|
|
|
29
29
|
};
|
|
30
30
|
}
|
|
31
31
|
function resolveProjectPath(rawPath, cwd = process.cwd()) {
|
|
32
|
+
if (typeof rawPath !== "string" || rawPath.length === 0) return null;
|
|
32
33
|
const root = resolve(cwd);
|
|
33
34
|
const resolved = isAbsolute(rawPath) ? resolve(rawPath) : resolve(root, rawPath);
|
|
34
35
|
const rel = relative(root, resolved);
|
|
@@ -132,7 +133,7 @@ var plugin = {
|
|
|
132
133
|
if (cfg.enabled && cfg.autoCapture) {
|
|
133
134
|
const hook = async (input, runtime = { signal: new AbortController().signal }) => {
|
|
134
135
|
const ti = input.toolInput ?? {};
|
|
135
|
-
const raw = ti["path"] ?? ti["file_path"] ?? ti["filePath"];
|
|
136
|
+
const raw = ti["path"] ?? ti["file_path"] ?? ti["filePath"] ?? ti["TargetFile"] ?? ti["targetFile"] ?? ti["file"];
|
|
136
137
|
if (typeof raw !== "string" || raw.length === 0) return;
|
|
137
138
|
const safePath = resolveProjectPath(raw);
|
|
138
139
|
if (!safePath) return;
|
|
@@ -192,7 +193,14 @@ var plugin = {
|
|
|
192
193
|
mutating: false,
|
|
193
194
|
async execute(input) {
|
|
194
195
|
if (!cfg.enabled) return { ok: false, error: "checkpoint is disabled" };
|
|
195
|
-
|
|
196
|
+
let paths = [];
|
|
197
|
+
const rawInput = input;
|
|
198
|
+
const raw = rawInput["paths"] ?? rawInput["path"] ?? rawInput["files"] ?? rawInput["file"] ?? rawInput["filePath"] ?? rawInput["file_path"] ?? rawInput["TargetFile"] ?? rawInput["targetFile"];
|
|
199
|
+
if (typeof raw === "string" && raw.trim().length > 0) {
|
|
200
|
+
paths = [raw.trim()];
|
|
201
|
+
} else if (Array.isArray(raw)) {
|
|
202
|
+
paths = raw.filter((p) => typeof p === "string" && p.trim().length > 0);
|
|
203
|
+
}
|
|
196
204
|
if (paths.length === 0) return { ok: false, error: "paths must not be empty" };
|
|
197
205
|
const files = [];
|
|
198
206
|
const rejectedOutsideProject = [];
|
|
@@ -295,17 +303,20 @@ var plugin = {
|
|
|
295
303
|
mutating: true,
|
|
296
304
|
async execute(input) {
|
|
297
305
|
if (!cfg.enabled) return { ok: false, error: "checkpoint is disabled" };
|
|
298
|
-
const
|
|
306
|
+
const raw = input ?? {};
|
|
307
|
+
const rawId = (typeof input.id === "string" && input.id.trim().length > 0 ? input.id.trim() : void 0) ?? (typeof raw["snapshotId"] === "string" ? raw["snapshotId"] : void 0) ?? (typeof raw["snapshot_id"] === "string" ? raw["snapshot_id"] : void 0);
|
|
308
|
+
const rawPath = (typeof input.path === "string" && input.path.trim().length > 0 ? input.path.trim() : void 0) ?? (typeof raw["filePath"] === "string" ? raw["filePath"] : void 0) ?? (typeof raw["file_path"] === "string" ? raw["file_path"] : void 0) ?? (typeof raw["TargetFile"] === "string" ? raw["TargetFile"] : void 0) ?? (typeof raw["targetFile"] === "string" ? raw["targetFile"] : void 0) ?? (typeof raw["file"] === "string" ? raw["file"] : void 0);
|
|
309
|
+
const snapshot = rawId ? state.snapshots.find((s) => s.id === rawId) : state.snapshots[state.snapshots.length - 1];
|
|
299
310
|
if (!snapshot) {
|
|
300
311
|
return {
|
|
301
312
|
ok: false,
|
|
302
|
-
error:
|
|
313
|
+
error: rawId ? `no snapshot with id "${rawId}"` : "no snapshots captured yet"
|
|
303
314
|
};
|
|
304
315
|
}
|
|
305
|
-
const targetPath =
|
|
306
|
-
const targets = targetPath ? snapshot.files.filter((f) => f.path === targetPath || f.path ===
|
|
316
|
+
const targetPath = rawPath ? resolveProjectPath(rawPath) ?? rawPath : null;
|
|
317
|
+
const targets = targetPath ? snapshot.files.filter((f) => f.path === targetPath || f.path === rawPath) : snapshot.files;
|
|
307
318
|
if (targets.length === 0) {
|
|
308
|
-
return { ok: false, error: `snapshot ${snapshot.id} has no entry for "${
|
|
319
|
+
return { ok: false, error: `snapshot ${snapshot.id} has no entry for "${rawPath}"` };
|
|
309
320
|
}
|
|
310
321
|
const restored = [];
|
|
311
322
|
const createdByTool = [];
|
package/dist/code-metrics.js
CHANGED
|
@@ -38,10 +38,12 @@ var DEFAULTS = {
|
|
|
38
38
|
function readConfig(raw) {
|
|
39
39
|
if (!raw || typeof raw !== "object") return { ...DEFAULTS };
|
|
40
40
|
const r = raw;
|
|
41
|
+
const rawExts = r["extensions"] ?? r["file_extensions"] ?? r["fileExtensions"];
|
|
42
|
+
const rawMax = r["maxFiles"] ?? r["max_files"] ?? r["limit"];
|
|
41
43
|
return {
|
|
42
44
|
enabled: r["enabled"] !== false,
|
|
43
|
-
extensions: Array.isArray(
|
|
44
|
-
maxFiles: typeof
|
|
45
|
+
extensions: Array.isArray(rawExts) ? rawExts.filter((x) => typeof x === "string") : DEFAULTS.extensions,
|
|
46
|
+
maxFiles: typeof rawMax === "number" && rawMax >= 1 && rawMax <= 500 ? rawMax : DEFAULTS.maxFiles
|
|
45
47
|
};
|
|
46
48
|
}
|
|
47
49
|
function normalizeExtensions(exts) {
|
|
@@ -71,15 +73,19 @@ function countFunctions(content) {
|
|
|
71
73
|
return count;
|
|
72
74
|
}
|
|
73
75
|
var COMPLEXITY_FORMULA = "control(if|else if|for|while|switch|catch) + (&& || ?? ||= &&= ??=) + ternary ?; optional chaining ?. is not counted";
|
|
76
|
+
function stripNonExecutable(code) {
|
|
77
|
+
return code.replace(/\/\*[\s\S]*?\*\//g, " ").replace(/\/\/[^\n]*/g, " ").replace(/(["'`])(?:\\.|(?!\1)[^\\])*\1/g, " ").replace(/\b[A-Za-z_$][A-Za-z0-9_$]*\s*\?\s*:/g, " ");
|
|
78
|
+
}
|
|
74
79
|
function countComplexity(content) {
|
|
80
|
+
const code = stripNonExecutable(content);
|
|
75
81
|
const controlRe = /\b(if|else\s+if|for|while|switch|catch)\b/g;
|
|
76
82
|
let complexity = 0;
|
|
77
83
|
controlRe.lastIndex = 0;
|
|
78
|
-
for (const _match of
|
|
79
|
-
for (let i = 0; i <
|
|
80
|
-
const c =
|
|
81
|
-
const n1 =
|
|
82
|
-
const n2 =
|
|
84
|
+
for (const _match of code.matchAll(controlRe)) complexity++;
|
|
85
|
+
for (let i = 0; i < code.length; i++) {
|
|
86
|
+
const c = code[i];
|
|
87
|
+
const n1 = code[i + 1];
|
|
88
|
+
const n2 = code[i + 2];
|
|
83
89
|
if (c === "?" && n1 === "?" && n2 === "=") {
|
|
84
90
|
complexity++;
|
|
85
91
|
i += 2;
|
|
@@ -214,7 +220,8 @@ var plugin = {
|
|
|
214
220
|
if (!cfg.enabled) return;
|
|
215
221
|
if (input.toolResult?.isError) return;
|
|
216
222
|
const inp = input.toolInput ?? {};
|
|
217
|
-
const
|
|
223
|
+
const rawSource = inp["path"] ?? inp["TargetFile"] ?? inp["filePath"] ?? inp["targetFile"] ?? inp["file_path"] ?? inp["destination"] ?? inp["file"];
|
|
224
|
+
const sourcePath = typeof rawSource === "string" ? rawSource : void 0;
|
|
218
225
|
if (!sourcePath || typeof sourcePath !== "string") return;
|
|
219
226
|
if (!(0, runtime_exports.withinProject)(sourcePath)) return;
|
|
220
227
|
const exts = normalizeExtensions(cfg.extensions);
|
|
@@ -249,7 +256,8 @@ var plugin = {
|
|
|
249
256
|
mutating: false,
|
|
250
257
|
async execute(input) {
|
|
251
258
|
if (!cfg.enabled) return { ok: false, error: "code-metrics is disabled" };
|
|
252
|
-
const
|
|
259
|
+
const raw = input ?? {};
|
|
260
|
+
const rawPath = (typeof input.path === "string" && input.path.trim().length > 0 ? input.path.trim() : void 0) ?? (typeof raw["directory"] === "string" ? raw["directory"] : void 0) ?? (typeof raw["dir"] === "string" ? raw["dir"] : void 0) ?? (typeof raw["SearchDirectory"] === "string" ? raw["SearchDirectory"] : void 0) ?? (typeof raw["filePath"] === "string" ? raw["filePath"] : void 0) ?? (typeof raw["TargetFile"] === "string" ? raw["TargetFile"] : void 0) ?? (typeof raw["targetFile"] === "string" ? raw["targetFile"] : void 0) ?? (typeof raw["file_path"] === "string" ? raw["file_path"] : void 0) ?? (typeof raw["file"] === "string" ? raw["file"] : void 0) ?? ".";
|
|
253
261
|
if (!(0, runtime_exports.withinProject)(rawPath)) {
|
|
254
262
|
return { ok: false, error: "path is outside the project root" };
|
|
255
263
|
}
|