switchroom 0.20.13 → 0.20.14
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/dist/cli/switchroom.js
CHANGED
|
@@ -2120,7 +2120,7 @@ var init_esm = __esm(() => {
|
|
|
2120
2120
|
});
|
|
2121
2121
|
|
|
2122
2122
|
// src/build-info.ts
|
|
2123
|
-
var VERSION = "0.20.
|
|
2123
|
+
var VERSION = "0.20.14", COMMIT_SHA = "acb44b7f";
|
|
2124
2124
|
|
|
2125
2125
|
// src/cli/resolve-version.ts
|
|
2126
2126
|
import { existsSync, readFileSync } from "node:fs";
|
|
@@ -128794,6 +128794,8 @@ function buildBankMap(result) {
|
|
|
128794
128794
|
push(c.bank);
|
|
128795
128795
|
for (const a of result.arms ?? [])
|
|
128796
128796
|
push(a.bank);
|
|
128797
|
+
for (const p of result.phases ?? [])
|
|
128798
|
+
push(p.bank);
|
|
128797
128799
|
const width = Math.max(2, String(ordered.length).length);
|
|
128798
128800
|
const map2 = new Map;
|
|
128799
128801
|
ordered.forEach((bank, i2) => map2.set(bank, pseudonym(i2 + 1, width)));
|
|
@@ -128812,7 +128814,8 @@ function anonymiseResult(result) {
|
|
|
128812
128814
|
bankRows: (result.db?.bankRows ?? []).map((r) => ({ ...r, bank: sub(r.bank) }))
|
|
128813
128815
|
},
|
|
128814
128816
|
cells: (result.cells ?? []).map((c) => ({ ...c, bank: sub(c.bank) })),
|
|
128815
|
-
arms: result.arms
|
|
128817
|
+
arms: (result.arms ?? null)?.map((a) => ({ ...a, bank: sub(a.bank) })) ?? null,
|
|
128818
|
+
phases: (result.phases ?? null)?.map((p) => ({ ...p, bank: sub(p.bank) })) ?? null
|
|
128816
128819
|
}
|
|
128817
128820
|
};
|
|
128818
128821
|
}
|
|
@@ -128952,6 +128955,18 @@ function assertReadOnlyOrWritesAllowed(allowWrites, opts = {}) {
|
|
|
128952
128955
|
throw new SqlError("refusing to run: the harness's database session is WRITABLE " + `(transaction_read_only=${declared ?? "?"}, temp-table write ${writeLanded ? "succeeded" : "failed"}). ` + "This harness measures a read path and must not be able to mutate a bank. " + "Pass --allow-writes only if you genuinely intend a writable session " + "(contention profile `write` needs one for its own scratch table).");
|
|
128953
128956
|
}
|
|
128954
128957
|
}
|
|
128958
|
+
function readStatsEpoch(opts = {}) {
|
|
128959
|
+
const rows = sql(`SELECT
|
|
128960
|
+
(SELECT stats_reset::text FROM pg_stat_database WHERE datname = current_database()),
|
|
128961
|
+
(SELECT CASE WHEN heap_blks_hit + heap_blks_read = 0 THEN NULL
|
|
128962
|
+
ELSE heap_blks_hit::float8 / (heap_blks_hit + heap_blks_read) END
|
|
128963
|
+
FROM pg_statio_user_tables WHERE relname = 'memory_units');`, opts);
|
|
128964
|
+
const f = (rows[0] ?? "").split("|");
|
|
128965
|
+
return {
|
|
128966
|
+
statsResetAt: (f[0] ?? "") === "" ? null : f[0],
|
|
128967
|
+
heapHitRatio: (f[1] ?? "") === "" ? null : num3(f[1])
|
|
128968
|
+
};
|
|
128969
|
+
}
|
|
128955
128970
|
function resetStats(opts = {}) {
|
|
128956
128971
|
sql("SELECT pg_stat_reset();", { ...opts, writable: true });
|
|
128957
128972
|
}
|
|
@@ -129546,9 +129561,35 @@ function formatSummary(r) {
|
|
|
129546
129561
|
L.push(` ${pad5(a.bank, 16)}${pad5(a.method, 12)}${pad5(a.fact_type, 12)}${padL(String(a.n), 5)}` + `${padL(a.p50.toFixed(1), 9)}${padL(a.p95.toFixed(1), 9)}`);
|
|
129547
129562
|
}
|
|
129548
129563
|
}
|
|
129564
|
+
L.push(...formatPhases(r.phases ?? null));
|
|
129549
129565
|
return L.join(`
|
|
129550
129566
|
`);
|
|
129551
129567
|
}
|
|
129568
|
+
function formatPhases(phases) {
|
|
129569
|
+
if (phases === null || phases.length === 0)
|
|
129570
|
+
return [];
|
|
129571
|
+
const L = [];
|
|
129572
|
+
L.push("");
|
|
129573
|
+
L.push(" phase attribution (SEPARATE traced pass \u2014 not comparable to the latency table above)");
|
|
129574
|
+
L.push(` ${pad5("bank", 16)}${padL("conc", 6)}${padL("n", 5)}${padL("client ms", 11)}${padL("server ms", 11)}` + `${padL("db ms", 9)}${padL("db/server", 11)}${padL("max gain", 10)}`);
|
|
129575
|
+
for (const c of phases) {
|
|
129576
|
+
L.push(` ${pad5(c.bank, 16)}${padL(String(c.concurrency), 6)}${padL(String(c.n), 5)}` + `${padL(c.clientMsMean.toFixed(0), 11)}${padL(c.serverMsMean.toFixed(0), 11)}` + `${padL(c.dbMsMean.toFixed(0), 9)}${padL(`${round(c.dbShareOfServer * 100, 1)}%`, 11)}` + `${padL(`${round(c.maxDbSideGainFraction * 100, 1)}%`, 10)}`);
|
|
129577
|
+
}
|
|
129578
|
+
const worst = Math.max(...phases.map((c) => c.maxDbSideGainFraction));
|
|
129579
|
+
L.push("");
|
|
129580
|
+
L.push(` ceiling: a PERFECT database (every PostgreSQL call instantaneous) removes at most ` + `${round(worst * 100, 1)}% of end-to-end recall latency, at the most database-bound cell measured.`);
|
|
129581
|
+
L.push(" Any database-side proposal claiming more than that is refuted by this number.");
|
|
129582
|
+
const totals = new Map;
|
|
129583
|
+
for (const c of phases) {
|
|
129584
|
+
for (const p of c.phases)
|
|
129585
|
+
totals.set(p.name, (totals.get(p.name) ?? 0) + p.meanMs);
|
|
129586
|
+
}
|
|
129587
|
+
const ranked = [...totals.entries()].sort((a, b) => b[1] - a[1]).slice(0, 4);
|
|
129588
|
+
if (ranked.length > 0) {
|
|
129589
|
+
L.push(` largest phases by mean time across all cells: ${ranked.map(([n]) => n).join(", ")}`);
|
|
129590
|
+
}
|
|
129591
|
+
return L;
|
|
129592
|
+
}
|
|
129552
129593
|
function formatReproducibility(rep) {
|
|
129553
129594
|
const L = [];
|
|
129554
129595
|
L.push(`reproducibility (AC1) \u2014 tolerance \u00b1${round(rep.tolerance * 100, 0)}% on p95 per cell`);
|
|
@@ -129615,6 +129656,71 @@ function toCsv(r) {
|
|
|
129615
129656
|
`);
|
|
129616
129657
|
}
|
|
129617
129658
|
|
|
129659
|
+
// src/hindsight-bench/phases.ts
|
|
129660
|
+
var DB_PHASES = ["parallel_retrieval"];
|
|
129661
|
+
var DB_DIAGNOSTIC_PHASES = ["connection_wait"];
|
|
129662
|
+
function isDiagnosticPhase(entry) {
|
|
129663
|
+
const details = entry?.details;
|
|
129664
|
+
return details?.diagnostic === true;
|
|
129665
|
+
}
|
|
129666
|
+
function extractPhases(trace) {
|
|
129667
|
+
const summary = trace?.summary;
|
|
129668
|
+
const totalS = Number(summary?.total_duration_seconds);
|
|
129669
|
+
const raw = summary?.phase_metrics;
|
|
129670
|
+
const phases = new Map;
|
|
129671
|
+
const diagnostics = new Map;
|
|
129672
|
+
if (Array.isArray(raw)) {
|
|
129673
|
+
for (const entry of raw) {
|
|
129674
|
+
const name = entry?.phase_name;
|
|
129675
|
+
const secs = Number(entry?.duration_seconds);
|
|
129676
|
+
if (typeof name !== "string" || name === "" || !Number.isFinite(secs))
|
|
129677
|
+
continue;
|
|
129678
|
+
const into = isDiagnosticPhase(entry) ? diagnostics : phases;
|
|
129679
|
+
into.set(name, (into.get(name) ?? 0) + secs * 1000);
|
|
129680
|
+
}
|
|
129681
|
+
}
|
|
129682
|
+
return { serverMs: Number.isFinite(totalS) ? totalS * 1000 : 0, phases, diagnostics };
|
|
129683
|
+
}
|
|
129684
|
+
function reducePhaseCell(bank, rows, concurrency, samples, errors4) {
|
|
129685
|
+
if (samples.length === 0)
|
|
129686
|
+
return null;
|
|
129687
|
+
const clientMsMean = mean(samples.map((s) => s.clientMs));
|
|
129688
|
+
const serverMsMean = mean(samples.map((s) => s.extracted.serverMs));
|
|
129689
|
+
const names = new Set;
|
|
129690
|
+
for (const s of samples)
|
|
129691
|
+
for (const n of s.extracted.phases.keys())
|
|
129692
|
+
names.add(n);
|
|
129693
|
+
const phases = [];
|
|
129694
|
+
for (const name of [...names].sort()) {
|
|
129695
|
+
const vals = samples.map((s) => s.extracted.phases.get(name) ?? 0);
|
|
129696
|
+
const st = summarize(vals, 0);
|
|
129697
|
+
phases.push({
|
|
129698
|
+
name,
|
|
129699
|
+
meanMs: st.mean,
|
|
129700
|
+
p95Ms: st.p95,
|
|
129701
|
+
shareOfServer: serverMsMean > 0 ? st.mean / serverMsMean : 0
|
|
129702
|
+
});
|
|
129703
|
+
}
|
|
129704
|
+
phases.sort((a, b) => b.meanMs - a.meanMs);
|
|
129705
|
+
const dbMsMean = DB_PHASES.reduce((acc, name) => acc + mean(samples.map((s) => s.extracted.phases.get(name) ?? 0)), 0) + DB_DIAGNOSTIC_PHASES.reduce((acc, name) => acc + mean(samples.map((s) => s.extracted.diagnostics.get(name) ?? 0)), 0);
|
|
129706
|
+
return {
|
|
129707
|
+
bank,
|
|
129708
|
+
rows,
|
|
129709
|
+
concurrency,
|
|
129710
|
+
n: samples.length,
|
|
129711
|
+
errors: errors4,
|
|
129712
|
+
clientMsMean,
|
|
129713
|
+
serverMsMean,
|
|
129714
|
+
dbMsMean,
|
|
129715
|
+
dbShareOfServer: serverMsMean > 0 ? dbMsMean / serverMsMean : 0,
|
|
129716
|
+
maxDbSideGainFraction: clientMsMean > 0 ? dbMsMean / clientMsMean : 0,
|
|
129717
|
+
phases
|
|
129718
|
+
};
|
|
129719
|
+
}
|
|
129720
|
+
function mean(xs) {
|
|
129721
|
+
return xs.length === 0 ? 0 : xs.reduce((a, b) => a + b, 0) / xs.length;
|
|
129722
|
+
}
|
|
129723
|
+
|
|
129618
129724
|
// src/hindsight-bench/run.ts
|
|
129619
129725
|
var MAX_ERROR_SAMPLES = 5;
|
|
129620
129726
|
var realSleep = (ms) => new Promise((r) => setTimeout(r, ms));
|
|
@@ -129724,6 +129830,43 @@ async function runArmSweep(opts) {
|
|
|
129724
129830
|
rows.sort((a, b) => a.bank.localeCompare(b.bank) || b.p50 - a.p50);
|
|
129725
129831
|
return rows;
|
|
129726
129832
|
}
|
|
129833
|
+
async function runPhaseSweep(opts) {
|
|
129834
|
+
const { config: config2, db } = opts;
|
|
129835
|
+
const deps = opts.deps ?? {};
|
|
129836
|
+
const sleep5 = deps.sleep ?? realSleep;
|
|
129837
|
+
const log = deps.log ?? (() => {});
|
|
129838
|
+
const settleMs = opts.settleMs ?? 2000;
|
|
129839
|
+
const recall = deps.recall ?? ((bank, query) => recallOnce(bank, query, {
|
|
129840
|
+
apiUrl: config2.apiUrl,
|
|
129841
|
+
timeoutMs: config2.timeoutMs,
|
|
129842
|
+
budget: config2.budget,
|
|
129843
|
+
maxTokens: config2.maxTokens,
|
|
129844
|
+
trace: true
|
|
129845
|
+
}));
|
|
129846
|
+
const rowsFor = new Map(db.bankRows.map((b) => [b.bank, b.rows]));
|
|
129847
|
+
const out = [];
|
|
129848
|
+
for (const bank of config2.banks) {
|
|
129849
|
+
for (const concurrency of [...config2.concurrency].sort((a, b) => a - b)) {
|
|
129850
|
+
const count = Math.max(opts.samples, concurrency);
|
|
129851
|
+
const raw = await driveCell(bank, concurrency, count, recall);
|
|
129852
|
+
const ok = raw.filter((s) => s.ok);
|
|
129853
|
+
const samples = ok.map((s) => ({
|
|
129854
|
+
clientMs: s.ms,
|
|
129855
|
+
extracted: extractPhases(s.trace)
|
|
129856
|
+
}));
|
|
129857
|
+
const cell = reducePhaseCell(bank, rowsFor.get(bank) ?? 0, concurrency, samples, raw.length - ok.length);
|
|
129858
|
+
if (cell === null) {
|
|
129859
|
+
log(` phases: ${bank} c=${concurrency}: no successful traced calls`);
|
|
129860
|
+
} else {
|
|
129861
|
+
out.push(cell);
|
|
129862
|
+
log(` phases: ${bank} c=${concurrency}: n=${cell.n} db=${(cell.dbShareOfServer * 100).toFixed(1)}% of server, ` + `max end-to-end gain from a perfect DB = ${(cell.maxDbSideGainFraction * 100).toFixed(1)}%`);
|
|
129863
|
+
}
|
|
129864
|
+
if (settleMs > 0)
|
|
129865
|
+
await sleep5(settleMs);
|
|
129866
|
+
}
|
|
129867
|
+
}
|
|
129868
|
+
return out;
|
|
129869
|
+
}
|
|
129727
129870
|
|
|
129728
129871
|
// src/hindsight-bench/types.ts
|
|
129729
129872
|
var BENCH_SCHEMA_VERSION = 2;
|
|
@@ -129777,7 +129920,7 @@ function intOpt(raw, name) {
|
|
|
129777
129920
|
return n;
|
|
129778
129921
|
}
|
|
129779
129922
|
function registerHindsightBenchCommand(program3) {
|
|
129780
|
-
program3.command("hindsight-bench").description("Measure Hindsight recall latency as a function of bank size and concurrency. " + "Percentiles, not means. Read-only by default; --contention degrades the live box.").option("--api-url <url>", "Hindsight REST base", DEFAULT_API_URL).option("--container <name>", "hindsight container for the psql probes", DEFAULT_CONTAINER2).option("--banks <spec>", "all | top:<n> | spread:<n> | comma list", "spread:5").option("--concurrency <list>", "comma-separated concurrency levels", "1,4,8,16").option("--samples <n>", "recorded recalls per cell", "60").option("--warmup <n>", "discarded recalls per cell before recording", "8").option("--timeout-ms <ms>", "per-recall timeout", "30000").option("--settle-ms <ms>", "quiet period between cells", "2000").option("--budget <budget>", "recall budget", "mid").option("--max-tokens <n>", "recall max_tokens", "4096").option("--contention [profile]", "run the sweep under synthetic load: read (cache churn, SELECT-only) or " + "write (adds a WAL storm against a harness-owned scratch table; needs --allow-writes)").option("--contention-workers <n>", "concurrent load backends", String(DEFAULT_CONTENTION.workers)).option("--contention-scan-pct <pct>", "TABLESAMPLE percentage per churn scan", String(DEFAULT_CONTENTION.scanPct)).option("--contention-max-seconds <s>", "absolute in-SQL deadline for every load backend (orphan guard)", String(DEFAULT_CONTENTION.maxSeconds)).option("--reset-stats", "call pg_stat_reset() before the sweep (never implicit)", false).option("--allow-writes", "authorise a writable database session (AC5 gate)", false).option("--arms [n]", "additionally run a traced per-arm attribution pass (n samples/bank, default 5)").option("--label <text>", "free-form label recorded in the result file", "").option("--out <path>", "write the JSON result file (or the SVG in --plot mode)").option("--csv <path>", "also write a flat per-cell CSV").option("--plot <files...>", "render the chart from result files instead of measuring").option("--compare <files...>", "AC1 reproducibility verdict over two result files").option("--contention-compare <files...>", "AC4 contention verdict over two result files").option("--tolerance <fraction>", "AC1 tolerance", String(DEFAULT_TOLERANCE)).option("--json", "emit machine-readable JSON for the verdict modes", false).action(async (opts) => {
|
|
129923
|
+
program3.command("hindsight-bench").description("Measure Hindsight recall latency as a function of bank size and concurrency. " + "Percentiles, not means. Read-only by default; --contention degrades the live box.").option("--api-url <url>", "Hindsight REST base", DEFAULT_API_URL).option("--container <name>", "hindsight container for the psql probes", DEFAULT_CONTAINER2).option("--banks <spec>", "all | top:<n> | spread:<n> | comma list", "spread:5").option("--concurrency <list>", "comma-separated concurrency levels", "1,4,8,16").option("--samples <n>", "recorded recalls per cell", "60").option("--warmup <n>", "discarded recalls per cell before recording", "8").option("--timeout-ms <ms>", "per-recall timeout", "30000").option("--settle-ms <ms>", "quiet period between cells", "2000").option("--budget <budget>", "recall budget", "mid").option("--max-tokens <n>", "recall max_tokens", "4096").option("--contention [profile]", "run the sweep under synthetic load: read (cache churn, SELECT-only) or " + "write (adds a WAL storm against a harness-owned scratch table; needs --allow-writes)").option("--contention-workers <n>", "concurrent load backends", String(DEFAULT_CONTENTION.workers)).option("--contention-scan-pct <pct>", "TABLESAMPLE percentage per churn scan", String(DEFAULT_CONTENTION.scanPct)).option("--contention-max-seconds <s>", "absolute in-SQL deadline for every load backend (orphan guard)", String(DEFAULT_CONTENTION.maxSeconds)).option("--reset-stats", "call pg_stat_reset() before the sweep (never implicit)", false).option("--allow-writes", "authorise a writable database session (AC5 gate)", false).option("--arms [n]", "additionally run a traced per-arm attribution pass (n samples/bank, default 5)").option("--phases [n]", "additionally run a traced phase-attribution pass over the full concurrency ladder " + "(n samples/cell, default 8); reports how much end-to-end latency a perfect database could remove").option("--label <text>", "free-form label recorded in the result file", "").option("--out <path>", "write the JSON result file (or the SVG in --plot mode)").option("--csv <path>", "also write a flat per-cell CSV").option("--plot <files...>", "render the chart from result files instead of measuring").option("--compare <files...>", "AC1 reproducibility verdict over two result files").option("--contention-compare <files...>", "AC4 contention verdict over two result files").option("--tolerance <fraction>", "AC1 tolerance", String(DEFAULT_TOLERANCE)).option("--json", "emit machine-readable JSON for the verdict modes", false).action(async (opts) => {
|
|
129781
129924
|
if (opts.plot !== undefined)
|
|
129782
129925
|
return runPlotMode(opts);
|
|
129783
129926
|
if (opts.compare !== undefined)
|
|
@@ -129856,6 +129999,7 @@ async function runMeasureMode(opts) {
|
|
|
129856
129999
|
resetStats(sqlOpts);
|
|
129857
130000
|
process.stderr.write(`${source_default.yellow("!")} pg_stat_reset() called \u2014 cumulative statistics were discarded
|
|
129858
130001
|
`);
|
|
130002
|
+
db = { ...db, ...readStatsEpoch(sqlOpts) };
|
|
129859
130003
|
} catch (e) {
|
|
129860
130004
|
fail9(`--reset-stats failed: ${e.message}`);
|
|
129861
130005
|
}
|
|
@@ -129881,6 +130025,9 @@ async function runMeasureMode(opts) {
|
|
|
129881
130025
|
const armSamples = opts.arms === undefined ? 0 : opts.arms === true || opts.arms === "" ? 5 : Number(opts.arms);
|
|
129882
130026
|
if (!Number.isFinite(armSamples) || armSamples < 0)
|
|
129883
130027
|
fail9(`--arms must be a non-negative integer`);
|
|
130028
|
+
const phaseSamples = opts.phases === undefined ? 0 : opts.phases === true || opts.phases === "" ? 8 : Number(opts.phases);
|
|
130029
|
+
if (!Number.isFinite(phaseSamples) || phaseSamples < 0)
|
|
130030
|
+
fail9(`--phases must be a non-negative integer`);
|
|
129884
130031
|
process.stderr.write(`sweeping ${banks.length} bank(s) \u00d7 ${concurrency.length} concurrency level(s) = ` + `${banks.length * concurrency.length} cells, ${config2.samples} samples each ` + `(+${config2.warmup} warm-up) \u00b7 contention=${profile}
|
|
129885
130032
|
`);
|
|
129886
130033
|
const t0 = Date.now();
|
|
@@ -129914,6 +130061,14 @@ async function runMeasureMode(opts) {
|
|
|
129914
130061
|
});
|
|
129915
130062
|
const arms = armSamples > 0 ? await runArmSweep({ config: config2, samples: armSamples, deps: { log: (m) => process.stderr.write(`${m}
|
|
129916
130063
|
`) } }) : null;
|
|
130064
|
+
const phases = phaseSamples > 0 ? await runPhaseSweep({
|
|
130065
|
+
config: config2,
|
|
130066
|
+
db,
|
|
130067
|
+
samples: phaseSamples,
|
|
130068
|
+
settleMs: intOpt(opts.settleMs, "--settle-ms"),
|
|
130069
|
+
deps: { log: (m) => process.stderr.write(`${m}
|
|
130070
|
+
`) }
|
|
130071
|
+
}) : null;
|
|
129917
130072
|
result = {
|
|
129918
130073
|
schema: BENCH_SCHEMA_VERSION,
|
|
129919
130074
|
config: config2,
|
|
@@ -129921,6 +130076,7 @@ async function runMeasureMode(opts) {
|
|
|
129921
130076
|
instance,
|
|
129922
130077
|
cells,
|
|
129923
130078
|
arms,
|
|
130079
|
+
phases,
|
|
129924
130080
|
durationS: (Date.now() - t0) / 1000
|
|
129925
130081
|
};
|
|
129926
130082
|
} finally {
|
|
@@ -21559,7 +21559,7 @@ function allocateAgentUid(name) {
|
|
|
21559
21559
|
}
|
|
21560
21560
|
|
|
21561
21561
|
// src/build-info.ts
|
|
21562
|
-
var VERSION = "0.20.
|
|
21562
|
+
var VERSION = "0.20.14";
|
|
21563
21563
|
|
|
21564
21564
|
// src/setup/hindsight-recall-passthrough.ts
|
|
21565
21565
|
var HINDSIGHT_RECALL_TAG_WEIGHT_SEED = Object.freeze({ sidechain: 0.8 });
|
package/package.json
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "switchroom",
|
|
3
3
|
"//version": "NOT the release version — source of truth is the git tag, resolved by scripts/build.mjs:resolveVersion() (see CLAUDE.md > Standard release process). This field is stale by design and only the Layer-4 dev/non-tag fallback for build.mjs + src/cli/resolve-version.ts; do NOT bump it expecting a release to pick it up. npm-pack tarball naming needs a real version — do that as an UNCOMMITTED pack-time bump (see release step 6), never a committed one.",
|
|
4
|
-
"version": "0.20.
|
|
4
|
+
"version": "0.20.14",
|
|
5
5
|
"description": "Run Claude Code 24/7 on your Claude Pro/Max subscription over Telegram. Open-source alternative to OpenClaw and NanoClaw — no API keys.",
|
|
6
6
|
"type": "module",
|
|
7
7
|
"bin": {
|
|
@@ -103438,10 +103438,10 @@ function startOutboxSweep(deps) {
|
|
|
103438
103438
|
}
|
|
103439
103439
|
|
|
103440
103440
|
// ../src/build-info.ts
|
|
103441
|
-
var VERSION2 = "0.20.
|
|
103442
|
-
var COMMIT_SHA = "
|
|
103443
|
-
var COMMIT_DATE = "2026-08-
|
|
103444
|
-
var LATEST_PR =
|
|
103441
|
+
var VERSION2 = "0.20.14";
|
|
103442
|
+
var COMMIT_SHA = "acb44b7f";
|
|
103443
|
+
var COMMIT_DATE = "2026-08-07T07:09:13Z";
|
|
103444
|
+
var LATEST_PR = 4505;
|
|
103445
103445
|
var COMMITS_AHEAD_OF_TAG = 0;
|
|
103446
103446
|
|
|
103447
103447
|
// gateway/boot-version.ts
|