@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/dist/index.d.mts CHANGED
@@ -1,3 +1,4 @@
1
+ import { Server } from "node:net";
1
2
  //#region dir-lock.d.ts
2
3
  interface DirLockOptions {
3
4
  /** @deprecated Occupied locks are never expired. */
@@ -8,6 +9,10 @@ interface DirLockOptions {
8
9
  }
9
10
  declare function withDirLock<T>(lockPath: string, fn: () => T, { waitMs, pollMs, ensureParent }?: DirLockOptions): T;
10
11
  //#endregion
12
+ //#region macos-resources.d.ts
13
+ /** Whether a resource destination is a contained, non-empty path under Contents/Resources. */
14
+ declare function validMacosResourceDestination(value: unknown): value is string;
15
+ //#endregion
11
16
  //#region quoted-path.d.ts
12
17
  /** Quote a path for a shell command Stim prints for a human to copy and run. */
13
18
  declare function quotedPath(path: string): string;
@@ -23,6 +28,39 @@ interface StoreArtifactOptions {
23
28
  }
24
29
  declare function storeArtifact(dest: string, buildPath: string, { runFile, overwrite, writeMetadata, onRenameError }: StoreArtifactOptions): string | null;
25
30
  //#endregion
31
+ //#region compiled-helper.d.ts
32
+ /**
33
+ * Returns `<dir>/<name>-<hash>`, compiling it with `compile` first when it is missing. The hash covers `version` and
34
+ * each input's name and bytes, so a changed source or compiler builds a new helper beside the old one. `compile`
35
+ * writes to a private temporary path that is renamed into place, so concurrent builders never expose a partial file.
36
+ * Pruning is best effort and keeps this helper, the newest previous build, helpers modified in the last ten minutes and running helpers. It runs after a build and on the first call per process.
37
+ */
38
+ declare function compiledHelper({ dir, name, inputs, version, compile }: {
39
+ dir: string;
40
+ name: string;
41
+ inputs: readonly string[];
42
+ version: string;
43
+ compile: (output: string) => Promise<void>;
44
+ }): Promise<string>;
45
+ //#endregion
46
+ //#region metro-bridge.d.ts
47
+ interface MetroBridge {
48
+ server: Server;
49
+ close: () => Promise<void>;
50
+ }
51
+ /** Bind this gateway only to the client's own Tailscale address; `peer` is the pinned worker's literal address. */
52
+ declare function createMetroGateway({ metroPort, peer, secret }: {
53
+ metroPort: number;
54
+ peer: string;
55
+ secret: string;
56
+ }): MetroBridge;
57
+ /** Bind this endpoint only to worker loopback; `peer` comes from the approved client's authenticated connection. */
58
+ declare function createMetroBridge({ gatewayPort, peer, secret }: {
59
+ gatewayPort: number;
60
+ peer: string;
61
+ secret: string;
62
+ }): MetroBridge;
63
+ //#endregion
26
64
  //#region index.d.ts
27
65
  declare function configDir(): string;
28
66
  declare function workspaceSlug(projectRoot: string): string;
@@ -47,12 +85,15 @@ interface BuildRunOptions {
47
85
  variant?: string;
48
86
  abi?: string;
49
87
  allArch?: boolean;
88
+ arch?: string;
50
89
  configuration?: string;
51
90
  scheme?: string;
52
91
  buildConfiguration?: string;
53
92
  isSimulator?: boolean;
54
93
  device?: string | boolean | null;
55
94
  }
95
+ /** The simulator slice a local build compiles for this machine: `arm64` or `x86_64`. */
96
+ declare function hostSimulatorArch(arch?: string): "arm64" | "x86_64";
56
97
  declare function buildCacheKey(platform: string, fingerprintHash: string, options?: unknown): string;
57
98
  interface RegisterOptions {
58
99
  dir: string;
@@ -80,4 +121,4 @@ declare function readCacheManifest(file: string): CacheManifest;
80
121
  declare function updateCacheManifest(file: string, mutate: (caches: Array<Record<string, unknown>>) => Array<Record<string, unknown>>): CacheManifest;
81
122
  declare function registerCache({ dir, name, prune, note, entriesDepth, layout, replaces }: RegisterOptions): void;
82
123
  //#endregion
83
- export { BuildRunOptions, CacheManifest, CacheRegistrationMatch, type DirLockOptions, LOG_ROTATE_BYTES, METRO_NAMED_CACHE_LAYOUT, RegisterOptions, STORE_ROOT_TAG, type StoreArtifactOptions, artifactIn, buildCacheKey, buildCacheRoot, cacheManifestLockPath, cacheNameSegment, cachePathSetting, configDir, metroCacheRoot, quotedPath, readCacheManifest, registerCache, resolveArtifact, rotateLog, rotatedLogPath, sharedStoreRoot, storeArtifact, tagSharedStore, updateCacheManifest, withDirLock, workspaceId, workspaceLogDir, workspaceName, workspaceSlug, workspaceStateDir };
124
+ export { BuildRunOptions, CacheManifest, CacheRegistrationMatch, type DirLockOptions, LOG_ROTATE_BYTES, METRO_NAMED_CACHE_LAYOUT, type MetroBridge, RegisterOptions, STORE_ROOT_TAG, type StoreArtifactOptions, artifactIn, buildCacheKey, buildCacheRoot, cacheManifestLockPath, cacheNameSegment, cachePathSetting, compiledHelper, configDir, createMetroBridge, createMetroGateway, hostSimulatorArch, metroCacheRoot, quotedPath, readCacheManifest, registerCache, resolveArtifact, rotateLog, rotatedLogPath, sharedStoreRoot, storeArtifact, tagSharedStore, updateCacheManifest, validMacosResourceDestination, withDirLock, workspaceId, workspaceLogDir, workspaceName, workspaceSlug, workspaceStateDir };
package/dist/index.mjs CHANGED
@@ -1,3 +1,3 @@
1
1
  import { S as quotedPath } from "./ownership-claim-O31Y5iIb.mjs";
2
- import { C as artifactIn, E as withDirLock, S as workspaceStateDir, T as storeArtifact, _ as updateCacheManifest, a as buildCacheRoot, b as workspaceName, c as cachePathSetting, d as readCacheManifest, f as registerCache, g as tagSharedStore, h as sharedStoreRoot, i as buildCacheKey, l as configDir, m as rotatedLogPath, n as METRO_NAMED_CACHE_LAYOUT, o as cacheManifestLockPath, p as rotateLog, r as STORE_ROOT_TAG, s as cacheNameSegment, t as LOG_ROTATE_BYTES, u as metroCacheRoot, v as workspaceId, w as resolveArtifact, x as workspaceSlug, y as workspaceLogDir } from "./core-CmZJEFj_.mjs";
3
- export { LOG_ROTATE_BYTES, METRO_NAMED_CACHE_LAYOUT, STORE_ROOT_TAG, artifactIn, buildCacheKey, buildCacheRoot, cacheManifestLockPath, cacheNameSegment, cachePathSetting, configDir, metroCacheRoot, quotedPath, readCacheManifest, registerCache, resolveArtifact, rotateLog, rotatedLogPath, sharedStoreRoot, storeArtifact, tagSharedStore, updateCacheManifest, withDirLock, workspaceId, workspaceLogDir, workspaceName, workspaceSlug, workspaceStateDir };
2
+ import { A as validMacosResourceDestination, C as workspaceStateDir, D as artifactIn, E as compiledHelper, O as resolveArtifact, S as workspaceSlug, T as createMetroGateway, _ as tagSharedStore, a as buildCacheRoot, b as workspaceLogDir, c as cachePathSetting, d as metroCacheRoot, f as readCacheManifest, g as sharedStoreRoot, h as rotatedLogPath, i as buildCacheKey, j as withDirLock, k as storeArtifact, l as configDir, m as rotateLog, n as METRO_NAMED_CACHE_LAYOUT, o as cacheManifestLockPath, p as registerCache, r as STORE_ROOT_TAG, s as cacheNameSegment, t as LOG_ROTATE_BYTES, u as hostSimulatorArch, v as updateCacheManifest, w as createMetroBridge, x as workspaceName, y as workspaceId } from "./core-DWOUn9xp.mjs";
3
+ export { LOG_ROTATE_BYTES, METRO_NAMED_CACHE_LAYOUT, STORE_ROOT_TAG, artifactIn, buildCacheKey, buildCacheRoot, cacheManifestLockPath, cacheNameSegment, cachePathSetting, compiledHelper, configDir, createMetroBridge, createMetroGateway, hostSimulatorArch, metroCacheRoot, quotedPath, readCacheManifest, registerCache, resolveArtifact, rotateLog, rotatedLogPath, sharedStoreRoot, storeArtifact, tagSharedStore, updateCacheManifest, validMacosResourceDestination, withDirLock, workspaceId, workspaceLogDir, workspaceName, workspaceSlug, workspaceStateDir };
@@ -0,0 +1,308 @@
1
+ //#region oversight.d.ts
2
+ /** What a notification is about; each can be switched off on its own. */
3
+ declare const OVERSIGHT_CATEGORIES: readonly ["started", "stuck", "looping", "finished", "machine", "control", "attention"];
4
+ type OversightCategory = (typeof OVERSIGHT_CATEGORIES)[number];
5
+ declare const DEFAULT_STUCK_MINUTES = 15;
6
+ interface Activity {
7
+ state: string;
8
+ driver?: {
9
+ tool: string;
10
+ since: string | null;
11
+ };
12
+ lastActivityAt?: string;
13
+ recent?: Partial<Record<string, string>>;
14
+ }
15
+ interface Device {
16
+ name?: string | null;
17
+ state?: string;
18
+ physical?: boolean;
19
+ activity?: Activity;
20
+ }
21
+ interface Build {
22
+ platform: string;
23
+ status: string;
24
+ result?: string;
25
+ startedAt: string;
26
+ finishedAt: string | null;
27
+ errorCode?: string;
28
+ diagnostics?: {
29
+ file: string | null;
30
+ line: number | null;
31
+ }[];
32
+ }
33
+ /** The part of a `stim status --json` environment the rules read. */
34
+ interface OversightEnvironment {
35
+ path: string;
36
+ live: boolean;
37
+ phase?: string;
38
+ ios?: Device | null;
39
+ android?: Device | null;
40
+ slots?: {
41
+ slot: string;
42
+ ios?: Device | null;
43
+ android?: Device | null;
44
+ }[];
45
+ worktree?: {
46
+ path: string;
47
+ branch?: string;
48
+ repository?: string;
49
+ git?: {
50
+ mergedInto: string | null;
51
+ } | null;
52
+ } | null;
53
+ build?: {
54
+ state: string;
55
+ startedAt: string;
56
+ platform?: string;
57
+ } | null;
58
+ issues?: {
59
+ code: string;
60
+ severity: string;
61
+ message: string;
62
+ remedy: string;
63
+ slot?: string;
64
+ }[];
65
+ physicalDevices?: {
66
+ platform: string;
67
+ slot: string;
68
+ id: string;
69
+ name: string | null;
70
+ model: string | null;
71
+ lease: {
72
+ expiresAt: string;
73
+ };
74
+ }[];
75
+ remoteDevices?: {
76
+ sessionId: string;
77
+ startedAt: string | null;
78
+ }[];
79
+ lastBuilds?: {
80
+ ios?: Build;
81
+ android?: Build;
82
+ };
83
+ builds?: {
84
+ ios?: Build[];
85
+ android?: Build[];
86
+ };
87
+ logs?: {
88
+ errorsSinceMarker: number;
89
+ } | null;
90
+ web?: {
91
+ running: boolean;
92
+ activity?: Activity;
93
+ } | null;
94
+ }
95
+ interface OversightStatus {
96
+ environments: OversightEnvironment[];
97
+ unprovisionedWorktrees?: {
98
+ path: string;
99
+ repository?: string;
100
+ }[];
101
+ }
102
+ /** A workspace's pull request, from GitHub. */
103
+ interface OversightPullRequest {
104
+ number: number;
105
+ state: "open" | "merged" | "closed";
106
+ draft: boolean;
107
+ url: string;
108
+ }
109
+ interface OversightInput {
110
+ machine: string;
111
+ /** Null when the machine's status is not current, so its workspaces are left as they were. */
112
+ status: OversightStatus | null;
113
+ volumes: {
114
+ freeBytes: number;
115
+ }[] | null;
116
+ memoryPressure: string | null;
117
+ /** The phone's connection to the machine; null where it is not known, as on the machine itself. */
118
+ link: "open" | "offline" | "refused" | "unpaired" | null;
119
+ /** Each workspace's pull request by path, null when it has none; a missing path was not looked up. */
120
+ pullRequests: Record<string, OversightPullRequest | null>;
121
+ /** `grantedAt` of the device leases stim-server holds for phones, so a person controlling a device is no agent. */
122
+ ownLeases: readonly string[];
123
+ }
124
+ interface OversightPrefs {
125
+ categories: readonly OversightCategory[];
126
+ stuckMinutes: number;
127
+ /** Whether it is quiet hours now: nothing notifies, and what still holds afterwards notifies then. */
128
+ quiet: boolean;
129
+ }
130
+ type OversightTarget = {
131
+ kind: "machine";
132
+ } | {
133
+ kind: "workspace";
134
+ path: string;
135
+ } | {
136
+ kind: "device";
137
+ path: string;
138
+ platform: "ios" | "android" | "web" | "macos";
139
+ slot: string;
140
+ } | {
141
+ kind: "build";
142
+ path: string;
143
+ platform: "ios" | "android";
144
+ } | {
145
+ kind: "url";
146
+ path: string;
147
+ url: string;
148
+ };
149
+ interface OversightNotification {
150
+ /** Stable for the workspace or machine and category, so a later notification replaces the earlier one. */
151
+ id: string;
152
+ category: OversightCategory;
153
+ title: string;
154
+ body: string;
155
+ /** Delivered without sound or banner interruption. */
156
+ quiet: boolean;
157
+ /** Groups notifications in the notification list; null leaves them ungrouped. */
158
+ thread: string | null;
159
+ target: OversightTarget;
160
+ }
161
+ interface Loop {
162
+ signature: string;
163
+ notified: boolean;
164
+ }
165
+ interface WorkspaceEntry {
166
+ seenAt: number;
167
+ warmed: boolean;
168
+ drove: boolean;
169
+ drivenAt: number | null;
170
+ driveNotified: boolean;
171
+ errors: number;
172
+ errorsAt: number | null;
173
+ stuckAt: number | null;
174
+ finished: boolean;
175
+ /** Ids of the `attention` items already notified, so each notifies once per episode. */
176
+ attention: string[];
177
+ loops: {
178
+ ios?: Loop;
179
+ android?: Loop;
180
+ };
181
+ pr: {
182
+ number: number;
183
+ ready: boolean;
184
+ merged: boolean;
185
+ } | null | undefined;
186
+ mergedInto: string | null;
187
+ mergeNotified: boolean;
188
+ }
189
+ interface Held {
190
+ since: number;
191
+ notified: boolean;
192
+ }
193
+ interface OversightState {
194
+ workspaces: Record<string, WorkspaceEntry>;
195
+ disk?: Held;
196
+ memory?: Held;
197
+ /** Whether memory pressure was ever read, so the first reading records what is true without notifying. */
198
+ memoryKnown?: boolean;
199
+ link?: Held & {
200
+ kind: string;
201
+ };
202
+ }
203
+ interface OversightResult {
204
+ state: OversightState;
205
+ notifications: OversightNotification[];
206
+ /** When a timed rule may become due while nothing else changes. */
207
+ wakeAt: number | null;
208
+ }
209
+ /** The name home shows for a workspace: its branch, else its checkout's folder. */
210
+ declare function oversightTitle(env: OversightEnvironment, status: OversightStatus): string;
211
+ type Platform = "ios" | "android" | "web";
212
+ interface SlotDevice {
213
+ platform: Platform;
214
+ slot: string;
215
+ model: string;
216
+ modelLabel?: "ios-simulator" | "android-device" | "android-emulator" | "chrome";
217
+ running: boolean;
218
+ activity: Activity | undefined;
219
+ }
220
+ /**
221
+ * The notifications a machine owes since `previous`, the state the last call returned. Null `previous` records
222
+ * what is already true without notifying, so a restart or a new registration stays quiet. Each workspace and
223
+ * machine problem notifies once per episode, under one id per category, so a later episode replaces it.
224
+ * `awakeSince` restarts the offline settle time, for a checker that was not running.
225
+ */
226
+ declare function oversee(previous: OversightState | null, input: OversightInput, prefs: OversightPrefs, now: number, awakeSince?: number): OversightResult;
227
+ /** Whether `minuteOfDay` falls in quiet hours from `start` to `end`, minutes after midnight; they may span midnight. */
228
+ declare function inQuietHours(quietHours: {
229
+ start: number;
230
+ end: number;
231
+ } | null, minuteOfDay: number): boolean;
232
+ /** What only a person can act on or decide. */
233
+ interface NeedsAttentionItem {
234
+ /** Stable while the problem lasts; `stuck`, `looping` and `machine` items use the oversight notification ids. */
235
+ id: string;
236
+ /** The oversight notification category that covers the item; `attention` is for the rest. */
237
+ category: "attention" | "stuck" | "looping" | "machine";
238
+ severity: "error" | "warning";
239
+ /** The workspace path; null for the machine. */
240
+ workspace: string | null;
241
+ body: string;
242
+ /** A `stim` command to run from `workspace`, or null when the fix is outside Stim. */
243
+ remedy: string | null;
244
+ }
245
+ interface NeedsAttentionInput {
246
+ environments: OversightEnvironment[];
247
+ /** Each volume Stim uses; null when not measured. */
248
+ volumes: {
249
+ freeBytes: number;
250
+ }[] | null;
251
+ now: number;
252
+ stuckMinutes: number;
253
+ easSessionMinutes: number;
254
+ /** `grantedAt` of the device leases stim-server holds for phones, so a person controlling a device is no agent. */
255
+ ownLeases?: readonly string[];
256
+ }
257
+ /** Selected attention facts for rendering a body without repeating the rule that selected the item. */
258
+ type AttentionMessage = {
259
+ kind: "issue";
260
+ slot?: string;
261
+ message: string;
262
+ } | {
263
+ kind: "signing";
264
+ platform: string;
265
+ code: string;
266
+ } | {
267
+ kind: "diagnostic-loop";
268
+ platform: string;
269
+ count: number;
270
+ file: string;
271
+ line: number;
272
+ language: string | undefined;
273
+ } | {
274
+ kind: "launch-loop";
275
+ platform: string;
276
+ count: number;
277
+ } | {
278
+ kind: "build-loop";
279
+ platform: string;
280
+ count: number;
281
+ errorCode: string | undefined;
282
+ } | {
283
+ kind: "lease";
284
+ leased: string;
285
+ } | {
286
+ kind: "eas";
287
+ minutes: number;
288
+ } | {
289
+ kind: "stuck";
290
+ minutes: number;
291
+ green: "ios" | "android" | null;
292
+ model: string;
293
+ modelLabel: SlotDevice["modelLabel"];
294
+ } | {
295
+ kind: "disk";
296
+ freeBytes: number;
297
+ };
298
+ /** Formats only an attention item's body; identity, remedy and ordering stay with the policy. */
299
+ type AttentionFormatter = (message: AttentionMessage) => string;
300
+ /** A failed run older than this on an idle workspace is history, not a problem. */
301
+ declare const STALE_MS: number;
302
+ /**
303
+ * The items, errors first, then the machine's, then live workspaces' before idle ones', each in status order. Log
304
+ * errors, a single failed run, and issues an agent's next `stim` command repairs are left out: agents handle them.
305
+ */
306
+ declare function needsAttention(input: NeedsAttentionInput, format?: AttentionFormatter): NeedsAttentionItem[];
307
+ //#endregion
308
+ export { AttentionFormatter, AttentionMessage, DEFAULT_STUCK_MINUTES, NeedsAttentionInput, NeedsAttentionItem, OVERSIGHT_CATEGORIES, OversightCategory, OversightEnvironment, OversightInput, OversightNotification, OversightPrefs, OversightPullRequest, OversightResult, OversightState, OversightStatus, OversightTarget, STALE_MS, inQuietHours, needsAttention, oversee, oversightTitle };