@rotifer/playground 0.22.0 → 0.23.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/CHANGELOG.md +24 -0
- package/README.md +1 -1
- package/dist/cloud/client.d.ts +1 -6
- package/dist/cloud/client.d.ts.map +1 -1
- package/dist/cloud/client.js +0 -37
- package/dist/cloud/client.js.map +1 -1
- package/dist/cloud/invocation.d.ts +29 -0
- package/dist/cloud/invocation.d.ts.map +1 -1
- package/dist/cloud/invocation.js +58 -7
- package/dist/cloud/invocation.js.map +1 -1
- package/dist/cloud/types.d.ts +0 -5
- package/dist/cloud/types.d.ts.map +1 -1
- package/dist/cloud/types.js.map +1 -1
- package/dist/commands/arena-watch.d.ts.map +1 -1
- package/dist/commands/arena-watch.js +43 -26
- package/dist/commands/arena-watch.js.map +1 -1
- package/dist/commands/run.d.ts.map +1 -1
- package/dist/commands/run.js +7 -0
- package/dist/commands/run.js.map +1 -1
- package/dist/commands/telemetry.d.ts +3 -0
- package/dist/commands/telemetry.d.ts.map +1 -0
- package/dist/commands/telemetry.js +93 -0
- package/dist/commands/telemetry.js.map +1 -0
- package/dist/index.js +2 -0
- package/dist/index.js.map +1 -1
- package/dist/telemetry/config.d.ts +45 -0
- package/dist/telemetry/config.d.ts.map +1 -0
- package/dist/telemetry/config.js +147 -0
- package/dist/telemetry/config.js.map +1 -0
- package/dist/telemetry/consent.d.ts +28 -0
- package/dist/telemetry/consent.d.ts.map +1 -0
- package/dist/telemetry/consent.js +43 -0
- package/dist/telemetry/consent.js.map +1 -0
- package/dist/telemetry/heartbeat.d.ts +9 -0
- package/dist/telemetry/heartbeat.d.ts.map +1 -0
- package/dist/telemetry/heartbeat.js +122 -0
- package/dist/telemetry/heartbeat.js.map +1 -0
- package/dist/utils/leaderboard-watch.d.ts +44 -0
- package/dist/utils/leaderboard-watch.d.ts.map +1 -0
- package/dist/utils/leaderboard-watch.js +73 -0
- package/dist/utils/leaderboard-watch.js.map +1 -0
- package/dist/utils/run-logger.d.ts.map +1 -1
- package/dist/utils/run-logger.js +12 -0
- package/dist/utils/run-logger.js.map +1 -1
- package/package.json +5 -5
|
@@ -0,0 +1,122 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
+
exports.recordHeartbeat = recordHeartbeat;
|
|
4
|
+
/**
|
|
5
|
+
* Anonymous usage heartbeat (ADR-329).
|
|
6
|
+
*
|
|
7
|
+
* Answers a narrower question than gene_invocation_log: not "who called
|
|
8
|
+
* what", just "did this machine run something today, and through which
|
|
9
|
+
* channel". No identity, on by default, and — unlike the invocation report
|
|
10
|
+
* — it costs nothing to lose one. It is not §33.4 input; a dropped
|
|
11
|
+
* heartbeat is not a hole in an audited ledger, it is one machine's "active
|
|
12
|
+
* today" signal that will show up again tomorrow if the machine is still in
|
|
13
|
+
* use. That is why this file, unlike cloud/invocation.ts, does not track
|
|
14
|
+
* in-flight requests for a caller to await before process.exit() — the
|
|
15
|
+
* reliability engineering that report needs would be pure overhead here.
|
|
16
|
+
*/
|
|
17
|
+
const node_fs_1 = require("node:fs");
|
|
18
|
+
const node_path_1 = require("node:path");
|
|
19
|
+
const client_js_1 = require("../cloud/client.js");
|
|
20
|
+
const invocation_js_1 = require("../cloud/invocation.js");
|
|
21
|
+
const config_js_1 = require("./config.js");
|
|
22
|
+
// __dirname is CommonJS's own global here (see tsconfig's "module": "NodeNext"
|
|
23
|
+
// targeting CJS output) — no fileURLToPath(import.meta.url) needed, and that
|
|
24
|
+
// ESM-only syntax would fail to compile in this build target anyway.
|
|
25
|
+
let cachedVersion = null;
|
|
26
|
+
function packageVersion() {
|
|
27
|
+
if (cachedVersion !== null)
|
|
28
|
+
return cachedVersion;
|
|
29
|
+
try {
|
|
30
|
+
const pkg = JSON.parse((0, node_fs_1.readFileSync)((0, node_path_1.join)(__dirname, "..", "..", "package.json"), "utf-8"));
|
|
31
|
+
cachedVersion = typeof pkg.version === "string" ? pkg.version : null;
|
|
32
|
+
}
|
|
33
|
+
catch {
|
|
34
|
+
cachedVersion = null;
|
|
35
|
+
}
|
|
36
|
+
return cachedVersion;
|
|
37
|
+
}
|
|
38
|
+
/**
|
|
39
|
+
* The one-line disclosure, printed to stderr exactly once, before the first
|
|
40
|
+
* heartbeat this machine ever actually sends — never before, so a machine
|
|
41
|
+
* whose heartbeat is off (env or stored choice) never sees a notice about
|
|
42
|
+
* data that is never leaving it. Mirrors codegraph's wording pattern
|
|
43
|
+
* (ADR-329 measured its design against codegraph's, verified against its
|
|
44
|
+
* compiled output) but says MCP explicitly, because stderr is where CLI
|
|
45
|
+
* users look and exactly where MCP hosts do not — the MCP side of this
|
|
46
|
+
* (rotifer-mcp-server) carries the notice in a tool response instead, for
|
|
47
|
+
* that reason.
|
|
48
|
+
*/
|
|
49
|
+
function printFirstRunNotice() {
|
|
50
|
+
process.stderr.write("[rotifer] Anonymous usage heartbeat is on by default — no code, no identity, just " +
|
|
51
|
+
"\"this machine ran something today\". `rotifer telemetry off`, ROTIFER_TELEMETRY=0, " +
|
|
52
|
+
"or DO_NOT_TRACK=1 disables it. Details: https://rotifer.dev/telemetry\n");
|
|
53
|
+
}
|
|
54
|
+
/**
|
|
55
|
+
* Reports one Gene invocation's worth of activity for this machine, today,
|
|
56
|
+
* on the given channel. Fire-and-forget; every failure mode is silence,
|
|
57
|
+
* same contract as recordGeneInvocation. Safe to call unconditionally from
|
|
58
|
+
* every call site that already calls recordGeneInvocation — this function
|
|
59
|
+
* does its own consent and test-run checks.
|
|
60
|
+
*/
|
|
61
|
+
function recordHeartbeat() {
|
|
62
|
+
// The whole body is one try/catch, deliberately wider than the network
|
|
63
|
+
// call. loadOrInitHeartbeatConfig()/markFirstRunNoticeShown() write to
|
|
64
|
+
// ~/.rotifer/telemetry.json — config.ts does not swallow that failure
|
|
65
|
+
// (rotifer telemetry on/off should surface a write error to the user who
|
|
66
|
+
// ran it), but a Gene execution silently failing because this
|
|
67
|
+
// fire-and-forget signal couldn't touch the filesystem would be a much
|
|
68
|
+
// worse trade. Every failure mode here is silence, same contract as the
|
|
69
|
+
// network call below.
|
|
70
|
+
try {
|
|
71
|
+
if ((0, invocation_js_1.runningUnderTest)())
|
|
72
|
+
return;
|
|
73
|
+
const channel = (0, invocation_js_1.resolveInvocationChannel)();
|
|
74
|
+
if (channel === null)
|
|
75
|
+
return; // unattributable declared channel — see resolveInvocationChannel
|
|
76
|
+
const config = (0, config_js_1.loadOrInitHeartbeatConfig)();
|
|
77
|
+
const decision = (0, config_js_1.resolveHeartbeatDecision)(config);
|
|
78
|
+
if (!(0, config_js_1.heartbeatDecisionEnabled)(decision))
|
|
79
|
+
return;
|
|
80
|
+
// Only reached once we know a report is actually about to leave the
|
|
81
|
+
// process — see printFirstRunNotice's doc comment for why the ordering
|
|
82
|
+
// matters. Persisted synchronously so a crash in the fetch below can
|
|
83
|
+
// never cause the notice to reprint on the next run.
|
|
84
|
+
if (!config.first_run_notice_shown) {
|
|
85
|
+
printFirstRunNotice();
|
|
86
|
+
(0, config_js_1.markFirstRunNoticeShown)(config);
|
|
87
|
+
}
|
|
88
|
+
const cloudConfig = (0, client_js_1.loadCloudConfig)();
|
|
89
|
+
const url = `${cloudConfig.endpoint.replace(/\/+$/, "")}/rest/v1/rpc/record_heartbeat`;
|
|
90
|
+
// No Authorization header: record_heartbeat is anon-callable by design
|
|
91
|
+
// (migration 20260830010000) — that grant is the entire point of ADR-329.
|
|
92
|
+
// Sending credentials here would be pointless (the RPC does not use them)
|
|
93
|
+
// and would defeat the "no identity" promise for a user who happens to be
|
|
94
|
+
// signed in but has not opted into the signed-in invocation report.
|
|
95
|
+
fetch(url, {
|
|
96
|
+
method: "POST",
|
|
97
|
+
headers: { "Content-Type": "application/json", apikey: cloudConfig.anonKey },
|
|
98
|
+
body: JSON.stringify({
|
|
99
|
+
p_machine_id: config.machine_id,
|
|
100
|
+
p_channel: channel,
|
|
101
|
+
p_client_version: packageVersion(),
|
|
102
|
+
p_invocation_delta: 1,
|
|
103
|
+
}),
|
|
104
|
+
})
|
|
105
|
+
.then((res) => {
|
|
106
|
+
if (!res.ok && process.env.ROTIFER_DEBUG) {
|
|
107
|
+
process.stderr.write(`[rotifer] record_heartbeat failed (${res.status})\n`);
|
|
108
|
+
}
|
|
109
|
+
})
|
|
110
|
+
.catch((err) => {
|
|
111
|
+
if (process.env.ROTIFER_DEBUG) {
|
|
112
|
+
process.stderr.write(`[rotifer] record_heartbeat error: ${err?.message ?? err}\n`);
|
|
113
|
+
}
|
|
114
|
+
});
|
|
115
|
+
}
|
|
116
|
+
catch (err) {
|
|
117
|
+
if (process.env.ROTIFER_DEBUG) {
|
|
118
|
+
process.stderr.write(`[rotifer] record_heartbeat setup error: ${err?.message ?? err}\n`);
|
|
119
|
+
}
|
|
120
|
+
}
|
|
121
|
+
}
|
|
122
|
+
//# sourceMappingURL=heartbeat.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"heartbeat.js","sourceRoot":"","sources":["../../src/telemetry/heartbeat.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,44 @@
|
|
|
1
|
+
import type { LeaderboardRow } from "../cloud/client.js";
|
|
2
|
+
/**
|
|
3
|
+
* Stable identity of a leaderboard row across polls. The board folds to one
|
|
4
|
+
* row per logical gene, so the logical name (owner + name) is the key — the
|
|
5
|
+
* shown version (and with it the gene_id) legitimately changes when an author
|
|
6
|
+
* publishes, and that must not read as a disappearance plus an arrival.
|
|
7
|
+
*/
|
|
8
|
+
export declare function leaderboardKey(row: LeaderboardRow): string;
|
|
9
|
+
export type LeaderboardChange = {
|
|
10
|
+
kind: "new";
|
|
11
|
+
key: string;
|
|
12
|
+
row: LeaderboardRow;
|
|
13
|
+
} | {
|
|
14
|
+
kind: "tier";
|
|
15
|
+
key: string;
|
|
16
|
+
from: LeaderboardRow["tier"];
|
|
17
|
+
to: LeaderboardRow["tier"];
|
|
18
|
+
} | {
|
|
19
|
+
kind: "up" | "down";
|
|
20
|
+
key: string;
|
|
21
|
+
from: number;
|
|
22
|
+
to: number;
|
|
23
|
+
};
|
|
24
|
+
/**
|
|
25
|
+
* Diff two polls of the tiered leaderboard.
|
|
26
|
+
*
|
|
27
|
+
* Rank moves only exist inside a ranked tier: `tier_rank` is null for
|
|
28
|
+
* `not_evaluated` rows, and a null on either side is a tier story, not a rank
|
|
29
|
+
* story. A tier change is reported as such and suppresses the rank comparison
|
|
30
|
+
* for that row — "#3 → #1" across two different ladders compares nothing.
|
|
31
|
+
*/
|
|
32
|
+
export declare function diffLeaderboard(prev: LeaderboardRow[], curr: LeaderboardRow[]): LeaderboardChange[];
|
|
33
|
+
/**
|
|
34
|
+
* What the score column may show for a row. A `not_evaluated` row never shows
|
|
35
|
+
* a number, even when the ledger stores one — printing a stored value next to
|
|
36
|
+
* the words "not evaluated" is how a hash-derived number got read as a
|
|
37
|
+
* measurement in the first place (ADR-319 D4 display decision).
|
|
38
|
+
*/
|
|
39
|
+
export declare function fitnessCell(row: LeaderboardRow): string;
|
|
40
|
+
/** Same rule for V(g): no numbers on an unevaluated row. */
|
|
41
|
+
export declare function safetyCell(row: LeaderboardRow): string;
|
|
42
|
+
/** Position column: `not_evaluated` rows have no position, not position zero. */
|
|
43
|
+
export declare function rankCell(row: LeaderboardRow): string;
|
|
44
|
+
//# sourceMappingURL=leaderboard-watch.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"leaderboard-watch.d.ts","sourceRoot":"","sources":["../../src/utils/leaderboard-watch.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,cAAc,EAAE,MAAM,oBAAoB,CAAC;AAEzD;;;;;GAKG;AACH,wBAAgB,cAAc,CAAC,GAAG,EAAE,cAAc,GAAG,MAAM,CAE1D;AAED,MAAM,MAAM,iBAAiB,GACzB;IAAE,IAAI,EAAE,KAAK,CAAC;IAAC,GAAG,EAAE,MAAM,CAAC;IAAC,GAAG,EAAE,cAAc,CAAA;CAAE,GACjD;IACE,IAAI,EAAE,MAAM,CAAC;IACb,GAAG,EAAE,MAAM,CAAC;IACZ,IAAI,EAAE,cAAc,CAAC,MAAM,CAAC,CAAC;IAC7B,EAAE,EAAE,cAAc,CAAC,MAAM,CAAC,CAAC;CAC5B,GACD;IAAE,IAAI,EAAE,IAAI,GAAG,MAAM,CAAC;IAAC,GAAG,EAAE,MAAM,CAAC;IAAC,IAAI,EAAE,MAAM,CAAC;IAAC,EAAE,EAAE,MAAM,CAAA;CAAE,CAAC;AAEnE;;;;;;;GAOG;AACH,wBAAgB,eAAe,CAC7B,IAAI,EAAE,cAAc,EAAE,EACtB,IAAI,EAAE,cAAc,EAAE,GACrB,iBAAiB,EAAE,CA8BrB;AAED;;;;;GAKG;AACH,wBAAgB,WAAW,CAAC,GAAG,EAAE,cAAc,GAAG,MAAM,CAGvD;AAED,4DAA4D;AAC5D,wBAAgB,UAAU,CAAC,GAAG,EAAE,cAAc,GAAG,MAAM,CAGtD;AAED,iFAAiF;AACjF,wBAAgB,QAAQ,CAAC,GAAG,EAAE,cAAc,GAAG,MAAM,CAEpD"}
|
|
@@ -0,0 +1,73 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
+
exports.leaderboardKey = leaderboardKey;
|
|
4
|
+
exports.diffLeaderboard = diffLeaderboard;
|
|
5
|
+
exports.fitnessCell = fitnessCell;
|
|
6
|
+
exports.safetyCell = safetyCell;
|
|
7
|
+
exports.rankCell = rankCell;
|
|
8
|
+
/**
|
|
9
|
+
* Stable identity of a leaderboard row across polls. The board folds to one
|
|
10
|
+
* row per logical gene, so the logical name (owner + name) is the key — the
|
|
11
|
+
* shown version (and with it the gene_id) legitimately changes when an author
|
|
12
|
+
* publishes, and that must not read as a disappearance plus an arrival.
|
|
13
|
+
*/
|
|
14
|
+
function leaderboardKey(row) {
|
|
15
|
+
return `${row.owner_username}/${row.gene_name}`;
|
|
16
|
+
}
|
|
17
|
+
/**
|
|
18
|
+
* Diff two polls of the tiered leaderboard.
|
|
19
|
+
*
|
|
20
|
+
* Rank moves only exist inside a ranked tier: `tier_rank` is null for
|
|
21
|
+
* `not_evaluated` rows, and a null on either side is a tier story, not a rank
|
|
22
|
+
* story. A tier change is reported as such and suppresses the rank comparison
|
|
23
|
+
* for that row — "#3 → #1" across two different ladders compares nothing.
|
|
24
|
+
*/
|
|
25
|
+
function diffLeaderboard(prev, curr) {
|
|
26
|
+
const prevMap = new Map(prev.map((r) => [leaderboardKey(r), r]));
|
|
27
|
+
const changes = [];
|
|
28
|
+
for (const row of curr) {
|
|
29
|
+
const key = leaderboardKey(row);
|
|
30
|
+
const before = prevMap.get(key);
|
|
31
|
+
if (!before) {
|
|
32
|
+
changes.push({ kind: "new", key, row });
|
|
33
|
+
continue;
|
|
34
|
+
}
|
|
35
|
+
if (before.tier !== row.tier) {
|
|
36
|
+
changes.push({ kind: "tier", key, from: before.tier, to: row.tier });
|
|
37
|
+
continue;
|
|
38
|
+
}
|
|
39
|
+
if (before.tier_rank != null &&
|
|
40
|
+
row.tier_rank != null &&
|
|
41
|
+
before.tier_rank !== row.tier_rank) {
|
|
42
|
+
changes.push({
|
|
43
|
+
kind: row.tier_rank < before.tier_rank ? "up" : "down",
|
|
44
|
+
key,
|
|
45
|
+
from: before.tier_rank,
|
|
46
|
+
to: row.tier_rank,
|
|
47
|
+
});
|
|
48
|
+
}
|
|
49
|
+
}
|
|
50
|
+
return changes;
|
|
51
|
+
}
|
|
52
|
+
/**
|
|
53
|
+
* What the score column may show for a row. A `not_evaluated` row never shows
|
|
54
|
+
* a number, even when the ledger stores one — printing a stored value next to
|
|
55
|
+
* the words "not evaluated" is how a hash-derived number got read as a
|
|
56
|
+
* measurement in the first place (ADR-319 D4 display decision).
|
|
57
|
+
*/
|
|
58
|
+
function fitnessCell(row) {
|
|
59
|
+
if (row.tier === "not_evaluated" || row.fitness_value == null)
|
|
60
|
+
return "—";
|
|
61
|
+
return row.fitness_value.toFixed(4);
|
|
62
|
+
}
|
|
63
|
+
/** Same rule for V(g): no numbers on an unevaluated row. */
|
|
64
|
+
function safetyCell(row) {
|
|
65
|
+
if (row.tier === "not_evaluated" || row.safety_score == null)
|
|
66
|
+
return "—";
|
|
67
|
+
return row.safety_score.toFixed(4);
|
|
68
|
+
}
|
|
69
|
+
/** Position column: `not_evaluated` rows have no position, not position zero. */
|
|
70
|
+
function rankCell(row) {
|
|
71
|
+
return row.tier_rank == null ? "—" : String(row.tier_rank);
|
|
72
|
+
}
|
|
73
|
+
//# sourceMappingURL=leaderboard-watch.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"leaderboard-watch.js","sourceRoot":"","sources":["../../src/utils/leaderboard-watch.ts"],"names":[],"mappings":";;AAQA,wCAEC;AAoBD,0CAiCC;AAQD,kCAGC;AAGD,gCAGC;AAGD,4BAEC;AAnFD;;;;;GAKG;AACH,SAAgB,cAAc,CAAC,GAAmB;IAChD,OAAO,GAAG,GAAG,CAAC,cAAc,IAAI,GAAG,CAAC,SAAS,EAAE,CAAC;AAClD,CAAC;AAYD;;;;;;;GAOG;AACH,SAAgB,eAAe,CAC7B,IAAsB,EACtB,IAAsB;IAEtB,MAAM,OAAO,GAAG,IAAI,GAAG,CAAC,IAAI,CAAC,GAAG,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC,CAAC,cAAc,CAAC,CAAC,CAAC,EAAE,CAAC,CAAC,CAAC,CAAC,CAAC;IACjE,MAAM,OAAO,GAAwB,EAAE,CAAC;IAExC,KAAK,MAAM,GAAG,IAAI,IAAI,EAAE,CAAC;QACvB,MAAM,GAAG,GAAG,cAAc,CAAC,GAAG,CAAC,CAAC;QAChC,MAAM,MAAM,GAAG,OAAO,CAAC,GAAG,CAAC,GAAG,CAAC,CAAC;QAChC,IAAI,CAAC,MAAM,EAAE,CAAC;YACZ,OAAO,CAAC,IAAI,CAAC,EAAE,IAAI,EAAE,KAAK,EAAE,GAAG,EAAE,GAAG,EAAE,CAAC,CAAC;YACxC,SAAS;QACX,CAAC;QACD,IAAI,MAAM,CAAC,IAAI,KAAK,GAAG,CAAC,IAAI,EAAE,CAAC;YAC7B,OAAO,CAAC,IAAI,CAAC,EAAE,IAAI,EAAE,MAAM,EAAE,GAAG,EAAE,IAAI,EAAE,MAAM,CAAC,IAAI,EAAE,EAAE,EAAE,GAAG,CAAC,IAAI,EAAE,CAAC,CAAC;YACrE,SAAS;QACX,CAAC;QACD,IACE,MAAM,CAAC,SAAS,IAAI,IAAI;YACxB,GAAG,CAAC,SAAS,IAAI,IAAI;YACrB,MAAM,CAAC,SAAS,KAAK,GAAG,CAAC,SAAS,EAClC,CAAC;YACD,OAAO,CAAC,IAAI,CAAC;gBACX,IAAI,EAAE,GAAG,CAAC,SAAS,GAAG,MAAM,CAAC,SAAS,CAAC,CAAC,CAAC,IAAI,CAAC,CAAC,CAAC,MAAM;gBACtD,GAAG;gBACH,IAAI,EAAE,MAAM,CAAC,SAAS;gBACtB,EAAE,EAAE,GAAG,CAAC,SAAS;aAClB,CAAC,CAAC;QACL,CAAC;IACH,CAAC;IAED,OAAO,OAAO,CAAC;AACjB,CAAC;AAED;;;;;GAKG;AACH,SAAgB,WAAW,CAAC,GAAmB;IAC7C,IAAI,GAAG,CAAC,IAAI,KAAK,eAAe,IAAI,GAAG,CAAC,aAAa,IAAI,IAAI;QAAE,OAAO,GAAG,CAAC;IAC1E,OAAO,GAAG,CAAC,aAAa,CAAC,OAAO,CAAC,CAAC,CAAC,CAAC;AACtC,CAAC;AAED,4DAA4D;AAC5D,SAAgB,UAAU,CAAC,GAAmB;IAC5C,IAAI,GAAG,CAAC,IAAI,KAAK,eAAe,IAAI,GAAG,CAAC,YAAY,IAAI,IAAI;QAAE,OAAO,GAAG,CAAC;IACzE,OAAO,GAAG,CAAC,YAAY,CAAC,OAAO,CAAC,CAAC,CAAC,CAAC;AACrC,CAAC;AAED,iFAAiF;AACjF,SAAgB,QAAQ,CAAC,GAAmB;IAC1C,OAAO,GAAG,CAAC,SAAS,IAAI,IAAI,CAAC,CAAC,CAAC,GAAG,CAAC,CAAC,CAAC,MAAM,CAAC,GAAG,CAAC,SAAS,CAAC,CAAC;AAC7D,CAAC"}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"run-logger.d.ts","sourceRoot":"","sources":["../../src/utils/run-logger.ts"],"names":[],"mappings":"
|
|
1
|
+
{"version":3,"file":"run-logger.d.ts","sourceRoot":"","sources":["../../src/utils/run-logger.ts"],"names":[],"mappings":"AAUA,UAAU,iBAAiB;IACzB,QAAQ,EAAE,MAAM,CAAC;IACjB;;;;;OAKG;IACH,OAAO,CAAC,EAAE,MAAM,CAAC;IACjB,OAAO,EAAE,OAAO,CAAC;IACjB,UAAU,EAAE,MAAM,CAAC;IACnB,SAAS,EAAE,MAAM,CAAC;IAClB,UAAU,EAAE,MAAM,CAAC;IACnB,KAAK,CAAC,EAAE,MAAM,CAAC;IACf,YAAY,CAAC,EAAE,MAAM,CAAC;CACvB;AAED,wBAAgB,gBAAgB,CAAC,IAAI,EAAE,iBAAiB,GAAG,IAAI,CAkD9D;AAED,wBAAgB,SAAS,IAAI,MAAM,CAElC;AAED,MAAM,WAAW,WAAW;IAC1B,MAAM,EAAE,MAAM,CAAC;IACf,SAAS,EAAE,MAAM,CAAC;IAClB,OAAO,EAAE,OAAO,CAAC;IACjB,UAAU,EAAE,MAAM,CAAC;IACnB,SAAS,EAAE,MAAM,CAAC;IAClB,UAAU,EAAE,MAAM,CAAC;IACnB,KAAK,CAAC,EAAE,MAAM,CAAC;IACf,YAAY,CAAC,EAAE,MAAM,CAAC;CACvB;AAED,wBAAgB,WAAW,CAAC,QAAQ,EAAE,MAAM,GAAG,WAAW,EAAE,CAiB3D"}
|
package/dist/utils/run-logger.js
CHANGED
|
@@ -8,9 +8,21 @@ const node_path_1 = require("node:path");
|
|
|
8
8
|
const node_os_1 = require("node:os");
|
|
9
9
|
const private_fs_js_1 = require("./private-fs.js");
|
|
10
10
|
const invocation_js_1 = require("../cloud/invocation.js");
|
|
11
|
+
const heartbeat_js_1 = require("../telemetry/heartbeat.js");
|
|
11
12
|
const MAX_LOG_SIZE = 10 * 1024 * 1024; // 10MB rotation
|
|
12
13
|
const LOG_DIR = (0, node_path_1.join)((0, node_os_1.homedir)(), ".rotifer", "run-logs");
|
|
13
14
|
function logGeneExecution(meta) {
|
|
15
|
+
// Unconditional — unlike the recordGeneInvocation call below this one,
|
|
16
|
+
// which only fires when meta.geneDir names a Cloud-installed Gene. The
|
|
17
|
+
// heartbeat (ADR-329) doesn't need a resolvable Cloud identity: "this
|
|
18
|
+
// machine ran something today" is true whether meta.geneDir is set,
|
|
19
|
+
// unset, or points at a local, never-published Gene. Gating it on the
|
|
20
|
+
// same condition as the identity-carrying report would silently drop the
|
|
21
|
+
// heartbeat for exactly the callers (locally-authored Genes, composed
|
|
22
|
+
// agents without one obvious geneDir) that most need the anonymous signal
|
|
23
|
+
// to be counted at all. No try/catch needed here — recordHeartbeat()
|
|
24
|
+
// guarantees it never throws.
|
|
25
|
+
(0, heartbeat_js_1.recordHeartbeat)();
|
|
14
26
|
try {
|
|
15
27
|
(0, private_fs_js_1.ensurePrivateDir)(LOG_DIR);
|
|
16
28
|
const logFile = (0, node_path_1.join)(LOG_DIR, `${meta.geneName}.jsonl`);
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"run-logger.js","sourceRoot":"","sources":["../../src/utils/run-logger.ts"],"names":[],"mappings":";;
|
|
1
|
+
{"version":3,"file":"run-logger.js","sourceRoot":"","sources":["../../src/utils/run-logger.ts"],"names":[],"mappings":"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"}
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@rotifer/playground",
|
|
3
|
-
"version": "0.
|
|
3
|
+
"version": "0.23.0",
|
|
4
4
|
"description": "Rotifer Protocol Playground — local development environment for gene development, Arena competition, and protocol simulation",
|
|
5
5
|
"license": "Apache-2.0",
|
|
6
6
|
"author": "Rotifer Protocol Contributors",
|
|
@@ -87,10 +87,10 @@
|
|
|
87
87
|
},
|
|
88
88
|
"optionalDependencies": {
|
|
89
89
|
"@rolldown/binding-linux-x64-gnu": "1.1.1",
|
|
90
|
-
"@rotifer/playground-darwin-arm64": "0.
|
|
91
|
-
"@rotifer/playground-darwin-x64": "0.
|
|
92
|
-
"@rotifer/playground-linux-x64-gnu": "0.
|
|
93
|
-
"@rotifer/playground-win32-x64-msvc": "0.
|
|
90
|
+
"@rotifer/playground-darwin-arm64": "0.23.0",
|
|
91
|
+
"@rotifer/playground-darwin-x64": "0.23.0",
|
|
92
|
+
"@rotifer/playground-linux-x64-gnu": "0.23.0",
|
|
93
|
+
"@rotifer/playground-win32-x64-msvc": "0.23.0"
|
|
94
94
|
},
|
|
95
95
|
"engines": {
|
|
96
96
|
"node": ">=22.18.0"
|