stim 1.11.0 → 1.12.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.
Files changed (71) hide show
  1. package/dist/{activity-BtG4Va9l.mjs → activity-CCZJs__P.mjs} +4 -3
  2. package/dist/{android-C4zG2Tuc.mjs → android-75Sk2rIR.mjs} +25 -8
  3. package/dist/{android-C1q4l523.mjs → android-B7X-8H7h.mjs} +75 -32
  4. package/dist/{android-BA2i_KAV.mjs → android-BQiKJYK0.mjs} +1 -1
  5. package/dist/{android-cas-DfJkwCXW.mjs → android-cas-DzLPXiEn.mjs} +7 -7
  6. package/dist/{app-install-DHut6JnV.mjs → app-install-CsZi0SAT.mjs} +1 -1
  7. package/dist/{workspaces-COD2xCz-.mjs → budget-DbzW5VTD.mjs} +641 -32
  8. package/dist/{build-plan-CeAYgKAx.mjs → build-plan-CqntbR7b.mjs} +120 -35
  9. package/dist/{build-progress-CDwogz6R.mjs → build-progress-h60GPV27.mjs} +3 -3
  10. package/dist/{cache-manifest-Pubfp8wV.mjs → cache-manifest-DWPF4RKJ.mjs} +1 -1
  11. package/dist/cache-manifest.mjs +1 -1
  12. package/dist/cli.mjs +16 -16
  13. package/dist/collector-run.mjs +4 -4
  14. package/dist/{command-output-D5z2_bcF.mjs → command-output-BWCj5Vh-.mjs} +1 -1
  15. package/dist/{config-BEq0Qw_a.mjs → config-0jCcMM0E.mjs} +10 -1
  16. package/dist/{dependency-state-r9UesA9a.mjs → dependency-state-DNN0yfx6.mjs} +1 -1
  17. package/dist/{deps-OF7CD5Dx.mjs → deps-CO-_7UOm.mjs} +2 -2
  18. package/dist/{device-BwH2iI3O.mjs → device-9r9xRYDa.mjs} +7 -7
  19. package/dist/{device-lease-D83nqeMX.mjs → device-lease-B9LAXIUH.mjs} +5 -5
  20. package/dist/{device-pool-DHj7cdPy.mjs → device-pool-BoezJd-c.mjs} +4 -4
  21. package/dist/{device-remote-BQZSnnmE.mjs → device-remote-C0_o-tJH.mjs} +254 -579
  22. package/dist/{doctor-D8QdMRMf.mjs → doctor-LfDlbR-N.mjs} +19 -18
  23. package/dist/{error-diagnostics-UYFSQwRy.mjs → error-diagnostics-CCxjn31V.mjs} +7 -7
  24. package/dist/{gc-COZteyiq.mjs → gc-C4nQFcTX.mjs} +203 -39
  25. package/dist/{guide-NDvTmMi-.mjs → guide-BPBlh9ML.mjs} +189 -38
  26. package/dist/{guide-status-CWvti2Lg.mjs → guide-status-i9ogHt4v.mjs} +2 -2
  27. package/dist/{idle-NETbeNiQ.mjs → idle-S3tFZ53_.mjs} +7 -7
  28. package/dist/{in-use-DVhlSoyn.mjs → in-use-D9XYEgFD.mjs} +7 -7
  29. package/dist/{ios-CQLKpNfr.mjs → ios-CDzWL1mj.mjs} +30 -29
  30. package/dist/{ios-DArbmwer.mjs → ios-CZWOHTTc.mjs} +23 -19
  31. package/dist/{ios-device-CwDZo0X4.mjs → ios-device-D9cLxVr5.mjs} +1 -1
  32. package/dist/{launch-verify-CuPDGXdr.mjs → launch-verify-B2oR_kFN.mjs} +2 -2
  33. package/dist/{logs-B44a1UeU.mjs → logs-SzuYudOj.mjs} +6 -6
  34. package/dist/{merge-state-DDxS-XIZ.mjs → merge-state-ytFQCeh4.mjs} +38 -8
  35. package/dist/{metro-BWLOJ_Wr.mjs → metro-Dzo30hvJ.mjs} +1 -1
  36. package/dist/{named-ports-Dc7neAlc.mjs → named-ports-Dn1o61D9.mjs} +3 -3
  37. package/dist/{ownership-BiojdtAp.mjs → ownership-B8d4kXBx.mjs} +49 -16
  38. package/dist/{ownership-D2xbLVoz.mjs → ownership-Dqnrjrio.mjs} +2 -2
  39. package/dist/{ports-DwBaRFJs.mjs → ports-Dp_QTwTC.mjs} +3 -3
  40. package/dist/{project-BXZzOABt.mjs → project-B8rbutVC.mjs} +4 -72
  41. package/dist/{reload-By9Dwsrt.mjs → reload-nocmx8KB.mjs} +9 -9
  42. package/dist/remote-cache-BRsRZru5.mjs +526 -0
  43. package/dist/{server-bare-D_RK1RCj.mjs → server-bare-Gn3ssSdK.mjs} +1 -1
  44. package/dist/{server-expo-o6H5gcBc.mjs → server-expo-CeT1nIIk.mjs} +2 -2
  45. package/dist/server-expo-eWi9Coof.mjs +2 -0
  46. package/dist/{settings-B5oFZEri.mjs → settings-BlyDn2Oz.mjs} +2 -2
  47. package/dist/{settings-C0ugALSC.mjs → settings-bE-Gu3Ti.mjs} +23 -11
  48. package/dist/settings.schema.json +22 -2
  49. package/dist/{simslim-CIR3IYJO.mjs → simslim-COtEEP7x.mjs} +6 -5
  50. package/dist/{slot-launch-rggO1Esw.mjs → slot-launch-DIACGEfH.mjs} +4 -4
  51. package/dist/{spawn-claims-BJwXTMPt.mjs → spawn-claims-PT8aQpCa.mjs} +1 -1
  52. package/dist/{start-i8zc9VmS.mjs → start-BFstVBlx.mjs} +1 -1
  53. package/dist/{start-BSsf2tUs.mjs → start-BboE1HIS.mjs} +108 -17
  54. package/dist/{state-WGdIbi_d.mjs → state-DcDgzfu3.mjs} +15 -3
  55. package/dist/{stats-BAgJaLA4.mjs → stats-D8rUTPHd.mjs} +1 -1
  56. package/dist/{stats-DBYJ5bxL.mjs → stats-DiCtmluY.mjs} +4 -4
  57. package/dist/{status-Q-WDEGCB.mjs → status-BUASYyy_.mjs} +73 -28
  58. package/dist/{status-CitcBRsC.mjs → status-DI9Tjo7T.mjs} +41 -29
  59. package/dist/stim-desktop-D0xhpZt8.mjs +29 -0
  60. package/dist/{stop-rst5mL14.mjs → stop-BI7QY76M.mjs} +2 -2
  61. package/dist/{stop-DIhrvu0B.mjs → stop-Bn6v-GvS.mjs} +23 -16
  62. package/dist/supervisor-run.mjs +11 -11
  63. package/dist/{workspace-process-lock-Cx74RSDZ.mjs → workspace-process-lock-BvvJTfo_.mjs} +2 -2
  64. package/dist/{worktree-DhxDTK44.mjs → worktree-B5sTRskL.mjs} +1 -1
  65. package/dist/{worktree-KOjMX3zA.mjs → worktree-ChDL5fO1.mjs} +17 -16
  66. package/dist/{worktree-BlizKDpZ.mjs → worktree-DeBQSVtR.mjs} +3 -1
  67. package/dist/{xcode-B5SPD--o.mjs → xcode-BzplpQzc.mjs} +7 -7
  68. package/package.json +5 -5
  69. package/dist/budget-De3P2rq_.mjs +0 -620
  70. package/dist/native-run-D7yB_AsB.mjs +0 -143
  71. package/dist/server-expo-B-CCUJZj.mjs +0 -2
