@trusty-squire/mcp 1.1.6 → 1.1.7
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +34 -16
- package/dist/api-client.d.ts +11 -3
- package/dist/api-client.d.ts.map +1 -1
- package/dist/api-client.js +14 -4
- package/dist/api-client.js.map +1 -1
- package/dist/bot/browser.d.ts +19 -1
- package/dist/bot/browser.d.ts.map +1 -1
- package/dist/bot/browser.js +228 -30
- package/dist/bot/browser.js.map +1 -1
- package/dist/bot/near-text-hint.d.ts +7 -3
- package/dist/bot/near-text-hint.d.ts.map +1 -1
- package/dist/bot/near-text-hint.js +1 -2
- package/dist/bot/near-text-hint.js.map +1 -1
- package/dist/bot/operator-recipe.d.ts +694 -36
- package/dist/bot/operator-recipe.d.ts.map +1 -1
- package/dist/bot/operator-recipe.js +565 -43
- package/dist/bot/operator-recipe.js.map +1 -1
- package/dist/bot/pay-operator.d.ts +4 -2
- package/dist/bot/pay-operator.d.ts.map +1 -1
- package/dist/bot/pay-operator.js +173 -67
- package/dist/bot/pay-operator.js.map +1 -1
- package/dist/bot/promote-to-skill.d.ts +1 -0
- package/dist/bot/promote-to-skill.d.ts.map +1 -1
- package/dist/bot/promote-to-skill.js +20 -30
- package/dist/bot/promote-to-skill.js.map +1 -1
- package/dist/bot/provision-session.d.ts +44 -1
- package/dist/bot/provision-session.d.ts.map +1 -1
- package/dist/bot/provision-session.js +1300 -104
- package/dist/bot/provision-session.js.map +1 -1
- package/dist/eval/replay-harness/corpus.d.ts +7 -0
- package/dist/eval/replay-harness/corpus.d.ts.map +1 -0
- package/dist/eval/replay-harness/corpus.js +183 -0
- package/dist/eval/replay-harness/corpus.js.map +1 -0
- package/dist/eval/replay-harness/har-mutate.d.ts +36 -0
- package/dist/eval/replay-harness/har-mutate.d.ts.map +1 -0
- package/dist/eval/replay-harness/har-mutate.js +119 -0
- package/dist/eval/replay-harness/har-mutate.js.map +1 -0
- package/dist/eval/replay-harness/har-substrate.d.ts +16 -0
- package/dist/eval/replay-harness/har-substrate.d.ts.map +1 -0
- package/dist/eval/replay-harness/har-substrate.js +99 -0
- package/dist/eval/replay-harness/har-substrate.js.map +1 -0
- package/dist/eval/replay-harness/index.d.ts +8 -0
- package/dist/eval/replay-harness/index.d.ts.map +1 -0
- package/dist/eval/replay-harness/index.js +8 -0
- package/dist/eval/replay-harness/index.js.map +1 -0
- package/dist/eval/replay-harness/metrics.d.ts +9 -0
- package/dist/eval/replay-harness/metrics.d.ts.map +1 -0
- package/dist/eval/replay-harness/metrics.js +117 -0
- package/dist/eval/replay-harness/metrics.js.map +1 -0
- package/dist/eval/replay-harness/reporter.d.ts +4 -0
- package/dist/eval/replay-harness/reporter.d.ts.map +1 -0
- package/dist/eval/replay-harness/reporter.js +62 -0
- package/dist/eval/replay-harness/reporter.js.map +1 -0
- package/dist/eval/replay-harness/runner.d.ts +36 -0
- package/dist/eval/replay-harness/runner.d.ts.map +1 -0
- package/dist/eval/replay-harness/runner.js +167 -0
- package/dist/eval/replay-harness/runner.js.map +1 -0
- package/dist/eval/replay-harness/types.d.ts +135 -0
- package/dist/eval/replay-harness/types.d.ts.map +1 -0
- package/dist/eval/replay-harness/types.js +2 -0
- package/dist/eval/replay-harness/types.js.map +1 -0
- package/dist/server.d.ts.map +1 -1
- package/dist/server.js +1 -0
- package/dist/server.js.map +1 -1
- package/dist/tools/grant-app-access.js +1 -1
- package/dist/tools/grant-app-access.js.map +1 -1
- package/dist/tools/operate-pay.d.ts +10 -10
- package/dist/tools/operate-pay.d.ts.map +1 -1
- package/dist/tools/operate-pay.js +42 -16
- package/dist/tools/operate-pay.js.map +1 -1
- package/dist/tools/provision-drive.d.ts +165 -8
- package/dist/tools/provision-drive.d.ts.map +1 -1
- package/dist/tools/provision-drive.js +211 -40
- package/dist/tools/provision-drive.js.map +1 -1
- package/package.json +2 -1
|
@@ -0,0 +1,183 @@
|
|
|
1
|
+
import { existsSync, readFileSync, readdirSync } from "node:fs";
|
|
2
|
+
import { dirname, isAbsolute, join, resolve } from "node:path";
|
|
3
|
+
import { fileURLToPath } from "node:url";
|
|
4
|
+
const DEFAULT_CORPUS_DIR = resolve(dirname(fileURLToPath(import.meta.url)), "../../../../../corpus/shopping");
|
|
5
|
+
function isObject(value) {
|
|
6
|
+
return typeof value === "object" && value !== null && !Array.isArray(value);
|
|
7
|
+
}
|
|
8
|
+
function isNonNegativeNumber(value) {
|
|
9
|
+
return typeof value === "number" && Number.isFinite(value) && value >= 0;
|
|
10
|
+
}
|
|
11
|
+
function parseEndState(value, label) {
|
|
12
|
+
if (!isObject(value) || !Array.isArray(value.line_items)) {
|
|
13
|
+
throw new Error(`${label}: expected_end_state must contain line_items`);
|
|
14
|
+
}
|
|
15
|
+
const lineItems = value.line_items.map((item, index) => {
|
|
16
|
+
if (!isObject(item) ||
|
|
17
|
+
typeof item.title_contains !== "string" ||
|
|
18
|
+
!Number.isInteger(item.qty) ||
|
|
19
|
+
item.qty < 1) {
|
|
20
|
+
throw new Error(`${label}: invalid line_items[${index}]`);
|
|
21
|
+
}
|
|
22
|
+
return { title_contains: item.title_contains, qty: item.qty };
|
|
23
|
+
});
|
|
24
|
+
if (!Number.isInteger(value.total_cents) || value.total_cents < 0) {
|
|
25
|
+
throw new Error(`${label}: total_cents must be a non-negative integer`);
|
|
26
|
+
}
|
|
27
|
+
if (typeof value.reached !== "string" || value.reached.length === 0) {
|
|
28
|
+
throw new Error(`${label}: reached must be a non-empty string`);
|
|
29
|
+
}
|
|
30
|
+
return {
|
|
31
|
+
line_items: lineItems,
|
|
32
|
+
total_cents: value.total_cents,
|
|
33
|
+
reached: value.reached,
|
|
34
|
+
};
|
|
35
|
+
}
|
|
36
|
+
function parseBaseline(value, label) {
|
|
37
|
+
if (!isObject(value))
|
|
38
|
+
throw new Error(`${label}: cold_baseline is required`);
|
|
39
|
+
const endState = parseEndState(value.end_state, `${label}.cold_baseline.end_state`);
|
|
40
|
+
if (!isNonNegativeNumber(value.turns) ||
|
|
41
|
+
!isNonNegativeNumber(value.tokens) ||
|
|
42
|
+
!isNonNegativeNumber(value.wall_clock_ms)) {
|
|
43
|
+
throw new Error(`${label}: cold_baseline costs must be non-negative numbers`);
|
|
44
|
+
}
|
|
45
|
+
if (!isObject(value.provenance) ||
|
|
46
|
+
value.provenance.source !== "driver" ||
|
|
47
|
+
typeof value.provenance.driver !== "string" ||
|
|
48
|
+
value.provenance.driver.length === 0 ||
|
|
49
|
+
typeof value.provenance.model !== "string" ||
|
|
50
|
+
value.provenance.model.length === 0 ||
|
|
51
|
+
typeof value.provenance.recorded_at !== "string" ||
|
|
52
|
+
Number.isNaN(Date.parse(value.provenance.recorded_at)) ||
|
|
53
|
+
!Number.isInteger(value.provenance.browser_observations) ||
|
|
54
|
+
value.provenance.browser_observations < 1 ||
|
|
55
|
+
typeof value.provenance.evidence_sha256 !== "string" ||
|
|
56
|
+
!/^[a-f0-9]{64}$/.test(value.provenance.evidence_sha256) ||
|
|
57
|
+
(value.provenance.capture_policy !== "read-only-playwright-mcp-v2" &&
|
|
58
|
+
value.provenance.capture_policy !== "read-only-playwright-mcp-v3") ||
|
|
59
|
+
(endState.reached === "checkout_review" &&
|
|
60
|
+
value.provenance.capture_policy !== "read-only-playwright-mcp-v3")) {
|
|
61
|
+
throw new Error(`${label}: cold_baseline requires grounded browser provenance`);
|
|
62
|
+
}
|
|
63
|
+
return {
|
|
64
|
+
turns: value.turns,
|
|
65
|
+
tokens: value.tokens,
|
|
66
|
+
wall_clock_ms: value.wall_clock_ms,
|
|
67
|
+
end_state: endState,
|
|
68
|
+
provenance: {
|
|
69
|
+
source: "driver",
|
|
70
|
+
driver: value.provenance.driver,
|
|
71
|
+
model: value.provenance.model,
|
|
72
|
+
recorded_at: value.provenance.recorded_at,
|
|
73
|
+
browser_observations: value.provenance.browser_observations,
|
|
74
|
+
evidence_sha256: value.provenance.evidence_sha256,
|
|
75
|
+
capture_policy: value.provenance.capture_policy,
|
|
76
|
+
},
|
|
77
|
+
};
|
|
78
|
+
}
|
|
79
|
+
export function resolveShoppingCorpusDir() {
|
|
80
|
+
const configured = process.env.REPLAY_EVAL_CORPUS_DIR?.trim();
|
|
81
|
+
if (configured !== undefined && ["", "0", "off", "false"].includes(configured.toLowerCase())) {
|
|
82
|
+
return null;
|
|
83
|
+
}
|
|
84
|
+
const directory = configured ?? DEFAULT_CORPUS_DIR;
|
|
85
|
+
return existsSync(directory) ? directory : null;
|
|
86
|
+
}
|
|
87
|
+
export function parseTaskRecord(value, file) {
|
|
88
|
+
if (!isObject(value))
|
|
89
|
+
throw new Error(`${file}: task record must be an object`);
|
|
90
|
+
const requiredStrings = ["task_id", "domain", "entry_url", "har"];
|
|
91
|
+
for (const field of requiredStrings) {
|
|
92
|
+
if (typeof value[field] !== "string" || value[field].length === 0) {
|
|
93
|
+
throw new Error(`${file}: ${field} must be a non-empty string`);
|
|
94
|
+
}
|
|
95
|
+
}
|
|
96
|
+
if (value.verb !== "purchase")
|
|
97
|
+
throw new Error(`${file}: v1 supports verb=purchase only`);
|
|
98
|
+
if (value.bucket !== "repeat" && value.bucket !== "novel") {
|
|
99
|
+
throw new Error(`${file}: bucket must be repeat or novel`);
|
|
100
|
+
}
|
|
101
|
+
if (!isObject(value.params)) {
|
|
102
|
+
throw new Error(`${file}: params is required`);
|
|
103
|
+
}
|
|
104
|
+
const params = value.params;
|
|
105
|
+
if (!isObject(params.address)) {
|
|
106
|
+
throw new Error(`${file}: params.address is required`);
|
|
107
|
+
}
|
|
108
|
+
const address = params.address;
|
|
109
|
+
if (typeof params.product_query !== "string" ||
|
|
110
|
+
typeof params.card_ref !== "string" ||
|
|
111
|
+
typeof address.country !== "string" ||
|
|
112
|
+
typeof address.postal_code !== "string") {
|
|
113
|
+
throw new Error(`${file}: invalid params`);
|
|
114
|
+
}
|
|
115
|
+
if (!isObject(value.capture) ||
|
|
116
|
+
(value.capture.status !== "captured" && value.capture.status !== "skipped")) {
|
|
117
|
+
throw new Error(`${file}: capture status is required`);
|
|
118
|
+
}
|
|
119
|
+
const expectedEndState = parseEndState(value.expected_end_state, file);
|
|
120
|
+
const coldBaseline = parseBaseline(value.cold_baseline, file);
|
|
121
|
+
const task = {
|
|
122
|
+
task_id: value.task_id,
|
|
123
|
+
verb: "purchase",
|
|
124
|
+
domain: value.domain,
|
|
125
|
+
entry_url: value.entry_url,
|
|
126
|
+
params: {
|
|
127
|
+
product_query: params.product_query,
|
|
128
|
+
...(typeof params.product_variant_id === "string"
|
|
129
|
+
? { product_variant_id: params.product_variant_id }
|
|
130
|
+
: {}),
|
|
131
|
+
...(Number.isInteger(params.product_price_cents) &&
|
|
132
|
+
params.product_price_cents >= 0
|
|
133
|
+
? { product_price_cents: params.product_price_cents }
|
|
134
|
+
: {}),
|
|
135
|
+
address: {
|
|
136
|
+
country: address.country,
|
|
137
|
+
postal_code: address.postal_code,
|
|
138
|
+
...(typeof address.region === "string" ? { region: address.region } : {}),
|
|
139
|
+
},
|
|
140
|
+
card_ref: params.card_ref,
|
|
141
|
+
},
|
|
142
|
+
expected_end_state: expectedEndState,
|
|
143
|
+
har: value.har,
|
|
144
|
+
bucket: value.bucket,
|
|
145
|
+
cold_baseline: coldBaseline,
|
|
146
|
+
capture: {
|
|
147
|
+
status: value.capture.status,
|
|
148
|
+
...(typeof value.capture.captured_at === "string"
|
|
149
|
+
? { captured_at: value.capture.captured_at }
|
|
150
|
+
: {}),
|
|
151
|
+
...(typeof value.capture.skip_reason === "string"
|
|
152
|
+
? { skip_reason: value.capture.skip_reason }
|
|
153
|
+
: {}),
|
|
154
|
+
},
|
|
155
|
+
};
|
|
156
|
+
if (task.capture.status === "captured" && !existsSync(resolveHarPath(task, dirname(file)))) {
|
|
157
|
+
throw new Error(`${file}: captured HAR is missing (${task.har})`);
|
|
158
|
+
}
|
|
159
|
+
return task;
|
|
160
|
+
}
|
|
161
|
+
export function loadShoppingCorpus(directory = resolveShoppingCorpusDir()) {
|
|
162
|
+
if (directory === null)
|
|
163
|
+
return [];
|
|
164
|
+
return readdirSync(directory)
|
|
165
|
+
.filter((name) => name.endsWith(".json") && name !== "capture-log.json")
|
|
166
|
+
.sort()
|
|
167
|
+
.map((name) => {
|
|
168
|
+
const file = join(directory, name);
|
|
169
|
+
return parseTaskRecord(JSON.parse(readFileSync(file, "utf8")), file);
|
|
170
|
+
});
|
|
171
|
+
}
|
|
172
|
+
export function resolveHarPath(task, corpusDir) {
|
|
173
|
+
return isAbsolute(task.har) ? task.har : join(corpusDir, task.har);
|
|
174
|
+
}
|
|
175
|
+
export function endStatesMatch(actual, expected) {
|
|
176
|
+
if (actual.total_cents !== expected.total_cents || actual.reached !== expected.reached)
|
|
177
|
+
return false;
|
|
178
|
+
if (actual.line_items.length !== expected.line_items.length)
|
|
179
|
+
return false;
|
|
180
|
+
return expected.line_items.every((wanted) => actual.line_items.some((actualItem) => actualItem.qty === wanted.qty &&
|
|
181
|
+
actualItem.title_contains.toLowerCase().includes(wanted.title_contains.toLowerCase())));
|
|
182
|
+
}
|
|
183
|
+
//# sourceMappingURL=corpus.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"corpus.js","sourceRoot":"","sources":["../../../src/eval/replay-harness/corpus.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,36 @@
|
|
|
1
|
+
import type { DriftMutationName } from "./types.js";
|
|
2
|
+
interface HarContent {
|
|
3
|
+
text?: string;
|
|
4
|
+
encoding?: string;
|
|
5
|
+
mimeType?: string;
|
|
6
|
+
}
|
|
7
|
+
interface HarEntry {
|
|
8
|
+
request?: {
|
|
9
|
+
url?: string;
|
|
10
|
+
};
|
|
11
|
+
response?: {
|
|
12
|
+
content?: HarContent;
|
|
13
|
+
};
|
|
14
|
+
}
|
|
15
|
+
export interface HarFile {
|
|
16
|
+
log: {
|
|
17
|
+
entries: HarEntry[];
|
|
18
|
+
[key: string]: unknown;
|
|
19
|
+
};
|
|
20
|
+
[key: string]: unknown;
|
|
21
|
+
}
|
|
22
|
+
export interface MutationOptions {
|
|
23
|
+
expectedTotalCents?: number;
|
|
24
|
+
changedTotalCents?: number;
|
|
25
|
+
displayedPriceCents?: number;
|
|
26
|
+
}
|
|
27
|
+
export interface MutationResult {
|
|
28
|
+
har: HarFile;
|
|
29
|
+
mutation: DriftMutationName;
|
|
30
|
+
responses_changed: number;
|
|
31
|
+
replacements: number;
|
|
32
|
+
observed_total_cents?: number;
|
|
33
|
+
}
|
|
34
|
+
export declare function mutateHar(input: HarFile, mutation: DriftMutationName, options?: MutationOptions): MutationResult;
|
|
35
|
+
export {};
|
|
36
|
+
//# sourceMappingURL=har-mutate.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"har-mutate.d.ts","sourceRoot":"","sources":["../../../src/eval/replay-harness/har-mutate.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,iBAAiB,EAAE,MAAM,YAAY,CAAC;AAEpD,UAAU,UAAU;IAClB,IAAI,CAAC,EAAE,MAAM,CAAC;IACd,QAAQ,CAAC,EAAE,MAAM,CAAC;IAClB,QAAQ,CAAC,EAAE,MAAM,CAAC;CACnB;AAED,UAAU,QAAQ;IAChB,OAAO,CAAC,EAAE;QAAE,GAAG,CAAC,EAAE,MAAM,CAAA;KAAE,CAAC;IAC3B,QAAQ,CAAC,EAAE;QAAE,OAAO,CAAC,EAAE,UAAU,CAAA;KAAE,CAAC;CACrC;AAED,MAAM,WAAW,OAAO;IACtB,GAAG,EAAE;QAAE,OAAO,EAAE,QAAQ,EAAE,CAAC;QAAC,CAAC,GAAG,EAAE,MAAM,GAAG,OAAO,CAAA;KAAE,CAAC;IACrD,CAAC,GAAG,EAAE,MAAM,GAAG,OAAO,CAAC;CACxB;AAED,MAAM,WAAW,eAAe;IAC9B,kBAAkB,CAAC,EAAE,MAAM,CAAC;IAC5B,iBAAiB,CAAC,EAAE,MAAM,CAAC;IAC3B,mBAAmB,CAAC,EAAE,MAAM,CAAC;CAC9B;AAED,MAAM,WAAW,cAAc;IAC7B,GAAG,EAAE,OAAO,CAAC;IACb,QAAQ,EAAE,iBAAiB,CAAC;IAC5B,iBAAiB,EAAE,MAAM,CAAC;IAC1B,YAAY,EAAE,MAAM,CAAC;IACrB,oBAAoB,CAAC,EAAE,MAAM,CAAC;CAC/B;AAwHD,wBAAgB,SAAS,CACvB,KAAK,EAAE,OAAO,EACd,QAAQ,EAAE,iBAAiB,EAC3B,OAAO,GAAE,eAAoB,GAC5B,cAAc,CAyBhB"}
|
|
@@ -0,0 +1,119 @@
|
|
|
1
|
+
function decode(content) {
|
|
2
|
+
if (typeof content.text !== "string")
|
|
3
|
+
return null;
|
|
4
|
+
return content.encoding === "base64"
|
|
5
|
+
? Buffer.from(content.text, "base64").toString("utf8")
|
|
6
|
+
: content.text;
|
|
7
|
+
}
|
|
8
|
+
function encode(content, body) {
|
|
9
|
+
content.text = content.encoding === "base64" ? Buffer.from(body).toString("base64") : body;
|
|
10
|
+
}
|
|
11
|
+
function replaceFirst(body, pattern, replacement) {
|
|
12
|
+
if (!pattern.test(body))
|
|
13
|
+
return { body, replacements: 0 };
|
|
14
|
+
pattern.lastIndex = 0;
|
|
15
|
+
return { body: body.replace(pattern, replacement), replacements: 1 };
|
|
16
|
+
}
|
|
17
|
+
function moneyForms(cents) {
|
|
18
|
+
const dollars = cents / 100;
|
|
19
|
+
const forms = [`$${dollars.toFixed(2)}`];
|
|
20
|
+
if (cents % 100 === 0)
|
|
21
|
+
forms.push(`$${dollars.toFixed(0)}`);
|
|
22
|
+
return forms;
|
|
23
|
+
}
|
|
24
|
+
function escapeRegExp(value) {
|
|
25
|
+
return value.replace(/[.*+?^${}()|[\]\\]/g, "\\$&");
|
|
26
|
+
}
|
|
27
|
+
function mutateBody(body, mutation, options) {
|
|
28
|
+
if (mutation === "rename-button") {
|
|
29
|
+
const button = replaceFirst(body, /(<button\b[^>]*>[\s\S]{0,1000}?)(add\s+to\s+(?:cart|bag)|continue|choose)([\s\S]{0,1000}?<\/button>)/i, (_match, before, _label, after) => `${before}Purchase item${after}`);
|
|
30
|
+
if (button.replacements > 0)
|
|
31
|
+
return button;
|
|
32
|
+
return replaceFirst(body, /add\s+to\s+(?:cart|bag)|continue|choose/i, "Purchase item");
|
|
33
|
+
}
|
|
34
|
+
if (mutation === "swap-testid") {
|
|
35
|
+
const testId = replaceFirst(body, /data-testid=(['"])([^'"]+)\1/i, (_match, quote, value) => `data-testid=${quote}drifted-${value}${quote}`);
|
|
36
|
+
if (testId.replacements > 0)
|
|
37
|
+
return testId;
|
|
38
|
+
return replaceFirst(body, /\bid=(['"])([^'"]+)\1/i, (_match, quote, value) => `id=${quote}drifted-${value}${quote}`);
|
|
39
|
+
}
|
|
40
|
+
if (mutation === "remove-field") {
|
|
41
|
+
const required = replaceFirst(body, /<input\b(?=[^>]*\brequired\b)[^>]*>/i, "");
|
|
42
|
+
if (required.replacements > 0)
|
|
43
|
+
return required;
|
|
44
|
+
const checkoutField = replaceFirst(body, /<input\b(?=[^>]*\bname=(['"])(?:updates\[\]|quantity|checkout\[[^'"]+)\1)[^>]*>/i, "");
|
|
45
|
+
if (checkoutField.replacements > 0)
|
|
46
|
+
return checkoutField;
|
|
47
|
+
return replaceFirst(body, /<input\b[^>]*>/i, "");
|
|
48
|
+
}
|
|
49
|
+
if (mutation === "change-price") {
|
|
50
|
+
if (options.expectedTotalCents === undefined) {
|
|
51
|
+
throw new Error("change-price requires expectedTotalCents");
|
|
52
|
+
}
|
|
53
|
+
const displayed = options.displayedPriceCents ?? options.expectedTotalCents;
|
|
54
|
+
const changedDisplayed = displayed + 100;
|
|
55
|
+
const changedTotal = options.changedTotalCents ?? options.expectedTotalCents + 100;
|
|
56
|
+
let next = body;
|
|
57
|
+
let replacements = 0;
|
|
58
|
+
const oldForms = moneyForms(displayed);
|
|
59
|
+
const newForms = moneyForms(changedDisplayed);
|
|
60
|
+
for (const [index, oldForm] of oldForms.entries()) {
|
|
61
|
+
const replacement = newForms[index] ?? newForms[0] ?? String(changedDisplayed);
|
|
62
|
+
const result = replaceFirst(next, new RegExp(`${escapeRegExp(oldForm)}(?!\\d)`), replacement);
|
|
63
|
+
next = result.body;
|
|
64
|
+
replacements += result.replacements;
|
|
65
|
+
if (replacements > 0)
|
|
66
|
+
break;
|
|
67
|
+
}
|
|
68
|
+
if (replacements === 0) {
|
|
69
|
+
const centsResult = replaceFirst(next, new RegExp(`((?:total_price|totalPrice|price)\\s*[\":=]+\\s*)${displayed}(?!\\d)`), `$1${changedDisplayed}`);
|
|
70
|
+
next = centsResult.body;
|
|
71
|
+
replacements += centsResult.replacements;
|
|
72
|
+
}
|
|
73
|
+
return { body: next, replacements, observedTotalCents: changedTotal };
|
|
74
|
+
}
|
|
75
|
+
if (mutation === "out-of-stock") {
|
|
76
|
+
const availability = replaceFirst(body, /("available"\s*:\s*)true/i, "$1false");
|
|
77
|
+
if (availability.replacements > 0)
|
|
78
|
+
return availability;
|
|
79
|
+
const stockText = replaceFirst(body, /\bin stock\b/i, "Out of stock");
|
|
80
|
+
if (stockText.replacements > 0)
|
|
81
|
+
return stockText;
|
|
82
|
+
return replaceFirst(body, /\badd\s+to\s+cart\b/i, "Sold out");
|
|
83
|
+
}
|
|
84
|
+
const overlay = '<div data-replay-eval-overlay role="dialog" aria-modal="true">Store notice</div>';
|
|
85
|
+
const inserted = replaceFirst(body, /<\/body>/i, `${overlay}</body>`);
|
|
86
|
+
if (inserted.replacements > 0)
|
|
87
|
+
return inserted;
|
|
88
|
+
return { body: `${body}${overlay}`, replacements: 1 };
|
|
89
|
+
}
|
|
90
|
+
export function mutateHar(input, mutation, options = {}) {
|
|
91
|
+
const har = structuredClone(input);
|
|
92
|
+
let responsesChanged = 0;
|
|
93
|
+
let replacements = 0;
|
|
94
|
+
let observedTotalCents;
|
|
95
|
+
for (const entry of har.log.entries) {
|
|
96
|
+
const content = entry.response?.content;
|
|
97
|
+
if (content === undefined)
|
|
98
|
+
continue;
|
|
99
|
+
const body = decode(content);
|
|
100
|
+
if (body === null)
|
|
101
|
+
continue;
|
|
102
|
+
const changed = mutateBody(body, mutation, options);
|
|
103
|
+
if (changed.replacements === 0)
|
|
104
|
+
continue;
|
|
105
|
+
encode(content, changed.body);
|
|
106
|
+
responsesChanged += 1;
|
|
107
|
+
replacements += changed.replacements;
|
|
108
|
+
observedTotalCents = changed.observedTotalCents ?? observedTotalCents;
|
|
109
|
+
break;
|
|
110
|
+
}
|
|
111
|
+
return {
|
|
112
|
+
har,
|
|
113
|
+
mutation,
|
|
114
|
+
responses_changed: responsesChanged,
|
|
115
|
+
replacements,
|
|
116
|
+
...(observedTotalCents === undefined ? {} : { observed_total_cents: observedTotalCents }),
|
|
117
|
+
};
|
|
118
|
+
}
|
|
119
|
+
//# sourceMappingURL=har-mutate.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"har-mutate.js","sourceRoot":"","sources":["../../../src/eval/replay-harness/har-mutate.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,16 @@
|
|
|
1
|
+
import { type Page } from "playwright";
|
|
2
|
+
import type { ExpectedEndState, ShoppingTaskRecord } from "./types.js";
|
|
3
|
+
export interface ColdDriverResult {
|
|
4
|
+
turns: number;
|
|
5
|
+
tokens: number;
|
|
6
|
+
end_state: ExpectedEndState;
|
|
7
|
+
}
|
|
8
|
+
export interface LiveCheckoutResult extends ColdDriverResult {
|
|
9
|
+
wall_clock_ms: number;
|
|
10
|
+
}
|
|
11
|
+
export declare function assertLiveCheckoutEndState(task: ShoppingTaskRecord, actual: ExpectedEndState): void;
|
|
12
|
+
export declare function whitejadeCartPermalink(task: ShoppingTaskRecord): string;
|
|
13
|
+
export declare function recordFrozenDocumentHar(entryUrl: string, harPath: string): Promise<string>;
|
|
14
|
+
export declare function runLiveWhitejadeCheckout(task: ShoppingTaskRecord, drive: (page: Page) => Promise<ColdDriverResult>): Promise<LiveCheckoutResult>;
|
|
15
|
+
export declare function replayFrozenHar<T>(entryUrl: string, harPath: string, observe: (page: Page) => Promise<T>): Promise<T>;
|
|
16
|
+
//# sourceMappingURL=har-substrate.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"har-substrate.d.ts","sourceRoot":"","sources":["../../../src/eval/replay-harness/har-substrate.ts"],"names":[],"mappings":"AAGA,OAAO,EAAY,KAAK,IAAI,EAAE,MAAM,YAAY,CAAC;AAEjD,OAAO,KAAK,EAAE,gBAAgB,EAAE,kBAAkB,EAAE,MAAM,YAAY,CAAC;AAEvE,MAAM,WAAW,gBAAgB;IAC/B,KAAK,EAAE,MAAM,CAAC;IACd,MAAM,EAAE,MAAM,CAAC;IACf,SAAS,EAAE,gBAAgB,CAAC;CAC7B;AAED,MAAM,WAAW,kBAAmB,SAAQ,gBAAgB;IAC1D,aAAa,EAAE,MAAM,CAAC;CACvB;AAED,wBAAgB,0BAA0B,CACxC,IAAI,EAAE,kBAAkB,EACxB,MAAM,EAAE,gBAAgB,GACvB,IAAI,CAIN;AAED,wBAAgB,sBAAsB,CAAC,IAAI,EAAE,kBAAkB,GAAG,MAAM,CAKvE;AAaD,wBAAsB,uBAAuB,CAAC,QAAQ,EAAE,MAAM,EAAE,OAAO,EAAE,MAAM,GAAG,OAAO,CAAC,MAAM,CAAC,CAyBhG;AAMD,wBAAsB,wBAAwB,CAC5C,IAAI,EAAE,kBAAkB,EACxB,KAAK,EAAE,CAAC,IAAI,EAAE,IAAI,KAAK,OAAO,CAAC,gBAAgB,CAAC,GAC/C,OAAO,CAAC,kBAAkB,CAAC,CAuB7B;AAED,wBAAsB,eAAe,CAAC,CAAC,EACrC,QAAQ,EAAE,MAAM,EAChB,OAAO,EAAE,MAAM,EACf,OAAO,EAAE,CAAC,IAAI,EAAE,IAAI,KAAK,OAAO,CAAC,CAAC,CAAC,GAClC,OAAO,CAAC,CAAC,CAAC,CAYZ"}
|
|
@@ -0,0 +1,99 @@
|
|
|
1
|
+
import { mkdirSync } from "node:fs";
|
|
2
|
+
import { dirname } from "node:path";
|
|
3
|
+
import { performance } from "node:perf_hooks";
|
|
4
|
+
import { chromium } from "playwright";
|
|
5
|
+
import { endStatesMatch } from "./corpus.js";
|
|
6
|
+
export function assertLiveCheckoutEndState(task, actual) {
|
|
7
|
+
if (!endStatesMatch(actual, task.expected_end_state)) {
|
|
8
|
+
throw new Error(`${task.task_id}: live checkout did not reach its expected end state`);
|
|
9
|
+
}
|
|
10
|
+
}
|
|
11
|
+
export function whitejadeCartPermalink(task) {
|
|
12
|
+
if (task.domain !== "whitejade.xyz" || task.params.product_variant_id === undefined) {
|
|
13
|
+
throw new Error(`${task.task_id}: live checkout requires a whitejade product variant`);
|
|
14
|
+
}
|
|
15
|
+
return `https://whitejade.xyz/cart/${encodeURIComponent(task.params.product_variant_id)}:1`;
|
|
16
|
+
}
|
|
17
|
+
function assertStableHarEntry(entryUrl) {
|
|
18
|
+
const pathname = new URL(entryUrl).pathname.toLowerCase();
|
|
19
|
+
if (pathname === "/cart" || pathname.startsWith("/cart/") || pathname.startsWith("/checkout")) {
|
|
20
|
+
throw new Error("checkout/cart pages are live-only and must never be written to a HAR");
|
|
21
|
+
}
|
|
22
|
+
}
|
|
23
|
+
// Small live-seed helper. It records the navigation response through
|
|
24
|
+
// Playwright's native HAR writer while aborting non-document resources; the
|
|
25
|
+
// frozen replay runs with JavaScript disabled and the same missing-request
|
|
26
|
+
// policy, so a seed stays compact without a custom VCR layer.
|
|
27
|
+
export async function recordFrozenDocumentHar(entryUrl, harPath) {
|
|
28
|
+
assertStableHarEntry(entryUrl);
|
|
29
|
+
mkdirSync(dirname(harPath), { recursive: true });
|
|
30
|
+
const browser = await chromium.launch({ headless: true, args: ["--no-sandbox"] });
|
|
31
|
+
const context = await browser.newContext({
|
|
32
|
+
javaScriptEnabled: false,
|
|
33
|
+
recordHar: {
|
|
34
|
+
path: harPath,
|
|
35
|
+
content: "embed",
|
|
36
|
+
mode: "minimal",
|
|
37
|
+
urlFilter: entryUrl,
|
|
38
|
+
},
|
|
39
|
+
});
|
|
40
|
+
await context.route("**/*", async (route) => {
|
|
41
|
+
if (route.request().resourceType() === "document")
|
|
42
|
+
await route.continue();
|
|
43
|
+
else
|
|
44
|
+
await route.abort();
|
|
45
|
+
});
|
|
46
|
+
const page = await context.newPage();
|
|
47
|
+
try {
|
|
48
|
+
await page.goto(entryUrl, { waitUntil: "domcontentloaded", timeout: 60_000 });
|
|
49
|
+
return page.url();
|
|
50
|
+
}
|
|
51
|
+
finally {
|
|
52
|
+
await context.close();
|
|
53
|
+
await browser.close();
|
|
54
|
+
}
|
|
55
|
+
}
|
|
56
|
+
// Checkout is deliberately live-only. Shopify checkout URLs are session-keyed,
|
|
57
|
+
// so this path has no recordHar and installs no HAR route (especially no
|
|
58
|
+
// notFound="abort"). The supplied driver is the existing guarded operator/LLM
|
|
59
|
+
// path; the harness only measures it and checks its returned end state.
|
|
60
|
+
export async function runLiveWhitejadeCheckout(task, drive) {
|
|
61
|
+
const browser = await chromium.launch({ headless: true, args: ["--no-sandbox"] });
|
|
62
|
+
const context = await browser.newContext();
|
|
63
|
+
const page = await context.newPage();
|
|
64
|
+
const started = performance.now();
|
|
65
|
+
try {
|
|
66
|
+
await page.goto(whitejadeCartPermalink(task), {
|
|
67
|
+
waitUntil: "domcontentloaded",
|
|
68
|
+
timeout: 60_000,
|
|
69
|
+
});
|
|
70
|
+
if (!new URL(page.url()).pathname.startsWith("/checkouts/")) {
|
|
71
|
+
throw new Error(`${task.task_id}: whitejade did not enter live checkout`);
|
|
72
|
+
}
|
|
73
|
+
const result = await drive(page);
|
|
74
|
+
assertLiveCheckoutEndState(task, result.end_state);
|
|
75
|
+
return {
|
|
76
|
+
...result,
|
|
77
|
+
wall_clock_ms: Math.round(performance.now() - started),
|
|
78
|
+
};
|
|
79
|
+
}
|
|
80
|
+
finally {
|
|
81
|
+
await context.close();
|
|
82
|
+
await browser.close();
|
|
83
|
+
}
|
|
84
|
+
}
|
|
85
|
+
export async function replayFrozenHar(entryUrl, harPath, observe) {
|
|
86
|
+
const browser = await chromium.launch({ headless: true, args: ["--no-sandbox"] });
|
|
87
|
+
const context = await browser.newContext({ javaScriptEnabled: false });
|
|
88
|
+
const page = await context.newPage();
|
|
89
|
+
await page.routeFromHAR(harPath, { update: false, notFound: "abort" });
|
|
90
|
+
try {
|
|
91
|
+
await page.goto(entryUrl, { waitUntil: "domcontentloaded" });
|
|
92
|
+
return await observe(page);
|
|
93
|
+
}
|
|
94
|
+
finally {
|
|
95
|
+
await context.close();
|
|
96
|
+
await browser.close();
|
|
97
|
+
}
|
|
98
|
+
}
|
|
99
|
+
//# sourceMappingURL=har-substrate.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"har-substrate.js","sourceRoot":"","sources":["../../../src/eval/replay-harness/har-substrate.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../../src/eval/replay-harness/index.ts"],"names":[],"mappings":"AAAA,cAAc,aAAa,CAAC;AAC5B,cAAc,iBAAiB,CAAC;AAChC,cAAc,oBAAoB,CAAC;AACnC,cAAc,cAAc,CAAC;AAC7B,cAAc,eAAe,CAAC;AAC9B,cAAc,aAAa,CAAC;AAC5B,cAAc,YAAY,CAAC"}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"index.js","sourceRoot":"","sources":["../../../src/eval/replay-harness/index.ts"],"names":[],"mappings":"AAAA,cAAc,aAAa,CAAC;AAC5B,cAAc,iBAAiB,CAAC;AAChC,cAAc,oBAAoB,CAAC;AACnC,cAAc,cAAc,CAAC;AAC7B,cAAc,eAAe,CAAC;AAC9B,cAAc,aAAa,CAAC;AAC5B,cAAc,YAAY,CAAC"}
|
|
@@ -0,0 +1,9 @@
|
|
|
1
|
+
import type { DriftObservation, HarnessMetrics, HarnessReport, HarnessThresholds, TaskObservation } from "./types.js";
|
|
2
|
+
export declare const DEFAULT_THRESHOLDS: HarnessThresholds;
|
|
3
|
+
export declare function computeMetrics(tasks: TaskObservation[], drift: DriftObservation[]): HarnessMetrics;
|
|
4
|
+
export declare function buildHarnessReport(tasks: TaskObservation[], drift: DriftObservation[], options?: {
|
|
5
|
+
generatedAt?: string;
|
|
6
|
+
thresholds?: HarnessThresholds;
|
|
7
|
+
mode?: HarnessReport["mode"];
|
|
8
|
+
}): HarnessReport;
|
|
9
|
+
//# sourceMappingURL=metrics.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"metrics.d.ts","sourceRoot":"","sources":["../../../src/eval/replay-harness/metrics.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EACV,gBAAgB,EAChB,cAAc,EACd,aAAa,EACb,iBAAiB,EACjB,eAAe,EAChB,MAAM,YAAY,CAAC;AAEpB,eAAO,MAAM,kBAAkB,EAAE,iBAMhC,CAAC;AAkBF,wBAAgB,cAAc,CAC5B,KAAK,EAAE,eAAe,EAAE,EACxB,KAAK,EAAE,gBAAgB,EAAE,GACxB,cAAc,CAkDhB;AAED,wBAAgB,kBAAkB,CAChC,KAAK,EAAE,eAAe,EAAE,EACxB,KAAK,EAAE,gBAAgB,EAAE,EACzB,OAAO,GAAE;IACP,WAAW,CAAC,EAAE,MAAM,CAAC;IACrB,UAAU,CAAC,EAAE,iBAAiB,CAAC;IAC/B,IAAI,CAAC,EAAE,aAAa,CAAC,MAAM,CAAC,CAAC;CACzB,GACL,aAAa,CAoEf"}
|