@vijaypjavvadi/bdd2pw 1.1.7 → 2.0.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/CHANGELOG.md +148 -0
- package/dist/cli.js +22 -2
- package/dist/cli.js.map +1 -1
- package/dist/index.js +34 -7
- package/dist/index.js.map +1 -1
- package/dist/llm/anthropicClient.d.ts +49 -0
- package/dist/llm/anthropicClient.js +279 -0
- package/dist/llm/anthropicClient.js.map +1 -0
- package/dist/llm/cache.d.ts +51 -0
- package/dist/llm/cache.js +150 -0
- package/dist/llm/cache.js.map +1 -0
- package/dist/llm/candidateRules.d.ts +30 -0
- package/dist/llm/candidateRules.js +89 -0
- package/dist/llm/candidateRules.js.map +1 -0
- package/dist/llm/governanceClient.d.ts +36 -16
- package/dist/llm/governanceClient.js +73 -7
- package/dist/llm/governanceClient.js.map +1 -1
- package/dist/llm/index.d.ts +28 -0
- package/dist/llm/index.js +83 -0
- package/dist/llm/index.js.map +1 -0
- package/dist/llm/llmStepMatcher.d.ts +35 -0
- package/dist/llm/llmStepMatcher.js +93 -0
- package/dist/llm/llmStepMatcher.js.map +1 -0
- package/dist/llm/prompt.d.ts +39 -0
- package/dist/llm/prompt.js +113 -0
- package/dist/llm/prompt.js.map +1 -0
- package/dist/llm/types.d.ts +143 -0
- package/dist/llm/types.js +17 -0
- package/dist/llm/types.js.map +1 -0
- package/dist/types.d.ts +32 -0
- package/package.json +1 -1
|
@@ -0,0 +1,143 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* LLM fallback types — v2.0.
|
|
3
|
+
*
|
|
4
|
+
* The LLM is invoked ONLY when bdd2pw's deterministic rule table
|
|
5
|
+
* (`src/transformers/stepMatcher.ts`) fails to match a step. The LLM's
|
|
6
|
+
* job is to produce a single `StepBinding` matching the existing IR
|
|
7
|
+
* shape. This is identical to what a hand-written rule would produce, so
|
|
8
|
+
* downstream emitters don't need to know an LLM was involved.
|
|
9
|
+
*
|
|
10
|
+
* Every LLM-generated binding is also appended to
|
|
11
|
+
* `<repo>/artefacts/candidate-rules.jsonl` so a separate offline pipeline
|
|
12
|
+
* can review and propose new deterministic rules. Auto-writing rules
|
|
13
|
+
* back into `stepMatcher.ts` is deferred to v2.1+ (see docs/SCOPE.md).
|
|
14
|
+
*/
|
|
15
|
+
import type { PageObjectIR, StepIR, StepBinding } from "../types";
|
|
16
|
+
export interface LLMClientOptions {
|
|
17
|
+
/** Provider identifier — "anthropic" in v2.0; OpenAI/Gemini in v2.1+. */
|
|
18
|
+
provider: "anthropic";
|
|
19
|
+
/** Anthropic model. Default: claude-sonnet-4-6. */
|
|
20
|
+
model?: string;
|
|
21
|
+
/** API key. Resolved from env var (ANTHROPIC_API_KEY) when omitted. */
|
|
22
|
+
apiKey?: string;
|
|
23
|
+
/**
|
|
24
|
+
* ai-governance sidecar base URL — default http://localhost:4900.
|
|
25
|
+
* EVERY prompt is POSTed to `${governanceUrl}/sanitize` before being
|
|
26
|
+
* sent to the provider. If the sidecar is unreachable, generation fails
|
|
27
|
+
* (fail-closed) — we don't leak unsanitised payloads.
|
|
28
|
+
*/
|
|
29
|
+
governanceUrl?: string;
|
|
30
|
+
/** Max LLM calls per scaffold(). Default 50. */
|
|
31
|
+
maxCalls?: number;
|
|
32
|
+
/** Cache database path. Default <repo>/.bdd2pw/llm-cache.sqlite. */
|
|
33
|
+
cachePath?: string;
|
|
34
|
+
/**
|
|
35
|
+
* Disable governance sanitisation. NOT for production — only useful in
|
|
36
|
+
* unit tests where the sidecar isn't running and the test prompts
|
|
37
|
+
* contain no real user data.
|
|
38
|
+
*/
|
|
39
|
+
skipGovernance?: boolean;
|
|
40
|
+
/**
|
|
41
|
+
* Optional logger callback (defaults to no-op). Useful in tests to
|
|
42
|
+
* capture prompts/responses without polluting stdout.
|
|
43
|
+
*/
|
|
44
|
+
log?: (event: LLMLogEvent) => void;
|
|
45
|
+
}
|
|
46
|
+
export type LLMLogEvent = {
|
|
47
|
+
kind: "cache_hit";
|
|
48
|
+
key: string;
|
|
49
|
+
} | {
|
|
50
|
+
kind: "cache_miss";
|
|
51
|
+
key: string;
|
|
52
|
+
} | {
|
|
53
|
+
kind: "sanitise_start";
|
|
54
|
+
bytes: number;
|
|
55
|
+
} | {
|
|
56
|
+
kind: "sanitise_done";
|
|
57
|
+
bytes: number;
|
|
58
|
+
findings: number;
|
|
59
|
+
} | {
|
|
60
|
+
kind: "provider_call_start";
|
|
61
|
+
model: string;
|
|
62
|
+
promptBytes: number;
|
|
63
|
+
} | {
|
|
64
|
+
kind: "provider_call_done";
|
|
65
|
+
model: string;
|
|
66
|
+
latencyMs: number;
|
|
67
|
+
inputTokens: number;
|
|
68
|
+
outputTokens: number;
|
|
69
|
+
} | {
|
|
70
|
+
kind: "binding_parsed";
|
|
71
|
+
binding: StepBinding;
|
|
72
|
+
} | {
|
|
73
|
+
kind: "error";
|
|
74
|
+
phase: string;
|
|
75
|
+
message: string;
|
|
76
|
+
};
|
|
77
|
+
/** Input to the step-binding generator. */
|
|
78
|
+
export interface GenerateBindingInput {
|
|
79
|
+
/** The Gherkin step that didn't match any rule. */
|
|
80
|
+
step: StepIR;
|
|
81
|
+
/** The current Page Object — fields, methods, class name. */
|
|
82
|
+
pom: PageObjectIR;
|
|
83
|
+
/** camelCase variable name used in the spec (e.g. `loginPage`). */
|
|
84
|
+
pageVar: string;
|
|
85
|
+
/** URL the scaffold targets — gives the LLM additional context. */
|
|
86
|
+
url?: string;
|
|
87
|
+
/** Stable scaffold-run identifier. Logged into candidate-rules.jsonl. */
|
|
88
|
+
scaffoldId: string;
|
|
89
|
+
}
|
|
90
|
+
/** Result of an LLM-generation attempt. */
|
|
91
|
+
export interface GenerateBindingResult {
|
|
92
|
+
/** When generation succeeds. */
|
|
93
|
+
binding?: StepBinding;
|
|
94
|
+
/** When generation fails — soft-fail, caller falls back to TODO warning. */
|
|
95
|
+
error?: string;
|
|
96
|
+
/** True if the binding came from cache (no provider call made). */
|
|
97
|
+
fromCache: boolean;
|
|
98
|
+
/** Provider model name (for audit). */
|
|
99
|
+
model?: string;
|
|
100
|
+
/** Total latency including governance + provider + parsing, ms. */
|
|
101
|
+
latencyMs?: number;
|
|
102
|
+
}
|
|
103
|
+
/**
|
|
104
|
+
* Pluggable LLM client. v2.0 ships AnthropicLLMClient (provider=anthropic)
|
|
105
|
+
* and MockLLMClient (for tests). v2.1 adds OpenAI/Gemini.
|
|
106
|
+
*/
|
|
107
|
+
export interface LLMClient {
|
|
108
|
+
/** Generate a StepBinding for an unmatched step. */
|
|
109
|
+
generateBinding(input: GenerateBindingInput): Promise<GenerateBindingResult>;
|
|
110
|
+
/** Have we hit the max-calls budget for this scaffold? */
|
|
111
|
+
budgetExhausted(): boolean;
|
|
112
|
+
/** Calls made so far. */
|
|
113
|
+
callsMade(): number;
|
|
114
|
+
/** Close any underlying resources (cache db handle, etc.). */
|
|
115
|
+
close?(): Promise<void>;
|
|
116
|
+
}
|
|
117
|
+
/**
|
|
118
|
+
* Single line written to artefacts/candidate-rules.jsonl. The offline
|
|
119
|
+
* review pipeline ingests these to propose new deterministic rules.
|
|
120
|
+
*/
|
|
121
|
+
export interface CandidateRuleEntry {
|
|
122
|
+
/** ISO-8601 timestamp of when the LLM produced this binding. */
|
|
123
|
+
ts: string;
|
|
124
|
+
/** Stable scaffold-run identifier. */
|
|
125
|
+
scaffoldId: string;
|
|
126
|
+
/** Original Gherkin step text — input to any future regex. */
|
|
127
|
+
stepText: string;
|
|
128
|
+
/** Step keyword (Given/When/Then/And/But) — for context. */
|
|
129
|
+
stepKeyword: string;
|
|
130
|
+
/** The binding the LLM produced. */
|
|
131
|
+
binding: StepBinding;
|
|
132
|
+
/** POM signature — class name + field names + method names. */
|
|
133
|
+
pomSignature: {
|
|
134
|
+
className: string;
|
|
135
|
+
fieldNames: string[];
|
|
136
|
+
methodNames: string[];
|
|
137
|
+
};
|
|
138
|
+
/** LLM provider + model. */
|
|
139
|
+
provider: string;
|
|
140
|
+
model: string;
|
|
141
|
+
/** Whether this binding came from cache (LLM not actually called). */
|
|
142
|
+
fromCache: boolean;
|
|
143
|
+
}
|
|
@@ -0,0 +1,17 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
/**
|
|
3
|
+
* LLM fallback types — v2.0.
|
|
4
|
+
*
|
|
5
|
+
* The LLM is invoked ONLY when bdd2pw's deterministic rule table
|
|
6
|
+
* (`src/transformers/stepMatcher.ts`) fails to match a step. The LLM's
|
|
7
|
+
* job is to produce a single `StepBinding` matching the existing IR
|
|
8
|
+
* shape. This is identical to what a hand-written rule would produce, so
|
|
9
|
+
* downstream emitters don't need to know an LLM was involved.
|
|
10
|
+
*
|
|
11
|
+
* Every LLM-generated binding is also appended to
|
|
12
|
+
* `<repo>/artefacts/candidate-rules.jsonl` so a separate offline pipeline
|
|
13
|
+
* can review and propose new deterministic rules. Auto-writing rules
|
|
14
|
+
* back into `stepMatcher.ts` is deferred to v2.1+ (see docs/SCOPE.md).
|
|
15
|
+
*/
|
|
16
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
17
|
+
//# sourceMappingURL=types.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"types.js","sourceRoot":"","sources":["../../src/llm/types.ts"],"names":[],"mappings":";AAAA;;;;;;;;;;;;;GAaG"}
|
package/dist/types.d.ts
CHANGED
|
@@ -125,6 +125,38 @@ export interface ScaffoldOptions {
|
|
|
125
125
|
* offline runs.
|
|
126
126
|
*/
|
|
127
127
|
snapshotFile?: string;
|
|
128
|
+
/**
|
|
129
|
+
* LLM fallback (v2.0+) — when a Gherkin step doesn't match any
|
|
130
|
+
* deterministic rule, defer to an LLM to produce the binding. Off by
|
|
131
|
+
* default. Every successful binding is appended to
|
|
132
|
+
* `<repo>/artefacts/candidate-rules.jsonl` for offline review (v2.0)
|
|
133
|
+
* or auto-rule-write (v2.1+, deferred).
|
|
134
|
+
*
|
|
135
|
+
* - `provider`: "anthropic" (only provider in v2.0). v2.1+ will add
|
|
136
|
+
* "openai" and "gemini". The legacy `llm` flag in scaffold options
|
|
137
|
+
* already accepts these strings; pass it through.
|
|
138
|
+
* - `model`: override the default model. Default for Anthropic is
|
|
139
|
+
* claude-sonnet-4-6.
|
|
140
|
+
* - `apiKey`: API key for the provider. Defaults to
|
|
141
|
+
* `process.env.ANTHROPIC_API_KEY` when omitted.
|
|
142
|
+
* - `governanceUrl`: ai-governance sidecar URL. Default
|
|
143
|
+
* http://localhost:4900. The sidecar's /sanitize endpoint scrubs
|
|
144
|
+
* every prompt before it leaves the perimeter (fail-closed).
|
|
145
|
+
* - `maxCalls`: max LLM calls per scaffold. Default 50.
|
|
146
|
+
* - `cachePath`: SQLite cache file. Default
|
|
147
|
+
* `<repo>/.bdd2pw/llm-cache.sqlite`. Pass ":memory:" for tests.
|
|
148
|
+
* - `skipGovernance`: ONLY for tests. When true, prompts skip the
|
|
149
|
+
* sidecar. Production runs MUST keep this off.
|
|
150
|
+
*/
|
|
151
|
+
llmConfig?: {
|
|
152
|
+
provider: "anthropic";
|
|
153
|
+
model?: string;
|
|
154
|
+
apiKey?: string;
|
|
155
|
+
governanceUrl?: string;
|
|
156
|
+
maxCalls?: number;
|
|
157
|
+
cachePath?: string;
|
|
158
|
+
skipGovernance?: boolean;
|
|
159
|
+
};
|
|
128
160
|
/**
|
|
129
161
|
* Enable self-healing locator integration (v1.1+).
|
|
130
162
|
*
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@vijaypjavvadi/bdd2pw",
|
|
3
|
-
"version": "
|
|
3
|
+
"version": "2.0.0",
|
|
4
4
|
"description": "Scaffold runnable Playwright TypeScript tests from Gherkin .feature files. Detects existing Page Objects, scans live pages via Microsoft Playwright MCP, emits POMs + specs, ready for execution. CLI + HTTP service. Optional governed LLM fallback (Anthropic / OpenAI / Gemini).",
|
|
5
5
|
"bin": {
|
|
6
6
|
"bdd2pw": "dist/cli.js"
|