@@ -1,8 +1,8 @@
1
1
  import { t as getExecutor } from "./exec-DK8KaVHK.mjs";
2
2
  import { o as readNdjsonGenerations } from "./ndjson-CDY9IkVC.mjs";
3
- import { s as isAppLaunchError } from "./command-output-D5z2_bcF.mjs";
3
+ import { s as isAppLaunchError } from "./command-output-BWCj5Vh-.mjs";
4
4
  import { t as DEV_MENU_LAUNCH_ARGS } from "./ios-device-BiOsSVzd.mjs";
5
- import { d as deviceShellArg, n as ANDROID_DISABLE_AUTO_LAUNCH_EXTRA, o as androidAppProcess } from "./app-install-DHut6JnV.mjs";
5
+ import { d as deviceShellArg, n as ANDROID_DISABLE_AUTO_LAUNCH_EXTRA, o as androidAppProcess } from "./app-install-CsZi0SAT.mjs";
6
6
  import { join } from "node:path";
7
7
  //#region src/engine/app-readiness.ts
8
8
  const APP_READINESS_TIMEOUT_MS = 3e4;
@@ -1,10 +1,10 @@
1
- import { D as process_identity_exports, H as projectDeviceSlots, V as parseDeviceSlotOption, g as loadConfig$1, h as isPathPrefix } from "./config-BEq0Qw_a.mjs";
1
+ import { H as parseDeviceSlotOption, O as process_identity_exports, U as projectDeviceSlots, _ as loadConfig$1, g as isPathPrefix } from "./config-0jCcMM0E.mjs";
2
2
  import { n as SOURCES, t as LEVELS } from "./ndjson-CDY9IkVC.mjs";
