personal-agent-benchmark 0.0.0-stage → 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/README.md +128 -2
- package/bin/pab.js +5 -0
- package/dist/src/browser.d.ts +29 -0
- package/dist/src/browser.js +37 -0
- package/dist/src/browser.js.map +1 -0
- package/dist/src/cli.d.ts +20 -0
- package/dist/src/cli.js +331 -0
- package/dist/src/cli.js.map +1 -0
- package/dist/src/core/archive.d.ts +49 -0
- package/dist/src/core/archive.js +213 -0
- package/dist/src/core/archive.js.map +1 -0
- package/dist/src/core/audit.d.ts +15 -0
- package/dist/src/core/audit.js +85 -0
- package/dist/src/core/audit.js.map +1 -0
- package/dist/src/core/bundle.d.ts +42 -0
- package/dist/src/core/bundle.js +80 -0
- package/dist/src/core/bundle.js.map +1 -0
- package/dist/src/core/lookup.d.ts +15 -0
- package/dist/src/core/lookup.js +82 -0
- package/dist/src/core/lookup.js.map +1 -0
- package/dist/src/core/normalize.d.ts +45 -0
- package/dist/src/core/normalize.js +143 -0
- package/dist/src/core/normalize.js.map +1 -0
- package/dist/src/core/rules.d.ts +38 -0
- package/dist/src/core/rules.js +187 -0
- package/dist/src/core/rules.js.map +1 -0
- package/dist/src/core/store.d.ts +26 -0
- package/dist/src/core/store.js +78 -0
- package/dist/src/core/store.js.map +1 -0
- package/dist/src/core/types.d.ts +125 -0
- package/dist/src/core/types.js +3 -0
- package/dist/src/core/types.js.map +1 -0
- package/dist/src/core/util.d.ts +21 -0
- package/dist/src/core/util.js +150 -0
- package/dist/src/core/util.js.map +1 -0
- package/dist/src/core/warc.d.ts +55 -0
- package/dist/src/core/warc.js +258 -0
- package/dist/src/core/warc.js.map +1 -0
- package/dist/src/core/writer.d.ts +26 -0
- package/dist/src/core/writer.js +119 -0
- package/dist/src/core/writer.js.map +1 -0
- package/dist/src/grading.d.ts +63 -0
- package/dist/src/grading.js +173 -0
- package/dist/src/grading.js.map +1 -0
- package/dist/src/judge.d.ts +25 -0
- package/dist/src/judge.js +119 -0
- package/dist/src/judge.js.map +1 -0
- package/dist/src/paths.d.ts +2 -0
- package/dist/src/paths.js +40 -0
- package/dist/src/paths.js.map +1 -0
- package/dist/src/replay/clock.d.ts +19 -0
- package/dist/src/replay/clock.js +60 -0
- package/dist/src/replay/clock.js.map +1 -0
- package/dist/src/replay/engine.d.ts +53 -0
- package/dist/src/replay/engine.js +280 -0
- package/dist/src/replay/engine.js.map +1 -0
- package/dist/src/replay/launcher.d.ts +36 -0
- package/dist/src/replay/launcher.js +163 -0
- package/dist/src/replay/launcher.js.map +1 -0
- package/dist/src/replay/whistle-plugin.d.ts +24 -0
- package/dist/src/replay/whistle-plugin.js +82 -0
- package/dist/src/replay/whistle-plugin.js.map +1 -0
- package/dist/src/report.d.ts +3 -0
- package/dist/src/report.js +143 -0
- package/dist/src/report.js.map +1 -0
- package/dist/src/scoring.d.ts +87 -0
- package/dist/src/scoring.js +232 -0
- package/dist/src/scoring.js.map +1 -0
- package/dist/src/tasks.d.ts +61 -0
- package/dist/src/tasks.js +152 -0
- package/dist/src/tasks.js.map +1 -0
- package/docs/bundle-format.md +114 -0
- package/docs/deploy.md +78 -0
- package/docs/grading.md +81 -0
- package/docs/site-rules.md +114 -0
- package/docs/tasks.md +63 -0
- package/package.json +121 -4
- package/plugins/whistle.bench-replay/index.js +1 -0
- package/plugins/whistle.bench-replay/package.json +7 -0
- package/sites/_default.yaml +80 -0
- package/sites/amazon.com.yaml +125 -0
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"writer.js","sourceRoot":"","sources":["../../../src/core/writer.ts"],"names":[],"mappings":";;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;AAAA,MAAY,EAAE,oCAAgB;AAC9B,MAAY,IAAI,sCAAkB;AAIlC,iCAAuE;AACvE,iCAAoC;AAsBpC,mGAAmG;AACnG,MAAM,YAAY,GAAG,CAAC,kBAAkB,EAAE,IAAI,CAAC,IAAI,CAAC,SAAS,EAAE,YAAY,CAAC,CAAC,CAAC;AAE9E;;;;GAIG;AACI,KAAK,sBAAsB,MAAc,EAAE,SAAqB,EAAE,CAAqB;IAC5F,IAAI,CAAC,SAAS,CAAC,MAAM;QAAE,MAAM,IAAI,KAAK,CAAC,uBAAuB,CAAC,CAAC;IAChE,SAAS,CAAC,OAAO,CAAC,CAAC,EAAE,EAAE,CAAC,EAAE,EAAE,CAAC,CAAC,EAAE,CAAC,EAAE,GAAG,GAAG,GAAG,MAAM,CAAC,CAAC,GAAG,CAAC,CAAC,CAAC,QAAQ,CAAC,CAAC,EAAE,GAAG,CAAC,CAAC,CAAC,CAAC;IAE7E,EAAE,CAAC,MAAM,CAAC,IAAI,CAAC,IAAI,CAAC,MAAM,CAAC,GAAG,EAAE,SAAS,CAAC,EAAE,EAAE,SAAS,EAAE,IAAI,EAAE,KAAK,EAAE,IAAI,EAAE,CAAC,CAAC;IAC9E,KAAK,MAAM,CAAC,IAAI,YAAY;QAAE,EAAE,CAAC,MAAM,CAAC,IAAI,CAAC,IAAI,CAAC,MAAM,CAAC,GAAG,EAAE,CAAC,CAAC,EAAE,EAAE,KAAK,EAAE,IAAI,EAAE,CAAC,CAAC;IACnF,MAAM,MAAM,GAAG,IAAI,iBAAU,CAAC,IAAI,CAAC,IAAI,CAAC,MAAM,CAAC,GAAG,EAAE,SAAS,EAAE,WAAW,CAAC,CAAC,CAAC;IAC7E,MAAM,aAAa,GAAG,IAAI,GAAG,EAAoB,CAAC;IAClD,MAAM,SAAS,GAAG,CAAC,CAAC,cAAc,IAAI,IAAI,CAAC;IAC3C,MAAM,OAAO,GAAY,EAAE,CAAC;IAC5B,IAAI,QAAQ,GAAG,CAAC,CAAC;IACjB,IAAI,KAAK,GAAG,CAAC,CAAC;IACd,KAAK,MAAM,EAAE,IAAI,SAAS,EAAE,CAAC;QAC3B,MAAM,MAAM,GAAG,IAAA,aAAM,EAAC,EAAE,CAAC,QAAQ,CAAC,CAAC;QACnC,MAAM,KAAK,GAAG,EAAE,CAAC,QAAQ,CAAC,MAAM,IAAI,SAAS,CAAC,CAAC,CAAC,aAAa,CAAC,GAAG,CAAC,MAAM,CAAC,CAAC,CAAC,CAAC,SAAS,CAAC;QACtF,MAAM,KAAK,GAAG,MAAM,MAAM,CAAC,aAAa,CAAC,EAAE,EAAE,KAAK,CAAC,CAAC,CAAC,EAAE,GAAG,EAAE,KAAK,CAAC,GAAG,EAAE,IAAI,EAAE,KAAK,CAAC,EAAE,EAAE,MAAM,EAAE,CAAC,CAAC,CAAC,SAAS,CAAC,CAAC;QAC7G,IAAI,KAAK;YAAE,QAAQ,EAAE,CAAC;aACjB,CAAC;YACJ,KAAK,IAAI,EAAE,CAAC,QAAQ,CAAC,MAAM,CAAC;YAC5B,IAAI,EAAE,CAAC,QAAQ,CAAC,MAAM,IAAI,SAAS;gBAAE,aAAa,CAAC,GAAG,CAAC,MAAM,EAAE,EAAE,CAAC,CAAC;QACrE,CAAC;QACD,OAAO,CAAC,IAAI,CAAC;YACX,EAAE,EAAE,EAAE,CAAC,EAAE;YACT,EAAE,EAAE,EAAE,CAAC,EAAE;YACT,MAAM,EAAE,EAAE,CAAC,MAAM;YACjB,GAAG,EAAE,EAAE,CAAC,GAAG;YACX,MAAM,EAAE,EAAE,CAAC,MAAM;YACjB,IAAI,EAAE,IAAA,aAAM,EAAC,EAAE,CAAC,WAAW,CAAC;YAC5B,YAAY,EAAE,EAAE,CAAC,YAAY;YAC7B,cAAc,EAAE,IAAA,aAAM,EAAC,EAAE,CAAC,UAAU,EAAE,cAAc,CAAC;YACrD,OAAO,EAAE,EAAE,CAAC,OAAO,IAAI,EAAE,CAAC,OAAO,CAAC,MAAM,CAAC,CAAC,CAAC,EAAE,CAAC,OAAO,CAAC,QAAQ,CAAC,QAAQ,CAAC,CAAC,CAAC,CAAC,SAAS;YACpF,MAAM;YACN,IAAI,EAAE,EAAE,CAAC,QAAQ,CAAC,MAAM;YACxB,SAAS,EAAE,KAAK,CAAC,GAAG,CAAC,MAAM;YAC3B,SAAS,EAAE,KAAK,CAAC,GAAG,CAAC,MAAM;YAC3B,UAAU,EAAE,KAAK,CAAC,IAAI,CAAC,MAAM;YAC7B,UAAU,EAAE,KAAK,CAAC,IAAI,CAAC,MAAM;YAC7B,SAAS,EAAE,KAAK,EAAE,EAAE;SACrB,CAAC,CAAC;IACL,CAAC;IACD,MAAM,CAAC,KAAK,EAAE,CAAC;IACf,IAAA,iBAAU,EAAC,MAAM,CAAC,WAAW,EAAE,OAAO,CAAC,CAAC;IAExC,MAAM,KAAK,GAAiB,CAAC,CAAC,KAAK,EAAE,MAAM;QACzC,CAAC,CAAC,CAAC,CAAC,KAAK;QACT,CAAC,CAAC,OAAO;aACJ,MAAM,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC,CAAC,CAAC,MAAM,KAAK,KAAK,IAAI,CAAC,CAAC,MAAM,KAAK,GAAG,IAAI,CAAC,CAAC,IAAI,KAAK,WAAW,IAAI,CAAC,CAAC,CAAC,YAAY,IAAI,UAAU,CAAC,KAAK,UAAU,CAAC;aAChI,GAAG,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC,CAAC,EAAE,EAAE,EAAE,CAAC,CAAC,EAAE,EAAE,GAAG,EAAE,CAAC,CAAC,GAAG,EAAE,EAAE,EAAE,CAAC,CAAC,EAAE,EAAE,CAAC,CAAC,CAAC;IACxD,MAAM,OAAO,GAAG,IAAI,GAAG,CAAC,OAAO,CAAC,MAAM,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC,CAAC,CAAC,MAAM,KAAK,KAAK,CAAC,CAAC,GAAG,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC,CAAC,CAAC,GAAG,CAAC,CAAC,CAAC;IACrF,MAAM,SAAS,GAAG,IAAI,GAAG,CAAC,OAAO,CAAC,MAAM,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC,CAAC,CAAC,MAAM,KAAK,KAAK,CAAC,CAAC,GAAG,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC,CAAC,CAAC,GAAG,CAAC,CAAC,CAAC;IACvF,KAAK,MAAM,CAAC,IAAI,KAAK;QAAE,CAAC,CAAC,OAAO,GAAG,OAAO,CAAC,GAAG,CAAC,CAAC,CAAC,GAAG,CAAC,CAAC,CAAC,CAAC,KAAK,CAAC,CAAC,CAAC,SAAS,CAAC,GAAG,CAAC,CAAC,CAAC,GAAG,CAAC,CAAC,CAAC,CAAC,MAAM,CAAC,CAAC,CAAC,MAAM,CAAC;IACvG,IAAA,iBAAU,EAAC,MAAM,CAAC,SAAS,EAAE,KAAK,CAAC,CAAC;IAEpC,MAAM,QAAQ,GAA2B,EAAE,CAAC;IAC5C,KAAK,MAAM,CAAC,IAAI,KAAK,CAAC,MAAM,CAAC,CAAC,EAAE,EAAE,EAAE,CAAC,EAAE,CAAC,IAAI,KAAK,iBAAiB,CAAC,EAAE,CAAC;QACpE,MAAM,IAAI,GAAG,IAAI,GAAG,CAAC,CAAC,CAAC,GAAG,CAAC,CAAC,QAAQ,CAAC;QACrC,QAAQ,CAAC,CAAC,CAAC,KAAK,CAAC,OAAO,CAAC,IAAI,CAAC,EAAE,IAAI,IAAI,IAAI,CAAC,KAAK,CAAC,CAAC,GAAG,CAAC;IAC1D,CAAC;IACD,MAAM,QAAQ,GAAa;QACzB,OAAO,EAAE,CAAC,CAAC,IAAI,CAAC,OAAO;QACvB,aAAa,EAAE,OAAO,CAAC,CAAC,CAAC,CAAC,EAAE;QAC5B,WAAW,EAAE,OAAO,CAAC,OAAO,CAAC,MAAM,GAAG,CAAC,CAAC,CAAC,EAAE;QAC3C,SAAS,EAAE,QAAQ;QACnB,MAAM,EAAE,CAAC,CAAC,IAAI,CAAC,MAAM;QACrB,QAAQ,EAAE,CAAC,CAAC,IAAI,CAAC,QAAQ;KAC1B,CAAC;IACF,IAAA,gBAAS,EAAC,MAAM,CAAC,YAAY,EAAE,QAAQ,CAAC,CAAC;IACzC,OAAO,EAAE,OAAO,EAAE,QAAQ,EAAE,QAAQ,EAAE,KAAK,EAAE,CAAC;AAChD,CAAC"}
|
|
@@ -0,0 +1,63 @@
|
|
|
1
|
+
import type { RecordStore } from './core/store';
|
|
2
|
+
/**
|
|
3
|
+
* tasks/<id>/grading.yaml: how an agent's answer to the task is scored (docs/grading.md).
|
|
4
|
+
* An LLM extracts fields from the answer and answers yes/no questions; the program compares the
|
|
5
|
+
* extracted fields with the expected ones and checks the requests the agent made in the replay.
|
|
6
|
+
*/
|
|
7
|
+
export type FieldType = 'money' | 'number' | 'text' | 'boolean';
|
|
8
|
+
export interface Grading {
|
|
9
|
+
/** Fields an LLM extracts from the agent's answer. */
|
|
10
|
+
extract?: Record<string, {
|
|
11
|
+
type: FieldType;
|
|
12
|
+
description?: string;
|
|
13
|
+
}>;
|
|
14
|
+
/** Compared by the program; any failure scores 0. */
|
|
15
|
+
require?: Requirement[];
|
|
16
|
+
/** Yes/no questions an LLM answers about the answer. */
|
|
17
|
+
checks?: Check[];
|
|
18
|
+
/** Requests the agent must or must not have made, from the replay log. */
|
|
19
|
+
trace?: TraceRule[];
|
|
20
|
+
}
|
|
21
|
+
export interface Requirement {
|
|
22
|
+
field: string;
|
|
23
|
+
equals?: number | string | boolean;
|
|
24
|
+
min?: number;
|
|
25
|
+
max?: number;
|
|
26
|
+
one_of?: (string | number)[];
|
|
27
|
+
contains?: string;
|
|
28
|
+
/** For numbers: how far the answer may be from equals (default 0.01). */
|
|
29
|
+
tolerance?: number;
|
|
30
|
+
/** Where the expected value appears in the recording: a page and its text as shown there. */
|
|
31
|
+
source?: {
|
|
32
|
+
url: string;
|
|
33
|
+
text: string;
|
|
34
|
+
};
|
|
35
|
+
}
|
|
36
|
+
export interface Check {
|
|
37
|
+
id: string;
|
|
38
|
+
question: string;
|
|
39
|
+
/** A "no" scores 0 (the default when no weight is given). */
|
|
40
|
+
required?: boolean;
|
|
41
|
+
/** Partial credit instead: counts toward the score once every required item passed. */
|
|
42
|
+
weight?: number;
|
|
43
|
+
}
|
|
44
|
+
export interface TraceRule {
|
|
45
|
+
id: string;
|
|
46
|
+
must?: RequestMatch;
|
|
47
|
+
must_not?: RequestMatch;
|
|
48
|
+
}
|
|
49
|
+
export interface RequestMatch {
|
|
50
|
+
method?: string;
|
|
51
|
+
/** Glob over the full URL; * matches anything. */
|
|
52
|
+
url: string;
|
|
53
|
+
/** Only requests the replay answered from the recording (not misses). */
|
|
54
|
+
hit?: boolean;
|
|
55
|
+
}
|
|
56
|
+
export declare function parseGrading(text: string): Grading;
|
|
57
|
+
/** What is wrong with a grading, as sentences; empty when it can be used. */
|
|
58
|
+
export declare function validateGrading(g: Grading): string[];
|
|
59
|
+
/**
|
|
60
|
+
* Expected values whose source page is not in the recording, or does not show the text: the
|
|
61
|
+
* answer could not have been read during replay.
|
|
62
|
+
*/
|
|
63
|
+
export declare function checkSources(g: Grading, store: RecordStore): Promise<string[]>;
|
|
@@ -0,0 +1,173 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
var __createBinding = (this && this.__createBinding) || (Object.create ? (function(o, m, k, k2) {
|
|
3
|
+
if (k2 === undefined) k2 = k;
|
|
4
|
+
var desc = Object.getOwnPropertyDescriptor(m, k);
|
|
5
|
+
if (!desc || ("get" in desc ? !m.__esModule : desc.writable || desc.configurable)) {
|
|
6
|
+
desc = { enumerable: true, get: function() { return m[k]; } };
|
|
7
|
+
}
|
|
8
|
+
Object.defineProperty(o, k2, desc);
|
|
9
|
+
}) : (function(o, m, k, k2) {
|
|
10
|
+
if (k2 === undefined) k2 = k;
|
|
11
|
+
o[k2] = m[k];
|
|
12
|
+
}));
|
|
13
|
+
var __setModuleDefault = (this && this.__setModuleDefault) || (Object.create ? (function(o, v) {
|
|
14
|
+
Object.defineProperty(o, "default", { enumerable: true, value: v });
|
|
15
|
+
}) : function(o, v) {
|
|
16
|
+
o["default"] = v;
|
|
17
|
+
});
|
|
18
|
+
var __importStar = (this && this.__importStar) || (function () {
|
|
19
|
+
var ownKeys = function(o) {
|
|
20
|
+
ownKeys = Object.getOwnPropertyNames || function (o) {
|
|
21
|
+
var ar = [];
|
|
22
|
+
for (var k in o) if (Object.prototype.hasOwnProperty.call(o, k)) ar[ar.length] = k;
|
|
23
|
+
return ar;
|
|
24
|
+
};
|
|
25
|
+
return ownKeys(o);
|
|
26
|
+
};
|
|
27
|
+
return function (mod) {
|
|
28
|
+
if (mod && mod.__esModule) return mod;
|
|
29
|
+
var result = {};
|
|
30
|
+
if (mod != null) for (var k = ownKeys(mod), i = 0; i < k.length; i++) if (k[i] !== "default") __createBinding(result, mod, k[i]);
|
|
31
|
+
__setModuleDefault(result, mod);
|
|
32
|
+
return result;
|
|
33
|
+
};
|
|
34
|
+
})();
|
|
35
|
+
var __importDefault = (this && this.__importDefault) || function (mod) {
|
|
36
|
+
return (mod && mod.__esModule) ? mod : { "default": mod };
|
|
37
|
+
};
|
|
38
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
39
|
+
exports.parseGrading = parseGrading;
|
|
40
|
+
exports.validateGrading = validateGrading;
|
|
41
|
+
exports.checkSources = checkSources;
|
|
42
|
+
const cheerio = __importStar(require("cheerio"));
|
|
43
|
+
const yaml_1 = __importDefault(require("yaml"));
|
|
44
|
+
const lookup_1 = require("./core/lookup");
|
|
45
|
+
const normalize_1 = require("./core/normalize");
|
|
46
|
+
const TYPES = ['money', 'number', 'text', 'boolean'];
|
|
47
|
+
const KEYS = ['extract', 'require', 'checks', 'trace'];
|
|
48
|
+
const ID = /^[a-z][a-z0-9_]*$/;
|
|
49
|
+
function parseGrading(text) {
|
|
50
|
+
const value = yaml_1.default.parse(text);
|
|
51
|
+
if (!value || typeof value !== 'object' || Array.isArray(value))
|
|
52
|
+
throw new Error('grading.yaml must be a mapping');
|
|
53
|
+
return value;
|
|
54
|
+
}
|
|
55
|
+
/** What is wrong with a grading, as sentences; empty when it can be used. */
|
|
56
|
+
function validateGrading(g) {
|
|
57
|
+
const errors = [];
|
|
58
|
+
for (const k of Object.keys(g))
|
|
59
|
+
if (!KEYS.includes(k))
|
|
60
|
+
errors.push(`unknown key "${k}" (expected ${KEYS.join(', ')})`);
|
|
61
|
+
const fields = g.extract ?? {};
|
|
62
|
+
if (typeof fields !== 'object' || Array.isArray(fields))
|
|
63
|
+
errors.push('extract must map field names to { type, description }');
|
|
64
|
+
for (const [name, f] of Object.entries(fields)) {
|
|
65
|
+
if (!ID.test(name))
|
|
66
|
+
errors.push(`extract: field name "${name}" must be lowercase letters, digits and _`);
|
|
67
|
+
if (!f || !TYPES.includes(f.type))
|
|
68
|
+
errors.push(`extract.${name}: type must be one of ${TYPES.join(', ')}`);
|
|
69
|
+
if (f?.description !== undefined && typeof f.description !== 'string')
|
|
70
|
+
errors.push(`extract.${name}: description must be text (quote it if it has a colon)`);
|
|
71
|
+
}
|
|
72
|
+
const list = (key, v) => {
|
|
73
|
+
if (v !== undefined && !Array.isArray(v))
|
|
74
|
+
errors.push(`${key} must be a list`);
|
|
75
|
+
return Array.isArray(v) ? v : [];
|
|
76
|
+
};
|
|
77
|
+
const require = list('require', g.require);
|
|
78
|
+
const checks = list('checks', g.checks);
|
|
79
|
+
const trace = list('trace', g.trace);
|
|
80
|
+
if (!require.length && !checks.length && !trace.length)
|
|
81
|
+
errors.push('nothing to grade: add require, checks or trace');
|
|
82
|
+
require.forEach((r, i) => {
|
|
83
|
+
const at = `require[${i}]`;
|
|
84
|
+
const f = fields[r?.field];
|
|
85
|
+
if (!f)
|
|
86
|
+
return errors.push(`${at}: field "${r?.field}" is not in extract`);
|
|
87
|
+
const tests = ['equals', 'min', 'max', 'one_of', 'contains'].filter((k) => r[k] !== undefined);
|
|
88
|
+
if (!tests.length)
|
|
89
|
+
errors.push(`${at}: give equals, min/max, one_of or contains`);
|
|
90
|
+
if (r.equals !== undefined && (r.min !== undefined || r.max !== undefined || r.one_of !== undefined || r.contains !== undefined))
|
|
91
|
+
errors.push(`${at}: equals cannot be combined with other tests`);
|
|
92
|
+
const numeric = f.type === 'money' || f.type === 'number';
|
|
93
|
+
if (numeric) {
|
|
94
|
+
for (const k of ['equals', 'min', 'max'])
|
|
95
|
+
if (r[k] !== undefined && typeof r[k] !== 'number')
|
|
96
|
+
errors.push(`${at}: ${k} must be a number for a ${f.type} field`);
|
|
97
|
+
if (r.contains !== undefined)
|
|
98
|
+
errors.push(`${at}: contains is for text fields`);
|
|
99
|
+
if (r.tolerance !== undefined && !(typeof r.tolerance === 'number' && r.tolerance >= 0))
|
|
100
|
+
errors.push(`${at}: tolerance must be a number of 0 or more`);
|
|
101
|
+
}
|
|
102
|
+
else {
|
|
103
|
+
if (r.min !== undefined || r.max !== undefined || r.tolerance !== undefined)
|
|
104
|
+
errors.push(`${at}: min, max and tolerance are for number and money fields`);
|
|
105
|
+
if (f.type === 'boolean' && (typeof r.equals !== 'boolean' || tests.length > 1))
|
|
106
|
+
errors.push(`${at}: a boolean field takes equals: true or false`);
|
|
107
|
+
if (f.type === 'text' && r.equals !== undefined && typeof r.equals !== 'string')
|
|
108
|
+
errors.push(`${at}: equals must be text for a text field`);
|
|
109
|
+
}
|
|
110
|
+
if (r.one_of !== undefined && (!Array.isArray(r.one_of) || !r.one_of.length))
|
|
111
|
+
errors.push(`${at}: one_of must be a non-empty list`);
|
|
112
|
+
if (r.source !== undefined && !(typeof r.source?.url === 'string' && /^https?:\/\//.test(r.source.url) && typeof r.source.text === 'string' && r.source.text.trim()))
|
|
113
|
+
errors.push(`${at}: source needs an http(s) url and the text shown there`);
|
|
114
|
+
});
|
|
115
|
+
const ids = new Set();
|
|
116
|
+
const id = (at, v) => {
|
|
117
|
+
if (typeof v !== 'string' || !ID.test(v))
|
|
118
|
+
errors.push(`${at}: id must be lowercase letters, digits and _`);
|
|
119
|
+
else if (ids.has(v))
|
|
120
|
+
errors.push(`${at}: id "${v}" is used twice`);
|
|
121
|
+
else
|
|
122
|
+
ids.add(v);
|
|
123
|
+
};
|
|
124
|
+
checks.forEach((c, i) => {
|
|
125
|
+
const at = `checks[${i}]`;
|
|
126
|
+
id(at, c?.id);
|
|
127
|
+
if (typeof c?.question !== 'string' || !c.question.trim())
|
|
128
|
+
errors.push(`${at}: question is missing`);
|
|
129
|
+
if (c?.weight !== undefined && !(typeof c.weight === 'number' && c.weight > 0))
|
|
130
|
+
errors.push(`${at}: weight must be a positive number`);
|
|
131
|
+
if (c?.weight !== undefined && c.required)
|
|
132
|
+
errors.push(`${at}: a check is either required or weighted`);
|
|
133
|
+
});
|
|
134
|
+
trace.forEach((t, i) => {
|
|
135
|
+
const at = `trace[${i}]`;
|
|
136
|
+
id(at, t?.id);
|
|
137
|
+
const rules = [t?.must, t?.must_not].filter(Boolean);
|
|
138
|
+
if (rules.length !== 1)
|
|
139
|
+
errors.push(`${at}: give exactly one of must or must_not`);
|
|
140
|
+
for (const m of rules)
|
|
141
|
+
if (typeof m?.url !== 'string' || !m.url)
|
|
142
|
+
errors.push(`${at}: url is missing`);
|
|
143
|
+
});
|
|
144
|
+
return errors;
|
|
145
|
+
}
|
|
146
|
+
/**
|
|
147
|
+
* Expected values whose source page is not in the recording, or does not show the text: the
|
|
148
|
+
* answer could not have been read during replay.
|
|
149
|
+
*/
|
|
150
|
+
async function checkSources(g, store) {
|
|
151
|
+
const errors = [];
|
|
152
|
+
for (const [i, r] of (g.require ?? []).entries()) {
|
|
153
|
+
if (!r.source)
|
|
154
|
+
continue;
|
|
155
|
+
const norm = (0, normalize_1.normalizeRequest)({ method: 'GET', url: r.source.url }, store.rules);
|
|
156
|
+
// the copy replay would answer with (the last one for carts and checkouts)
|
|
157
|
+
const ix = (0, lookup_1.lookup)(store, norm)?.ix ?? store.findByUrl(r.source.url);
|
|
158
|
+
if (!ix) {
|
|
159
|
+
errors.push(`require[${i}] (${r.field}): ${r.source.url} is not in the recording`);
|
|
160
|
+
continue;
|
|
161
|
+
}
|
|
162
|
+
// the text a page shows, or the response itself: prices are often filled in by page scripts
|
|
163
|
+
// from data in the response, such as "currentPrice":228
|
|
164
|
+
const body = (await store.response(ix)).body.toString('utf8');
|
|
165
|
+
const shown = /html/i.test(ix.entry.mime) ? cheerio.load(body)('body').text() : '';
|
|
166
|
+
const want = squash(r.source.text);
|
|
167
|
+
if (!squash(shown).includes(want) && !squash(body).includes(want))
|
|
168
|
+
errors.push(`require[${i}] (${r.field}): "${r.source.text}" does not appear on ${r.source.url}`);
|
|
169
|
+
}
|
|
170
|
+
return errors;
|
|
171
|
+
}
|
|
172
|
+
const squash = (s) => s.replace(/\s+/g, ' ').trim().toLowerCase();
|
|
173
|
+
//# sourceMappingURL=grading.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"grading.js","sourceRoot":"","sources":["../../src/grading.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,25 @@
|
|
|
1
|
+
/** The LLM that reads an agent's answer for grading (docs/grading.md). */
|
|
2
|
+
export interface Judge {
|
|
3
|
+
/** How the model is reached ("api" or "claude-cli"), recorded with each result. */
|
|
4
|
+
readonly via: string;
|
|
5
|
+
readonly model: string;
|
|
6
|
+
/** Asks once; the reply follows `schema`. Returns it and the model that answered. */
|
|
7
|
+
ask(req: JudgeRequest): Promise<{
|
|
8
|
+
output: unknown;
|
|
9
|
+
model: string;
|
|
10
|
+
}>;
|
|
11
|
+
}
|
|
12
|
+
export interface JudgeRequest {
|
|
13
|
+
system: string;
|
|
14
|
+
prompt: string;
|
|
15
|
+
schema: Record<string, unknown>;
|
|
16
|
+
}
|
|
17
|
+
export declare const DEFAULT_MODEL = "claude-opus-5-5";
|
|
18
|
+
/**
|
|
19
|
+
* "api" (the Claude API, with ANTHROPIC_API_KEY or ANTHROPIC_AUTH_TOKEN) or "cli" (a local
|
|
20
|
+
* `claude` that is signed in). Without a choice: the API when a key is set, otherwise the CLI.
|
|
21
|
+
*/
|
|
22
|
+
export declare function pickJudge(kind?: string, model?: string): Judge;
|
|
23
|
+
export declare function apiJudge(model?: string): Judge;
|
|
24
|
+
/** `claude -p` with no tools, run outside any project so no project instructions are read. */
|
|
25
|
+
export declare function cliJudge(model?: string, bin?: string): Judge;
|
|
@@ -0,0 +1,119 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
var __createBinding = (this && this.__createBinding) || (Object.create ? (function(o, m, k, k2) {
|
|
3
|
+
if (k2 === undefined) k2 = k;
|
|
4
|
+
var desc = Object.getOwnPropertyDescriptor(m, k);
|
|
5
|
+
if (!desc || ("get" in desc ? !m.__esModule : desc.writable || desc.configurable)) {
|
|
6
|
+
desc = { enumerable: true, get: function() { return m[k]; } };
|
|
7
|
+
}
|
|
8
|
+
Object.defineProperty(o, k2, desc);
|
|
9
|
+
}) : (function(o, m, k, k2) {
|
|
10
|
+
if (k2 === undefined) k2 = k;
|
|
11
|
+
o[k2] = m[k];
|
|
12
|
+
}));
|
|
13
|
+
var __setModuleDefault = (this && this.__setModuleDefault) || (Object.create ? (function(o, v) {
|
|
14
|
+
Object.defineProperty(o, "default", { enumerable: true, value: v });
|
|
15
|
+
}) : function(o, v) {
|
|
16
|
+
o["default"] = v;
|
|
17
|
+
});
|
|
18
|
+
var __importStar = (this && this.__importStar) || (function () {
|
|
19
|
+
var ownKeys = function(o) {
|
|
20
|
+
ownKeys = Object.getOwnPropertyNames || function (o) {
|
|
21
|
+
var ar = [];
|
|
22
|
+
for (var k in o) if (Object.prototype.hasOwnProperty.call(o, k)) ar[ar.length] = k;
|
|
23
|
+
return ar;
|
|
24
|
+
};
|
|
25
|
+
return ownKeys(o);
|
|
26
|
+
};
|
|
27
|
+
return function (mod) {
|
|
28
|
+
if (mod && mod.__esModule) return mod;
|
|
29
|
+
var result = {};
|
|
30
|
+
if (mod != null) for (var k = ownKeys(mod), i = 0; i < k.length; i++) if (k[i] !== "default") __createBinding(result, mod, k[i]);
|
|
31
|
+
__setModuleDefault(result, mod);
|
|
32
|
+
return result;
|
|
33
|
+
};
|
|
34
|
+
})();
|
|
35
|
+
var __importDefault = (this && this.__importDefault) || function (mod) {
|
|
36
|
+
return (mod && mod.__esModule) ? mod : { "default": mod };
|
|
37
|
+
};
|
|
38
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
39
|
+
exports.DEFAULT_MODEL = void 0;
|
|
40
|
+
exports.pickJudge = pickJudge;
|
|
41
|
+
exports.apiJudge = apiJudge;
|
|
42
|
+
exports.cliJudge = cliJudge;
|
|
43
|
+
const node_child_process_1 = require("node:child_process");
|
|
44
|
+
const os = __importStar(require("node:os"));
|
|
45
|
+
const sdk_1 = __importDefault(require("@anthropic-ai/sdk"));
|
|
46
|
+
exports.DEFAULT_MODEL = 'claude-opus-5-5';
|
|
47
|
+
/**
|
|
48
|
+
* "api" (the Claude API, with ANTHROPIC_API_KEY or ANTHROPIC_AUTH_TOKEN) or "cli" (a local
|
|
49
|
+
* `claude` that is signed in). Without a choice: the API when a key is set, otherwise the CLI.
|
|
50
|
+
*/
|
|
51
|
+
function pickJudge(kind, model = exports.DEFAULT_MODEL) {
|
|
52
|
+
const k = kind ?? (process.env.ANTHROPIC_API_KEY || process.env.ANTHROPIC_AUTH_TOKEN ? 'api' : 'cli');
|
|
53
|
+
if (k === 'api')
|
|
54
|
+
return apiJudge(model);
|
|
55
|
+
if (k === 'cli')
|
|
56
|
+
return cliJudge(model);
|
|
57
|
+
throw new Error(`unknown judge "${kind}" (api or cli)`);
|
|
58
|
+
}
|
|
59
|
+
function apiJudge(model = exports.DEFAULT_MODEL) {
|
|
60
|
+
const client = new sdk_1.default();
|
|
61
|
+
return {
|
|
62
|
+
via: 'api',
|
|
63
|
+
model,
|
|
64
|
+
async ask({ system, prompt, schema }) {
|
|
65
|
+
const msg = await client.beta.messages
|
|
66
|
+
.stream({
|
|
67
|
+
model,
|
|
68
|
+
max_tokens: 16000,
|
|
69
|
+
system,
|
|
70
|
+
messages: [{ role: 'user', content: prompt }],
|
|
71
|
+
output_config: { effort: 'medium', format: { type: 'json_schema', schema } },
|
|
72
|
+
// a declined request is re-run on Anthropic's recommended fallback model
|
|
73
|
+
betas: ['server-side-fallback-2026-07-01'],
|
|
74
|
+
fallbacks: 'default',
|
|
75
|
+
})
|
|
76
|
+
.finalMessage();
|
|
77
|
+
if (msg.stop_reason === 'refusal')
|
|
78
|
+
throw new Error(`the grader declined: ${msg.stop_details?.explanation ?? 'no reason given'}`);
|
|
79
|
+
if (msg.stop_reason === 'max_tokens')
|
|
80
|
+
throw new Error('the grader ran out of output tokens');
|
|
81
|
+
const text = msg.content.flatMap((b) => (b.type === 'text' ? [b.text] : [])).join('');
|
|
82
|
+
return { output: JSON.parse(text), model: msg.model };
|
|
83
|
+
},
|
|
84
|
+
};
|
|
85
|
+
}
|
|
86
|
+
/** `claude -p` with no tools, run outside any project so no project instructions are read. */
|
|
87
|
+
function cliJudge(model = exports.DEFAULT_MODEL, bin = process.env.PAB_CLAUDE_BIN ?? 'claude') {
|
|
88
|
+
return {
|
|
89
|
+
via: 'claude-cli',
|
|
90
|
+
model,
|
|
91
|
+
async ask({ system, prompt, schema }) {
|
|
92
|
+
const args = ['-p', '--output-format', 'json', '--model', model, '--tools', '', '--strict-mcp-config', '--no-session-persistence', '--system-prompt', system, '--json-schema', JSON.stringify(schema)];
|
|
93
|
+
const out = await run(bin, args, prompt);
|
|
94
|
+
let reply;
|
|
95
|
+
try {
|
|
96
|
+
reply = JSON.parse(out);
|
|
97
|
+
}
|
|
98
|
+
catch {
|
|
99
|
+
throw new Error(`${bin} -p did not return JSON: ${out.slice(0, 300)}`);
|
|
100
|
+
}
|
|
101
|
+
if (reply.is_error || reply.structured_output === undefined)
|
|
102
|
+
throw new Error(`${bin} -p failed: ${(reply.result ?? out).slice(0, 300)}`);
|
|
103
|
+
return { output: reply.structured_output, model: Object.keys(reply.modelUsage ?? {})[0] ?? model };
|
|
104
|
+
},
|
|
105
|
+
};
|
|
106
|
+
}
|
|
107
|
+
function run(bin, args, input) {
|
|
108
|
+
return new Promise((resolve, reject) => {
|
|
109
|
+
const child = (0, node_child_process_1.spawn)(bin, args, { cwd: os.tmpdir(), stdio: ['pipe', 'pipe', 'pipe'], timeout: 10 * 60_000 });
|
|
110
|
+
let out = '';
|
|
111
|
+
let err = '';
|
|
112
|
+
child.stdout.on('data', (d) => (out += d));
|
|
113
|
+
child.stderr.on('data', (d) => (err += d));
|
|
114
|
+
child.on('error', (e) => reject(new Error(`cannot run ${bin}: ${e.message}`)));
|
|
115
|
+
child.on('close', (code) => (code === 0 ? resolve(out) : reject(new Error(`${bin} exited with ${code}: ${(err || out).slice(0, 300)}`))));
|
|
116
|
+
child.stdin.end(input);
|
|
117
|
+
});
|
|
118
|
+
}
|
|
119
|
+
//# sourceMappingURL=judge.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"judge.js","sourceRoot":"","sources":["../../src/judge.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,40 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
var __createBinding = (this && this.__createBinding) || (Object.create ? (function(o, m, k, k2) {
|
|
3
|
+
if (k2 === undefined) k2 = k;
|
|
4
|
+
var desc = Object.getOwnPropertyDescriptor(m, k);
|
|
5
|
+
if (!desc || ("get" in desc ? !m.__esModule : desc.writable || desc.configurable)) {
|
|
6
|
+
desc = { enumerable: true, get: function() { return m[k]; } };
|
|
7
|
+
}
|
|
8
|
+
Object.defineProperty(o, k2, desc);
|
|
9
|
+
}) : (function(o, m, k, k2) {
|
|
10
|
+
if (k2 === undefined) k2 = k;
|
|
11
|
+
o[k2] = m[k];
|
|
12
|
+
}));
|
|
13
|
+
var __setModuleDefault = (this && this.__setModuleDefault) || (Object.create ? (function(o, v) {
|
|
14
|
+
Object.defineProperty(o, "default", { enumerable: true, value: v });
|
|
15
|
+
}) : function(o, v) {
|
|
16
|
+
o["default"] = v;
|
|
17
|
+
});
|
|
18
|
+
var __importStar = (this && this.__importStar) || (function () {
|
|
19
|
+
var ownKeys = function(o) {
|
|
20
|
+
ownKeys = Object.getOwnPropertyNames || function (o) {
|
|
21
|
+
var ar = [];
|
|
22
|
+
for (var k in o) if (Object.prototype.hasOwnProperty.call(o, k)) ar[ar.length] = k;
|
|
23
|
+
return ar;
|
|
24
|
+
};
|
|
25
|
+
return ownKeys(o);
|
|
26
|
+
};
|
|
27
|
+
return function (mod) {
|
|
28
|
+
if (mod && mod.__esModule) return mod;
|
|
29
|
+
var result = {};
|
|
30
|
+
if (mod != null) for (var k = ownKeys(mod), i = 0; i < k.length; i++) if (k[i] !== "default") __createBinding(result, mod, k[i]);
|
|
31
|
+
__setModuleDefault(result, mod);
|
|
32
|
+
return result;
|
|
33
|
+
};
|
|
34
|
+
})();
|
|
35
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
36
|
+
exports.PACKAGE_ROOT = void 0;
|
|
37
|
+
const path = __importStar(require("node:path"));
|
|
38
|
+
/** Root of this package: the repository checkout, or node_modules/personal-agent-benchmark. */
|
|
39
|
+
exports.PACKAGE_ROOT = path.resolve(__dirname, '..', '..');
|
|
40
|
+
//# sourceMappingURL=paths.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"paths.js","sourceRoot":"","sources":["../../src/paths.ts"],"names":[],"mappings":";;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;AAAA,MAAY,IAAI,sCAAkB;AAElC,+FAA+F;AAClF,QAAA,YAAY,GAAG,IAAI,CAAC,OAAO,CAAC,SAAS,EAAE,IAAI,EAAE,IAAI,CAAC,CAAC"}
|
|
@@ -0,0 +1,19 @@
|
|
|
1
|
+
import type { HeaderList } from '../core/types';
|
|
2
|
+
/**
|
|
3
|
+
* Page clock shim: shifts `Date` in replayed HTML documents to the recording time, so countdowns
|
|
4
|
+
* and "deal ends in" logic behave as they did during capture. Time keeps flowing from that point.
|
|
5
|
+
* Done in the proxy rather than with libfaketime, which breaks Chromium's CDP in practice and
|
|
6
|
+
* would not reach agents that bring their own browser.
|
|
7
|
+
*/
|
|
8
|
+
export declare function clockScript(recordedMs: number): string;
|
|
9
|
+
/** Inserts the shim at the top of <head> (or the document) and lets it through any CSP. */
|
|
10
|
+
export declare function injectClock(html: string, headers: HeaderList, recordedMs: number): {
|
|
11
|
+
html: string;
|
|
12
|
+
headers: HeaderList;
|
|
13
|
+
};
|
|
14
|
+
/**
|
|
15
|
+
* Lets the shim through script-src / script-src-elem. When a directive allows 'unsafe-inline' and
|
|
16
|
+
* has no hash or nonce, it is left alone: adding a hash would switch 'unsafe-inline' off for the
|
|
17
|
+
* page's own inline scripts.
|
|
18
|
+
*/
|
|
19
|
+
export declare function allowScriptHash(csp: string, hash: string): string;
|
|
@@ -0,0 +1,60 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
+
exports.clockScript = clockScript;
|
|
4
|
+
exports.injectClock = injectClock;
|
|
5
|
+
exports.allowScriptHash = allowScriptHash;
|
|
6
|
+
const node_crypto_1 = require("node:crypto");
|
|
7
|
+
/**
|
|
8
|
+
* Page clock shim: shifts `Date` in replayed HTML documents to the recording time, so countdowns
|
|
9
|
+
* and "deal ends in" logic behave as they did during capture. Time keeps flowing from that point.
|
|
10
|
+
* Done in the proxy rather than with libfaketime, which breaks Chromium's CDP in practice and
|
|
11
|
+
* would not reach agents that bring their own browser.
|
|
12
|
+
*/
|
|
13
|
+
function clockScript(recordedMs) {
|
|
14
|
+
return ('(function(){if(window.__rrClock)return;window.__rrClock=1;' +
|
|
15
|
+
`var D=Date,o=${recordedMs}-D.now();` +
|
|
16
|
+
'function F(){if(!(this instanceof F))return new D(D.now()+o).toString();' +
|
|
17
|
+
'if(arguments.length===0)return new D(D.now()+o);' +
|
|
18
|
+
'return new (Function.prototype.bind.apply(D,[null].concat([].slice.call(arguments))))();}' +
|
|
19
|
+
'F.prototype=D.prototype;F.now=function(){return D.now()+o};F.parse=D.parse;F.UTC=D.UTC;' +
|
|
20
|
+
"try{Object.defineProperty(F,'name',{value:'Date'})}catch(e){}window.Date=F;})();");
|
|
21
|
+
}
|
|
22
|
+
/** Inserts the shim at the top of <head> (or the document) and lets it through any CSP. */
|
|
23
|
+
function injectClock(html, headers, recordedMs) {
|
|
24
|
+
if (html.includes('__rrClock'))
|
|
25
|
+
return { html, headers };
|
|
26
|
+
const script = clockScript(recordedMs);
|
|
27
|
+
const tag = `<script>${script}</script>`;
|
|
28
|
+
const head = /<head[^>]*>/i.exec(html);
|
|
29
|
+
const out = head ? html.slice(0, head.index + head[0].length) + tag + html.slice(head.index + head[0].length) : tag + html;
|
|
30
|
+
const hash = `'sha256-${(0, node_crypto_1.createHash)('sha256').update(script).digest('base64')}'`;
|
|
31
|
+
const patched = headers.map(([k, v]) => (k.toLowerCase() === 'content-security-policy' ? [k, allowScriptHash(v, hash)] : [k, v]));
|
|
32
|
+
return { html: out, headers: patched };
|
|
33
|
+
}
|
|
34
|
+
/**
|
|
35
|
+
* Lets the shim through script-src / script-src-elem. When a directive allows 'unsafe-inline' and
|
|
36
|
+
* has no hash or nonce, it is left alone: adding a hash would switch 'unsafe-inline' off for the
|
|
37
|
+
* page's own inline scripts.
|
|
38
|
+
*/
|
|
39
|
+
function allowScriptHash(csp, hash) {
|
|
40
|
+
const directives = csp.split(';').map((d) => d.trim()).filter(Boolean);
|
|
41
|
+
if (!directives.some((d) => /^script-src(-elem)?(\s|$)/i.test(d))) {
|
|
42
|
+
const fallback = directives.find((d) => /^default-src(\s|$)/i.test(d));
|
|
43
|
+
// only default-src governs scripts: derive a script-src from it that also allows the shim
|
|
44
|
+
if (fallback && !/'unsafe-inline'/i.test(fallback))
|
|
45
|
+
directives.push(fallback.replace(/^default-src/i, 'script-src') + ' ' + hash);
|
|
46
|
+
return directives.join('; ');
|
|
47
|
+
}
|
|
48
|
+
return directives
|
|
49
|
+
.map((d) => {
|
|
50
|
+
const directive = d.trim();
|
|
51
|
+
if (!/^script-src(-elem)?(\s|$)/i.test(directive))
|
|
52
|
+
return directive;
|
|
53
|
+
const hasHashOrNonce = /'(nonce|sha256|sha384|sha512)-/i.test(directive);
|
|
54
|
+
if (/'unsafe-inline'/i.test(directive) && !hasHashOrNonce)
|
|
55
|
+
return directive;
|
|
56
|
+
return `${directive} ${hash}`;
|
|
57
|
+
})
|
|
58
|
+
.join('; ');
|
|
59
|
+
}
|
|
60
|
+
//# sourceMappingURL=clock.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"clock.js","sourceRoot":"","sources":["../../../src/replay/clock.ts"],"names":[],"mappings":";;;;;AAAA,6CAAyC;AAGzC;;;;;GAKG;AACH,qBAA4B,UAAkB;IAC5C,OAAO,CACL,4DAA4D;QAC5D,gBAAgB,UAAU,WAAW;QACrC,0EAA0E;QAC1E,kDAAkD;QAClD,2FAA2F;QAC3F,yFAAyF;QACzF,kFAAkF,CACnF,CAAC;AACJ,CAAC;AAED,2FAA2F;AAC3F,qBAA4B,IAAY,EAAE,OAAmB,EAAE,UAAkB;IAC/E,IAAI,IAAI,CAAC,QAAQ,CAAC,WAAW,CAAC;QAAE,OAAO,EAAE,IAAI,EAAE,OAAO,EAAE,CAAC;IACzD,MAAM,MAAM,GAAG,WAAW,CAAC,UAAU,CAAC,CAAC;IACvC,MAAM,GAAG,GAAG,WAAW,MAAM,WAAW,CAAC;IACzC,MAAM,IAAI,GAAG,cAAc,CAAC,IAAI,CAAC,IAAI,CAAC,CAAC;IACvC,MAAM,GAAG,GAAG,IAAI,CAAC,CAAC,CAAC,IAAI,CAAC,KAAK,CAAC,CAAC,EAAE,IAAI,CAAC,KAAK,GAAG,IAAI,CAAC,CAAC,CAAC,CAAC,MAAM,CAAC,GAAG,GAAG,GAAG,IAAI,CAAC,KAAK,CAAC,IAAI,CAAC,KAAK,GAAG,IAAI,CAAC,CAAC,CAAC,CAAC,MAAM,CAAC,CAAC,CAAC,CAAC,GAAG,GAAG,IAAI,CAAC;IAC3H,MAAM,IAAI,GAAG,WAAW,IAAA,wBAAU,EAAC,QAAQ,CAAC,CAAC,MAAM,CAAC,MAAM,CAAC,CAAC,MAAM,CAAC,QAAQ,CAAC,GAAG,CAAC;IAChF,MAAM,OAAO,GAAG,OAAO,CAAC,GAAG,CAAC,CAAC,CAAC,CAAC,EAAE,CAAC,CAAC,EAAoB,EAAE,CAAC,CAAC,CAAC,CAAC,WAAW,EAAE,KAAK,yBAAyB,CAAC,CAAC,CAAC,CAAC,CAAC,EAAE,eAAe,CAAC,CAAC,EAAE,IAAI,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,EAAE,CAAC,CAAC,CAAC,CAAC,CAAC;IACpJ,OAAO,EAAE,IAAI,EAAE,GAAG,EAAE,OAAO,EAAE,OAAO,EAAE,CAAC;AACzC,CAAC;AAED;;;;GAIG;AACH,yBAAgC,GAAW,EAAE,IAAY;IACvD,MAAM,UAAU,GAAG,GAAG,CAAC,KAAK,CAAC,GAAG,CAAC,CAAC,GAAG,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC,CAAC,CAAC,IAAI,EAAE,CAAC,CAAC,MAAM,CAAC,OAAO,CAAC,CAAC;IACvE,IAAI,CAAC,UAAU,CAAC,IAAI,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC,4BAA4B,CAAC,IAAI,CAAC,CAAC,CAAC,CAAC,EAAE,CAAC;QAClE,MAAM,QAAQ,GAAG,UAAU,CAAC,IAAI,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC,qBAAqB,CAAC,IAAI,CAAC,CAAC,CAAC,CAAC,CAAC;QACvE,0FAA0F;QAC1F,IAAI,QAAQ,IAAI,CAAC,kBAAkB,CAAC,IAAI,CAAC,QAAQ,CAAC;YAAE,UAAU,CAAC,IAAI,CAAC,QAAQ,CAAC,OAAO,CAAC,eAAe,EAAE,YAAY,CAAC,GAAG,GAAG,GAAG,IAAI,CAAC,CAAC;QAClI,OAAO,UAAU,CAAC,IAAI,CAAC,IAAI,CAAC,CAAC;IAC/B,CAAC;IACD,OAAO,UAAU;SACd,GAAG,CAAC,CAAC,CAAC,EAAE,EAAE;QACT,MAAM,SAAS,GAAG,CAAC,CAAC,IAAI,EAAE,CAAC;QAC3B,IAAI,CAAC,4BAA4B,CAAC,IAAI,CAAC,SAAS,CAAC;YAAE,OAAO,SAAS,CAAC;QACpE,MAAM,cAAc,GAAG,iCAAiC,CAAC,IAAI,CAAC,SAAS,CAAC,CAAC;QACzE,IAAI,kBAAkB,CAAC,IAAI,CAAC,SAAS,CAAC,IAAI,CAAC,cAAc;YAAE,OAAO,SAAS,CAAC;QAC5E,OAAO,GAAG,SAAS,IAAI,IAAI,EAAE,CAAC;IAChC,CAAC,CAAC;SACD,IAAI,CAAC,IAAI,CAAC,CAAC;AAChB,CAAC"}
|
|
@@ -0,0 +1,53 @@
|
|
|
1
|
+
import { Bundle } from '../core/bundle';
|
|
2
|
+
import { type NormalizedRequest } from '../core/normalize';
|
|
3
|
+
import { RuleSet } from '../core/rules';
|
|
4
|
+
import { RecordStore } from '../core/store';
|
|
5
|
+
import type { Manifest, ReplayRequest, ReplayResponse, ResourceClass } from '../core/types';
|
|
6
|
+
export declare const CONTROL_HOST = "rr.control";
|
|
7
|
+
export interface EngineOptions {
|
|
8
|
+
logFile?: string;
|
|
9
|
+
/** Extra rule directories layered over the bundle's own rules (later wins). */
|
|
10
|
+
rulesDirs?: string[];
|
|
11
|
+
/** "recorded" (default) shifts page clocks to the recording time; "off" leaves them alone. */
|
|
12
|
+
clock?: 'recorded' | 'off';
|
|
13
|
+
}
|
|
14
|
+
export interface ReplayStats {
|
|
15
|
+
requests: number;
|
|
16
|
+
bySource: Record<string, number>;
|
|
17
|
+
byClass: Record<ResourceClass, {
|
|
18
|
+
total: number;
|
|
19
|
+
hit: number;
|
|
20
|
+
miss: number;
|
|
21
|
+
}>;
|
|
22
|
+
misses: Record<string, {
|
|
23
|
+
count: number;
|
|
24
|
+
resourceClass: ResourceClass;
|
|
25
|
+
url: string;
|
|
26
|
+
}>;
|
|
27
|
+
}
|
|
28
|
+
/**
|
|
29
|
+
* Answers every request from a recording bundle. It never opens a network connection:
|
|
30
|
+
* misses are answered locally and logged.
|
|
31
|
+
*/
|
|
32
|
+
export declare class ReplayEngine {
|
|
33
|
+
readonly bundle: Bundle;
|
|
34
|
+
readonly rules: RuleSet;
|
|
35
|
+
readonly store: RecordStore;
|
|
36
|
+
readonly manifest: Manifest;
|
|
37
|
+
private stats;
|
|
38
|
+
private readonly logFile?;
|
|
39
|
+
private readonly clockMs?;
|
|
40
|
+
constructor(bundleDir: string, opts?: EngineOptions);
|
|
41
|
+
getStats(): ReplayStats;
|
|
42
|
+
reset(): void;
|
|
43
|
+
handle(req: ReplayRequest): Promise<ReplayResponse>;
|
|
44
|
+
private resolve;
|
|
45
|
+
private missResponse;
|
|
46
|
+
private cachedNotFound;
|
|
47
|
+
private notFoundPage;
|
|
48
|
+
/** Loads each site's recorded 404 page once; call before serving. */
|
|
49
|
+
warmUp(): Promise<void>;
|
|
50
|
+
private control;
|
|
51
|
+
private record;
|
|
52
|
+
}
|
|
53
|
+
export declare function classify(req: ReplayRequest, norm: NormalizedRequest): ResourceClass;
|