@wrongstack/plugins 0.293.0 → 0.295.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/README.md +7 -71
- package/dist/accessibility-auditor/index.d.ts +1 -1
- package/dist/accessibility-auditor/index.d.ts.map +1 -1
- package/dist/accessibility-auditor.js +50 -33
- package/dist/agent-handoff/index.d.ts +1 -1
- package/dist/agent-handoff/index.d.ts.map +1 -1
- package/dist/agent-handoff.js +30 -1
- package/dist/api-compatibility-gate/index.d.ts +1 -1
- package/dist/api-compatibility-gate/index.d.ts.map +1 -1
- package/dist/api-compatibility-gate.js +21 -16
- package/dist/audit/index.d.ts +386 -0
- package/dist/audit/index.d.ts.map +1 -0
- package/dist/audit.d.ts +1 -0
- package/dist/audit.js +454 -0
- package/dist/auto-doc/index.d.ts +1 -1
- package/dist/auto-doc/index.d.ts.map +1 -1
- package/dist/auto-doc.js +3 -1
- package/dist/auto-escalate/index.d.ts +1 -1
- package/dist/auto-escalate/index.d.ts.map +1 -1
- package/dist/auto-i18n-extractor/index.d.ts +1 -1
- package/dist/auto-i18n-extractor/index.d.ts.map +1 -1
- package/dist/auto-i18n-extractor.js +7 -1
- package/dist/branch-guard/index.d.ts +1 -1
- package/dist/branch-guard/index.d.ts.map +1 -1
- package/dist/branch-guard.js +111 -1
- package/dist/catalog.d.ts +5 -30
- package/dist/catalog.d.ts.map +1 -1
- package/dist/changelog-writer/index.d.ts +1 -1
- package/dist/changelog-writer/index.d.ts.map +1 -1
- package/dist/changelog-writer.js +137 -3
- package/dist/checkpoint/index.d.ts +3 -1
- package/dist/checkpoint/index.d.ts.map +1 -1
- package/dist/checkpoint.js +41 -16
- package/dist/code-metrics/index.d.ts +1 -1
- package/dist/code-metrics/index.d.ts.map +1 -1
- package/dist/code-metrics.js +34 -29
- package/dist/commit-validator/index.d.ts +1 -1
- package/dist/commit-validator/index.d.ts.map +1 -1
- package/dist/commit-validator.js +17 -7
- package/dist/config-validator/index.d.ts +1 -1
- package/dist/config-validator/index.d.ts.map +1 -1
- package/dist/context-pins/index.d.ts +1 -1
- package/dist/context-pins/index.d.ts.map +1 -1
- package/dist/context-pins.js +6 -5
- package/dist/cost-tracker/index.d.ts +1 -1
- package/dist/cost-tracker/index.d.ts.map +1 -1
- package/dist/cost-tracker.js +109 -2
- package/dist/cron/index.d.ts +1 -1
- package/dist/cron/index.d.ts.map +1 -1
- package/dist/cron.js +1 -0
- package/dist/dead-code-detector/index.d.ts +1 -1
- package/dist/dead-code-detector/index.d.ts.map +1 -1
- package/dist/dead-code-detector.js +31 -18
- package/dist/dep-guard/index.d.ts +1 -1
- package/dist/dep-guard/index.d.ts.map +1 -1
- package/dist/dependency-vulnerability-gate/index.d.ts +1 -1
- package/dist/dependency-vulnerability-gate/index.d.ts.map +1 -1
- package/dist/dependency-vulnerability-gate.js +67 -20
- package/dist/diff-summary/index.d.ts +1 -1
- package/dist/diff-summary/index.d.ts.map +1 -1
- package/dist/diff-summary.js +128 -30
- package/dist/doc-sync-guard/index.d.ts +1 -1
- package/dist/doc-sync-guard/index.d.ts.map +1 -1
- package/dist/doc-sync-guard.js +7 -1
- package/dist/duplicate-code-detector/index.d.ts +26 -1
- package/dist/duplicate-code-detector/index.d.ts.map +1 -1
- package/dist/duplicate-code-detector.js +280 -69
- package/dist/error-lens/index.d.ts +1 -1
- package/dist/error-lens/index.d.ts.map +1 -1
- package/dist/factories/index.d.ts +4 -0
- package/dist/factories/index.d.ts.map +1 -0
- package/dist/factories.d.ts +1 -0
- package/dist/factories.js +74 -0
- package/dist/feature-flag-tracker/index.d.ts +1 -1
- package/dist/feature-flag-tracker/index.d.ts.map +1 -1
- package/dist/feature-flag-tracker.js +59 -33
- package/dist/file-watcher/index.d.ts +1 -1
- package/dist/file-watcher/index.d.ts.map +1 -1
- package/dist/file-watcher.js +6 -7
- package/dist/format-on-save/index.d.ts +3 -1
- package/dist/format-on-save/index.d.ts.map +1 -1
- package/dist/format-on-save.js +289 -59
- package/dist/generated-plugin-exports.d.ts +65 -0
- package/dist/generated-plugin-exports.d.ts.map +1 -0
- package/dist/git-autocommit/index.d.ts +1 -1
- package/dist/git-autocommit/index.d.ts.map +1 -1
- package/dist/import-organizer/index.d.ts +1 -1
- package/dist/import-organizer/index.d.ts.map +1 -1
- package/dist/import-organizer.js +141 -20
- package/dist/index.d.ts +4 -183
- package/dist/index.d.ts.map +1 -1
- package/dist/index.js +18298 -17279
- package/dist/injection-shield/index.d.ts +1 -1
- package/dist/injection-shield/index.d.ts.map +1 -1
- package/dist/interface-contract-guard/index.d.ts +1 -1
- package/dist/interface-contract-guard/index.d.ts.map +1 -1
- package/dist/interface-contract-guard.js +87 -53
- package/dist/knowledge-graph/index.d.ts +1 -1
- package/dist/knowledge-graph/index.d.ts.map +1 -1
- package/dist/knowledge-graph.js +7 -6
- package/dist/license-audit-gate/index.d.ts +1 -1
- package/dist/license-audit-gate/index.d.ts.map +1 -1
- package/dist/lint-gate/index.d.ts +1 -1
- package/dist/lint-gate/index.d.ts.map +1 -1
- package/dist/lint-gate.js +112 -1
- package/dist/llm-cache/index.d.ts +5 -1
- package/dist/llm-cache/index.d.ts.map +1 -1
- package/dist/llm-cache.js +16 -8
- package/dist/loop-breaker/index.d.ts +1 -1
- package/dist/loop-breaker/index.d.ts.map +1 -1
- package/dist/loop-breaker.js +25 -9
- package/dist/manifest/index.d.ts +16 -0
- package/dist/manifest/index.d.ts.map +1 -0
- package/dist/manifest.d.ts +1 -0
- package/dist/manifest.js +152 -0
- package/dist/migration-planner/index.d.ts +1 -1
- package/dist/migration-planner/index.d.ts.map +1 -1
- package/dist/migration-planner.js +5 -1
- package/dist/model-router/index.d.ts +1 -1
- package/dist/model-router/index.d.ts.map +1 -1
- package/dist/notify-hub/index.d.ts +1 -1
- package/dist/notify-hub/index.d.ts.map +1 -1
- package/dist/notify-hub/webhook-channel.d.ts +1 -1
- package/dist/notify-hub/webhook-channel.d.ts.map +1 -1
- package/dist/notify-hub.js +41 -4
- package/dist/path-guard/index.d.ts +1 -1
- package/dist/path-guard/index.d.ts.map +1 -1
- package/dist/performance-regression-gate/index.d.ts +1 -1
- package/dist/performance-regression-gate/index.d.ts.map +1 -1
- package/dist/plugin-stack-observer/index.d.ts +1 -1
- package/dist/plugin-stack-observer/index.d.ts.map +1 -1
- package/dist/pr-drafter/index.d.ts +1 -1
- package/dist/pr-drafter/index.d.ts.map +1 -1
- package/dist/pr-drafter.js +28 -29
- package/dist/process-guard/index.d.ts +1 -1
- package/dist/process-guard/index.d.ts.map +1 -1
- package/dist/prompt-firewall/index.d.ts +1 -1
- package/dist/prompt-firewall/index.d.ts.map +1 -1
- package/dist/prompt-firewall.js +140 -11
- package/dist/refactor-suggester/index.d.ts +1 -1
- package/dist/refactor-suggester/index.d.ts.map +1 -1
- package/dist/refactor-suggester.js +148 -33
- package/dist/release-notes-generator/index.d.ts +1 -1
- package/dist/release-notes-generator/index.d.ts.map +1 -1
- package/dist/release-notes-generator.js +29 -22
- package/dist/runtime/bounded-map.d.ts +86 -0
- package/dist/runtime/bounded-map.d.ts.map +1 -0
- package/dist/runtime/credential-patterns.d.ts +42 -0
- package/dist/runtime/credential-patterns.d.ts.map +1 -0
- package/dist/runtime/index.d.ts +18 -0
- package/dist/runtime/index.d.ts.map +1 -1
- package/dist/runtime/llm.d.ts +1 -1
- package/dist/runtime/llm.d.ts.map +1 -1
- package/dist/runtime/local-bin.d.ts +120 -0
- package/dist/runtime/local-bin.d.ts.map +1 -0
- package/dist/runtime/safe-json.d.ts +25 -0
- package/dist/runtime/safe-json.d.ts.map +1 -0
- package/dist/runtime.js +332 -22
- package/dist/schema-evolution-guard/index.d.ts +1 -1
- package/dist/schema-evolution-guard/index.d.ts.map +1 -1
- package/dist/schema-evolution-guard.js +7 -1
- package/dist/secret-scanner/index.d.ts +1 -1
- package/dist/secret-scanner/index.d.ts.map +1 -1
- package/dist/secret-scanner.js +181 -48
- package/dist/security-hotspot-scanner/index.d.ts +1 -1
- package/dist/security-hotspot-scanner/index.d.ts.map +1 -1
- package/dist/security-hotspot-scanner.js +158 -20
- package/dist/semantic-search-indexer/index.d.ts +1 -1
- package/dist/semantic-search-indexer/index.d.ts.map +1 -1
- package/dist/semantic-search-indexer.js +7 -1
- package/dist/semver-bump/index.d.ts +1 -1
- package/dist/semver-bump/index.d.ts.map +1 -1
- package/dist/semver-bump.js +97 -43
- package/dist/session-recap/index.d.ts +1 -1
- package/dist/session-recap/index.d.ts.map +1 -1
- package/dist/shell-check/index.d.ts +1 -1
- package/dist/shell-check/index.d.ts.map +1 -1
- package/dist/smart-rename/index.d.ts +1 -1
- package/dist/smart-rename/index.d.ts.map +1 -1
- package/dist/spec-linker/index.d.ts +1 -1
- package/dist/spec-linker/index.d.ts.map +1 -1
- package/dist/spec-linker.js +222 -20772
- package/dist/template-engine/index.d.ts +1 -1
- package/dist/template-engine/index.d.ts.map +1 -1
- package/dist/template-engine.js +34 -8
- package/dist/test-coverage-gate/index.d.ts +1 -1
- package/dist/test-coverage-gate/index.d.ts.map +1 -1
- package/dist/test-coverage-gate.js +34 -14
- package/dist/test-flake-detector/index.d.ts +1 -1
- package/dist/test-flake-detector/index.d.ts.map +1 -1
- package/dist/test-flake-detector.js +31 -20
- package/dist/test-generator/index.d.ts +1 -1
- package/dist/test-generator/index.d.ts.map +1 -1
- package/dist/test-runner-gate/index.d.ts +1 -1
- package/dist/test-runner-gate/index.d.ts.map +1 -1
- package/dist/test-runner-gate.js +132 -9
- package/dist/todo-listener/index.d.ts +1 -32
- package/dist/todo-listener/index.d.ts.map +1 -1
- package/dist/todo-listener.js +30 -1
- package/dist/todo-tracker/index.d.ts +1 -1
- package/dist/todo-tracker/index.d.ts.map +1 -1
- package/dist/todo-tracker.js +3 -4
- package/dist/token-budget/index.d.ts +1 -1
- package/dist/token-budget/index.d.ts.map +1 -1
- package/dist/token-throttle/index.d.ts +1 -1
- package/dist/token-throttle/index.d.ts.map +1 -1
- package/dist/token-throttle.js +17 -2
- package/dist/type-gate/index.d.ts +1 -1
- package/dist/type-gate/index.d.ts.map +1 -1
- package/dist/type-gate.js +106 -19
- package/package.json +80 -68
|
@@ -7,7 +7,7 @@
|
|
|
7
7
|
* - template_create: Save a named template to the plugin store
|
|
8
8
|
* - template_list: List all saved templates
|
|
9
9
|
*/
|
|
10
|
-
import type { Plugin } from '@wrongstack/core';
|
|
10
|
+
import type { Plugin } from '@wrongstack/core/types';
|
|
11
11
|
declare const plugin: Plugin;
|
|
12
12
|
export default plugin;
|
|
13
13
|
//# sourceMappingURL=index.d.ts.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../src/template-engine/index.ts"],"names":[],"mappings":"AAAA;;;;;;;;GAQG;AACH,OAAO,KAAK,EAAE,MAAM,EAAE,MAAM,
|
|
1
|
+
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../src/template-engine/index.ts"],"names":[],"mappings":"AAAA;;;;;;;;GAQG;AACH,OAAO,KAAK,EAAE,MAAM,EAAE,MAAM,wBAAwB,CAAC;AA+HrD,QAAA,MAAM,MAAM,EAAE,MA4Sb,CAAC;eAEa,MAAM"}
|
package/dist/template-engine.js
CHANGED
|
@@ -1,5 +1,31 @@
|
|
|
1
1
|
// src/template-engine/index.ts
|
|
2
|
-
import {
|
|
2
|
+
import { readFile, writeFile } from "node:fs/promises";
|
|
3
|
+
import { isAbsolute as isAbsolute2 } from "node:path";
|
|
4
|
+
|
|
5
|
+
// src/runtime/index.ts
|
|
6
|
+
import { basename, extname, isAbsolute, relative, resolve } from "node:path";
|
|
7
|
+
|
|
8
|
+
// src/runtime/local-bin.ts
|
|
9
|
+
import { buildWin32CmdShimInvocation, resolveWin32Command } from "@wrongstack/tools/win32";
|
|
10
|
+
|
|
11
|
+
// src/runtime/index.ts
|
|
12
|
+
var MAX_BUFFER_BYTES = 16 * 1024 * 1024;
|
|
13
|
+
function hasLeadingDash(arg) {
|
|
14
|
+
return arg.length > 0 && arg.startsWith("-");
|
|
15
|
+
}
|
|
16
|
+
function withinProjectPath(projectRoot, candidate) {
|
|
17
|
+
if (candidate.length === 0 || candidate.length > 4096) return false;
|
|
18
|
+
if (hasLeadingDash(candidate)) return false;
|
|
19
|
+
const resolved = isAbsolute(candidate) ? resolve(candidate) : resolve(projectRoot, candidate);
|
|
20
|
+
const rel = relative(projectRoot, resolved);
|
|
21
|
+
return rel === "" || !rel.startsWith("..") && !isAbsolute(rel);
|
|
22
|
+
}
|
|
23
|
+
function withinProject(p) {
|
|
24
|
+
const cwd = process.cwd();
|
|
25
|
+
return withinProjectPath(cwd, p) || relative(cwd, p) === ".";
|
|
26
|
+
}
|
|
27
|
+
|
|
28
|
+
// src/template-engine/index.ts
|
|
3
29
|
var API_VERSION = "^0.1.10";
|
|
4
30
|
var templates = /* @__PURE__ */ new Map();
|
|
5
31
|
function expandTemplate(template, variables) {
|
|
@@ -46,9 +72,12 @@ function renderTemplateRaw(template, variables) {
|
|
|
46
72
|
return result;
|
|
47
73
|
}
|
|
48
74
|
function validateRelativeTemplatePath(field, value) {
|
|
49
|
-
if (
|
|
75
|
+
if (isAbsolute2(value) || value.split(/[\\/]+/).includes("..")) {
|
|
50
76
|
return `${field} must be a relative path without ".." components`;
|
|
51
77
|
}
|
|
78
|
+
if (!withinProject(value)) {
|
|
79
|
+
return `${field} must resolve inside the project directory`;
|
|
80
|
+
}
|
|
52
81
|
return null;
|
|
53
82
|
}
|
|
54
83
|
var plugin = {
|
|
@@ -119,8 +148,7 @@ var plugin = {
|
|
|
119
148
|
if (output_path) {
|
|
120
149
|
const pathError = validateRelativeTemplatePath("output_path", output_path);
|
|
121
150
|
if (pathError) return { ok: false, error: pathError };
|
|
122
|
-
|
|
123
|
-
writeFileSync(output_path, result, "utf-8");
|
|
151
|
+
await writeFile(output_path, result, "utf-8");
|
|
124
152
|
return {
|
|
125
153
|
ok: true,
|
|
126
154
|
output_path,
|
|
@@ -173,8 +201,7 @@ var plugin = {
|
|
|
173
201
|
}
|
|
174
202
|
let content;
|
|
175
203
|
try {
|
|
176
|
-
|
|
177
|
-
content = readFileSync(template_path, "utf-8");
|
|
204
|
+
content = await readFile(template_path, "utf-8");
|
|
178
205
|
} catch (err) {
|
|
179
206
|
return { ok: false, error: `Could not read template file: ${err}` };
|
|
180
207
|
}
|
|
@@ -187,8 +214,7 @@ var plugin = {
|
|
|
187
214
|
if (output_path) {
|
|
188
215
|
const pathError = validateRelativeTemplatePath("output_path", output_path);
|
|
189
216
|
if (pathError) return { ok: false, error: pathError };
|
|
190
|
-
|
|
191
|
-
writeFileSync(output_path, result, "utf-8");
|
|
217
|
+
await writeFile(output_path, result, "utf-8");
|
|
192
218
|
return {
|
|
193
219
|
ok: true,
|
|
194
220
|
template_path,
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../src/test-coverage-gate/index.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;GA8BG;
|
|
1
|
+
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../src/test-coverage-gate/index.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;GA8BG;AAGH,OAAO,KAAK,EAAE,MAAM,EAAE,MAAM,wBAAwB,CAAC;AAwIrD,QAAA,MAAM,MAAM,EAAE,MA0Ob,CAAC;eAEa,MAAM"}
|
|
@@ -1,6 +1,30 @@
|
|
|
1
1
|
// src/test-coverage-gate/index.ts
|
|
2
2
|
import { readFileSync } from "node:fs";
|
|
3
|
-
|
|
3
|
+
|
|
4
|
+
// src/runtime/index.ts
|
|
5
|
+
import { basename, extname, isAbsolute, relative, resolve } from "node:path";
|
|
6
|
+
|
|
7
|
+
// src/runtime/local-bin.ts
|
|
8
|
+
import { buildWin32CmdShimInvocation, resolveWin32Command } from "@wrongstack/tools/win32";
|
|
9
|
+
|
|
10
|
+
// src/runtime/index.ts
|
|
11
|
+
var MAX_BUFFER_BYTES = 16 * 1024 * 1024;
|
|
12
|
+
function hasLeadingDash(arg) {
|
|
13
|
+
return arg.length > 0 && arg.startsWith("-");
|
|
14
|
+
}
|
|
15
|
+
function withinProjectPath(projectRoot, candidate) {
|
|
16
|
+
if (candidate.length === 0 || candidate.length > 4096) return false;
|
|
17
|
+
if (hasLeadingDash(candidate)) return false;
|
|
18
|
+
const resolved = isAbsolute(candidate) ? resolve(candidate) : resolve(projectRoot, candidate);
|
|
19
|
+
const rel = relative(projectRoot, resolved);
|
|
20
|
+
return rel === "" || !rel.startsWith("..") && !isAbsolute(rel);
|
|
21
|
+
}
|
|
22
|
+
function withinProject(p) {
|
|
23
|
+
const cwd = process.cwd();
|
|
24
|
+
return withinProjectPath(cwd, p) || relative(cwd, p) === ".";
|
|
25
|
+
}
|
|
26
|
+
|
|
27
|
+
// src/test-coverage-gate/index.ts
|
|
4
28
|
var API_VERSION = "^0.1.10";
|
|
5
29
|
var state = {
|
|
6
30
|
invocationCount: 0,
|
|
@@ -21,28 +45,24 @@ var DEFAULTS = {
|
|
|
21
45
|
deltaThreshold: 1,
|
|
22
46
|
runOnChange: [".ts", ".tsx", ".js", ".jsx"]
|
|
23
47
|
};
|
|
48
|
+
var runOnChangeSet = new Set(DEFAULTS.runOnChange);
|
|
24
49
|
function readConfig(raw) {
|
|
25
|
-
if (!raw || typeof raw !== "object")
|
|
50
|
+
if (!raw || typeof raw !== "object") {
|
|
51
|
+
runOnChangeSet = new Set(DEFAULTS.runOnChange);
|
|
52
|
+
return { ...DEFAULTS };
|
|
53
|
+
}
|
|
26
54
|
const r = raw;
|
|
55
|
+
const runOnChange = Array.isArray(r["runOnChange"]) ? r["runOnChange"].filter((x) => typeof x === "string") : DEFAULTS.runOnChange;
|
|
56
|
+
runOnChangeSet = new Set(runOnChange);
|
|
27
57
|
return {
|
|
28
58
|
enabled: r["enabled"] !== false,
|
|
29
59
|
coveragePath: typeof r["coveragePath"] === "string" ? r["coveragePath"] : DEFAULTS.coveragePath,
|
|
30
60
|
threshold: typeof r["threshold"] === "number" && r["threshold"] >= 0 && r["threshold"] <= 100 ? r["threshold"] : DEFAULTS.threshold,
|
|
31
61
|
mode: r["mode"] === "block" ? "block" : DEFAULTS.mode,
|
|
32
62
|
deltaThreshold: typeof r["deltaThreshold"] === "number" && r["deltaThreshold"] >= 0 ? r["deltaThreshold"] : DEFAULTS.deltaThreshold,
|
|
33
|
-
runOnChange
|
|
63
|
+
runOnChange
|
|
34
64
|
};
|
|
35
65
|
}
|
|
36
|
-
function withinProject(p) {
|
|
37
|
-
if (typeof p !== "string" || p.length === 0 || p.length > 4096) return false;
|
|
38
|
-
const root = process.cwd();
|
|
39
|
-
const resolved = isAbsolute(p) ? resolve(p) : resolve(root, p);
|
|
40
|
-
const rel = relative(root, resolved);
|
|
41
|
-
if (rel === "" || rel === ".") return true;
|
|
42
|
-
if (rel.startsWith("..")) return false;
|
|
43
|
-
if (isAbsolute(rel)) return false;
|
|
44
|
-
return true;
|
|
45
|
-
}
|
|
46
66
|
function readCoverageSummary(coveragePath) {
|
|
47
67
|
try {
|
|
48
68
|
const raw = readFileSync(coveragePath, "utf-8");
|
|
@@ -125,7 +145,7 @@ var plugin = {
|
|
|
125
145
|
if (!sourcePath || typeof sourcePath !== "string") return;
|
|
126
146
|
if (!withinProject(sourcePath)) return;
|
|
127
147
|
const ext = sourcePath.includes(".") ? sourcePath.slice(sourcePath.lastIndexOf(".")).toLowerCase() : "";
|
|
128
|
-
if (!
|
|
148
|
+
if (!runOnChangeSet.has(ext)) {
|
|
129
149
|
state.skippedCount += 1;
|
|
130
150
|
return;
|
|
131
151
|
}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../src/test-flake-detector/index.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;;;;GAoBG;AAMH,OAAO,KAAK,EAAE,MAAM,EAAE,MAAM,
|
|
1
|
+
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../src/test-flake-detector/index.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;;;;GAoBG;AAMH,OAAO,KAAK,EAAE,MAAM,EAAE,MAAM,wBAAwB,CAAC;AAyQrD,QAAA,MAAM,MAAM,EAAE,MA6Nb,CAAC;eAEa,MAAM"}
|
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
// src/test-flake-detector/index.ts
|
|
2
|
-
import {
|
|
2
|
+
import { execFile } from "node:child_process";
|
|
3
3
|
import { readFileSync } from "node:fs";
|
|
4
4
|
import { createRequire } from "node:module";
|
|
5
5
|
import { dirname, isAbsolute, relative, resolve } from "node:path";
|
|
@@ -144,24 +144,35 @@ function resolveTestCommand(baseCommand, testPattern) {
|
|
|
144
144
|
};
|
|
145
145
|
}
|
|
146
146
|
function runOnce(command, timeoutMs) {
|
|
147
|
-
|
|
148
|
-
|
|
149
|
-
|
|
150
|
-
|
|
151
|
-
|
|
152
|
-
|
|
153
|
-
|
|
154
|
-
|
|
155
|
-
|
|
156
|
-
|
|
157
|
-
|
|
158
|
-
|
|
159
|
-
|
|
160
|
-
|
|
161
|
-
|
|
162
|
-
|
|
163
|
-
|
|
164
|
-
|
|
147
|
+
return new Promise((resolveRun) => {
|
|
148
|
+
execFile(
|
|
149
|
+
command.cmd,
|
|
150
|
+
command.args,
|
|
151
|
+
{
|
|
152
|
+
encoding: "utf8",
|
|
153
|
+
timeout: timeoutMs,
|
|
154
|
+
cwd: process.cwd(),
|
|
155
|
+
windowsHide: true,
|
|
156
|
+
maxBuffer: 10 * 1024 * 1024,
|
|
157
|
+
shell: false
|
|
158
|
+
},
|
|
159
|
+
(error, stdout, stderr) => {
|
|
160
|
+
if (!error) {
|
|
161
|
+
resolveRun({ output: stdout });
|
|
162
|
+
return;
|
|
163
|
+
}
|
|
164
|
+
if (error.killed) {
|
|
165
|
+
resolveRun({ output: stdout, error: `timeout after ${timeoutMs}ms` });
|
|
166
|
+
return;
|
|
167
|
+
}
|
|
168
|
+
resolveRun({
|
|
169
|
+
output: `${stdout}
|
|
170
|
+
${stderr}`.trim(),
|
|
171
|
+
error: error.message || "test command exited with non-zero code"
|
|
172
|
+
});
|
|
173
|
+
}
|
|
174
|
+
);
|
|
175
|
+
});
|
|
165
176
|
}
|
|
166
177
|
var plugin = {
|
|
167
178
|
name: "test-flake-detector",
|
|
@@ -251,7 +262,7 @@ var plugin = {
|
|
|
251
262
|
let runsCompleted = 0;
|
|
252
263
|
const runErrors = [];
|
|
253
264
|
for (let run = 1; run <= requestedRuns; run += 1) {
|
|
254
|
-
const { output, error } = runOnce(command, cfg.timeoutMs);
|
|
265
|
+
const { output, error } = await runOnce(command, cfg.timeoutMs);
|
|
255
266
|
state.runCount += 1;
|
|
256
267
|
if (error) {
|
|
257
268
|
state.errorCount += 1;
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../src/test-generator/index.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;;;;;;;GAuBG;AAIH,OAAO,KAAK,EAAE,MAAM,EAAE,MAAM,
|
|
1
|
+
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../src/test-generator/index.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;;;;;;;GAuBG;AAIH,OAAO,KAAK,EAAE,MAAM,EAAE,MAAM,wBAAwB,CAAC;AAkGrD,MAAM,WAAW,cAAc;IAC7B,IAAI,EAAE,MAAM,CAAC;IACb,IAAI,EAAE,UAAU,GAAG,OAAO,GAAG,OAAO,GAAG,OAAO,CAAC;CAChD;AAkLD,QAAA,MAAM,MAAM,EAAE,MAqLb,CAAC;eAEa,MAAM"}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../src/test-runner-gate/index.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;GA8BG;AAKH,OAAO,KAAK,EAAE,MAAM,EAAE,MAAM,
|
|
1
|
+
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../src/test-runner-gate/index.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;GA8BG;AAKH,OAAO,KAAK,EAAE,MAAM,EAAE,MAAM,wBAAwB,CAAC;AAufrD,QAAA,MAAM,MAAM,EAAE,MA+Tb,CAAC;eAEa,MAAM"}
|
package/dist/test-runner-gate.js
CHANGED
|
@@ -2,9 +2,109 @@
|
|
|
2
2
|
import { execFile } from "node:child_process";
|
|
3
3
|
import { access } from "node:fs/promises";
|
|
4
4
|
import { basename as basename2, dirname, isAbsolute as isAbsolute2, join } from "node:path";
|
|
5
|
+
import { buildWin32CmdShimInvocation as buildWin32CmdShimInvocation2, resolveWin32Command as resolveWin32Command2 } from "@wrongstack/tools/win32";
|
|
5
6
|
|
|
6
7
|
// src/runtime/index.ts
|
|
7
8
|
import { basename, extname, isAbsolute, relative, resolve } from "node:path";
|
|
9
|
+
|
|
10
|
+
// src/runtime/local-bin.ts
|
|
11
|
+
import { buildWin32CmdShimInvocation, resolveWin32Command } from "@wrongstack/tools/win32";
|
|
12
|
+
|
|
13
|
+
// src/runtime/bounded-map.ts
|
|
14
|
+
var BoundedMap = class {
|
|
15
|
+
map = /* @__PURE__ */ new Map();
|
|
16
|
+
max;
|
|
17
|
+
ttlMs;
|
|
18
|
+
now;
|
|
19
|
+
/** Entries dropped to stay under `max`. Surfaced by plugin health(). */
|
|
20
|
+
evictions = 0;
|
|
21
|
+
constructor(options) {
|
|
22
|
+
const normalizedMax = Math.floor(options.max);
|
|
23
|
+
this.max = Number.isSafeInteger(normalizedMax) ? Math.max(1, normalizedMax) : 1;
|
|
24
|
+
this.ttlMs = options.ttlMs;
|
|
25
|
+
this.now = options.now ?? Date.now;
|
|
26
|
+
}
|
|
27
|
+
expired(entry) {
|
|
28
|
+
return this.ttlMs !== void 0 && this.now() - entry.storedAt > this.ttlMs;
|
|
29
|
+
}
|
|
30
|
+
get(key) {
|
|
31
|
+
const entry = this.map.get(key);
|
|
32
|
+
if (entry === void 0) return void 0;
|
|
33
|
+
if (this.expired(entry)) {
|
|
34
|
+
this.map.delete(key);
|
|
35
|
+
return void 0;
|
|
36
|
+
}
|
|
37
|
+
this.map.delete(key);
|
|
38
|
+
this.map.set(key, entry);
|
|
39
|
+
return entry.value;
|
|
40
|
+
}
|
|
41
|
+
/**
|
|
42
|
+
* Read without promoting the key to most-recently-used. Use for
|
|
43
|
+
* diagnostics that must not perturb the eviction order.
|
|
44
|
+
*/
|
|
45
|
+
peek(key) {
|
|
46
|
+
const entry = this.map.get(key);
|
|
47
|
+
if (entry === void 0 || this.expired(entry)) return void 0;
|
|
48
|
+
return entry.value;
|
|
49
|
+
}
|
|
50
|
+
has(key) {
|
|
51
|
+
const entry = this.map.get(key);
|
|
52
|
+
if (entry === void 0) return false;
|
|
53
|
+
if (this.expired(entry)) {
|
|
54
|
+
this.map.delete(key);
|
|
55
|
+
return false;
|
|
56
|
+
}
|
|
57
|
+
return true;
|
|
58
|
+
}
|
|
59
|
+
set(key, value) {
|
|
60
|
+
this.map.delete(key);
|
|
61
|
+
this.map.set(key, { value, storedAt: this.now() });
|
|
62
|
+
while (this.map.size > this.max) {
|
|
63
|
+
const coldest = this.map.keys().next().value;
|
|
64
|
+
if (coldest === void 0) break;
|
|
65
|
+
this.map.delete(coldest);
|
|
66
|
+
this.evictions += 1;
|
|
67
|
+
}
|
|
68
|
+
return this;
|
|
69
|
+
}
|
|
70
|
+
delete(key) {
|
|
71
|
+
return this.map.delete(key);
|
|
72
|
+
}
|
|
73
|
+
clear() {
|
|
74
|
+
this.map.clear();
|
|
75
|
+
this.evictions = 0;
|
|
76
|
+
}
|
|
77
|
+
get size() {
|
|
78
|
+
return this.map.size;
|
|
79
|
+
}
|
|
80
|
+
/** How many entries have been dropped to respect `max`, since the last clear. */
|
|
81
|
+
get evictionCount() {
|
|
82
|
+
return this.evictions;
|
|
83
|
+
}
|
|
84
|
+
/** Drop every expired entry. Cheap enough to call from a status tool. */
|
|
85
|
+
prune() {
|
|
86
|
+
if (this.ttlMs === void 0) return 0;
|
|
87
|
+
let removed = 0;
|
|
88
|
+
for (const [key, entry] of this.map) {
|
|
89
|
+
if (this.expired(entry)) {
|
|
90
|
+
this.map.delete(key);
|
|
91
|
+
removed += 1;
|
|
92
|
+
}
|
|
93
|
+
}
|
|
94
|
+
return removed;
|
|
95
|
+
}
|
|
96
|
+
/** Live (non-expired) entries, coldest first. */
|
|
97
|
+
*entries() {
|
|
98
|
+
for (const [key, entry] of this.map) {
|
|
99
|
+
if (!this.expired(entry)) yield [key, entry.value];
|
|
100
|
+
}
|
|
101
|
+
}
|
|
102
|
+
[Symbol.iterator]() {
|
|
103
|
+
return this.entries();
|
|
104
|
+
}
|
|
105
|
+
};
|
|
106
|
+
|
|
107
|
+
// src/runtime/index.ts
|
|
8
108
|
var MAX_BUFFER_BYTES = 16 * 1024 * 1024;
|
|
9
109
|
function hasLeadingDash(arg) {
|
|
10
110
|
return arg.length > 0 && arg.startsWith("-");
|
|
@@ -17,10 +117,20 @@ function withinProjectPath(projectRoot, candidate) {
|
|
|
17
117
|
return rel === "" || !rel.startsWith("..") && !isAbsolute(rel);
|
|
18
118
|
}
|
|
19
119
|
function withinProject(p) {
|
|
20
|
-
|
|
120
|
+
const cwd = process.cwd();
|
|
121
|
+
return withinProjectPath(cwd, p) || relative(cwd, p) === ".";
|
|
21
122
|
}
|
|
22
123
|
|
|
23
124
|
// src/test-runner-gate/index.ts
|
|
125
|
+
function resolveExec(command, args) {
|
|
126
|
+
const resolved = resolveWin32Command2(command);
|
|
127
|
+
const needsShell = process.platform === "win32" && (resolved.endsWith(".cmd") || resolved.endsWith(".bat"));
|
|
128
|
+
if (needsShell) {
|
|
129
|
+
const shim = buildWin32CmdShimInvocation2(resolved, args);
|
|
130
|
+
return { cmd: shim.command, args: shim.args, windowsVerbatimArguments: true };
|
|
131
|
+
}
|
|
132
|
+
return { cmd: resolved, args: [...args], windowsVerbatimArguments: false };
|
|
133
|
+
}
|
|
24
134
|
var API_VERSION = "^0.1.10";
|
|
25
135
|
var state = {
|
|
26
136
|
invocationCount: 0,
|
|
@@ -85,7 +195,7 @@ function pathContentHash(content) {
|
|
|
85
195
|
}
|
|
86
196
|
return h >>> 0;
|
|
87
197
|
}
|
|
88
|
-
var lastPassedHash =
|
|
198
|
+
var lastPassedHash = new BoundedMap({ max: 1024 });
|
|
89
199
|
var ALLOWED_COMMAND_TOKENS = /* @__PURE__ */ new Set([
|
|
90
200
|
"npx",
|
|
91
201
|
"pnpm",
|
|
@@ -140,10 +250,13 @@ async function detectRunner(requested) {
|
|
|
140
250
|
if (!match) return null;
|
|
141
251
|
try {
|
|
142
252
|
await new Promise((resolve2, reject) => {
|
|
143
|
-
|
|
253
|
+
const ex = resolveExec("npx", [`${match.name}`, "--version"]);
|
|
254
|
+
execFile(ex.cmd, ex.args, {
|
|
144
255
|
encoding: "utf-8",
|
|
145
256
|
timeout: 5e3,
|
|
146
|
-
cwd: process.cwd()
|
|
257
|
+
cwd: process.cwd(),
|
|
258
|
+
windowsHide: true,
|
|
259
|
+
...ex.windowsVerbatimArguments ? { windowsVerbatimArguments: true } : {}
|
|
147
260
|
}, (err) => err ? reject(err) : resolve2());
|
|
148
261
|
});
|
|
149
262
|
return match;
|
|
@@ -154,10 +267,13 @@ async function detectRunner(requested) {
|
|
|
154
267
|
for (const candidate of candidates) {
|
|
155
268
|
try {
|
|
156
269
|
await new Promise((resolve2, reject) => {
|
|
157
|
-
|
|
270
|
+
const ex = resolveExec("npx", [`${candidate.name}`, "--version"]);
|
|
271
|
+
execFile(ex.cmd, ex.args, {
|
|
158
272
|
encoding: "utf-8",
|
|
159
273
|
timeout: 5e3,
|
|
160
|
-
cwd: process.cwd()
|
|
274
|
+
cwd: process.cwd(),
|
|
275
|
+
windowsHide: true,
|
|
276
|
+
...ex.windowsVerbatimArguments ? { windowsVerbatimArguments: true } : {}
|
|
161
277
|
}, (err) => err ? reject(err) : resolve2());
|
|
162
278
|
});
|
|
163
279
|
return candidate;
|
|
@@ -205,10 +321,17 @@ async function runTests(testFile, runner, customCommand, timeoutMs) {
|
|
|
205
321
|
try {
|
|
206
322
|
const { stdout: out } = await new Promise(
|
|
207
323
|
(resolve2, reject) => {
|
|
324
|
+
const ex = resolveExec(cmd, fullArgs);
|
|
208
325
|
execFile(
|
|
209
|
-
cmd,
|
|
210
|
-
|
|
211
|
-
{
|
|
326
|
+
ex.cmd,
|
|
327
|
+
ex.args,
|
|
328
|
+
{
|
|
329
|
+
encoding: "utf-8",
|
|
330
|
+
timeout: timeoutMs,
|
|
331
|
+
cwd: process.cwd(),
|
|
332
|
+
windowsHide: true,
|
|
333
|
+
...ex.windowsVerbatimArguments ? { windowsVerbatimArguments: true } : {}
|
|
334
|
+
},
|
|
212
335
|
(err, out2, stderr) => {
|
|
213
336
|
if (err) reject(Object.assign(err, { stdout: out2, stderr }));
|
|
214
337
|
else resolve2({ stdout: out2, stderr });
|
|
@@ -1,35 +1,4 @@
|
|
|
1
|
-
|
|
2
|
-
* todo-listener plugin — PostToolUse hook on the `todo` tool that
|
|
3
|
-
* broadcasts a structured status update to the project mailbox.
|
|
4
|
-
*
|
|
5
|
-
* When the agent (or any plugin) calls the built-in `todo` tool, the
|
|
6
|
-
* full todo list is replaced in `ctx.todos`. The hook fires after the
|
|
7
|
-
* tool completes, reads the new state, and posts a compact summary
|
|
8
|
-
* to the project mailbox so that other agents in the same project
|
|
9
|
-
* (terminals, WebUIs, shadow agents) can see what this agent is
|
|
10
|
-
* working on in real time.
|
|
11
|
-
*
|
|
12
|
-
* Use cases:
|
|
13
|
-
* - Multi-agent fleets where a coordinator should know which
|
|
14
|
-
* sub-agent is working on which item
|
|
15
|
-
* - Long-running sessions where a user opens a second terminal and
|
|
16
|
-
* wants to see the in-progress plan
|
|
17
|
-
* - Shadow agents that audit progress across the project
|
|
18
|
-
*
|
|
19
|
-
* Config (`config.extensions['todo-listener']`):
|
|
20
|
-
*
|
|
21
|
-
* ```jsonc
|
|
22
|
-
* {
|
|
23
|
-
* "enabled": false,
|
|
24
|
-
* "subjectPrefix": "todo: ",
|
|
25
|
-
* "broadcastOnChange": true,
|
|
26
|
-
* "cooldownMs": 30000
|
|
27
|
-
* }
|
|
28
|
-
* ```
|
|
29
|
-
*
|
|
30
|
-
* @public
|
|
31
|
-
*/
|
|
32
|
-
import type { Plugin } from '@wrongstack/core';
|
|
1
|
+
import type { Plugin } from '@wrongstack/core/types';
|
|
33
2
|
declare const plugin: Plugin;
|
|
34
3
|
export default plugin;
|
|
35
4
|
//# sourceMappingURL=index.d.ts.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../src/todo-listener/index.ts"],"names":[],"mappings":"
|
|
1
|
+
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../src/todo-listener/index.ts"],"names":[],"mappings":"AAiCA,OAAO,KAAK,EAAE,MAAM,EAAE,MAAM,wBAAwB,CAAC;AAoGrD,QAAA,MAAM,MAAM,EAAE,MAuNb,CAAC;eAEa,MAAM"}
|
package/dist/todo-listener.js
CHANGED
|
@@ -1,3 +1,32 @@
|
|
|
1
|
+
// src/runtime/local-bin.ts
|
|
2
|
+
import { buildWin32CmdShimInvocation, resolveWin32Command } from "@wrongstack/tools/win32";
|
|
3
|
+
|
|
4
|
+
// src/runtime/safe-json.ts
|
|
5
|
+
var UNSERIALIZABLE = "[unserializable]";
|
|
6
|
+
function safeJsonStringify(value, indent) {
|
|
7
|
+
try {
|
|
8
|
+
const stack = [];
|
|
9
|
+
const out = JSON.stringify(
|
|
10
|
+
value,
|
|
11
|
+
function replacer(_key, val) {
|
|
12
|
+
if (typeof val === "bigint") return `${val.toString()}n`;
|
|
13
|
+
if (val === null || typeof val !== "object") return val;
|
|
14
|
+
while (stack.length > 0 && stack[stack.length - 1] !== this) stack.pop();
|
|
15
|
+
if (stack.includes(val)) return "[circular]";
|
|
16
|
+
stack.push(val);
|
|
17
|
+
return val;
|
|
18
|
+
},
|
|
19
|
+
indent
|
|
20
|
+
);
|
|
21
|
+
return out ?? String(value);
|
|
22
|
+
} catch {
|
|
23
|
+
return UNSERIALIZABLE;
|
|
24
|
+
}
|
|
25
|
+
}
|
|
26
|
+
|
|
27
|
+
// src/runtime/index.ts
|
|
28
|
+
var MAX_BUFFER_BYTES = 16 * 1024 * 1024;
|
|
29
|
+
|
|
1
30
|
// src/todo-listener/index.ts
|
|
2
31
|
var state = {
|
|
3
32
|
invocationCount: 0,
|
|
@@ -112,7 +141,7 @@ var plugin = {
|
|
|
112
141
|
0,
|
|
113
142
|
200
|
|
114
143
|
);
|
|
115
|
-
const body =
|
|
144
|
+
const body = safeJsonStringify(payload, 2);
|
|
116
145
|
const sendInput = {
|
|
117
146
|
from: `plugin:todo-listener`,
|
|
118
147
|
to: "*",
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../src/todo-tracker/index.ts"],"names":[],"mappings":"AA+BA,OAAO,KAAK,EAAE,MAAM,EAAE,MAAM,
|
|
1
|
+
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../src/todo-tracker/index.ts"],"names":[],"mappings":"AA+BA,OAAO,KAAK,EAAE,MAAM,EAAE,MAAM,wBAAwB,CAAC;AAuKrD,QAAA,MAAM,MAAM,EAAE,MAsZb,CAAC;eAEa,MAAM"}
|
package/dist/todo-tracker.js
CHANGED
|
@@ -1,6 +1,7 @@
|
|
|
1
1
|
// src/todo-tracker/index.ts
|
|
2
2
|
import * as fsp from "node:fs/promises";
|
|
3
3
|
import { randomUUID } from "node:crypto";
|
|
4
|
+
import { atomicWrite, ensureDir } from "@wrongstack/core/utils";
|
|
4
5
|
function deriveFilePath(api) {
|
|
5
6
|
const raw = api.config.extensions?.["todo-tracker"];
|
|
6
7
|
const explicit = typeof raw?.["filePath"] === "string" ? raw["filePath"] : null;
|
|
@@ -30,10 +31,8 @@ async function loadFile(filePath) {
|
|
|
30
31
|
}
|
|
31
32
|
}
|
|
32
33
|
async function saveFile(filePath, file) {
|
|
33
|
-
|
|
34
|
-
await
|
|
35
|
-
await fsp.writeFile(tmp, JSON.stringify(file, null, 2), { encoding: "utf8", mode: 384 });
|
|
36
|
-
await fsp.rename(tmp, filePath);
|
|
34
|
+
await ensureDir(filePath.replace(/[/\\][^/\\]+$/, ""));
|
|
35
|
+
await atomicWrite(filePath, JSON.stringify(file, null, 2), { mode: 384 });
|
|
37
36
|
}
|
|
38
37
|
var state = {
|
|
39
38
|
filePath: null,
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../src/token-budget/index.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;GAiCG;AACH,OAAO,KAAK,EAAE,MAAM,EAAE,MAAM,
|
|
1
|
+
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../src/token-budget/index.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;GAiCG;AACH,OAAO,KAAK,EAAE,MAAM,EAAE,MAAM,wBAAwB,CAAC;AAqFrD,QAAA,MAAM,MAAM,EAAE,MA8Qb,CAAC;eAEa,MAAM"}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../src/token-throttle/index.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;GAgCG;AACH,OAAO,KAAK,EAAE,MAAM,EAAa,MAAM,
|
|
1
|
+
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../src/token-throttle/index.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;GAgCG;AACH,OAAO,KAAK,EAAE,MAAM,EAAa,MAAM,wBAAwB,CAAC;AA8ChE,MAAM,WAAW,UAAU;IACzB,EAAE,EAAE,MAAM,CAAC;IACX,MAAM,EAAE,MAAM,CAAC;CAChB;AAED,gEAAgE;AAChE,wBAAgB,WAAW,CAAC,OAAO,EAAE,UAAU,EAAE,EAAE,GAAG,EAAE,MAAM,GAAG,UAAU,EAAE,CAE5E;AAED,0CAA0C;AAC1C,wBAAgB,WAAW,CAAC,OAAO,EAAE,UAAU,EAAE,GAAG,MAAM,CAEzD;AAED;;;;;GAKG;AACH,wBAAgB,oBAAoB,CAClC,OAAO,EAAE,UAAU,EAAE,EACrB,GAAG,EAAE,MAAM,EACX,KAAK,EAAE,MAAM,EACb,SAAS,EAAE,MAAM,GAChB,MAAM,CAoBR;AAyED,QAAA,MAAM,MAAM,EAAE,MAqKb,CAAC;eAEa,MAAM"}
|