3
- import { j as workspaceLogsDir, m as readWorkspaceState$1 } from "./metro-BWLOJ_Wr.mjs";
4
- import { o as findProjectRoot } from "./project-BXZzOABt.mjs";
5
- import { f as refuseNoProject, v as launchErrorPreview } from "./command-output-D5z2_bcF.mjs";
6
- import { i as readAgentDeviceRecords, t as agentDeviceLiveness } from "./activity-BtG4Va9l.mjs";
7
- import { i as captureWorkspaceCrashes, t as errorDiagnostics } from "./error-diagnostics-UYFSQwRy.mjs";
3
+ import { j as workspaceLogsDir, m as readWorkspaceState$1 } from "./metro-Dzo30hvJ.mjs";
4
+ import { i as findProjectRoot } from "./project-B8rbutVC.mjs";
5
+ import { f as refuseNoProject, v as launchErrorPreview } from "./command-output-BWCj5Vh-.mjs";
6
+ import { i as readAgentDeviceRecords, t as agentDeviceLiveness } from "./activity-CCZJs__P.mjs";
7
+ import { i as captureWorkspaceCrashes, t as errorDiagnostics } from "./error-diagnostics-CCxjn31V.mjs";
8
8
  import { closeSync, fstatSync, openSync, readFileSync, readSync, readdirSync, realpathSync, statSync } from "node:fs";
9
9
  import { buildCriteria, compileGrep, fileSizes, followLogs, logFiles, parseSince, queryLogs, readLogRecords, recordMatches, sortByTs } from "@stim-cli/core/state";
10
10
  import { join, relative, resolve, sep } from "node:path";
@@ -117,7 +117,9 @@ function committedOn(path, branch, head) {
117
117
  });
118
118
  }
