@metamask-previews/tooling-insight 1.0.1-preview-898fae5
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/CHANGELOG.md +38 -0
- package/LICENSE +21 -0
- package/README.md +134 -0
- package/dist/daily-anonymizer.cjs +8 -0
- package/dist/daily-anonymizer.cjs.map +1 -0
- package/dist/daily-anonymizer.d.cts +3 -0
- package/dist/daily-anonymizer.d.cts.map +1 -0
- package/dist/daily-anonymizer.d.mts +3 -0
- package/dist/daily-anonymizer.d.mts.map +1 -0
- package/dist/daily-anonymizer.mjs +6 -0
- package/dist/daily-anonymizer.mjs.map +1 -0
- package/dist/index.cjs +6 -0
- package/dist/index.cjs.map +1 -0
- package/dist/index.d.cts +4 -0
- package/dist/index.d.cts.map +1 -0
- package/dist/index.d.mts +4 -0
- package/dist/index.d.mts.map +1 -0
- package/dist/index.mjs +2 -0
- package/dist/index.mjs.map +1 -0
- package/dist/lib/allowlist.cjs +159 -0
- package/dist/lib/allowlist.cjs.map +1 -0
- package/dist/lib/allowlist.d.cts +31 -0
- package/dist/lib/allowlist.d.cts.map +1 -0
- package/dist/lib/allowlist.d.mts +31 -0
- package/dist/lib/allowlist.d.mts.map +1 -0
- package/dist/lib/allowlist.mjs +155 -0
- package/dist/lib/allowlist.mjs.map +1 -0
- package/dist/lib/csv.cjs +152 -0
- package/dist/lib/csv.cjs.map +1 -0
- package/dist/lib/csv.d.cts +16 -0
- package/dist/lib/csv.d.cts.map +1 -0
- package/dist/lib/csv.d.mts +16 -0
- package/dist/lib/csv.d.mts.map +1 -0
- package/dist/lib/csv.mjs +149 -0
- package/dist/lib/csv.mjs.map +1 -0
- package/dist/lib/exposition.cjs +102 -0
- package/dist/lib/exposition.cjs.map +1 -0
- package/dist/lib/exposition.d.cts +9 -0
- package/dist/lib/exposition.d.cts.map +1 -0
- package/dist/lib/exposition.d.mts +9 -0
- package/dist/lib/exposition.d.mts.map +1 -0
- package/dist/lib/exposition.mjs +99 -0
- package/dist/lib/exposition.mjs.map +1 -0
- package/dist/lib/fold.cjs +294 -0
- package/dist/lib/fold.cjs.map +1 -0
- package/dist/lib/fold.d.cts +32 -0
- package/dist/lib/fold.d.cts.map +1 -0
- package/dist/lib/fold.d.mts +32 -0
- package/dist/lib/fold.d.mts.map +1 -0
- package/dist/lib/fold.mjs +288 -0
- package/dist/lib/fold.mjs.map +1 -0
- package/dist/lib/log.cjs +116 -0
- package/dist/lib/log.cjs.map +1 -0
- package/dist/lib/log.d.cts +32 -0
- package/dist/lib/log.d.cts.map +1 -0
- package/dist/lib/log.d.mts +32 -0
- package/dist/lib/log.d.mts.map +1 -0
- package/dist/lib/log.mjs +113 -0
- package/dist/lib/log.mjs.map +1 -0
- package/dist/lib/paths.cjs +91 -0
- package/dist/lib/paths.cjs.map +1 -0
- package/dist/lib/paths.d.cts +45 -0
- package/dist/lib/paths.d.cts.map +1 -0
- package/dist/lib/paths.d.mts +45 -0
- package/dist/lib/paths.d.mts.map +1 -0
- package/dist/lib/paths.mjs +82 -0
- package/dist/lib/paths.mjs.map +1 -0
- package/dist/lib/push.cjs +122 -0
- package/dist/lib/push.cjs.map +1 -0
- package/dist/lib/push.d.cts +58 -0
- package/dist/lib/push.d.cts.map +1 -0
- package/dist/lib/push.d.mts +58 -0
- package/dist/lib/push.d.mts.map +1 -0
- package/dist/lib/push.mjs +116 -0
- package/dist/lib/push.mjs.map +1 -0
- package/dist/lib/remoteWrite.cjs +177 -0
- package/dist/lib/remoteWrite.cjs.map +1 -0
- package/dist/lib/remoteWrite.d.cts +24 -0
- package/dist/lib/remoteWrite.d.cts.map +1 -0
- package/dist/lib/remoteWrite.d.mts +24 -0
- package/dist/lib/remoteWrite.d.mts.map +1 -0
- package/dist/lib/remoteWrite.mjs +172 -0
- package/dist/lib/remoteWrite.mjs.map +1 -0
- package/dist/lib/state.cjs +100 -0
- package/dist/lib/state.cjs.map +1 -0
- package/dist/lib/state.d.cts +28 -0
- package/dist/lib/state.d.cts.map +1 -0
- package/dist/lib/state.d.mts +28 -0
- package/dist/lib/state.d.mts.map +1 -0
- package/dist/lib/state.mjs +95 -0
- package/dist/lib/state.mjs.map +1 -0
- package/dist/lib/types.cjs +3 -0
- package/dist/lib/types.cjs.map +1 -0
- package/dist/lib/types.d.cts +82 -0
- package/dist/lib/types.d.cts.map +1 -0
- package/dist/lib/types.d.mts +82 -0
- package/dist/lib/types.d.mts.map +1 -0
- package/dist/lib/types.mjs +2 -0
- package/dist/lib/types.mjs.map +1 -0
- package/dist/run.cjs +137 -0
- package/dist/run.cjs.map +1 -0
- package/dist/run.d.cts +20 -0
- package/dist/run.d.cts.map +1 -0
- package/dist/run.d.mts +20 -0
- package/dist/run.d.mts.map +1 -0
- package/dist/run.mjs +134 -0
- package/dist/run.mjs.map +1 -0
- package/package.json +100 -0
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"remoteWrite.mjs","sourceRoot":"","sources":["../../src/lib/remoteWrite.ts"],"names":[],"mappings":"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","sourcesContent":["// Prometheus remote_write encoder for the daily anonymizer (MCWP-644 / INFRA-3677).\n//\n// The Mimir remote_write endpoint accepts only snappy-compressed protobuf\n// (`WriteRequest`) with per-sample timestamps. Both the protobuf and the snappy\n// block are hand-rolled here so the tool stays dependency-free:\n// - protobuf: the WriteRequest schema is four tiny messages, trivially encoded.\n// - snappy: a valid block can be a single all-literals run (no back-references),\n// which any snappy decoder accepts. We skip real compression — payloads are\n// KB-scale, so the ratio is irrelevant — and avoid pulling a snappy library.\n\nimport type { SamplePoint } from './types';\n\nconst textEncoder = new TextEncoder();\n\n/**\n * Concatenate multiple `Uint8Array` chunks into a single array.\n *\n * @param chunks - Arrays of bytes to concatenate, in order.\n * @returns A single `Uint8Array` containing all chunks concatenated.\n */\nfunction concat(chunks: Uint8Array[]): Uint8Array {\n const total = chunks.reduce((sum, chunk) => sum + chunk.length, 0);\n const out = new Uint8Array(total);\n let offset = 0;\n for (const chunk of chunks) {\n out.set(chunk, offset);\n offset += chunk.length;\n }\n return out;\n}\n\n/**\n * Base-128 varint (protobuf + snappy length preamble). BigInt-safe for int64.\n *\n * @param value - The integer to encode as a varint.\n * @returns Base-128 varint encoding as a `Uint8Array`.\n */\nfunction varint(value: number | bigint): Uint8Array {\n let remaining = typeof value === 'bigint' ? value : BigInt(value);\n const bytes: number[] = [];\n do {\n let byte = Number(remaining & 0x7fn);\n remaining >>= 7n;\n if (remaining > 0n) {\n byte |= 0x80;\n }\n bytes.push(byte);\n } while (remaining > 0n);\n return Uint8Array.from(bytes);\n}\n\n/**\n * A length-delimited (wire type 2) field: tag byte, length varint, then the payload.\n *\n * @param fieldNumber - The protobuf field number (1-based).\n * @param payload - Raw bytes of the field value.\n * @returns Wire-encoded length-delimited field as a `Uint8Array`.\n */\nfunction lengthDelimitedField(\n fieldNumber: number,\n payload: Uint8Array,\n): Uint8Array {\n const tag = (fieldNumber << 3) | 2;\n return concat([varint(tag), varint(payload.length), payload]);\n}\n\n// Label { name = 1; value = 2; }\n/**\n * Encode a Prometheus label name/value pair as a protobuf `Label` message.\n *\n * @param name - Label name.\n * @param value - Label value.\n * @returns Encoded `Label` message as a `Uint8Array`.\n */\nfunction encodeLabel(name: string, value: string): Uint8Array {\n return concat([\n lengthDelimitedField(1, textEncoder.encode(name)),\n lengthDelimitedField(2, textEncoder.encode(value)),\n ]);\n}\n\n// Sample { double value = 1; int64 timestamp = 2; }\n/**\n * Encode a Prometheus sample value and timestamp as a protobuf `Sample` message.\n *\n * @param value - Metric value (float64).\n * @param timestampMs - Timestamp in milliseconds since epoch.\n * @returns Encoded `Sample` message as a `Uint8Array`.\n */\nfunction encodeSample(value: number, timestampMs: number): Uint8Array {\n const valueBytes = new Uint8Array(8);\n new DataView(valueBytes.buffer).setFloat64(0, value, true);\n const valueField = concat([varint((1 << 3) | 1), valueBytes]);\n const timestampField = concat([\n varint((2 << 3) | 0),\n varint(BigInt(timestampMs)),\n ]);\n return concat([valueField, timestampField]);\n}\n\n// TimeSeries { repeated Label labels = 1; repeated Sample samples = 2; }\n/**\n * Encode a single time series (one set of labels with one sample) as a protobuf `TimeSeries`.\n *\n * @param labels - Array of `[name, value]` label pairs.\n * @param value - Metric value for the single sample.\n * @param timestampMs - Timestamp in milliseconds since epoch.\n * @returns Encoded `TimeSeries` message as a `Uint8Array`.\n */\nfunction encodeTimeSeries(\n labels: readonly (readonly [string, string])[],\n value: number,\n timestampMs: number,\n): Uint8Array {\n const labelFields = labels.map(([name, labelValue]) =>\n lengthDelimitedField(1, encodeLabel(name, labelValue)),\n );\n const sampleField = lengthDelimitedField(2, encodeSample(value, timestampMs));\n return concat([...labelFields, sampleField]);\n}\n\n/**\n * Build the sorted label pairs for a sample point, ready for the protobuf encoder.\n *\n * @param sample - The sample point whose labels to extract.\n * @returns Label pairs sorted lexicographically by name (required by Mimir).\n */\nfunction sampleLabels(sample: SamplePoint): [string, string][] {\n // Mimir requires label names sorted lexicographically; `__name__` (ASCII `_` = 95)\n // precedes all lowercase keys, so the array below is already in order.\n // `le` sorts between `instance` and `repo` and is only present on _bucket samples.\n const labels: [string, string][] = [\n ['__name__', sample.metric],\n ['agent_vendor', sample.labels.agent_vendor],\n ['event_type', sample.labels.event_type],\n ['instance', sample.labels.instance],\n ];\n if (sample.le !== undefined) {\n labels.push(['le', sample.le]);\n }\n labels.push(\n ['repo', sample.labels.repo],\n ['tool_name', sample.labels.tool_name],\n ['tool_type', sample.labels.tool_type],\n );\n return labels;\n}\n\n/**\n * Encode a batch of samples as an (uncompressed) `WriteRequest` protobuf.\n *\n * @param samples - Sample points to encode into `TimeSeries` messages.\n * @returns Raw protobuf `WriteRequest` bytes.\n */\nexport function encodeWriteRequest(samples: SamplePoint[]): Uint8Array {\n // WriteRequest { repeated TimeSeries timeseries = 1; }\n const series = samples.map((sample) =>\n lengthDelimitedField(\n 1,\n encodeTimeSeries(sampleLabels(sample), sample.value, sample.timestampMs),\n ),\n );\n return concat(series);\n}\n\n/**\n * Wrap raw bytes in a snappy block as a single all-literals run.\n * Format: varint(uncompressedLength) + literal element(s) + raw bytes.\n *\n * @param data - The raw bytes to wrap.\n * @returns A snappy-framed byte array accepted by any snappy decoder.\n */\nexport function snappyBlock(data: Uint8Array): Uint8Array {\n if (data.length === 0) {\n return varint(0); // valid snappy block: uncompressed length 0, no literals\n }\n\n const preamble = varint(data.length);\n const literalLengthMinusOne = data.length - 1;\n\n if (literalLengthMinusOne < 60) {\n const tag = literalLengthMinusOne << 2; // literal tag, wire type 0b00\n return concat([preamble, Uint8Array.from([tag]), data]);\n }\n\n // Length needs 1-4 extra little-endian bytes; the 6-bit field holds 59 + count.\n const extraBytes: number[] = [];\n let remaining = literalLengthMinusOne;\n while (remaining > 0) {\n extraBytes.push(remaining & 0xff);\n remaining >>>= 8;\n }\n const tag = (59 + extraBytes.length) << 2;\n return concat([preamble, Uint8Array.from([tag, ...extraBytes]), data]);\n}\n\n/**\n * Encode samples into the exact body posted to the remote_write endpoint.\n *\n * @param samples - The sample points to encode.\n * @returns A snappy-wrapped protobuf `WriteRequest`.\n */\nexport function encodeRemoteWrite(samples: SamplePoint[]): Uint8Array {\n return snappyBlock(encodeWriteRequest(samples));\n}\n"]}
|
|
@@ -0,0 +1,100 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
+
exports.readState = readState;
|
|
4
|
+
exports.markRunStart = markRunStart;
|
|
5
|
+
exports.markPushed = markPushed;
|
|
6
|
+
const node_crypto_1 = require("node:crypto");
|
|
7
|
+
const node_fs_1 = require("node:fs");
|
|
8
|
+
const paths_1 = require("./paths.cjs");
|
|
9
|
+
/**
|
|
10
|
+
* Atomic write via temp file + rename (POSIX); mode 0o600 — file holds the per-install UUID.
|
|
11
|
+
*
|
|
12
|
+
* @param path - Absolute path to the target file.
|
|
13
|
+
* @param contents - String contents to write to the file.
|
|
14
|
+
*/
|
|
15
|
+
function writeAtomic(path, contents) {
|
|
16
|
+
// Per-process unique suffix prevents concurrent detached spawns from clobbering each other's temp file.
|
|
17
|
+
const tmp = `${path}.${process.pid}.${(0, node_crypto_1.randomUUID)()}.tmp`;
|
|
18
|
+
(0, node_fs_1.writeFileSync)(tmp, contents, { mode: 0o600 });
|
|
19
|
+
(0, node_fs_1.renameSync)(tmp, path);
|
|
20
|
+
}
|
|
21
|
+
/**
|
|
22
|
+
* Create a fresh anonymizer state with a new random UUID.
|
|
23
|
+
*
|
|
24
|
+
* @returns A new `AnonymizerState` with a freshly generated UUID.
|
|
25
|
+
*/
|
|
26
|
+
function defaultState() {
|
|
27
|
+
return {
|
|
28
|
+
version: 1,
|
|
29
|
+
instance_uuid: (0, node_crypto_1.randomUUID)(),
|
|
30
|
+
last_pushed_day: null,
|
|
31
|
+
last_run_at: null,
|
|
32
|
+
};
|
|
33
|
+
}
|
|
34
|
+
/**
|
|
35
|
+
* Parse a JSON string into an `AnonymizerState`, throwing on invalid structure.
|
|
36
|
+
*
|
|
37
|
+
* @param raw - Raw JSON string read from the state file.
|
|
38
|
+
* @returns The validated `AnonymizerState`.
|
|
39
|
+
*/
|
|
40
|
+
function parseState(raw) {
|
|
41
|
+
const parsed = JSON.parse(raw);
|
|
42
|
+
if (parsed.version !== 1 || typeof parsed.instance_uuid !== 'string') {
|
|
43
|
+
throw new Error('Invalid anonymizer state file');
|
|
44
|
+
}
|
|
45
|
+
return parsed;
|
|
46
|
+
}
|
|
47
|
+
/**
|
|
48
|
+
* Read the anonymizer state from disk, creating a new state file if absent.
|
|
49
|
+
*
|
|
50
|
+
* @param options - Optional state path override.
|
|
51
|
+
* @returns The current anonymizer state.
|
|
52
|
+
*/
|
|
53
|
+
function readState(options = {}) {
|
|
54
|
+
const path = options.statePath ?? (0, paths_1.getStatePath)();
|
|
55
|
+
if ((0, node_fs_1.existsSync)(path)) {
|
|
56
|
+
try {
|
|
57
|
+
return parseState((0, node_fs_1.readFileSync)(path, 'utf8'));
|
|
58
|
+
}
|
|
59
|
+
catch {
|
|
60
|
+
// Corrupt or unreadable state file — recreate rather than wedge the pipeline forever.
|
|
61
|
+
}
|
|
62
|
+
}
|
|
63
|
+
const state = defaultState();
|
|
64
|
+
writeAtomic(path, `${JSON.stringify(state, null, 2)}\n`);
|
|
65
|
+
return state;
|
|
66
|
+
}
|
|
67
|
+
/**
|
|
68
|
+
* Serialise and atomically write state to disk.
|
|
69
|
+
*
|
|
70
|
+
* @param state - The state to serialise and write.
|
|
71
|
+
* @param path - Absolute path to the target state file.
|
|
72
|
+
*/
|
|
73
|
+
function writeState(state, path) {
|
|
74
|
+
writeAtomic(path, `${JSON.stringify(state, null, 2)}\n`);
|
|
75
|
+
}
|
|
76
|
+
/**
|
|
77
|
+
* Record that a run has started by updating `last_run_at`.
|
|
78
|
+
*
|
|
79
|
+
* @param nowIso - ISO-8601 timestamp of the run start.
|
|
80
|
+
* @param options - Optional state path override.
|
|
81
|
+
*/
|
|
82
|
+
function markRunStart(nowIso, options = {}) {
|
|
83
|
+
const path = options.statePath ?? (0, paths_1.getStatePath)();
|
|
84
|
+
const state = readState(options);
|
|
85
|
+
state.last_run_at = nowIso;
|
|
86
|
+
writeState(state, path);
|
|
87
|
+
}
|
|
88
|
+
/**
|
|
89
|
+
* Advance the push cursor to `latestDay` after a successful push.
|
|
90
|
+
*
|
|
91
|
+
* @param latestDay - The latest UTC day that was successfully pushed.
|
|
92
|
+
* @param options - Optional state path override.
|
|
93
|
+
*/
|
|
94
|
+
function markPushed(latestDay, options = {}) {
|
|
95
|
+
const path = options.statePath ?? (0, paths_1.getStatePath)();
|
|
96
|
+
const state = readState(options);
|
|
97
|
+
state.last_pushed_day = latestDay;
|
|
98
|
+
writeState(state, path);
|
|
99
|
+
}
|
|
100
|
+
//# sourceMappingURL=state.cjs.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"state.cjs","sourceRoot":"","sources":["../../src/lib/state.ts"],"names":[],"mappings":";;AA2DA,8BAYC;AAkBD,oCAQC;AAQD,gCAQC;AAjHD,6CAAyC;AACzC,qCAA8E;AAE9E,uCAAuC;AASvC;;;;;GAKG;AACH,SAAS,WAAW,CAAC,IAAY,EAAE,QAAgB;IACjD,wGAAwG;IACxG,MAAM,GAAG,GAAG,GAAG,IAAI,IAAI,OAAO,CAAC,GAAG,IAAI,IAAA,wBAAU,GAAE,MAAM,CAAC;IACzD,IAAA,uBAAa,EAAC,GAAG,EAAE,QAAQ,EAAE,EAAE,IAAI,EAAE,KAAK,EAAE,CAAC,CAAC;IAC9C,IAAA,oBAAU,EAAC,GAAG,EAAE,IAAI,CAAC,CAAC;AACxB,CAAC;AAED;;;;GAIG;AACH,SAAS,YAAY;IACnB,OAAO;QACL,OAAO,EAAE,CAAC;QACV,aAAa,EAAE,IAAA,wBAAU,GAAE;QAC3B,eAAe,EAAE,IAAI;QACrB,WAAW,EAAE,IAAI;KAClB,CAAC;AACJ,CAAC;AAED;;;;;GAKG;AACH,SAAS,UAAU,CAAC,GAAW;IAC7B,MAAM,MAAM,GAAG,IAAI,CAAC,KAAK,CAAC,GAAG,CAAoB,CAAC;IAClD,IAAI,MAAM,CAAC,OAAO,KAAK,CAAC,IAAI,OAAO,MAAM,CAAC,aAAa,KAAK,QAAQ,EAAE,CAAC;QACrE,MAAM,IAAI,KAAK,CAAC,+BAA+B,CAAC,CAAC;IACnD,CAAC;IACD,OAAO,MAAM,CAAC;AAChB,CAAC;AAED;;;;;GAKG;AACH,SAAgB,SAAS,CAAC,UAA6B,EAAE;IACvD,MAAM,IAAI,GAAG,OAAO,CAAC,SAAS,IAAI,IAAA,oBAAY,GAAE,CAAC;IACjD,IAAI,IAAA,oBAAU,EAAC,IAAI,CAAC,EAAE,CAAC;QACrB,IAAI,CAAC;YACH,OAAO,UAAU,CAAC,IAAA,sBAAY,EAAC,IAAI,EAAE,MAAM,CAAC,CAAC,CAAC;QAChD,CAAC;QAAC,MAAM,CAAC;YACP,sFAAsF;QACxF,CAAC;IACH,CAAC;IACD,MAAM,KAAK,GAAG,YAAY,EAAE,CAAC;IAC7B,WAAW,CAAC,IAAI,EAAE,GAAG,IAAI,CAAC,SAAS,CAAC,KAAK,EAAE,IAAI,EAAE,CAAC,CAAC,IAAI,CAAC,CAAC;IACzD,OAAO,KAAK,CAAC;AACf,CAAC;AAED;;;;;GAKG;AACH,SAAS,UAAU,CAAC,KAAsB,EAAE,IAAY;IACtD,WAAW,CAAC,IAAI,EAAE,GAAG,IAAI,CAAC,SAAS,CAAC,KAAK,EAAE,IAAI,EAAE,CAAC,CAAC,IAAI,CAAC,CAAC;AAC3D,CAAC;AAED;;;;;GAKG;AACH,SAAgB,YAAY,CAC1B,MAAc,EACd,UAA6B,EAAE;IAE/B,MAAM,IAAI,GAAG,OAAO,CAAC,SAAS,IAAI,IAAA,oBAAY,GAAE,CAAC;IACjD,MAAM,KAAK,GAAG,SAAS,CAAC,OAAO,CAAC,CAAC;IACjC,KAAK,CAAC,WAAW,GAAG,MAAM,CAAC;IAC3B,UAAU,CAAC,KAAK,EAAE,IAAI,CAAC,CAAC;AAC1B,CAAC;AAED;;;;;GAKG;AACH,SAAgB,UAAU,CACxB,SAAiB,EACjB,UAA6B,EAAE;IAE/B,MAAM,IAAI,GAAG,OAAO,CAAC,SAAS,IAAI,IAAA,oBAAY,GAAE,CAAC;IACjD,MAAM,KAAK,GAAG,SAAS,CAAC,OAAO,CAAC,CAAC;IACjC,KAAK,CAAC,eAAe,GAAG,SAAS,CAAC;IAClC,UAAU,CAAC,KAAK,EAAE,IAAI,CAAC,CAAC;AAC1B,CAAC","sourcesContent":["import { randomUUID } from 'node:crypto';\nimport { existsSync, readFileSync, renameSync, writeFileSync } from 'node:fs';\n\nimport { getStatePath } from './paths';\nimport type { AnonymizerState } from './types';\n\n/** Options for state store functions. */\nexport type StateStoreOptions = {\n /** Absolute path to the state JSON file; defaults to `getStatePath()`. */\n statePath?: string;\n};\n\n/**\n * Atomic write via temp file + rename (POSIX); mode 0o600 — file holds the per-install UUID.\n *\n * @param path - Absolute path to the target file.\n * @param contents - String contents to write to the file.\n */\nfunction writeAtomic(path: string, contents: string): void {\n // Per-process unique suffix prevents concurrent detached spawns from clobbering each other's temp file.\n const tmp = `${path}.${process.pid}.${randomUUID()}.tmp`;\n writeFileSync(tmp, contents, { mode: 0o600 });\n renameSync(tmp, path);\n}\n\n/**\n * Create a fresh anonymizer state with a new random UUID.\n *\n * @returns A new `AnonymizerState` with a freshly generated UUID.\n */\nfunction defaultState(): AnonymizerState {\n return {\n version: 1,\n instance_uuid: randomUUID(),\n last_pushed_day: null,\n last_run_at: null,\n };\n}\n\n/**\n * Parse a JSON string into an `AnonymizerState`, throwing on invalid structure.\n *\n * @param raw - Raw JSON string read from the state file.\n * @returns The validated `AnonymizerState`.\n */\nfunction parseState(raw: string): AnonymizerState {\n const parsed = JSON.parse(raw) as AnonymizerState;\n if (parsed.version !== 1 || typeof parsed.instance_uuid !== 'string') {\n throw new Error('Invalid anonymizer state file');\n }\n return parsed;\n}\n\n/**\n * Read the anonymizer state from disk, creating a new state file if absent.\n *\n * @param options - Optional state path override.\n * @returns The current anonymizer state.\n */\nexport function readState(options: StateStoreOptions = {}): AnonymizerState {\n const path = options.statePath ?? getStatePath();\n if (existsSync(path)) {\n try {\n return parseState(readFileSync(path, 'utf8'));\n } catch {\n // Corrupt or unreadable state file — recreate rather than wedge the pipeline forever.\n }\n }\n const state = defaultState();\n writeAtomic(path, `${JSON.stringify(state, null, 2)}\\n`);\n return state;\n}\n\n/**\n * Serialise and atomically write state to disk.\n *\n * @param state - The state to serialise and write.\n * @param path - Absolute path to the target state file.\n */\nfunction writeState(state: AnonymizerState, path: string): void {\n writeAtomic(path, `${JSON.stringify(state, null, 2)}\\n`);\n}\n\n/**\n * Record that a run has started by updating `last_run_at`.\n *\n * @param nowIso - ISO-8601 timestamp of the run start.\n * @param options - Optional state path override.\n */\nexport function markRunStart(\n nowIso: string,\n options: StateStoreOptions = {},\n): void {\n const path = options.statePath ?? getStatePath();\n const state = readState(options);\n state.last_run_at = nowIso;\n writeState(state, path);\n}\n\n/**\n * Advance the push cursor to `latestDay` after a successful push.\n *\n * @param latestDay - The latest UTC day that was successfully pushed.\n * @param options - Optional state path override.\n */\nexport function markPushed(\n latestDay: string,\n options: StateStoreOptions = {},\n): void {\n const path = options.statePath ?? getStatePath();\n const state = readState(options);\n state.last_pushed_day = latestDay;\n writeState(state, path);\n}\n"]}
|
|
@@ -0,0 +1,28 @@
|
|
|
1
|
+
import type { AnonymizerState } from "./types.cjs";
|
|
2
|
+
/** Options for state store functions. */
|
|
3
|
+
export type StateStoreOptions = {
|
|
4
|
+
/** Absolute path to the state JSON file; defaults to `getStatePath()`. */
|
|
5
|
+
statePath?: string;
|
|
6
|
+
};
|
|
7
|
+
/**
|
|
8
|
+
* Read the anonymizer state from disk, creating a new state file if absent.
|
|
9
|
+
*
|
|
10
|
+
* @param options - Optional state path override.
|
|
11
|
+
* @returns The current anonymizer state.
|
|
12
|
+
*/
|
|
13
|
+
export declare function readState(options?: StateStoreOptions): AnonymizerState;
|
|
14
|
+
/**
|
|
15
|
+
* Record that a run has started by updating `last_run_at`.
|
|
16
|
+
*
|
|
17
|
+
* @param nowIso - ISO-8601 timestamp of the run start.
|
|
18
|
+
* @param options - Optional state path override.
|
|
19
|
+
*/
|
|
20
|
+
export declare function markRunStart(nowIso: string, options?: StateStoreOptions): void;
|
|
21
|
+
/**
|
|
22
|
+
* Advance the push cursor to `latestDay` after a successful push.
|
|
23
|
+
*
|
|
24
|
+
* @param latestDay - The latest UTC day that was successfully pushed.
|
|
25
|
+
* @param options - Optional state path override.
|
|
26
|
+
*/
|
|
27
|
+
export declare function markPushed(latestDay: string, options?: StateStoreOptions): void;
|
|
28
|
+
//# sourceMappingURL=state.d.cts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"state.d.cts","sourceRoot":"","sources":["../../src/lib/state.ts"],"names":[],"mappings":"AAIA,OAAO,KAAK,EAAE,eAAe,EAAE,oBAAgB;AAE/C,yCAAyC;AACzC,MAAM,MAAM,iBAAiB,GAAG;IAC9B,0EAA0E;IAC1E,SAAS,CAAC,EAAE,MAAM,CAAC;CACpB,CAAC;AA2CF;;;;;GAKG;AACH,wBAAgB,SAAS,CAAC,OAAO,GAAE,iBAAsB,GAAG,eAAe,CAY1E;AAYD;;;;;GAKG;AACH,wBAAgB,YAAY,CAC1B,MAAM,EAAE,MAAM,EACd,OAAO,GAAE,iBAAsB,GAC9B,IAAI,CAKN;AAED;;;;;GAKG;AACH,wBAAgB,UAAU,CACxB,SAAS,EAAE,MAAM,EACjB,OAAO,GAAE,iBAAsB,GAC9B,IAAI,CAKN"}
|
|
@@ -0,0 +1,28 @@
|
|
|
1
|
+
import type { AnonymizerState } from "./types.mjs";
|
|
2
|
+
/** Options for state store functions. */
|
|
3
|
+
export type StateStoreOptions = {
|
|
4
|
+
/** Absolute path to the state JSON file; defaults to `getStatePath()`. */
|
|
5
|
+
statePath?: string;
|
|
6
|
+
};
|
|
7
|
+
/**
|
|
8
|
+
* Read the anonymizer state from disk, creating a new state file if absent.
|
|
9
|
+
*
|
|
10
|
+
* @param options - Optional state path override.
|
|
11
|
+
* @returns The current anonymizer state.
|
|
12
|
+
*/
|
|
13
|
+
export declare function readState(options?: StateStoreOptions): AnonymizerState;
|
|
14
|
+
/**
|
|
15
|
+
* Record that a run has started by updating `last_run_at`.
|
|
16
|
+
*
|
|
17
|
+
* @param nowIso - ISO-8601 timestamp of the run start.
|
|
18
|
+
* @param options - Optional state path override.
|
|
19
|
+
*/
|
|
20
|
+
export declare function markRunStart(nowIso: string, options?: StateStoreOptions): void;
|
|
21
|
+
/**
|
|
22
|
+
* Advance the push cursor to `latestDay` after a successful push.
|
|
23
|
+
*
|
|
24
|
+
* @param latestDay - The latest UTC day that was successfully pushed.
|
|
25
|
+
* @param options - Optional state path override.
|
|
26
|
+
*/
|
|
27
|
+
export declare function markPushed(latestDay: string, options?: StateStoreOptions): void;
|
|
28
|
+
//# sourceMappingURL=state.d.mts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"state.d.mts","sourceRoot":"","sources":["../../src/lib/state.ts"],"names":[],"mappings":"AAIA,OAAO,KAAK,EAAE,eAAe,EAAE,oBAAgB;AAE/C,yCAAyC;AACzC,MAAM,MAAM,iBAAiB,GAAG;IAC9B,0EAA0E;IAC1E,SAAS,CAAC,EAAE,MAAM,CAAC;CACpB,CAAC;AA2CF;;;;;GAKG;AACH,wBAAgB,SAAS,CAAC,OAAO,GAAE,iBAAsB,GAAG,eAAe,CAY1E;AAYD;;;;;GAKG;AACH,wBAAgB,YAAY,CAC1B,MAAM,EAAE,MAAM,EACd,OAAO,GAAE,iBAAsB,GAC9B,IAAI,CAKN;AAED;;;;;GAKG;AACH,wBAAgB,UAAU,CACxB,SAAS,EAAE,MAAM,EACjB,OAAO,GAAE,iBAAsB,GAC9B,IAAI,CAKN"}
|
|
@@ -0,0 +1,95 @@
|
|
|
1
|
+
import { randomUUID } from "node:crypto";
|
|
2
|
+
import { existsSync, readFileSync, renameSync, writeFileSync } from "node:fs";
|
|
3
|
+
import { getStatePath } from "./paths.mjs";
|
|
4
|
+
/**
|
|
5
|
+
* Atomic write via temp file + rename (POSIX); mode 0o600 — file holds the per-install UUID.
|
|
6
|
+
*
|
|
7
|
+
* @param path - Absolute path to the target file.
|
|
8
|
+
* @param contents - String contents to write to the file.
|
|
9
|
+
*/
|
|
10
|
+
function writeAtomic(path, contents) {
|
|
11
|
+
// Per-process unique suffix prevents concurrent detached spawns from clobbering each other's temp file.
|
|
12
|
+
const tmp = `${path}.${process.pid}.${randomUUID()}.tmp`;
|
|
13
|
+
writeFileSync(tmp, contents, { mode: 0o600 });
|
|
14
|
+
renameSync(tmp, path);
|
|
15
|
+
}
|
|
16
|
+
/**
|
|
17
|
+
* Create a fresh anonymizer state with a new random UUID.
|
|
18
|
+
*
|
|
19
|
+
* @returns A new `AnonymizerState` with a freshly generated UUID.
|
|
20
|
+
*/
|
|
21
|
+
function defaultState() {
|
|
22
|
+
return {
|
|
23
|
+
version: 1,
|
|
24
|
+
instance_uuid: randomUUID(),
|
|
25
|
+
last_pushed_day: null,
|
|
26
|
+
last_run_at: null,
|
|
27
|
+
};
|
|
28
|
+
}
|
|
29
|
+
/**
|
|
30
|
+
* Parse a JSON string into an `AnonymizerState`, throwing on invalid structure.
|
|
31
|
+
*
|
|
32
|
+
* @param raw - Raw JSON string read from the state file.
|
|
33
|
+
* @returns The validated `AnonymizerState`.
|
|
34
|
+
*/
|
|
35
|
+
function parseState(raw) {
|
|
36
|
+
const parsed = JSON.parse(raw);
|
|
37
|
+
if (parsed.version !== 1 || typeof parsed.instance_uuid !== 'string') {
|
|
38
|
+
throw new Error('Invalid anonymizer state file');
|
|
39
|
+
}
|
|
40
|
+
return parsed;
|
|
41
|
+
}
|
|
42
|
+
/**
|
|
43
|
+
* Read the anonymizer state from disk, creating a new state file if absent.
|
|
44
|
+
*
|
|
45
|
+
* @param options - Optional state path override.
|
|
46
|
+
* @returns The current anonymizer state.
|
|
47
|
+
*/
|
|
48
|
+
export function readState(options = {}) {
|
|
49
|
+
const path = options.statePath ?? getStatePath();
|
|
50
|
+
if (existsSync(path)) {
|
|
51
|
+
try {
|
|
52
|
+
return parseState(readFileSync(path, 'utf8'));
|
|
53
|
+
}
|
|
54
|
+
catch {
|
|
55
|
+
// Corrupt or unreadable state file — recreate rather than wedge the pipeline forever.
|
|
56
|
+
}
|
|
57
|
+
}
|
|
58
|
+
const state = defaultState();
|
|
59
|
+
writeAtomic(path, `${JSON.stringify(state, null, 2)}\n`);
|
|
60
|
+
return state;
|
|
61
|
+
}
|
|
62
|
+
/**
|
|
63
|
+
* Serialise and atomically write state to disk.
|
|
64
|
+
*
|
|
65
|
+
* @param state - The state to serialise and write.
|
|
66
|
+
* @param path - Absolute path to the target state file.
|
|
67
|
+
*/
|
|
68
|
+
function writeState(state, path) {
|
|
69
|
+
writeAtomic(path, `${JSON.stringify(state, null, 2)}\n`);
|
|
70
|
+
}
|
|
71
|
+
/**
|
|
72
|
+
* Record that a run has started by updating `last_run_at`.
|
|
73
|
+
*
|
|
74
|
+
* @param nowIso - ISO-8601 timestamp of the run start.
|
|
75
|
+
* @param options - Optional state path override.
|
|
76
|
+
*/
|
|
77
|
+
export function markRunStart(nowIso, options = {}) {
|
|
78
|
+
const path = options.statePath ?? getStatePath();
|
|
79
|
+
const state = readState(options);
|
|
80
|
+
state.last_run_at = nowIso;
|
|
81
|
+
writeState(state, path);
|
|
82
|
+
}
|
|
83
|
+
/**
|
|
84
|
+
* Advance the push cursor to `latestDay` after a successful push.
|
|
85
|
+
*
|
|
86
|
+
* @param latestDay - The latest UTC day that was successfully pushed.
|
|
87
|
+
* @param options - Optional state path override.
|
|
88
|
+
*/
|
|
89
|
+
export function markPushed(latestDay, options = {}) {
|
|
90
|
+
const path = options.statePath ?? getStatePath();
|
|
91
|
+
const state = readState(options);
|
|
92
|
+
state.last_pushed_day = latestDay;
|
|
93
|
+
writeState(state, path);
|
|
94
|
+
}
|
|
95
|
+
//# sourceMappingURL=state.mjs.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"state.mjs","sourceRoot":"","sources":["../../src/lib/state.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,UAAU,EAAE,oBAAoB;AACzC,OAAO,EAAE,UAAU,EAAE,YAAY,EAAE,UAAU,EAAE,aAAa,EAAE,gBAAgB;AAE9E,OAAO,EAAE,YAAY,EAAE,oBAAgB;AASvC;;;;;GAKG;AACH,SAAS,WAAW,CAAC,IAAY,EAAE,QAAgB;IACjD,wGAAwG;IACxG,MAAM,GAAG,GAAG,GAAG,IAAI,IAAI,OAAO,CAAC,GAAG,IAAI,UAAU,EAAE,MAAM,CAAC;IACzD,aAAa,CAAC,GAAG,EAAE,QAAQ,EAAE,EAAE,IAAI,EAAE,KAAK,EAAE,CAAC,CAAC;IAC9C,UAAU,CAAC,GAAG,EAAE,IAAI,CAAC,CAAC;AACxB,CAAC;AAED;;;;GAIG;AACH,SAAS,YAAY;IACnB,OAAO;QACL,OAAO,EAAE,CAAC;QACV,aAAa,EAAE,UAAU,EAAE;QAC3B,eAAe,EAAE,IAAI;QACrB,WAAW,EAAE,IAAI;KAClB,CAAC;AACJ,CAAC;AAED;;;;;GAKG;AACH,SAAS,UAAU,CAAC,GAAW;IAC7B,MAAM,MAAM,GAAG,IAAI,CAAC,KAAK,CAAC,GAAG,CAAoB,CAAC;IAClD,IAAI,MAAM,CAAC,OAAO,KAAK,CAAC,IAAI,OAAO,MAAM,CAAC,aAAa,KAAK,QAAQ,EAAE,CAAC;QACrE,MAAM,IAAI,KAAK,CAAC,+BAA+B,CAAC,CAAC;IACnD,CAAC;IACD,OAAO,MAAM,CAAC;AAChB,CAAC;AAED;;;;;GAKG;AACH,MAAM,UAAU,SAAS,CAAC,UAA6B,EAAE;IACvD,MAAM,IAAI,GAAG,OAAO,CAAC,SAAS,IAAI,YAAY,EAAE,CAAC;IACjD,IAAI,UAAU,CAAC,IAAI,CAAC,EAAE,CAAC;QACrB,IAAI,CAAC;YACH,OAAO,UAAU,CAAC,YAAY,CAAC,IAAI,EAAE,MAAM,CAAC,CAAC,CAAC;QAChD,CAAC;QAAC,MAAM,CAAC;YACP,sFAAsF;QACxF,CAAC;IACH,CAAC;IACD,MAAM,KAAK,GAAG,YAAY,EAAE,CAAC;IAC7B,WAAW,CAAC,IAAI,EAAE,GAAG,IAAI,CAAC,SAAS,CAAC,KAAK,EAAE,IAAI,EAAE,CAAC,CAAC,IAAI,CAAC,CAAC;IACzD,OAAO,KAAK,CAAC;AACf,CAAC;AAED;;;;;GAKG;AACH,SAAS,UAAU,CAAC,KAAsB,EAAE,IAAY;IACtD,WAAW,CAAC,IAAI,EAAE,GAAG,IAAI,CAAC,SAAS,CAAC,KAAK,EAAE,IAAI,EAAE,CAAC,CAAC,IAAI,CAAC,CAAC;AAC3D,CAAC;AAED;;;;;GAKG;AACH,MAAM,UAAU,YAAY,CAC1B,MAAc,EACd,UAA6B,EAAE;IAE/B,MAAM,IAAI,GAAG,OAAO,CAAC,SAAS,IAAI,YAAY,EAAE,CAAC;IACjD,MAAM,KAAK,GAAG,SAAS,CAAC,OAAO,CAAC,CAAC;IACjC,KAAK,CAAC,WAAW,GAAG,MAAM,CAAC;IAC3B,UAAU,CAAC,KAAK,EAAE,IAAI,CAAC,CAAC;AAC1B,CAAC;AAED;;;;;GAKG;AACH,MAAM,UAAU,UAAU,CACxB,SAAiB,EACjB,UAA6B,EAAE;IAE/B,MAAM,IAAI,GAAG,OAAO,CAAC,SAAS,IAAI,YAAY,EAAE,CAAC;IACjD,MAAM,KAAK,GAAG,SAAS,CAAC,OAAO,CAAC,CAAC;IACjC,KAAK,CAAC,eAAe,GAAG,SAAS,CAAC;IAClC,UAAU,CAAC,KAAK,EAAE,IAAI,CAAC,CAAC;AAC1B,CAAC","sourcesContent":["import { randomUUID } from 'node:crypto';\nimport { existsSync, readFileSync, renameSync, writeFileSync } from 'node:fs';\n\nimport { getStatePath } from './paths';\nimport type { AnonymizerState } from './types';\n\n/** Options for state store functions. */\nexport type StateStoreOptions = {\n /** Absolute path to the state JSON file; defaults to `getStatePath()`. */\n statePath?: string;\n};\n\n/**\n * Atomic write via temp file + rename (POSIX); mode 0o600 — file holds the per-install UUID.\n *\n * @param path - Absolute path to the target file.\n * @param contents - String contents to write to the file.\n */\nfunction writeAtomic(path: string, contents: string): void {\n // Per-process unique suffix prevents concurrent detached spawns from clobbering each other's temp file.\n const tmp = `${path}.${process.pid}.${randomUUID()}.tmp`;\n writeFileSync(tmp, contents, { mode: 0o600 });\n renameSync(tmp, path);\n}\n\n/**\n * Create a fresh anonymizer state with a new random UUID.\n *\n * @returns A new `AnonymizerState` with a freshly generated UUID.\n */\nfunction defaultState(): AnonymizerState {\n return {\n version: 1,\n instance_uuid: randomUUID(),\n last_pushed_day: null,\n last_run_at: null,\n };\n}\n\n/**\n * Parse a JSON string into an `AnonymizerState`, throwing on invalid structure.\n *\n * @param raw - Raw JSON string read from the state file.\n * @returns The validated `AnonymizerState`.\n */\nfunction parseState(raw: string): AnonymizerState {\n const parsed = JSON.parse(raw) as AnonymizerState;\n if (parsed.version !== 1 || typeof parsed.instance_uuid !== 'string') {\n throw new Error('Invalid anonymizer state file');\n }\n return parsed;\n}\n\n/**\n * Read the anonymizer state from disk, creating a new state file if absent.\n *\n * @param options - Optional state path override.\n * @returns The current anonymizer state.\n */\nexport function readState(options: StateStoreOptions = {}): AnonymizerState {\n const path = options.statePath ?? getStatePath();\n if (existsSync(path)) {\n try {\n return parseState(readFileSync(path, 'utf8'));\n } catch {\n // Corrupt or unreadable state file — recreate rather than wedge the pipeline forever.\n }\n }\n const state = defaultState();\n writeAtomic(path, `${JSON.stringify(state, null, 2)}\\n`);\n return state;\n}\n\n/**\n * Serialise and atomically write state to disk.\n *\n * @param state - The state to serialise and write.\n * @param path - Absolute path to the target state file.\n */\nfunction writeState(state: AnonymizerState, path: string): void {\n writeAtomic(path, `${JSON.stringify(state, null, 2)}\\n`);\n}\n\n/**\n * Record that a run has started by updating `last_run_at`.\n *\n * @param nowIso - ISO-8601 timestamp of the run start.\n * @param options - Optional state path override.\n */\nexport function markRunStart(\n nowIso: string,\n options: StateStoreOptions = {},\n): void {\n const path = options.statePath ?? getStatePath();\n const state = readState(options);\n state.last_run_at = nowIso;\n writeState(state, path);\n}\n\n/**\n * Advance the push cursor to `latestDay` after a successful push.\n *\n * @param latestDay - The latest UTC day that was successfully pushed.\n * @param options - Optional state path override.\n */\nexport function markPushed(\n latestDay: string,\n options: StateStoreOptions = {},\n): void {\n const path = options.statePath ?? getStatePath();\n const state = readState(options);\n state.last_pushed_day = latestDay;\n writeState(state, path);\n}\n"]}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"types.cjs","sourceRoot":"","sources":["../../src/lib/types.ts"],"names":[],"mappings":"","sourcesContent":["/** CSV `event_type` column — raw values before fold maps `end` + success to terminal labels. */\nexport type CsvEventType = 'start' | 'end' | 'interrupted';\n\n/** Emitted Prometheus `event_type` label after fold applies the success mapping table. */\nexport type EventTypeLabel = 'start' | 'success' | 'failure' | 'interrupted';\n\n/** The type of tool that emitted the event. */\nexport type ToolType = 'skill' | 'yarn_script';\n\n/** One parsed row from a `*-events.log` source file, with `repo` derived from the filename. */\nexport type ToolEvent = {\n /** Name of the repo that the tool ran in, derived from the log filename. */\n repo: string;\n /** Raw tool name as recorded by the collector (may include a `skill:` or `yarn:` prefix). */\n tool_name: string;\n /** Whether the tool is a Cursor skill or a yarn script. */\n tool_type: ToolType;\n /** Raw CSV event type — `start`, `end`, or `interrupted`. */\n event_type: CsvEventType;\n /** AI agent that triggered the tool (e.g. `cursor`), or empty string for human invocations. */\n agent_vendor: string;\n /** Opaque session identifier grouping a start/end pair. */\n session_id: string;\n /** Outcome for `end` events — `true` for success, `false` for failure, `null` when absent. */\n success: boolean | null;\n /** Wall-clock duration of the tool run in milliseconds, or `null` when not recorded. */\n duration_ms: number | null;\n /** ISO-8601 UTC timestamp at which the event was recorded. */\n created_at: string;\n};\n\n/** The two Prometheus metric names emitted by the anonymizer. */\nexport type MetricName =\n | 'metamask_devtools_usage_count'\n | 'metamask_devtools_duration_sum_ms'\n | 'metamask_devtools_duration_ms_bucket'\n | 'metamask_devtools_duration_ms_sum'\n | 'metamask_devtools_duration_ms_count';\n\n/** Prometheus label set shared by both emitted metrics (fold group key minus `day`). */\nexport type SampleLabels = {\n /** Repository name (derived from the events-log filename). */\n repo: string;\n /** Tool name after prefix stripping, used as a Prometheus label. */\n tool_name: string;\n /** Tool type (`skill` or `yarn_script`). */\n tool_type: ToolType;\n /** Outcome category: `start`, `success`, `failure`, or `interrupted`. */\n event_type: EventTypeLabel;\n /** AI agent vendor string, or empty for human-triggered events. */\n agent_vendor: string;\n /** Per-install UUID that anonymizes the contributor identity. */\n instance: string;\n};\n\n/** One counter sample for exposition — one element per `(metric, labels, day)` tuple. */\nexport type SamplePoint = {\n /** Prometheus metric name for this sample. */\n metric: MetricName;\n /** Full Prometheus label set for this sample. */\n labels: SampleLabels;\n /** Accumulated counter value (event count or duration sum). */\n value: number;\n /** UTC calendar day bucket (`YYYY-MM-DD`). */\n day: string;\n /** UTC midnight of `day` in milliseconds (Prometheus sample timestamp). */\n timestampMs: number;\n /**\n * Upper bound for histogram bucket samples (`metamask_devtools_duration_ms_bucket`).\n * Holds the stringified numeric boundary (e.g. `\"1000\"`) or `\"+Inf\"`.\n * Absent on all other metric types.\n */\n le?: string;\n};\n\n/** Persisted anonymizer state file shape. */\nexport type AnonymizerState = {\n /** Schema version; must be `1`. */\n version: 1;\n /** Per-install random UUID that anonymizes contributor identity across pushes. */\n instance_uuid: string;\n /** Last UTC day successfully pushed (`YYYY-MM-DD`), or null before first push. */\n last_pushed_day: string | null;\n /** ISO-8601 UTC timestamp of the last anonymize run, or null before first run. */\n last_run_at: string | null;\n};\n\n/** Skill names are stored with the `mms-` prefix; yarn script names are bare keys from package.json. */\nexport type Allowlist = {\n /** Set of allowlisted skill names, each prefixed with `mms-`. */\n skills: ReadonlySet<string>;\n /** Set of allowlisted yarn script names (bare keys from the consuming repo's `package.json`). */\n scripts: ReadonlySet<string>;\n};\n"]}
|
|
@@ -0,0 +1,82 @@
|
|
|
1
|
+
/** CSV `event_type` column — raw values before fold maps `end` + success to terminal labels. */
|
|
2
|
+
export type CsvEventType = 'start' | 'end' | 'interrupted';
|
|
3
|
+
/** Emitted Prometheus `event_type` label after fold applies the success mapping table. */
|
|
4
|
+
export type EventTypeLabel = 'start' | 'success' | 'failure' | 'interrupted';
|
|
5
|
+
/** The type of tool that emitted the event. */
|
|
6
|
+
export type ToolType = 'skill' | 'yarn_script';
|
|
7
|
+
/** One parsed row from a `*-events.log` source file, with `repo` derived from the filename. */
|
|
8
|
+
export type ToolEvent = {
|
|
9
|
+
/** Name of the repo that the tool ran in, derived from the log filename. */
|
|
10
|
+
repo: string;
|
|
11
|
+
/** Raw tool name as recorded by the collector (may include a `skill:` or `yarn:` prefix). */
|
|
12
|
+
tool_name: string;
|
|
13
|
+
/** Whether the tool is a Cursor skill or a yarn script. */
|
|
14
|
+
tool_type: ToolType;
|
|
15
|
+
/** Raw CSV event type — `start`, `end`, or `interrupted`. */
|
|
16
|
+
event_type: CsvEventType;
|
|
17
|
+
/** AI agent that triggered the tool (e.g. `cursor`), or empty string for human invocations. */
|
|
18
|
+
agent_vendor: string;
|
|
19
|
+
/** Opaque session identifier grouping a start/end pair. */
|
|
20
|
+
session_id: string;
|
|
21
|
+
/** Outcome for `end` events — `true` for success, `false` for failure, `null` when absent. */
|
|
22
|
+
success: boolean | null;
|
|
23
|
+
/** Wall-clock duration of the tool run in milliseconds, or `null` when not recorded. */
|
|
24
|
+
duration_ms: number | null;
|
|
25
|
+
/** ISO-8601 UTC timestamp at which the event was recorded. */
|
|
26
|
+
created_at: string;
|
|
27
|
+
};
|
|
28
|
+
/** The two Prometheus metric names emitted by the anonymizer. */
|
|
29
|
+
export type MetricName = 'metamask_devtools_usage_count' | 'metamask_devtools_duration_sum_ms' | 'metamask_devtools_duration_ms_bucket' | 'metamask_devtools_duration_ms_sum' | 'metamask_devtools_duration_ms_count';
|
|
30
|
+
/** Prometheus label set shared by both emitted metrics (fold group key minus `day`). */
|
|
31
|
+
export type SampleLabels = {
|
|
32
|
+
/** Repository name (derived from the events-log filename). */
|
|
33
|
+
repo: string;
|
|
34
|
+
/** Tool name after prefix stripping, used as a Prometheus label. */
|
|
35
|
+
tool_name: string;
|
|
36
|
+
/** Tool type (`skill` or `yarn_script`). */
|
|
37
|
+
tool_type: ToolType;
|
|
38
|
+
/** Outcome category: `start`, `success`, `failure`, or `interrupted`. */
|
|
39
|
+
event_type: EventTypeLabel;
|
|
40
|
+
/** AI agent vendor string, or empty for human-triggered events. */
|
|
41
|
+
agent_vendor: string;
|
|
42
|
+
/** Per-install UUID that anonymizes the contributor identity. */
|
|
43
|
+
instance: string;
|
|
44
|
+
};
|
|
45
|
+
/** One counter sample for exposition — one element per `(metric, labels, day)` tuple. */
|
|
46
|
+
export type SamplePoint = {
|
|
47
|
+
/** Prometheus metric name for this sample. */
|
|
48
|
+
metric: MetricName;
|
|
49
|
+
/** Full Prometheus label set for this sample. */
|
|
50
|
+
labels: SampleLabels;
|
|
51
|
+
/** Accumulated counter value (event count or duration sum). */
|
|
52
|
+
value: number;
|
|
53
|
+
/** UTC calendar day bucket (`YYYY-MM-DD`). */
|
|
54
|
+
day: string;
|
|
55
|
+
/** UTC midnight of `day` in milliseconds (Prometheus sample timestamp). */
|
|
56
|
+
timestampMs: number;
|
|
57
|
+
/**
|
|
58
|
+
* Upper bound for histogram bucket samples (`metamask_devtools_duration_ms_bucket`).
|
|
59
|
+
* Holds the stringified numeric boundary (e.g. `"1000"`) or `"+Inf"`.
|
|
60
|
+
* Absent on all other metric types.
|
|
61
|
+
*/
|
|
62
|
+
le?: string;
|
|
63
|
+
};
|
|
64
|
+
/** Persisted anonymizer state file shape. */
|
|
65
|
+
export type AnonymizerState = {
|
|
66
|
+
/** Schema version; must be `1`. */
|
|
67
|
+
version: 1;
|
|
68
|
+
/** Per-install random UUID that anonymizes contributor identity across pushes. */
|
|
69
|
+
instance_uuid: string;
|
|
70
|
+
/** Last UTC day successfully pushed (`YYYY-MM-DD`), or null before first push. */
|
|
71
|
+
last_pushed_day: string | null;
|
|
72
|
+
/** ISO-8601 UTC timestamp of the last anonymize run, or null before first run. */
|
|
73
|
+
last_run_at: string | null;
|
|
74
|
+
};
|
|
75
|
+
/** Skill names are stored with the `mms-` prefix; yarn script names are bare keys from package.json. */
|
|
76
|
+
export type Allowlist = {
|
|
77
|
+
/** Set of allowlisted skill names, each prefixed with `mms-`. */
|
|
78
|
+
skills: ReadonlySet<string>;
|
|
79
|
+
/** Set of allowlisted yarn script names (bare keys from the consuming repo's `package.json`). */
|
|
80
|
+
scripts: ReadonlySet<string>;
|
|
81
|
+
};
|
|
82
|
+
//# sourceMappingURL=types.d.cts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"types.d.cts","sourceRoot":"","sources":["../../src/lib/types.ts"],"names":[],"mappings":"AAAA,gGAAgG;AAChG,MAAM,MAAM,YAAY,GAAG,OAAO,GAAG,KAAK,GAAG,aAAa,CAAC;AAE3D,0FAA0F;AAC1F,MAAM,MAAM,cAAc,GAAG,OAAO,GAAG,SAAS,GAAG,SAAS,GAAG,aAAa,CAAC;AAE7E,+CAA+C;AAC/C,MAAM,MAAM,QAAQ,GAAG,OAAO,GAAG,aAAa,CAAC;AAE/C,+FAA+F;AAC/F,MAAM,MAAM,SAAS,GAAG;IACtB,4EAA4E;IAC5E,IAAI,EAAE,MAAM,CAAC;IACb,6FAA6F;IAC7F,SAAS,EAAE,MAAM,CAAC;IAClB,2DAA2D;IAC3D,SAAS,EAAE,QAAQ,CAAC;IACpB,6DAA6D;IAC7D,UAAU,EAAE,YAAY,CAAC;IACzB,+FAA+F;IAC/F,YAAY,EAAE,MAAM,CAAC;IACrB,2DAA2D;IAC3D,UAAU,EAAE,MAAM,CAAC;IACnB,8FAA8F;IAC9F,OAAO,EAAE,OAAO,GAAG,IAAI,CAAC;IACxB,wFAAwF;IACxF,WAAW,EAAE,MAAM,GAAG,IAAI,CAAC;IAC3B,8DAA8D;IAC9D,UAAU,EAAE,MAAM,CAAC;CACpB,CAAC;AAEF,iEAAiE;AACjE,MAAM,MAAM,UAAU,GAClB,+BAA+B,GAC/B,mCAAmC,GACnC,sCAAsC,GACtC,mCAAmC,GACnC,qCAAqC,CAAC;AAE1C,wFAAwF;AACxF,MAAM,MAAM,YAAY,GAAG;IACzB,8DAA8D;IAC9D,IAAI,EAAE,MAAM,CAAC;IACb,oEAAoE;IACpE,SAAS,EAAE,MAAM,CAAC;IAClB,4CAA4C;IAC5C,SAAS,EAAE,QAAQ,CAAC;IACpB,yEAAyE;IACzE,UAAU,EAAE,cAAc,CAAC;IAC3B,mEAAmE;IACnE,YAAY,EAAE,MAAM,CAAC;IACrB,iEAAiE;IACjE,QAAQ,EAAE,MAAM,CAAC;CAClB,CAAC;AAEF,yFAAyF;AACzF,MAAM,MAAM,WAAW,GAAG;IACxB,8CAA8C;IAC9C,MAAM,EAAE,UAAU,CAAC;IACnB,iDAAiD;IACjD,MAAM,EAAE,YAAY,CAAC;IACrB,+DAA+D;IAC/D,KAAK,EAAE,MAAM,CAAC;IACd,8CAA8C;IAC9C,GAAG,EAAE,MAAM,CAAC;IACZ,2EAA2E;IAC3E,WAAW,EAAE,MAAM,CAAC;IACpB;;;;OAIG;IACH,EAAE,CAAC,EAAE,MAAM,CAAC;CACb,CAAC;AAEF,6CAA6C;AAC7C,MAAM,MAAM,eAAe,GAAG;IAC5B,mCAAmC;IACnC,OAAO,EAAE,CAAC,CAAC;IACX,kFAAkF;IAClF,aAAa,EAAE,MAAM,CAAC;IACtB,kFAAkF;IAClF,eAAe,EAAE,MAAM,GAAG,IAAI,CAAC;IAC/B,kFAAkF;IAClF,WAAW,EAAE,MAAM,GAAG,IAAI,CAAC;CAC5B,CAAC;AAEF,wGAAwG;AACxG,MAAM,MAAM,SAAS,GAAG;IACtB,iEAAiE;IACjE,MAAM,EAAE,WAAW,CAAC,MAAM,CAAC,CAAC;IAC5B,iGAAiG;IACjG,OAAO,EAAE,WAAW,CAAC,MAAM,CAAC,CAAC;CAC9B,CAAC"}
|
|
@@ -0,0 +1,82 @@
|
|
|
1
|
+
/** CSV `event_type` column — raw values before fold maps `end` + success to terminal labels. */
|
|
2
|
+
export type CsvEventType = 'start' | 'end' | 'interrupted';
|
|
3
|
+
/** Emitted Prometheus `event_type` label after fold applies the success mapping table. */
|
|
4
|
+
export type EventTypeLabel = 'start' | 'success' | 'failure' | 'interrupted';
|
|
5
|
+
/** The type of tool that emitted the event. */
|
|
6
|
+
export type ToolType = 'skill' | 'yarn_script';
|
|
7
|
+
/** One parsed row from a `*-events.log` source file, with `repo` derived from the filename. */
|
|
8
|
+
export type ToolEvent = {
|
|
9
|
+
/** Name of the repo that the tool ran in, derived from the log filename. */
|
|
10
|
+
repo: string;
|
|
11
|
+
/** Raw tool name as recorded by the collector (may include a `skill:` or `yarn:` prefix). */
|
|
12
|
+
tool_name: string;
|
|
13
|
+
/** Whether the tool is a Cursor skill or a yarn script. */
|
|
14
|
+
tool_type: ToolType;
|
|
15
|
+
/** Raw CSV event type — `start`, `end`, or `interrupted`. */
|
|
16
|
+
event_type: CsvEventType;
|
|
17
|
+
/** AI agent that triggered the tool (e.g. `cursor`), or empty string for human invocations. */
|
|
18
|
+
agent_vendor: string;
|
|
19
|
+
/** Opaque session identifier grouping a start/end pair. */
|
|
20
|
+
session_id: string;
|
|
21
|
+
/** Outcome for `end` events — `true` for success, `false` for failure, `null` when absent. */
|
|
22
|
+
success: boolean | null;
|
|
23
|
+
/** Wall-clock duration of the tool run in milliseconds, or `null` when not recorded. */
|
|
24
|
+
duration_ms: number | null;
|
|
25
|
+
/** ISO-8601 UTC timestamp at which the event was recorded. */
|
|
26
|
+
created_at: string;
|
|
27
|
+
};
|
|
28
|
+
/** The two Prometheus metric names emitted by the anonymizer. */
|
|
29
|
+
export type MetricName = 'metamask_devtools_usage_count' | 'metamask_devtools_duration_sum_ms' | 'metamask_devtools_duration_ms_bucket' | 'metamask_devtools_duration_ms_sum' | 'metamask_devtools_duration_ms_count';
|
|
30
|
+
/** Prometheus label set shared by both emitted metrics (fold group key minus `day`). */
|
|
31
|
+
export type SampleLabels = {
|
|
32
|
+
/** Repository name (derived from the events-log filename). */
|
|
33
|
+
repo: string;
|
|
34
|
+
/** Tool name after prefix stripping, used as a Prometheus label. */
|
|
35
|
+
tool_name: string;
|
|
36
|
+
/** Tool type (`skill` or `yarn_script`). */
|
|
37
|
+
tool_type: ToolType;
|
|
38
|
+
/** Outcome category: `start`, `success`, `failure`, or `interrupted`. */
|
|
39
|
+
event_type: EventTypeLabel;
|
|
40
|
+
/** AI agent vendor string, or empty for human-triggered events. */
|
|
41
|
+
agent_vendor: string;
|
|
42
|
+
/** Per-install UUID that anonymizes the contributor identity. */
|
|
43
|
+
instance: string;
|
|
44
|
+
};
|
|
45
|
+
/** One counter sample for exposition — one element per `(metric, labels, day)` tuple. */
|
|
46
|
+
export type SamplePoint = {
|
|
47
|
+
/** Prometheus metric name for this sample. */
|
|
48
|
+
metric: MetricName;
|
|
49
|
+
/** Full Prometheus label set for this sample. */
|
|
50
|
+
labels: SampleLabels;
|
|
51
|
+
/** Accumulated counter value (event count or duration sum). */
|
|
52
|
+
value: number;
|
|
53
|
+
/** UTC calendar day bucket (`YYYY-MM-DD`). */
|
|
54
|
+
day: string;
|
|
55
|
+
/** UTC midnight of `day` in milliseconds (Prometheus sample timestamp). */
|
|
56
|
+
timestampMs: number;
|
|
57
|
+
/**
|
|
58
|
+
* Upper bound for histogram bucket samples (`metamask_devtools_duration_ms_bucket`).
|
|
59
|
+
* Holds the stringified numeric boundary (e.g. `"1000"`) or `"+Inf"`.
|
|
60
|
+
* Absent on all other metric types.
|
|
61
|
+
*/
|
|
62
|
+
le?: string;
|
|
63
|
+
};
|
|
64
|
+
/** Persisted anonymizer state file shape. */
|
|
65
|
+
export type AnonymizerState = {
|
|
66
|
+
/** Schema version; must be `1`. */
|
|
67
|
+
version: 1;
|
|
68
|
+
/** Per-install random UUID that anonymizes contributor identity across pushes. */
|
|
69
|
+
instance_uuid: string;
|
|
70
|
+
/** Last UTC day successfully pushed (`YYYY-MM-DD`), or null before first push. */
|
|
71
|
+
last_pushed_day: string | null;
|
|
72
|
+
/** ISO-8601 UTC timestamp of the last anonymize run, or null before first run. */
|
|
73
|
+
last_run_at: string | null;
|
|
74
|
+
};
|
|
75
|
+
/** Skill names are stored with the `mms-` prefix; yarn script names are bare keys from package.json. */
|
|
76
|
+
export type Allowlist = {
|
|
77
|
+
/** Set of allowlisted skill names, each prefixed with `mms-`. */
|
|
78
|
+
skills: ReadonlySet<string>;
|
|
79
|
+
/** Set of allowlisted yarn script names (bare keys from the consuming repo's `package.json`). */
|
|
80
|
+
scripts: ReadonlySet<string>;
|
|
81
|
+
};
|
|
82
|
+
//# sourceMappingURL=types.d.mts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"types.d.mts","sourceRoot":"","sources":["../../src/lib/types.ts"],"names":[],"mappings":"AAAA,gGAAgG;AAChG,MAAM,MAAM,YAAY,GAAG,OAAO,GAAG,KAAK,GAAG,aAAa,CAAC;AAE3D,0FAA0F;AAC1F,MAAM,MAAM,cAAc,GAAG,OAAO,GAAG,SAAS,GAAG,SAAS,GAAG,aAAa,CAAC;AAE7E,+CAA+C;AAC/C,MAAM,MAAM,QAAQ,GAAG,OAAO,GAAG,aAAa,CAAC;AAE/C,+FAA+F;AAC/F,MAAM,MAAM,SAAS,GAAG;IACtB,4EAA4E;IAC5E,IAAI,EAAE,MAAM,CAAC;IACb,6FAA6F;IAC7F,SAAS,EAAE,MAAM,CAAC;IAClB,2DAA2D;IAC3D,SAAS,EAAE,QAAQ,CAAC;IACpB,6DAA6D;IAC7D,UAAU,EAAE,YAAY,CAAC;IACzB,+FAA+F;IAC/F,YAAY,EAAE,MAAM,CAAC;IACrB,2DAA2D;IAC3D,UAAU,EAAE,MAAM,CAAC;IACnB,8FAA8F;IAC9F,OAAO,EAAE,OAAO,GAAG,IAAI,CAAC;IACxB,wFAAwF;IACxF,WAAW,EAAE,MAAM,GAAG,IAAI,CAAC;IAC3B,8DAA8D;IAC9D,UAAU,EAAE,MAAM,CAAC;CACpB,CAAC;AAEF,iEAAiE;AACjE,MAAM,MAAM,UAAU,GAClB,+BAA+B,GAC/B,mCAAmC,GACnC,sCAAsC,GACtC,mCAAmC,GACnC,qCAAqC,CAAC;AAE1C,wFAAwF;AACxF,MAAM,MAAM,YAAY,GAAG;IACzB,8DAA8D;IAC9D,IAAI,EAAE,MAAM,CAAC;IACb,oEAAoE;IACpE,SAAS,EAAE,MAAM,CAAC;IAClB,4CAA4C;IAC5C,SAAS,EAAE,QAAQ,CAAC;IACpB,yEAAyE;IACzE,UAAU,EAAE,cAAc,CAAC;IAC3B,mEAAmE;IACnE,YAAY,EAAE,MAAM,CAAC;IACrB,iEAAiE;IACjE,QAAQ,EAAE,MAAM,CAAC;CAClB,CAAC;AAEF,yFAAyF;AACzF,MAAM,MAAM,WAAW,GAAG;IACxB,8CAA8C;IAC9C,MAAM,EAAE,UAAU,CAAC;IACnB,iDAAiD;IACjD,MAAM,EAAE,YAAY,CAAC;IACrB,+DAA+D;IAC/D,KAAK,EAAE,MAAM,CAAC;IACd,8CAA8C;IAC9C,GAAG,EAAE,MAAM,CAAC;IACZ,2EAA2E;IAC3E,WAAW,EAAE,MAAM,CAAC;IACpB;;;;OAIG;IACH,EAAE,CAAC,EAAE,MAAM,CAAC;CACb,CAAC;AAEF,6CAA6C;AAC7C,MAAM,MAAM,eAAe,GAAG;IAC5B,mCAAmC;IACnC,OAAO,EAAE,CAAC,CAAC;IACX,kFAAkF;IAClF,aAAa,EAAE,MAAM,CAAC;IACtB,kFAAkF;IAClF,eAAe,EAAE,MAAM,GAAG,IAAI,CAAC;IAC/B,kFAAkF;IAClF,WAAW,EAAE,MAAM,GAAG,IAAI,CAAC;CAC5B,CAAC;AAEF,wGAAwG;AACxG,MAAM,MAAM,SAAS,GAAG;IACtB,iEAAiE;IACjE,MAAM,EAAE,WAAW,CAAC,MAAM,CAAC,CAAC;IAC5B,iGAAiG;IACjG,OAAO,EAAE,WAAW,CAAC,MAAM,CAAC,CAAC;CAC9B,CAAC"}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"types.mjs","sourceRoot":"","sources":["../../src/lib/types.ts"],"names":[],"mappings":"","sourcesContent":["/** CSV `event_type` column — raw values before fold maps `end` + success to terminal labels. */\nexport type CsvEventType = 'start' | 'end' | 'interrupted';\n\n/** Emitted Prometheus `event_type` label after fold applies the success mapping table. */\nexport type EventTypeLabel = 'start' | 'success' | 'failure' | 'interrupted';\n\n/** The type of tool that emitted the event. */\nexport type ToolType = 'skill' | 'yarn_script';\n\n/** One parsed row from a `*-events.log` source file, with `repo` derived from the filename. */\nexport type ToolEvent = {\n /** Name of the repo that the tool ran in, derived from the log filename. */\n repo: string;\n /** Raw tool name as recorded by the collector (may include a `skill:` or `yarn:` prefix). */\n tool_name: string;\n /** Whether the tool is a Cursor skill or a yarn script. */\n tool_type: ToolType;\n /** Raw CSV event type — `start`, `end`, or `interrupted`. */\n event_type: CsvEventType;\n /** AI agent that triggered the tool (e.g. `cursor`), or empty string for human invocations. */\n agent_vendor: string;\n /** Opaque session identifier grouping a start/end pair. */\n session_id: string;\n /** Outcome for `end` events — `true` for success, `false` for failure, `null` when absent. */\n success: boolean | null;\n /** Wall-clock duration of the tool run in milliseconds, or `null` when not recorded. */\n duration_ms: number | null;\n /** ISO-8601 UTC timestamp at which the event was recorded. */\n created_at: string;\n};\n\n/** The two Prometheus metric names emitted by the anonymizer. */\nexport type MetricName =\n | 'metamask_devtools_usage_count'\n | 'metamask_devtools_duration_sum_ms'\n | 'metamask_devtools_duration_ms_bucket'\n | 'metamask_devtools_duration_ms_sum'\n | 'metamask_devtools_duration_ms_count';\n\n/** Prometheus label set shared by both emitted metrics (fold group key minus `day`). */\nexport type SampleLabels = {\n /** Repository name (derived from the events-log filename). */\n repo: string;\n /** Tool name after prefix stripping, used as a Prometheus label. */\n tool_name: string;\n /** Tool type (`skill` or `yarn_script`). */\n tool_type: ToolType;\n /** Outcome category: `start`, `success`, `failure`, or `interrupted`. */\n event_type: EventTypeLabel;\n /** AI agent vendor string, or empty for human-triggered events. */\n agent_vendor: string;\n /** Per-install UUID that anonymizes the contributor identity. */\n instance: string;\n};\n\n/** One counter sample for exposition — one element per `(metric, labels, day)` tuple. */\nexport type SamplePoint = {\n /** Prometheus metric name for this sample. */\n metric: MetricName;\n /** Full Prometheus label set for this sample. */\n labels: SampleLabels;\n /** Accumulated counter value (event count or duration sum). */\n value: number;\n /** UTC calendar day bucket (`YYYY-MM-DD`). */\n day: string;\n /** UTC midnight of `day` in milliseconds (Prometheus sample timestamp). */\n timestampMs: number;\n /**\n * Upper bound for histogram bucket samples (`metamask_devtools_duration_ms_bucket`).\n * Holds the stringified numeric boundary (e.g. `\"1000\"`) or `\"+Inf\"`.\n * Absent on all other metric types.\n */\n le?: string;\n};\n\n/** Persisted anonymizer state file shape. */\nexport type AnonymizerState = {\n /** Schema version; must be `1`. */\n version: 1;\n /** Per-install random UUID that anonymizes contributor identity across pushes. */\n instance_uuid: string;\n /** Last UTC day successfully pushed (`YYYY-MM-DD`), or null before first push. */\n last_pushed_day: string | null;\n /** ISO-8601 UTC timestamp of the last anonymize run, or null before first run. */\n last_run_at: string | null;\n};\n\n/** Skill names are stored with the `mms-` prefix; yarn script names are bare keys from package.json. */\nexport type Allowlist = {\n /** Set of allowlisted skill names, each prefixed with `mms-`. */\n skills: ReadonlySet<string>;\n /** Set of allowlisted yarn script names (bare keys from the consuming repo's `package.json`). */\n scripts: ReadonlySet<string>;\n};\n"]}
|