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,21 @@
|
|
|
1
|
+
import type { HeaderList } from './types';
|
|
2
|
+
export declare function sha256(data: Buffer | string): string;
|
|
3
|
+
/** JSON.stringify with sorted object keys, so equal objects give equal strings. */
|
|
4
|
+
export declare function stableStringify(value: unknown): string;
|
|
5
|
+
/** Glob with `*` (anything) and `?` (one char); case-insensitive. */
|
|
6
|
+
export declare function globToRegExp(glob: string): RegExp;
|
|
7
|
+
export declare function matchesAny(value: string, globs: string[] | undefined): boolean;
|
|
8
|
+
export declare function header(headers: HeaderList, name: string): string | undefined;
|
|
9
|
+
export declare function headerFromRecord(headers: Record<string, string | string[] | undefined>, name: string): string | undefined;
|
|
10
|
+
export declare function withoutHeaders(headers: HeaderList, names: string[]): HeaderList;
|
|
11
|
+
export declare function setHeader(headers: HeaderList, name: string, value: string): HeaderList;
|
|
12
|
+
export declare function mimeOf(headers: HeaderList): string;
|
|
13
|
+
export declare function isTextMime(mime: string): boolean;
|
|
14
|
+
export declare function readJsonl<T>(file: string): T[];
|
|
15
|
+
export declare function writeJsonl(file: string, rows: unknown[]): void;
|
|
16
|
+
export declare function writeJson(file: string, value: unknown): void;
|
|
17
|
+
export declare function readJson<T>(file: string): T;
|
|
18
|
+
/** 14-digit WARC/CDX timestamp from an ISO date. */
|
|
19
|
+
export declare function cdxTimestamp(iso: string): string;
|
|
20
|
+
export declare function tokens(text: string): string[];
|
|
21
|
+
export declare function jaccard(a: string[], b: string[]): number;
|
|
@@ -0,0 +1,150 @@
|
|
|
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.sha256 = sha256;
|
|
37
|
+
exports.stableStringify = stableStringify;
|
|
38
|
+
exports.globToRegExp = globToRegExp;
|
|
39
|
+
exports.matchesAny = matchesAny;
|
|
40
|
+
exports.header = header;
|
|
41
|
+
exports.headerFromRecord = headerFromRecord;
|
|
42
|
+
exports.withoutHeaders = withoutHeaders;
|
|
43
|
+
exports.setHeader = setHeader;
|
|
44
|
+
exports.mimeOf = mimeOf;
|
|
45
|
+
exports.isTextMime = isTextMime;
|
|
46
|
+
exports.readJsonl = readJsonl;
|
|
47
|
+
exports.writeJsonl = writeJsonl;
|
|
48
|
+
exports.writeJson = writeJson;
|
|
49
|
+
exports.readJson = readJson;
|
|
50
|
+
exports.cdxTimestamp = cdxTimestamp;
|
|
51
|
+
exports.tokens = tokens;
|
|
52
|
+
exports.jaccard = jaccard;
|
|
53
|
+
const node_crypto_1 = require("node:crypto");
|
|
54
|
+
const fs = __importStar(require("node:fs"));
|
|
55
|
+
const path = __importStar(require("node:path"));
|
|
56
|
+
function sha256(data) {
|
|
57
|
+
return (0, node_crypto_1.createHash)('sha256').update(data).digest('hex');
|
|
58
|
+
}
|
|
59
|
+
/** JSON.stringify with sorted object keys, so equal objects give equal strings. */
|
|
60
|
+
function stableStringify(value) {
|
|
61
|
+
if (value === null || typeof value !== 'object')
|
|
62
|
+
return JSON.stringify(value);
|
|
63
|
+
if (Array.isArray(value))
|
|
64
|
+
return '[' + value.map(stableStringify).join(',') + ']';
|
|
65
|
+
const obj = value;
|
|
66
|
+
return '{' + Object.keys(obj).sort().map((k) => JSON.stringify(k) + ':' + stableStringify(obj[k])).join(',') + '}';
|
|
67
|
+
}
|
|
68
|
+
/** Glob with `*` (anything) and `?` (one char); case-insensitive. */
|
|
69
|
+
function globToRegExp(glob) {
|
|
70
|
+
const re = glob.replace(/[.+^${}()|[\]\\]/g, '\\$&').replace(/\*/g, '.*').replace(/\?/g, '.');
|
|
71
|
+
return new RegExp('^' + re + '$', 'i');
|
|
72
|
+
}
|
|
73
|
+
function matchesAny(value, globs) {
|
|
74
|
+
if (!globs || globs.length === 0)
|
|
75
|
+
return false;
|
|
76
|
+
return globs.some((g) => globToRegExp(g).test(value));
|
|
77
|
+
}
|
|
78
|
+
function header(headers, name) {
|
|
79
|
+
const lower = name.toLowerCase();
|
|
80
|
+
for (const [k, v] of headers)
|
|
81
|
+
if (k.toLowerCase() === lower)
|
|
82
|
+
return v;
|
|
83
|
+
return undefined;
|
|
84
|
+
}
|
|
85
|
+
function headerFromRecord(headers, name) {
|
|
86
|
+
const lower = name.toLowerCase();
|
|
87
|
+
for (const k of Object.keys(headers)) {
|
|
88
|
+
if (k.toLowerCase() !== lower)
|
|
89
|
+
continue;
|
|
90
|
+
const v = headers[k];
|
|
91
|
+
return Array.isArray(v) ? v.join(', ') : v;
|
|
92
|
+
}
|
|
93
|
+
return undefined;
|
|
94
|
+
}
|
|
95
|
+
function withoutHeaders(headers, names) {
|
|
96
|
+
const drop = new Set(names.map((n) => n.toLowerCase()));
|
|
97
|
+
return headers.filter(([k]) => !drop.has(k.toLowerCase()));
|
|
98
|
+
}
|
|
99
|
+
function setHeader(headers, name, value) {
|
|
100
|
+
return [...withoutHeaders(headers, [name]), [name, value]];
|
|
101
|
+
}
|
|
102
|
+
function mimeOf(headers) {
|
|
103
|
+
return (header(headers, 'content-type') || '').split(';')[0].trim().toLowerCase();
|
|
104
|
+
}
|
|
105
|
+
function isTextMime(mime) {
|
|
106
|
+
return (mime.startsWith('text/') ||
|
|
107
|
+
/(json|javascript|xml|x-www-form-urlencoded|svg)/.test(mime));
|
|
108
|
+
}
|
|
109
|
+
function readJsonl(file) {
|
|
110
|
+
if (!fs.existsSync(file))
|
|
111
|
+
return [];
|
|
112
|
+
return fs
|
|
113
|
+
.readFileSync(file, 'utf8')
|
|
114
|
+
.split('\n')
|
|
115
|
+
.filter((l) => l.trim())
|
|
116
|
+
.map((l) => JSON.parse(l));
|
|
117
|
+
}
|
|
118
|
+
function writeJsonl(file, rows) {
|
|
119
|
+
fs.mkdirSync(path.dirname(file), { recursive: true });
|
|
120
|
+
fs.writeFileSync(file, rows.map((r) => JSON.stringify(r)).join('\n') + (rows.length ? '\n' : ''));
|
|
121
|
+
}
|
|
122
|
+
function writeJson(file, value) {
|
|
123
|
+
fs.mkdirSync(path.dirname(file), { recursive: true });
|
|
124
|
+
fs.writeFileSync(file, JSON.stringify(value, null, 2) + '\n');
|
|
125
|
+
}
|
|
126
|
+
function readJson(file) {
|
|
127
|
+
return JSON.parse(fs.readFileSync(file, 'utf8'));
|
|
128
|
+
}
|
|
129
|
+
/** 14-digit WARC/CDX timestamp from an ISO date. */
|
|
130
|
+
function cdxTimestamp(iso) {
|
|
131
|
+
return new Date(iso).toISOString().replace(/[-:TZ.]/g, '').slice(0, 14);
|
|
132
|
+
}
|
|
133
|
+
function tokens(text) {
|
|
134
|
+
return text
|
|
135
|
+
.toLowerCase()
|
|
136
|
+
.split(/[^\p{L}\p{N}]+/u)
|
|
137
|
+
.filter(Boolean);
|
|
138
|
+
}
|
|
139
|
+
function jaccard(a, b) {
|
|
140
|
+
const sa = new Set(a);
|
|
141
|
+
const sb = new Set(b);
|
|
142
|
+
if (sa.size === 0 && sb.size === 0)
|
|
143
|
+
return 1;
|
|
144
|
+
let inter = 0;
|
|
145
|
+
for (const t of sa)
|
|
146
|
+
if (sb.has(t))
|
|
147
|
+
inter++;
|
|
148
|
+
return inter / (sa.size + sb.size - inter);
|
|
149
|
+
}
|
|
150
|
+
//# sourceMappingURL=util.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"util.js","sourceRoot":"","sources":["../../../src/core/util.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,55 @@
|
|
|
1
|
+
import type { Exchange, HeaderList, StoredResponse } from './types';
|
|
2
|
+
export interface Span {
|
|
3
|
+
offset: number;
|
|
4
|
+
length: number;
|
|
5
|
+
}
|
|
6
|
+
/**
|
|
7
|
+
* Appends WARC records to one file and reports where each landed. Records are written
|
|
8
|
+
* uncompressed by default: bundles are compressed as a whole for transport, which shrinks them
|
|
9
|
+
* far more than per-record gzip (cross-record redundancy); pass gzip for a standalone .warc.gz.
|
|
10
|
+
*/
|
|
11
|
+
export declare class WarcWriter {
|
|
12
|
+
readonly file: string;
|
|
13
|
+
private readonly opts;
|
|
14
|
+
private readonly fd;
|
|
15
|
+
private offset;
|
|
16
|
+
constructor(file: string, opts?: {
|
|
17
|
+
gzip?: boolean;
|
|
18
|
+
});
|
|
19
|
+
writeInfo(info: Record<string, string>): Promise<Span>;
|
|
20
|
+
/** Writes a response (or a revisit pointing at an identical earlier payload) and its request. */
|
|
21
|
+
writeExchange(ex: Exchange, revisit?: {
|
|
22
|
+
url: string;
|
|
23
|
+
date: string;
|
|
24
|
+
digest: string;
|
|
25
|
+
}): Promise<{
|
|
26
|
+
req: Span;
|
|
27
|
+
resp: Span;
|
|
28
|
+
}>;
|
|
29
|
+
close(): void;
|
|
30
|
+
private write;
|
|
31
|
+
}
|
|
32
|
+
/**
|
|
33
|
+
* Header lines as stored, as a header list. Recorders before record-replay 0.5.5 kept a header the
|
|
34
|
+
* site sent several times (Set-Cookie above all) as one value joined by newlines, as DevTools
|
|
35
|
+
* reports it, and wrote it that way: each further value is a line of its own after the header's
|
|
36
|
+
* line, ended by a bare newline, or by CRLF once the recording was rewritten. A line that is not a
|
|
37
|
+
* header is taken as a further value of the header before it; `malformed` counts those lines (lines
|
|
38
|
+
* before any header are left out).
|
|
39
|
+
*/
|
|
40
|
+
export declare function parseHeaderLines(lines: string[]): {
|
|
41
|
+
headers: HeaderList;
|
|
42
|
+
malformed: number;
|
|
43
|
+
};
|
|
44
|
+
/** Reads one record (plain or gzip member) at a known offset and returns its HTTP status, headers and payload. */
|
|
45
|
+
export declare function readResponseAt(file: string, span: Span): Promise<StoredResponse & {
|
|
46
|
+
type: string;
|
|
47
|
+
malformedHeaderLines: number;
|
|
48
|
+
}>;
|
|
49
|
+
export declare function readRequestAt(file: string, span: Span): Promise<{
|
|
50
|
+
headers: HeaderList;
|
|
51
|
+
malformedHeaderLines: number;
|
|
52
|
+
body: Buffer;
|
|
53
|
+
}>;
|
|
54
|
+
/** Iterates request/response pairs of any WARC (e.g. from ArchiveWeb.page) as exchanges. */
|
|
55
|
+
export declare function readExchanges(file: string): AsyncGenerator<Exchange>;
|
|
@@ -0,0 +1,258 @@
|
|
|
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.WarcWriter = void 0;
|
|
37
|
+
exports.parseHeaderLines = parseHeaderLines;
|
|
38
|
+
exports.readResponseAt = readResponseAt;
|
|
39
|
+
exports.readRequestAt = readRequestAt;
|
|
40
|
+
exports.readExchanges = readExchanges;
|
|
41
|
+
const fs = __importStar(require("node:fs"));
|
|
42
|
+
const path = __importStar(require("node:path"));
|
|
43
|
+
const node_http_1 = require("node:http");
|
|
44
|
+
const warcio_1 = require("warcio");
|
|
45
|
+
const util_1 = require("./util");
|
|
46
|
+
const REVISIT_PROFILE = 'http://netpreserve.org/warc/1.1/revisit/identical-payload-digest';
|
|
47
|
+
/**
|
|
48
|
+
* Appends WARC records to one file and reports where each landed. Records are written
|
|
49
|
+
* uncompressed by default: bundles are compressed as a whole for transport, which shrinks them
|
|
50
|
+
* far more than per-record gzip (cross-record redundancy); pass gzip for a standalone .warc.gz.
|
|
51
|
+
*/
|
|
52
|
+
class WarcWriter {
|
|
53
|
+
file;
|
|
54
|
+
opts;
|
|
55
|
+
fd;
|
|
56
|
+
offset = 0;
|
|
57
|
+
constructor(file, opts = {}) {
|
|
58
|
+
this.file = file;
|
|
59
|
+
this.opts = opts;
|
|
60
|
+
fs.mkdirSync(path.dirname(file), { recursive: true });
|
|
61
|
+
this.fd = fs.openSync(file, 'w');
|
|
62
|
+
}
|
|
63
|
+
async writeInfo(info) {
|
|
64
|
+
const record = warcio_1.WARCRecord.createWARCInfo({ filename: path.basename(this.file), warcVersion: 'WARC/1.1' }, info);
|
|
65
|
+
return this.write(record);
|
|
66
|
+
}
|
|
67
|
+
/** Writes a response (or a revisit pointing at an identical earlier payload) and its request. */
|
|
68
|
+
async writeExchange(ex, revisit) {
|
|
69
|
+
const statusline = `HTTP/1.1 ${ex.status} ${ex.statusText || node_http_1.STATUS_CODES[ex.status] || ''}`.trim();
|
|
70
|
+
const warcHeaders = { 'RR-Exchange-Id': ex.id };
|
|
71
|
+
if (ex.originalContentEncoding)
|
|
72
|
+
warcHeaders['RR-Original-Content-Encoding'] = ex.originalContentEncoding;
|
|
73
|
+
if (ex.resourceType)
|
|
74
|
+
warcHeaders['RR-Resource-Type'] = ex.resourceType;
|
|
75
|
+
let respRecord;
|
|
76
|
+
if (revisit) {
|
|
77
|
+
respRecord = warcio_1.WARCRecord.create({
|
|
78
|
+
url: ex.url,
|
|
79
|
+
date: ex.ts,
|
|
80
|
+
type: 'revisit',
|
|
81
|
+
warcVersion: 'WARC/1.1',
|
|
82
|
+
refersToUrl: revisit.url,
|
|
83
|
+
refersToDate: revisit.date,
|
|
84
|
+
warcHeaders: { ...warcHeaders, 'WARC-Profile': REVISIT_PROFILE, 'RR-Payload-Sha256': revisit.digest },
|
|
85
|
+
httpHeaders: ex.respHeaders,
|
|
86
|
+
statusline,
|
|
87
|
+
keepHeadersCase: true,
|
|
88
|
+
}, []);
|
|
89
|
+
}
|
|
90
|
+
else {
|
|
91
|
+
respRecord = warcio_1.WARCRecord.create({
|
|
92
|
+
url: ex.url,
|
|
93
|
+
date: ex.ts,
|
|
94
|
+
type: 'response',
|
|
95
|
+
warcVersion: 'WARC/1.1',
|
|
96
|
+
warcHeaders,
|
|
97
|
+
httpHeaders: ex.respHeaders,
|
|
98
|
+
statusline,
|
|
99
|
+
keepHeadersCase: true,
|
|
100
|
+
}, [ex.respBody]);
|
|
101
|
+
}
|
|
102
|
+
const respId = respRecord.warcHeader('WARC-Record-ID') ?? '';
|
|
103
|
+
const resp = await this.write(respRecord);
|
|
104
|
+
const u = new URL(ex.url);
|
|
105
|
+
const reqHeaders = (0, util_1.header)(ex.reqHeaders, 'host') ? ex.reqHeaders : [['Host', u.host], ...ex.reqHeaders];
|
|
106
|
+
const reqRecord = warcio_1.WARCRecord.create({
|
|
107
|
+
url: ex.url,
|
|
108
|
+
date: ex.ts,
|
|
109
|
+
type: 'request',
|
|
110
|
+
warcVersion: 'WARC/1.1',
|
|
111
|
+
warcHeaders: { 'WARC-Concurrent-To': respId, 'RR-Exchange-Id': ex.id },
|
|
112
|
+
httpHeaders: reqHeaders,
|
|
113
|
+
statusline: `${ex.method} ${u.pathname}${u.search} HTTP/1.1`,
|
|
114
|
+
keepHeadersCase: true,
|
|
115
|
+
}, ex.reqBody && ex.reqBody.length ? [ex.reqBody] : []);
|
|
116
|
+
const req = await this.write(reqRecord);
|
|
117
|
+
return { req, resp };
|
|
118
|
+
}
|
|
119
|
+
close() {
|
|
120
|
+
fs.closeSync(this.fd);
|
|
121
|
+
}
|
|
122
|
+
async write(record) {
|
|
123
|
+
const bytes = await warcio_1.WARCSerializer.serialize(record, { gzip: this.opts.gzip ?? false });
|
|
124
|
+
fs.writeSync(this.fd, bytes);
|
|
125
|
+
const span = { offset: this.offset, length: bytes.length };
|
|
126
|
+
this.offset += bytes.length;
|
|
127
|
+
return span;
|
|
128
|
+
}
|
|
129
|
+
}
|
|
130
|
+
exports.WarcWriter = WarcWriter;
|
|
131
|
+
const HEADER_NAME = /^[!#$%&'*+.^_`|~0-9A-Za-z-]+$/;
|
|
132
|
+
const CRLFCRLF = Buffer.from('\r\n\r\n');
|
|
133
|
+
/**
|
|
134
|
+
* Header lines as stored, as a header list. Recorders before record-replay 0.5.5 kept a header the
|
|
135
|
+
* site sent several times (Set-Cookie above all) as one value joined by newlines, as DevTools
|
|
136
|
+
* reports it, and wrote it that way: each further value is a line of its own after the header's
|
|
137
|
+
* line, ended by a bare newline, or by CRLF once the recording was rewritten. A line that is not a
|
|
138
|
+
* header is taken as a further value of the header before it; `malformed` counts those lines (lines
|
|
139
|
+
* before any header are left out).
|
|
140
|
+
*/
|
|
141
|
+
function parseHeaderLines(lines) {
|
|
142
|
+
const headers = [];
|
|
143
|
+
let malformed = 0;
|
|
144
|
+
let last;
|
|
145
|
+
for (const line of lines) {
|
|
146
|
+
// values joined to a line by bare newlines are never headers of their own
|
|
147
|
+
for (const [i, part] of line.split(/\r?\n|\r/).entries()) {
|
|
148
|
+
const colon = part.indexOf(':');
|
|
149
|
+
const name = colon > 0 ? part.slice(0, colon) : '';
|
|
150
|
+
if (i === 0 && HEADER_NAME.test(name)) {
|
|
151
|
+
headers.push([name, part.slice(colon + 1).trim()]);
|
|
152
|
+
last = name;
|
|
153
|
+
continue;
|
|
154
|
+
}
|
|
155
|
+
malformed++;
|
|
156
|
+
if (last && part.trim())
|
|
157
|
+
headers.push([last, part.trim()]);
|
|
158
|
+
}
|
|
159
|
+
}
|
|
160
|
+
return { headers, malformed };
|
|
161
|
+
}
|
|
162
|
+
/**
|
|
163
|
+
* The HTTP message stored in a record, read by its bytes: warcio's own parsing drops header lines
|
|
164
|
+
* without a colon, so a malformed header could be neither repaired nor seen.
|
|
165
|
+
*/
|
|
166
|
+
function httpMessage(content) {
|
|
167
|
+
const end = content.indexOf(CRLFCRLF);
|
|
168
|
+
const [startLine = '', ...lines] = (end < 0 ? content : content.subarray(0, end)).toString('utf8').split('\r\n');
|
|
169
|
+
const { headers, malformed } = parseHeaderLines(lines.filter(Boolean));
|
|
170
|
+
return { startLine, headers, malformedHeaderLines: malformed, body: end < 0 ? Buffer.alloc(0) : content.subarray(end + 4) };
|
|
171
|
+
}
|
|
172
|
+
/** Status of a stored response; a request that got no response is stored with status -1. */
|
|
173
|
+
function statusOf(startLine) {
|
|
174
|
+
const m = /^HTTP\/\S+ (-?\d+) ?(.*)$/.exec(startLine);
|
|
175
|
+
return m ? { status: Number(m[1]), statusText: m[2] } : { status: 200, statusText: '' };
|
|
176
|
+
}
|
|
177
|
+
async function readRecordAt(file, span) {
|
|
178
|
+
const record = await warcio_1.WARCParser.parse([readSpan(file, span)], { keepHeadersCase: true, parseHttp: false });
|
|
179
|
+
if (!record)
|
|
180
|
+
throw new Error(`no WARC record at ${file}:${span.offset}`);
|
|
181
|
+
return { type: record.warcType ?? '', http: httpMessage(Buffer.from(await record.readFully(false))) };
|
|
182
|
+
}
|
|
183
|
+
/** Reads one record (plain or gzip member) at a known offset and returns its HTTP status, headers and payload. */
|
|
184
|
+
async function readResponseAt(file, span) {
|
|
185
|
+
const { type, http } = await readRecordAt(file, span);
|
|
186
|
+
return { type, ...statusOf(http.startLine), headers: http.headers, malformedHeaderLines: http.malformedHeaderLines, body: http.body };
|
|
187
|
+
}
|
|
188
|
+
async function readRequestAt(file, span) {
|
|
189
|
+
const { http } = await readRecordAt(file, span);
|
|
190
|
+
return { headers: http.headers, malformedHeaderLines: http.malformedHeaderLines, body: http.body };
|
|
191
|
+
}
|
|
192
|
+
function readSpan(file, span) {
|
|
193
|
+
const fd = fs.openSync(file, 'r');
|
|
194
|
+
try {
|
|
195
|
+
const buf = Buffer.alloc(span.length);
|
|
196
|
+
fs.readSync(fd, buf, 0, span.length, span.offset);
|
|
197
|
+
return buf;
|
|
198
|
+
}
|
|
199
|
+
finally {
|
|
200
|
+
fs.closeSync(fd);
|
|
201
|
+
}
|
|
202
|
+
}
|
|
203
|
+
/** Iterates request/response pairs of any WARC (e.g. from ArchiveWeb.page) as exchanges. */
|
|
204
|
+
async function* readExchanges(file) {
|
|
205
|
+
const stream = fs.createReadStream(file);
|
|
206
|
+
let n = 0;
|
|
207
|
+
const parser = new warcio_1.WARCParser(stream, { keepHeadersCase: true, parseHttp: false });
|
|
208
|
+
const responses = [];
|
|
209
|
+
const byRespId = new Map();
|
|
210
|
+
const requests = [];
|
|
211
|
+
for await (const record of parser) {
|
|
212
|
+
const type = record.warcType;
|
|
213
|
+
if (type === 'response' || type === 'revisit') {
|
|
214
|
+
const http = httpMessage(Buffer.from(await record.readFully(false)));
|
|
215
|
+
const ex = {
|
|
216
|
+
id: `w${n++}`,
|
|
217
|
+
ts: record.warcDate ?? new Date().toISOString(),
|
|
218
|
+
method: 'GET',
|
|
219
|
+
url: record.warcTargetURI ?? '',
|
|
220
|
+
httpVersion: 'HTTP/1.1',
|
|
221
|
+
reqHeaders: [],
|
|
222
|
+
...statusOf(http.startLine),
|
|
223
|
+
respHeaders: http.headers,
|
|
224
|
+
respBody: type === 'response' ? http.body : Buffer.alloc(0),
|
|
225
|
+
originalContentEncoding: (0, util_1.header)(http.headers, 'content-encoding'),
|
|
226
|
+
malformedHeaderLines: http.malformedHeaderLines,
|
|
227
|
+
};
|
|
228
|
+
responses.push(ex);
|
|
229
|
+
byRespId.set(record.warcHeader('WARC-Record-ID') ?? '', ex);
|
|
230
|
+
}
|
|
231
|
+
else if (type === 'request') {
|
|
232
|
+
const http = httpMessage(Buffer.from(await record.readFully(false)));
|
|
233
|
+
requests.push({
|
|
234
|
+
concurrentTo: record.warcHeader('WARC-Concurrent-To') ?? undefined,
|
|
235
|
+
url: record.warcTargetURI ?? '',
|
|
236
|
+
method: http.startLine.split(' ')[0] || 'GET',
|
|
237
|
+
headers: http.headers,
|
|
238
|
+
malformedHeaderLines: http.malformedHeaderLines,
|
|
239
|
+
body: http.body,
|
|
240
|
+
});
|
|
241
|
+
}
|
|
242
|
+
else {
|
|
243
|
+
await record.skipFully();
|
|
244
|
+
}
|
|
245
|
+
}
|
|
246
|
+
for (const r of requests) {
|
|
247
|
+
const ex = (r.concurrentTo && byRespId.get(r.concurrentTo)) || responses.find((e) => e.url === r.url && e.reqHeaders.length === 0);
|
|
248
|
+
if (!ex)
|
|
249
|
+
continue;
|
|
250
|
+
ex.method = r.method.toUpperCase();
|
|
251
|
+
ex.reqHeaders = r.headers;
|
|
252
|
+
ex.malformedHeaderLines = (ex.malformedHeaderLines ?? 0) + r.malformedHeaderLines;
|
|
253
|
+
ex.reqBody = r.body.length ? r.body : undefined;
|
|
254
|
+
}
|
|
255
|
+
for (const ex of responses)
|
|
256
|
+
yield ex;
|
|
257
|
+
}
|
|
258
|
+
//# sourceMappingURL=warc.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"warc.js","sourceRoot":"","sources":["../../../src/core/warc.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,26 @@
|
|
|
1
|
+
import type { Bundle, PageRecord } from './bundle';
|
|
2
|
+
import type { RuleSet } from './rules';
|
|
3
|
+
import type { Entry, Exchange, Manifest } from './types';
|
|
4
|
+
/** The manifest fields a recorder knows before writing; the rest come from the exchanges. */
|
|
5
|
+
export type BundleMeta = Pick<Manifest, 'task_id' | 'locale' | 'timezone'>;
|
|
6
|
+
export interface WriteBundleOptions {
|
|
7
|
+
meta: BundleMeta;
|
|
8
|
+
/** Decides site names and which page is each site's 404 page. */
|
|
9
|
+
rules: RuleSet;
|
|
10
|
+
/** Top-level pages visited while recording; defaults to every HTML document. */
|
|
11
|
+
pages?: PageRecord[];
|
|
12
|
+
/** Payloads at least this large are stored once and referenced by revisit records. */
|
|
13
|
+
dedupeMinBytes?: number;
|
|
14
|
+
}
|
|
15
|
+
export interface WriteBundleResult {
|
|
16
|
+
entries: Entry[];
|
|
17
|
+
manifest: Manifest;
|
|
18
|
+
revisits: number;
|
|
19
|
+
bytes: number;
|
|
20
|
+
}
|
|
21
|
+
/**
|
|
22
|
+
* Writes the replayable part of a bundle from exchanges that are already safe to store:
|
|
23
|
+
* archive/data.warc, indexes/entries.jsonl, pages/pages.jsonl and manifest.json. Exchanges are
|
|
24
|
+
* stored in the given order and get ids e000001, e000002, ...
|
|
25
|
+
*/
|
|
26
|
+
export declare function writeBundle(bundle: Bundle, exchanges: Exchange[], o: WriteBundleOptions): Promise<WriteBundleResult>;
|
|
@@ -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
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
36
|
+
exports.writeBundle = writeBundle;
|
|
37
|
+
const fs = __importStar(require("node:fs"));
|
|
38
|
+
const path = __importStar(require("node:path"));
|
|
39
|
+
const util_1 = require("./util");
|
|
40
|
+
const warc_1 = require("./warc");
|
|
41
|
+
/** Files of earlier bundle versions that replay never read; removed when a bundle is rewritten. */
|
|
42
|
+
const LEGACY_FILES = ['datapackage.json', path.join('indexes', 'index.cdxj')];
|
|
43
|
+
/**
|
|
44
|
+
* Writes the replayable part of a bundle from exchanges that are already safe to store:
|
|
45
|
+
* archive/data.warc, indexes/entries.jsonl, pages/pages.jsonl and manifest.json. Exchanges are
|
|
46
|
+
* stored in the given order and get ids e000001, e000002, ...
|
|
47
|
+
*/
|
|
48
|
+
async function writeBundle(bundle, exchanges, o) {
|
|
49
|
+
if (!exchanges.length)
|
|
50
|
+
throw new Error('no exchanges to write');
|
|
51
|
+
exchanges.forEach((ex, i) => (ex.id = 'e' + String(i + 1).padStart(6, '0')));
|
|
52
|
+
fs.rmSync(path.join(bundle.dir, 'archive'), { recursive: true, force: true });
|
|
53
|
+
for (const f of LEGACY_FILES)
|
|
54
|
+
fs.rmSync(path.join(bundle.dir, f), { force: true });
|
|
55
|
+
const writer = new warc_1.WarcWriter(path.join(bundle.dir, 'archive', 'data.warc'));
|
|
56
|
+
const firstByDigest = new Map();
|
|
57
|
+
const minDedupe = o.dedupeMinBytes ?? 1024;
|
|
58
|
+
const entries = [];
|
|
59
|
+
let revisits = 0;
|
|
60
|
+
let bytes = 0;
|
|
61
|
+
for (const ex of exchanges) {
|
|
62
|
+
const digest = (0, util_1.sha256)(ex.respBody);
|
|
63
|
+
const first = ex.respBody.length >= minDedupe ? firstByDigest.get(digest) : undefined;
|
|
64
|
+
const spans = await writer.writeExchange(ex, first ? { url: first.url, date: first.ts, digest } : undefined);
|
|
65
|
+
if (first)
|
|
66
|
+
revisits++;
|
|
67
|
+
else {
|
|
68
|
+
bytes += ex.respBody.length;
|
|
69
|
+
if (ex.respBody.length >= minDedupe)
|
|
70
|
+
firstByDigest.set(digest, ex);
|
|
71
|
+
}
|
|
72
|
+
entries.push({
|
|
73
|
+
id: ex.id,
|
|
74
|
+
ts: ex.ts,
|
|
75
|
+
method: ex.method,
|
|
76
|
+
url: ex.url,
|
|
77
|
+
status: ex.status,
|
|
78
|
+
mime: (0, util_1.mimeOf)(ex.respHeaders),
|
|
79
|
+
resourceType: ex.resourceType,
|
|
80
|
+
reqContentType: (0, util_1.header)(ex.reqHeaders, 'content-type'),
|
|
81
|
+
reqBody: ex.reqBody && ex.reqBody.length ? ex.reqBody.toString('base64') : undefined,
|
|
82
|
+
digest,
|
|
83
|
+
size: ex.respBody.length,
|
|
84
|
+
reqOffset: spans.req.offset,
|
|
85
|
+
reqLength: spans.req.length,
|
|
86
|
+
respOffset: spans.resp.offset,
|
|
87
|
+
respLength: spans.resp.length,
|
|
88
|
+
revisitOf: first?.id,
|
|
89
|
+
});
|
|
90
|
+
}
|
|
91
|
+
writer.close();
|
|
92
|
+
(0, util_1.writeJsonl)(bundle.entriesPath, entries);
|
|
93
|
+
const pages = o.pages?.length
|
|
94
|
+
? o.pages
|
|
95
|
+
: entries
|
|
96
|
+
.filter((e) => e.method === 'GET' && e.status === 200 && e.mime === 'text/html' && (e.resourceType ?? 'document') === 'document')
|
|
97
|
+
.map((e) => ({ id: e.id, url: e.url, ts: e.ts }));
|
|
98
|
+
const getUrls = new Set(entries.filter((e) => e.method === 'GET').map((e) => e.url));
|
|
99
|
+
const otherUrls = new Set(entries.filter((e) => e.method !== 'GET').map((e) => e.url));
|
|
100
|
+
for (const p of pages)
|
|
101
|
+
p.fetched = getUrls.has(p.url) ? 'GET' : otherUrls.has(p.url) ? 'POST' : 'none';
|
|
102
|
+
(0, util_1.writeJsonl)(bundle.pagesPath, pages);
|
|
103
|
+
const notFound = {};
|
|
104
|
+
for (const p of pages.filter((pg) => pg.note === 'not-found-probe')) {
|
|
105
|
+
const host = new URL(p.url).hostname;
|
|
106
|
+
notFound[o.rules.siteFor(host)?.site ?? host] ??= p.url;
|
|
107
|
+
}
|
|
108
|
+
const manifest = {
|
|
109
|
+
task_id: o.meta.task_id,
|
|
110
|
+
captured_from: entries[0].ts,
|
|
111
|
+
captured_to: entries[entries.length - 1].ts,
|
|
112
|
+
not_found: notFound,
|
|
113
|
+
locale: o.meta.locale,
|
|
114
|
+
timezone: o.meta.timezone,
|
|
115
|
+
};
|
|
116
|
+
(0, util_1.writeJson)(bundle.manifestPath, manifest);
|
|
117
|
+
return { entries, manifest, revisits, bytes };
|
|
118
|
+
}
|
|
119
|
+
//# sourceMappingURL=writer.js.map
|