codeprobe 0.1.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 +21 -0
- package/README.md +406 -0
- package/dist/cli.d.ts +7 -0
- package/dist/cli.d.ts.map +1 -0
- package/dist/cli.js +104 -0
- package/dist/cli.js.map +1 -0
- package/dist/commands/ab.d.ts +7 -0
- package/dist/commands/ab.d.ts.map +1 -0
- package/dist/commands/ab.js +230 -0
- package/dist/commands/ab.js.map +1 -0
- package/dist/commands/agents.d.ts +10 -0
- package/dist/commands/agents.d.ts.map +1 -0
- package/dist/commands/agents.js +326 -0
- package/dist/commands/agents.js.map +1 -0
- package/dist/commands/autotest.d.ts +10 -0
- package/dist/commands/autotest.d.ts.map +1 -0
- package/dist/commands/autotest.js +408 -0
- package/dist/commands/autotest.js.map +1 -0
- package/dist/commands/benchmark.d.ts +6 -0
- package/dist/commands/benchmark.d.ts.map +1 -0
- package/dist/commands/benchmark.js +215 -0
- package/dist/commands/benchmark.js.map +1 -0
- package/dist/commands/check.d.ts +10 -0
- package/dist/commands/check.d.ts.map +1 -0
- package/dist/commands/check.js +333 -0
- package/dist/commands/check.js.map +1 -0
- package/dist/commands/context.d.ts +16 -0
- package/dist/commands/context.d.ts.map +1 -0
- package/dist/commands/context.js +219 -0
- package/dist/commands/context.js.map +1 -0
- package/dist/commands/cost.d.ts +9 -0
- package/dist/commands/cost.d.ts.map +1 -0
- package/dist/commands/cost.js +142 -0
- package/dist/commands/cost.js.map +1 -0
- package/dist/commands/dashboard.d.ts +10 -0
- package/dist/commands/dashboard.d.ts.map +1 -0
- package/dist/commands/dashboard.js +462 -0
- package/dist/commands/dashboard.js.map +1 -0
- package/dist/commands/diff.d.ts +6 -0
- package/dist/commands/diff.d.ts.map +1 -0
- package/dist/commands/diff.js +118 -0
- package/dist/commands/diff.js.map +1 -0
- package/dist/commands/doctor.d.ts +12 -0
- package/dist/commands/doctor.d.ts.map +1 -0
- package/dist/commands/doctor.js +203 -0
- package/dist/commands/doctor.js.map +1 -0
- package/dist/commands/explain.d.ts +7 -0
- package/dist/commands/explain.d.ts.map +1 -0
- package/dist/commands/explain.js +164 -0
- package/dist/commands/explain.js.map +1 -0
- package/dist/commands/flaky.d.ts +10 -0
- package/dist/commands/flaky.d.ts.map +1 -0
- package/dist/commands/flaky.js +141 -0
- package/dist/commands/flaky.js.map +1 -0
- package/dist/commands/generateClaudeMd.d.ts +11 -0
- package/dist/commands/generateClaudeMd.d.ts.map +1 -0
- package/dist/commands/generateClaudeMd.js +278 -0
- package/dist/commands/generateClaudeMd.js.map +1 -0
- package/dist/commands/generateRules.d.ts +11 -0
- package/dist/commands/generateRules.d.ts.map +1 -0
- package/dist/commands/generateRules.js +413 -0
- package/dist/commands/generateRules.js.map +1 -0
- package/dist/commands/heatmap.d.ts +7 -0
- package/dist/commands/heatmap.d.ts.map +1 -0
- package/dist/commands/heatmap.js +117 -0
- package/dist/commands/heatmap.js.map +1 -0
- package/dist/commands/history.d.ts +13 -0
- package/dist/commands/history.d.ts.map +1 -0
- package/dist/commands/history.js +113 -0
- package/dist/commands/history.js.map +1 -0
- package/dist/commands/hooks.d.ts +9 -0
- package/dist/commands/hooks.d.ts.map +1 -0
- package/dist/commands/hooks.js +199 -0
- package/dist/commands/hooks.js.map +1 -0
- package/dist/commands/improve.d.ts +7 -0
- package/dist/commands/improve.d.ts.map +1 -0
- package/dist/commands/improve.js +192 -0
- package/dist/commands/improve.js.map +1 -0
- package/dist/commands/init.d.ts +9 -0
- package/dist/commands/init.d.ts.map +1 -0
- package/dist/commands/init.js +270 -0
- package/dist/commands/init.js.map +1 -0
- package/dist/commands/installHook.d.ts +9 -0
- package/dist/commands/installHook.d.ts.map +1 -0
- package/dist/commands/installHook.js +78 -0
- package/dist/commands/installHook.js.map +1 -0
- package/dist/commands/lint.d.ts +6 -0
- package/dist/commands/lint.d.ts.map +1 -0
- package/dist/commands/lint.js +237 -0
- package/dist/commands/lint.js.map +1 -0
- package/dist/commands/map.d.ts +9 -0
- package/dist/commands/map.d.ts.map +1 -0
- package/dist/commands/map.js +114 -0
- package/dist/commands/map.js.map +1 -0
- package/dist/commands/mcp.d.ts +6 -0
- package/dist/commands/mcp.d.ts.map +1 -0
- package/dist/commands/mcp.js +151 -0
- package/dist/commands/mcp.js.map +1 -0
- package/dist/commands/models.d.ts +9 -0
- package/dist/commands/models.d.ts.map +1 -0
- package/dist/commands/models.js +89 -0
- package/dist/commands/models.js.map +1 -0
- package/dist/commands/pack.d.ts +10 -0
- package/dist/commands/pack.d.ts.map +1 -0
- package/dist/commands/pack.js +248 -0
- package/dist/commands/pack.js.map +1 -0
- package/dist/commands/recommend.d.ts +10 -0
- package/dist/commands/recommend.d.ts.map +1 -0
- package/dist/commands/recommend.js +472 -0
- package/dist/commands/recommend.js.map +1 -0
- package/dist/commands/regression.d.ts +10 -0
- package/dist/commands/regression.d.ts.map +1 -0
- package/dist/commands/regression.js +212 -0
- package/dist/commands/regression.js.map +1 -0
- package/dist/commands/repl.d.ts +9 -0
- package/dist/commands/repl.d.ts.map +1 -0
- package/dist/commands/repl.js +245 -0
- package/dist/commands/repl.js.map +1 -0
- package/dist/commands/scan.d.ts +10 -0
- package/dist/commands/scan.d.ts.map +1 -0
- package/dist/commands/scan.js +352 -0
- package/dist/commands/scan.js.map +1 -0
- package/dist/commands/score.d.ts +10 -0
- package/dist/commands/score.d.ts.map +1 -0
- package/dist/commands/score.js +192 -0
- package/dist/commands/score.js.map +1 -0
- package/dist/commands/security.d.ts +10 -0
- package/dist/commands/security.d.ts.map +1 -0
- package/dist/commands/security.js +211 -0
- package/dist/commands/security.js.map +1 -0
- package/dist/commands/simulate.d.ts +7 -0
- package/dist/commands/simulate.d.ts.map +1 -0
- package/dist/commands/simulate.js +149 -0
- package/dist/commands/simulate.js.map +1 -0
- package/dist/commands/summary.d.ts +9 -0
- package/dist/commands/summary.d.ts.map +1 -0
- package/dist/commands/summary.js +271 -0
- package/dist/commands/summary.js.map +1 -0
- package/dist/commands/test.d.ts +9 -0
- package/dist/commands/test.d.ts.map +1 -0
- package/dist/commands/test.js +219 -0
- package/dist/commands/test.js.map +1 -0
- package/dist/commands/ui.d.ts +8 -0
- package/dist/commands/ui.d.ts.map +1 -0
- package/dist/commands/ui.js +222 -0
- package/dist/commands/ui.js.map +1 -0
- package/dist/commands/validate.d.ts +7 -0
- package/dist/commands/validate.d.ts.map +1 -0
- package/dist/commands/validate.js +254 -0
- package/dist/commands/validate.js.map +1 -0
- package/dist/commands/workflow.d.ts +39 -0
- package/dist/commands/workflow.d.ts.map +1 -0
- package/dist/commands/workflow.js +309 -0
- package/dist/commands/workflow.js.map +1 -0
- package/dist/core/__tests__/contextAnalyzer.test.d.ts +2 -0
- package/dist/core/__tests__/contextAnalyzer.test.d.ts.map +1 -0
- package/dist/core/__tests__/contextAnalyzer.test.js +48 -0
- package/dist/core/__tests__/contextAnalyzer.test.js.map +1 -0
- package/dist/core/__tests__/promptLinter.test.d.ts +2 -0
- package/dist/core/__tests__/promptLinter.test.d.ts.map +1 -0
- package/dist/core/__tests__/promptLinter.test.js +74 -0
- package/dist/core/__tests__/promptLinter.test.js.map +1 -0
- package/dist/core/__tests__/promptRunner.test.d.ts +2 -0
- package/dist/core/__tests__/promptRunner.test.d.ts.map +1 -0
- package/dist/core/__tests__/promptRunner.test.js +84 -0
- package/dist/core/__tests__/promptRunner.test.js.map +1 -0
- package/dist/core/__tests__/securityScanner.test.d.ts +2 -0
- package/dist/core/__tests__/securityScanner.test.d.ts.map +1 -0
- package/dist/core/__tests__/securityScanner.test.js +39 -0
- package/dist/core/__tests__/securityScanner.test.js.map +1 -0
- package/dist/core/agentTracer.d.ts +21 -0
- package/dist/core/agentTracer.d.ts.map +1 -0
- package/dist/core/agentTracer.js +355 -0
- package/dist/core/agentTracer.js.map +1 -0
- package/dist/core/anthropicClient.d.ts +26 -0
- package/dist/core/anthropicClient.d.ts.map +1 -0
- package/dist/core/anthropicClient.js +62 -0
- package/dist/core/anthropicClient.js.map +1 -0
- package/dist/core/benchmarkRunner.d.ts +25 -0
- package/dist/core/benchmarkRunner.d.ts.map +1 -0
- package/dist/core/benchmarkRunner.js +182 -0
- package/dist/core/benchmarkRunner.js.map +1 -0
- package/dist/core/contextAnalyzer.d.ts +19 -0
- package/dist/core/contextAnalyzer.d.ts.map +1 -0
- package/dist/core/contextAnalyzer.js +221 -0
- package/dist/core/contextAnalyzer.js.map +1 -0
- package/dist/core/contextPacker.d.ts +26 -0
- package/dist/core/contextPacker.d.ts.map +1 -0
- package/dist/core/contextPacker.js +358 -0
- package/dist/core/contextPacker.js.map +1 -0
- package/dist/core/datasetRunner.d.ts +10 -0
- package/dist/core/datasetRunner.d.ts.map +1 -0
- package/dist/core/datasetRunner.js +130 -0
- package/dist/core/datasetRunner.js.map +1 -0
- package/dist/core/doctorRunner.d.ts +24 -0
- package/dist/core/doctorRunner.d.ts.map +1 -0
- package/dist/core/doctorRunner.js +278 -0
- package/dist/core/doctorRunner.js.map +1 -0
- package/dist/core/hookScanner.d.ts +24 -0
- package/dist/core/hookScanner.d.ts.map +1 -0
- package/dist/core/hookScanner.js +226 -0
- package/dist/core/hookScanner.js.map +1 -0
- package/dist/core/mcpScanner.d.ts +22 -0
- package/dist/core/mcpScanner.d.ts.map +1 -0
- package/dist/core/mcpScanner.js +290 -0
- package/dist/core/mcpScanner.js.map +1 -0
- package/dist/core/modelRegistry.d.ts +35 -0
- package/dist/core/modelRegistry.d.ts.map +1 -0
- package/dist/core/modelRegistry.js +97 -0
- package/dist/core/modelRegistry.js.map +1 -0
- package/dist/core/promptDiff.d.ts +25 -0
- package/dist/core/promptDiff.d.ts.map +1 -0
- package/dist/core/promptDiff.js +130 -0
- package/dist/core/promptDiff.js.map +1 -0
- package/dist/core/promptExplainer.d.ts +17 -0
- package/dist/core/promptExplainer.d.ts.map +1 -0
- package/dist/core/promptExplainer.js +334 -0
- package/dist/core/promptExplainer.js.map +1 -0
- package/dist/core/promptImprover.d.ts +19 -0
- package/dist/core/promptImprover.d.ts.map +1 -0
- package/dist/core/promptImprover.js +260 -0
- package/dist/core/promptImprover.js.map +1 -0
- package/dist/core/promptLinter.d.ts +24 -0
- package/dist/core/promptLinter.d.ts.map +1 -0
- package/dist/core/promptLinter.js +319 -0
- package/dist/core/promptLinter.js.map +1 -0
- package/dist/core/promptRunner.d.ts +31 -0
- package/dist/core/promptRunner.d.ts.map +1 -0
- package/dist/core/promptRunner.js +427 -0
- package/dist/core/promptRunner.js.map +1 -0
- package/dist/core/providers/anthropic.d.ts +10 -0
- package/dist/core/providers/anthropic.d.ts.map +1 -0
- package/dist/core/providers/anthropic.js +26 -0
- package/dist/core/providers/anthropic.js.map +1 -0
- package/dist/core/providers/base.d.ts +22 -0
- package/dist/core/providers/base.d.ts.map +1 -0
- package/dist/core/providers/base.js +2 -0
- package/dist/core/providers/base.js.map +1 -0
- package/dist/core/providers/factory.d.ts +7 -0
- package/dist/core/providers/factory.d.ts.map +1 -0
- package/dist/core/providers/factory.js +42 -0
- package/dist/core/providers/factory.js.map +1 -0
- package/dist/core/providers/google.d.ts +10 -0
- package/dist/core/providers/google.d.ts.map +1 -0
- package/dist/core/providers/google.js +47 -0
- package/dist/core/providers/google.js.map +1 -0
- package/dist/core/providers/openai.d.ts +19 -0
- package/dist/core/providers/openai.d.ts.map +1 -0
- package/dist/core/providers/openai.js +54 -0
- package/dist/core/providers/openai.js.map +1 -0
- package/dist/core/regressionRunner.d.ts +11 -0
- package/dist/core/regressionRunner.d.ts.map +1 -0
- package/dist/core/regressionRunner.js +116 -0
- package/dist/core/regressionRunner.js.map +1 -0
- package/dist/core/repositorySimulator.d.ts +17 -0
- package/dist/core/repositorySimulator.d.ts.map +1 -0
- package/dist/core/repositorySimulator.js +104 -0
- package/dist/core/repositorySimulator.js.map +1 -0
- package/dist/core/scorer.d.ts +30 -0
- package/dist/core/scorer.d.ts.map +1 -0
- package/dist/core/scorer.js +317 -0
- package/dist/core/scorer.js.map +1 -0
- package/dist/core/securityScanner.d.ts +23 -0
- package/dist/core/securityScanner.d.ts.map +1 -0
- package/dist/core/securityScanner.js +216 -0
- package/dist/core/securityScanner.js.map +1 -0
- package/dist/core/skillValidator.d.ts +41 -0
- package/dist/core/skillValidator.d.ts.map +1 -0
- package/dist/core/skillValidator.js +235 -0
- package/dist/core/skillValidator.js.map +1 -0
- package/dist/core/testHistory.d.ts +44 -0
- package/dist/core/testHistory.d.ts.map +1 -0
- package/dist/core/testHistory.js +91 -0
- package/dist/core/testHistory.js.map +1 -0
- package/dist/tokenizers/claudeTokenizer.d.ts +26 -0
- package/dist/tokenizers/claudeTokenizer.d.ts.map +1 -0
- package/dist/tokenizers/claudeTokenizer.js +83 -0
- package/dist/tokenizers/claudeTokenizer.js.map +1 -0
- package/dist/types/agent.d.ts +26 -0
- package/dist/types/agent.d.ts.map +1 -0
- package/dist/types/agent.js +5 -0
- package/dist/types/agent.js.map +1 -0
- package/dist/types/config.d.ts +30 -0
- package/dist/types/config.d.ts.map +1 -0
- package/dist/types/config.js +5 -0
- package/dist/types/config.js.map +1 -0
- package/dist/types/context.d.ts +77 -0
- package/dist/types/context.d.ts.map +1 -0
- package/dist/types/context.js +5 -0
- package/dist/types/context.js.map +1 -0
- package/dist/types/dataset.d.ts +26 -0
- package/dist/types/dataset.d.ts.map +1 -0
- package/dist/types/dataset.js +5 -0
- package/dist/types/dataset.js.map +1 -0
- package/dist/types/diagnostics.d.ts +31 -0
- package/dist/types/diagnostics.d.ts.map +1 -0
- package/dist/types/diagnostics.js +5 -0
- package/dist/types/diagnostics.js.map +1 -0
- package/dist/types/prompt.d.ts +53 -0
- package/dist/types/prompt.d.ts.map +1 -0
- package/dist/types/prompt.js +5 -0
- package/dist/types/prompt.js.map +1 -0
- package/dist/types/results.d.ts +42 -0
- package/dist/types/results.d.ts.map +1 -0
- package/dist/types/results.js +5 -0
- package/dist/types/results.js.map +1 -0
- package/dist/ui/dashboard.d.ts +57 -0
- package/dist/ui/dashboard.d.ts.map +1 -0
- package/dist/ui/dashboard.js +644 -0
- package/dist/ui/dashboard.js.map +1 -0
- package/dist/utils/__tests__/hashing.test.d.ts +2 -0
- package/dist/utils/__tests__/hashing.test.d.ts.map +1 -0
- package/dist/utils/__tests__/hashing.test.js +28 -0
- package/dist/utils/__tests__/hashing.test.js.map +1 -0
- package/dist/utils/__tests__/output.test.d.ts +2 -0
- package/dist/utils/__tests__/output.test.d.ts.map +1 -0
- package/dist/utils/__tests__/output.test.js +62 -0
- package/dist/utils/__tests__/output.test.js.map +1 -0
- package/dist/utils/cache.d.ts +29 -0
- package/dist/utils/cache.d.ts.map +1 -0
- package/dist/utils/cache.js +87 -0
- package/dist/utils/cache.js.map +1 -0
- package/dist/utils/config.d.ts +15 -0
- package/dist/utils/config.d.ts.map +1 -0
- package/dist/utils/config.js +61 -0
- package/dist/utils/config.js.map +1 -0
- package/dist/utils/errors.d.ts +43 -0
- package/dist/utils/errors.d.ts.map +1 -0
- package/dist/utils/errors.js +83 -0
- package/dist/utils/errors.js.map +1 -0
- package/dist/utils/fs.d.ts +44 -0
- package/dist/utils/fs.d.ts.map +1 -0
- package/dist/utils/fs.js +119 -0
- package/dist/utils/fs.js.map +1 -0
- package/dist/utils/hashing.d.ts +13 -0
- package/dist/utils/hashing.d.ts.map +1 -0
- package/dist/utils/hashing.js +18 -0
- package/dist/utils/hashing.js.map +1 -0
- package/dist/utils/logger.d.ts +32 -0
- package/dist/utils/logger.d.ts.map +1 -0
- package/dist/utils/logger.js +76 -0
- package/dist/utils/logger.js.map +1 -0
- package/dist/utils/output.d.ts +34 -0
- package/dist/utils/output.d.ts.map +1 -0
- package/dist/utils/output.js +99 -0
- package/dist/utils/output.js.map +1 -0
- package/dist/utils/paths.d.ts +33 -0
- package/dist/utils/paths.d.ts.map +1 -0
- package/dist/utils/paths.js +51 -0
- package/dist/utils/paths.js.map +1 -0
- package/dist/utils/spinner.d.ts +23 -0
- package/dist/utils/spinner.d.ts.map +1 -0
- package/dist/utils/spinner.js +79 -0
- package/dist/utils/spinner.js.map +1 -0
- package/package.json +60 -0
|
@@ -0,0 +1,334 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Prompt explainer: offline analysis of a prompt spec.
|
|
3
|
+
*
|
|
4
|
+
* Generates a plain-text explanation of what a prompt does,
|
|
5
|
+
* identifies potential weaknesses, and suggests improvements --
|
|
6
|
+
* all without making any LLM calls.
|
|
7
|
+
*/
|
|
8
|
+
import { readFile } from 'node:fs/promises';
|
|
9
|
+
import yaml from 'js-yaml';
|
|
10
|
+
/**
|
|
11
|
+
* Rough token estimation: ~4 characters per token.
|
|
12
|
+
*/
|
|
13
|
+
function estimateTokenCount(text) {
|
|
14
|
+
if (!text)
|
|
15
|
+
return 0;
|
|
16
|
+
return Math.ceil(text.length / 4);
|
|
17
|
+
}
|
|
18
|
+
/**
|
|
19
|
+
* Parse a YAML file into a PromptSpec. Returns null on failure.
|
|
20
|
+
*/
|
|
21
|
+
async function parseSpec(specPath) {
|
|
22
|
+
let content;
|
|
23
|
+
try {
|
|
24
|
+
content = await readFile(specPath, 'utf-8');
|
|
25
|
+
}
|
|
26
|
+
catch {
|
|
27
|
+
return null;
|
|
28
|
+
}
|
|
29
|
+
let parsed;
|
|
30
|
+
try {
|
|
31
|
+
parsed = yaml.load(content);
|
|
32
|
+
}
|
|
33
|
+
catch {
|
|
34
|
+
return null;
|
|
35
|
+
}
|
|
36
|
+
if (parsed === null || parsed === undefined || typeof parsed !== 'object') {
|
|
37
|
+
return null;
|
|
38
|
+
}
|
|
39
|
+
const obj = parsed;
|
|
40
|
+
return {
|
|
41
|
+
name: typeof obj['name'] === 'string' ? obj['name'] : specPath,
|
|
42
|
+
description: typeof obj['description'] === 'string' ? obj['description'] : undefined,
|
|
43
|
+
model: typeof obj['model'] === 'string' ? obj['model'] : undefined,
|
|
44
|
+
system: typeof obj['system'] === 'string' ? obj['system'] : undefined,
|
|
45
|
+
prompt: typeof obj['prompt'] === 'string' ? obj['prompt'] : '',
|
|
46
|
+
tests: Array.isArray(obj['tests']) ? parseRawTests(obj['tests']) : undefined,
|
|
47
|
+
};
|
|
48
|
+
}
|
|
49
|
+
/**
|
|
50
|
+
* Parse raw test entries from YAML.
|
|
51
|
+
*/
|
|
52
|
+
function parseRawTests(rawTests) {
|
|
53
|
+
return rawTests
|
|
54
|
+
.filter((t) => typeof t === 'object' && t !== null)
|
|
55
|
+
.map((t) => {
|
|
56
|
+
const test = {
|
|
57
|
+
name: typeof t['name'] === 'string' ? t['name'] : 'unnamed',
|
|
58
|
+
input: typeof t['input'] === 'string' ? t['input'] : undefined,
|
|
59
|
+
inputFile: typeof t['inputFile'] === 'string' ? t['inputFile'] : undefined,
|
|
60
|
+
};
|
|
61
|
+
if (typeof t['expect'] === 'object' && t['expect'] !== null) {
|
|
62
|
+
const e = t['expect'];
|
|
63
|
+
const expect = {};
|
|
64
|
+
if (Array.isArray(e['contains'])) {
|
|
65
|
+
expect.contains = e['contains'].filter((v) => typeof v === 'string');
|
|
66
|
+
}
|
|
67
|
+
if (Array.isArray(e['notContains'])) {
|
|
68
|
+
expect.notContains = e['notContains'].filter((v) => typeof v === 'string');
|
|
69
|
+
}
|
|
70
|
+
if (Array.isArray(e['regex'])) {
|
|
71
|
+
expect.regex = e['regex'].filter((v) => typeof v === 'string');
|
|
72
|
+
}
|
|
73
|
+
if (typeof e['equals'] === 'string') {
|
|
74
|
+
expect.equals = e['equals'];
|
|
75
|
+
}
|
|
76
|
+
if (typeof e['jsonSchema'] === 'object' && e['jsonSchema'] !== null) {
|
|
77
|
+
expect.jsonSchema = e['jsonSchema'];
|
|
78
|
+
}
|
|
79
|
+
test.expect = expect;
|
|
80
|
+
}
|
|
81
|
+
return test;
|
|
82
|
+
});
|
|
83
|
+
}
|
|
84
|
+
/**
|
|
85
|
+
* Describe the prompt's purpose based on its content.
|
|
86
|
+
*/
|
|
87
|
+
function describePrompt(spec) {
|
|
88
|
+
const lines = [];
|
|
89
|
+
lines.push(`Prompt: "${spec.name}"`);
|
|
90
|
+
if (spec.description) {
|
|
91
|
+
lines.push(`Description: ${spec.description}`);
|
|
92
|
+
}
|
|
93
|
+
if (spec.model) {
|
|
94
|
+
lines.push(`Target model: ${spec.model}`);
|
|
95
|
+
}
|
|
96
|
+
else {
|
|
97
|
+
lines.push('Target model: not specified (will use default)');
|
|
98
|
+
}
|
|
99
|
+
const promptTokens = estimateTokenCount(spec.prompt);
|
|
100
|
+
const systemTokens = estimateTokenCount(spec.system ?? '');
|
|
101
|
+
const totalTokens = promptTokens + systemTokens;
|
|
102
|
+
lines.push(`Estimated size: ~${totalTokens} tokens (prompt: ~${promptTokens}, system: ~${systemTokens})`);
|
|
103
|
+
if (spec.system) {
|
|
104
|
+
lines.push('');
|
|
105
|
+
lines.push('System prompt sets context for the assistant with the following instructions:');
|
|
106
|
+
// Extract a brief summary from the first sentence or first 120 chars
|
|
107
|
+
const firstSentence = spec.system.split(/[.!?\n]/).filter(Boolean)[0]?.trim();
|
|
108
|
+
if (firstSentence) {
|
|
109
|
+
const summary = firstSentence.length > 120
|
|
110
|
+
? firstSentence.slice(0, 117) + '...'
|
|
111
|
+
: firstSentence;
|
|
112
|
+
lines.push(` "${summary}"`);
|
|
113
|
+
}
|
|
114
|
+
}
|
|
115
|
+
lines.push('');
|
|
116
|
+
lines.push('The user prompt instructs the model to:');
|
|
117
|
+
// Extract key action phrases
|
|
118
|
+
const actionPatterns = [
|
|
119
|
+
{ pattern: /\b(generate|create|write|produce|make)\b/i, verb: 'generate content' },
|
|
120
|
+
{ pattern: /\b(analyze|review|evaluate|assess|examine)\b/i, verb: 'analyze input' },
|
|
121
|
+
{ pattern: /\b(translate|convert|transform)\b/i, verb: 'translate or convert' },
|
|
122
|
+
{ pattern: /\b(summarize|condense|shorten)\b/i, verb: 'summarize content' },
|
|
123
|
+
{ pattern: /\b(classify|categorize|label|tag)\b/i, verb: 'classify or categorize' },
|
|
124
|
+
{ pattern: /\b(explain|describe|elaborate)\b/i, verb: 'explain or describe' },
|
|
125
|
+
{ pattern: /\b(extract|find|identify|detect)\b/i, verb: 'extract or identify information' },
|
|
126
|
+
{ pattern: /\b(fix|correct|repair|debug)\b/i, verb: 'fix or correct issues' },
|
|
127
|
+
{ pattern: /\b(compare|contrast|diff)\b/i, verb: 'compare items' },
|
|
128
|
+
{ pattern: /\b(list|enumerate|outline)\b/i, verb: 'list or enumerate items' },
|
|
129
|
+
];
|
|
130
|
+
const detectedActions = [];
|
|
131
|
+
for (const { pattern, verb } of actionPatterns) {
|
|
132
|
+
if (pattern.test(spec.prompt)) {
|
|
133
|
+
detectedActions.push(verb);
|
|
134
|
+
}
|
|
135
|
+
}
|
|
136
|
+
if (detectedActions.length > 0) {
|
|
137
|
+
for (const action of detectedActions) {
|
|
138
|
+
lines.push(` - ${action}`);
|
|
139
|
+
}
|
|
140
|
+
}
|
|
141
|
+
else {
|
|
142
|
+
lines.push(' - (no specific action verb detected -- the prompt may need clearer instructions)');
|
|
143
|
+
}
|
|
144
|
+
return lines;
|
|
145
|
+
}
|
|
146
|
+
/**
|
|
147
|
+
* Identify potential weaknesses in the prompt spec.
|
|
148
|
+
*/
|
|
149
|
+
function identifyWeaknesses(spec) {
|
|
150
|
+
const weaknesses = [];
|
|
151
|
+
if (!spec.system) {
|
|
152
|
+
weaknesses.push('No system prompt: the model has no role or constraint context.');
|
|
153
|
+
}
|
|
154
|
+
else if (spec.system.length < 20) {
|
|
155
|
+
weaknesses.push('System prompt is very short and may not provide enough context.');
|
|
156
|
+
}
|
|
157
|
+
// Check for vague language
|
|
158
|
+
const vagueWords = ['good', 'nice', 'appropriate', 'proper', 'suitable', 'adequate', 'reasonable'];
|
|
159
|
+
const fullText = [spec.system ?? '', spec.prompt].join(' ').toLowerCase();
|
|
160
|
+
const foundVague = vagueWords.filter((w) => fullText.includes(w));
|
|
161
|
+
if (foundVague.length > 0) {
|
|
162
|
+
weaknesses.push(`Uses vague language (${foundVague.join(', ')}) that may lead to inconsistent outputs.`);
|
|
163
|
+
}
|
|
164
|
+
// Check for format specification
|
|
165
|
+
const formatPatterns = [
|
|
166
|
+
/\bformat\b/i, /\bjson\b/i, /\byaml\b/i, /\bmarkdown\b/i,
|
|
167
|
+
/\boutput\s+as\b/i, /\brespond\s+(with|in)\b/i,
|
|
168
|
+
];
|
|
169
|
+
const hasFormat = formatPatterns.some((p) => p.test(fullText));
|
|
170
|
+
if (!hasFormat) {
|
|
171
|
+
weaknesses.push('No output format specified. Responses may vary in structure.');
|
|
172
|
+
}
|
|
173
|
+
// Check for prompt injection vulnerability
|
|
174
|
+
const injectionPatterns = [
|
|
175
|
+
/ignore\s+(all\s+)?previous/i,
|
|
176
|
+
/disregard/i,
|
|
177
|
+
/new\s+instructions/i,
|
|
178
|
+
];
|
|
179
|
+
const hasInjectionRisk = injectionPatterns.some((p) => p.test(fullText));
|
|
180
|
+
if (hasInjectionRisk) {
|
|
181
|
+
weaknesses.push('Contains patterns that could be exploited for prompt injection.');
|
|
182
|
+
}
|
|
183
|
+
// Check prompt size
|
|
184
|
+
const totalTokens = estimateTokenCount(fullText);
|
|
185
|
+
if (totalTokens > 4000) {
|
|
186
|
+
weaknesses.push(`Large prompt (~${totalTokens} tokens) may increase latency and cost without proportional quality gains.`);
|
|
187
|
+
}
|
|
188
|
+
// Check for contradictions
|
|
189
|
+
const contradictions = [
|
|
190
|
+
[/be\s+concise/i, /explain\s+in\s+detail/i, '"be concise" + "explain in detail"'],
|
|
191
|
+
[/be\s+brief/i, /be\s+thorough/i, '"be brief" + "be thorough"'],
|
|
192
|
+
[/do\s+not\s+explain/i, /explain\s+(your|the)\s+reasoning/i, '"do not explain" + "explain reasoning"'],
|
|
193
|
+
];
|
|
194
|
+
for (const [a, b, desc] of contradictions) {
|
|
195
|
+
if (a.test(fullText) && b.test(fullText)) {
|
|
196
|
+
weaknesses.push(`Contradictory instructions: ${desc}.`);
|
|
197
|
+
}
|
|
198
|
+
}
|
|
199
|
+
if (weaknesses.length === 0) {
|
|
200
|
+
weaknesses.push('No major weaknesses detected.');
|
|
201
|
+
}
|
|
202
|
+
return weaknesses;
|
|
203
|
+
}
|
|
204
|
+
/**
|
|
205
|
+
* Analyze tests and explain why they might fail.
|
|
206
|
+
*/
|
|
207
|
+
function analyzeTests(spec) {
|
|
208
|
+
const lines = [];
|
|
209
|
+
const tests = spec.tests ?? [];
|
|
210
|
+
if (tests.length === 0) {
|
|
211
|
+
lines.push('No tests defined. Cannot analyze potential test failures.');
|
|
212
|
+
lines.push('Recommendation: add at least 2-3 tests covering primary and edge cases.');
|
|
213
|
+
return lines;
|
|
214
|
+
}
|
|
215
|
+
lines.push(`${tests.length} test(s) defined:`);
|
|
216
|
+
for (const test of tests) {
|
|
217
|
+
lines.push('');
|
|
218
|
+
lines.push(` Test: "${test.name}"`);
|
|
219
|
+
if (!test.expect) {
|
|
220
|
+
lines.push(' Issue: No assertions. This test will always pass, providing no safety net.');
|
|
221
|
+
continue;
|
|
222
|
+
}
|
|
223
|
+
const reasons = [];
|
|
224
|
+
if (test.expect.contains && test.expect.contains.length > 0) {
|
|
225
|
+
lines.push(` Checks output contains: ${test.expect.contains.map((s) => `"${s}"`).join(', ')}`);
|
|
226
|
+
reasons.push('Could fail if the model paraphrases expected keywords or uses synonyms.');
|
|
227
|
+
}
|
|
228
|
+
if (test.expect.notContains && test.expect.notContains.length > 0) {
|
|
229
|
+
lines.push(` Checks output does NOT contain: ${test.expect.notContains.map((s) => `"${s}"`).join(', ')}`);
|
|
230
|
+
reasons.push('Could fail if the model mentions excluded terms in context or explanations.');
|
|
231
|
+
}
|
|
232
|
+
if (test.expect.regex && test.expect.regex.length > 0) {
|
|
233
|
+
lines.push(` Checks output matches regex patterns`);
|
|
234
|
+
reasons.push('Regex assertions can be brittle if the model varies whitespace or formatting.');
|
|
235
|
+
}
|
|
236
|
+
if (test.expect.equals !== undefined) {
|
|
237
|
+
const preview = test.expect.equals.length > 60
|
|
238
|
+
? test.expect.equals.slice(0, 57) + '...'
|
|
239
|
+
: test.expect.equals;
|
|
240
|
+
lines.push(` Checks exact match: "${preview}"`);
|
|
241
|
+
reasons.push('Exact match is very strict. Any extra whitespace, punctuation, or phrasing difference causes failure.');
|
|
242
|
+
}
|
|
243
|
+
if (test.expect.jsonSchema) {
|
|
244
|
+
lines.push(' Validates output against a JSON schema');
|
|
245
|
+
reasons.push('Could fail if the model wraps JSON in markdown code blocks or adds extra text.');
|
|
246
|
+
}
|
|
247
|
+
if (reasons.length > 0) {
|
|
248
|
+
lines.push(' Potential failure reasons:');
|
|
249
|
+
for (const reason of reasons) {
|
|
250
|
+
lines.push(` - ${reason}`);
|
|
251
|
+
}
|
|
252
|
+
}
|
|
253
|
+
}
|
|
254
|
+
return lines;
|
|
255
|
+
}
|
|
256
|
+
/**
|
|
257
|
+
* Generate improvement suggestions.
|
|
258
|
+
*/
|
|
259
|
+
function generateSuggestions(spec) {
|
|
260
|
+
const suggestions = [];
|
|
261
|
+
if (!spec.system) {
|
|
262
|
+
suggestions.push('Add a system prompt that defines the assistant\'s role and constraints.');
|
|
263
|
+
}
|
|
264
|
+
if (!spec.description) {
|
|
265
|
+
suggestions.push('Add a description field for better documentation and discoverability.');
|
|
266
|
+
}
|
|
267
|
+
if (!spec.model) {
|
|
268
|
+
suggestions.push('Specify a target model to ensure consistent behavior across environments.');
|
|
269
|
+
}
|
|
270
|
+
const tests = spec.tests ?? [];
|
|
271
|
+
if (tests.length === 0) {
|
|
272
|
+
suggestions.push('Add tests with assertions to catch regressions.');
|
|
273
|
+
}
|
|
274
|
+
else if (tests.length < 3) {
|
|
275
|
+
suggestions.push('Add more test cases (aim for 3-5) covering happy path, edge cases, and error cases.');
|
|
276
|
+
}
|
|
277
|
+
const hasJsonSchema = tests.some((t) => t.expect?.jsonSchema);
|
|
278
|
+
if (!hasJsonSchema && tests.length > 0) {
|
|
279
|
+
suggestions.push('Consider adding jsonSchema assertions for structured output validation.');
|
|
280
|
+
}
|
|
281
|
+
const fullText = [spec.system ?? '', spec.prompt].join(' ');
|
|
282
|
+
const tokenCount = estimateTokenCount(fullText);
|
|
283
|
+
if (tokenCount > 3000) {
|
|
284
|
+
suggestions.push('Consider splitting long instructions into a system prompt (static context) and user prompt (per-request).');
|
|
285
|
+
}
|
|
286
|
+
if (suggestions.length === 0) {
|
|
287
|
+
suggestions.push('The prompt spec looks well-structured. Consider adding more edge case tests for robustness.');
|
|
288
|
+
}
|
|
289
|
+
return suggestions;
|
|
290
|
+
}
|
|
291
|
+
/**
|
|
292
|
+
* Analyze a prompt spec file and generate a plain-text explanation.
|
|
293
|
+
*
|
|
294
|
+
* This is a purely offline analysis -- no LLM calls are made.
|
|
295
|
+
*
|
|
296
|
+
* @param specPath Absolute path to a YAML prompt spec file.
|
|
297
|
+
* @returns Multi-line plain-text explanation.
|
|
298
|
+
*/
|
|
299
|
+
export async function explainPrompt(specPath) {
|
|
300
|
+
const spec = await parseSpec(specPath);
|
|
301
|
+
if (!spec) {
|
|
302
|
+
return [
|
|
303
|
+
`Failed to parse prompt spec at: ${specPath}`,
|
|
304
|
+
'',
|
|
305
|
+
'Ensure the file is valid YAML with at least a "prompt" field.',
|
|
306
|
+
'Example:',
|
|
307
|
+
' name: my-prompt',
|
|
308
|
+
' prompt: "Summarize the following text: {{input}}"',
|
|
309
|
+
].join('\n');
|
|
310
|
+
}
|
|
311
|
+
const sections = [];
|
|
312
|
+
// Section 1: What does this prompt do?
|
|
313
|
+
sections.push([
|
|
314
|
+
'== What This Prompt Does ==',
|
|
315
|
+
...describePrompt(spec),
|
|
316
|
+
]);
|
|
317
|
+
// Section 2: Potential weaknesses
|
|
318
|
+
sections.push([
|
|
319
|
+
'== Potential Weaknesses ==',
|
|
320
|
+
...identifyWeaknesses(spec),
|
|
321
|
+
]);
|
|
322
|
+
// Section 3: Test analysis
|
|
323
|
+
sections.push([
|
|
324
|
+
'== Test Analysis ==',
|
|
325
|
+
...analyzeTests(spec),
|
|
326
|
+
]);
|
|
327
|
+
// Section 4: Suggestions
|
|
328
|
+
sections.push([
|
|
329
|
+
'== Suggestions for Improvement ==',
|
|
330
|
+
...generateSuggestions(spec),
|
|
331
|
+
]);
|
|
332
|
+
return sections.map((section) => section.join('\n')).join('\n\n');
|
|
333
|
+
}
|
|
334
|
+
//# sourceMappingURL=promptExplainer.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"promptExplainer.js","sourceRoot":"","sources":["../../src/core/promptExplainer.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,19 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Prompt improvement suggestion engine.
|
|
3
|
+
*
|
|
4
|
+
* Analyzes a prompt spec and generates actionable improvement
|
|
5
|
+
* suggestions covering format, schema, testing, and prompt quality.
|
|
6
|
+
*/
|
|
7
|
+
import type { ImprovementSuggestion } from '../types/diagnostics.js';
|
|
8
|
+
/**
|
|
9
|
+
* Analyze a prompt spec and generate improvement suggestions.
|
|
10
|
+
*
|
|
11
|
+
* This is a purely offline analysis -- no LLM calls are made.
|
|
12
|
+
* Suggestions are prioritized by their expected impact on prompt
|
|
13
|
+
* quality and test reliability.
|
|
14
|
+
*
|
|
15
|
+
* @param specPath Absolute path to a YAML prompt spec file.
|
|
16
|
+
* @returns Ordered array of improvement suggestions.
|
|
17
|
+
*/
|
|
18
|
+
export declare function improvePrompt(specPath: string): Promise<ImprovementSuggestion[]>;
|
|
19
|
+
//# sourceMappingURL=promptImprover.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"promptImprover.d.ts","sourceRoot":"","sources":["../../src/core/promptImprover.ts"],"names":[],"mappings":"AAAA;;;;;GAKG;AAIH,OAAO,KAAK,EAAE,qBAAqB,EAAE,MAAM,yBAAyB,CAAC;AAmHrE;;;;;;;;;GASG;AACH,wBAAsB,aAAa,CACjC,QAAQ,EAAE,MAAM,GACf,OAAO,CAAC,qBAAqB,EAAE,CAAC,CA4JlC"}
|
|
@@ -0,0 +1,260 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Prompt improvement suggestion engine.
|
|
3
|
+
*
|
|
4
|
+
* Analyzes a prompt spec and generates actionable improvement
|
|
5
|
+
* suggestions covering format, schema, testing, and prompt quality.
|
|
6
|
+
*/
|
|
7
|
+
import { readFile } from 'node:fs/promises';
|
|
8
|
+
import yaml from 'js-yaml';
|
|
9
|
+
/**
|
|
10
|
+
* Rough token estimation: ~4 characters per token.
|
|
11
|
+
*/
|
|
12
|
+
function estimateTokenCount(text) {
|
|
13
|
+
if (!text)
|
|
14
|
+
return 0;
|
|
15
|
+
return Math.ceil(text.length / 4);
|
|
16
|
+
}
|
|
17
|
+
/**
|
|
18
|
+
* Parse a YAML file into a PromptSpec. Returns null on failure.
|
|
19
|
+
*/
|
|
20
|
+
async function parseSpec(specPath) {
|
|
21
|
+
let content;
|
|
22
|
+
try {
|
|
23
|
+
content = await readFile(specPath, 'utf-8');
|
|
24
|
+
}
|
|
25
|
+
catch {
|
|
26
|
+
return null;
|
|
27
|
+
}
|
|
28
|
+
let parsed;
|
|
29
|
+
try {
|
|
30
|
+
parsed = yaml.load(content);
|
|
31
|
+
}
|
|
32
|
+
catch {
|
|
33
|
+
return null;
|
|
34
|
+
}
|
|
35
|
+
if (parsed === null || parsed === undefined || typeof parsed !== 'object') {
|
|
36
|
+
return null;
|
|
37
|
+
}
|
|
38
|
+
const obj = parsed;
|
|
39
|
+
return {
|
|
40
|
+
name: typeof obj['name'] === 'string' ? obj['name'] : specPath,
|
|
41
|
+
description: typeof obj['description'] === 'string' ? obj['description'] : undefined,
|
|
42
|
+
model: typeof obj['model'] === 'string' ? obj['model'] : undefined,
|
|
43
|
+
system: typeof obj['system'] === 'string' ? obj['system'] : undefined,
|
|
44
|
+
prompt: typeof obj['prompt'] === 'string' ? obj['prompt'] : '',
|
|
45
|
+
tests: Array.isArray(obj['tests']) ? parseRawTests(obj['tests']) : undefined,
|
|
46
|
+
};
|
|
47
|
+
}
|
|
48
|
+
/**
|
|
49
|
+
* Parse raw test entries from YAML.
|
|
50
|
+
*/
|
|
51
|
+
function parseRawTests(rawTests) {
|
|
52
|
+
return rawTests
|
|
53
|
+
.filter((t) => typeof t === 'object' && t !== null)
|
|
54
|
+
.map((t) => {
|
|
55
|
+
const test = {
|
|
56
|
+
name: typeof t['name'] === 'string' ? t['name'] : 'unnamed',
|
|
57
|
+
input: typeof t['input'] === 'string' ? t['input'] : undefined,
|
|
58
|
+
inputFile: typeof t['inputFile'] === 'string' ? t['inputFile'] : undefined,
|
|
59
|
+
};
|
|
60
|
+
if (typeof t['expect'] === 'object' && t['expect'] !== null) {
|
|
61
|
+
const e = t['expect'];
|
|
62
|
+
const expect = {};
|
|
63
|
+
if (Array.isArray(e['contains'])) {
|
|
64
|
+
expect.contains = e['contains'].filter((v) => typeof v === 'string');
|
|
65
|
+
}
|
|
66
|
+
if (Array.isArray(e['notContains'])) {
|
|
67
|
+
expect.notContains = e['notContains'].filter((v) => typeof v === 'string');
|
|
68
|
+
}
|
|
69
|
+
if (Array.isArray(e['regex'])) {
|
|
70
|
+
expect.regex = e['regex'].filter((v) => typeof v === 'string');
|
|
71
|
+
}
|
|
72
|
+
if (typeof e['equals'] === 'string') {
|
|
73
|
+
expect.equals = e['equals'];
|
|
74
|
+
}
|
|
75
|
+
if (typeof e['jsonSchema'] === 'object' && e['jsonSchema'] !== null) {
|
|
76
|
+
expect.jsonSchema = e['jsonSchema'];
|
|
77
|
+
}
|
|
78
|
+
test.expect = expect;
|
|
79
|
+
}
|
|
80
|
+
return test;
|
|
81
|
+
});
|
|
82
|
+
}
|
|
83
|
+
/**
|
|
84
|
+
* Check whether any test uses a jsonSchema assertion.
|
|
85
|
+
*/
|
|
86
|
+
function hasJsonSchemaAssertion(tests) {
|
|
87
|
+
return tests.some((t) => t.expect?.jsonSchema !== undefined);
|
|
88
|
+
}
|
|
89
|
+
/**
|
|
90
|
+
* Check whether any test uses file-based input.
|
|
91
|
+
*/
|
|
92
|
+
function hasFileBasedInput(tests) {
|
|
93
|
+
return tests.some((t) => t.inputFile !== undefined);
|
|
94
|
+
}
|
|
95
|
+
/**
|
|
96
|
+
* Count the distinct assertion types used across all tests.
|
|
97
|
+
*/
|
|
98
|
+
function countAssertionTypes(tests) {
|
|
99
|
+
const types = new Set();
|
|
100
|
+
for (const test of tests) {
|
|
101
|
+
if (!test.expect)
|
|
102
|
+
continue;
|
|
103
|
+
if (test.expect.contains)
|
|
104
|
+
types.add('contains');
|
|
105
|
+
if (test.expect.notContains)
|
|
106
|
+
types.add('notContains');
|
|
107
|
+
if (test.expect.regex)
|
|
108
|
+
types.add('regex');
|
|
109
|
+
if (test.expect.equals !== undefined)
|
|
110
|
+
types.add('equals');
|
|
111
|
+
if (test.expect.jsonSchema)
|
|
112
|
+
types.add('jsonSchema');
|
|
113
|
+
}
|
|
114
|
+
return types.size;
|
|
115
|
+
}
|
|
116
|
+
/**
|
|
117
|
+
* Analyze a prompt spec and generate improvement suggestions.
|
|
118
|
+
*
|
|
119
|
+
* This is a purely offline analysis -- no LLM calls are made.
|
|
120
|
+
* Suggestions are prioritized by their expected impact on prompt
|
|
121
|
+
* quality and test reliability.
|
|
122
|
+
*
|
|
123
|
+
* @param specPath Absolute path to a YAML prompt spec file.
|
|
124
|
+
* @returns Ordered array of improvement suggestions.
|
|
125
|
+
*/
|
|
126
|
+
export async function improvePrompt(specPath) {
|
|
127
|
+
const spec = await parseSpec(specPath);
|
|
128
|
+
if (!spec) {
|
|
129
|
+
return [
|
|
130
|
+
{
|
|
131
|
+
category: 'parse-error',
|
|
132
|
+
priority: 'high',
|
|
133
|
+
message: 'Cannot parse the prompt spec file.',
|
|
134
|
+
details: 'Ensure the file is valid YAML and contains at least a "prompt" field.',
|
|
135
|
+
},
|
|
136
|
+
];
|
|
137
|
+
}
|
|
138
|
+
const suggestions = [];
|
|
139
|
+
// 1. Missing output format specification
|
|
140
|
+
const fullText = [spec.system ?? '', spec.prompt].join('\n');
|
|
141
|
+
const formatIndicators = [
|
|
142
|
+
/\bformat\b/i, /\bjson\b/i, /\bxml\b/i, /\byaml\b/i,
|
|
143
|
+
/\bmarkdown\b/i, /\bcsv\b/i, /\btable\b/i,
|
|
144
|
+
/\bbullet/i, /\bnumbered\s+list/i,
|
|
145
|
+
/\boutput\s+as\b/i, /\brespond\s+(with|in|as)\b/i,
|
|
146
|
+
];
|
|
147
|
+
const hasFormat = formatIndicators.some((p) => p.test(fullText));
|
|
148
|
+
if (!hasFormat) {
|
|
149
|
+
suggestions.push({
|
|
150
|
+
category: 'output-format',
|
|
151
|
+
priority: 'high',
|
|
152
|
+
message: 'Add an explicit output format specification.',
|
|
153
|
+
details: 'Specify the expected output format (JSON, markdown, plain text, etc.) to get more consistent responses. ' +
|
|
154
|
+
'Example: add "Respond in JSON with keys: answer, confidence" to your prompt.',
|
|
155
|
+
});
|
|
156
|
+
}
|
|
157
|
+
// 2. Overly long prompts
|
|
158
|
+
const tokenCount = estimateTokenCount(fullText);
|
|
159
|
+
if (tokenCount > 4000) {
|
|
160
|
+
suggestions.push({
|
|
161
|
+
category: 'prompt-length',
|
|
162
|
+
priority: 'medium',
|
|
163
|
+
message: `Prompt is ~${tokenCount} tokens. Consider trimming for efficiency.`,
|
|
164
|
+
details: 'Long prompts increase latency and cost. Try extracting examples into separate test inputs, ' +
|
|
165
|
+
'removing redundant instructions, or using a system prompt for static context.',
|
|
166
|
+
});
|
|
167
|
+
}
|
|
168
|
+
// 3. Missing schema constraints
|
|
169
|
+
const tests = spec.tests ?? [];
|
|
170
|
+
if (tests.length > 0 && !hasJsonSchemaAssertion(tests)) {
|
|
171
|
+
suggestions.push({
|
|
172
|
+
category: 'schema-validation',
|
|
173
|
+
priority: 'medium',
|
|
174
|
+
message: 'Add jsonSchema assertions to validate structured output.',
|
|
175
|
+
details: 'If your prompt produces structured data, adding a jsonSchema assertion ensures ' +
|
|
176
|
+
'the output conforms to the expected shape. This catches schema drift and missing fields.',
|
|
177
|
+
});
|
|
178
|
+
}
|
|
179
|
+
// 4. Missing regression tests
|
|
180
|
+
if (tests.length === 0) {
|
|
181
|
+
suggestions.push({
|
|
182
|
+
category: 'testing',
|
|
183
|
+
priority: 'high',
|
|
184
|
+
message: 'Add tests to verify prompt behavior.',
|
|
185
|
+
details: 'Tests prevent regressions when you modify the prompt. Start with 2-3 tests covering ' +
|
|
186
|
+
'the primary use case, an edge case, and an adversarial input.',
|
|
187
|
+
});
|
|
188
|
+
}
|
|
189
|
+
// 5. Missing system prompt
|
|
190
|
+
if (!spec.system) {
|
|
191
|
+
suggestions.push({
|
|
192
|
+
category: 'system-prompt',
|
|
193
|
+
priority: 'high',
|
|
194
|
+
message: 'Add a system prompt to set context and constraints.',
|
|
195
|
+
details: 'A system prompt defines the assistant\'s role, tone, and boundaries. ' +
|
|
196
|
+
'Example: "You are a code review assistant. Respond concisely with actionable feedback."',
|
|
197
|
+
});
|
|
198
|
+
}
|
|
199
|
+
// 6. Generic system prompts
|
|
200
|
+
if (spec.system) {
|
|
201
|
+
const genericPatterns = [
|
|
202
|
+
/^you are (a|an) (helpful|friendly) assistant\.?$/i,
|
|
203
|
+
/^you are a chatbot\.?$/i,
|
|
204
|
+
/^you are an ai\.?$/i,
|
|
205
|
+
/^respond helpfully\.?$/i,
|
|
206
|
+
/^be helpful\.?$/i,
|
|
207
|
+
];
|
|
208
|
+
const isGeneric = genericPatterns.some((p) => p.test(spec.system.trim()));
|
|
209
|
+
if (isGeneric) {
|
|
210
|
+
suggestions.push({
|
|
211
|
+
category: 'system-prompt',
|
|
212
|
+
priority: 'medium',
|
|
213
|
+
message: 'System prompt is too generic. Make it more specific to your use case.',
|
|
214
|
+
details: 'Generic system prompts like "You are a helpful assistant" do not meaningfully constrain ' +
|
|
215
|
+
'the model. Specify the domain, output expectations, and constraints. ' +
|
|
216
|
+
'Example: "You are a TypeScript expert. Review code for bugs, type safety issues, ' +
|
|
217
|
+
'and performance problems. Respond with a numbered list."',
|
|
218
|
+
});
|
|
219
|
+
}
|
|
220
|
+
}
|
|
221
|
+
// 7. Missing file-based test inputs
|
|
222
|
+
if (tests.length > 0 && !hasFileBasedInput(tests)) {
|
|
223
|
+
suggestions.push({
|
|
224
|
+
category: 'test-fixtures',
|
|
225
|
+
priority: 'low',
|
|
226
|
+
message: 'Consider adding file-based test inputs for complex scenarios.',
|
|
227
|
+
details: 'For long or structured inputs, use inputFile to reference fixture files. ' +
|
|
228
|
+
'This keeps the spec clean and makes it easy to test with realistic data.',
|
|
229
|
+
});
|
|
230
|
+
}
|
|
231
|
+
// 8. Test coverage breadth
|
|
232
|
+
if (tests.length > 0 && tests.length < 3) {
|
|
233
|
+
suggestions.push({
|
|
234
|
+
category: 'test-coverage',
|
|
235
|
+
priority: 'medium',
|
|
236
|
+
message: `Only ${tests.length} test(s) defined. Consider adding more diverse test cases.`,
|
|
237
|
+
details: 'Good test coverage includes: (1) a happy-path test, (2) an edge case with unusual input, ' +
|
|
238
|
+
'(3) a negative test with invalid input, and (4) a boundary test. ' +
|
|
239
|
+
'Aim for at least 3-5 tests per prompt spec.',
|
|
240
|
+
});
|
|
241
|
+
}
|
|
242
|
+
// Bonus: low assertion diversity
|
|
243
|
+
if (tests.length > 0) {
|
|
244
|
+
const assertionTypeCount = countAssertionTypes(tests);
|
|
245
|
+
if (assertionTypeCount <= 1 && tests.length >= 2) {
|
|
246
|
+
suggestions.push({
|
|
247
|
+
category: 'assertion-diversity',
|
|
248
|
+
priority: 'low',
|
|
249
|
+
message: 'Tests use only one type of assertion. Consider diversifying.',
|
|
250
|
+
details: 'Using a mix of contains, regex, notContains, and jsonSchema assertions ' +
|
|
251
|
+
'provides broader coverage and catches more issues.',
|
|
252
|
+
});
|
|
253
|
+
}
|
|
254
|
+
}
|
|
255
|
+
// Sort by priority: high first, then medium, then low
|
|
256
|
+
const priorityOrder = { high: 0, medium: 1, low: 2 };
|
|
257
|
+
suggestions.sort((a, b) => priorityOrder[a.priority] - priorityOrder[b.priority]);
|
|
258
|
+
return suggestions;
|
|
259
|
+
}
|
|
260
|
+
//# sourceMappingURL=promptImprover.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"promptImprover.js","sourceRoot":"","sources":["../../src/core/promptImprover.ts"],"names":[],"mappings":"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"}
|