@promptci/core 0.0.1 → 0.2.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/LICENSE +201 -201
- package/README.md +29 -30
- package/dist/action-pinning.d.ts +37 -0
- package/dist/action-pinning.d.ts.map +1 -0
- package/dist/action-pinning.js +277 -0
- package/dist/action-pinning.js.map +1 -0
- package/dist/agent-practices.d.ts +3 -1
- package/dist/agent-practices.d.ts.map +1 -1
- package/dist/agent-practices.js +198 -94
- package/dist/agent-practices.js.map +1 -1
- package/dist/ai-config.d.ts +178 -0
- package/dist/ai-config.d.ts.map +1 -0
- package/dist/ai-config.js +721 -0
- package/dist/ai-config.js.map +1 -0
- package/dist/alias-files.d.ts +33 -0
- package/dist/alias-files.d.ts.map +1 -0
- package/dist/alias-files.js +60 -0
- package/dist/alias-files.js.map +1 -0
- package/dist/baseline.d.ts +17 -1
- package/dist/baseline.d.ts.map +1 -1
- package/dist/baseline.js +5 -1
- package/dist/baseline.js.map +1 -1
- package/dist/buried-critical.d.ts +17 -0
- package/dist/buried-critical.d.ts.map +1 -0
- package/dist/buried-critical.js +107 -0
- package/dist/buried-critical.js.map +1 -0
- package/dist/canonical-owner.d.ts.map +1 -1
- package/dist/canonical-owner.js +60 -30
- package/dist/canonical-owner.js.map +1 -1
- package/dist/ci-alignment.d.ts.map +1 -1
- package/dist/ci-alignment.js +3 -2
- package/dist/ci-alignment.js.map +1 -1
- package/dist/command-validity.d.ts +16 -0
- package/dist/command-validity.d.ts.map +1 -1
- package/dist/command-validity.js +387 -134
- package/dist/command-validity.js.map +1 -1
- package/dist/conflicts.d.ts.map +1 -1
- package/dist/conflicts.js +4 -44
- package/dist/conflicts.js.map +1 -1
- package/dist/context-analysis.d.ts.map +1 -1
- package/dist/context-analysis.js +13 -2
- package/dist/context-analysis.js.map +1 -1
- package/dist/context-bloat.d.ts +20 -1
- package/dist/context-bloat.d.ts.map +1 -1
- package/dist/context-bloat.js +99 -15
- package/dist/context-bloat.js.map +1 -1
- package/dist/context-optimizer.d.ts.map +1 -1
- package/dist/context-optimizer.js +18 -54
- package/dist/context-optimizer.js.map +1 -1
- package/dist/copilot-instructions-detector.d.ts +24 -0
- package/dist/copilot-instructions-detector.d.ts.map +1 -0
- package/dist/copilot-instructions-detector.js +145 -0
- package/dist/copilot-instructions-detector.js.map +1 -0
- package/dist/cursor-rules-detector.d.ts +17 -0
- package/dist/cursor-rules-detector.d.ts.map +1 -0
- package/dist/cursor-rules-detector.js +110 -0
- package/dist/cursor-rules-detector.js.map +1 -0
- package/dist/custom-rules.d.ts +52 -0
- package/dist/custom-rules.d.ts.map +1 -0
- package/dist/custom-rules.js +303 -0
- package/dist/custom-rules.js.map +1 -0
- package/dist/dead-references.d.ts +8 -2
- package/dist/dead-references.d.ts.map +1 -1
- package/dist/dead-references.js +315 -68
- package/dist/dead-references.js.map +1 -1
- package/dist/dependency-staleness.d.ts +35 -0
- package/dist/dependency-staleness.d.ts.map +1 -0
- package/dist/dependency-staleness.js +1001 -0
- package/dist/dependency-staleness.js.map +1 -0
- package/dist/detectors.d.ts +1 -3
- package/dist/detectors.d.ts.map +1 -1
- package/dist/detectors.js +74 -56
- package/dist/detectors.js.map +1 -1
- package/dist/duplicates.d.ts.map +1 -1
- package/dist/duplicates.js +15 -9
- package/dist/duplicates.js.map +1 -1
- package/dist/evidence.d.ts +39 -0
- package/dist/evidence.d.ts.map +1 -0
- package/dist/evidence.js +78 -0
- package/dist/evidence.js.map +1 -0
- package/dist/finding-id.d.ts +21 -0
- package/dist/finding-id.d.ts.map +1 -0
- package/dist/finding-id.js +31 -0
- package/dist/finding-id.js.map +1 -0
- package/dist/fix-engine.d.ts +11 -0
- package/dist/fix-engine.d.ts.map +1 -1
- package/dist/fix-engine.js +88 -71
- package/dist/fix-engine.js.map +1 -1
- package/dist/frameworks/dotnet.js +2 -2
- package/dist/frameworks/dotnet.js.map +1 -1
- package/dist/frameworks/python.d.ts.map +1 -1
- package/dist/frameworks/python.js +5 -2
- package/dist/frameworks/python.js.map +1 -1
- package/dist/frameworks/rust.d.ts.map +1 -1
- package/dist/frameworks/rust.js +2 -1
- package/dist/frameworks/rust.js.map +1 -1
- package/dist/git-symlinks.d.ts +30 -0
- package/dist/git-symlinks.d.ts.map +1 -0
- package/dist/git-symlinks.js +161 -0
- package/dist/git-symlinks.js.map +1 -0
- package/dist/gitignore.d.ts +22 -0
- package/dist/gitignore.d.ts.map +1 -0
- package/dist/gitignore.js +157 -0
- package/dist/gitignore.js.map +1 -0
- package/dist/health-score.d.ts.map +1 -1
- package/dist/health-score.js +35 -5
- package/dist/health-score.js.map +1 -1
- package/dist/hooks-settings-detector.d.ts +17 -0
- package/dist/hooks-settings-detector.d.ts.map +1 -0
- package/dist/hooks-settings-detector.js +228 -0
- package/dist/hooks-settings-detector.js.map +1 -0
- package/dist/index.d.ts +29 -8
- package/dist/index.d.ts.map +1 -1
- package/dist/index.js +21 -6
- package/dist/index.js.map +1 -1
- package/dist/makefile.d.ts +37 -0
- package/dist/makefile.d.ts.map +1 -0
- package/dist/makefile.js +156 -0
- package/dist/makefile.js.map +1 -0
- package/dist/manifest-consistency.d.ts +6 -0
- package/dist/manifest-consistency.d.ts.map +1 -1
- package/dist/manifest-consistency.js +75 -10
- package/dist/manifest-consistency.js.map +1 -1
- package/dist/markdown-fences.d.ts +112 -0
- package/dist/markdown-fences.d.ts.map +1 -0
- package/dist/markdown-fences.js +174 -0
- package/dist/markdown-fences.js.map +1 -0
- package/dist/mcp-config-detector.d.ts +20 -0
- package/dist/mcp-config-detector.d.ts.map +1 -0
- package/dist/mcp-config-detector.js +237 -0
- package/dist/mcp-config-detector.js.map +1 -0
- package/dist/missing-context.d.ts.map +1 -1
- package/dist/missing-context.js +2 -52
- package/dist/missing-context.js.map +1 -1
- package/dist/model-budgets.d.ts +69 -0
- package/dist/model-budgets.d.ts.map +1 -0
- package/dist/model-budgets.js +110 -0
- package/dist/model-budgets.js.map +1 -0
- package/dist/negative-instructions.d.ts +26 -0
- package/dist/negative-instructions.d.ts.map +1 -0
- package/dist/negative-instructions.js +169 -0
- package/dist/negative-instructions.js.map +1 -0
- package/dist/path-containment.d.ts +41 -0
- package/dist/path-containment.d.ts.map +1 -0
- package/dist/path-containment.js +123 -0
- package/dist/path-containment.js.map +1 -0
- package/dist/project-type.d.ts +12 -2
- package/dist/project-type.d.ts.map +1 -1
- package/dist/project-type.js +25 -12
- package/dist/project-type.js.map +1 -1
- package/dist/prompt-cache.d.ts.map +1 -1
- package/dist/prompt-cache.js +33 -24
- package/dist/prompt-cache.js.map +1 -1
- package/dist/promptci-gitignore.d.ts +34 -0
- package/dist/promptci-gitignore.d.ts.map +1 -0
- package/dist/promptci-gitignore.js +42 -0
- package/dist/promptci-gitignore.js.map +1 -0
- package/dist/repo-context.d.ts +80 -0
- package/dist/repo-context.d.ts.map +1 -1
- package/dist/repo-context.js +170 -16
- package/dist/repo-context.js.map +1 -1
- package/dist/report.d.ts +8 -0
- package/dist/report.d.ts.map +1 -1
- package/dist/report.js +163 -63
- package/dist/report.js.map +1 -1
- package/dist/scan.d.ts.map +1 -1
- package/dist/scan.js +47 -4
- package/dist/scan.js.map +1 -1
- package/dist/scanner.d.ts +61 -1
- package/dist/scanner.d.ts.map +1 -1
- package/dist/scanner.js +367 -70
- package/dist/scanner.js.map +1 -1
- package/dist/security-pack.d.ts +20 -0
- package/dist/security-pack.d.ts.map +1 -1
- package/dist/security-pack.js +33 -14
- package/dist/security-pack.js.map +1 -1
- package/dist/skill-supply-chain.d.ts +132 -0
- package/dist/skill-supply-chain.d.ts.map +1 -0
- package/dist/skill-supply-chain.js +2954 -0
- package/dist/skill-supply-chain.js.map +1 -0
- package/dist/skills-detector.d.ts +23 -0
- package/dist/skills-detector.d.ts.map +1 -0
- package/dist/skills-detector.js +279 -0
- package/dist/skills-detector.js.map +1 -0
- package/dist/stale-instructions.d.ts +4 -1
- package/dist/stale-instructions.d.ts.map +1 -1
- package/dist/stale-instructions.js +53 -55
- package/dist/stale-instructions.js.map +1 -1
- package/dist/subagents-detector.d.ts +19 -0
- package/dist/subagents-detector.d.ts.map +1 -0
- package/dist/subagents-detector.js +155 -0
- package/dist/subagents-detector.js.map +1 -0
- package/dist/suppression.d.ts +2 -0
- package/dist/suppression.d.ts.map +1 -1
- package/dist/suppression.js +16 -47
- package/dist/suppression.js.map +1 -1
- package/dist/types.d.ts +62 -4
- package/dist/types.d.ts.map +1 -1
- package/dist/types.js +47 -1
- package/dist/types.js.map +1 -1
- package/dist/vague-guidance.d.ts +15 -2
- package/dist/vague-guidance.d.ts.map +1 -1
- package/dist/vague-guidance.js +44 -41
- package/dist/vague-guidance.js.map +1 -1
- package/dist/windsurf-detector.d.ts +22 -0
- package/dist/windsurf-detector.d.ts.map +1 -0
- package/dist/windsurf-detector.js +96 -0
- package/dist/windsurf-detector.js.map +1 -0
- package/dist/within-section-dedup.d.ts +16 -0
- package/dist/within-section-dedup.d.ts.map +1 -0
- package/dist/within-section-dedup.js +148 -0
- package/dist/within-section-dedup.js.map +1 -0
- package/dist/workspace-manifests.d.ts +80 -0
- package/dist/workspace-manifests.d.ts.map +1 -0
- package/dist/workspace-manifests.js +333 -0
- package/dist/workspace-manifests.js.map +1 -0
- package/package.json +11 -8
- package/dist/cheap-model-routing.d.ts +0 -4
- package/dist/cheap-model-routing.d.ts.map +0 -1
- package/dist/cheap-model-routing.js +0 -43
- package/dist/cheap-model-routing.js.map +0 -1
- package/dist/cli-output-filter.d.ts +0 -16
- package/dist/cli-output-filter.d.ts.map +0 -1
- package/dist/cli-output-filter.js +0 -88
- package/dist/cli-output-filter.js.map +0 -1
- package/dist/context-cost.d.ts +0 -4
- package/dist/context-cost.d.ts.map +0 -1
- package/dist/context-cost.js +0 -70
- package/dist/context-cost.js.map +0 -1
- package/dist/context-recommender.d.ts +0 -3
- package/dist/context-recommender.d.ts.map +0 -1
- package/dist/context-recommender.js +0 -329
- package/dist/context-recommender.js.map +0 -1
- package/dist/llm.d.ts +0 -6
- package/dist/llm.d.ts.map +0 -1
- package/dist/llm.js +0 -67
- package/dist/llm.js.map +0 -1
- package/dist/mcp-detector.d.ts +0 -4
- package/dist/mcp-detector.d.ts.map +0 -1
- package/dist/mcp-detector.js +0 -131
- package/dist/mcp-detector.js.map +0 -1
- package/dist/native-tool-preference.d.ts +0 -20
- package/dist/native-tool-preference.d.ts.map +0 -1
- package/dist/native-tool-preference.js +0 -94
- package/dist/native-tool-preference.js.map +0 -1
- package/dist/output-verbosity.d.ts +0 -3
- package/dist/output-verbosity.d.ts.map +0 -1
- package/dist/output-verbosity.js +0 -83
- package/dist/output-verbosity.js.map +0 -1
- package/dist/product-boundary.d.ts +0 -11
- package/dist/product-boundary.d.ts.map +0 -1
- package/dist/product-boundary.js +0 -301
- package/dist/product-boundary.js.map +0 -1
package/dist/llm.js
DELETED
|
@@ -1,67 +0,0 @@
|
|
|
1
|
-
/**
|
|
2
|
-
* Lightweight LLM Client wrapper using Node's native fetch.
|
|
3
|
-
* Gated by OPENAI_API_KEY and ANTHROPIC_API_KEY.
|
|
4
|
-
*/
|
|
5
|
-
export async function callLlm(systemPrompt, userPrompt, responseFormatJson = false) {
|
|
6
|
-
const openaiKey = process.env.OPENAI_API_KEY;
|
|
7
|
-
const anthropicKey = process.env.ANTHROPIC_API_KEY;
|
|
8
|
-
if (!openaiKey && !anthropicKey) {
|
|
9
|
-
throw new Error('Please set OPENAI_API_KEY or ANTHROPIC_API_KEY to use this feature.');
|
|
10
|
-
}
|
|
11
|
-
const modelOverride = process.env.PROMPTCI_LLM_MODEL;
|
|
12
|
-
if (openaiKey) {
|
|
13
|
-
const model = modelOverride ?? 'gpt-4o';
|
|
14
|
-
const body = {
|
|
15
|
-
model,
|
|
16
|
-
messages: [
|
|
17
|
-
{ role: 'system', content: systemPrompt },
|
|
18
|
-
{ role: 'user', content: userPrompt }
|
|
19
|
-
],
|
|
20
|
-
};
|
|
21
|
-
if (responseFormatJson) {
|
|
22
|
-
body.response_format = { type: 'json_object' };
|
|
23
|
-
}
|
|
24
|
-
const res = await globalThis.fetch('https://api.openai.com/v1/chat/completions', {
|
|
25
|
-
method: 'POST',
|
|
26
|
-
headers: {
|
|
27
|
-
'Content-Type': 'application/json',
|
|
28
|
-
'Authorization': `Bearer ${openaiKey}`,
|
|
29
|
-
},
|
|
30
|
-
body: JSON.stringify(body),
|
|
31
|
-
});
|
|
32
|
-
if (!res.ok) {
|
|
33
|
-
const errText = await res.text();
|
|
34
|
-
throw new Error(`OpenAI API request failed (${res.status}): ${errText}`);
|
|
35
|
-
}
|
|
36
|
-
const json = await res.json();
|
|
37
|
-
return json.choices?.[0]?.message?.content || '';
|
|
38
|
-
}
|
|
39
|
-
else {
|
|
40
|
-
// Anthropic
|
|
41
|
-
const model = modelOverride ?? 'claude-3-5-sonnet-latest';
|
|
42
|
-
const body = {
|
|
43
|
-
model,
|
|
44
|
-
max_tokens: 4096,
|
|
45
|
-
system: systemPrompt,
|
|
46
|
-
messages: [
|
|
47
|
-
{ role: 'user', content: userPrompt }
|
|
48
|
-
],
|
|
49
|
-
};
|
|
50
|
-
const res = await globalThis.fetch('https://api.anthropic.com/v1/messages', {
|
|
51
|
-
method: 'POST',
|
|
52
|
-
headers: {
|
|
53
|
-
'Content-Type': 'application/json',
|
|
54
|
-
'x-api-key': anthropicKey,
|
|
55
|
-
'anthropic-version': '2023-06-01',
|
|
56
|
-
},
|
|
57
|
-
body: JSON.stringify(body),
|
|
58
|
-
});
|
|
59
|
-
if (!res.ok) {
|
|
60
|
-
const errText = await res.text();
|
|
61
|
-
throw new Error(`Anthropic API request failed (${res.status}): ${errText}`);
|
|
62
|
-
}
|
|
63
|
-
const json = await res.json();
|
|
64
|
-
return json.content?.[0]?.text || '';
|
|
65
|
-
}
|
|
66
|
-
}
|
|
67
|
-
//# sourceMappingURL=llm.js.map
|
package/dist/llm.js.map
DELETED
|
@@ -1 +0,0 @@
|
|
|
1
|
-
{"version":3,"file":"llm.js","sourceRoot":"","sources":["../src/llm.ts"],"names":[],"mappings":"AAAA;;;GAGG;AAEH,MAAM,CAAC,KAAK,UAAU,OAAO,CAC3B,YAAoB,EACpB,UAAkB,EAClB,qBAA8B,KAAK;IAEnC,MAAM,SAAS,GAAG,OAAO,CAAC,GAAG,CAAC,cAAc,CAAC;IAC7C,MAAM,YAAY,GAAG,OAAO,CAAC,GAAG,CAAC,iBAAiB,CAAC;IAEnD,IAAI,CAAC,SAAS,IAAI,CAAC,YAAY,EAAE,CAAC;QAChC,MAAM,IAAI,KAAK,CAAC,qEAAqE,CAAC,CAAC;IACzF,CAAC;IAED,MAAM,aAAa,GAAG,OAAO,CAAC,GAAG,CAAC,kBAAkB,CAAC;IAErD,IAAI,SAAS,EAAE,CAAC;QACd,MAAM,KAAK,GAAG,aAAa,IAAI,QAAQ,CAAC;QACxC,MAAM,IAAI,GAA4B;YACpC,KAAK;YACL,QAAQ,EAAE;gBACR,EAAE,IAAI,EAAE,QAAQ,EAAE,OAAO,EAAE,YAAY,EAAE;gBACzC,EAAE,IAAI,EAAE,MAAM,EAAE,OAAO,EAAE,UAAU,EAAE;aACtC;SACF,CAAC;QACF,IAAI,kBAAkB,EAAE,CAAC;YACvB,IAAI,CAAC,eAAe,GAAG,EAAE,IAAI,EAAE,aAAa,EAAE,CAAC;QACjD,CAAC;QAED,MAAM,GAAG,GAAG,MAAM,UAAU,CAAC,KAAK,CAAC,4CAA4C,EAAE;YAC/E,MAAM,EAAE,MAAM;YACd,OAAO,EAAE;gBACP,cAAc,EAAE,kBAAkB;gBAClC,eAAe,EAAE,UAAU,SAAS,EAAE;aACvC;YACD,IAAI,EAAE,IAAI,CAAC,SAAS,CAAC,IAAI,CAAC;SAC3B,CAAC,CAAC;QAEH,IAAI,CAAC,GAAG,CAAC,EAAE,EAAE,CAAC;YACZ,MAAM,OAAO,GAAG,MAAM,GAAG,CAAC,IAAI,EAAE,CAAC;YACjC,MAAM,IAAI,KAAK,CAAC,8BAA8B,GAAG,CAAC,MAAM,MAAM,OAAO,EAAE,CAAC,CAAC;QAC3E,CAAC;QAED,MAAM,IAAI,GAAG,MAAM,GAAG,CAAC,IAAI,EAM1B,CAAC;QACF,OAAO,IAAI,CAAC,OAAO,EAAE,CAAC,CAAC,CAAC,EAAE,OAAO,EAAE,OAAO,IAAI,EAAE,CAAC;IACnD,CAAC;SAAM,CAAC;QACN,YAAY;QACZ,MAAM,KAAK,GAAG,aAAa,IAAI,0BAA0B,CAAC;QAC1D,MAAM,IAAI,GAA4B;YACpC,KAAK;YACL,UAAU,EAAE,IAAI;YAChB,MAAM,EAAE,YAAY;YACpB,QAAQ,EAAE;gBACR,EAAE,IAAI,EAAE,MAAM,EAAE,OAAO,EAAE,UAAU,EAAE;aACtC;SACF,CAAC;QAEF,MAAM,GAAG,GAAG,MAAM,UAAU,CAAC,KAAK,CAAC,uCAAuC,EAAE;YAC1E,MAAM,EAAE,MAAM;YACd,OAAO,EAAE;gBACP,cAAc,EAAE,kBAAkB;gBAClC,WAAW,EAAE,YAAa;gBAC1B,mBAAmB,EAAE,YAAY;aAClC;YACD,IAAI,EAAE,IAAI,CAAC,SAAS,CAAC,IAAI,CAAC;SAC3B,CAAC,CAAC;QAEH,IAAI,CAAC,GAAG,CAAC,EAAE,EAAE,CAAC;YACZ,MAAM,OAAO,GAAG,MAAM,GAAG,CAAC,IAAI,EAAE,CAAC;YACjC,MAAM,IAAI,KAAK,CAAC,iCAAiC,GAAG,CAAC,MAAM,MAAM,OAAO,EAAE,CAAC,CAAC;QAC9E,CAAC;QAED,MAAM,IAAI,GAAG,MAAM,GAAG,CAAC,IAAI,EAK1B,CAAC;QACF,OAAO,IAAI,CAAC,OAAO,EAAE,CAAC,CAAC,CAAC,EAAE,IAAI,IAAI,EAAE,CAAC;IACvC,CAAC;AACH,CAAC"}
|
package/dist/mcp-detector.d.ts
DELETED
|
@@ -1 +0,0 @@
|
|
|
1
|
-
{"version":3,"file":"mcp-detector.d.ts","sourceRoot":"","sources":["../src/mcp-detector.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,WAAW,EAAE,MAAM,mBAAmB,CAAC;AACrD,OAAO,KAAK,EAAE,aAAa,EAAE,MAAM,YAAY,CAAC;AAyDhD,wBAAgB,gBAAgB,CAAC,OAAO,EAAE,WAAW,GAAG,aAAa,EAAE,CAmFtE"}
|
package/dist/mcp-detector.js
DELETED
|
@@ -1,131 +0,0 @@
|
|
|
1
|
-
import * as path from 'node:path';
|
|
2
|
-
import * as fs from 'node:fs';
|
|
3
|
-
import * as crypto from 'node:crypto';
|
|
4
|
-
/**
|
|
5
|
-
* B4: id was keyed by `${file.fileType}` — two files sharing a fileType (e.g.
|
|
6
|
-
* CLAUDE.md and .claude/notes.md, both 'claude') collided on the same id.
|
|
7
|
-
*/
|
|
8
|
-
function expensivePatternIssueId(expName, filePath) {
|
|
9
|
-
const hash = crypto.createHash('sha1').update(`mcp-tooling-expensive:${expName}:${filePath}`).digest('hex').slice(0, 12);
|
|
10
|
-
return `mcp-tooling-expensive-${expName.replace(/\s+/g, '-')}-${hash}`;
|
|
11
|
-
}
|
|
12
|
-
const EXPENSIVE_PATTERNS = [
|
|
13
|
-
{
|
|
14
|
-
pattern: /\bread\s+all\s+(?:docs|documentation)\b/i,
|
|
15
|
-
name: 'read all docs',
|
|
16
|
-
signal: 'docs',
|
|
17
|
-
title: 'Instructions command reading all documentation at once',
|
|
18
|
-
recommendation: 'Recommend using ripgrep (rg) to find relevant docs or linking to docs and asking the agent to open only relevant sections on-demand.',
|
|
19
|
-
fixRecipe: 'Use local search tools (like rg) to find relevant documentation instead of loading all docs at once.'
|
|
20
|
-
},
|
|
21
|
-
{
|
|
22
|
-
pattern: /\bload\s+the\s+entire\s+codebase\b/i,
|
|
23
|
-
name: 'load the entire codebase',
|
|
24
|
-
signal: 'any',
|
|
25
|
-
title: 'Instructions command loading the entire codebase',
|
|
26
|
-
recommendation: 'Recommend using search tools (like rg) or file listing tools instead of reading the entire codebase into context.',
|
|
27
|
-
fixRecipe: 'Do not read all files in the codebase. Use ripgrep or file search to locate files of interest.'
|
|
28
|
-
},
|
|
29
|
-
{
|
|
30
|
-
pattern: /\balways\s+include\s+all\s+(?:db\s+)?schema\b/i,
|
|
31
|
-
name: 'always include all schema files',
|
|
32
|
-
signal: 'database',
|
|
33
|
-
title: 'Instructions command loading all database schemas',
|
|
34
|
-
recommendation: 'Recommend querying database schemas via a database MCP server or searching for specific schema definitions on-demand.',
|
|
35
|
-
fixRecipe: 'Do not load entire database schemas. Query the specific table structures using local search or schema files on-demand.'
|
|
36
|
-
},
|
|
37
|
-
{
|
|
38
|
-
pattern: /\bpaste\s+the\s+full\s+logs\b/i,
|
|
39
|
-
name: 'paste the full logs',
|
|
40
|
-
signal: 'any',
|
|
41
|
-
title: 'Instructions command pasting full logs',
|
|
42
|
-
recommendation: 'Recommend summarizing logs or sharing only key error traces instead of pasting complete logs.',
|
|
43
|
-
fixRecipe: 'Summarize command failures and paste only the relevant error lines rather than full logs.'
|
|
44
|
-
},
|
|
45
|
-
{
|
|
46
|
-
pattern: /\bread\s+every\s+file\b/i,
|
|
47
|
-
name: 'read every file',
|
|
48
|
-
signal: 'any',
|
|
49
|
-
title: 'Instructions command reading every source file',
|
|
50
|
-
recommendation: 'Recommend using search tools or targeted file reading tools to find relevant code sections.',
|
|
51
|
-
fixRecipe: 'Use ripgrep to find target code instead of reading every file.'
|
|
52
|
-
}
|
|
53
|
-
];
|
|
54
|
-
export function detectMcpTooling(context) {
|
|
55
|
-
const issues = [];
|
|
56
|
-
const { repoRoot, files } = context;
|
|
57
|
-
if (files.length === 0) {
|
|
58
|
-
return [];
|
|
59
|
-
}
|
|
60
|
-
const hasDocsDir = fs.existsSync(path.join(repoRoot, 'docs')) || fs.existsSync(path.join(repoRoot, 'doc'));
|
|
61
|
-
const deps = {
|
|
62
|
-
...context.packageJson.dependencies,
|
|
63
|
-
...context.packageJson.devDependencies,
|
|
64
|
-
};
|
|
65
|
-
const hasSupabaseDependency = Object.keys(deps).some((name) => name.startsWith('@supabase/'));
|
|
66
|
-
const hasScannedSupabasePackage = context.files.some((f) => f.path.endsWith('package.json') && f.content.includes('@supabase/supabase-js'));
|
|
67
|
-
const hasDbDir = fs.existsSync(path.join(repoRoot, 'supabase')) ||
|
|
68
|
-
fs.existsSync(path.join(repoRoot, 'prisma')) ||
|
|
69
|
-
fs.existsSync(path.join(repoRoot, 'db')) ||
|
|
70
|
-
hasSupabaseDependency ||
|
|
71
|
-
hasScannedSupabasePackage;
|
|
72
|
-
const hasMonorepo = fs.existsSync(path.join(repoRoot, 'packages')) ||
|
|
73
|
-
fs.existsSync(path.join(repoRoot, 'apps')) ||
|
|
74
|
-
fs.existsSync(path.join(repoRoot, 'pnpm-workspace.yaml'));
|
|
75
|
-
const hasMcpConfig = fs.existsSync(path.join(repoRoot, 'mcp-config.json')) ||
|
|
76
|
-
fs.existsSync(path.join(repoRoot, '.cursor', 'mcp.json')) ||
|
|
77
|
-
fs.existsSync(path.join(repoRoot, '.claudegpt', 'mcp.json'));
|
|
78
|
-
const hasSchemas = fs.existsSync(path.join(repoRoot, 'schema.graphql')) ||
|
|
79
|
-
fs.existsSync(path.join(repoRoot, 'openapi.json')) ||
|
|
80
|
-
fs.existsSync(path.join(repoRoot, 'swagger.json')) ||
|
|
81
|
-
context.files.some(f => f.path.endsWith('schema.prisma'));
|
|
82
|
-
for (const file of files) {
|
|
83
|
-
const fileName = path.basename(file.path);
|
|
84
|
-
for (const exp of EXPENSIVE_PATTERNS) {
|
|
85
|
-
if (exp.pattern.test(file.content)) {
|
|
86
|
-
if (exp.signal === 'docs' && !hasDocsDir)
|
|
87
|
-
continue;
|
|
88
|
-
if (exp.signal === 'database' && !hasDbDir)
|
|
89
|
-
continue;
|
|
90
|
-
let recommendation = exp.recommendation;
|
|
91
|
-
let fixRecipe = exp.fixRecipe;
|
|
92
|
-
// Customise based on filesystem signals
|
|
93
|
-
if (exp.name === 'load the entire codebase' || exp.name === 'read every file') {
|
|
94
|
-
if (hasMonorepo) {
|
|
95
|
-
recommendation = 'This monorepo has multiple packages/apps. Reading or loading the entire codebase is extremely expensive. Recommend using file search (like rg), file listing tools, or a workspace MCP server instead.';
|
|
96
|
-
fixRecipe = 'Do not read all files in the codebase. Use ripgrep (rg) or a directory listing MCP to search for relevant files.';
|
|
97
|
-
}
|
|
98
|
-
else if (hasMcpConfig) {
|
|
99
|
-
recommendation = 'Recommend using your configured MCP server tools (like filesystem search) instead of instructing the agent to load or read the entire codebase.';
|
|
100
|
-
fixRecipe = 'Use filesystem search or MCP tools to read files of interest instead of loading the entire codebase.';
|
|
101
|
-
}
|
|
102
|
-
}
|
|
103
|
-
else if (exp.name === 'always include all schema files') {
|
|
104
|
-
if (hasMcpConfig) {
|
|
105
|
-
recommendation = 'Recommend querying database schemas via your configured database MCP server instead of pasting or loading schema files on-demand.';
|
|
106
|
-
fixRecipe = 'Do not load entire database schemas. Query the specific table structures using your database MCP server tools.';
|
|
107
|
-
}
|
|
108
|
-
else if (hasSchemas) {
|
|
109
|
-
recommendation = 'Recommend querying specific schema definitions or APIs on-demand instead of loading all schema files at once.';
|
|
110
|
-
fixRecipe = 'Do not load entire schema files. Use local search or file reads to view only the relevant schema files on-demand.';
|
|
111
|
-
}
|
|
112
|
-
}
|
|
113
|
-
issues.push({
|
|
114
|
-
id: expensivePatternIssueId(exp.name, file.path),
|
|
115
|
-
severity: 'warning',
|
|
116
|
-
category: 'context_bloat',
|
|
117
|
-
title: exp.title,
|
|
118
|
-
summary: `The instruction file "${fileName}" commands the agent to "${exp.name}". This encourages expensive broad context loading instead of using targeted search or MCP tools.`,
|
|
119
|
-
filePaths: [file.path],
|
|
120
|
-
locations: [],
|
|
121
|
-
evidence: [`Matched pattern: ${exp.pattern.toString()}`],
|
|
122
|
-
recommendation,
|
|
123
|
-
fixRecipe,
|
|
124
|
-
confidence: 0.8,
|
|
125
|
-
});
|
|
126
|
-
}
|
|
127
|
-
}
|
|
128
|
-
}
|
|
129
|
-
return issues;
|
|
130
|
-
}
|
|
131
|
-
//# sourceMappingURL=mcp-detector.js.map
|
package/dist/mcp-detector.js.map
DELETED
|
@@ -1 +0,0 @@
|
|
|
1
|
-
{"version":3,"file":"mcp-detector.js","sourceRoot":"","sources":["../src/mcp-detector.ts"],"names":[],"mappings":"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"}
|
|
@@ -1,20 +0,0 @@
|
|
|
1
|
-
/**
|
|
2
|
-
* Native tool preference detector for PromptCI.
|
|
3
|
-
*
|
|
4
|
-
* Checks whether Claude-targeted instruction files guide agents to prefer
|
|
5
|
-
* Claude Code's built-in tools (Read, Grep, Glob) over equivalent Bash
|
|
6
|
-
* commands (cat, grep, find).
|
|
7
|
-
*
|
|
8
|
-
* Why it matters:
|
|
9
|
-
* - Built-in tools are faster (dedicated implementation, no subprocess overhead)
|
|
10
|
-
* - They use fewer tokens — Glob returns compact path lists, Grep returns
|
|
11
|
-
* matched lines only, Read returns file content without shell noise
|
|
12
|
-
* - They bypass the PreToolUse hook entirely, so no RTK rewrite is needed
|
|
13
|
-
* - They respect Claude Code's permission model without separate Bash approval
|
|
14
|
-
*
|
|
15
|
-
* Only fires when Claude-targeted instruction files exist but contain no
|
|
16
|
-
* guidance about preferring these tools.
|
|
17
|
-
*/
|
|
18
|
-
import type { InstructionFile, PromptCiIssue } from './types.js';
|
|
19
|
-
export declare function detectNativeToolPreference(files: InstructionFile[]): PromptCiIssue[];
|
|
20
|
-
//# sourceMappingURL=native-tool-preference.d.ts.map
|
|
@@ -1 +0,0 @@
|
|
|
1
|
-
{"version":3,"file":"native-tool-preference.d.ts","sourceRoot":"","sources":["../src/native-tool-preference.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;GAgBG;AAGH,OAAO,KAAK,EAAE,eAAe,EAAE,aAAa,EAAE,MAAM,YAAY,CAAC;AAgCjE,wBAAgB,0BAA0B,CAAC,KAAK,EAAE,eAAe,EAAE,GAAG,aAAa,EAAE,CAkDpF"}
|
|
@@ -1,94 +0,0 @@
|
|
|
1
|
-
/**
|
|
2
|
-
* Native tool preference detector for PromptCI.
|
|
3
|
-
*
|
|
4
|
-
* Checks whether Claude-targeted instruction files guide agents to prefer
|
|
5
|
-
* Claude Code's built-in tools (Read, Grep, Glob) over equivalent Bash
|
|
6
|
-
* commands (cat, grep, find).
|
|
7
|
-
*
|
|
8
|
-
* Why it matters:
|
|
9
|
-
* - Built-in tools are faster (dedicated implementation, no subprocess overhead)
|
|
10
|
-
* - They use fewer tokens — Glob returns compact path lists, Grep returns
|
|
11
|
-
* matched lines only, Read returns file content without shell noise
|
|
12
|
-
* - They bypass the PreToolUse hook entirely, so no RTK rewrite is needed
|
|
13
|
-
* - They respect Claude Code's permission model without separate Bash approval
|
|
14
|
-
*
|
|
15
|
-
* Only fires when Claude-targeted instruction files exist but contain no
|
|
16
|
-
* guidance about preferring these tools.
|
|
17
|
-
*/
|
|
18
|
-
import * as path from 'node:path';
|
|
19
|
-
// Positive signals — guidance about preferring native/built-in tools already exists.
|
|
20
|
-
// Tool names (Read, Grep, Glob) are matched case-sensitively — they are always
|
|
21
|
-
// capitalized when referring to Claude Code built-ins, unlike shell commands.
|
|
22
|
-
const NATIVE_TOOL_SIGNALS = [
|
|
23
|
-
/\bRead\s+tool\b/,
|
|
24
|
-
/\bGrep\s+tool\b/,
|
|
25
|
-
/\bGlob\s+tool\b/,
|
|
26
|
-
/\b[Uu]se\s+Read\b/,
|
|
27
|
-
/\b[Uu]se\s+Grep\b/,
|
|
28
|
-
/\b[Uu]se\s+Glob\b/,
|
|
29
|
-
/\b[Pp]refer\s+Read\b/,
|
|
30
|
-
/\b[Pp]refer\s+Grep\b/,
|
|
31
|
-
/\b[Pp]refer\s+Glob\b/,
|
|
32
|
-
/\bdedicated\s+tools?\b.*\binstead\s+of\s+(cat|grep|find)\b/i,
|
|
33
|
-
/\b(avoid|instead\s+of|not)\b.*\b(cat|grep|find)\b.*\b(Read|Grep|Glob)\b/,
|
|
34
|
-
/\b(Read|Grep|Glob)\b.*\b(instead\s+of|not|avoid)\b.*\b(cat|grep|find)\b/i,
|
|
35
|
-
/built[- ]in\s+tools?\s+(over|instead\s+of|not|vs\.?)\s+(bash|shell|cat|grep|find)/i,
|
|
36
|
-
];
|
|
37
|
-
function isClaudeFile(file) {
|
|
38
|
-
const p = file.path.replace(/\\/g, '/').toLowerCase();
|
|
39
|
-
const base = path.basename(file.path).toLowerCase();
|
|
40
|
-
return (file.fileType === 'claude' ||
|
|
41
|
-
base === 'claude.md' ||
|
|
42
|
-
p.includes('/.claude/') ||
|
|
43
|
-
base === 'claude.local.md');
|
|
44
|
-
}
|
|
45
|
-
export function detectNativeToolPreference(files) {
|
|
46
|
-
const claudeFiles = files.filter(isClaudeFile);
|
|
47
|
-
if (claudeFiles.length === 0)
|
|
48
|
-
return [];
|
|
49
|
-
const combinedClaudeContent = claudeFiles.map((f) => f.content).join('\n');
|
|
50
|
-
const hasGuidance = NATIVE_TOOL_SIGNALS.some((pat) => pat.test(combinedClaudeContent));
|
|
51
|
-
if (hasGuidance)
|
|
52
|
-
return [];
|
|
53
|
-
// Also check all instruction files — guidance in AGENTS.md counts if Claude reads it.
|
|
54
|
-
const combinedAll = files.map((f) => f.content).join('\n');
|
|
55
|
-
const hasGuidanceAnywhere = NATIVE_TOOL_SIGNALS.some((pat) => pat.test(combinedAll));
|
|
56
|
-
if (hasGuidanceAnywhere)
|
|
57
|
-
return [];
|
|
58
|
-
return [
|
|
59
|
-
{
|
|
60
|
-
id: 'native-tool-preference-missing',
|
|
61
|
-
severity: 'info',
|
|
62
|
-
category: 'agent_practices',
|
|
63
|
-
title: 'No guidance to prefer built-in tools over Bash equivalents (Claude Code)',
|
|
64
|
-
summary: "Claude Code's built-in Read, Grep, and Glob tools are faster and more token-efficient " +
|
|
65
|
-
'than their Bash equivalents (cat/head/tail, grep/rg, find). Instructions that explicitly ' +
|
|
66
|
-
'prefer these tools reduce context noise and bypass the Bash permission prompt entirely. ' +
|
|
67
|
-
'No such guidance was found in Claude-targeted instruction files.',
|
|
68
|
-
filePaths: claudeFiles.map((f) => f.path),
|
|
69
|
-
locations: [],
|
|
70
|
-
evidence: [
|
|
71
|
-
`No Read/Grep/Glob preference guidance found in: ${claudeFiles.map((f) => path.basename(f.path)).join(', ')}.`,
|
|
72
|
-
],
|
|
73
|
-
recommendation: 'Add a rule to Claude-targeted files instructing agents to prefer Read over cat/head/tail, ' +
|
|
74
|
-
'Grep over grep/rg, and Glob over find when working with local files. Reserve Bash for ' +
|
|
75
|
-
'operations that have no dedicated tool (e.g. git commands, running tests).',
|
|
76
|
-
fixRecipe: [
|
|
77
|
-
'## Tool Selection (Claude Code)',
|
|
78
|
-
'',
|
|
79
|
-
'Prefer dedicated tools over Bash for file operations — they are faster, more token-efficient,',
|
|
80
|
-
'and bypass the Bash permission prompt:',
|
|
81
|
-
'',
|
|
82
|
-
'- **File search**: Use `Glob` (not `find` or `ls`)',
|
|
83
|
-
'- **Content search**: Use `Grep` (not `grep` or `rg`)',
|
|
84
|
-
'- **Read files**: Use `Read` (not `cat`/`head`/`tail`)',
|
|
85
|
-
'',
|
|
86
|
-
'Reserve Bash for operations without a dedicated tool: git commands, running builds/tests,',
|
|
87
|
-
'package manager commands, and other shell-only operations.',
|
|
88
|
-
].join('\n'),
|
|
89
|
-
confidence: 0.7,
|
|
90
|
-
impact: 'medium',
|
|
91
|
-
},
|
|
92
|
-
];
|
|
93
|
-
}
|
|
94
|
-
//# sourceMappingURL=native-tool-preference.js.map
|
|
@@ -1 +0,0 @@
|
|
|
1
|
-
{"version":3,"file":"native-tool-preference.js","sourceRoot":"","sources":["../src/native-tool-preference.ts"],"names":[],"mappings":"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"}
|
|
@@ -1 +0,0 @@
|
|
|
1
|
-
{"version":3,"file":"output-verbosity.d.ts","sourceRoot":"","sources":["../src/output-verbosity.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,eAAe,EAAE,aAAa,EAAE,MAAM,YAAY,CAAC;AAiCjE,wBAAgB,qBAAqB,CAAC,KAAK,EAAE,eAAe,EAAE,GAAG,aAAa,EAAE,CA8D/E"}
|
package/dist/output-verbosity.js
DELETED
|
@@ -1,83 +0,0 @@
|
|
|
1
|
-
import * as path from 'node:path';
|
|
2
|
-
import * as crypto from 'node:crypto';
|
|
3
|
-
/**
|
|
4
|
-
* B4: id was keyed by `${file.fileType}` — two files sharing a fileType (e.g.
|
|
5
|
-
* CLAUDE.md and .claude/notes.md, both 'claude') collided on the same id.
|
|
6
|
-
*/
|
|
7
|
-
function verbosityEncouragedIssueId(filePath) {
|
|
8
|
-
const hash = crypto.createHash('sha1').update(`cost-verbosity-encouraged:${filePath}`).digest('hex').slice(0, 12);
|
|
9
|
-
return `cost-verbosity-encouraged-${hash}`;
|
|
10
|
-
}
|
|
11
|
-
const VERBOSITY_ENCOURAGED_PATTERNS = [
|
|
12
|
-
/explain\s+everything\s+in\s+detail/i,
|
|
13
|
-
/explain\s+in\s+detail/i,
|
|
14
|
-
/always\s+include\s+full\s+command\s+output/i,
|
|
15
|
-
/provide\s+exhaustive\s+summaries/i,
|
|
16
|
-
/print\s+the\s+entire\s+report/i,
|
|
17
|
-
/include\s+all\s+logs/i,
|
|
18
|
-
/\b(?:provide|include|write|give)\s+(?:a\s+)?detailed\s+explanation\b/i,
|
|
19
|
-
];
|
|
20
|
-
const CONCISENESS_PATTERNS = [
|
|
21
|
-
/summarize\s+command/i,
|
|
22
|
-
/do\s+not\s+paste\s+(?:full\s+)?logs/i,
|
|
23
|
-
/keep\s+final\s+answers\s+concise/i,
|
|
24
|
-
/be\s+concise/i,
|
|
25
|
-
/brief\s+summary/i,
|
|
26
|
-
/only\s+key\s+failures/i,
|
|
27
|
-
/use\s+links\s+to\s+generated\s+artifacts/i,
|
|
28
|
-
];
|
|
29
|
-
export function detectOutputVerbosity(files) {
|
|
30
|
-
const issues = [];
|
|
31
|
-
const targetFiles = files.filter((f) => ['claude', 'agents', 'cursor', 'copilot', 'prompt'].includes(f.fileType));
|
|
32
|
-
if (targetFiles.length === 0) {
|
|
33
|
-
return [];
|
|
34
|
-
}
|
|
35
|
-
const combinedContent = targetFiles.map((f) => f.content).join('\n');
|
|
36
|
-
// 1. Check for verbosity encouraged (e.g. demanding full logs, verbose explanations)
|
|
37
|
-
for (const file of targetFiles) {
|
|
38
|
-
const fileName = path.basename(file.path);
|
|
39
|
-
const lines = file.content.split(/\r?\n/);
|
|
40
|
-
for (const line of lines) {
|
|
41
|
-
const matchesVerbosity = VERBOSITY_ENCOURAGED_PATTERNS.some((pat) => pat.test(line));
|
|
42
|
-
if (matchesVerbosity) {
|
|
43
|
-
// Exclude conditional debugging rules (e.g., "include logs when failing")
|
|
44
|
-
const isConditional = /fail|error|debug|crash|when\s+failing/i.test(line);
|
|
45
|
-
if (!isConditional) {
|
|
46
|
-
issues.push({
|
|
47
|
-
id: verbosityEncouragedIssueId(file.path),
|
|
48
|
-
severity: 'warning',
|
|
49
|
-
category: 'agent_practices',
|
|
50
|
-
title: 'Verbose output behavior encouraged',
|
|
51
|
-
summary: `The instruction file "${fileName}" encourages the agent to produce overly verbose outputs or print excessive logs, increasing output-token costs.`,
|
|
52
|
-
filePaths: [file.path],
|
|
53
|
-
locations: [],
|
|
54
|
-
evidence: [`Matched verbose instruction line: "${line.trim()}"`],
|
|
55
|
-
recommendation: 'Encourage concise status updates and final answers to reduce output token cost. Summarize logs and command results instead of pasting them in full.',
|
|
56
|
-
fixRecipe: 'Replace verbosity demands with instructions like: "Be concise and summarize results, linking to files instead of printing them in full."',
|
|
57
|
-
confidence: 0.85,
|
|
58
|
-
});
|
|
59
|
-
break; // one issue per file is enough
|
|
60
|
-
}
|
|
61
|
-
}
|
|
62
|
-
}
|
|
63
|
-
}
|
|
64
|
-
// 2. Check for missing conciseness guidelines
|
|
65
|
-
const hasConcisenessGuidelines = CONCISENESS_PATTERNS.some((pat) => pat.test(combinedContent));
|
|
66
|
-
if (!hasConcisenessGuidelines) {
|
|
67
|
-
issues.push({
|
|
68
|
-
id: 'cost-missing-verbosity-discipline',
|
|
69
|
-
severity: 'info',
|
|
70
|
-
category: 'agent_practices',
|
|
71
|
-
title: 'Missing output verbosity discipline',
|
|
72
|
-
summary: 'No conciseness or verbosity discipline guidelines found in instruction files. Verbose agents write redundant code dumps and explanations, bloating output tokens.',
|
|
73
|
-
filePaths: targetFiles.map((f) => f.path),
|
|
74
|
-
locations: [],
|
|
75
|
-
evidence: ['No guidelines found encouraging conciseness, log summarization, or artifact linking.'],
|
|
76
|
-
recommendation: 'Add guidance to keep answers concise, summarize command output, and link to files instead of pasting large content.',
|
|
77
|
-
fixRecipe: 'Add a section: "Summarize command results. Do not paste full logs unless requested. Keep final answers concise."',
|
|
78
|
-
confidence: 0.8,
|
|
79
|
-
});
|
|
80
|
-
}
|
|
81
|
-
return issues;
|
|
82
|
-
}
|
|
83
|
-
//# sourceMappingURL=output-verbosity.js.map
|
|
@@ -1 +0,0 @@
|
|
|
1
|
-
{"version":3,"file":"output-verbosity.js","sourceRoot":"","sources":["../src/output-verbosity.ts"],"names":[],"mappings":"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"}
|
|
@@ -1,11 +0,0 @@
|
|
|
1
|
-
import type { RepoContext } from './repo-context.js';
|
|
2
|
-
import type { PromptCiIssue } from './types.js';
|
|
3
|
-
/**
|
|
4
|
-
* Detects stale product-boundary instructions that contradict filesystem
|
|
5
|
-
* evidence of a feature already existing in the repo.
|
|
6
|
-
*
|
|
7
|
-
* One finding is emitted per (capability × file) regardless of how many
|
|
8
|
-
* contradictory patterns match in that file, to keep the report actionable.
|
|
9
|
-
*/
|
|
10
|
-
export declare function detectProductBoundary(context: RepoContext): PromptCiIssue[];
|
|
11
|
-
//# sourceMappingURL=product-boundary.d.ts.map
|
|
@@ -1 +0,0 @@
|
|
|
1
|
-
{"version":3,"file":"product-boundary.d.ts","sourceRoot":"","sources":["../src/product-boundary.ts"],"names":[],"mappings":"AAGA,OAAO,KAAK,EAAE,WAAW,EAAE,MAAM,mBAAmB,CAAC;AACrD,OAAO,KAAK,EAAE,aAAa,EAAE,MAAM,YAAY,CAAC;AAmUhD;;;;;;GAMG;AACH,wBAAgB,qBAAqB,CAAC,OAAO,EAAE,WAAW,GAAG,aAAa,EAAE,CAqC3E"}
|