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
|
@@ -0,0 +1,411 @@
|
|
|
1
|
+
import { t as getExecutor } from "./exec-CaErVv7t.mjs";
|
|
2
|
+
import { j as formatBytes } from "./config-D0DbpZtM.mjs";
|
|
3
|
+
import { t as process_identity_exports } from "./process-identity-BmRm1qV0.mjs";
|
|
4
|
+
import { o as formatLongDuration } from "./command-output-DnJMdEY-.mjs";
|
|
5
|
+
import { a as envDir, l as processMatches, s as parseAgentDeviceRecord } from "./activity-BxwdD81S.mjs";
|
|
6
|
+
import { c as listWorkspaceDirs } from "./workspaces-BV4pdHFz.mjs";
|
|
7
|
+
import { randomUUID } from "node:crypto";
|
|
8
|
+
import { existsSync, mkdirSync, readFileSync, readdirSync, realpathSync, renameSync, rmSync, statSync, writeFileSync } from "node:fs";
|
|
9
|
+
import { dirname, isAbsolute, join, relative, resolve, sep } from "node:path";
|
|
10
|
+
import { configDir } from "@stim-cli/core";
|
|
11
|
+
import { agentDeviceUsageFile, readAgentDeviceUsageCache, readSwiftpmCacheUsage, swiftpmCacheUsageFile } from "@stim-cli/core/state";
|
|
12
|
+
import { homedir } from "node:os";
|
|
13
|
+
import chalk from "chalk";
|
|
14
|
+
//#region src/devices/report-only-usage.ts
|
|
15
|
+
function canonical(path) {
|
|
16
|
+
try {
|
|
17
|
+
return realpathSync.native(path);
|
|
18
|
+
} catch {
|
|
19
|
+
return resolve(path);
|
|
20
|
+
}
|
|
21
|
+
}
|
|
22
|
+
function parseDu(output) {
|
|
23
|
+
const sizes = /* @__PURE__ */ new Map();
|
|
24
|
+
for (const line of output.split("\n")) {
|
|
25
|
+
const match = /^(\d+)\t(.+?)\r?$/.exec(line);
|
|
26
|
+
if (match) sizes.set(resolve(match[2]), Number(match[1]) * 1024);
|
|
27
|
+
}
|
|
28
|
+
return sizes;
|
|
29
|
+
}
|
|
30
|
+
async function measureDu(args) {
|
|
31
|
+
let output = "";
|
|
32
|
+
let complete = true;
|
|
33
|
+
try {
|
|
34
|
+
output = await getExecutor().runFileAsync("du", args, { timeoutMs: 2e4 });
|
|
35
|
+
} catch (error) {
|
|
36
|
+
complete = false;
|
|
37
|
+
const failure = error;
|
|
38
|
+
if (failure.status === 1 && !failure.code && typeof failure.stdout === "string") output = failure.stdout;
|
|
39
|
+
}
|
|
40
|
+
return {
|
|
41
|
+
sizes: parseDu(output),
|
|
42
|
+
complete
|
|
43
|
+
};
|
|
44
|
+
}
|
|
45
|
+
function writeUsageCache(file, value) {
|
|
46
|
+
const temporary = `${file}.${randomUUID()}.tmp`;
|
|
47
|
+
try {
|
|
48
|
+
mkdirSync(dirname(file), { recursive: true });
|
|
49
|
+
writeFileSync(temporary, JSON.stringify(value));
|
|
50
|
+
renameSync(temporary, file);
|
|
51
|
+
} catch {
|
|
52
|
+
try {
|
|
53
|
+
rmSync(temporary, { force: true });
|
|
54
|
+
} catch {}
|
|
55
|
+
}
|
|
56
|
+
}
|
|
57
|
+
//#endregion
|
|
58
|
+
//#region src/devices/swiftpm-cache-usage.ts
|
|
59
|
+
async function getSwiftpmCacheUsage({ maxAgeMs = 6e5 } = {}) {
|
|
60
|
+
const dir = canonical(process.platform === "darwin" ? join(homedir(), "Library", "Caches", "org.swift.swiftpm") : join(process.env.XDG_CACHE_HOME || join(homedir(), ".cache"), "org.swift.swiftpm"));
|
|
61
|
+
const cached = readSwiftpmCacheUsage();
|
|
62
|
+
const age = cached ? Date.now() - Date.parse(cached.measuredAt) : Infinity;
|
|
63
|
+
if (cached && cached.dir === dir && age >= 0 && age < maxAgeMs) return cached;
|
|
64
|
+
const present = existsSync(dir);
|
|
65
|
+
const result = present ? await measureDu(["-sk", dir]) : null;
|
|
66
|
+
const bytes = present ? result?.complete ? result.sizes.get(dir) ?? null : null : 0;
|
|
67
|
+
const usage = {
|
|
68
|
+
version: 1,
|
|
69
|
+
measuredAt: (/* @__PURE__ */ new Date()).toISOString(),
|
|
70
|
+
dir,
|
|
71
|
+
present,
|
|
72
|
+
bytes,
|
|
73
|
+
complete: bytes !== null
|
|
74
|
+
};
|
|
75
|
+
writeUsageCache(swiftpmCacheUsageFile(), usage);
|
|
76
|
+
return usage;
|
|
77
|
+
}
|
|
78
|
+
//#endregion
|
|
79
|
+
//#region src/devices/agent-device-usage.ts
|
|
80
|
+
const MAX_AGE_MS = 6e5;
|
|
81
|
+
function contains(parent, path) {
|
|
82
|
+
const rel = relative(parent, path);
|
|
83
|
+
return rel === "" || rel !== ".." && !rel.startsWith(`..${sep}`) && !isAbsolute(rel);
|
|
84
|
+
}
|
|
85
|
+
function parseRunnerMetadata(raw) {
|
|
86
|
+
let value = null;
|
|
87
|
+
try {
|
|
88
|
+
value = raw === null ? null : JSON.parse(raw);
|
|
89
|
+
} catch {}
|
|
90
|
+
return {
|
|
91
|
+
packageVersion: typeof value?.packageVersion === "string" ? value.packageVersion : null,
|
|
92
|
+
xcodeBuildVersion: typeof value?.xcodeBuildVersion === "string" ? value.xcodeBuildVersion : null
|
|
93
|
+
};
|
|
94
|
+
}
|
|
95
|
+
function runnerLastUsedAt(plist, mtimeMs) {
|
|
96
|
+
const match = plist?.match(/<key>LastAccessedDate<\/key>\s*<date>([^<]+)<\/date>/);
|
|
97
|
+
const date = match ? Date.parse(match[1]) : NaN;
|
|
98
|
+
const at = Number.isFinite(date) ? date : mtimeMs;
|
|
99
|
+
return at !== null && Number.isFinite(at) ? new Date(at).toISOString() : null;
|
|
100
|
+
}
|
|
101
|
+
function runnerInUse(dir, leases, unreadable, lock, startOf) {
|
|
102
|
+
if (unreadable || leases.some((lease) => !lease.readable)) return {
|
|
103
|
+
inUse: true,
|
|
104
|
+
inUseReason: "unreadable"
|
|
105
|
+
};
|
|
106
|
+
for (const lease of leases) {
|
|
107
|
+
if (!lease.xctestrunPath || !contains(dir, lease.xctestrunPath)) continue;
|
|
108
|
+
const liveness = [lease.owner, lease.runner].flatMap((process) => process ? [processMatches(process, startOf)] : []);
|
|
109
|
+
if (liveness.includes("live")) return {
|
|
110
|
+
inUse: true,
|
|
111
|
+
inUseReason: "lease"
|
|
112
|
+
};
|
|
113
|
+
if (liveness.includes("unknown")) return {
|
|
114
|
+
inUse: true,
|
|
115
|
+
inUseReason: "unreadable"
|
|
116
|
+
};
|
|
117
|
+
}
|
|
118
|
+
if (lock === "unreadable") return {
|
|
119
|
+
inUse: true,
|
|
120
|
+
inUseReason: "unreadable"
|
|
121
|
+
};
|
|
122
|
+
if (lock && processMatches(lock, startOf) !== "dead") return {
|
|
123
|
+
inUse: true,
|
|
124
|
+
inUseReason: "lock"
|
|
125
|
+
};
|
|
126
|
+
return {
|
|
127
|
+
inUse: false,
|
|
128
|
+
inUseReason: null
|
|
129
|
+
};
|
|
130
|
+
}
|
|
131
|
+
function subtract(total, parts) {
|
|
132
|
+
return total === null || parts.some((part) => part === null) ? null : Math.max(0, total - parts.reduce((sum, part) => sum + part, 0));
|
|
133
|
+
}
|
|
134
|
+
function largest(entries) {
|
|
135
|
+
return entries.toSorted((a, b) => (b.bytes ?? -1) - (a.bytes ?? -1));
|
|
136
|
+
}
|
|
137
|
+
function assembleAgentDeviceUsage(tree, sizes, complete, measuredAt) {
|
|
138
|
+
const size = (dir) => tree.absent.has(dir) ? 0 : sizes.get(dir) ?? null;
|
|
139
|
+
const { stateDir, runnerRoot } = tree.roots;
|
|
140
|
+
const sessions = join(stateDir, "sessions");
|
|
141
|
+
const logs = join(stateDir, "logs");
|
|
142
|
+
const runnerBytes = tree.runnerPresent ? size(runnerRoot) : 0;
|
|
143
|
+
const platforms = largest(tree.platforms.map((platform) => ({
|
|
144
|
+
...platform,
|
|
145
|
+
bytes: size(platform.dir),
|
|
146
|
+
entries: largest(platform.entries.map((entry) => ({
|
|
147
|
+
...entry,
|
|
148
|
+
bytes: size(entry.dir)
|
|
149
|
+
})))
|
|
150
|
+
})));
|
|
151
|
+
const stateBytes = tree.statePresent ? size(stateDir) : 0;
|
|
152
|
+
const sessionsBytes = tree.statePresent ? size(sessions) : 0;
|
|
153
|
+
const logsBytes = tree.statePresent ? size(logs) : 0;
|
|
154
|
+
const workspaces = largest(tree.workspaces.map((entry) => ({
|
|
155
|
+
...entry,
|
|
156
|
+
bytes: size(entry.dir)
|
|
157
|
+
})));
|
|
158
|
+
const hosted = tree.hosted ? {
|
|
159
|
+
...tree.hosted,
|
|
160
|
+
bytes: size(tree.hosted.dir)
|
|
161
|
+
} : null;
|
|
162
|
+
return {
|
|
163
|
+
version: 1,
|
|
164
|
+
measuredAt,
|
|
165
|
+
complete,
|
|
166
|
+
bytes: (stateBytes ?? 0) + (contains(stateDir, runnerRoot) ? 0 : runnerBytes ?? 0) + workspaces.reduce((sum, entry) => sum + (entry.bytes ?? 0), 0) + (hosted?.bytes ?? 0),
|
|
167
|
+
stateDir: {
|
|
168
|
+
dir: stateDir,
|
|
169
|
+
present: tree.statePresent,
|
|
170
|
+
bytes: stateBytes,
|
|
171
|
+
sessions: {
|
|
172
|
+
dir: sessions,
|
|
173
|
+
bytes: sessionsBytes,
|
|
174
|
+
count: tree.sessionsCount
|
|
175
|
+
},
|
|
176
|
+
logs: {
|
|
177
|
+
dir: logs,
|
|
178
|
+
bytes: logsBytes
|
|
179
|
+
},
|
|
180
|
+
other: {
|
|
181
|
+
bytes: subtract(stateBytes, [
|
|
182
|
+
sessionsBytes,
|
|
183
|
+
logsBytes,
|
|
184
|
+
...contains(stateDir, runnerRoot) ? [runnerBytes] : []
|
|
185
|
+
]),
|
|
186
|
+
largest: largest(tree.otherChildren.map((entry) => ({
|
|
187
|
+
...entry,
|
|
188
|
+
bytes: sizes.get(join(stateDir, entry.name)) ?? entry.bytes
|
|
189
|
+
}))).slice(0, 5)
|
|
190
|
+
}
|
|
191
|
+
},
|
|
192
|
+
runnerBuilds: {
|
|
193
|
+
dir: runnerRoot,
|
|
194
|
+
present: tree.runnerPresent,
|
|
195
|
+
bytes: runnerBytes,
|
|
196
|
+
sharedBytes: tree.runnerPresent ? subtract(size(join(runnerRoot, "derived")), platforms.map((entry) => entry.bytes)) : 0,
|
|
197
|
+
platforms
|
|
198
|
+
},
|
|
199
|
+
workspaces,
|
|
200
|
+
hosted
|
|
201
|
+
};
|
|
202
|
+
}
|
|
203
|
+
function readText(path) {
|
|
204
|
+
try {
|
|
205
|
+
return readFileSync(path, "utf8");
|
|
206
|
+
} catch {
|
|
207
|
+
return null;
|
|
208
|
+
}
|
|
209
|
+
}
|
|
210
|
+
function children(dir) {
|
|
211
|
+
try {
|
|
212
|
+
return readdirSync(dir);
|
|
213
|
+
} catch {
|
|
214
|
+
return [];
|
|
215
|
+
}
|
|
216
|
+
}
|
|
217
|
+
function directories(dir) {
|
|
218
|
+
try {
|
|
219
|
+
return readdirSync(dir, { withFileTypes: true }).filter((entry) => entry.isDirectory()).map((entry) => entry.name);
|
|
220
|
+
} catch {
|
|
221
|
+
return [];
|
|
222
|
+
}
|
|
223
|
+
}
|
|
224
|
+
function workspaceAgentDeviceDir(dir) {
|
|
225
|
+
return join(dir, "agent-device");
|
|
226
|
+
}
|
|
227
|
+
function readRunnerLock(dir) {
|
|
228
|
+
if (!existsSync(dir)) return null;
|
|
229
|
+
try {
|
|
230
|
+
const owner = JSON.parse(readFileSync(join(dir, "owner.json"), "utf8"));
|
|
231
|
+
if (owner && typeof owner === "object" && !Array.isArray(owner) && "pid" in owner && typeof owner.pid === "number" && Number.isInteger(owner.pid) && owner.pid > 0 && "startTime" in owner && typeof owner.startTime === "string" && Number.isFinite(Date.parse(owner.startTime))) return {
|
|
232
|
+
pid: owner.pid,
|
|
233
|
+
startTime: owner.startTime
|
|
234
|
+
};
|
|
235
|
+
} catch {}
|
|
236
|
+
return "unreadable";
|
|
237
|
+
}
|
|
238
|
+
function discover() {
|
|
239
|
+
const runnerRoot = canonical(join(homedir(), ".agent-device", "apple-runner"));
|
|
240
|
+
const hostedDir = canonical(join(configDir(), "server", "agent-device"));
|
|
241
|
+
const workspaceDirs = listWorkspaceDirs().map(({ dir, projectRoot }) => ({
|
|
242
|
+
dir: canonical(workspaceAgentDeviceDir(dir)),
|
|
243
|
+
projectRoot,
|
|
244
|
+
bytes: null
|
|
245
|
+
}));
|
|
246
|
+
const override = envDir("AGENT_DEVICE_STATE_DIR");
|
|
247
|
+
const candidate = override ? canonical(override) : null;
|
|
248
|
+
const overlaps = candidate && [...workspaceDirs.map(({ dir }) => dir), hostedDir].some((dir) => contains(dir, candidate) || contains(candidate, dir));
|
|
249
|
+
const stateDir = candidate && !overlaps ? candidate : canonical(join(homedir(), ".agent-device"));
|
|
250
|
+
const workspaces = workspaceDirs.filter(({ dir }) => existsSync(dir));
|
|
251
|
+
const roots = {
|
|
252
|
+
stateDir,
|
|
253
|
+
runnerRoot,
|
|
254
|
+
hostedDir,
|
|
255
|
+
workspaceDirs: workspaces.map(({ dir }) => dir).toSorted()
|
|
256
|
+
};
|
|
257
|
+
const leaseDir = envDir("AGENT_DEVICE_IOS_RUNNER_LEASE_DIR") ?? join(runnerRoot, "leases");
|
|
258
|
+
let leases = [];
|
|
259
|
+
let unreadable = false;
|
|
260
|
+
try {
|
|
261
|
+
leases = readdirSync(leaseDir).filter((name) => name.endsWith(".json")).map((name) => {
|
|
262
|
+
const path = join(leaseDir, name);
|
|
263
|
+
const record = parseAgentDeviceRecord("runner-lease", path, readText(path));
|
|
264
|
+
if (record.xctestrunPath) record.xctestrunPath = canonical(record.xctestrunPath);
|
|
265
|
+
return record;
|
|
266
|
+
});
|
|
267
|
+
} catch (error) {
|
|
268
|
+
unreadable = error.code !== "ENOENT";
|
|
269
|
+
}
|
|
270
|
+
const starts = /* @__PURE__ */ new Map();
|
|
271
|
+
const startOf = (pid) => {
|
|
272
|
+
if (!starts.has(pid)) starts.set(pid, (0, process_identity_exports.inspectProcessStart)(pid));
|
|
273
|
+
return starts.get(pid);
|
|
274
|
+
};
|
|
275
|
+
const derived = join(runnerRoot, "derived");
|
|
276
|
+
const platforms = directories(derived).flatMap((platform) => {
|
|
277
|
+
const dir = join(derived, platform);
|
|
278
|
+
const entries = directories(dir).filter((name) => name.startsWith("cache-") && !name.endsWith(".lock")).map((name) => {
|
|
279
|
+
const entryDir = join(dir, name);
|
|
280
|
+
let mtime = null;
|
|
281
|
+
try {
|
|
282
|
+
mtime = statSync(entryDir).mtimeMs;
|
|
283
|
+
} catch {}
|
|
284
|
+
return Object.assign({
|
|
285
|
+
name,
|
|
286
|
+
dir: entryDir,
|
|
287
|
+
bytes: null,
|
|
288
|
+
lastUsedAt: runnerLastUsedAt(readText(join(entryDir, "info.plist")), mtime)
|
|
289
|
+
}, parseRunnerMetadata(readText(join(entryDir, ".agent-device-runner-cache.json"))), runnerInUse(canonical(entryDir), leases, unreadable, readRunnerLock(`${entryDir}.lock`), startOf));
|
|
290
|
+
});
|
|
291
|
+
return entries.length ? [{
|
|
292
|
+
platform,
|
|
293
|
+
dir,
|
|
294
|
+
bytes: null,
|
|
295
|
+
entries
|
|
296
|
+
}] : [];
|
|
297
|
+
});
|
|
298
|
+
const statePresent = existsSync(stateDir);
|
|
299
|
+
const runnerPresent = existsSync(runnerRoot);
|
|
300
|
+
const absent = new Set([
|
|
301
|
+
join(stateDir, "sessions"),
|
|
302
|
+
join(stateDir, "logs"),
|
|
303
|
+
derived
|
|
304
|
+
].filter((dir) => !existsSync(dir)));
|
|
305
|
+
const otherChildren = children(stateDir).filter((name) => ![
|
|
306
|
+
"sessions",
|
|
307
|
+
"logs",
|
|
308
|
+
"apple-runner"
|
|
309
|
+
].includes(name)).map((name) => {
|
|
310
|
+
let bytes = null;
|
|
311
|
+
try {
|
|
312
|
+
const stat = statSync(join(stateDir, name));
|
|
313
|
+
if (stat.isFile() && typeof stat.blocks === "number") bytes = stat.blocks * 512;
|
|
314
|
+
} catch {}
|
|
315
|
+
return {
|
|
316
|
+
name,
|
|
317
|
+
bytes
|
|
318
|
+
};
|
|
319
|
+
});
|
|
320
|
+
return {
|
|
321
|
+
roots,
|
|
322
|
+
statePresent,
|
|
323
|
+
runnerPresent,
|
|
324
|
+
sessionsCount: directories(join(stateDir, "sessions")).length,
|
|
325
|
+
otherChildren,
|
|
326
|
+
platforms,
|
|
327
|
+
workspaces,
|
|
328
|
+
hosted: existsSync(hostedDir) ? {
|
|
329
|
+
dir: hostedDir,
|
|
330
|
+
bytes: null,
|
|
331
|
+
sessions: directories(hostedDir).length
|
|
332
|
+
} : null,
|
|
333
|
+
absent
|
|
334
|
+
};
|
|
335
|
+
}
|
|
336
|
+
async function getAgentDeviceUsage({ maxAgeMs = MAX_AGE_MS } = {}) {
|
|
337
|
+
const tree = discover();
|
|
338
|
+
const cached = readAgentDeviceUsageCache();
|
|
339
|
+
const age = cached ? Date.now() - Date.parse(cached.usage.measuredAt) : Infinity;
|
|
340
|
+
if (cached && age >= 0 && age < maxAgeMs && JSON.stringify(cached.roots) === JSON.stringify(tree.roots)) return cached.usage;
|
|
341
|
+
const sizes = /* @__PURE__ */ new Map();
|
|
342
|
+
let complete = true;
|
|
343
|
+
const measure = async (args) => {
|
|
344
|
+
const result = await measureDu(args);
|
|
345
|
+
complete &&= result.complete;
|
|
346
|
+
for (const [dir, bytes] of result.sizes) sizes.set(dir, bytes);
|
|
347
|
+
};
|
|
348
|
+
if (tree.statePresent) await measure([
|
|
349
|
+
"-k",
|
|
350
|
+
"-d",
|
|
351
|
+
"4",
|
|
352
|
+
tree.roots.stateDir
|
|
353
|
+
]);
|
|
354
|
+
if (tree.runnerPresent && !contains(tree.roots.stateDir, tree.roots.runnerRoot)) await measure([
|
|
355
|
+
"-k",
|
|
356
|
+
"-d",
|
|
357
|
+
"4",
|
|
358
|
+
tree.roots.runnerRoot
|
|
359
|
+
]);
|
|
360
|
+
const extra = [...tree.roots.workspaceDirs, ...tree.hosted ? [tree.hosted.dir] : []];
|
|
361
|
+
if (extra.length) await measure(["-sk", ...extra]);
|
|
362
|
+
const usage = assembleAgentDeviceUsage(tree, sizes, complete, (/* @__PURE__ */ new Date()).toISOString());
|
|
363
|
+
writeUsageCache(agentDeviceUsageFile(), {
|
|
364
|
+
...usage,
|
|
365
|
+
roots: tree.roots
|
|
366
|
+
});
|
|
367
|
+
return usage;
|
|
368
|
+
}
|
|
369
|
+
//#endregion
|
|
370
|
+
//#region src/devices/swiftpm-cache-usage-output.ts
|
|
371
|
+
function swiftpmCacheLines(usage, now = Date.now()) {
|
|
372
|
+
if (!usage?.present) return [];
|
|
373
|
+
return [
|
|
374
|
+
`SwiftPM cache (${usage.bytes === null ? "unknown" : formatBytes(usage.bytes).replace(/([KMG])$/, " $1B")}${usage.complete ? "" : ", incomplete"}) - measured ${formatLongDuration(Math.max(0, now - Date.parse(usage.measuredAt)))} ago`,
|
|
375
|
+
` ${usage.dir}`,
|
|
376
|
+
chalk.dim(" shared by every SwiftPM build on this machine; Stim reports it and never deletes it")
|
|
377
|
+
];
|
|
378
|
+
}
|
|
379
|
+
//#endregion
|
|
380
|
+
//#region src/devices/agent-device-usage-output.ts
|
|
381
|
+
const size = (bytes) => bytes === null ? "unknown" : formatBytes(bytes);
|
|
382
|
+
function agentDeviceLines(usage, detailed = false, now = Date.now()) {
|
|
383
|
+
if (!usage || !usage.stateDir.present && !usage.runnerBuilds.present && !usage.workspaces.length && !usage.hosted) return [];
|
|
384
|
+
const lines = [`agent-device (${formatBytes(usage.bytes)}${usage.complete ? "" : ", incomplete"}) - measured ${formatLongDuration(Math.max(0, now - Date.parse(usage.measuredAt)))} ago`];
|
|
385
|
+
lines.push(` runner builds: ${size(usage.runnerBuilds.bytes)}`);
|
|
386
|
+
for (const platform of usage.runnerBuilds.platforms) {
|
|
387
|
+
lines.push(` ${platform.platform}: ${size(platform.bytes)}, ${platform.entries.length} entries, ${platform.entries.filter((entry) => entry.inUse).length} in use`);
|
|
388
|
+
if (detailed) for (const entry of platform.entries) {
|
|
389
|
+
const details = [
|
|
390
|
+
entry.lastUsedAt ? `last use ${entry.lastUsedAt.slice(0, 10)}` : "last use unknown",
|
|
391
|
+
entry.packageVersion ? `agent-device ${entry.packageVersion}` : null,
|
|
392
|
+
entry.xcodeBuildVersion ? `Xcode ${entry.xcodeBuildVersion}` : null,
|
|
393
|
+
entry.inUse ? `in use (${entry.inUseReason})` : null
|
|
394
|
+
].filter(Boolean);
|
|
395
|
+
lines.push(` ${entry.name}: ${size(entry.bytes)}, ${details.join(", ")}`, ` ${entry.dir}`);
|
|
396
|
+
}
|
|
397
|
+
}
|
|
398
|
+
const { sessions, logs, other } = usage.stateDir;
|
|
399
|
+
lines.push(` sessions: ${size(sessions.bytes)}, ${sessions.count} entries`, ` logs: ${size(logs.bytes)}`, ` other: ${size(other.bytes)}`);
|
|
400
|
+
if (detailed) for (const entry of other.largest) lines.push(` ${entry.name}: ${size(entry.bytes)}`);
|
|
401
|
+
const knownWorkspaceBytes = usage.workspaces.reduce((sum, entry) => sum + (entry.bytes ?? 0), 0);
|
|
402
|
+
if (usage.workspaces.length) {
|
|
403
|
+
lines.push(` workspaces: ${usage.workspaces.length}, ${usage.workspaces.some((entry) => entry.bytes === null) ? "at least " : ""}${formatBytes(knownWorkspaceBytes)}`);
|
|
404
|
+
if (detailed) for (const entry of usage.workspaces) lines.push(` ${entry.dir}: ${size(entry.bytes)}`);
|
|
405
|
+
}
|
|
406
|
+
if (usage.hosted) lines.push(` stim-server hosted: ${size(usage.hosted.bytes)}${detailed ? `, ${usage.hosted.sessions} entries, ${usage.hosted.dir}` : ""}`);
|
|
407
|
+
if (detailed) lines.push(" Stim never trims or deletes the shared runner builds, sessions, logs and other state or the hosted driver dir; a workspace's own agent-device dir goes only with its workspace.", " A lease flag identifies a live owner or runner; a lock flag identifies a live or unverified lock owner, and unreadable flags conservatively keep entries in use.", " Clear the rest with agent-device's own tooling or by removing the directories yourself.");
|
|
408
|
+
return lines;
|
|
409
|
+
}
|
|
410
|
+
//#endregion
|
|
411
|
+
export { getSwiftpmCacheUsage as i, swiftpmCacheLines as n, getAgentDeviceUsage as r, agentDeviceLines as t };
|