119
119
  /**
120
- * Whether the worktree's HEAD is merged into `target`. The signals, all local git:
120
+ * Whether the worktree's HEAD is merged into `target`, and when: `mergedAt` is the committer date, in epoch
121
+ * milliseconds, of the commit on `target` that brought the work in, the latest one for a rebase merge.
122
+ * The signals, all local git:
121
123
  * - HEAD is an ancestor of the default branch, off its first-parent line, and the branch's reflog shows a commit made
122
124
  * on it that HEAD contains, so a merge commit brought the branch's own work in. A branch with no commit of its own
123
125
  * is not merged.
@@ -147,7 +149,21 @@ function mergeState(path, { ref, name }, { timeoutMs = GIT_TIMEOUT_MS } = {}) {
147
149
  timeoutMs,
148
150
  untrimmed: true
149
151
  });
150
- const patchIds = (text) => text ? git(["patch-id", "--verbatim"], text).split("\n").flatMap((line) => line.split(" ")[0] || []) : [];
152
+ const patchIdCommits = (text) => new Map(text ? git(["patch-id", "--verbatim"], text).split("\n").flatMap((line) => {
153
+ const [id, commit] = line.split(" ");
154
+ return id && commit ? [[id, commit]] : [];
155
+ }) : []);
156
+ const patchIds = (text) => [...patchIdCommits(text).keys()];
157
+ const committedAt = (commits) => {
158
+ const times = commits.length ? git([
159
+ "show",
160
+ "-s",
161
+ "--format=%ct",
162
+ ...commits
163
+ ]).split("\n").map(Number) : [];
164
+ if (!times.length || !times.every(Number.isFinite)) throw new Error(`no committer date for ${commits.join(" ")}`);
165
+ return Math.max(...times) * 1e3;
166
+ };
151
167
  const diffOptions = ["--no-color", "--no-ext-diff"];
152
168
  const noOwnCommits = notMerged(`no commits of its own beyond ${name}`);
153
169
  try {
@@ -169,11 +185,24 @@ function mergeState(path, { ref, name }, { timeoutMs = GIT_TIMEOUT_MS } = {}) {
169
185
  "--parents",
170
186
  `${head}..${ref}`
171
187
  ]).split("\n").some((line) => line.split(" ")[1] === head) || !committedOn(path, branch, head)) return noOwnCommits;
188
+ const descendants = new Set(git([
189
+ "rev-list",
190
+ "--ancestry-path",
191
+ `${head}..${ref}`
192
+ ]).split("\n"));
193
+ const landed = git([
194
+ "rev-list",
195
+ "--first-parent",
196
+ "--reverse",
197
+ `${head}..${ref}`
198
+ ]).split("\n").find((commit) => descendants.has(commit));
199
+ if (!landed) throw new Error(`no commit on ${name} merges ${head}`);
172
200
  return {
173
201
  merged: true,
174
202
  into: name,
175
203
  head,
176
- coversUnpushed: false
204
+ coversUnpushed: false,
205
+ mergedAt: committedAt([landed])
177
206
  };
178
207
  }
179
208
  const files = git([
@@ -195,12 +224,13 @@ function mergeState(path, { ref, name }, { timeoutMs = GIT_TIMEOUT_MS } = {}) {
195
224
  "--",
196
225
  ...pathspec
197
226
  ]);
198
- const upstream = new Set(patchIds(log(`${base}..${ref}`, files)));
199
- const patchEquivalent = () => ({
227
+ const upstream = patchIdCommits(log(`${base}..${ref}`, files));
228
+ const patchEquivalent = (ids) => ({
200
229
  merged: true,
201
230
  into: name,
202
231
  head,
203
- coversUnpushed: upstreamGone(path, branch)
232
+ coversUnpushed: upstreamGone(path, branch),
233
+ mergedAt: committedAt(ids.map((id) => upstream.get(id)))
204
234
  });
205
235
  const squash = patchIds(patch([
206
236
  "diff",
@@ -208,14 +238,14 @@ function mergeState(path, { ref, name }, { timeoutMs = GIT_TIMEOUT_MS } = {}) {
208
238
  base,
209
239
  head
210
240
  ]));
211
- if (squash.length === 1 && upstream.has(squash[0])) return patchEquivalent();
241
+ if (squash.length === 1 && upstream.has(squash[0])) return patchEquivalent(squash);
212
242
  if (!git([
213
243
  "rev-list",
214
244
  "--merges",
215
245
  `${base}..${head}`
216
246
  ])) {
217
247
  const own = patchIds(log(`${base}..${head}`));
218
- if (own.length && own.every((id) => upstream.has(id))) return patchEquivalent();
248
+ if (own.length && own.every((id) => upstream.has(id))) return patchEquivalent(own);
219
249
  }
220
250
  return notMerged(`not merged into ${name}`);
221
251
  } catch (error) {
@@ -1,4 +1,4 @@
1
- import { D as process_identity_exports, M as isOnMountedVolume, N as listMountedVolumes, g as loadConfig$1, n as allMetroPorts, r as claimMetroPort, y as releaseMetroPort } from "./config-BEq0Qw_a.mjs";
1
+ import { N as isOnMountedVolume, O as process_identity_exports, P as listMountedVolumes, _ as loadConfig$1, b as releaseMetroPort, n as allMetroPorts, r as claimMetroPort } from "./config-0jCcMM0E.mjs";
2
2
  import { t as getExecutor } from "./exec-DK8KaVHK.mjs";
3
3
  import { existsSync, mkdirSync, renameSync, rmSync, writeFileSync } from "node:fs";
4
4
  import { existsSync as existsSync$1, readlinkSync, realpathSync as realpathSync$1 } from "fs";
@@ -1,7 +1,7 @@
1
- import { D as process_identity_exports, T as withConfigLock, f as getProject, g as loadConfig, s as ensureConfig, u as getConfigDir, x as saveConfig } from "./config-BEq0Qw_a.mjs";
1
+ import { E as withConfigLock, O as process_identity_exports, S as saveConfig, _ as loadConfig, c as ensureConfig, d as getConfigDir, p as getProject } from "./config-0jCcMM0E.mjs";
2
2
  import { t as getExecutor } from "./exec-DK8KaVHK.mjs";
3
- import { c as signalProcessTree, n as listeningPids, u as isPortFree } from "./metro-BWLOJ_Wr.mjs";
4
- import { t as withWorkspaceProcessLock } from "./workspace-process-lock-Cx74RSDZ.mjs";
3
+ import { c as signalProcessTree, n as listeningPids, u as isPortFree } from "./metro-Dzo30hvJ.mjs";
4
+ import { t as withWorkspaceProcessLock } from "./workspace-process-lock-BvvJTfo_.mjs";
5
5
  import { realpathSync } from "node:fs";
6
6
  //#region src/named-ports.ts
7
7
  const FIRST_PORT = 8900;
@@ -1,14 +1,16 @@
1
- import { D as process_identity_exports, H as projectDeviceSlots, I as assignSlotDevice, O as acquireAvdClaim, T as withConfigLock, U as removeSlotDevice, d as getConfigPath, g as loadConfig, k as ownership_claim_exports, s as ensureConfig, u as getConfigDir, x as saveConfig, z as deviceSlotPlatforms } from "./config-BEq0Qw_a.mjs";
1
+ import { A as ownership_claim_exports, B as deviceSlotPlatforms, E as withConfigLock, L as assignSlotDevice, O as process_identity_exports, S as saveConfig, U as projectDeviceSlots, W as removeSlotDevice, _ as loadConfig, c as ensureConfig, d as getConfigDir, f as getConfigPath, k as acquireAvdClaim } from "./config-0jCcMM0E.mjs";
2
2
  import { t as getExecutor } from "./exec-DK8KaVHK.mjs";
3
- import { c as signalProcessTree, i as pidExists } from "./metro-BWLOJ_Wr.mjs";
4
- import { r as workspaceProcessLockPath, t as withWorkspaceProcessLock } from "./workspace-process-lock-Cx74RSDZ.mjs";
3
+ import { c as signalProcessTree, i as pidExists } from "./metro-Dzo30hvJ.mjs";
4
+ import { r as workspaceProcessLockPath, t as withWorkspaceProcessLock } from "./workspace-process-lock-BvvJTfo_.mjs";
5
5
  import { t as createLineReader } from "./process-output-Fpl8PYi8.mjs";
6
- import { l as phaseLine } from "./command-output-D5z2_bcF.mjs";
7
- import { G as sleepSync, H as resolveOwnedAvdSerial, J as wipeAvdUserData, K as waitForAndroidEmulatorShutdown, L as ownedAvdSystemImage, N as ownedAvdDirectory, P as ownedAvdMatchesConfiguration, W as shutdownAndroidEmulator, _ as deleteAvd, d as avdPathExists, k as listOrphanedAvdDirectories, p as avdStorageRoots, u as assertOwnedAvdStopped, w as isStimOwnedAvdName } from "./android-C4zG2Tuc.mjs";
8
- import { S as resolveOwnedIosSim, a as deleteParkedIosSim, d as listIosDeviceTypes, g as parseRuntimeVersion, h as parkedSimName, i as deleteIosSim, o as eraseIosSim, v as renameIosSim, w as shutdownIosSim } from "./ios-DArbmwer.mjs";
9
- import { closeSync, lstatSync, mkdirSync, openSync, readFileSync, renameSync, rmSync, unlinkSync } from "node:fs";
10
- import { basename, dirname, join, resolve, sep } from "node:path";
6
+ import { l as phaseLine } from "./command-output-BWCj5Vh-.mjs";
7
+ import { i as readAgentDeviceRecords } from "./activity-CCZJs__P.mjs";
8
+ import { A as listOrphanedAvdDirectories, F as ownedAvdMatchesConfiguration, K as shutdownAndroidEmulator, P as ownedAvdDirectory, R as ownedAvdSystemImage, T as isStimOwnedAvdName, W as resolveOwnedAvdSerial, Y as waitForAndroidEmulatorShutdown, Z as wipeAvdUserData, d as assertOwnedAvdStopped, f as avdPathExists, m as avdStorageRoots, q as sleepSync, v as deleteAvd } from "./android-75Sk2rIR.mjs";
9
+ import { S as resolveOwnedIosSim, a as deleteParkedIosSim, d as listIosDeviceTypes, g as parseRuntimeVersion, h as parkedSimName, i as deleteIosSim, o as eraseIosSim, v as renameIosSim, w as shutdownIosSim } from "./ios-CZWOHTTc.mjs";
10
+ import { closeSync, lstatSync, mkdirSync, openSync, readFileSync, realpathSync, renameSync, rmSync, unlinkSync } from "node:fs";
11
+ import { basename, dirname, isAbsolute, join, relative, resolve, sep } from "node:path";
11
12
  import { createHash, randomUUID } from "node:crypto";
13
+ import { homedir } from "node:os";
12
14
  import { isDeepStrictEqual } from "node:util";
13
15
  import { resolve4 } from "node:dns/promises";
14
16
  import { request } from "node:https";
@@ -22,17 +24,41 @@ function parseAgentDeviceSessions(output) {
22
24
  const id = row.platform === "ios" ? row.device_udid : row.id;
23
25
  if (row.platform !== "ios" && row.platform !== "android" || typeof row.name !== "string" || !row.name.trim() || typeof id !== "string" || !id || typeof row.createdAt !== "number" || !Number.isFinite(row.createdAt) || row.platform === "ios" && row.id !== void 0 && row.id !== id) return [];
24
26
  return [{
25
- name: row.name,
27
+ name: typeof row.address === "string" && row.address.trim() ? row.address : row.name,
26
28
  platform: row.platform,
27
29
  id,
30
+ device: typeof row.device === "string" ? row.device : null,
28
31
  createdAt: row.createdAt
29
32
  }];
30
33
  });
31
34
  }
35
+ function isOwnDeviceSession(session, device, owner) {
36
+ if (session.platform !== device.platform || session.id !== device.id) return false;
37
+ if (device.platform === "android" && session.device !== device.avdName.replaceAll("_", " ")) return false;
38
+ if (!owner) return true;
39
+ return owner.claims.some((claim) => claim.session === session.name && claim.workspace !== null && within(owner.workspace, claim.workspace));
40
+ }
41
+ function within(root, path) {
42
+ const rest = relative(root, path);
43
+ return rest === "" || !isAbsolute(rest) && rest.split(sep)[0] !== "..";
44
+ }
45
+ function canonical(path) {
46
+ try {
47
+ return realpathSync(path);
48
+ } catch {
49
+ return null;
50
+ }
51
+ }
52
+ function deviceClaims(device) {
53
+ return readAgentDeviceRecords(homedir()).filter((record) => record.kind === "claim" && record.deviceId === device.id).map((record) => ({
54
+ session: record.session,
55
+ workspace: record.workspace && canonical(record.workspace)
56
+ }));
57
+ }
32
58
  function report(message) {
33
59
  process.stderr.write(`${phaseLine("device", message)}\n`);
34
60
  }
35
- function closeOwnedDeviceSessions(device, stillOwned) {
61
+ function closeOwnedDeviceSessions(device, stillOwned, workspace) {
36
62
  const exec = getExecutor();
37
63
  const deadline = Date.now() + 15e3;
38
64
  const run = (args) => {
@@ -56,7 +82,13 @@ function closeOwnedDeviceSessions(device, stillOwned) {
56
82
  ]));
57
83
  try {
58
84
  if (!exec.findExecutable("agent-device")) return;
59
- const sessions = list().filter((session) => session.platform === device.platform && session.id === device.id);
85
+ const root = workspace === void 0 ? void 0 : canonical(workspace);
86
+ if (root === null) return;
87
+ const owner = root === void 0 ? void 0 : {
88
+ workspace: root,
89
+ claims: deviceClaims(device)
90
+ };
91
+ const sessions = list().filter((session) => isOwnDeviceSession(session, device, owner));
60
92
  for (const session of sessions) try {
61
93
  if (!list().some((current) => current.name === session.name && current.platform === session.platform && current.id === session.id && current.createdAt === session.createdAt)) continue;
62
94
  if (!stillOwned()) return;
@@ -376,7 +408,7 @@ function parkOwnedIosSim(settled, udid, park) {
376
408
  })
377
409
  };
378
410
  }
379
- function teardownOwnedIosSim(udid, { del = false, label, park, shutdownClock = {} } = {}) {
411
+ function teardownOwnedIosSim(udid, { del = false, label, park, workspace, shutdownClock = {} } = {}) {
380
412
  let parkFallback;
381
413
  try {
382
414
  const resolved = resolveOwnedIosSim(udid);
@@ -389,7 +421,7 @@ function teardownOwnedIosSim(udid, { del = false, label, park, shutdownClock = {
389
421
  closeOwnedDeviceSessions({
390
422
  platform: "ios",
391
423
  id: udid
392
- }, () => Boolean(resolveOwnedIosSim(udid).sim));
424
+ }, () => Boolean(resolveOwnedIosSim(udid).sim), workspace);
393
425
  const current = resolveOwnedIosSim(udid);
394
426
  if (current.missing) return { status: "missing" };
395
427
  if (current.notOwned) return {
@@ -520,7 +552,7 @@ function teardownOwnedAvd(avdName, options = {}) {
520
552
  (0, ownership_claim_exports.releaseClaim)(claim);
521
553
  }
522
554
  }
523
- function teardownClaimedAvd(avdName, claim, { del = false, park, owner, orphanedDirectory, onlyIfMissing = false, waitForShutdown = waitForAndroidEmulatorShutdown, assertStopped = assertOwnedAvdStopped, resolveAvd = resolveOwnedAvdSerial }) {
555
+ function teardownClaimedAvd(avdName, claim, { del = false, park, owner, workspace, orphanedDirectory, onlyIfMissing = false, waitForShutdown = waitForAndroidEmulatorShutdown, assertStopped = assertOwnedAvdStopped, resolveAvd = resolveOwnedAvdSerial }) {
524
556
  let parkFallback;
525
557
  try {
526
558
  if (del) withConfigLock(() => assertAvdReferences(avdName, owner));
@@ -547,8 +579,9 @@ function teardownClaimedAvd(avdName, claim, { del = false, park, owner, orphaned
547
579
  };
548
580
  closeOwnedDeviceSessions({
549
581
  platform: "android",
550
- id: serial
551
- }, stillOwned);
582
+ id: serial,
583
+ avdName
584
+ }, stillOwned, workspace);
552
585
  if (!stillOwned()) throw new Error(`Owned AVD ${avdName} changed before shutdown; it was kept.`);
553
586
  waitForShutdown(avdName, (timeoutMs) => {
554
587
  (0, ownership_claim_exports.markClaimChildPending)(claim);
@@ -1,5 +1,5 @@
1
- import { D as process_identity_exports } from "./config-BEq0Qw_a.mjs";
2
- import { _ as withWorkspaceStateLock, i as pidExists, m as readWorkspaceState, y as writeWorkspaceState } from "./metro-BWLOJ_Wr.mjs";
1
+ import { O as process_identity_exports } from "./config-0jCcMM0E.mjs";
2
+ import { _ as withWorkspaceStateLock, i as pidExists, m as readWorkspaceState, y as writeWorkspaceState } from "./metro-Dzo30hvJ.mjs";
3
3
  import { realpathSync } from "node:fs";
4
4
  //#region src/collector/state.ts
5
5
  function collectorRoot(root) {
@@ -1,6 +1,6 @@
1
- import { f as getProject } from "./config-BEq0Qw_a.mjs";
2
- import { o as findProjectRoot } from "./project-BXZzOABt.mjs";
3
- import { n as getNamedPort, t as clearNamedPorts } from "./named-ports-Dc7neAlc.mjs";
1
+ import { p as getProject } from "./config-0jCcMM0E.mjs";
2
+ import { i as findProjectRoot } from "./project-B8rbutVC.mjs";
3
+ import { n as getNamedPort, t as clearNamedPorts } from "./named-ports-Dn1o61D9.mjs";
4
4
  //#region src/commands/ports.ts
5
5
  async function inProject(action) {
6
6
  try {
@@ -1,6 +1,6 @@
1
- import { c as findEnclosingWorktreeRoot, f as getProject } from "./config-BEq0Qw_a.mjs";
2
- import { y as repoRoot } from "./worktree-BlizKDpZ.mjs";
3
- import { existsSync, readFileSync, readdirSync, realpathSync } from "fs";
1
+ import { l as findEnclosingWorktreeRoot, p as getProject } from "./config-0jCcMM0E.mjs";
2
+ import { y as repoRoot } from "./worktree-DeBQSVtR.mjs";
3
+ import { existsSync, readFileSync, realpathSync } from "fs";
4
4
  import { basename, dirname, join, resolve } from "path";
5
5
  import { createRequire } from "module";
6
6
  //#region src/workspace/project.ts
@@ -176,73 +176,5 @@ function readAppConfigText(projectRoot) {
176
176
  }
177
177
  return null;
178
178
  }
179
- function detectBundleId(projectRoot) {
180
- const fromJson = readAppJson(projectRoot)?.expo?.ios?.bundleIdentifier;
181
- if (typeof fromJson === "string" && fromJson) return fromJson;
182
- const text = readAppConfigText(projectRoot);
183
- if (text) {
184
- const id = text.match(/bundleIdentifier\s*:\s*["']([^"']+)["']/)?.[1];
185
- if (id) return id;
186
- }
187
- return detectBundleIdFromPbxproj(projectRoot);
188
- }
189
- function detectAndroidPackage(projectRoot) {
190
- const fromJson = readAppJson(projectRoot)?.expo?.android?.package;
191
- if (typeof fromJson === "string" && fromJson) return fromJson;
192
- const text = readAppConfigText(projectRoot);
193
- if (text) {
194
- const pkg = text.match(/package\s*:\s*["']([^"']+)["']/)?.[1];
195
- if (pkg) return pkg;
196
- }
197
- return detectAndroidPackageFromGradle(projectRoot);
198
- }
199
- function detectBundleIdFromPbxproj(projectRoot) {
200
- const iosDir = join(projectRoot, "ios");
201
- if (!existsSync(iosDir)) return null;
202
- let entries;
203
- try {
204
- entries = readdirSync(iosDir, { withFileTypes: true });
205
- } catch {
206
- return null;
207
- }
208
- for (const entry of entries) {
209
- if (!entry.isDirectory() || !entry.name.endsWith(".xcodeproj")) continue;
210
- const pbx = join(iosDir, entry.name, "project.pbxproj");
211
- if (!existsSync(pbx)) continue;
212
- let text;
213
- try {
214
- text = readFileSync(pbx, "utf-8");
215
- } catch {
216
- continue;
217
- }
218
- const concrete = [...text.matchAll(/PRODUCT_BUNDLE_IDENTIFIER\s*=\s*([^;\s"]+)\s*;/g)].map((m) => m[1]).filter((id) => !!id && !id.startsWith("$") && !id.includes("("));
219
- if (concrete.length === 0) continue;
220
- const counts = {};
221
- for (const id of concrete) counts[id] = (counts[id] || 0) + 1;
222
- let best = null, bestCount = 0, bestLen = Infinity;
223
- for (const [id, count] of Object.entries(counts)) if (count > bestCount || count === bestCount && id.length < bestLen) {
224
- best = id;
225
- bestCount = count;
226
- bestLen = id.length;
227
- }
228
- return best;
229
- }
230
- return null;
231
- }
232
- function detectAndroidPackageFromGradle(projectRoot) {
233
- const gradle = join(projectRoot, "android", "app", "build.gradle");
234
- if (!existsSync(gradle)) return null;
235
- let text;
236
- try {
237
- text = readFileSync(gradle, "utf-8");
238
- } catch {
239
- return null;
240
- }
241
- const nsId = text.match(/namespace\s+["']([^"']+)["']/)?.[1];
242
- if (nsId) return nsId;
243
- const appId = text.match(/applicationId\s+["']([^"']+)["']/)?.[1];
244
- if (appId) return appId;
245
- return null;
246
- }
247
179
  //#endregion
248
- export { detectIsExpo as a, ownedDeviceLabel as c, detectBundleId as i, projectShortcut as l, appProjectProblem as n, findProjectRoot as o, detectAndroidPackage as r, isPackageResolvable as s, NO_PROJECT_REFUSAL as t, resolvePackageJson as u };
180
+ export { isPackageResolvable as a, readAppConfigText as c, findProjectRoot as i, readAppJson as l, appProjectProblem as n, ownedDeviceLabel as o, detectIsExpo as r, projectShortcut as s, NO_PROJECT_REFUSAL as t, resolvePackageJson as u };
@@ -1,12 +1,12 @@
1
- import { B as parseDeviceSlotKey, f as getProject, z as deviceSlotPlatforms } from "./config-BEq0Qw_a.mjs";
2
- import { h as recordWorkspaceUse, s as resolveProjectMetro } from "./metro-BWLOJ_Wr.mjs";
3
- import { o as findProjectRoot } from "./project-BXZzOABt.mjs";
4
- import { d as readWorkspaceLaunches } from "./state-WGdIbi_d.mjs";
5
- import { f as refuseNoProject, l as phaseLine } from "./command-output-D5z2_bcF.mjs";
6
- import { H as resolveOwnedAvdSerial } from "./android-C4zG2Tuc.mjs";
7
- import { S as resolveOwnedIosSim } from "./ios-DArbmwer.mjs";
8
- import { h as iosAppProcess, o as androidAppProcess } from "./app-install-DHut6JnV.mjs";
9
- import { n as nativeRunCommand } from "./slot-launch-rggO1Esw.mjs";
1
+ import { B as deviceSlotPlatforms, V as parseDeviceSlotKey, p as getProject } from "./config-0jCcMM0E.mjs";
2
+ import { h as recordWorkspaceUse, s as resolveProjectMetro } from "./metro-Dzo30hvJ.mjs";
3
+ import { i as findProjectRoot } from "./project-B8rbutVC.mjs";
4
+ import { f as readWorkspaceLaunches } from "./state-DcDgzfu3.mjs";
5
+ import { f as refuseNoProject, l as phaseLine } from "./command-output-BWCj5Vh-.mjs";
6
+ import { W as resolveOwnedAvdSerial } from "./android-75Sk2rIR.mjs";
7
+ import { S as resolveOwnedIosSim } from "./ios-CZWOHTTc.mjs";
8
+ import { h as iosAppProcess, o as androidAppProcess } from "./app-install-CsZi0SAT.mjs";
9
+ import { n as nativeRunCommand } from "./slot-launch-DIACGEfH.mjs";
10
10
  import chalk from "chalk";
11
11
  import { WebSocket } from "ws";
12
12
  //#region src/engine/reload.ts