stim 1.14.0 → 1.16.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +2 -0
- package/dist/activity-BxwdD81S.mjs +609 -0
- package/dist/agent-device-usage-output-Dpih1Tfa.mjs +411 -0
- package/dist/{android-d6rGq1pA.mjs → android-B_NumVyQ.mjs} +169 -81
- package/dist/{android-LbPFRWVL.mjs → android-Ift4kVvt.mjs} +517 -413
- package/dist/android-cas-8U4DPqeR.mjs +167 -0
- package/dist/android-cas-compiler.mjs +2 -2
- package/dist/{android-XpvCrV7q.mjs → android-r2rBL8kV.mjs} +2 -2
- package/dist/{app-install-BpgSgkJj.mjs → app-install-CKWdbXIX.mjs} +128 -151
- package/dist/attempt-Bk2ouQVL.mjs +39 -0
- package/dist/budget-DjrURfQn.mjs +2700 -0
- package/dist/{build-plan-Dcr-3ie0.mjs → build-plan-DjeSb2Xl.mjs} +192 -653
- package/dist/build-slots-rUk77xqh.mjs +132 -0
- package/dist/{cache-manifest-C68QQ0ua.mjs → cache-manifest-DnUHBJaU.mjs} +2 -2
- package/dist/cache-manifest.mjs +1 -1
- package/dist/{chrome-BPCiC3ZX.mjs → chrome-BrcVWQyD.mjs} +1 -1
- package/dist/cli-BkYZ_6hy.mjs +51 -0
- package/dist/cli.mjs +6 -42
- package/dist/client-BTY686R6.mjs +1368 -0
- package/dist/collector-run.mjs +9 -195
- package/dist/{command-output-DVcpw6eE.mjs → command-output-DnJMdEY-.mjs} +1 -1
- package/dist/{config-lvc7d3C2.mjs → config-D0DbpZtM.mjs} +28 -29
- package/dist/{created-devices-CllH_8eb.mjs → created-devices-D5owjN4C.mjs} +2 -2
- package/dist/{dependency-state-DsT7aKeo.mjs → dependency-state-B6cMXZab.mjs} +2 -2
- package/dist/{deps-D9IcKqXS.mjs → deps-urbmfXig.mjs} +3 -3
- package/dist/{detached-entry-DJHoca49.mjs → detached-entry-CiTEgMR1.mjs} +1 -1
- package/dist/dev-client-CroAIjjj.mjs +43 -0
- package/dist/{device-CjuuAJjQ.mjs → device-DZQjF7H5.mjs} +8 -7
- package/dist/device-capacity-BHwxNBlu.mjs +136 -0
- package/dist/device-host-worker.d.mts +1 -0
- package/dist/device-host-worker.mjs +964 -0
- package/dist/device-ios-BadmeL2V.mjs +381 -0
- package/dist/{device-lease-5c3WrVRm.mjs → device-lease-D-hLqx1b.mjs} +43 -36
- package/dist/{device-pool-BiyDyPP-.mjs → device-lease-run-CqjShqWW.mjs} +6 -126
- package/dist/device-pool-CUaEWMMm.mjs +125 -0
- package/dist/{device-remote-D87zEzaq.mjs → device-remote-D5WVWqOq.mjs} +69 -163
- package/dist/{doctor-x9pnU9fq.mjs → doctor-Cimf-gGB.mjs} +241 -103
- package/dist/{error-diagnostics-C5HzcwCW.mjs → error-diagnostics-B9L4Ae0x.mjs} +15 -18
- package/dist/{exec-DK8KaVHK.mjs → exec-CaErVv7t.mjs} +5 -1
- package/dist/{gc-ko6mUAYD.mjs → gc-Bqy4bjEu.mjs} +599 -108
- package/dist/{android-cas-iZK3DOCr.mjs → gradle-BsO1MdsH.mjs} +8 -294
- package/dist/{guide-6R0VNFqI.mjs → guide-B_uyKTxW.mjs} +2511 -239
- package/dist/{guide-status-BZrFPIA_.mjs → guide-status-CjEZMAD4.mjs} +3 -3
- package/dist/hosted-client-a-WmqE2L.mjs +197 -0
- package/dist/hosted-ios-CIWelIqf.mjs +220 -0
- package/dist/hosted-logs-D5g041Q3.mjs +187 -0
- package/dist/hosted-macos-BSZyIb3y.mjs +135 -0
- package/dist/idle-DYVymG92.mjs +1099 -0
- package/dist/idle-shutdown-CTsDnAde.mjs +122 -0
- package/dist/in-use-DvBw0Kxo.mjs +130 -0
- package/dist/{ios-BwDPrnYQ.mjs → ios-BaInn3sW.mjs} +201 -10
- package/dist/ios-Cr1h5gnO.mjs +189 -0
- package/dist/{ios-P1f5nm2n.mjs → ios-aq3QoGI3.mjs} +1159 -633
- package/dist/{ios-device-BiOsSVzd.mjs → ios-device-Ee7sDXfp.mjs} +1 -1
- package/dist/{ios-device-DGglU3E_.mjs → ios-device-FfCN_C8p.mjs} +12 -7
- package/dist/ios-state-DS5UpYTH.mjs +48 -0
- package/dist/{launch-verify-Deg4tB3Z.mjs → launch-verify-2DBRizjo.mjs} +5 -5
- package/dist/logs-CHEVK8zD.mjs +371 -0
- package/dist/machines-BIBUdhpj.mjs +265 -0
- package/dist/macos-CSYEAFmF.mjs +473 -0
- package/dist/macos-run.d.mts +5 -0
- package/dist/macos-run.mjs +2 -0
- package/dist/maintenance-run.d.mts +4 -0
- package/dist/maintenance-run.mjs +254 -0
- package/dist/{metro-CcEo8Fl8.mjs → metro-BeK1ZPz1.mjs} +20 -120
- package/dist/metro-gateway-BJ-rxQAB.mjs +84 -0
- package/dist/{named-ports-Blg8IxOh.mjs → named-ports-Bk_YXEmE.mjs} +6 -59
- package/dist/native-run-NaBrRFtQ.mjs +147 -0
- package/dist/{native-runtime-DjBHRg5m.mjs → native-runtime-DBzRnEKS.mjs} +9 -5
- package/dist/{ndjson-CDY9IkVC.mjs → ndjson-PclOIwVY.mjs} +2 -2
- package/dist/offload-worker.d.mts +122 -0
- package/dist/offload-worker.mjs +606 -0
- package/dist/{ownership-DyYDF5ww.mjs → ownership-DiA16AsN.mjs} +3 -2
- package/dist/ownership-hCkPzGmr.mjs +571 -0
- package/dist/{page-BHUzTDFt.mjs → page-QF_Ke10s.mjs} +7 -2
- package/dist/{ports-BguS83ex.mjs → ports-R2k4Knz3.mjs} +3 -3
- package/dist/prebuild-D2fsca_Z.mjs +213 -0
- package/dist/preview-DhVbvPAZ.mjs +318 -0
- package/dist/process-identity-BmRm1qV0.mjs +12 -0
- package/dist/{project-CWlvEaeN.mjs → project-Du91Ilvc.mjs} +74 -19
- package/dist/pull-request-pxnDCQzn.mjs +322 -0
- package/dist/pull-requests.d.mts +120 -0
- package/dist/pull-requests.mjs +2 -0
- package/dist/recordings-BIXOzVnr.mjs +37 -0
- package/dist/{reload-BiniwsSZ.mjs → reload-rM9jV1fz.mjs} +109 -24
- package/dist/{remote-cache-CcR6o6lI.mjs → remote-cache-C8-V13XN.mjs} +5 -5
- package/dist/run-f4vI6EnK.mjs +119 -0
- package/dist/{server-bare-DGfgyJ5J.mjs → server-bare-CpPGmnmO.mjs} +33 -15
- package/dist/server-expo-CVqO2c35.mjs +2 -0
- package/dist/{server-expo-BVuwQ65v.mjs → server-expo-MC0rHlOC.mjs} +8 -12
- package/dist/settings-BBpMcDbD.mjs +25 -0
- package/dist/{settings-B-fsC-Om.mjs → settings-ZkDzkzvB.mjs} +22 -10
- package/dist/settings-oTSkkNrM.mjs +1439 -0
- package/dist/settings.schema.json +845 -97
- package/dist/{simslim-DrDN4WuV.mjs → simslim-B8-7AoTI.mjs} +8 -132
- package/dist/{slot-launch-D5t8EiMf.mjs → slot-launch-B8VrHxn1.mjs} +11 -8
- package/dist/{spawn-claims-Drw_o-Fb.mjs → spawn-claims-D0XfSe8u.mjs} +1 -1
- package/dist/spawn-entry-jw19m8Nl.mjs +17 -0
- package/dist/stage-CzaiwFsI.mjs +143 -0
- package/dist/start-CX8Ig-U2.mjs +2 -0
- package/dist/{start-s4RXp1wy.mjs → start-ClDfwXa4.mjs} +116 -65
- package/dist/state-3DwSQIBK.mjs +41 -0
- package/dist/state-B4PQFXMW.d.mts +12 -0
- package/dist/{state-Dk9RVXI7.mjs → state-C1jB7Q8q.mjs} +70 -8
- package/dist/{state-DHqvsbqC.mjs → state-DcW6vOd_.mjs} +7 -4
- package/dist/stats-CEZ_i5je.mjs +77 -0
- package/dist/{status-BgAuxESg.mjs → status-BuvBFeII.mjs} +118 -20
- package/dist/{status-BsPAnfOI.mjs → status-Cs7VLg9D.mjs} +542 -283
- package/dist/status-DlKvVJBE.mjs +49 -0
- package/dist/stdout-reader-C8yjre1x.mjs +23 -0
- package/dist/stim-desktop-Cnz8CPnl.mjs +63 -0
- package/dist/stim-footprint.swift +32 -0
- package/dist/{stim-installations-CINXy_su.mjs → stim-installations-QMEI32v1.mjs} +1 -1
- package/dist/stop-B0Yxtmiy.mjs +48 -0
- package/dist/{stop-BzreOWJp.mjs → stop-Bffozsac.mjs} +83 -16
- package/dist/{stop-BWIF_6BK.mjs → stop-Dt_dM16A.mjs} +2 -2
- package/dist/stop-cause-CidxIqup.mjs +97 -0
- package/dist/supervisor-run.d.mts +43 -11
- package/dist/supervisor-run.mjs +363 -24
- package/dist/support-CAP8qDUF.mjs +316 -0
- package/dist/support-D4aYJniO.mjs +201 -0
- package/dist/teardown-CL6vDs2Y.mjs +727 -0
- package/dist/{xcode-Cp5KvK9x.mjs → toolchain-DkUflduf.mjs} +364 -14
- package/dist/trigger-Bemu8ytw.mjs +65 -0
- package/dist/trigger-CXts6qt1.mjs +2 -0
- package/dist/warm-progress-CpGv3Wb6.mjs +732 -0
- package/dist/{web-BsQs1WlO.mjs → web-DWUaMp8P.mjs} +37 -21
- package/dist/web-run.mjs +310 -13
- package/dist/workspace-process-lock-BL7Q0HCO.mjs +57 -0
- package/dist/workspace-state-B8-aJ1_5.mjs +371 -0
- package/dist/workspaces-BV4pdHFz.mjs +306 -0
- package/dist/{worktree-UrQWXSeb.mjs → worktree-K-xj9Db0.mjs} +625 -256
- package/dist/worktree-jnG8Iph5.mjs +2 -0
- package/package.json +10 -5
- package/shim/bundle-response.cjs +28 -12
- package/dist/activity-CYVDcrt3.mjs +0 -356
- package/dist/budget-CGDkhvv_.mjs +0 -1745
- package/dist/build-progress-DxKpwnaS.mjs +0 -247
- package/dist/idle-DXtx3RbX.mjs +0 -191
- package/dist/in-use-DlqBDKqY.mjs +0 -249
- package/dist/logs-Civ4gbBH.mjs +0 -486
- package/dist/merge-state-ytFQCeh4.mjs +0 -262
- package/dist/server-expo-DIHDhvGg.mjs +0 -2
- package/dist/settings-D61iNOsB.mjs +0 -629
- package/dist/start-Cetfvy8l.mjs +0 -2
- package/dist/stats-CFpFGlJV.mjs +0 -62
- package/dist/stats-CX1Z8Tca.mjs +0 -368
- package/dist/stim-desktop-CXt8-Z3J.mjs +0 -40
- package/dist/stop-cause-hjGBOZTG.mjs +0 -1231
- package/dist/worktree-BVrHsYZG.mjs +0 -752
- package/dist/worktree-CHWWvm5v.mjs +0 -2
- package/dist/{metro-store-DzeWkfqW.mjs → metro-store-CDDZHtPl.mjs} +1 -1
package/dist/stats-CFpFGlJV.mjs
DELETED
|
@@ -1,62 +0,0 @@
|
|
|
1
|
-
import { s as gitCommonDir, y as repoRoot } from "./worktree-BVrHsYZG.mjs";
|
|
2
|
-
import { a as findProjectRoot } from "./project-CWlvEaeN.mjs";
|
|
3
|
-
import { o as formatLongDuration } from "./command-output-DVcpw6eE.mjs";
|
|
4
|
-
import { a as statsProjectKey, r as readStats } from "./stats-CX1Z8Tca.mjs";
|
|
5
|
-
import chalk from "chalk";
|
|
6
|
-
//#region src/commands/stats.ts
|
|
7
|
-
const PLATFORMS = ["ios", "android"];
|
|
8
|
-
const PLATFORM_WIDTH = 9;
|
|
9
|
-
function statsCommand(program) {
|
|
10
|
-
program.command("stats").description("Show how many `ios` and `android` runs this project and this machine have recorded, how many hit the build cache, and an estimate of the time that cache saved.").option("--json", "print the aggregates as JSON").action((opts) => {
|
|
11
|
-
const root = findProjectRoot(process.cwd());
|
|
12
|
-
const key = root ? statsProjectKey({
|
|
13
|
-
root,
|
|
14
|
-
commonDir: gitCommonDir(root),
|
|
15
|
-
repoRoot: repoRoot(root)
|
|
16
|
-
}) : null;
|
|
17
|
-
const { record, note } = readStats();
|
|
18
|
-
if (note) console.error(chalk.dim(note));
|
|
19
|
-
const machine = record?.machine ?? {};
|
|
20
|
-
const project = key ? record?.projects?.[key] ?? {} : {};
|
|
21
|
-
if (opts.json) {
|
|
22
|
-
console.log(JSON.stringify({
|
|
23
|
-
version: 1,
|
|
24
|
-
project: key ? {
|
|
25
|
-
key,
|
|
26
|
-
ios: project.ios ?? null,
|
|
27
|
-
android: project.android ?? null
|
|
28
|
-
} : null,
|
|
29
|
-
machine: {
|
|
30
|
-
ios: machine.ios ?? null,
|
|
31
|
-
android: machine.android ?? null
|
|
32
|
-
}
|
|
33
|
-
}));
|
|
34
|
-
return;
|
|
35
|
-
}
|
|
36
|
-
const lines = [];
|
|
37
|
-
if (key) lines.push(`project ${key}`, ...sectionLines(project));
|
|
38
|
-
lines.push("machine", ...sectionLines(machine));
|
|
39
|
-
for (const line of lines) console.log(line);
|
|
40
|
-
});
|
|
41
|
-
}
|
|
42
|
-
function sectionLines(scope) {
|
|
43
|
-
const lines = PLATFORMS.filter((platform) => scope[platform]).map((platform) => bucketLine(platform, scope[platform]));
|
|
44
|
-
return lines.length ? lines : [chalk.dim(" no runs recorded")];
|
|
45
|
-
}
|
|
46
|
-
function bucketLine(platform, bucket) {
|
|
47
|
-
const finished = bucket.runs - bucket.failed;
|
|
48
|
-
const cells = [
|
|
49
|
-
`${bucket.runs} runs${bucket.failed > 0 ? ` (${bucket.failed} failed)` : ""}`,
|
|
50
|
-
`${bucket.hits} hits (${finished > 0 ? `${Math.round(bucket.hits / finished * 100)}%` : "-"})`,
|
|
51
|
-
`cold run ${average(bucket.coldRunMs, bucket.coldRuns)} avg`,
|
|
52
|
-
`hit run ${average(bucket.hitRunMs, bucket.hitRuns)} avg`,
|
|
53
|
-
`saved ~${formatLongDuration(bucket.timeSavedMs)} (estimated)`,
|
|
54
|
-
`since ${bucket.firstRunAt.slice(0, 10)}`
|
|
55
|
-
];
|
|
56
|
-
return ` ${platform.padEnd(PLATFORM_WIDTH)}${cells.join(" ")}`;
|
|
57
|
-
}
|
|
58
|
-
function average(totalMs, runs) {
|
|
59
|
-
return runs > 0 ? formatLongDuration(Math.round(totalMs / runs)) : "-";
|
|
60
|
-
}
|
|
61
|
-
//#endregion
|
|
62
|
-
export { statsCommand as default };
|
package/dist/stats-CX1Z8Tca.mjs
DELETED
|
@@ -1,368 +0,0 @@
|
|
|
1
|
-
import { E as withConfigLock, d as getConfigDir } from "./config-lvc7d3C2.mjs";
|
|
2
|
-
import { readFileSync, realpathSync, renameSync, rmSync, writeFileSync } from "node:fs";
|
|
3
|
-
import { basename, dirname, join, relative, resolve } from "node:path";
|
|
4
|
-
const PLATFORMS = ["ios", "android"];
|
|
5
|
-
const OUTCOMES = ["hit", "cold"];
|
|
6
|
-
function statsFile() {
|
|
7
|
-
return join(getConfigDir(), "stats.json");
|
|
8
|
-
}
|
|
9
|
-
function emptyStats() {
|
|
10
|
-
return {
|
|
11
|
-
version: 1,
|
|
12
|
-
machine: {},
|
|
13
|
-
projects: {}
|
|
14
|
-
};
|
|
15
|
-
}
|
|
16
|
-
function statsProjectKey({ root, commonDir, repoRoot }) {
|
|
17
|
-
if (commonDir && repoRoot && basename(commonDir) === ".git") return canonical(join(dirname(commonDir), relative(repoRoot, root)));
|
|
18
|
-
return canonical(root);
|
|
19
|
-
}
|
|
20
|
-
function updateStats(record, run, now) {
|
|
21
|
-
const at = new Date(now).toISOString();
|
|
22
|
-
const durationMs = wholeMs(run.durationMs);
|
|
23
|
-
const phases = {
|
|
24
|
-
coldBuildMs: wholeMs(run.coldBuildMs),
|
|
25
|
-
podsMs: wholeMs(run.podsMs)
|
|
26
|
-
};
|
|
27
|
-
const projects = { ...record.projects };
|
|
28
|
-
const scope = { ...projects[run.projectKey] };
|
|
29
|
-
const machine = { ...record.machine };
|
|
30
|
-
const before = scope[run.platform] ?? null;
|
|
31
|
-
const credit = creditMs(before, run, durationMs);
|
|
32
|
-
scope[run.platform] = applyRun(before, run, {
|
|
33
|
-
at,
|
|
34
|
-
durationMs,
|
|
35
|
-
credit,
|
|
36
|
-
phases
|
|
37
|
-
});
|
|
38
|
-
projects[run.projectKey] = scope;
|
|
39
|
-
machine[run.platform] = applyRun(machine[run.platform] ?? null, run, {
|
|
40
|
-
at,
|
|
41
|
-
durationMs,
|
|
42
|
-
credit,
|
|
43
|
-
phases
|
|
44
|
-
});
|
|
45
|
-
const history = { ...record.history };
|
|
46
|
-
if (run.phases && !run.failed && !run.waitedForBuild) {
|
|
47
|
-
const outcome = isHit(run.cacheHit) ? "hit" : "cold";
|
|
48
|
-
const project = { ...history[run.projectKey] };
|
|
49
|
-
const lists = { ...project[run.platform] };
|
|
50
|
-
const sample = {
|
|
51
|
-
at,
|
|
52
|
-
durationMs,
|
|
53
|
-
phases: wholePhases(run.phases)
|
|
54
|
-
};
|
|
55
|
-
lists[outcome] = [...lists[outcome] ?? [], sample].slice(-10);
|
|
56
|
-
project[run.platform] = lists;
|
|
57
|
-
history[run.projectKey] = project;
|
|
58
|
-
}
|
|
59
|
-
return {
|
|
60
|
-
version: 1,
|
|
61
|
-
machine,
|
|
62
|
-
projects,
|
|
63
|
-
...Object.keys(history).length ? { history } : {}
|
|
64
|
-
};
|
|
65
|
-
}
|
|
66
|
-
function readStats() {
|
|
67
|
-
const path = statsFile();
|
|
68
|
-
let text;
|
|
69
|
-
try {
|
|
70
|
-
text = readFileSync(path, "utf-8");
|
|
71
|
-
} catch {
|
|
72
|
-
return {
|
|
73
|
-
record: null,
|
|
74
|
-
note: null
|
|
75
|
-
};
|
|
76
|
-
}
|
|
77
|
-
const parsed = parseRecord(text);
|
|
78
|
-
if (!parsed) return {
|
|
79
|
-
record: null,
|
|
80
|
-
note: `Run statistics at ${path} could not be read; the next ios or android run moves them aside and starts a new file.`
|
|
81
|
-
};
|
|
82
|
-
if (parsed.version > 1) return {
|
|
83
|
-
record: null,
|
|
84
|
-
note: `Run statistics at ${path} are version ${parsed.version}, which this Stim does not understand, so none are shown.`
|
|
85
|
-
};
|
|
86
|
-
return {
|
|
87
|
-
record: normalize(parsed),
|
|
88
|
-
note: null
|
|
89
|
-
};
|
|
90
|
-
}
|
|
91
|
-
function projectEstimates(record, projectKey, platform) {
|
|
92
|
-
const bucket = record?.projects?.[projectKey]?.[platform] ?? null;
|
|
93
|
-
return {
|
|
94
|
-
coldBuildMs: positive(bucket?.lastColdBuildMs),
|
|
95
|
-
podsMs: positive(bucket?.lastPodsMs)
|
|
96
|
-
};
|
|
97
|
-
}
|
|
98
|
-
function readRunEstimates({ projectKey, platform, read = readStats }) {
|
|
99
|
-
if (!projectKey) return {
|
|
100
|
-
coldBuildMs: null,
|
|
101
|
-
podsMs: null
|
|
102
|
-
};
|
|
103
|
-
try {
|
|
104
|
-
return projectEstimates(read().record, projectKey, platform);
|
|
105
|
-
} catch {
|
|
106
|
-
return {
|
|
107
|
-
coldBuildMs: null,
|
|
108
|
-
podsMs: null
|
|
109
|
-
};
|
|
110
|
-
}
|
|
111
|
-
}
|
|
112
|
-
function recordRunStats(run, now) {
|
|
113
|
-
return withConfigLock(() => {
|
|
114
|
-
const path = statsFile();
|
|
115
|
-
const loaded = loadForUpdate(path, now);
|
|
116
|
-
if (loaded.newerVersion !== null) return {
|
|
117
|
-
recorded: false,
|
|
118
|
-
note: `Run statistics at ${path} are version ${loaded.newerVersion}, which this Stim does not understand, so this run was not recorded.`
|
|
119
|
-
};
|
|
120
|
-
writeStats(path, updateStats(loaded.record, run, now));
|
|
121
|
-
return {
|
|
122
|
-
recorded: true,
|
|
123
|
-
note: loaded.note
|
|
124
|
-
};
|
|
125
|
-
});
|
|
126
|
-
}
|
|
127
|
-
function createRunRecorder({ platform, write, now, note, phases }) {
|
|
128
|
-
let projectKey = null;
|
|
129
|
-
let cacheKey = null;
|
|
130
|
-
let coldBuildMs = 0;
|
|
131
|
-
let podsMs = 0;
|
|
132
|
-
let recorded = false;
|
|
133
|
-
return {
|
|
134
|
-
setProject(key) {
|
|
135
|
-
projectKey = key;
|
|
136
|
-
},
|
|
137
|
-
setCacheKey(key) {
|
|
138
|
-
cacheKey = key;
|
|
139
|
-
},
|
|
140
|
-
setBuildMs(ms) {
|
|
141
|
-
coldBuildMs = wholeMs(ms);
|
|
142
|
-
},
|
|
143
|
-
setPodsMs(ms) {
|
|
144
|
-
podsMs = wholeMs(ms);
|
|
145
|
-
},
|
|
146
|
-
record({ failed, cacheHit = false, waited = null, durationMs }) {
|
|
147
|
-
if (!projectKey || !cacheKey || recorded) return;
|
|
148
|
-
recorded = true;
|
|
149
|
-
const ran = failed ? {} : phases?.() ?? {};
|
|
150
|
-
try {
|
|
151
|
-
const outcome = write({
|
|
152
|
-
platform,
|
|
153
|
-
projectKey,
|
|
154
|
-
failed,
|
|
155
|
-
cacheHit,
|
|
156
|
-
waitedForBuild: Boolean(waited),
|
|
157
|
-
durationMs,
|
|
158
|
-
...coldBuildMs > 0 ? { coldBuildMs } : {},
|
|
159
|
-
...podsMs > 0 ? { podsMs } : {},
|
|
160
|
-
...Object.keys(ran).length ? { phases: ran } : {}
|
|
161
|
-
}, now());
|
|
162
|
-
if (outcome?.note) note(outcome.note);
|
|
163
|
-
} catch (error) {
|
|
164
|
-
note(`Run statistics could not be recorded: ${error?.message || error}`);
|
|
165
|
-
}
|
|
166
|
-
}
|
|
167
|
-
};
|
|
168
|
-
}
|
|
169
|
-
function loadForUpdate(path, now) {
|
|
170
|
-
let text;
|
|
171
|
-
try {
|
|
172
|
-
text = readFileSync(path, "utf-8");
|
|
173
|
-
} catch {
|
|
174
|
-
return {
|
|
175
|
-
record: emptyStats(),
|
|
176
|
-
note: null,
|
|
177
|
-
newerVersion: null
|
|
178
|
-
};
|
|
179
|
-
}
|
|
180
|
-
const parsed = parseRecord(text);
|
|
181
|
-
if (!parsed) {
|
|
182
|
-
const aside = `${path}.corrupt-${now}`;
|
|
183
|
-
renameSync(path, aside);
|
|
184
|
-
return {
|
|
185
|
-
record: emptyStats(),
|
|
186
|
-
note: `Run statistics at ${path} could not be read, so they were moved to ${aside} and a new file was started.`,
|
|
187
|
-
newerVersion: null
|
|
188
|
-
};
|
|
189
|
-
}
|
|
190
|
-
if (parsed.version > 1) return {
|
|
191
|
-
record: emptyStats(),
|
|
192
|
-
note: null,
|
|
193
|
-
newerVersion: parsed.version
|
|
194
|
-
};
|
|
195
|
-
return {
|
|
196
|
-
record: normalize(parsed),
|
|
197
|
-
note: null,
|
|
198
|
-
newerVersion: null
|
|
199
|
-
};
|
|
200
|
-
}
|
|
201
|
-
function writeStats(path, record) {
|
|
202
|
-
const tmp = `${path}.${process.pid}.${Math.random().toString(36).slice(2)}.tmp`;
|
|
203
|
-
writeFileSync(tmp, `${JSON.stringify(record)}\n`);
|
|
204
|
-
try {
|
|
205
|
-
renameSync(tmp, path);
|
|
206
|
-
} catch (error) {
|
|
207
|
-
rmSync(tmp, { force: true });
|
|
208
|
-
throw error;
|
|
209
|
-
}
|
|
210
|
-
}
|
|
211
|
-
function parseRecord(text) {
|
|
212
|
-
let parsed;
|
|
213
|
-
try {
|
|
214
|
-
parsed = JSON.parse(text);
|
|
215
|
-
} catch {
|
|
216
|
-
return null;
|
|
217
|
-
}
|
|
218
|
-
if (!parsed || typeof parsed !== "object" || Array.isArray(parsed)) return null;
|
|
219
|
-
const version = parsed.version;
|
|
220
|
-
if (typeof version !== "number" || !Number.isInteger(version)) return null;
|
|
221
|
-
return parsed;
|
|
222
|
-
}
|
|
223
|
-
function normalize(record) {
|
|
224
|
-
const projects = {};
|
|
225
|
-
const source = record.projects;
|
|
226
|
-
if (source && typeof source === "object" && !Array.isArray(source)) for (const [key, scope] of Object.entries(source)) projects[key] = normalizeScope(scope);
|
|
227
|
-
const history = {};
|
|
228
|
-
if (isObject(record.history)) for (const [key, scope] of Object.entries(record.history)) {
|
|
229
|
-
const normalized = normalizeHistory(scope);
|
|
230
|
-
if (Object.keys(normalized).length) history[key] = normalized;
|
|
231
|
-
}
|
|
232
|
-
return {
|
|
233
|
-
version: 1,
|
|
234
|
-
machine: normalizeScope(record.machine),
|
|
235
|
-
projects,
|
|
236
|
-
...Object.keys(history).length ? { history } : {}
|
|
237
|
-
};
|
|
238
|
-
}
|
|
239
|
-
function isObject(value) {
|
|
240
|
-
return Boolean(value) && typeof value === "object" && !Array.isArray(value);
|
|
241
|
-
}
|
|
242
|
-
function normalizeHistory(scope) {
|
|
243
|
-
const history = {};
|
|
244
|
-
if (!isObject(scope)) return history;
|
|
245
|
-
for (const platform of PLATFORMS) {
|
|
246
|
-
const lists = scope[platform];
|
|
247
|
-
if (!isObject(lists)) continue;
|
|
248
|
-
const normalized = {};
|
|
249
|
-
for (const outcome of OUTCOMES) {
|
|
250
|
-
const samples = lists[outcome];
|
|
251
|
-
if (!Array.isArray(samples)) continue;
|
|
252
|
-
const kept = samples.filter(isObject).flatMap((sample) => {
|
|
253
|
-
const durationMs = wholeMs(sample.durationMs);
|
|
254
|
-
if (durationMs <= 0) return [];
|
|
255
|
-
return [{
|
|
256
|
-
at: timestamp(sample.at),
|
|
257
|
-
durationMs,
|
|
258
|
-
phases: wholePhases(sample.phases)
|
|
259
|
-
}];
|
|
260
|
-
});
|
|
261
|
-
if (kept.length) normalized[outcome] = kept.slice(-10);
|
|
262
|
-
}
|
|
263
|
-
if (Object.keys(normalized).length) history[platform] = normalized;
|
|
264
|
-
}
|
|
265
|
-
return history;
|
|
266
|
-
}
|
|
267
|
-
function wholePhases(phases) {
|
|
268
|
-
const out = {};
|
|
269
|
-
if (!isObject(phases)) return out;
|
|
270
|
-
for (const [name, ms] of Object.entries(phases)) {
|
|
271
|
-
const value = Number(ms);
|
|
272
|
-
if (Number.isFinite(value) && value >= 0) out[name] = Math.round(value);
|
|
273
|
-
}
|
|
274
|
-
return out;
|
|
275
|
-
}
|
|
276
|
-
function normalizeScope(scope) {
|
|
277
|
-
const normalized = {};
|
|
278
|
-
if (!scope || typeof scope !== "object" || Array.isArray(scope)) return normalized;
|
|
279
|
-
for (const platform of PLATFORMS) {
|
|
280
|
-
const bucket = scope[platform];
|
|
281
|
-
if (bucket && typeof bucket === "object" && !Array.isArray(bucket)) normalized[platform] = normalizeBucket(bucket);
|
|
282
|
-
}
|
|
283
|
-
return normalized;
|
|
284
|
-
}
|
|
285
|
-
function normalizeBucket(bucket) {
|
|
286
|
-
return {
|
|
287
|
-
runs: count(bucket.runs),
|
|
288
|
-
failed: count(bucket.failed),
|
|
289
|
-
hits: count(bucket.hits),
|
|
290
|
-
misses: count(bucket.misses),
|
|
291
|
-
coldRuns: count(bucket.coldRuns),
|
|
292
|
-
coldRunMs: count(bucket.coldRunMs),
|
|
293
|
-
hitRuns: count(bucket.hitRuns),
|
|
294
|
-
hitRunMs: count(bucket.hitRunMs),
|
|
295
|
-
timeSavedMs: count(bucket.timeSavedMs),
|
|
296
|
-
firstRunAt: timestamp(bucket.firstRunAt),
|
|
297
|
-
lastRunAt: timestamp(bucket.lastRunAt),
|
|
298
|
-
...count(bucket.lastColdBuildMs) > 0 ? { lastColdBuildMs: count(bucket.lastColdBuildMs) } : {},
|
|
299
|
-
...count(bucket.lastPodsMs) > 0 ? { lastPodsMs: count(bucket.lastPodsMs) } : {}
|
|
300
|
-
};
|
|
301
|
-
}
|
|
302
|
-
function applyRun(bucket, run, { at, durationMs, credit, phases }) {
|
|
303
|
-
const next = bucket ? { ...bucket } : {
|
|
304
|
-
runs: 0,
|
|
305
|
-
failed: 0,
|
|
306
|
-
hits: 0,
|
|
307
|
-
misses: 0,
|
|
308
|
-
coldRuns: 0,
|
|
309
|
-
coldRunMs: 0,
|
|
310
|
-
hitRuns: 0,
|
|
311
|
-
hitRunMs: 0,
|
|
312
|
-
timeSavedMs: 0,
|
|
313
|
-
firstRunAt: at,
|
|
314
|
-
lastRunAt: at
|
|
315
|
-
};
|
|
316
|
-
next.runs += 1;
|
|
317
|
-
next.lastRunAt = at;
|
|
318
|
-
if (phases.coldBuildMs > 0) next.lastColdBuildMs = phases.coldBuildMs;
|
|
319
|
-
if (phases.podsMs > 0) next.lastPodsMs = phases.podsMs;
|
|
320
|
-
if (run.failed) {
|
|
321
|
-
next.failed += 1;
|
|
322
|
-
return next;
|
|
323
|
-
}
|
|
324
|
-
if (isHit(run.cacheHit)) {
|
|
325
|
-
next.hits += 1;
|
|
326
|
-
if (!run.waitedForBuild) {
|
|
327
|
-
next.hitRuns += 1;
|
|
328
|
-
next.hitRunMs += durationMs;
|
|
329
|
-
next.timeSavedMs += credit;
|
|
330
|
-
}
|
|
331
|
-
return next;
|
|
332
|
-
}
|
|
333
|
-
next.misses += 1;
|
|
334
|
-
next.coldRuns += 1;
|
|
335
|
-
next.coldRunMs += durationMs;
|
|
336
|
-
return next;
|
|
337
|
-
}
|
|
338
|
-
function creditMs(bucket, run, durationMs) {
|
|
339
|
-
if (run.failed || !isHit(run.cacheHit) || run.waitedForBuild) return 0;
|
|
340
|
-
if (!bucket || bucket.coldRuns <= 0) return 0;
|
|
341
|
-
return Math.max(0, Math.round(bucket.coldRunMs / bucket.coldRuns) - durationMs);
|
|
342
|
-
}
|
|
343
|
-
function isHit(cacheHit) {
|
|
344
|
-
return cacheHit === "local" || cacheHit === "remote";
|
|
345
|
-
}
|
|
346
|
-
function positive(value) {
|
|
347
|
-
const ms = wholeMs(value);
|
|
348
|
-
return ms > 0 ? ms : null;
|
|
349
|
-
}
|
|
350
|
-
function wholeMs(value) {
|
|
351
|
-
const ms = Number(value);
|
|
352
|
-
return Number.isFinite(ms) && ms > 0 ? Math.round(ms) : 0;
|
|
353
|
-
}
|
|
354
|
-
function count(value) {
|
|
355
|
-
return wholeMs(value);
|
|
356
|
-
}
|
|
357
|
-
function timestamp(value) {
|
|
358
|
-
return typeof value === "string" && value !== "" ? value : (/* @__PURE__ */ new Date(0)).toISOString();
|
|
359
|
-
}
|
|
360
|
-
function canonical(path) {
|
|
361
|
-
try {
|
|
362
|
-
return realpathSync(path);
|
|
363
|
-
} catch {
|
|
364
|
-
return resolve(path);
|
|
365
|
-
}
|
|
366
|
-
}
|
|
367
|
-
//#endregion
|
|
368
|
-
export { statsProjectKey as a, recordRunStats as i, readRunEstimates as n, readStats as r, createRunRecorder as t };
|
|
@@ -1,40 +0,0 @@
|
|
|
1
|
-
import { t as getExecutor } from "./exec-DK8KaVHK.mjs";
|
|
2
|
-
//#region src/devices/stim-desktop.ts
|
|
3
|
-
const LAUNCH_SERVICES_LOOKUP = `ObjC.import('AppKit'); const url = $.NSWorkspace.sharedWorkspace.URLForApplicationWithBundleIdentifier('dev.stim.desktop'); url.isNil() ? '' : url.path.js`;
|
|
4
|
-
const STIM_DESKTOP_INSTALLED = "Stim Desktop installed";
|
|
5
|
-
/**
|
|
6
|
-
* macOS `open` passes its environment to an app it launches, so Stim Desktop
|
|
7
|
-
* started by a command run under a scoped `STIM_HOME` would serve that home.
|
|
8
|
-
*/
|
|
9
|
-
const STIM_DESKTOP_OPEN_OPTIONS = {
|
|
10
|
-
timeoutMs: 5e3,
|
|
11
|
-
killSignal: "SIGKILL",
|
|
12
|
-
omitEnv: ["STIM_HOME"]
|
|
13
|
-
};
|
|
14
|
-
/** Stim Desktop sets `STIM_DESKTOP_APP` to its bundle path for every command it runs; a non-empty value means Desktop is installed. */
|
|
15
|
-
function stimDesktopInstalled(platform = process.platform, env = process.env) {
|
|
16
|
-
if (platform !== "darwin") return false;
|
|
17
|
-
if (env.STIM_DESKTOP_APP) return true;
|
|
18
|
-
const found = getExecutor().runFileQuiet("osascript", [
|
|
19
|
-
"-l",
|
|
20
|
-
"JavaScript",
|
|
21
|
-
"-e",
|
|
22
|
-
LAUNCH_SERVICES_LOOKUP
|
|
23
|
-
], {
|
|
24
|
-
timeoutMs: 5e3,
|
|
25
|
-
killSignal: "SIGKILL"
|
|
26
|
-
});
|
|
27
|
-
return Boolean(found);
|
|
28
|
-
}
|
|
29
|
-
function settingDefault(setting, desktopInstalled = stimDesktopInstalled) {
|
|
30
|
-
if (setting.desktopDefault !== void 0 && desktopInstalled()) return {
|
|
31
|
-
value: setting.desktopDefault,
|
|
32
|
-
reason: STIM_DESKTOP_INSTALLED
|
|
33
|
-
};
|
|
34
|
-
return {
|
|
35
|
-
value: setting.default,
|
|
36
|
-
reason: null
|
|
37
|
-
};
|
|
38
|
-
}
|
|
39
|
-
//#endregion
|
|
40
|
-
export { settingDefault as n, stimDesktopInstalled as r, STIM_DESKTOP_OPEN_OPTIONS as t };
|