@stim-cli/core 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 +18 -0
- package/dist/{core-CmZJEFj_.mjs → core-DWOUn9xp.mjs} +179 -5
- package/dist/index-DPo8Bexj.d.mts +2228 -0
- package/dist/index.d.mts +42 -1
- package/dist/index.mjs +2 -2
- package/dist/oversight.d.mts +308 -0
- package/dist/oversight.mjs +666 -0
- package/dist/ownership-claim-Xxxr9MPp.d.mts +152 -0
- package/dist/ownership-claim.d.mts +1 -151
- package/dist/phone-protocol.d.mts +458 -0
- package/dist/phone-protocol.mjs +2 -0
- package/dist/process-identity-BTyww2Xj.d.mts +37 -0
- package/dist/process-identity.d.mts +2 -30
- package/dist/process-identity.mjs +10 -2
- package/dist/protocol-B0KcaUee.d.mts +1465 -0
- package/dist/protocol.d.mts +2 -0
- package/dist/protocol.mjs +379 -0
- package/dist/receive-protocol.d.mts +12 -0
- package/dist/receive-protocol.mjs +19751 -0
- package/dist/state.d.mts +2 -777
- package/dist/state.mjs +4126 -1133
- package/package.json +21 -1
|
@@ -0,0 +1,2228 @@
|
|
|
1
|
+
import { o as ClaimHandle } from "./ownership-claim-Xxxr9MPp.mjs";
|
|
2
|
+
//#region state/ndjson.d.ts
|
|
3
|
+
interface NdjsonRecord {
|
|
4
|
+
ts?: number;
|
|
5
|
+
src?: string;
|
|
6
|
+
level?: string;
|
|
7
|
+
msg?: string;
|
|
8
|
+
/** With `logs --errors --json`: the code frame and stack lines Expo printed after this error. */
|
|
9
|
+
context?: string[];
|
|
10
|
+
[key: string]: unknown;
|
|
11
|
+
}
|
|
12
|
+
declare const LEVELS: string[];
|
|
13
|
+
declare const SOURCES: string[];
|
|
14
|
+
declare function levelRank(level?: string): number;
|
|
15
|
+
declare function parseNdjsonLine(line: unknown): NdjsonRecord | null;
|
|
16
|
+
declare function parseNdjsonText(text: unknown): NdjsonRecord[];
|
|
17
|
+
declare function readNdjsonGenerations(file: string): NdjsonRecord[];
|
|
18
|
+
//#endregion
|
|
19
|
+
//#region state/agent-actions.d.ts
|
|
20
|
+
interface AgentTarget {
|
|
21
|
+
platform: "ios" | "android";
|
|
22
|
+
id: string;
|
|
23
|
+
slot: string;
|
|
24
|
+
name?: string;
|
|
25
|
+
}
|
|
26
|
+
interface AgentActionReaderOptions {
|
|
27
|
+
sessionsDirs: readonly string[] | (() => readonly string[]);
|
|
28
|
+
targets?: AgentTarget[];
|
|
29
|
+
sinceTs?: number;
|
|
30
|
+
now?: () => number;
|
|
31
|
+
claimedDevice?: (session: string, sessionsDir: string) => string | null;
|
|
32
|
+
}
|
|
33
|
+
/**
|
|
34
|
+
* Reads agent-device session actions incrementally from the supplied sessions directories. With targets,
|
|
35
|
+
* records are restricted to those devices; without targets, retained session metadata supplies attribution.
|
|
36
|
+
* Missing directories and unreadable files yield no records.
|
|
37
|
+
*/
|
|
38
|
+
declare function createAgentActionReader({ sessionsDirs, targets, sinceTs, now, claimedDevice }: AgentActionReaderOptions): () => NdjsonRecord[];
|
|
39
|
+
//#endregion
|
|
40
|
+
//#region state/agent-device-usage.d.ts
|
|
41
|
+
interface AgentDeviceUsage {
|
|
42
|
+
version: 1;
|
|
43
|
+
measuredAt: string;
|
|
44
|
+
bytes: number;
|
|
45
|
+
complete: boolean;
|
|
46
|
+
stateDir: {
|
|
47
|
+
dir: string;
|
|
48
|
+
present: boolean;
|
|
49
|
+
bytes: number | null;
|
|
50
|
+
sessions: {
|
|
51
|
+
dir: string;
|
|
52
|
+
bytes: number | null;
|
|
53
|
+
count: number;
|
|
54
|
+
};
|
|
55
|
+
logs: {
|
|
56
|
+
dir: string;
|
|
57
|
+
bytes: number | null;
|
|
58
|
+
};
|
|
59
|
+
other: {
|
|
60
|
+
bytes: number | null;
|
|
61
|
+
largest: {
|
|
62
|
+
name: string;
|
|
63
|
+
bytes: number | null;
|
|
64
|
+
}[];
|
|
65
|
+
};
|
|
66
|
+
};
|
|
67
|
+
runnerBuilds: {
|
|
68
|
+
dir: string;
|
|
69
|
+
present: boolean;
|
|
70
|
+
bytes: number | null;
|
|
71
|
+
sharedBytes: number | null;
|
|
72
|
+
platforms: {
|
|
73
|
+
platform: string;
|
|
74
|
+
dir: string;
|
|
75
|
+
bytes: number | null;
|
|
76
|
+
entries: {
|
|
77
|
+
name: string;
|
|
78
|
+
dir: string;
|
|
79
|
+
bytes: number | null;
|
|
80
|
+
lastUsedAt: string | null;
|
|
81
|
+
packageVersion: string | null;
|
|
82
|
+
xcodeBuildVersion: string | null;
|
|
83
|
+
inUse: boolean;
|
|
84
|
+
inUseReason: "lease" | "lock" | "unreadable" | null;
|
|
85
|
+
}[];
|
|
86
|
+
}[];
|
|
87
|
+
};
|
|
88
|
+
workspaces: {
|
|
89
|
+
dir: string;
|
|
90
|
+
projectRoot: string | null;
|
|
91
|
+
bytes: number | null;
|
|
92
|
+
}[];
|
|
93
|
+
hosted: {
|
|
94
|
+
dir: string;
|
|
95
|
+
bytes: number | null;
|
|
96
|
+
sessions: number;
|
|
97
|
+
} | null;
|
|
98
|
+
}
|
|
99
|
+
interface AgentDeviceUsageRoots {
|
|
100
|
+
stateDir: string;
|
|
101
|
+
runnerRoot: string;
|
|
102
|
+
hostedDir: string;
|
|
103
|
+
workspaceDirs: string[];
|
|
104
|
+
}
|
|
105
|
+
declare function agentDeviceUsageFile(): string;
|
|
106
|
+
declare function readAgentDeviceUsageCache(): {
|
|
107
|
+
usage: AgentDeviceUsage;
|
|
108
|
+
roots: AgentDeviceUsageRoots;
|
|
109
|
+
} | null;
|
|
110
|
+
declare function readAgentDeviceUsage(): AgentDeviceUsage | null;
|
|
111
|
+
//#endregion
|
|
112
|
+
//#region state/swiftpm-cache-usage.d.ts
|
|
113
|
+
interface SwiftpmCacheUsage {
|
|
114
|
+
version: 1;
|
|
115
|
+
measuredAt: string;
|
|
116
|
+
dir: string;
|
|
117
|
+
present: boolean;
|
|
118
|
+
bytes: number | null;
|
|
119
|
+
complete: boolean;
|
|
120
|
+
}
|
|
121
|
+
declare function swiftpmCacheUsageFile(): string;
|
|
122
|
+
declare function readSwiftpmCacheUsage(): SwiftpmCacheUsage | null;
|
|
123
|
+
//#endregion
|
|
124
|
+
//#region state/build-capacity.d.ts
|
|
125
|
+
declare function buildSlotsDir(): string;
|
|
126
|
+
declare function buildSlotPath(index: number): string;
|
|
127
|
+
/**
|
|
128
|
+
* Takes the first free one of `max` `concurrency.maxBuilds` slots, recording `details` and the slot `index`. Returns
|
|
129
|
+
* null while every slot is held; throws the claim refusal when no slot is busy but one cannot be resolved.
|
|
130
|
+
*/
|
|
131
|
+
declare function tryAcquireBuildSlotClaim({ max, details }: {
|
|
132
|
+
max: number;
|
|
133
|
+
details: Record<string, unknown>;
|
|
134
|
+
}): {
|
|
135
|
+
claim: ClaimHandle;
|
|
136
|
+
index: number;
|
|
137
|
+
path: string;
|
|
138
|
+
} | null;
|
|
139
|
+
/**
|
|
140
|
+
* How busy this Mac is for native builds. `loadPerCore` is the 5-minute load average divided by the CPU count,
|
|
141
|
+
* rounded to one decimal. `builds` counts this Stim home's runs that hold a live native-run claim and are in
|
|
142
|
+
* prebuild, pods or compile here, not on a build machine, plus the build slots this Mac holds for other Macs'
|
|
143
|
+
* offloaded builds. `maxBuilds` is `concurrency.maxBuilds`, 0 when unlimited.
|
|
144
|
+
*/
|
|
145
|
+
interface MachineCapacity {
|
|
146
|
+
cpus: number;
|
|
147
|
+
loadPerCore: number;
|
|
148
|
+
builds: number;
|
|
149
|
+
maxBuilds: number;
|
|
150
|
+
maxLoadPerCore: number;
|
|
151
|
+
}
|
|
152
|
+
declare function machineCapacity(): MachineCapacity;
|
|
153
|
+
/** Why a Mac with this capacity should not take another native build; null when it can. */
|
|
154
|
+
declare function saturation(capacity: MachineCapacity): string | null;
|
|
155
|
+
//#endregion
|
|
156
|
+
//#region state/build-machines.d.ts
|
|
157
|
+
/**
|
|
158
|
+
* A build machine this Mac asked to build on. `machine` is the `offload.machines` entry; `nodeId` is the
|
|
159
|
+
* worker's tailnet StableID pinned when the request was sent, which every later connection must match.
|
|
160
|
+
*/
|
|
161
|
+
interface BuildMachineCredential {
|
|
162
|
+
machine: string;
|
|
163
|
+
nodeId: string;
|
|
164
|
+
dnsName: string;
|
|
165
|
+
deviceId: string;
|
|
166
|
+
deviceToken: string;
|
|
167
|
+
state: "pending" | "approved";
|
|
168
|
+
requestedAt: string;
|
|
169
|
+
ticketHash?: string;
|
|
170
|
+
}
|
|
171
|
+
declare function readBuildMachines(): BuildMachineCredential[];
|
|
172
|
+
//#endregion
|
|
173
|
+
//#region state/config-types.d.ts
|
|
174
|
+
type SettingsObject = Record<string, unknown>;
|
|
175
|
+
interface SupervisorRecord {
|
|
176
|
+
processToken?: string;
|
|
177
|
+
pid?: number;
|
|
178
|
+
port?: number;
|
|
179
|
+
startedAt?: string;
|
|
180
|
+
serverPid?: number;
|
|
181
|
+
mode?: string;
|
|
182
|
+
[key: string]: unknown;
|
|
183
|
+
}
|
|
184
|
+
interface IosDeviceRecord {
|
|
185
|
+
deviceUdid?: string;
|
|
186
|
+
deviceName?: string | null;
|
|
187
|
+
owned?: boolean;
|
|
188
|
+
serial?: string;
|
|
189
|
+
simslimManaged?: boolean;
|
|
190
|
+
schemeApprovals?: string[];
|
|
191
|
+
[key: string]: unknown;
|
|
192
|
+
}
|
|
193
|
+
interface AndroidDeviceRecord {
|
|
194
|
+
avdName?: string;
|
|
195
|
+
consolePort?: number;
|
|
196
|
+
serial?: string;
|
|
197
|
+
kind?: string;
|
|
198
|
+
deviceName?: string | null;
|
|
199
|
+
owned?: boolean;
|
|
200
|
+
setupIncomplete?: boolean;
|
|
201
|
+
bootPending?: boolean;
|
|
202
|
+
[key: string]: unknown;
|
|
203
|
+
}
|
|
204
|
+
type DeviceRecord = IosDeviceRecord | AndroidDeviceRecord;
|
|
205
|
+
interface PlatformRecords {
|
|
206
|
+
ios?: IosDeviceRecord;
|
|
207
|
+
android?: AndroidDeviceRecord;
|
|
208
|
+
[platform: string]: DeviceRecord | undefined;
|
|
209
|
+
}
|
|
210
|
+
interface ProjectRecord {
|
|
211
|
+
ports?: Record<string, number>;
|
|
212
|
+
metroPort?: number | null;
|
|
213
|
+
platforms?: PlatformRecords;
|
|
214
|
+
deviceSlots?: Record<string, PlatformRecords>;
|
|
215
|
+
supervisor?: SupervisorRecord;
|
|
216
|
+
settings?: SettingsObject;
|
|
217
|
+
worktreeRoot?: boolean;
|
|
218
|
+
worktreeBranch?: string;
|
|
219
|
+
worktreeBranchOwned?: boolean;
|
|
220
|
+
worktreeMainRoot?: string;
|
|
221
|
+
worktreeRemovalComplete?: boolean;
|
|
222
|
+
worktreePendingBranchSha?: string;
|
|
223
|
+
label?: string;
|
|
224
|
+
bundleId?: string;
|
|
225
|
+
androidPackage?: string;
|
|
226
|
+
isExpo?: boolean;
|
|
227
|
+
lastBuild?: Record<string, unknown>;
|
|
228
|
+
doctorRuns?: Partial<Record<"ios" | "android", DoctorRunRecord>>;
|
|
229
|
+
[key: string]: unknown;
|
|
230
|
+
}
|
|
231
|
+
interface DoctorRunRecord {
|
|
232
|
+
at: string;
|
|
233
|
+
version: string;
|
|
234
|
+
}
|
|
235
|
+
interface RepoRecord {
|
|
236
|
+
settings?: SettingsObject;
|
|
237
|
+
[key: string]: unknown;
|
|
238
|
+
}
|
|
239
|
+
interface ConcurrencyLimits {
|
|
240
|
+
maxBuilds: number;
|
|
241
|
+
maxDevices: number;
|
|
242
|
+
}
|
|
243
|
+
interface StimConfig {
|
|
244
|
+
version?: number;
|
|
245
|
+
projects: Record<string, ProjectRecord>;
|
|
246
|
+
repos: Record<string, RepoRecord>;
|
|
247
|
+
tempDir?: unknown;
|
|
248
|
+
iosSimulatorApp?: unknown;
|
|
249
|
+
androidEmulatorApp?: unknown;
|
|
250
|
+
optimizations?: unknown;
|
|
251
|
+
concurrency?: {
|
|
252
|
+
maxBuilds?: unknown;
|
|
253
|
+
maxDevices?: unknown;
|
|
254
|
+
};
|
|
255
|
+
pool?: {
|
|
256
|
+
iosParkedMax?: unknown;
|
|
257
|
+
androidParkedMax?: unknown;
|
|
258
|
+
};
|
|
259
|
+
parked?: {
|
|
260
|
+
ios?: unknown;
|
|
261
|
+
android?: unknown;
|
|
262
|
+
};
|
|
263
|
+
caches?: {
|
|
264
|
+
buildCache?: unknown;
|
|
265
|
+
metroCache?: unknown;
|
|
266
|
+
};
|
|
267
|
+
hosting?: {
|
|
268
|
+
machines?: unknown;
|
|
269
|
+
agentDriver?: unknown;
|
|
270
|
+
};
|
|
271
|
+
server?: {
|
|
272
|
+
acceptClientBuilds?: unknown;
|
|
273
|
+
};
|
|
274
|
+
offload?: {
|
|
275
|
+
machine?: unknown;
|
|
276
|
+
machines?: unknown;
|
|
277
|
+
mode?: unknown;
|
|
278
|
+
workerRoot?: unknown;
|
|
279
|
+
maxLoadPerCore?: unknown;
|
|
280
|
+
gradleDaemonIdleMinutes?: unknown;
|
|
281
|
+
};
|
|
282
|
+
[key: string]: unknown;
|
|
283
|
+
}
|
|
284
|
+
type Config = StimConfig;
|
|
285
|
+
//#endregion
|
|
286
|
+
//#region state/config.d.ts
|
|
287
|
+
declare function withConfigLock<T>(fn: () => T): T;
|
|
288
|
+
declare function configCorruptRepair(path?: string): string;
|
|
289
|
+
/** The build worker root: `offload.workerRoot` when it is absolute, else `$STIM_HOME/build-worker`. */
|
|
290
|
+
declare function buildWorkerRoot(config?: Config | null): string;
|
|
291
|
+
declare function loadConfig(): Config | null;
|
|
292
|
+
declare function getProject(projectPath: string): ProjectRecord | null;
|
|
293
|
+
declare function getConcurrencyLimits({ env }?: {
|
|
294
|
+
env?: NodeJS.ProcessEnv;
|
|
295
|
+
}): ConcurrencyLimits;
|
|
296
|
+
declare function getProjectSettings(projectPath: string): Record<string, unknown>;
|
|
297
|
+
declare function getProjectSetting(projectPath: string, dottedKey: string): unknown;
|
|
298
|
+
declare function getRepoSettings(gitCommonDir: string): Record<string, unknown>;
|
|
299
|
+
declare function isPathPrefix(prefix: string, path: string): boolean;
|
|
300
|
+
declare function findEnclosingWorktreeRoot(projectPath: string): string | null;
|
|
301
|
+
declare function allMetroPorts(): number[];
|
|
302
|
+
declare function findProjectByMetroPort(port: number): string | null;
|
|
303
|
+
//#endregion
|
|
304
|
+
//#region state/json-file.d.ts
|
|
305
|
+
/**
|
|
306
|
+
* Runs `fn` with each state file read from disk at most once: inside it, including after an `await`, `readStateFile`
|
|
307
|
+
* returns the text of the first read of that path, and a path found missing stays missing. Callers still parse every time, so no two
|
|
308
|
+
* share a mutable object. Only for computations that write none of the files they read.
|
|
309
|
+
*/
|
|
310
|
+
declare function withStateReadCache<T>(fn: () => T): T;
|
|
311
|
+
declare function readStateFile(path: string): string;
|
|
312
|
+
declare function readJsonFile(path: string): unknown;
|
|
313
|
+
declare function isJsonObject(value: unknown): value is Record<string, unknown>;
|
|
314
|
+
declare function readJsonObject(path: string): Record<string, unknown> | null;
|
|
315
|
+
//#endregion
|
|
316
|
+
//#region state/ledgers.d.ts
|
|
317
|
+
type CreatedDevicePlatform = "ios" | "android" | "web";
|
|
318
|
+
/** `web` lists the absolute paths of browser profile directories Stim created. */
|
|
319
|
+
interface CreatedDevices {
|
|
320
|
+
ios: ReadonlySet<string>;
|
|
321
|
+
android: ReadonlySet<string>;
|
|
322
|
+
web: ReadonlySet<string>;
|
|
323
|
+
}
|
|
324
|
+
declare function readCreatedDevices(): CreatedDevices;
|
|
325
|
+
interface EasSessionClaim {
|
|
326
|
+
sessionId: string;
|
|
327
|
+
name: string;
|
|
328
|
+
platform: "ios" | "android";
|
|
329
|
+
workspaceRoot: string;
|
|
330
|
+
workspaceHome: string;
|
|
331
|
+
stateFile: string;
|
|
332
|
+
}
|
|
333
|
+
interface EasSessionLedgerRead {
|
|
334
|
+
claims: Map<string, EasSessionClaim>;
|
|
335
|
+
notice: string | null;
|
|
336
|
+
safe: boolean;
|
|
337
|
+
}
|
|
338
|
+
/** Returns the claim normalized to canonical paths, or null when it is not a valid claim for `id`. */
|
|
339
|
+
declare function validEasSessionClaim(id: string, value: unknown): EasSessionClaim | null;
|
|
340
|
+
declare function readEasSessionLedger(root?: string): EasSessionLedgerRead;
|
|
341
|
+
//#endregion
|
|
342
|
+
//#region state/error-entries.d.ts
|
|
343
|
+
/**
|
|
344
|
+
* The number of rows a log list shows for `records`, an error query's result in log order. Stim Desktop's
|
|
345
|
+
* `LogEntryList` and the phone's `groupRecords` group the same way and replay the same vectors: in Expo's dev
|
|
346
|
+
* server one failed bundle is a `Bundling failed` marker line, the error line and a failed bundle response,
|
|
347
|
+
* which the apps list as one row, and every other record is its own row.
|
|
348
|
+
*/
|
|
349
|
+
declare function countErrorEntries(records: readonly NdjsonRecord[]): number;
|
|
350
|
+
//#endregion
|
|
351
|
+
//#region state/logs-query.d.ts
|
|
352
|
+
interface SinceResult {
|
|
353
|
+
ms?: number;
|
|
354
|
+
error?: string;
|
|
355
|
+
}
|
|
356
|
+
interface GrepResult {
|
|
357
|
+
re?: RegExp;
|
|
358
|
+
error?: string;
|
|
359
|
+
}
|
|
360
|
+
interface MarkerWindow {
|
|
361
|
+
launchTs: number | null;
|
|
362
|
+
bundleTs: number | null;
|
|
363
|
+
pageLoadTs: number | null;
|
|
364
|
+
}
|
|
365
|
+
interface QueryCriteria {
|
|
366
|
+
slot?: string;
|
|
367
|
+
includeAppDeviceErrors?: boolean;
|
|
368
|
+
sources?: string[];
|
|
369
|
+
minLevel?: string;
|
|
370
|
+
grep?: RegExp;
|
|
371
|
+
sinceTs?: number;
|
|
372
|
+
errorsOnly?: boolean;
|
|
373
|
+
markerTs?: number;
|
|
374
|
+
bundleMarkerTs?: number;
|
|
375
|
+
}
|
|
376
|
+
interface TailState {
|
|
377
|
+
offset: number;
|
|
378
|
+
partial: string;
|
|
379
|
+
}
|
|
380
|
+
declare function parseSince(text: unknown): SinceResult;
|
|
381
|
+
declare function compileGrep(pattern: unknown): GrepResult;
|
|
382
|
+
declare const ERROR_SOURCES: string[];
|
|
383
|
+
declare function markerWindow(records: NdjsonRecord[]): MarkerWindow;
|
|
384
|
+
/**
|
|
385
|
+
* The platform a bundle marker speaks for, lowercased: its `platform` field, or the tag @expo/cli prints before
|
|
386
|
+
* "Bundled" ("iOS", "Android", "Web", "RSC(iOS)" as ios, or an environment tag such as "DOM"). Null when unknown.
|
|
387
|
+
*/
|
|
388
|
+
declare function bundleMarkerPlatform(record: NdjsonRecord): string | null;
|
|
389
|
+
declare function recordMatches(record: NdjsonRecord | null | undefined, criteria?: QueryCriteria): boolean;
|
|
390
|
+
declare function buildCriteria({ slot, sources, minLevel, since, grep, errorsOnly, markerTs, bundleMarkerTs, now }?: {
|
|
391
|
+
slot?: string;
|
|
392
|
+
sources?: string[];
|
|
393
|
+
minLevel?: string;
|
|
394
|
+
since?: string | null;
|
|
395
|
+
grep?: string | RegExp | null;
|
|
396
|
+
errorsOnly?: boolean;
|
|
397
|
+
markerTs?: number;
|
|
398
|
+
bundleMarkerTs?: number;
|
|
399
|
+
now?: number;
|
|
400
|
+
}): QueryCriteria;
|
|
401
|
+
declare function logFiles(dir: string): string[];
|
|
402
|
+
declare function fileSizes(dir: string): Record<string, number>;
|
|
403
|
+
declare function readLogRecords(dir: string, include?: (name: string) => boolean): NdjsonRecord[];
|
|
404
|
+
declare const NATIVE_CRASH_LOG_PREFIX = "native-crash-";
|
|
405
|
+
/** Reads the CLI timeline with retained native crash records after other records at the same timestamp. */
|
|
406
|
+
declare function readLogTimeline(dir: string, records?: NdjsonRecord[]): NdjsonRecord[];
|
|
407
|
+
type ExpoContextTarget = "msg" | "field";
|
|
408
|
+
/**
|
|
409
|
+
* Adds the code frame and stack lines Expo printed after each Expo error record, either joined into
|
|
410
|
+
* `msg` or as a `context` string array.
|
|
411
|
+
*/
|
|
412
|
+
declare function attachExpoErrorContext(all: NdjsonRecord[], matched: NdjsonRecord[], into?: ExpoContextTarget): NdjsonRecord[];
|
|
413
|
+
declare function queryLogs({ slot, dir, records, sources, minLevel, since, grep, tail, errorsOnly, errorContext, now }?: {
|
|
414
|
+
slot?: string;
|
|
415
|
+
dir?: string;
|
|
416
|
+
records?: NdjsonRecord[];
|
|
417
|
+
sources?: string[];
|
|
418
|
+
minLevel?: string;
|
|
419
|
+
since?: string;
|
|
420
|
+
grep?: string | RegExp;
|
|
421
|
+
tail?: number;
|
|
422
|
+
errorsOnly?: boolean;
|
|
423
|
+
errorContext?: boolean;
|
|
424
|
+
now?: number;
|
|
425
|
+
}): NdjsonRecord[];
|
|
426
|
+
/** Queries the JSON timeline, including Expo context fields on errors as `stim logs --json` does. */
|
|
427
|
+
declare function queryJsonLogs(options?: Parameters<typeof queryLogs>[0]): NdjsonRecord[];
|
|
428
|
+
declare function tailRead(prev: TailState | null | undefined, size: number): {
|
|
429
|
+
start: number;
|
|
430
|
+
prev: TailState;
|
|
431
|
+
};
|
|
432
|
+
declare function advanceTail(prev: TailState | null | undefined, chunk: string | null | undefined, size: number): {
|
|
433
|
+
state: TailState;
|
|
434
|
+
records: NdjsonRecord[];
|
|
435
|
+
};
|
|
436
|
+
declare function followLogs({ dir, onRecord, criteria, intervalMs, offsets, errorContext }: {
|
|
437
|
+
dir: string;
|
|
438
|
+
onRecord: (record: NdjsonRecord) => void;
|
|
439
|
+
criteria?: QueryCriteria;
|
|
440
|
+
intervalMs?: number;
|
|
441
|
+
offsets?: Record<string, number> | null;
|
|
442
|
+
/** Holds each Expo error until a poll adds no more of its code frame or stack lines, then attaches them. */
|
|
443
|
+
errorContext?: ExpoContextTarget;
|
|
444
|
+
}): () => void;
|
|
445
|
+
declare function sortByTs(records: NdjsonRecord[]): NdjsonRecord[];
|
|
446
|
+
//#endregion
|
|
447
|
+
//#region state/paths.d.ts
|
|
448
|
+
declare function getConfigPath(): string;
|
|
449
|
+
declare function configLockPath(): string;
|
|
450
|
+
declare function workspaceMetadataFile(projectRoot: string): string;
|
|
451
|
+
declare function workspaceAgentDeviceDir(projectRoot: string): string;
|
|
452
|
+
declare function workspaceLogsDir(projectRoot: string): string;
|
|
453
|
+
/** Device screen footage stim-server records for the workspace, one directory per platform and slot. */
|
|
454
|
+
declare function workspaceRecordingsDir(projectRoot: string): string;
|
|
455
|
+
declare function workspaceLogErrorIndex(projectRoot: string): string;
|
|
456
|
+
declare function workspaceDerivedData(projectRoot: string): string;
|
|
457
|
+
declare function workspaceGradleBuild(projectRoot: string): string;
|
|
458
|
+
declare function workspaceBuildDetailFile(projectRoot: string): string;
|
|
459
|
+
/** The agent sessions that stopped running in the workspace in the last `ENDED_AGENT_RETENTION_MS`. */
|
|
460
|
+
declare function workspaceEndedAgentsFile(projectRoot: string): string;
|
|
461
|
+
declare function workspaceEndedAgentsLock(projectRoot: string): string;
|
|
462
|
+
declare function supervisorPidFile(projectRoot: string): string;
|
|
463
|
+
declare function workspaceStateFile(projectRoot: string): string;
|
|
464
|
+
declare function workspaceStateLock(projectRoot: string): string;
|
|
465
|
+
declare function supervisorLogFile(projectRoot: string): string;
|
|
466
|
+
declare function emulatorLogFile(projectRoot: string): string;
|
|
467
|
+
declare function sharedCompilationCache(): string;
|
|
468
|
+
declare function sharedCcache(): string;
|
|
469
|
+
declare function sharedGradle(): string;
|
|
470
|
+
declare function sharedPods(): string;
|
|
471
|
+
declare function createdDevicesFile(): string;
|
|
472
|
+
declare function gitMergeCacheDir(): string;
|
|
473
|
+
declare function pullRequestCacheDir(): string;
|
|
474
|
+
declare function agentSessionsCacheFile(): string;
|
|
475
|
+
declare function diskUsageCacheDir(): string;
|
|
476
|
+
/** The build machines this Mac paired with, each with its pinned tailnet node and device token. */
|
|
477
|
+
declare function buildMachinesFile(): string;
|
|
478
|
+
declare function buildMachinesLock(): string;
|
|
479
|
+
/** The hosting machines this Mac asked for access, separate from build credentials. */
|
|
480
|
+
declare function deviceHostMachinesFile(): string;
|
|
481
|
+
declare function deviceHostMachinesLock(): string;
|
|
482
|
+
declare function deviceHostMachinesClaims(): string;
|
|
483
|
+
declare function createdDevicesLock(): string;
|
|
484
|
+
/** The EAS session ledger lives under the real home directory, never under STIM_HOME. */
|
|
485
|
+
declare function easMachineStateRoot(): string;
|
|
486
|
+
declare function easSessionLedgerFile(root?: string): string;
|
|
487
|
+
declare function easSessionLedgerLock(root?: string): string;
|
|
488
|
+
/** Where stim-server records, one file per server process, the devices whose frames a client subscribes to. */
|
|
489
|
+
declare function deviceViewersDir(): string;
|
|
490
|
+
declare function statsFile(): string;
|
|
491
|
+
declare function maintenanceDir(): string;
|
|
492
|
+
declare function maintenanceStateFile(): string;
|
|
493
|
+
declare function maintenanceAttemptFile(): string;
|
|
494
|
+
declare function maintenanceNdjsonFile(): string;
|
|
495
|
+
declare function maintenanceChildLogFile(): string;
|
|
496
|
+
declare function maintenanceRunClaims(): string;
|
|
497
|
+
declare function archiveRoot(): string;
|
|
498
|
+
declare function archiveDir(id: string): string;
|
|
499
|
+
declare function archiveLock(): string;
|
|
500
|
+
declare function serverSetupDir(): string;
|
|
501
|
+
declare function setupJournalFile(hash: string): string | null;
|
|
502
|
+
//#endregion
|
|
503
|
+
//#region state/recordings.d.ts
|
|
504
|
+
/** The footage stim-server keeps per device: the last 15 minutes recorded, however long ago. */
|
|
505
|
+
declare const RECORDING_FOOTAGE_MS: number;
|
|
506
|
+
/** The recordings of every workspace of one Stim home together; past it the oldest footage goes first. */
|
|
507
|
+
declare const RECORDING_CAP_BYTES: number;
|
|
508
|
+
/** The platforms stim-server records: owned simulators and emulators, and the Stim-owned Chrome page. */
|
|
509
|
+
declare const RECORDING_PLATFORMS: readonly ["ios", "android", "web"];
|
|
510
|
+
type RecordingPlatform = (typeof RECORDING_PLATFORMS)[number];
|
|
511
|
+
/**
|
|
512
|
+
* One file of H.264 footage. A closed segment is named `<start>-<end>.seg`, in epoch milliseconds of its first and
|
|
513
|
+
* last access unit; the segment being written is `<start>.part`, and its end is its modification time.
|
|
514
|
+
*/
|
|
515
|
+
interface RecordedSegment {
|
|
516
|
+
file: string;
|
|
517
|
+
start: number;
|
|
518
|
+
end: number;
|
|
519
|
+
bytes: number;
|
|
520
|
+
open: boolean;
|
|
521
|
+
}
|
|
522
|
+
interface RecordedDevice {
|
|
523
|
+
platform: RecordingPlatform;
|
|
524
|
+
slot: string;
|
|
525
|
+
dir: string;
|
|
526
|
+
segments: RecordedSegment[];
|
|
527
|
+
}
|
|
528
|
+
/** The directory under a workspace's recordings that holds one device slot's footage. */
|
|
529
|
+
declare function recordingDeviceName(platform: RecordingPlatform, slot: string): string;
|
|
530
|
+
/** Segment names hold whole milliseconds: the start rounded down and the end rounded up. */
|
|
531
|
+
declare function closedSegmentName(start: number, end: number): string;
|
|
532
|
+
declare function openSegmentName(start: number): string;
|
|
533
|
+
/** The segments in one device directory, oldest first. Files that are not segments are left out; `closedOnly` excludes files still being written. */
|
|
534
|
+
declare function listSegments(dir: string, closedOnly?: boolean): RecordedSegment[];
|
|
535
|
+
/** Every device slot recorded under a workspace's recordings directory. */
|
|
536
|
+
declare function listRecordedDevices(recordingsDir: string): RecordedDevice[];
|
|
537
|
+
declare function recordedBytes(devices: readonly RecordedDevice[]): number;
|
|
538
|
+
/**
|
|
539
|
+
* The oldest closed segments to delete so that one device keeps at most `footageMs` of footage. Time between
|
|
540
|
+
* segments, while nothing was recorded, does not count. The open segment is never chosen.
|
|
541
|
+
*/
|
|
542
|
+
declare function footageDrops(segments: readonly RecordedSegment[], footageMs: number): RecordedSegment[];
|
|
543
|
+
/** The oldest closed segments across all devices to delete so that together they hold at most `capBytes`. */
|
|
544
|
+
declare function capDrops(devices: readonly RecordedDevice[], capBytes: number): RecordedSegment[];
|
|
545
|
+
/**
|
|
546
|
+
* Whether stim-server records a workspace's devices: `STIM_RECORDING`, then `recording.enabled` in the workspace,
|
|
547
|
+
* repo and machine layers, in that order, and true by default.
|
|
548
|
+
*/
|
|
549
|
+
declare function recordingEnabled(env: NodeJS.ProcessEnv, layers: readonly unknown[]): boolean;
|
|
550
|
+
//#endregion
|
|
551
|
+
//#region state/settings-registry.d.ts
|
|
552
|
+
declare const ANDROID_COMPILER_CACHE_CHOICES: readonly ["auto", "ccache", "cas", "none"];
|
|
553
|
+
declare const ANDROID_PCH_CHOICES: readonly ["auto", "on", "off"];
|
|
554
|
+
type TunnelMode = "auto" | "off" | "expo" | "cloudflared" | "ngrok" | "tailscale";
|
|
555
|
+
declare const TUNNEL_MODES: readonly TunnelMode[];
|
|
556
|
+
type RemoteDeviceBackend = "proxy" | "eas";
|
|
557
|
+
type SettingScope = "machine" | "workspace" | "repo" | "committed";
|
|
558
|
+
declare const SETTING_SCOPES: readonly SettingScope[];
|
|
559
|
+
type SettingType = {
|
|
560
|
+
kind: "string";
|
|
561
|
+
pattern?: string;
|
|
562
|
+
patternHelp?: string;
|
|
563
|
+
} | {
|
|
564
|
+
kind: "path";
|
|
565
|
+
absolute?: boolean;
|
|
566
|
+
relative?: boolean;
|
|
567
|
+
} | {
|
|
568
|
+
kind: "strings";
|
|
569
|
+
} | {
|
|
570
|
+
kind: "number";
|
|
571
|
+
integer?: boolean;
|
|
572
|
+
minimum?: number;
|
|
573
|
+
exclusiveMinimum?: number;
|
|
574
|
+
maximum?: number;
|
|
575
|
+
} | {
|
|
576
|
+
kind: "boolean";
|
|
577
|
+
} | {
|
|
578
|
+
kind: "choice";
|
|
579
|
+
choices: readonly string[];
|
|
580
|
+
} | {
|
|
581
|
+
kind: "object";
|
|
582
|
+
} | {
|
|
583
|
+
kind: "bundle-url";
|
|
584
|
+
};
|
|
585
|
+
/**
|
|
586
|
+
* One setting Stim reads. `scopes` are the layers the setting may be written to;
|
|
587
|
+
* `committedAt: 'repository'` reads the committed layer from the repository root's
|
|
588
|
+
* `.stim.json` instead of the app's. A `sensitive` value is never printed and is
|
|
589
|
+
* written to `.stim.json` only as an `env:` or `file:` reference. `scopedHomeValue`
|
|
590
|
+
* replaces every layer and the default while STIM_HOME is set and `env` is not.
|
|
591
|
+
* `ciValue` replaces every layer and the default while CI is set and `env` is not.
|
|
592
|
+
* `desktopDefault` replaces `default` on macOS while Stim Desktop is installed.
|
|
593
|
+
*/
|
|
594
|
+
interface SettingDefinition {
|
|
595
|
+
key: string;
|
|
596
|
+
type: SettingType;
|
|
597
|
+
scopes: readonly SettingScope[];
|
|
598
|
+
description: string;
|
|
599
|
+
default?: string | number | boolean;
|
|
600
|
+
env?: string;
|
|
601
|
+
sensitive?: boolean;
|
|
602
|
+
committedAt?: "repository";
|
|
603
|
+
scopedHomeValue?: string | number | boolean;
|
|
604
|
+
ciValue?: string | number | boolean;
|
|
605
|
+
desktopDefault?: string;
|
|
606
|
+
}
|
|
607
|
+
interface SettingEntry {
|
|
608
|
+
key: string;
|
|
609
|
+
value: unknown;
|
|
610
|
+
origin: SettingScope | "env" | "default" | null;
|
|
611
|
+
layers: Partial<Record<SettingScope, unknown>>;
|
|
612
|
+
env?: {
|
|
613
|
+
name: string;
|
|
614
|
+
value: string;
|
|
615
|
+
};
|
|
616
|
+
sensitive?: true;
|
|
617
|
+
defaultReason?: string;
|
|
618
|
+
}
|
|
619
|
+
/** The payload `stim settings --json` prints. */
|
|
620
|
+
interface SettingsPayload {
|
|
621
|
+
project: string | null;
|
|
622
|
+
files: Partial<Record<SettingScope, string>>;
|
|
623
|
+
settings: SettingEntry[];
|
|
624
|
+
unknown: Array<{
|
|
625
|
+
key: string;
|
|
626
|
+
scope: SettingScope;
|
|
627
|
+
file: string;
|
|
628
|
+
value: unknown;
|
|
629
|
+
}>;
|
|
630
|
+
}
|
|
631
|
+
declare const REMOTE_DEVICE_BACKENDS: readonly RemoteDeviceBackend[];
|
|
632
|
+
declare const IOS_SIMULATOR_APPS: readonly ["xcode", "siniulator", "stim-desktop"];
|
|
633
|
+
declare const ANDROID_EMULATOR_APPS: readonly ["emulator", "stim-desktop"];
|
|
634
|
+
declare const OFFLOAD_MODES: readonly ["auto", "force", "off"];
|
|
635
|
+
type OffloadMode = (typeof OFFLOAD_MODES)[number];
|
|
636
|
+
declare const WEB_VIEWPORTS: readonly ["desktop", "phone"];
|
|
637
|
+
type WebViewport = (typeof WEB_VIEWPORTS)[number];
|
|
638
|
+
declare const SETTINGS: readonly SettingDefinition[];
|
|
639
|
+
declare function settingDefinition(key: string): SettingDefinition | null;
|
|
640
|
+
declare function isLayeredSetting(setting: SettingDefinition): boolean;
|
|
641
|
+
declare const SETTING_GROUPS: readonly string[];
|
|
642
|
+
declare function expectedShape(type: SettingType): string;
|
|
643
|
+
declare function acceptsShape(setting: SettingDefinition, value: unknown): boolean;
|
|
644
|
+
declare function settingValueError(setting: SettingDefinition, value: unknown): string | null;
|
|
645
|
+
declare function isSensitiveReference(value: unknown): boolean;
|
|
646
|
+
/**
|
|
647
|
+
* Coerces raw text (a CLI argument or an environment variable) through a setting's
|
|
648
|
+
* registry type, the same way for both sources. Types whose values are not written
|
|
649
|
+
* as bare text (boolean, number, strings, object) are read as JSON; a value that
|
|
650
|
+
* fails to parse is left as the original string so `settingValueError` reports it. A boolean also reads `1` and `0`.
|
|
651
|
+
*/
|
|
652
|
+
declare function coerceSettingText(setting: SettingDefinition, raw: string): unknown;
|
|
653
|
+
//#endregion
|
|
654
|
+
//#region state/settings-schema.d.ts
|
|
655
|
+
declare const SETTINGS_SCHEMA_FILE = "settings.schema.json";
|
|
656
|
+
declare const SETTINGS_SCHEMA_URL: string;
|
|
657
|
+
type JsonSchema = Record<string, unknown>;
|
|
658
|
+
/**
|
|
659
|
+
* The published settings schema. The root describes a committed `.stim.json`;
|
|
660
|
+
* `$defs.machine` describes the settings keys of `$STIM_HOME/config.json`.
|
|
661
|
+
* Every leaf carries `x-stim` with its dotted key, kind, writable scopes,
|
|
662
|
+
* environment override, and sensitivity.
|
|
663
|
+
*/
|
|
664
|
+
declare function settingsJsonSchema(): JsonSchema;
|
|
665
|
+
//#endregion
|
|
666
|
+
//#region state/hosted-app.d.ts
|
|
667
|
+
interface HostedAppFile {
|
|
668
|
+
path: string;
|
|
669
|
+
kind: "file" | "exec" | "link";
|
|
670
|
+
size: number;
|
|
671
|
+
sha256: string;
|
|
672
|
+
}
|
|
673
|
+
interface HostedAppOffer {
|
|
674
|
+
session: string;
|
|
675
|
+
attempt: string;
|
|
676
|
+
bundleId: string;
|
|
677
|
+
mode: "development" | "release";
|
|
678
|
+
devClientScheme?: string;
|
|
679
|
+
arguments?: string[];
|
|
680
|
+
manifest: {
|
|
681
|
+
sha256: string;
|
|
682
|
+
size: number;
|
|
683
|
+
};
|
|
684
|
+
}
|
|
685
|
+
interface HostedAppDelivery extends Omit<HostedAppOffer, "manifest"> {
|
|
686
|
+
state: "receiving" | "installing" | "installed" | "unknown";
|
|
687
|
+
launched: true | "unverified" | null;
|
|
688
|
+
notice?: string;
|
|
689
|
+
}
|
|
690
|
+
interface HostedAppRecord extends HostedAppDelivery {
|
|
691
|
+
manifest: HostedAppOffer["manifest"];
|
|
692
|
+
files: HostedAppFile[];
|
|
693
|
+
}
|
|
694
|
+
declare const HOSTED_APP_CHUNK_BYTES: number;
|
|
695
|
+
declare function hostedAppAttempt(value: unknown): value is string;
|
|
696
|
+
declare function hostedAppArea(session: string, attempt: string, workerHome?: string): string;
|
|
697
|
+
declare function hostedAppBlobs(session: string, workerHome?: string): string;
|
|
698
|
+
/** Transfers cached verification after a rename, only for the same inode, size, mtime and digest. */
|
|
699
|
+
declare function rememberHostedAppBlobRename(from: string, to: string, file: {
|
|
700
|
+
size: number;
|
|
701
|
+
sha256: string;
|
|
702
|
+
}): void;
|
|
703
|
+
/** Checks regular blob bytes, including their size, before content-addressed reuse. */
|
|
704
|
+
declare function validHostedAppBlob(path: string, file: {
|
|
705
|
+
size: number;
|
|
706
|
+
sha256: string;
|
|
707
|
+
}): boolean;
|
|
708
|
+
/** At most 32 plain arguments of 1024 characters (8192 in total), with no NUL, CR or LF. */
|
|
709
|
+
declare function validHostedAppArguments(value: unknown): value is string[];
|
|
710
|
+
declare function parseHostedAppOffer(value: unknown): HostedAppOffer | null;
|
|
711
|
+
/** Relative normalized paths, with no file or link as another entry's ancestor. */
|
|
712
|
+
declare function parseHostedAppManifest(value: unknown): HostedAppFile[] | null;
|
|
713
|
+
/** Reads a server-written receipt; malformed or missing established state remains unresolved. */
|
|
714
|
+
declare function readHostedAppMetadata(session: string, attempt: string, workerHome?: string): Omit<HostedAppRecord, "files">;
|
|
715
|
+
declare function readHostedApp(session: string, attempt: string, workerHome?: string): HostedAppRecord;
|
|
716
|
+
//#endregion
|
|
717
|
+
//#region state/hosted-macos.d.ts
|
|
718
|
+
/** App slots one host offers; a slot names the host-assigned bundle id `<bundleId>.hosted<slot>`. */
|
|
719
|
+
declare const HOSTED_MACOS_APP_SLOTS = 64;
|
|
720
|
+
declare const HOSTED_AGENT_DRIVERS: readonly ["none", "agent-device"];
|
|
721
|
+
type HostedAgentDriverName = (typeof HOSTED_AGENT_DRIVERS)[number];
|
|
722
|
+
/** What a host reports in a macOS offer: no simulator is created, so the choice is the host itself. */
|
|
723
|
+
interface HostedMacosChoice {
|
|
724
|
+
architecture: "arm64" | "x86_64";
|
|
725
|
+
macosVersion: string;
|
|
726
|
+
}
|
|
727
|
+
/** A ready hosted macOS session's identity: the host it runs on and the app slot reserved for it. */
|
|
728
|
+
interface HostedMacosDevice extends HostedMacosChoice {
|
|
729
|
+
appSlot: number;
|
|
730
|
+
}
|
|
731
|
+
/**
|
|
732
|
+
* The agent-device lease owner scope a client names on every request. `deviceKey` is `<bundleId>@<pid>`
|
|
733
|
+
* for a macOS app, or `ios:mobile:<udid>` with `backend: ios-instance` for a hosted simulator.
|
|
734
|
+
*/
|
|
735
|
+
interface HostedAgentLease {
|
|
736
|
+
tenant: string;
|
|
737
|
+
runId: string;
|
|
738
|
+
clientId: string;
|
|
739
|
+
deviceKey: string;
|
|
740
|
+
backend?: "ios-instance";
|
|
741
|
+
}
|
|
742
|
+
/**
|
|
743
|
+
* Agent control the host grants a client for one installed hosted app, sent only over that client's approved
|
|
744
|
+
* device-host connection and never journaled. `none` means the host's `hosting.agentDriver` starts no driver.
|
|
745
|
+
* `path` is the session's base route on the host, `scope` the driver's handle that limits it to this one app,
|
|
746
|
+
* and `lease` the scope that pins the driver's lease allocation.
|
|
747
|
+
*/
|
|
748
|
+
type HostedAgentGrant = {
|
|
749
|
+
driver: "none";
|
|
750
|
+
} | {
|
|
751
|
+
driver: Exclude<HostedAgentDriverName, "none">;
|
|
752
|
+
path: string;
|
|
753
|
+
token: string;
|
|
754
|
+
scope: string;
|
|
755
|
+
lease: HostedAgentLease;
|
|
756
|
+
};
|
|
757
|
+
/** `app.launch` and `app.attach` results; a host includes `agent` once the app is installed. */
|
|
758
|
+
type HostedAppLaunch = HostedAppDelivery & {
|
|
759
|
+
agent?: HostedAgentGrant;
|
|
760
|
+
};
|
|
761
|
+
/**
|
|
762
|
+
* Agent control as the client hands it to a coding agent: secrets stay in files Stim writes with mode
|
|
763
|
+
* 0600, and `command` shows how to address the hosted app. Never carries a token inline. `setting` names
|
|
764
|
+
* the hosting Mac's setting that turns a driver on.
|
|
765
|
+
*/
|
|
766
|
+
type HostedAgentAccess = {
|
|
767
|
+
driver: "none";
|
|
768
|
+
setting: "hosting.agentDriver";
|
|
769
|
+
} | {
|
|
770
|
+
driver: "agent-device";
|
|
771
|
+
remoteConfig: string;
|
|
772
|
+
command: string;
|
|
773
|
+
};
|
|
774
|
+
/** Where a workspace's macOS app runs when `stim macos --remote` placed it on another Mac. */
|
|
775
|
+
interface HostedMacosPlacement {
|
|
776
|
+
machine: string;
|
|
777
|
+
session: string;
|
|
778
|
+
appSlot: number;
|
|
779
|
+
appAttempt: string;
|
|
780
|
+
/** The host-assigned id the running app uses, `hostedMacosBundleId(<offered id>, appSlot)`. */
|
|
781
|
+
bundleId: string;
|
|
782
|
+
agent: HostedAgentAccess;
|
|
783
|
+
}
|
|
784
|
+
declare function hostedMacosAppSlot(value: unknown): value is number;
|
|
785
|
+
declare function hostedMacosBundleId(bundleId: string, appSlot: number): string;
|
|
786
|
+
declare function parseHostedMacosChoice(value: unknown): HostedMacosChoice | null;
|
|
787
|
+
declare function parseHostedMacosDevice(value: unknown): HostedMacosDevice | null;
|
|
788
|
+
/** A grant naming a driver this client does not know is not usable; it parses as null. */
|
|
789
|
+
declare function parseHostedAgentGrant(value: unknown): HostedAgentGrant | null;
|
|
790
|
+
declare function parseHostedAgentAccess(value: unknown): HostedAgentAccess | null;
|
|
791
|
+
declare function parseHostedMacosPlacement(value: unknown): HostedMacosPlacement | null;
|
|
792
|
+
//#endregion
|
|
793
|
+
//#region state/device-host.d.ts
|
|
794
|
+
type HostedDevicePlatform = "ios" | "android" | "macos";
|
|
795
|
+
interface HostedIosChoice {
|
|
796
|
+
deviceTypeId: string;
|
|
797
|
+
runtimeId: string;
|
|
798
|
+
deviceType: string;
|
|
799
|
+
runtime: string;
|
|
800
|
+
architecture: "arm64" | "x86_64";
|
|
801
|
+
}
|
|
802
|
+
interface HostedIosDevice extends HostedIosChoice {
|
|
803
|
+
udid: string;
|
|
804
|
+
name: string;
|
|
805
|
+
}
|
|
806
|
+
interface HostedAndroidChoice {
|
|
807
|
+
systemImage: string;
|
|
808
|
+
deviceProfile: string;
|
|
809
|
+
architecture: "arm64-v8a" | "x86_64";
|
|
810
|
+
}
|
|
811
|
+
interface HostedAndroidDevice extends HostedAndroidChoice {
|
|
812
|
+
avdName: string;
|
|
813
|
+
serial: string;
|
|
814
|
+
consolePort: number;
|
|
815
|
+
}
|
|
816
|
+
type HostedDevice = HostedIosDevice | HostedAndroidDevice | HostedMacosDevice;
|
|
817
|
+
interface HostedDeviceSelectors {
|
|
818
|
+
deviceType?: string;
|
|
819
|
+
runtime?: string;
|
|
820
|
+
systemImage?: string;
|
|
821
|
+
deviceProfile?: string;
|
|
822
|
+
}
|
|
823
|
+
interface HostedDeviceOfferRequest extends HostedDeviceSelectors {
|
|
824
|
+
platform: HostedDevicePlatform;
|
|
825
|
+
}
|
|
826
|
+
type HostedNativeOffer = {
|
|
827
|
+
resources: {
|
|
828
|
+
cpus: number;
|
|
829
|
+
/** Five-minute system load divided by available CPU count. */
|
|
830
|
+
loadPerCore: number;
|
|
831
|
+
memoryFreeBytes: number;
|
|
832
|
+
memoryPressure: "normal" | "warning" | "critical" | null;
|
|
833
|
+
/** Available bytes on the Stim home volume, not necessarily the Android AVD volume. */
|
|
834
|
+
workerDiskFreeBytes: number | null;
|
|
835
|
+
};
|
|
836
|
+
declined: string | null;
|
|
837
|
+
} & ({
|
|
838
|
+
platform: "ios";
|
|
839
|
+
choice: HostedIosChoice | null;
|
|
840
|
+
} | {
|
|
841
|
+
platform: "android";
|
|
842
|
+
choice: HostedAndroidChoice | null;
|
|
843
|
+
} | {
|
|
844
|
+
platform: "macos";
|
|
845
|
+
choice: HostedMacosChoice | null;
|
|
846
|
+
});
|
|
847
|
+
type HostedDeviceOffer = HostedNativeOffer & {
|
|
848
|
+
capacity: {
|
|
849
|
+
running: number;
|
|
850
|
+
max: number;
|
|
851
|
+
available: number | null;
|
|
852
|
+
};
|
|
853
|
+
};
|
|
854
|
+
interface HostedDeviceRequest extends HostedDeviceOfferRequest {
|
|
855
|
+
workspace: string;
|
|
856
|
+
slot: string;
|
|
857
|
+
attempt: string;
|
|
858
|
+
}
|
|
859
|
+
type HostedDevicePhase = "preparing" | "ready" | "stopping" | "stopped" | "unknown";
|
|
860
|
+
interface HostedDeviceSession extends HostedDeviceRequest {
|
|
861
|
+
id: string;
|
|
862
|
+
client: string;
|
|
863
|
+
state: HostedDevicePhase;
|
|
864
|
+
device: HostedDevice | null;
|
|
865
|
+
consolePort?: number;
|
|
866
|
+
appSlot?: number;
|
|
867
|
+
createdAt: string;
|
|
868
|
+
notice?: string;
|
|
869
|
+
appAttempt?: string;
|
|
870
|
+
metroPort?: number;
|
|
871
|
+
}
|
|
872
|
+
declare function deviceHostRoot(): string;
|
|
873
|
+
declare function deviceHostArea(id: string): string;
|
|
874
|
+
declare function parseHostedChoice(value: unknown): HostedIosChoice | null;
|
|
875
|
+
declare function parseHostedDevice(value: unknown): HostedIosDevice | null;
|
|
876
|
+
declare function parseHostedAndroidDevice(value: unknown): HostedAndroidDevice | null;
|
|
877
|
+
/** Android Emulator -help-port defines the supported even console ports as 5554 through 5584. */
|
|
878
|
+
declare function hostedConsolePort(value: unknown): value is number;
|
|
879
|
+
declare function parseHostedPlatformDevice(value: unknown, platform: HostedDevicePlatform): HostedDevice | null;
|
|
880
|
+
declare function hostedDeviceId(device: HostedDevice): string;
|
|
881
|
+
declare function parseHostedRequest(value: unknown): HostedDeviceRequest | null;
|
|
882
|
+
declare function parseHostedOfferRequest(value: unknown): HostedDeviceOfferRequest | null;
|
|
883
|
+
declare function parseHostedNativeOffer(value: unknown): HostedNativeOffer | null;
|
|
884
|
+
/** A missing established journal or malformed record is a refusal, never an empty reservation set. */
|
|
885
|
+
declare function readHostedSessions(): HostedDeviceSession[];
|
|
886
|
+
/** The private worker's exact device record; an absent record is unresolved after creation started. */
|
|
887
|
+
declare function readHostedDevice(home: string): HostedIosDevice;
|
|
888
|
+
declare function readHostedDevice(home: string, platform: "android"): HostedAndroidDevice;
|
|
889
|
+
declare function readHostedDevice(home: string, platform: "macos"): HostedMacosDevice;
|
|
890
|
+
declare function readHostedDevice(home: string, platform: HostedDevicePlatform): HostedDevice;
|
|
891
|
+
declare function readHostedDeviceLedger(home: string, options?: {
|
|
892
|
+
required?: boolean;
|
|
893
|
+
}): {
|
|
894
|
+
ios: string[];
|
|
895
|
+
android: string[];
|
|
896
|
+
web: string[];
|
|
897
|
+
} | null;
|
|
898
|
+
/** Hosted sessions use isolated homes: only one exact device of their platform may appear in this ledger. */
|
|
899
|
+
declare function assertHostedDeviceLedger(home: string, id: string, platform?: HostedDevicePlatform, options?: {
|
|
900
|
+
allowEmpty?: boolean;
|
|
901
|
+
}): "listed" | "empty";
|
|
902
|
+
//#endregion
|
|
903
|
+
//#region state/workspace-state.d.ts
|
|
904
|
+
interface WorkspaceState {
|
|
905
|
+
supervisor?: Record<string, unknown>;
|
|
906
|
+
collectors?: Record<string, unknown>;
|
|
907
|
+
lastBuild?: Record<string, unknown>;
|
|
908
|
+
launches?: Record<string, unknown>;
|
|
909
|
+
remoteDevice?: Record<string, unknown>;
|
|
910
|
+
metroTunnel?: Record<string, unknown>;
|
|
911
|
+
[key: string]: unknown;
|
|
912
|
+
}
|
|
913
|
+
declare const IDLE_STOP_KEY = "devServerStop";
|
|
914
|
+
/** Why the supervisor last stopped the dev server on its own: `metro.idleStopMinutes` with no use. */
|
|
915
|
+
interface IdleStopRecord {
|
|
916
|
+
reason: "idle";
|
|
917
|
+
at: string;
|
|
918
|
+
idleMinutes: number;
|
|
919
|
+
}
|
|
920
|
+
declare function readIdleStop(state: WorkspaceState | null | undefined): IdleStopRecord | null;
|
|
921
|
+
declare const DEVICE_IDLE_SHUTDOWN_KEY = "deviceIdleShutdowns";
|
|
922
|
+
/** An owned simulator or emulator the supervisor shut down after `devices.idleShutdownMinutes` with no use. */
|
|
923
|
+
interface DeviceIdleShutdownRecord {
|
|
924
|
+
at: string;
|
|
925
|
+
idleMinutes: number;
|
|
926
|
+
}
|
|
927
|
+
/** The recorded idle shutdowns by device slot key (`ios`, `android`, `ios:<slot>`). */
|
|
928
|
+
declare function readDeviceIdleShutdowns(state: WorkspaceState | null | undefined): Record<string, DeviceIdleShutdownRecord>;
|
|
929
|
+
declare const DEV_SERVER_STOP_REQUEST_KEY = "devServerStopRequest";
|
|
930
|
+
/** A Stim component's intent to stop the supervisor with `processToken`, written before it signals. */
|
|
931
|
+
interface DevServerStopRequest {
|
|
932
|
+
processToken: string;
|
|
933
|
+
by: string;
|
|
934
|
+
pid: number;
|
|
935
|
+
at: string;
|
|
936
|
+
workspace?: string;
|
|
937
|
+
}
|
|
938
|
+
declare function readDevServerStopRequest(state: WorkspaceState | null | undefined): DevServerStopRequest | null;
|
|
939
|
+
/**
|
|
940
|
+
* Why the dev server last stopped, stored under `IDLE_STOP_KEY`. `requested` names the Stim component that
|
|
941
|
+
* asked; `signal` is a SIGTERM or SIGINT no Stim component asked for; `server-exited` is the dev server
|
|
942
|
+
* process exiting on its own.
|
|
943
|
+
*/
|
|
944
|
+
type DevServerStopRecord = IdleStopRecord | {
|
|
945
|
+
reason: "requested";
|
|
946
|
+
at: string;
|
|
947
|
+
by: string;
|
|
948
|
+
byPid: number;
|
|
949
|
+
byWorkspace?: string;
|
|
950
|
+
} | {
|
|
951
|
+
reason: "signal";
|
|
952
|
+
at: string;
|
|
953
|
+
signal: string;
|
|
954
|
+
} | {
|
|
955
|
+
reason: "server-exited";
|
|
956
|
+
at: string;
|
|
957
|
+
mode: string;
|
|
958
|
+
code: number | null;
|
|
959
|
+
signal: string | null;
|
|
960
|
+
};
|
|
961
|
+
/** A stopped dev server's last cause in status; `vanished` is a supervisor proven gone that recorded none. */
|
|
962
|
+
type MetroLastStop = DevServerStopRecord | {
|
|
963
|
+
reason: "vanished";
|
|
964
|
+
pid: number;
|
|
965
|
+
startedAt: string | null;
|
|
966
|
+
};
|
|
967
|
+
declare function readDevServerStop(state: WorkspaceState | null | undefined): DevServerStopRecord | null;
|
|
968
|
+
/** Each platform's latest run; `lastBuild` holds whichever platform ran last. */
|
|
969
|
+
declare const LAST_BUILD_KEYS: Readonly<Record<StatsPlatform, string>>;
|
|
970
|
+
declare const BUILD_HISTORY_KEY = "buildHistory";
|
|
971
|
+
declare const BUILD_HISTORY_LIMIT = 10;
|
|
972
|
+
/** A recorded miss reason in the shape status reports, without `baseline.cacheKey`; null when malformed. */
|
|
973
|
+
declare function parseMissReason(value: unknown): BuildMissReason | null;
|
|
974
|
+
/**
|
|
975
|
+
* The first diagnostics of a failed build in the shape a last-build record stores and `status` reports, the
|
|
976
|
+
* ones with a source position first.
|
|
977
|
+
*/
|
|
978
|
+
declare function buildDiagnostics(value: unknown): BuildDiagnostic[];
|
|
979
|
+
declare function readLastBuilds(state: WorkspaceState | null | undefined): Partial<Record<StatsPlatform, LastBuildReport>>;
|
|
980
|
+
/** Each platform's recorded runs, newest first, at most `BUILD_HISTORY_LIMIT` each. */
|
|
981
|
+
declare function readBuildHistory(state: WorkspaceState | null | undefined): Partial<Record<StatsPlatform, BuildHistoryEntry[]>>;
|
|
982
|
+
declare function readWorkspaceState(root: string): WorkspaceState | null;
|
|
983
|
+
declare function lastUseFrom(state: WorkspaceState | null, logMtimes: readonly number[]): number;
|
|
984
|
+
declare function workspaceLastUsed(root: string): number;
|
|
985
|
+
declare const WARM_KEY = "warm";
|
|
986
|
+
/** How long a successful warm keeps a workspace `ready` when nothing runs in it. */
|
|
987
|
+
declare const READY_PHASE_MS: number;
|
|
988
|
+
/**
|
|
989
|
+
* What `stim worktree warm` last recorded in a workspace: a warm in progress, held by the ownership claim
|
|
990
|
+
* `claim` names, or a successful warm that finished at `at`.
|
|
991
|
+
*/
|
|
992
|
+
type WarmRecord = {
|
|
993
|
+
phase: "warming";
|
|
994
|
+
step: WarmStep;
|
|
995
|
+
startedAt: string;
|
|
996
|
+
claim: {
|
|
997
|
+
root: string;
|
|
998
|
+
claimId: string;
|
|
999
|
+
};
|
|
1000
|
+
} | {
|
|
1001
|
+
phase: "ready";
|
|
1002
|
+
at: string;
|
|
1003
|
+
};
|
|
1004
|
+
declare function readWarmRecord(state: WorkspaceState | null | undefined): WarmRecord | null;
|
|
1005
|
+
declare const WORKSPACE_AGENT_KEY = "agentSession";
|
|
1006
|
+
/**
|
|
1007
|
+
* The coding-agent session whose shell ran the Stim command that last recorded `lastUsedAt`, with that command's
|
|
1008
|
+
* working directory as `cwd` and its time as `lastActiveAt`.
|
|
1009
|
+
*/
|
|
1010
|
+
declare function readWorkspaceAgent(state: WorkspaceState | null | undefined): AgentSession | null;
|
|
1011
|
+
//#endregion
|
|
1012
|
+
//#region state/hosted-ios.d.ts
|
|
1013
|
+
/** A workspace slot's placement; null device means its reservation has not reached ready yet. */
|
|
1014
|
+
interface HostedIosPlacement {
|
|
1015
|
+
machine: string;
|
|
1016
|
+
session: string;
|
|
1017
|
+
appAttempt: string;
|
|
1018
|
+
device: HostedIosDevice | null;
|
|
1019
|
+
selected: string;
|
|
1020
|
+
agent: HostedAgentAccess;
|
|
1021
|
+
}
|
|
1022
|
+
/** Public hosting facts; the host's UDID and private Metro gateway are excluded. */
|
|
1023
|
+
type HostedIosStatus = Pick<HostedIosPlacement, "machine" | "session" | "selected" | "agent"> & {
|
|
1024
|
+
device: {
|
|
1025
|
+
name: string;
|
|
1026
|
+
runtime: string;
|
|
1027
|
+
} | null;
|
|
1028
|
+
/** The latest session probe in status, independent of a conflicting local simulator's state. */
|
|
1029
|
+
state?: string;
|
|
1030
|
+
};
|
|
1031
|
+
declare function parseHostedIosPlacement(value: unknown): HostedIosPlacement | null;
|
|
1032
|
+
declare function hostedIosStatus(placement: HostedIosPlacement): HostedIosStatus;
|
|
1033
|
+
/** Includes unreadable placements so callers retain every recorded hosting slot. */
|
|
1034
|
+
declare function hostedIosRecords(state: WorkspaceState | null): Record<string, unknown>;
|
|
1035
|
+
declare function unreadableHostedIos(slot: string): string;
|
|
1036
|
+
declare function hostedIosPlacements(state: WorkspaceState | null): Record<string, HostedIosPlacement>;
|
|
1037
|
+
//#endregion
|
|
1038
|
+
//#region state/maintenance.d.ts
|
|
1039
|
+
type MaintenanceMode = "off" | "report";
|
|
1040
|
+
type MaintenanceCheck = "pressure" | "size";
|
|
1041
|
+
type MaintenanceActionKind = "would-clear-outputs" | "would-trim-cache" | "would-empty-cache" | "would-shutdown-device" | "would-stop-workspace";
|
|
1042
|
+
interface MaintenanceAction {
|
|
1043
|
+
kind: MaintenanceActionKind;
|
|
1044
|
+
target: string;
|
|
1045
|
+
bytes: number;
|
|
1046
|
+
reason: string;
|
|
1047
|
+
workspace?: string;
|
|
1048
|
+
}
|
|
1049
|
+
interface MaintenanceSize {
|
|
1050
|
+
name: string;
|
|
1051
|
+
dir: string;
|
|
1052
|
+
bytes: number;
|
|
1053
|
+
measuredAt: number;
|
|
1054
|
+
category: "workspace-outputs" | "build-cache" | "metro-cache" | "compilation-cache" | "ccache" | "other";
|
|
1055
|
+
workspace?: string;
|
|
1056
|
+
idleDays?: number | null;
|
|
1057
|
+
blocked?: string;
|
|
1058
|
+
}
|
|
1059
|
+
interface MaintenancePressure {
|
|
1060
|
+
disk: {
|
|
1061
|
+
volume: string;
|
|
1062
|
+
freeMb: number;
|
|
1063
|
+
}[];
|
|
1064
|
+
memory: {
|
|
1065
|
+
level: "normal" | "warning" | "critical" | null;
|
|
1066
|
+
availableBytes: number | null;
|
|
1067
|
+
pressured: boolean;
|
|
1068
|
+
};
|
|
1069
|
+
warningSince: number | null;
|
|
1070
|
+
}
|
|
1071
|
+
interface MaintenancePass {
|
|
1072
|
+
startedAt: number;
|
|
1073
|
+
durationMs: number;
|
|
1074
|
+
trigger: string;
|
|
1075
|
+
mode: "report";
|
|
1076
|
+
freedBytes: 0;
|
|
1077
|
+
actions: number;
|
|
1078
|
+
stopped: 0;
|
|
1079
|
+
blocked: string[];
|
|
1080
|
+
}
|
|
1081
|
+
interface MaintenanceRecord extends NdjsonRecord {
|
|
1082
|
+
ts: number;
|
|
1083
|
+
src: "maintenance";
|
|
1084
|
+
level: "debug" | "info" | "warn" | "error";
|
|
1085
|
+
msg: string;
|
|
1086
|
+
event: "maintenance_pass" | "maintenance_action" | "maintenance_skip" | "maintenance_failure" | "maintenance_check";
|
|
1087
|
+
pass: string;
|
|
1088
|
+
trigger: string;
|
|
1089
|
+
mode: "report";
|
|
1090
|
+
}
|
|
1091
|
+
/** Version 1 contains report-only observations; every action is a plan and no resource was reclaimed. */
|
|
1092
|
+
interface MaintenanceState {
|
|
1093
|
+
version: 1;
|
|
1094
|
+
lastAt: Partial<Record<MaintenanceCheck, number>>;
|
|
1095
|
+
deferredAt?: Partial<Record<MaintenanceCheck, number>>;
|
|
1096
|
+
pressure: MaintenancePressure | null;
|
|
1097
|
+
sizes: MaintenanceSize[];
|
|
1098
|
+
lastPass: MaintenancePass | null;
|
|
1099
|
+
recent: MaintenanceRecord[];
|
|
1100
|
+
plan: MaintenanceAction[];
|
|
1101
|
+
skipKeys?: string[];
|
|
1102
|
+
}
|
|
1103
|
+
interface MaintenanceStatus {
|
|
1104
|
+
mode: MaintenanceMode;
|
|
1105
|
+
invalid?: string;
|
|
1106
|
+
claim?: {
|
|
1107
|
+
unresolved: string;
|
|
1108
|
+
removeCommand: string;
|
|
1109
|
+
};
|
|
1110
|
+
lastChecks: {
|
|
1111
|
+
pressure: number | null;
|
|
1112
|
+
size: number | null;
|
|
1113
|
+
};
|
|
1114
|
+
pressure: MaintenancePressure | null;
|
|
1115
|
+
sizes: MaintenanceSize[];
|
|
1116
|
+
lastPass: MaintenancePass | null;
|
|
1117
|
+
running: {
|
|
1118
|
+
startedAt: string;
|
|
1119
|
+
trigger: string;
|
|
1120
|
+
} | null;
|
|
1121
|
+
recent: MaintenanceRecord[];
|
|
1122
|
+
plan: MaintenanceAction[];
|
|
1123
|
+
}
|
|
1124
|
+
/** Rejects missing, corrupt or unsupported payloads without throwing. */
|
|
1125
|
+
declare function parseMaintenanceState(value: unknown): MaintenanceState | null;
|
|
1126
|
+
declare function readMaintenanceState(): MaintenanceState | null;
|
|
1127
|
+
declare function readMaintenanceAttempt(): number | undefined;
|
|
1128
|
+
//#endregion
|
|
1129
|
+
//#region state/archive.d.ts
|
|
1130
|
+
interface ArchivedBytes {
|
|
1131
|
+
logs: number;
|
|
1132
|
+
recordings: number;
|
|
1133
|
+
agentActions: number;
|
|
1134
|
+
record: number;
|
|
1135
|
+
total: number;
|
|
1136
|
+
}
|
|
1137
|
+
interface ArchivedWorkspace {
|
|
1138
|
+
id: string;
|
|
1139
|
+
projectRoot: string;
|
|
1140
|
+
project: string;
|
|
1141
|
+
workspace: string;
|
|
1142
|
+
worktree: {
|
|
1143
|
+
repository: string | null;
|
|
1144
|
+
branch: string | null;
|
|
1145
|
+
head: string | null;
|
|
1146
|
+
subject: string | null;
|
|
1147
|
+
merged: boolean | null;
|
|
1148
|
+
pullRequest: {
|
|
1149
|
+
number: number;
|
|
1150
|
+
state: string;
|
|
1151
|
+
title: string;
|
|
1152
|
+
url: string;
|
|
1153
|
+
} | null;
|
|
1154
|
+
};
|
|
1155
|
+
removedAt: string;
|
|
1156
|
+
removedBy: string;
|
|
1157
|
+
lastUsedAt: string | null;
|
|
1158
|
+
builds: {
|
|
1159
|
+
count: number;
|
|
1160
|
+
last: LastBuildReport | null;
|
|
1161
|
+
lastErrorCount: number;
|
|
1162
|
+
};
|
|
1163
|
+
agents: EndedAgentSession[];
|
|
1164
|
+
bytes: ArchivedBytes;
|
|
1165
|
+
expires: {
|
|
1166
|
+
logs: string | null;
|
|
1167
|
+
recordings: string | null;
|
|
1168
|
+
agentActions: string | null;
|
|
1169
|
+
record: string | null;
|
|
1170
|
+
};
|
|
1171
|
+
version: number;
|
|
1172
|
+
replacedBy?: string;
|
|
1173
|
+
}
|
|
1174
|
+
interface ArchivedUsage {
|
|
1175
|
+
count: number;
|
|
1176
|
+
bytes: number;
|
|
1177
|
+
byKind: {
|
|
1178
|
+
logs: number;
|
|
1179
|
+
recordings: number;
|
|
1180
|
+
agentActions: number;
|
|
1181
|
+
record: number;
|
|
1182
|
+
};
|
|
1183
|
+
}
|
|
1184
|
+
declare function readArchives(): ArchivedWorkspace[];
|
|
1185
|
+
declare function readArchive(id: string): ArchivedWorkspace | null;
|
|
1186
|
+
declare function archivedUsage(archives: readonly ArchivedWorkspace[]): ArchivedUsage;
|
|
1187
|
+
declare function linkReplacedArchives(archives: readonly ArchivedWorkspace[], paths: readonly string[]): ArchivedWorkspace[];
|
|
1188
|
+
declare function archiveEnabled(env: NodeJS.ProcessEnv, layers: readonly unknown[]): boolean;
|
|
1189
|
+
//#endregion
|
|
1190
|
+
//#region state/macos.d.ts
|
|
1191
|
+
interface MacosProcess {
|
|
1192
|
+
pid: number;
|
|
1193
|
+
processToken: string;
|
|
1194
|
+
startedAtMicros: number;
|
|
1195
|
+
}
|
|
1196
|
+
interface MacosBuild {
|
|
1197
|
+
state: "running" | "ok" | "failed";
|
|
1198
|
+
startedAt: string;
|
|
1199
|
+
finishedAt?: string;
|
|
1200
|
+
durationMs?: number;
|
|
1201
|
+
error?: string;
|
|
1202
|
+
errorCode?: string;
|
|
1203
|
+
buildMachine?: string;
|
|
1204
|
+
builtOn?: string;
|
|
1205
|
+
offloadedTo?: string;
|
|
1206
|
+
offloadFallback?: string;
|
|
1207
|
+
}
|
|
1208
|
+
interface MacosAppRecord {
|
|
1209
|
+
launchId: string;
|
|
1210
|
+
arguments: string[];
|
|
1211
|
+
product: string;
|
|
1212
|
+
bundle: string;
|
|
1213
|
+
bundleId: string;
|
|
1214
|
+
executable: string;
|
|
1215
|
+
build: MacosBuild;
|
|
1216
|
+
supervisor?: MacosProcess;
|
|
1217
|
+
app?: MacosProcess;
|
|
1218
|
+
/** Set when `stim macos --remote` reserved a session on another Mac; the app then has no local process. */
|
|
1219
|
+
host?: HostedMacosPlacement;
|
|
1220
|
+
/** Host launch evidence: true for a live app; status can override it in memory after probing the session. */
|
|
1221
|
+
hostLaunched?: boolean | "unverified";
|
|
1222
|
+
}
|
|
1223
|
+
interface MacosAppState extends MacosAppRecord {
|
|
1224
|
+
state: "running" | "orphaned" | "stopped" | "unverified";
|
|
1225
|
+
}
|
|
1226
|
+
declare function parseMacosRecord(value: unknown): MacosAppRecord | null;
|
|
1227
|
+
declare function readMacosRecord(root: string): MacosAppRecord | null;
|
|
1228
|
+
declare function readHostedMacosApp(home: string): MacosAppRecord | null;
|
|
1229
|
+
declare function macosAppState(record: MacosAppRecord | null): MacosAppState | null;
|
|
1230
|
+
//#endregion
|
|
1231
|
+
//#region state/status.d.ts
|
|
1232
|
+
type StatsPlatform = "ios" | "android";
|
|
1233
|
+
type RunOutcomeKind = "hit" | "cold";
|
|
1234
|
+
declare const BUILD_PHASES: readonly ["prepare", "cache-lookup", "wait", "prebuild", "pods", "compile", "device", "install", "launch"];
|
|
1235
|
+
type BuildPhase = (typeof BUILD_PHASES)[number];
|
|
1236
|
+
type ActiveBuildState = "running" | "stale" | "unknown";
|
|
1237
|
+
/**
|
|
1238
|
+
* Where a running build compiles: `local`, or the build machine it was offloaded to, with the phase it is in there
|
|
1239
|
+
* (`sync`, `deps`, `prebuild`, `pods`, `build` or `fetch`) and when the offload and that phase started.
|
|
1240
|
+
*/
|
|
1241
|
+
type BuildPlacement = "local" | {
|
|
1242
|
+
host: string;
|
|
1243
|
+
phase: string;
|
|
1244
|
+
startedAt: string;
|
|
1245
|
+
phaseStartedAt: string;
|
|
1246
|
+
};
|
|
1247
|
+
interface BuildReport {
|
|
1248
|
+
platform: StatsPlatform;
|
|
1249
|
+
slot: string;
|
|
1250
|
+
state: ActiveBuildState;
|
|
1251
|
+
phase: BuildPhase;
|
|
1252
|
+
startedAt: string;
|
|
1253
|
+
phaseStartedAt: string;
|
|
1254
|
+
outcome: RunOutcomeKind | null;
|
|
1255
|
+
/** Whether `outcome` is this run's own; before its cache lookup resolves it is the project's latest outcome. */
|
|
1256
|
+
outcomeKnown: boolean;
|
|
1257
|
+
/** The resolved lookup result; absent before resolution and when the run skips cache lookup. */
|
|
1258
|
+
cacheLookupOutcome?: "hit" | "miss";
|
|
1259
|
+
expectedMs: number | null;
|
|
1260
|
+
expectedPhaseMs: number | null;
|
|
1261
|
+
/** Milliseconds spent in phases already left; sums repeat visits, excludes the current visit, and is omitted before any phase completes and by older Stim. */
|
|
1262
|
+
completedPhaseMs?: Partial<Record<BuildPhase, number>>;
|
|
1263
|
+
basis: number;
|
|
1264
|
+
/**
|
|
1265
|
+
* The phases a run like this one goes through, in order, with each one's median in milliseconds, from the same
|
|
1266
|
+
* runs as `expectedMs`; null without comparable runs. The current phase can be one the plan does not list.
|
|
1267
|
+
*/
|
|
1268
|
+
plannedPhases: PlannedPhase[] | null;
|
|
1269
|
+
/** Why the run's cache lookup missed, once the run knows; `baseline` omits `cacheKey`. */
|
|
1270
|
+
missReason?: BuildMissReason;
|
|
1271
|
+
/**
|
|
1272
|
+
* True while `missReason` is the miss of the key the run looked up first and the run will prebuild or install pods,
|
|
1273
|
+
* then look the key up again. A hit on the second lookup removes `missReason` and sets `outcome` to `hit`.
|
|
1274
|
+
*/
|
|
1275
|
+
missProvisional?: true;
|
|
1276
|
+
/** What the native build tool is doing now, once it printed a line Stim recognizes. */
|
|
1277
|
+
detail?: BuildDetail;
|
|
1278
|
+
placement: BuildPlacement;
|
|
1279
|
+
/** While `phase` is `wait`: the workspace whose build of the same artifact this run waits on, when it is known. */
|
|
1280
|
+
waitingOn?: {
|
|
1281
|
+
path: string;
|
|
1282
|
+
};
|
|
1283
|
+
}
|
|
1284
|
+
/** One phase a running build is expected to go through, and its median duration in comparable runs. */
|
|
1285
|
+
interface PlannedPhase {
|
|
1286
|
+
phase: BuildPhase;
|
|
1287
|
+
expectedMs: number;
|
|
1288
|
+
}
|
|
1289
|
+
/** The native build tool's step inside a build's `compile` phase. */
|
|
1290
|
+
declare const NATIVE_BUILD_STEPS: readonly ["configure", "compile", "link", "resources", "script", "dex", "package", "sign"];
|
|
1291
|
+
type NativeBuildStep = (typeof NATIVE_BUILD_STEPS)[number];
|
|
1292
|
+
/**
|
|
1293
|
+
* A running build's progress as its tool reports it. `unit` is `targets` for xcodebuild and `tasks` for Gradle.
|
|
1294
|
+
* xcodebuild's `done` counts targets it finished and `total` the targets in its dependency graph, which includes
|
|
1295
|
+
* targets with nothing to do; Gradle's `done` counts the tasks it reported, with a null `total`. They are counts, not
|
|
1296
|
+
* a completion fraction. `status` reports the detail only during the `compile` phase. `line` is
|
|
1297
|
+
* the latest compile, link or task line with paths shortened to file names.
|
|
1298
|
+
*/
|
|
1299
|
+
interface BuildDetail {
|
|
1300
|
+
step: NativeBuildStep | null;
|
|
1301
|
+
unit: "targets" | "tasks" | null;
|
|
1302
|
+
done: number | null;
|
|
1303
|
+
total: number | null;
|
|
1304
|
+
line: string | null;
|
|
1305
|
+
updatedAt: string;
|
|
1306
|
+
}
|
|
1307
|
+
/** Where a build's app came from: a cache tier, or `false` when it compiled or failed before one was found. */
|
|
1308
|
+
type BuildCacheHit = "local" | "remote" | false;
|
|
1309
|
+
/** A platform's most recent `ios` or `android` run in one workspace. */
|
|
1310
|
+
interface LastBuildReport {
|
|
1311
|
+
platform: StatsPlatform;
|
|
1312
|
+
status: "ok" | "failed";
|
|
1313
|
+
cacheHit: BuildCacheHit;
|
|
1314
|
+
cacheSkipped: boolean;
|
|
1315
|
+
durationMs: number | null;
|
|
1316
|
+
fingerprint: string | null;
|
|
1317
|
+
startedAt: string;
|
|
1318
|
+
finishedAt: string | null;
|
|
1319
|
+
errorCode?: string;
|
|
1320
|
+
missReason?: BuildMissReason;
|
|
1321
|
+
/** The selected auto, local, or configured machine entry; present on new build records, including cache hits. */
|
|
1322
|
+
buildMachine?: string;
|
|
1323
|
+
/** Where compilation ran: here or a machine name; absent when no build ran. */
|
|
1324
|
+
builtOn?: string;
|
|
1325
|
+
/** The build machine that compiled the app when the build was offloaded. */
|
|
1326
|
+
offloadedTo?: string;
|
|
1327
|
+
/** Why the run built here after it considered offloading; absent when it offloaded or never considered it. */
|
|
1328
|
+
offloadFallback?: string;
|
|
1329
|
+
/** The first compiler diagnostics of a failed build, when the build tool reported any. */
|
|
1330
|
+
diagnostics?: BuildDiagnostic[];
|
|
1331
|
+
/** Present on a failed run: what failed, from `buildCause`. */
|
|
1332
|
+
cause?: BuildCause;
|
|
1333
|
+
}
|
|
1334
|
+
/**
|
|
1335
|
+
* A failed run's cause: the first diagnostic with a file and a line, keyed `file:line`, else the run's error code
|
|
1336
|
+
* (or `failed`), with null `file` and `line`. Consecutive failures with the same `key` failed the same way.
|
|
1337
|
+
*/
|
|
1338
|
+
interface BuildCause {
|
|
1339
|
+
key: string;
|
|
1340
|
+
file: string | null;
|
|
1341
|
+
line: number | null;
|
|
1342
|
+
}
|
|
1343
|
+
/** How a recorded build ended. `interrupted` is a run whose process ended without recording a result. */
|
|
1344
|
+
declare const BUILD_RESULTS: readonly ["succeeded", "failed", "cancelled", "interrupted"];
|
|
1345
|
+
type BuildResult = (typeof BUILD_RESULTS)[number];
|
|
1346
|
+
/**
|
|
1347
|
+
* One run in a workspace's recent build history. `configuration` is the iOS configuration or the Android
|
|
1348
|
+
* variant the run built, `Debug` or `debug` by default, and null when the run ended before resolving it.
|
|
1349
|
+
* `phases` holds the milliseconds spent in each phase the run entered. An interrupted run has null
|
|
1350
|
+
* `durationMs` and `finishedAt`, no cache facts, and 0 for the phase it stopped in.
|
|
1351
|
+
*/
|
|
1352
|
+
interface BuildHistoryEntry extends LastBuildReport {
|
|
1353
|
+
result: BuildResult;
|
|
1354
|
+
slot: string;
|
|
1355
|
+
configuration: string | null;
|
|
1356
|
+
cacheKey: string | null;
|
|
1357
|
+
phases: Partial<Record<BuildPhase, number>>;
|
|
1358
|
+
}
|
|
1359
|
+
/** One compiler error from a failed build: where it is, when the tool said, and its message. */
|
|
1360
|
+
interface BuildDiagnostic {
|
|
1361
|
+
file: string | null;
|
|
1362
|
+
line: number | null;
|
|
1363
|
+
column: number | null;
|
|
1364
|
+
message: string;
|
|
1365
|
+
}
|
|
1366
|
+
/** What kind of native input a changed fingerprint source is. */
|
|
1367
|
+
type BuildMissCategory = "native-dependency" | "config-plugin" | "app-config" | "app-asset" | "package" | "native-dir" | "autolinking" | "package-scripts" | "file" | "other";
|
|
1368
|
+
interface BuildMissChange {
|
|
1369
|
+
source: string;
|
|
1370
|
+
change: "added" | "removed" | "changed";
|
|
1371
|
+
category: BuildMissCategory;
|
|
1372
|
+
}
|
|
1373
|
+
/**
|
|
1374
|
+
* Why a run compiled instead of installing a cached app. `changes` holds at most 20 entries,
|
|
1375
|
+
* ordered by importance; `changeCount` is the full number of changed fingerprint sources.
|
|
1376
|
+
* Only a plan reports `prebuild-pending`: the run would prebuild before compiling, so the changes
|
|
1377
|
+
* compare the fingerprint before that prebuild.
|
|
1378
|
+
*/
|
|
1379
|
+
interface BuildMissReason {
|
|
1380
|
+
kind: "changed" | "no-baseline" | "same-sources" | "cache-skipped" | "fingerprint-error" | "prebuild-pending";
|
|
1381
|
+
summary: string;
|
|
1382
|
+
changes: BuildMissChange[];
|
|
1383
|
+
changeCount: number;
|
|
1384
|
+
/** `cacheKey` is kept in workspace state so a later miss can find this baseline; status omits it. */
|
|
1385
|
+
baseline: {
|
|
1386
|
+
fingerprint: string;
|
|
1387
|
+
cacheKey?: string;
|
|
1388
|
+
from: "workspace" | "project";
|
|
1389
|
+
} | null;
|
|
1390
|
+
rekeyedBy: string[];
|
|
1391
|
+
}
|
|
1392
|
+
/** The payload `stim ios --plan --json` and `stim android --plan --json` print. */
|
|
1393
|
+
interface BuildPlanPayload {
|
|
1394
|
+
platform: StatsPlatform;
|
|
1395
|
+
slot?: string;
|
|
1396
|
+
fingerprint: string;
|
|
1397
|
+
cacheKey: string | null;
|
|
1398
|
+
cacheHit: BuildCacheHit;
|
|
1399
|
+
provider: string | null;
|
|
1400
|
+
cacheSkipped: boolean;
|
|
1401
|
+
prebuild: "none" | "generate" | "regenerate" | "refuse" | null;
|
|
1402
|
+
outcome: RunOutcomeKind | null;
|
|
1403
|
+
expectedMs: number | null;
|
|
1404
|
+
basis: number;
|
|
1405
|
+
/** On a predicted miss with cache reads on, why the cache has no app; `baseline` omits `cacheKey`. */
|
|
1406
|
+
missReason?: BuildMissReason;
|
|
1407
|
+
refusal?: {
|
|
1408
|
+
code: string;
|
|
1409
|
+
message: string;
|
|
1410
|
+
remedy: string;
|
|
1411
|
+
};
|
|
1412
|
+
}
|
|
1413
|
+
type ActivityState = "driven" | "active" | "idle" | "unknown";
|
|
1414
|
+
interface ActivityDriver {
|
|
1415
|
+
tool: string;
|
|
1416
|
+
pid: number | null;
|
|
1417
|
+
since: string | null;
|
|
1418
|
+
}
|
|
1419
|
+
/** The kinds of evidence that date a device's last activity, in the order `recent` lists them. */
|
|
1420
|
+
declare const ACTIVITY_RECENCY_BASES: readonly ["agent-action", "device-log", "metro-bundle", "workspace-use", "supervisor-start", "page-log", "viewer"];
|
|
1421
|
+
type ActivityRecencyBasis = (typeof ACTIVITY_RECENCY_BASES)[number];
|
|
1422
|
+
interface DeviceActivity {
|
|
1423
|
+
state: ActivityState;
|
|
1424
|
+
driver?: ActivityDriver;
|
|
1425
|
+
lastActivityAt?: string;
|
|
1426
|
+
/** The newest time of each kind of evidence behind `lastActivityAt`, so a reader can leave out app log chatter. */
|
|
1427
|
+
recent?: Partial<Record<ActivityRecencyBasis, string>>;
|
|
1428
|
+
basis: string[];
|
|
1429
|
+
}
|
|
1430
|
+
/** Every state a device's app process can report. */
|
|
1431
|
+
declare const APP_PROCESS_STATES: readonly ["running", "stopped", "unknown"];
|
|
1432
|
+
/**
|
|
1433
|
+
* Whether the workspace's app process is alive on a device now. This is current process state, not launch evidence:
|
|
1434
|
+
* `launched` in an `ios` or `android` result stays the record of one launch. `id` is the bundle identifier or
|
|
1435
|
+
* package that was checked; `state` is "unknown" when the process listing could not be read.
|
|
1436
|
+
*/
|
|
1437
|
+
interface DeviceAppProcess {
|
|
1438
|
+
id: string;
|
|
1439
|
+
state: (typeof APP_PROCESS_STATES)[number];
|
|
1440
|
+
}
|
|
1441
|
+
/**
|
|
1442
|
+
* A linked worktree's `git status`. `changed` counts tracked paths with staged or unstaged changes, including
|
|
1443
|
+
* conflicts; `untracked` counts untracked entries as `git status` lists them, so an untracked directory counts once.
|
|
1444
|
+
* `ahead` and `behind` compare HEAD with `upstream`, and are null when there is no upstream or it no longer exists.
|
|
1445
|
+
* `mergedInto` names the default branch (`origin/main`) when `gc` would consider the branch merged into it, judged
|
|
1446
|
+
* from local refs without fetching.
|
|
1447
|
+
*/
|
|
1448
|
+
interface WorktreeGit {
|
|
1449
|
+
changed: number;
|
|
1450
|
+
untracked: number;
|
|
1451
|
+
upstream: string | null;
|
|
1452
|
+
ahead: number | null;
|
|
1453
|
+
behind: number | null;
|
|
1454
|
+
mergedInto: string | null;
|
|
1455
|
+
}
|
|
1456
|
+
/**
|
|
1457
|
+
* The GitHub pull request of a worktree's branch and HEAD, as `status --watch` last looked it up through `gh`.
|
|
1458
|
+
* `state` is `draft` for an open draft. `checks` counts the head commit's check runs and commit statuses, null when it
|
|
1459
|
+
* has none. `checkedAt` is when Stim last asked GitHub.
|
|
1460
|
+
*/
|
|
1461
|
+
interface WorktreePullRequest {
|
|
1462
|
+
number: number;
|
|
1463
|
+
url: string;
|
|
1464
|
+
title: string;
|
|
1465
|
+
state: "open" | "draft" | "merged" | "closed";
|
|
1466
|
+
checks: {
|
|
1467
|
+
passing: number;
|
|
1468
|
+
failing: number;
|
|
1469
|
+
pending: number;
|
|
1470
|
+
} | null;
|
|
1471
|
+
reviewDecision: "approved" | "changes-requested" | "review-required" | null;
|
|
1472
|
+
checkedAt: string;
|
|
1473
|
+
}
|
|
1474
|
+
interface WorktreeFacts {
|
|
1475
|
+
path: string;
|
|
1476
|
+
branch?: string;
|
|
1477
|
+
repository?: string;
|
|
1478
|
+
/** Null when git could not be read in time, or the worktree is in a folder status does not open. */
|
|
1479
|
+
git?: WorktreeGit | null;
|
|
1480
|
+
/** Null when GitHub has no pull request for the branch; absent when unknown, such as without `gh`. */
|
|
1481
|
+
pullRequest?: WorktreePullRequest | null;
|
|
1482
|
+
/** Present with `git`: what the worktree's git chip shows, from `gitChip`. */
|
|
1483
|
+
gitChip?: GitChip;
|
|
1484
|
+
}
|
|
1485
|
+
/** Every coding-agent tool whose sessions status can attribute to an environment. */
|
|
1486
|
+
declare const AGENT_TOOLS: readonly ["claude-code", "codex"];
|
|
1487
|
+
type AgentTool = (typeof AGENT_TOOLS)[number];
|
|
1488
|
+
/**
|
|
1489
|
+
* A coding-agent session working in an environment: one whose working directory `cwd` is the environment's path,
|
|
1490
|
+
* inside it, or its git worktree root, or one that ran a Stim command in it. `title` is the short name the tool keeps
|
|
1491
|
+
* for the session, never its conversation. `lastActiveAt` is the tool's own last update, or the Stim command's time
|
|
1492
|
+
* when that is newer. `openUrl` opens the session in the tool's desktop app when that app is installed on this Mac.
|
|
1493
|
+
* `webUrl` opens a Claude Code session with Remote Control connected on claude.ai/code or in the Claude mobile app.
|
|
1494
|
+
*/
|
|
1495
|
+
interface AgentSession {
|
|
1496
|
+
tool: AgentTool;
|
|
1497
|
+
sessionId: string;
|
|
1498
|
+
title?: string;
|
|
1499
|
+
cwd: string;
|
|
1500
|
+
startedAt?: string;
|
|
1501
|
+
lastActiveAt?: string;
|
|
1502
|
+
pid?: number;
|
|
1503
|
+
openUrl?: string;
|
|
1504
|
+
webUrl?: string;
|
|
1505
|
+
}
|
|
1506
|
+
/**
|
|
1507
|
+
* An agent session that stopped running in an environment, with the details Stim last found while it ran. `endedAt`
|
|
1508
|
+
* is the last time a status watcher found it running.
|
|
1509
|
+
*/
|
|
1510
|
+
interface EndedAgentSession extends Omit<AgentSession, "pid"> {
|
|
1511
|
+
endedAt: string;
|
|
1512
|
+
}
|
|
1513
|
+
interface AndroidRuntimeFacts {
|
|
1514
|
+
serial: string | null;
|
|
1515
|
+
state: "detected" | "not-detected" | "missing" | "unknown";
|
|
1516
|
+
error?: string;
|
|
1517
|
+
}
|
|
1518
|
+
/** Every connection state a physical device can report. */
|
|
1519
|
+
declare const PHYSICAL_DEVICE_CONNECTIONS: readonly ["connected", "disconnected", "unknown"];
|
|
1520
|
+
type PhysicalDeviceConnection = (typeof PHYSICAL_DEVICE_CONNECTIONS)[number];
|
|
1521
|
+
/**
|
|
1522
|
+
* A physical iPhone, iPad or Android phone the workspace holds an unexpired lease on, from `ios --device`,
|
|
1523
|
+
* `android --device` or `device lock`. Stim uses it and never owns it, so `owned` is always false. `id` is the
|
|
1524
|
+
* UDID or adb serial. `name` is the device's own name, falling back to the name the lease recorded; `model` is the
|
|
1525
|
+
* marketing name devicectl reports, null when it could not be read, or the Android model the lease recorded.
|
|
1526
|
+
* `connection` is `connected` when devicectl can reach the phone or adb lists it as `device`, `disconnected` when
|
|
1527
|
+
* the tool answered without it, and `unknown` when the tool could not be read in time. `lease.holder` is the
|
|
1528
|
+
* workspace path that holds it.
|
|
1529
|
+
*/
|
|
1530
|
+
interface PhysicalDeviceState {
|
|
1531
|
+
platform: StatsPlatform;
|
|
1532
|
+
slot: string;
|
|
1533
|
+
id: string;
|
|
1534
|
+
name: string | null;
|
|
1535
|
+
model: string | null;
|
|
1536
|
+
owned: false;
|
|
1537
|
+
physical: true;
|
|
1538
|
+
connection: PhysicalDeviceConnection;
|
|
1539
|
+
lease: {
|
|
1540
|
+
holder: string;
|
|
1541
|
+
kind: "declared" | "run";
|
|
1542
|
+
grantedAt: string | null;
|
|
1543
|
+
expiresAt: string;
|
|
1544
|
+
};
|
|
1545
|
+
}
|
|
1546
|
+
interface RemoteDeviceState {
|
|
1547
|
+
platform: "ios" | "android" | null;
|
|
1548
|
+
backend: "eas";
|
|
1549
|
+
sessionId: string;
|
|
1550
|
+
state: "claimed" | "unclaimed" | "unknown";
|
|
1551
|
+
startedAt: string | null;
|
|
1552
|
+
webPreviewUrl: string | null;
|
|
1553
|
+
}
|
|
1554
|
+
/**
|
|
1555
|
+
* One part of a worktree's git chip, in display order: commits ahead of and behind the upstream, uncommitted files
|
|
1556
|
+
* (changed plus untracked), the base branch the branch is merged into (left out when its pull request is merged,
|
|
1557
|
+
* whose own mark says so), and a branch with no upstream that is not merged.
|
|
1558
|
+
*/
|
|
1559
|
+
type GitChipPart = {
|
|
1560
|
+
kind: "arrows";
|
|
1561
|
+
ahead: number;
|
|
1562
|
+
behind: number;
|
|
1563
|
+
} | {
|
|
1564
|
+
kind: "changed";
|
|
1565
|
+
count: number;
|
|
1566
|
+
} | {
|
|
1567
|
+
kind: "merged";
|
|
1568
|
+
into: string;
|
|
1569
|
+
} | {
|
|
1570
|
+
kind: "no-upstream";
|
|
1571
|
+
};
|
|
1572
|
+
/** A pull request's checks at a glance: any failing, else any pending, else any passing; null without checks. */
|
|
1573
|
+
type ChecksState = "passing" | "failing" | "pending" | null;
|
|
1574
|
+
interface GitChip {
|
|
1575
|
+
parts: GitChipPart[];
|
|
1576
|
+
ci: ChecksState;
|
|
1577
|
+
}
|
|
1578
|
+
/**
|
|
1579
|
+
* Whether a running owned simulator or emulator lacks the workspace's app: `none` when its platform never built
|
|
1580
|
+
* successfully here and the latest build failed, `closed` when status saw no app process, else null.
|
|
1581
|
+
*/
|
|
1582
|
+
type AppPresence = "none" | "closed" | null;
|
|
1583
|
+
declare const WORKSPACE_STAGE_KINDS: readonly ["building", "warming", "ready", "build-failed", "running", "stopped"];
|
|
1584
|
+
/**
|
|
1585
|
+
* Where a workspace is, first match wins: `building` while a build runs, `warming` and `ready` from `phase` when
|
|
1586
|
+
* nothing is live, `build-failed` when the newest run of either platform failed, `running` when it is live or holds
|
|
1587
|
+
* a remote device, else `stopped`. `since` is when that began: the build's start, the warm phase's time, the failed
|
|
1588
|
+
* run's end (else start), the supervisor's start, or Metro's last stop. `platform` names the build for `building`
|
|
1589
|
+
* and `build-failed`. `closedApps` lists, for `running`, the devices whose `appPresence` is `closed`.
|
|
1590
|
+
*/
|
|
1591
|
+
interface WorkspaceStage {
|
|
1592
|
+
kind: (typeof WORKSPACE_STAGE_KINDS)[number];
|
|
1593
|
+
since: string | null;
|
|
1594
|
+
platform: StatsPlatform | "macos" | null;
|
|
1595
|
+
closedApps: {
|
|
1596
|
+
platform: StatsPlatform;
|
|
1597
|
+
slot: string;
|
|
1598
|
+
}[];
|
|
1599
|
+
}
|
|
1600
|
+
/** Every code a status issue can carry. */
|
|
1601
|
+
declare const STATUS_ISSUE_CODES: readonly ["port-not-ours", "sim-missing", "sim-without-metro", "avd-serial-changed", "avd-missing", "avd-not-detected", "avd-unchecked", "android-reverse-missing", "supervisor-unverified", "browser-unverified", "browser-orphaned"];
|
|
1602
|
+
type StatusIssueCode = (typeof STATUS_ISSUE_CODES)[number];
|
|
1603
|
+
/**
|
|
1604
|
+
* One thing in a workspace that needs the user, or with severity `info` a note that needs nothing. `remedy` is a
|
|
1605
|
+
* command to run from `workspace`; `slot` is absent for the default device slot. `warnings` carries the `error` and
|
|
1606
|
+
* `warning` issues as text.
|
|
1607
|
+
*
|
|
1608
|
+
* Severity:
|
|
1609
|
+
* - `error`: Stim cannot verify or safely act on something; a person resolves it, following the teardown guide.
|
|
1610
|
+
* - `warning`: something is broken now and needs someone to act, such as an app that cannot reach Metro, a held
|
|
1611
|
+
* port or a device that vanished while expected.
|
|
1612
|
+
* - `info`: a fact the next normal Stim command handles by itself, so it needs no action.
|
|
1613
|
+
*
|
|
1614
|
+
* The phone app and Stim Desktop show `error` and `warning` and hide `info`; plain `stim status` prints `info` as a
|
|
1615
|
+
* dim note with no remedy.
|
|
1616
|
+
*/
|
|
1617
|
+
interface StatusIssue {
|
|
1618
|
+
code: StatusIssueCode;
|
|
1619
|
+
severity: "error" | "warning" | "info";
|
|
1620
|
+
message: string;
|
|
1621
|
+
remedy: string;
|
|
1622
|
+
workspace: string;
|
|
1623
|
+
slot?: string;
|
|
1624
|
+
}
|
|
1625
|
+
/** Every state the owned page's latest load can report. */
|
|
1626
|
+
declare const WEB_PAGE_STATES: readonly ["loading", "loaded", "failed"];
|
|
1627
|
+
/**
|
|
1628
|
+
* The owned page's latest load, from the page-load marker in the workspace's web log: `url` is the document it
|
|
1629
|
+
* loaded, `state` is `failed` when that document did not load or the page crashed, with the log message as
|
|
1630
|
+
* `error`. `route`, present only when an in-app route change (history API or fragment) moved the page off `url`
|
|
1631
|
+
* since the load, is the URL it shows now.
|
|
1632
|
+
*/
|
|
1633
|
+
interface WebPageState {
|
|
1634
|
+
url: string;
|
|
1635
|
+
state: (typeof WEB_PAGE_STATES)[number];
|
|
1636
|
+
error?: string;
|
|
1637
|
+
route?: string;
|
|
1638
|
+
}
|
|
1639
|
+
/**
|
|
1640
|
+
* The workspace's Stim-owned Chrome. `pid` is Chrome's process and `supervisorPid` the Stim process that holds
|
|
1641
|
+
* its DevTools session. `cdpEndpoint` is the loopback DevTools HTTP endpoint agents can attach to, and `targetId`
|
|
1642
|
+
* the DevTools target of the owned page; both are null when the browser is not running. `profile` is the
|
|
1643
|
+
* Stim-owned user data directory. `page` is null before the page's first load. `activity` names DevTools clients
|
|
1644
|
+
* other than Stim's as drivers.
|
|
1645
|
+
*/
|
|
1646
|
+
interface WebBrowserState {
|
|
1647
|
+
browser: "chrome";
|
|
1648
|
+
version: string | null;
|
|
1649
|
+
running: boolean;
|
|
1650
|
+
pid: number | null;
|
|
1651
|
+
supervisorPid: number | null;
|
|
1652
|
+
url: string;
|
|
1653
|
+
headless: boolean;
|
|
1654
|
+
viewport: WebViewport;
|
|
1655
|
+
profile: string;
|
|
1656
|
+
cdpEndpoint: string | null;
|
|
1657
|
+
targetId: string | null;
|
|
1658
|
+
page?: WebPageState | null;
|
|
1659
|
+
activity?: DeviceActivity;
|
|
1660
|
+
}
|
|
1661
|
+
/** The steps of `stim worktree warm`: `refresh` fast-forwards and installs in the source checkout, `copy` carries ignored entries. */
|
|
1662
|
+
type WarmStep = "refresh" | "copy";
|
|
1663
|
+
/**
|
|
1664
|
+
* Where a workspace is in its lifecycle: `warming` while `stim worktree warm` runs in it, `ready` after a warm
|
|
1665
|
+
* succeeded and before any `start`, `ios`, `android`, `web` or `reload` there, for at most two hours; `live` when
|
|
1666
|
+
* anything it owns runs, else `idle`.
|
|
1667
|
+
*/
|
|
1668
|
+
declare const WORKSPACE_PHASES: readonly ["warming", "ready", "live", "idle"];
|
|
1669
|
+
type WorkspacePhase = (typeof WORKSPACE_PHASES)[number];
|
|
1670
|
+
/** A folder's size on disk as `status --watch` last measured it. */
|
|
1671
|
+
interface DiskMeasure {
|
|
1672
|
+
bytes: number;
|
|
1673
|
+
measuredAt: string;
|
|
1674
|
+
}
|
|
1675
|
+
/**
|
|
1676
|
+
* An environment's disk use as `status --watch` last measured it. `worktreeBytes` is the git worktree folder, or the
|
|
1677
|
+
* workspace folder outside one, node_modules included. `nodeModulesBytes` is node_modules at the worktree root and,
|
|
1678
|
+
* when different, at the workspace path, and is part of `worktreeBytes`. `buildBytes` is Stim's own folder for the
|
|
1679
|
+
* workspace: Xcode derived data, Gradle outputs and logs. A figure is null until it was measured; `measuredAt` is the
|
|
1680
|
+
* oldest measurement.
|
|
1681
|
+
*/
|
|
1682
|
+
interface EnvironmentDisk {
|
|
1683
|
+
worktreeBytes: number | null;
|
|
1684
|
+
nodeModulesBytes: number | null;
|
|
1685
|
+
buildBytes: number | null;
|
|
1686
|
+
measuredAt: string;
|
|
1687
|
+
}
|
|
1688
|
+
/**
|
|
1689
|
+
* A Metro bundle request: `bundling` while one is in flight on the workspace's Metro, with its `platform`,
|
|
1690
|
+
* `startedAt` and, when Metro reported progress for it, `percent` (0-100). `last` is the newest finished request,
|
|
1691
|
+
* `durationMs` from request to response end.
|
|
1692
|
+
*/
|
|
1693
|
+
interface MetroBundleState {
|
|
1694
|
+
bundling: boolean;
|
|
1695
|
+
platform?: StatsPlatform;
|
|
1696
|
+
startedAt?: string;
|
|
1697
|
+
percent?: number;
|
|
1698
|
+
last?: {
|
|
1699
|
+
platform: StatsPlatform;
|
|
1700
|
+
status: "ok" | "failed";
|
|
1701
|
+
durationMs: number;
|
|
1702
|
+
finishedAt: string;
|
|
1703
|
+
};
|
|
1704
|
+
}
|
|
1705
|
+
interface SimulatorState {
|
|
1706
|
+
host?: HostedIosStatus;
|
|
1707
|
+
name: string | null;
|
|
1708
|
+
udid: string;
|
|
1709
|
+
owned: boolean;
|
|
1710
|
+
state: string;
|
|
1711
|
+
activity?: DeviceActivity;
|
|
1712
|
+
app?: DeviceAppProcess;
|
|
1713
|
+
appPresence?: AppPresence;
|
|
1714
|
+
/** The simulator's data folder, for an owned simulator once measured. */
|
|
1715
|
+
disk?: DiskMeasure;
|
|
1716
|
+
/** Present while the device is not booted after the supervisor shut it down for `devices.idleShutdownMinutes`. */
|
|
1717
|
+
idleShutdown?: DeviceIdleShutdownRecord;
|
|
1718
|
+
}
|
|
1719
|
+
interface AndroidDeviceState {
|
|
1720
|
+
name: string | undefined;
|
|
1721
|
+
owned: boolean;
|
|
1722
|
+
physical: boolean;
|
|
1723
|
+
serial?: string | null;
|
|
1724
|
+
state?: AndroidRuntimeFacts["state"];
|
|
1725
|
+
deviceProfile?: string | null;
|
|
1726
|
+
activity?: DeviceActivity;
|
|
1727
|
+
app?: DeviceAppProcess;
|
|
1728
|
+
appPresence?: AppPresence;
|
|
1729
|
+
/** The AVD's folder, for an owned emulator once measured. */
|
|
1730
|
+
disk?: DiskMeasure;
|
|
1731
|
+
/** Present while the emulator is not running after the supervisor shut it down for `devices.idleShutdownMinutes`. */
|
|
1732
|
+
idleShutdown?: DeviceIdleShutdownRecord;
|
|
1733
|
+
}
|
|
1734
|
+
interface EnvironmentState {
|
|
1735
|
+
slots?: {
|
|
1736
|
+
slot: string;
|
|
1737
|
+
ios: SimulatorState | null | undefined;
|
|
1738
|
+
android: AndroidDeviceState | null | undefined;
|
|
1739
|
+
}[];
|
|
1740
|
+
path: string;
|
|
1741
|
+
/** Statically detected app platforms; always set by status, empty when none are detected. */
|
|
1742
|
+
platforms?: string[];
|
|
1743
|
+
live: boolean;
|
|
1744
|
+
phase?: WorkspacePhase;
|
|
1745
|
+
/** When the warm started (`warming`) or finished (`ready`); null for `live` and `idle`. */
|
|
1746
|
+
phaseSince?: string | null;
|
|
1747
|
+
/** Whether stim-server may record this workspace's device screens, from `recording.enabled`. */
|
|
1748
|
+
recording?: {
|
|
1749
|
+
enabled: boolean;
|
|
1750
|
+
};
|
|
1751
|
+
/** Where the workspace is, from `workspaceStage`; `stim status --json` always sets it. */
|
|
1752
|
+
stage?: WorkspaceStage;
|
|
1753
|
+
/** The step a `warming` workspace's warm is in; absent in every other phase. */
|
|
1754
|
+
warmStep?: WarmStep;
|
|
1755
|
+
/**
|
|
1756
|
+
* The memory this workspace's processes use, as `memorySource` says: the sum of its `machine` owners' `memoryMb`
|
|
1757
|
+
* when status read their footprints, or else a fixed estimate per booted simulator, detected emulator, running
|
|
1758
|
+
* Metro and running Chrome. `capacity.committedMb` sums it.
|
|
1759
|
+
*/
|
|
1760
|
+
memoryMb: number;
|
|
1761
|
+
/** How `memoryMb` was obtained; absent from payloads written before it existed, which carry the estimate. */
|
|
1762
|
+
memorySource?: Exclude<MemorySource, "rss">;
|
|
1763
|
+
warnings: string[];
|
|
1764
|
+
issues: StatusIssue[];
|
|
1765
|
+
ios?: SimulatorState | null;
|
|
1766
|
+
android?: AndroidDeviceState | null;
|
|
1767
|
+
metro?: {
|
|
1768
|
+
port: number;
|
|
1769
|
+
running: boolean;
|
|
1770
|
+
pid: number | null;
|
|
1771
|
+
tunnel?: {
|
|
1772
|
+
provider: Exclude<TunnelMode, "auto" | "off" | "expo">;
|
|
1773
|
+
url: string;
|
|
1774
|
+
};
|
|
1775
|
+
idleStop?: IdleStopRecord;
|
|
1776
|
+
lastStop?: MetroLastStop;
|
|
1777
|
+
/** The other process that answers Metro on `port`; `cwd` is null when its directory could not be read. */
|
|
1778
|
+
heldBy?: {
|
|
1779
|
+
pid: number;
|
|
1780
|
+
cwd: string | null;
|
|
1781
|
+
};
|
|
1782
|
+
/** Absent when the Metro log holds no bundle request. */
|
|
1783
|
+
bundle?: MetroBundleState;
|
|
1784
|
+
} | null;
|
|
1785
|
+
web?: WebBrowserState | null;
|
|
1786
|
+
macos?: MacosAppState | null;
|
|
1787
|
+
supervisor?: {
|
|
1788
|
+
pid: number | null;
|
|
1789
|
+
mode: string | null;
|
|
1790
|
+
startedAt: string | null;
|
|
1791
|
+
healthy: boolean;
|
|
1792
|
+
} | null;
|
|
1793
|
+
logs?: {
|
|
1794
|
+
dir: string;
|
|
1795
|
+
errorsSinceMarker: number;
|
|
1796
|
+
} | null;
|
|
1797
|
+
agentDevice?: {
|
|
1798
|
+
stateDir: string;
|
|
1799
|
+
};
|
|
1800
|
+
worktree?: WorktreeFacts | null;
|
|
1801
|
+
remoteDevices?: RemoteDeviceState[];
|
|
1802
|
+
/** The physical devices this workspace leases, in every slot; absent when it leases none. */
|
|
1803
|
+
physicalDevices?: PhysicalDeviceState[];
|
|
1804
|
+
build?: BuildReport | null;
|
|
1805
|
+
lastBuilds?: Partial<Record<StatsPlatform, LastBuildReport>>;
|
|
1806
|
+
/** Each platform's recent runs, newest first, at most `BUILD_HISTORY_LIMIT` each. */
|
|
1807
|
+
builds?: Partial<Record<StatsPlatform, BuildHistoryEntry[]>>;
|
|
1808
|
+
disk?: EnvironmentDisk;
|
|
1809
|
+
/** The coding-agent sessions working in the environment, most recently active first; absent when none. */
|
|
1810
|
+
agents?: AgentSession[];
|
|
1811
|
+
/** The agent sessions that stopped running here in the last 3 days, most recently ended first; absent when none. */
|
|
1812
|
+
endedAgents?: EndedAgentSession[];
|
|
1813
|
+
}
|
|
1814
|
+
/** `committedMb` sums the environments' `memoryMb`; `overCapacity` is that sum over 60% of `totalMemoryMb`. */
|
|
1815
|
+
interface StatusCapacity {
|
|
1816
|
+
liveCount: number;
|
|
1817
|
+
committedMb: number;
|
|
1818
|
+
totalMemoryMb: number;
|
|
1819
|
+
overCapacity: boolean;
|
|
1820
|
+
}
|
|
1821
|
+
interface DeviceLeaseState {
|
|
1822
|
+
slot?: string;
|
|
1823
|
+
path: string;
|
|
1824
|
+
platform: string;
|
|
1825
|
+
id: string | null;
|
|
1826
|
+
deviceName: string | null;
|
|
1827
|
+
holder: string | null;
|
|
1828
|
+
grantedAt: string | null;
|
|
1829
|
+
expiresAt: string | null;
|
|
1830
|
+
mine: boolean;
|
|
1831
|
+
expired: boolean;
|
|
1832
|
+
parsed: boolean;
|
|
1833
|
+
}
|
|
1834
|
+
/**
|
|
1835
|
+
* Where a memory figure comes from. `footprint` is each process's physical footprint, which Activity Monitor's Memory
|
|
1836
|
+
* column shows. `rss` sums resident set sizes, which count pages shared between processes once per process, so a
|
|
1837
|
+
* simulator reports well above its footprint; the machine owners fall back to it when the footprint helper cannot be
|
|
1838
|
+
* built. `estimate` is a fixed amount per running thing, which an environment reports whenever it has no footprint.
|
|
1839
|
+
*/
|
|
1840
|
+
declare const MEMORY_SOURCES: readonly ["footprint", "rss", "estimate"];
|
|
1841
|
+
type MemorySource = (typeof MEMORY_SOURCES)[number];
|
|
1842
|
+
/** Every kind of process owner the status machine section reports. */
|
|
1843
|
+
declare const MACHINE_OWNER_KINDS: readonly ["simulator", "emulator", "metro", "build", "browser", "macos", "server", "shared"];
|
|
1844
|
+
type MachineOwnerKind = (typeof MACHINE_OWNER_KINDS)[number];
|
|
1845
|
+
/**
|
|
1846
|
+
* One thing using this Mac's CPU and memory now. Each process is counted in exactly one owner: the one whose root
|
|
1847
|
+
* process is its nearest ancestor. `workspace` and `slot` (absent for the default slot) name the workspace a
|
|
1848
|
+
* simulator, emulator, Metro, build or Chrome belongs to; a device no workspace records has a null workspace, and
|
|
1849
|
+
* machine-wide processes are `shared`. `id` is the simulator's UDID, the emulator's AVD name, Metro's port as text,
|
|
1850
|
+
* the build's platform, or null. `owned` is true only for what Stim started and stops: a workspace's owned device,
|
|
1851
|
+
* Metro, build or Chrome. `cpuPercent` is `ps` %CPU summed over the owner's processes, where 100 is one core.
|
|
1852
|
+
* `residentMb` sums their resident set sizes; pages shared between processes count once per process, so a
|
|
1853
|
+
* simulator, whose processes all map the runtime's shared libraries, reports well above its physical footprint.
|
|
1854
|
+
* `memoryMb` sums their physical footprints when `MachineUsageState.memorySource` is `footprint`, taking the resident
|
|
1855
|
+
* size of a process the footprint helper could not read, and equals `residentMb` when it is `rss`.
|
|
1856
|
+
*/
|
|
1857
|
+
interface MachineOwner {
|
|
1858
|
+
kind: MachineOwnerKind;
|
|
1859
|
+
name: string;
|
|
1860
|
+
workspace: string | null;
|
|
1861
|
+
slot?: string;
|
|
1862
|
+
id: string | null;
|
|
1863
|
+
owned: boolean;
|
|
1864
|
+
cpuPercent: number;
|
|
1865
|
+
residentMb: number;
|
|
1866
|
+
memoryMb: number;
|
|
1867
|
+
processes: number;
|
|
1868
|
+
}
|
|
1869
|
+
/** Where this machine's CPU and memory go, from one pass over the host process table. */
|
|
1870
|
+
interface MachineUsageState {
|
|
1871
|
+
memorySource: Exclude<MemorySource, "estimate">;
|
|
1872
|
+
owners: MachineOwner[];
|
|
1873
|
+
}
|
|
1874
|
+
/** The payload `stim status --json` prints, and `status --watch --json` prints on each change. */
|
|
1875
|
+
interface StatusPayload {
|
|
1876
|
+
maintenance?: MaintenanceStatus;
|
|
1877
|
+
archived?: ArchivedWorkspace[];
|
|
1878
|
+
archivedUsage?: ArchivedUsage;
|
|
1879
|
+
environments: (EnvironmentState & {
|
|
1880
|
+
labelOnly?: true;
|
|
1881
|
+
})[];
|
|
1882
|
+
capacity: StatusCapacity;
|
|
1883
|
+
deviceLeases: DeviceLeaseState[];
|
|
1884
|
+
unprovisionedWorktrees: WorktreeFacts[];
|
|
1885
|
+
simctlAvailable: boolean;
|
|
1886
|
+
/** Null when nothing runs that status attributes, so it read no process table, or when the table was unreadable. */
|
|
1887
|
+
machine: MachineUsageState | null;
|
|
1888
|
+
}
|
|
1889
|
+
//#endregion
|
|
1890
|
+
//#region state/status-derived.d.ts
|
|
1891
|
+
declare function withGitChip(worktree: WorktreeFacts): WorktreeFacts;
|
|
1892
|
+
/** The environment with the conclusions clients draw from it: `stage`, `appPresence`, `gitChip` and `cause`. */
|
|
1893
|
+
declare function withDerivedFacts<T extends EnvironmentState>(env: T): T;
|
|
1894
|
+
//#endregion
|
|
1895
|
+
//#region state/status-measures.d.ts
|
|
1896
|
+
/** The file that caches `path`'s measured size, one file per folder. */
|
|
1897
|
+
declare function diskUsageCacheFile(path: string): string;
|
|
1898
|
+
/** The file that caches the pull request of the worktree at `path`. */
|
|
1899
|
+
declare function pullRequestCacheFile(path: string): string;
|
|
1900
|
+
/** One file of the disk-usage or pull-request cache. */
|
|
1901
|
+
interface StatusCacheEntry {
|
|
1902
|
+
kind: "disk-usage" | "pull-request";
|
|
1903
|
+
file: string;
|
|
1904
|
+
/** The folder or worktree the file caches, or null when the file does not record one under its own name. */
|
|
1905
|
+
path: string | null;
|
|
1906
|
+
bytes: number;
|
|
1907
|
+
}
|
|
1908
|
+
/** Every finished file in the disk-usage and pull-request caches; a file being written is not listed. */
|
|
1909
|
+
declare function listStatusCacheEntries(): StatusCacheEntry[];
|
|
1910
|
+
/** A worktree's cached pull request lookup: the branch and HEAD it was looked up for, and when. */
|
|
1911
|
+
interface PullRequestCacheEntry {
|
|
1912
|
+
path: string;
|
|
1913
|
+
branch: string;
|
|
1914
|
+
head: string;
|
|
1915
|
+
checkedAt: string;
|
|
1916
|
+
pullRequest: WorktreePullRequest | null;
|
|
1917
|
+
}
|
|
1918
|
+
/** The cached pull request lookup of the worktree at `path`, or null before one succeeded. */
|
|
1919
|
+
declare function readPullRequestCache(path: string): PullRequestCacheEntry | null;
|
|
1920
|
+
/** The cached size of the folder at `path`, or null before it was measured. */
|
|
1921
|
+
declare function readDiskUsage(path: string): DiskMeasure | null;
|
|
1922
|
+
/** The running build's tool detail its process last wrote, when the file belongs to the build with `claimId`. */
|
|
1923
|
+
declare function readBuildDetail(root: string, claimId: string): BuildDetail | null;
|
|
1924
|
+
/** The coding-agent sessions `status --watch` last found running on this Mac, and when it looked. */
|
|
1925
|
+
interface AgentSessionsCache {
|
|
1926
|
+
discoveredAt: string;
|
|
1927
|
+
sessions: AgentSession[];
|
|
1928
|
+
}
|
|
1929
|
+
/** An agent session as Stim wrote it to its cache or workspace state, or null when it is not one. */
|
|
1930
|
+
declare function agentSessionOf(value: unknown): AgentSession | null;
|
|
1931
|
+
/** How long a workspace keeps an agent session after it stopped running. */
|
|
1932
|
+
declare const ENDED_AGENT_RETENTION_MS: number;
|
|
1933
|
+
/** An ended agent session as Stim wrote it, or null when it is not one. */
|
|
1934
|
+
declare function endedAgentSessionOf(value: unknown): EndedAgentSession | null;
|
|
1935
|
+
/** The workspace's agent sessions that ended within `ENDED_AGENT_RETENTION_MS` of `now`, most recently ended first. */
|
|
1936
|
+
declare function readEndedAgentSessions(root: string, now: number): EndedAgentSession[];
|
|
1937
|
+
/** The agent sessions `status --watch` last cached, or null before it cached any. */
|
|
1938
|
+
declare function readAgentSessionsCache(): AgentSessionsCache | null;
|
|
1939
|
+
//#endregion
|
|
1940
|
+
//#region state/stim-build.d.ts
|
|
1941
|
+
/**
|
|
1942
|
+
* A digest of Stim's built code: the first 16 hex characters of the sha256 over the sorted `*.mjs` names and
|
|
1943
|
+
* bytes of a `stim` `dist` directory. A client and a build machine offload only when both compute the same one.
|
|
1944
|
+
*/
|
|
1945
|
+
declare function stimBuildDigest(dir: string): string | null;
|
|
1946
|
+
//#endregion
|
|
1947
|
+
//#region state/viewers.d.ts
|
|
1948
|
+
interface ViewedDevice {
|
|
1949
|
+
platform: "ios" | "android";
|
|
1950
|
+
/** The simulator UDID or the emulator serial. */
|
|
1951
|
+
id: string;
|
|
1952
|
+
}
|
|
1953
|
+
/** A stim-server's viewer record: the devices it streams frames of, and the server's process identity. */
|
|
1954
|
+
interface DeviceViewersRecord {
|
|
1955
|
+
pid: number;
|
|
1956
|
+
processToken: string;
|
|
1957
|
+
devices: ViewedDevice[];
|
|
1958
|
+
}
|
|
1959
|
+
/**
|
|
1960
|
+
* The devices a running stim-server streams frames of. A record whose server is not proven to be the same live
|
|
1961
|
+
* process counts for nothing.
|
|
1962
|
+
*/
|
|
1963
|
+
declare function readViewedDevices(dir?: string): ViewedDevice[];
|
|
1964
|
+
//#endregion
|
|
1965
|
+
//#region state/stats.d.ts
|
|
1966
|
+
declare const STATS_VERSION = 1;
|
|
1967
|
+
interface StatsBucket {
|
|
1968
|
+
runs: number;
|
|
1969
|
+
failed: number;
|
|
1970
|
+
hits: number;
|
|
1971
|
+
misses: number;
|
|
1972
|
+
coldRuns: number;
|
|
1973
|
+
coldRunMs: number;
|
|
1974
|
+
hitRuns: number;
|
|
1975
|
+
hitRunMs: number;
|
|
1976
|
+
timeSavedMs: number;
|
|
1977
|
+
firstRunAt: string;
|
|
1978
|
+
lastRunAt: string;
|
|
1979
|
+
lastColdBuildMs?: number;
|
|
1980
|
+
lastPodsMs?: number;
|
|
1981
|
+
offloadedRuns?: number;
|
|
1982
|
+
offloadedRunMs?: number;
|
|
1983
|
+
lastOffloadHost?: string;
|
|
1984
|
+
}
|
|
1985
|
+
type StatsScope = Partial<Record<StatsPlatform, StatsBucket>>;
|
|
1986
|
+
interface RunSample {
|
|
1987
|
+
at: string;
|
|
1988
|
+
durationMs: number;
|
|
1989
|
+
phases: Record<string, number>;
|
|
1990
|
+
/** Whether the run created, adopted or cold-booted its device; absent on samples recorded before the tag. */
|
|
1991
|
+
deviceSetup?: boolean;
|
|
1992
|
+
}
|
|
1993
|
+
type RunHistory = Partial<Record<StatsPlatform, Partial<Record<RunOutcomeKind, RunSample[]>>>>;
|
|
1994
|
+
/** Where a compiling build ran: here, on a build machine, or here after offloading it failed. */
|
|
1995
|
+
declare const PLACEMENT_DECISIONS: readonly ["here", "offloaded", "fell-back"];
|
|
1996
|
+
type PlacementDecision = (typeof PLACEMENT_DECISIONS)[number];
|
|
1997
|
+
interface StatsPlacement {
|
|
1998
|
+
at: string;
|
|
1999
|
+
project: string;
|
|
2000
|
+
platform: StatsPlatform;
|
|
2001
|
+
decision: PlacementDecision;
|
|
2002
|
+
reason: string;
|
|
2003
|
+
machine?: string;
|
|
2004
|
+
buildMs?: number;
|
|
2005
|
+
slotWaitMs?: number;
|
|
2006
|
+
/** The project's last cold build here before this run. */
|
|
2007
|
+
localEstimateMs?: number;
|
|
2008
|
+
failed?: true;
|
|
2009
|
+
}
|
|
2010
|
+
interface BuildMachineTotals {
|
|
2011
|
+
offloaded: number;
|
|
2012
|
+
offloadedMs: number;
|
|
2013
|
+
/** Sum of local estimate minus offloaded build time, over offloaded builds that had an estimate; can be negative. */
|
|
2014
|
+
savedMs: number;
|
|
2015
|
+
fallbacks: number;
|
|
2016
|
+
lastOffloadAt?: string;
|
|
2017
|
+
lastFallbackAt?: string;
|
|
2018
|
+
}
|
|
2019
|
+
interface StatsRecord {
|
|
2020
|
+
version: number;
|
|
2021
|
+
machine: StatsScope;
|
|
2022
|
+
projects: Record<string, StatsScope>;
|
|
2023
|
+
history?: Record<string, RunHistory>;
|
|
2024
|
+
placements?: StatsPlacement[];
|
|
2025
|
+
buildMachines?: Record<string, BuildMachineTotals>;
|
|
2026
|
+
}
|
|
2027
|
+
/**
|
|
2028
|
+
* The two phase durations a run reads back to size its own heartbeat: the
|
|
2029
|
+
* project's last cold build and its last `pod install`, in milliseconds.
|
|
2030
|
+
*/
|
|
2031
|
+
interface RunEstimates {
|
|
2032
|
+
coldBuildMs: number | null;
|
|
2033
|
+
podsMs: number | null;
|
|
2034
|
+
}
|
|
2035
|
+
interface ReadStatsResult {
|
|
2036
|
+
record: StatsRecord | null;
|
|
2037
|
+
note: string | null;
|
|
2038
|
+
}
|
|
2039
|
+
declare const HISTORY_LIMIT = 10;
|
|
2040
|
+
declare function statsProjectKey({ root, commonDir, repoRoot }: {
|
|
2041
|
+
root: string;
|
|
2042
|
+
commonDir: string | null;
|
|
2043
|
+
repoRoot: string | null;
|
|
2044
|
+
}): string;
|
|
2045
|
+
interface BuildMachineDay {
|
|
2046
|
+
offloaded: number;
|
|
2047
|
+
offloadedMs: number;
|
|
2048
|
+
savedMs: number;
|
|
2049
|
+
fallbacks: number;
|
|
2050
|
+
}
|
|
2051
|
+
interface OffloadSummary {
|
|
2052
|
+
today: {
|
|
2053
|
+
here: number;
|
|
2054
|
+
offloaded: number;
|
|
2055
|
+
fellBack: number;
|
|
2056
|
+
};
|
|
2057
|
+
machines: Record<string, {
|
|
2058
|
+
today: BuildMachineDay;
|
|
2059
|
+
total: BuildMachineTotals;
|
|
2060
|
+
}>;
|
|
2061
|
+
/** Newest first. */
|
|
2062
|
+
placements: StatsPlacement[];
|
|
2063
|
+
}
|
|
2064
|
+
/** Placement counts for the local calendar day of `now`, per-machine totals, and the retained placements. */
|
|
2065
|
+
declare function offloadSummary(record: StatsRecord | null, now: number): OffloadSummary;
|
|
2066
|
+
declare function trimSamples(samples: RunSample[]): RunSample[];
|
|
2067
|
+
declare function readStats(): ReadStatsResult;
|
|
2068
|
+
declare function readRunEstimates({ projectKey, platform, read }: {
|
|
2069
|
+
projectKey: string | null;
|
|
2070
|
+
platform: StatsPlatform;
|
|
2071
|
+
read?: () => ReadStatsResult;
|
|
2072
|
+
}): RunEstimates;
|
|
2073
|
+
declare function wholePhases(phases: unknown): Record<string, number>;
|
|
2074
|
+
declare function decodeStats(text: string): {
|
|
2075
|
+
record: StatsRecord | null;
|
|
2076
|
+
newerVersion: number | null;
|
|
2077
|
+
};
|
|
2078
|
+
interface StatsReport {
|
|
2079
|
+
version: number;
|
|
2080
|
+
project: ({
|
|
2081
|
+
key: string;
|
|
2082
|
+
} & StatsReport["machine"]) | null;
|
|
2083
|
+
machine: {
|
|
2084
|
+
ios: StatsBucket | null;
|
|
2085
|
+
android: StatsBucket | null;
|
|
2086
|
+
};
|
|
2087
|
+
offload: OffloadSummary;
|
|
2088
|
+
agentDevice: AgentDeviceUsage | null;
|
|
2089
|
+
swiftpmCache: SwiftpmCacheUsage | null;
|
|
2090
|
+
}
|
|
2091
|
+
declare function readStatsReport(key: string | null, now: number): {
|
|
2092
|
+
report: StatsReport;
|
|
2093
|
+
note: string | null;
|
|
2094
|
+
};
|
|
2095
|
+
declare function findProjectRoot(startDir: string): string | null;
|
|
2096
|
+
//#endregion
|
|
2097
|
+
//#region state/device-host-machines.d.ts
|
|
2098
|
+
/** A separately approved hosting machine, pinned before sending its device token. */
|
|
2099
|
+
interface DeviceHostMachineCredential {
|
|
2100
|
+
machine: string;
|
|
2101
|
+
nodeId: string;
|
|
2102
|
+
dnsName: string;
|
|
2103
|
+
deviceId: string;
|
|
2104
|
+
deviceToken: string;
|
|
2105
|
+
state: "pending" | "approved";
|
|
2106
|
+
requestedAt: string;
|
|
2107
|
+
ticketHash?: string;
|
|
2108
|
+
}
|
|
2109
|
+
/** An absent store is empty; unreadable or malformed credentials refuse access without discarding pins. */
|
|
2110
|
+
declare function readDeviceHostMachines(): DeviceHostMachineCredential[];
|
|
2111
|
+
//#endregion
|
|
2112
|
+
//#region state/hosted-metro.d.ts
|
|
2113
|
+
declare const HOSTED_METRO_REQUESTS_KEY = "hostedMetroRequests";
|
|
2114
|
+
declare const HOSTED_METRO_GATEWAYS_KEY = "hostedMetroGateways";
|
|
2115
|
+
/** Private supervisor request, keyed by hosted session; never part of a public payload. */
|
|
2116
|
+
interface HostedMetroRequest {
|
|
2117
|
+
id: string;
|
|
2118
|
+
machine: string;
|
|
2119
|
+
address: string;
|
|
2120
|
+
peer: string;
|
|
2121
|
+
secret: string;
|
|
2122
|
+
}
|
|
2123
|
+
interface HostedMetroGateway {
|
|
2124
|
+
id: string;
|
|
2125
|
+
processToken: string;
|
|
2126
|
+
port?: number;
|
|
2127
|
+
error?: string;
|
|
2128
|
+
}
|
|
2129
|
+
declare function hostedMetroRequests(state: WorkspaceState | null): Record<string, HostedMetroRequest>;
|
|
2130
|
+
declare function hostedMetroGateways(state: WorkspaceState | null): Record<string, HostedMetroGateway>;
|
|
2131
|
+
//#endregion
|
|
2132
|
+
//#region state/tailnet.d.ts
|
|
2133
|
+
declare const TAILNET_MACHINE_PATTERN: string;
|
|
2134
|
+
interface TailnetPeer {
|
|
2135
|
+
nodeId: string;
|
|
2136
|
+
dnsName: string;
|
|
2137
|
+
/** A tailnet address of the node; WireGuard delivers packets to it only from that node. */
|
|
2138
|
+
address: string;
|
|
2139
|
+
}
|
|
2140
|
+
declare function parseMachine(entry: string): {
|
|
2141
|
+
name: string;
|
|
2142
|
+
port: number;
|
|
2143
|
+
} | null;
|
|
2144
|
+
/**
|
|
2145
|
+
* The one peer in `tailscale status --json` whose MagicDNS name is `name` or starts with `name.`. `ID` there is
|
|
2146
|
+
* the node's StableID, the same value `tailscale whois` reports as `Node.StableID`.
|
|
2147
|
+
*/
|
|
2148
|
+
declare function findPeer(status: unknown, name: string): TailnetPeer | "missing" | "ambiguous";
|
|
2149
|
+
interface Endpoint {
|
|
2150
|
+
url: string;
|
|
2151
|
+
servername: string;
|
|
2152
|
+
host: string;
|
|
2153
|
+
}
|
|
2154
|
+
/**
|
|
2155
|
+
* Connects to the pinned node's own tailnet address rather than resolving its name, so the socket reaches the
|
|
2156
|
+
* node whose ID was just checked. `tailscale serve` still needs the MagicDNS name for TLS (SNI and certificate)
|
|
2157
|
+
* and for its Host routing.
|
|
2158
|
+
*/
|
|
2159
|
+
declare function endpoint(peer: TailnetPeer, port: number): Endpoint;
|
|
2160
|
+
/**
|
|
2161
|
+
* The endpoint of a paired machine's pinned node, or why Stim does not connect to it. The name must still
|
|
2162
|
+
* resolve to exactly the pinned node; the token is never sent anywhere else.
|
|
2163
|
+
*/
|
|
2164
|
+
declare function pinnedEndpoint(credential: {
|
|
2165
|
+
machine: string;
|
|
2166
|
+
nodeId: string;
|
|
2167
|
+
}, current: unknown): Endpoint | string;
|
|
2168
|
+
//#endregion
|
|
2169
|
+
//#region state/hosted-logs.d.ts
|
|
2170
|
+
type HostedLogsCursor = Record<string, number>;
|
|
2171
|
+
interface HostedLogsPage {
|
|
2172
|
+
records: NdjsonRecord[];
|
|
2173
|
+
cursor: HostedLogsCursor;
|
|
2174
|
+
/** Last completed iOS collection window, for detecting catch-up progress independently of file offsets. */
|
|
2175
|
+
checkpoint?: number;
|
|
2176
|
+
/** True when the budget ended this page before the end of the logs; ask again with `cursor`. */
|
|
2177
|
+
more: boolean;
|
|
2178
|
+
}
|
|
2179
|
+
declare const HOSTED_LOGS_PAGE_BYTES: number;
|
|
2180
|
+
declare const HOSTED_LOGS_FIRST_BYTES: number;
|
|
2181
|
+
declare function parseHostedLogsCursor(value: unknown): HostedLogsCursor | null;
|
|
2182
|
+
declare function hostedMacosLogsDir(home: string): string | null;
|
|
2183
|
+
declare const hostedIosLogsDir: (home: string) => string;
|
|
2184
|
+
/** The completed query window and overlap digests, or null for a missing, malformed or unreadable checkpoint. */
|
|
2185
|
+
declare function readHostedIosLogsCheckpoint(home: string): {
|
|
2186
|
+
until: number;
|
|
2187
|
+
boundary: string[];
|
|
2188
|
+
windowMs?: number;
|
|
2189
|
+
} | null;
|
|
2190
|
+
/**
|
|
2191
|
+
* The records in `dir` after `cursor`, in file order. A file without a cursor entry starts at most
|
|
2192
|
+
* {@link HOSTED_LOGS_FIRST_BYTES} before its end. A file that shrank since the cursor was taken was rotated: the end of
|
|
2193
|
+
* its previous generation is read first, and only as much of it as the page budget allows.
|
|
2194
|
+
*/
|
|
2195
|
+
declare function readLogsSince(dir: string, cursor: HostedLogsCursor): HostedLogsPage;
|
|
2196
|
+
//#endregion
|
|
2197
|
+
//#region state/agent-device.d.ts
|
|
2198
|
+
declare function agentDeviceStateDirs(home?: string): string[];
|
|
2199
|
+
//#endregion
|
|
2200
|
+
//#region state/setup-journal.d.ts
|
|
2201
|
+
type SetupCapability = "build" | "device-host";
|
|
2202
|
+
interface SetupJournal {
|
|
2203
|
+
v: 1;
|
|
2204
|
+
client: {
|
|
2205
|
+
nodeId: string;
|
|
2206
|
+
};
|
|
2207
|
+
expiresAt: string;
|
|
2208
|
+
capabilities: SetupCapability[];
|
|
2209
|
+
steps: {
|
|
2210
|
+
id: string;
|
|
2211
|
+
state: "pending" | "running" | "ok" | "skipped" | "failed";
|
|
2212
|
+
title: string;
|
|
2213
|
+
detail?: string;
|
|
2214
|
+
fix?: string;
|
|
2215
|
+
}[];
|
|
2216
|
+
granted: {
|
|
2217
|
+
capability: SetupCapability;
|
|
2218
|
+
id: string;
|
|
2219
|
+
}[];
|
|
2220
|
+
done: boolean;
|
|
2221
|
+
exit?: number;
|
|
2222
|
+
}
|
|
2223
|
+
declare function parseSetupJournal(value: unknown): SetupJournal | null;
|
|
2224
|
+
declare function readSetupJournal(hash: string): SetupJournal | null;
|
|
2225
|
+
declare function isJournalExpired(journal: SetupJournal, now?: number): boolean;
|
|
2226
|
+
declare function isSetupJournalPrunable(journal: SetupJournal, now: number): boolean;
|
|
2227
|
+
//#endregion
|
|
2228
|
+
export { trimSamples as $, createdDevicesLock as $a, validHostedAppBlob as $i, MaintenanceAction as $n, queryLogs as $o, HostedDevicePhase as $r, AgentDeviceUsageRoots as $s, EnvironmentDisk as $t, DeviceHostMachineCredential as A, RECORDING_CAP_BYTES as Aa, HostedMacosDevice as Ai, WebBrowserState as An, workspaceEndedAgentsFile as Ao, READY_PHASE_MS as Ar, withConfigLock as As, AndroidRuntimeFacts as At, STATS_VERSION as B, listSegments as Ba, HostedAppDelivery as Bi, MacosProcess as Bn, NATIVE_CRASH_LOG_PREFIX as Bo, readDevServerStopRequest as Br, SupervisorRecord as Bs, BuildMissChange as Bt, pinnedEndpoint as C, acceptsShape as Ca, HOSTED_MACOS_APP_SLOTS as Ci, StatusIssue as Cn, sharedPods as Co, DevServerStopRecord as Cr, getConcurrencyLimits as Cs, APP_PROCESS_STATES as Ct, HostedMetroRequest as D, isSensitiveReference as Da, HostedAgentLease as Di, WORKSPACE_PHASES as Dn, workspaceAgentDeviceDir as Do, IdleStopRecord as Dr, getRepoSettings as Ds, AgentSession as Dt, HostedMetroGateway as E, isLayeredSetting as Ea, HostedAgentGrant as Ei, WEB_PAGE_STATES as En, supervisorPidFile as Eo, IDLE_STOP_KEY as Er, getProjectSettings as Es, ActivityRecencyBasis as Et, PLACEMENT_DECISIONS as F, RecordingPlatform as Fa, parseHostedAgentGrant as Fi, WorktreeGit as Fn, workspaceMetadataFile as Fo, buildDiagnostics as Fr, PlatformRecords as Fs, BuildCause as Ft, StatsScope as G, agentSessionsCacheFile as Ga, hostedAppAttempt as Gi, ArchivedBytes as Gn, bundleMarkerPlatform as Go, readWorkspaceAgent as Gr, buildSlotsDir as Gs, BuildReport as Gt, StatsPlacement as H, recordedBytes as Ha, HostedAppOffer as Hi, parseMacosRecord as Hn, advanceTail as Ho, readIdleStop as Hr, readBuildMachines as Hs, BuildPhase as Ht, ReadStatsResult as I, capDrops as Ia, parseHostedMacosChoice as Ii, WorktreePullRequest as In, workspaceRecordingsDir as Io, lastUseFrom as Ir, ProjectRecord as Is, BuildDetail as It, offloadSummary as J, archiveRoot as Ja, parseHostedAppOffer as Ji, archiveEnabled as Jn, followLogs as Jo, HostedAndroidChoice as Jr, tryAcquireBuildSlotClaim as Js, DeviceActivity as Jt, decodeStats as K, archiveDir as Ka, hostedAppBlobs as Ki, ArchivedUsage as Kn, compileGrep as Ko, readWorkspaceState as Kr, machineCapacity as Ks, BuildResult as Kt, RunEstimates as L, closedSegmentName as La, parseHostedMacosDevice as Li, MacosAppRecord as Ln, workspaceStateFile as Lo, parseMissReason as Lr, RepoRecord as Ls, BuildDiagnostic as Lt, BuildMachineTotals as M, RECORDING_PLATFORMS as Ma, hostedMacosAppSlot as Mi, WorkspacePhase as Mn, workspaceGradleBuild as Mo, WORKSPACE_AGENT_KEY as Mr, Config as Ms, BUILD_PHASES as Mt, HISTORY_LIMIT as N, RecordedDevice as Na, hostedMacosBundleId as Ni, WorkspaceStage as Nn, workspaceLogErrorIndex as No, WarmRecord as Nr, DeviceRecord as Ns, BUILD_RESULTS as Nt, hostedMetroGateways as O, settingDefinition as Oa, HostedAppLaunch as Oi, WORKSPACE_STAGE_KINDS as On, workspaceBuildDetailFile as Oo, LAST_BUILD_KEYS as Or, isPathPrefix as Os, AgentTool as Ot, OffloadSummary as P, RecordedSegment as Pa, parseHostedAgentAccess as Pi, WorktreeFacts as Pn, workspaceLogsDir as Po, WorkspaceState as Pr, DoctorRunRecord as Ps, BuildCacheHit as Pt, statsProjectKey as Q, createdDevicesFile as Qa, validHostedAppArguments as Qi, readArchives as Qn, queryJsonLogs as Qo, HostedDeviceOfferRequest as Qr, AgentDeviceUsage as Qs, EndedAgentSession as Qt, RunHistory as R, footageDrops as Ra, parseHostedMacosPlacement as Ri, MacosAppState as Rn, workspaceStateLock as Ro, readBuildHistory as Rr, SettingsObject as Rs, BuildHistoryEntry as Rt, parseMachine as S, WebViewport as Sa, HOSTED_AGENT_DRIVERS as Si, StatusCapacity as Sn, sharedGradle as So, DEV_SERVER_STOP_REQUEST_KEY as Sr, findProjectByMetroPort as Ss, AGENT_TOOLS as St, HOSTED_METRO_REQUESTS_KEY as T, expectedShape as Ta, HostedAgentDriverName as Ti, StatusPayload as Tn, supervisorLogFile as To, DeviceIdleShutdownRecord as Tr, getProjectSetting as Ts, ActivityDriver as Tt, StatsRecord as U, recordingDeviceName as Ua, HostedAppRecord as Ui, readHostedMacosApp as Un, attachExpoErrorContext as Uo, readLastBuilds as Ur, MachineCapacity as Us, BuildPlacement as Ut, StatsBucket as V, openSegmentName as Va, HostedAppFile as Vi, macosAppState as Vn, QueryCriteria as Vo, readDeviceIdleShutdowns as Vr, BuildMachineCredential as Vs, BuildMissReason as Vt, StatsReport as W, recordingEnabled as Wa, hostedAppArea as Wi, readMacosRecord as Wn, buildCriteria as Wo, readWarmRecord as Wr, buildSlotPath as Ws, BuildPlanPayload as Wt, readStats as X, buildMachinesLock as Xa, readHostedAppMetadata as Xi, linkReplacedArchives as Xn, markerWindow as Xo, HostedDevice as Xr, readSwiftpmCacheUsage as Xs, DeviceLeaseState as Xt, readRunEstimates as Y, buildMachinesFile as Ya, readHostedApp as Yi, archivedUsage as Yn, logFiles as Yo, HostedAndroidDevice as Yr, SwiftpmCacheUsage as Ys, DeviceAppProcess as Yt, readStatsReport as Z, configLockPath as Za, rememberHostedAppBlobRename as Zi, readArchive as Zn, parseSince as Zo, HostedDeviceOffer as Zr, swiftpmCacheUsageFile as Zs, DiskMeasure as Zt, Endpoint as _, SettingType as _a, parseHostedPlatformDevice as _i, RemoteDeviceState as _n, pullRequestCacheDir as _o, parseHostedIosPlacement as _r, withStateReadCache as _s, readEndedAgentSessions as _t, parseSetupJournal as a, ANDROID_PCH_CHOICES as aa, createAgentActionReader as ac, HostedIosDevice as ai, MEMORY_SOURCES as an, easMachineStateRoot as ao, MaintenanceRecord as ar, countErrorEntries as as, AgentSessionsCache as at, endpoint as b, TunnelMode as ba, readHostedDeviceLedger as bi, SimulatorState as bn, sharedCcache as bo, BUILD_HISTORY_LIMIT as br, configCorruptRepair as bs, withGitChip as bt, HOSTED_LOGS_FIRST_BYTES as c, OffloadMode as ca, SOURCES as cc, deviceHostArea as ci, MachineUsageState as cn, emulatorLogFile as co, MaintenanceStatus as cr, EasSessionClaim as cs, StatusCacheEntry as ct, HostedLogsPage as d, SETTINGS as da, parseNdjsonText as dc, hostedDeviceId as di, NATIVE_BUILD_STEPS as dn, maintenanceAttemptFile as do, readMaintenanceState as dr, readEasSessionLedger as ds, endedAgentSessionOf as dt, SETTINGS_SCHEMA_FILE as ea, agentDeviceUsageFile as ec, HostedDevicePlatform as ei, EnvironmentState as en, deviceHostMachinesClaims as eo, MaintenanceActionKind as er, readLogRecords as es, wholePhases as et, hostedIosLogsDir as f, SETTING_GROUPS as fa, readNdjsonGenerations as fc, parseHostedAndroidDevice as fi, NativeBuildStep as fn, maintenanceChildLogFile as fo, HostedIosPlacement as fr, validEasSessionClaim as fs, listStatusCacheEntries as ft, readLogsSince as g, SettingScope as ga, parseHostedOfferRequest as gi, PlannedPhase as gn, maintenanceStateFile as go, hostedIosStatus as gr, readStateFile as gs, readDiskUsage as gt, readHostedIosLogsCheckpoint as h, SettingEntry as ha, parseHostedNativeOffer as hi, PhysicalDeviceState as hn, maintenanceRunClaims as ho, hostedIosRecords as hr, readJsonObject as hs, readBuildDetail as ht, isSetupJournalPrunable as i, ANDROID_EMULATOR_APPS as ia, AgentTarget as ic, HostedIosChoice as ii, MACHINE_OWNER_KINDS as in, diskUsageCacheDir as io, MaintenancePressure as ir, tailRead as is, stimBuildDigest as it, readDeviceHostMachines as j, RECORDING_FOOTAGE_MS as ja, HostedMacosPlacement as ji, WebPageState as jn, workspaceEndedAgentsLock as jo, WARM_KEY as jr, ConcurrencyLimits as js, AppPresence as jt, hostedMetroRequests as k, settingValueError as ka, HostedMacosChoice as ki, WarmStep as kn, workspaceDerivedData as ko, MetroLastStop as kr, loadConfig as ks, AndroidDeviceState as kt, HOSTED_LOGS_PAGE_BYTES as l, REMOTE_DEVICE_BACKENDS as la, levelRank as lc, deviceHostRoot as li, MemorySource as ln, getConfigPath as lo, parseMaintenanceState as lr, EasSessionLedgerRead as ls, agentSessionOf as lt, parseHostedLogsCursor as m, SettingDefinition as ma, parseHostedDevice as mi, PhysicalDeviceConnection as mn, maintenanceNdjsonFile as mo, hostedIosPlacements as mr, readJsonFile as ms, readAgentSessionsCache as mt, SetupJournal as n, settingsJsonSchema as na, readAgentDeviceUsageCache as nc, HostedDeviceSelectors as ni, GitChipPart as nn, deviceHostMachinesLock as no, MaintenanceMode as nr, recordMatches as ns, ViewedDevice as nt, readSetupJournal as o, IOS_SIMULATOR_APPS as oa, LEVELS as oc, HostedNativeOffer as oi, MachineOwner as on, easSessionLedgerFile as oo, MaintenanceSize as or, CreatedDevicePlatform as os, ENDED_AGENT_RETENTION_MS as ot, hostedMacosLogsDir as p, SETTING_SCOPES as pa, parseHostedChoice as pi, PHYSICAL_DEVICE_CONNECTIONS as pn, maintenanceDir as po, HostedIosStatus as pr, isJsonObject as ps, pullRequestCacheFile as pt, findProjectRoot as q, archiveLock as qa, parseHostedAppManifest as qi, ArchivedWorkspace as qn, fileSizes as qo, workspaceLastUsed as qr, saturation as qs, ChecksState as qt, isJournalExpired as r, ANDROID_COMPILER_CACHE_CHOICES as ra, AgentActionReaderOptions as rc, HostedDeviceSession as ri, LastBuildReport as rn, deviceViewersDir as ro, MaintenancePass as rr, sortByTs as rs, readViewedDevices as rt, agentDeviceStateDirs as s, OFFLOAD_MODES as sa, NdjsonRecord as sc, assertHostedDeviceLedger as si, MachineOwnerKind as sn, easSessionLedgerLock as so, MaintenanceState as sr, CreatedDevices as ss, PullRequestCacheEntry as st, SetupCapability as t, SETTINGS_SCHEMA_URL as ta, readAgentDeviceUsage as tc, HostedDeviceRequest as ti, GitChip as tn, deviceHostMachinesFile as to, MaintenanceCheck as tr, readLogTimeline as ts, DeviceViewersRecord as tt, HostedLogsCursor as u, RemoteDeviceBackend as ua, parseNdjsonLine as uc, hostedConsolePort as ui, MetroBundleState as un, gitMergeCacheDir as uo, readMaintenanceAttempt as ur, readCreatedDevices as us, diskUsageCacheFile as ut, TAILNET_MACHINE_PATTERN as v, SettingsPayload as va, parseHostedRequest as vi, RunOutcomeKind as vn, serverSetupDir as vo, unreadableHostedIos as vr, allMetroPorts as vs, readPullRequestCache as vt, HOSTED_METRO_GATEWAYS_KEY as w, coerceSettingText as wa, HostedAgentAccess as wi, StatusIssueCode as wn, statsFile as wo, DevServerStopRequest as wr, getProject as ws, ActiveBuildState as wt, findPeer as x, WEB_VIEWPORTS as xa, readHostedSessions as xi, StatsPlatform as xn, sharedCompilationCache as xo, DEVICE_IDLE_SHUTDOWN_KEY as xr, findEnclosingWorktreeRoot as xs, ACTIVITY_RECENCY_BASES as xt, TailnetPeer as y, TUNNEL_MODES as ya, readHostedDevice as yi, STATUS_ISSUE_CODES as yn, setupJournalFile as yo, BUILD_HISTORY_KEY as yr, buildWorkerRoot as ys, withDerivedFacts as yt, RunSample as z, listRecordedDevices as za, HOSTED_APP_CHUNK_BYTES as zi, MacosBuild as zn, ERROR_SOURCES as zo, readDevServerStop as zr, StimConfig as zs, BuildMissCategory as zt };
|