stim 1.13.0 → 1.15.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 (133) hide show
  1. package/README.md +2 -0
  2. package/dist/{activity-DfVKZTEB.mjs → activity-B2-kb7k0.mjs} +281 -41
  3. package/dist/{android-BHfAu2mf.mjs → android-CYmq0jNi.mjs} +2 -2
  4. package/dist/{android-CD8pr8Q2.mjs → android-Cu_L4RpL.mjs} +524 -412
  5. package/dist/{android-qx_31wJo.mjs → android-Db2eEMaf.mjs} +152 -65
  6. package/dist/android-cas-PnKfAdB2.mjs +167 -0
  7. package/dist/android-cas-compiler.mjs +2 -2
  8. package/dist/{app-install-CDFY2nUL.mjs → app-install-CAAplXAt.mjs} +162 -173
  9. package/dist/{budget-E5o91NR1.mjs → budget-CMiqghig.mjs} +1048 -77
  10. package/dist/{build-plan-BTa93o_r.mjs → build-plan-aeGMFX7e.mjs} +193 -650
  11. package/dist/build-progress-C2Jv1AtA.mjs +872 -0
  12. package/dist/build-slots-Df1ApSuH.mjs +127 -0
  13. package/dist/{cache-manifest-DWPF4RKJ.mjs → cache-manifest-DnUHBJaU.mjs} +2 -2
  14. package/dist/cache-manifest.mjs +1 -1
  15. package/dist/{chrome-B5hWgQJS.mjs → chrome-BrcVWQyD.mjs} +4 -4
  16. package/dist/cli-0cX5s4NM.mjs +45 -0
  17. package/dist/cli.mjs +6 -42
  18. package/dist/client-C2IS36Qf.mjs +1333 -0
  19. package/dist/collector-run.mjs +8 -7
  20. package/dist/{command-output-BIL7rlX7.mjs → command-output-CliHHn7a.mjs} +1 -1
  21. package/dist/{config-0jCcMM0E.mjs → config-D0DbpZtM.mjs} +29 -29
  22. package/dist/{created-devices-Cd558h31.mjs → created-devices-BwVb3liH.mjs} +2 -2
  23. package/dist/{dependency-state-DNN0yfx6.mjs → dependency-state-BmsjKZ2H.mjs} +2 -2
  24. package/dist/{deps-2Wo81np9.mjs → deps-BFlKbOIp.mjs} +3 -3
  25. package/dist/{detached-entry-DJHoca49.mjs → detached-entry-CiTEgMR1.mjs} +1 -1
  26. package/dist/dev-client-CjzLoNs0.mjs +80 -0
  27. package/dist/{device-Cf7vl-so.mjs → device-BZ1IyS5A.mjs} +7 -7
  28. package/dist/device-capacity-DMuKC7nx.mjs +136 -0
  29. package/dist/device-host-worker.d.mts +1 -0
  30. package/dist/device-host-worker.mjs +769 -0
  31. package/dist/device-ios-DMQBUPus.mjs +381 -0
  32. package/dist/{device-lease-CL9dZf73.mjs → device-lease-W5Pi1q38.mjs} +43 -36
  33. package/dist/{device-pool-MuoiyRcu.mjs → device-pool-B2r38YjS.mjs} +4 -4
  34. package/dist/{device-remote-DT9ngZiD.mjs → device-remote-9ulPsdhY.mjs} +68 -162
  35. package/dist/{doctor-D2iysNNH.mjs → doctor-BcE5xsBn.mjs} +191 -99
  36. package/dist/{error-diagnostics-BoiOhck8.mjs → error-diagnostics-Cb0P1WLS.mjs} +12 -11
  37. package/dist/{exec-DK8KaVHK.mjs → exec-CaErVv7t.mjs} +5 -1
  38. package/dist/{gc-eA-PRBX8.mjs → gc-BuL1Genr.mjs} +430 -102
  39. package/dist/{android-cas-B9Kv9aIy.mjs → gradle-CmdOBq1d.mjs} +8 -294
  40. package/dist/{guide-BfZ0OmiP.mjs → guide-cCSGRFd3.mjs} +2052 -240
  41. package/dist/{guide-status-BaMYu55M.mjs → guide-status-CIoWK6mG.mjs} +3 -3
  42. package/dist/hosted-macos-DwowNU7W.mjs +447 -0
  43. package/dist/idle-shutdown-B5LPaNyY.mjs +122 -0
  44. package/dist/in-use-CndPMilN.mjs +110 -0
  45. package/dist/{ios-CmEzZiOj.mjs → ios-3CtCRhwr.mjs} +201 -10
  46. package/dist/{ios-CcfCeZ19.mjs → ios-Chob8ny7.mjs} +560 -259
  47. package/dist/{ios-device-BW-t_Lkv.mjs → ios-device-DERmMmk-.mjs} +12 -7
  48. package/dist/{ios-device-BiOsSVzd.mjs → ios-device-Ee7sDXfp.mjs} +1 -1
  49. package/dist/{launch-verify-CuJaBpEa.mjs → launch-verify-CLlofxRt.mjs} +42 -11
  50. package/dist/{logs-DcSRbC2t.mjs → logs-h9h6MUvE.mjs} +95 -13
  51. package/dist/machine-usage-D_YYMzfR.mjs +283 -0
  52. package/dist/machines-CYtOCqcj.mjs +259 -0
  53. package/dist/macos-BwtbUtTN.mjs +468 -0
  54. package/dist/macos-run.d.mts +5 -0
  55. package/dist/macos-run.mjs +2 -0
  56. package/dist/{merge-state-ytFQCeh4.mjs → merge-state-BnxLNQiM.mjs} +22 -12
  57. package/dist/{metro-BPeY1YMh.mjs → metro-Di8EN2Tb.mjs} +20 -120
  58. package/dist/{named-ports-n7tnJsI8.mjs → named-ports-Dj_XBNaL.mjs} +8 -64
  59. package/dist/native-run-DFDoIRbY.mjs +147 -0
  60. package/dist/{native-runtime-CiiFHt0e.mjs → native-runtime-i6OkVg-w.mjs} +11 -6
  61. package/dist/offload-worker.d.mts +121 -0
  62. package/dist/offload-worker.mjs +601 -0
  63. package/dist/{ownership-Bz2kETAS.mjs → ownership-BkYxUtuj.mjs} +3 -2
  64. package/dist/{page-BTu7I60K.mjs → page-QF_Ke10s.mjs} +7 -2
  65. package/dist/{ports-C5UutqpJ.mjs → ports-DddwttKM.mjs} +3 -3
  66. package/dist/prebuild-BvxDlD6C.mjs +213 -0
  67. package/dist/process-identity-BmRm1qV0.mjs +12 -0
  68. package/dist/{project-DGeclhvO.mjs → project-CV3tDFHl.mjs} +9 -18
  69. package/dist/pull-request-pxnDCQzn.mjs +322 -0
  70. package/dist/pull-requests.d.mts +120 -0
  71. package/dist/pull-requests.mjs +2 -0
  72. package/dist/recordings-GEXp4iBT.mjs +37 -0
  73. package/dist/{reload-C-cV5yy_.mjs → reload-ChPiwvot.mjs} +70 -22
  74. package/dist/{remote-cache--aehr4Pr.mjs → remote-cache-CO2elm_b.mjs} +4 -4
  75. package/dist/run-B-xqRrsg.mjs +119 -0
  76. package/dist/{server-bare-Bq8BpSIo.mjs → server-bare-X7PUgizL.mjs} +60 -13
  77. package/dist/{server-expo-DUCg52-K.mjs → server-expo-DhtX6bom.mjs} +6 -10
  78. package/dist/server-expo-KJeD109I.mjs +2 -0
  79. package/dist/{settings-xB0Frkg6.mjs → settings-CduVcoxj.mjs} +77 -26
  80. package/dist/{settings-ssVBToDR.mjs → settings-DbL6uhH8.mjs} +16 -10
  81. package/dist/settings.schema.json +357 -2
  82. package/dist/{simslim-Bbg9UWrt.mjs → simslim-Ciluxlq4.mjs} +8 -132
  83. package/dist/slot-launch-BY0BrOLh.mjs +65 -0
  84. package/dist/{spawn-claims-PT8aQpCa.mjs → spawn-claims-D0XfSe8u.mjs} +1 -1
  85. package/dist/spawn-entry-DncpJvWL.mjs +16 -0
  86. package/dist/stage-CzaiwFsI.mjs +143 -0
  87. package/dist/start-CPO4wRg7.mjs +2 -0
  88. package/dist/{start-BZhItkiL.mjs → start-CUD9nasA.mjs} +108 -61
  89. package/dist/state-B4PQFXMW.d.mts +12 -0
  90. package/dist/state-BxCgeTQu.mjs +41 -0
  91. package/dist/{state-DwAU2_-D.mjs → state-CaeaHbDA.mjs} +7 -4
  92. package/dist/{state-l1pYwOre.mjs → state-DFm77wRn.mjs} +67 -5
  93. package/dist/stats-DBLLFmKd.mjs +66 -0
  94. package/dist/{status-TJlL0HWo.mjs → status-DYXxNOT0.mjs} +425 -260
  95. package/dist/{status-sszP4XKU.mjs → status-l84Gbvp2.mjs} +122 -20
  96. package/dist/stdout-reader-C8yjre1x.mjs +23 -0
  97. package/dist/stim-desktop-Cnz8CPnl.mjs +63 -0
  98. package/dist/stim-footprint.swift +32 -0
  99. package/dist/{stim-installations-CINXy_su.mjs → stim-installations-QMEI32v1.mjs} +1 -1
  100. package/dist/{stop-BZ2qMiBP.mjs → stop-Bad61z_2.mjs} +128 -19
  101. package/dist/stop-Bvf1MflS.mjs +48 -0
  102. package/dist/{stop-DskDKNTU.mjs → stop-CceYh1yG.mjs} +2 -2
  103. package/dist/stop-cause-CZ_Mr-v9.mjs +665 -0
  104. package/dist/supervisor-run.d.mts +44 -12
  105. package/dist/supervisor-run.mjs +276 -33
  106. package/dist/support-CDQbDkL5.mjs +315 -0
  107. package/dist/support-WLOzVKUv.mjs +176 -0
  108. package/dist/teardown-BYuQafiA.mjs +718 -0
  109. package/dist/{xcode-LM6A8cNZ.mjs → toolchain-DmeYjXD9.mjs} +363 -13
  110. package/dist/warm-progress-DVHLN4uC.mjs +463 -0
  111. package/dist/{idle-DxLi5OkN.mjs → watchman-Bx0wceoF.mjs} +55 -8
  112. package/dist/{web-sWXd5iek.mjs → web-k6w8-HnE.mjs} +39 -22
  113. package/dist/web-run.mjs +326 -13
  114. package/dist/workspace-process-lock-BL7Q0HCO.mjs +57 -0
  115. package/dist/workspace-state-CL2V2Ons.mjs +371 -0
  116. package/dist/worktree-BT_uULFx.mjs +2 -0
  117. package/dist/{worktree-DeBQSVtR.mjs → worktree-C0c5Udwa.mjs} +55 -54
  118. package/dist/{worktree-D4Do_XiQ.mjs → worktree-qXKzADSC.mjs} +161 -255
  119. package/package.json +10 -5
  120. package/shim/bundle-response.cjs +55 -10
  121. package/shim/bundle-response.d.cts +1 -0
  122. package/shim/expo-metro-config.cjs +10 -2
  123. package/dist/build-progress-l7d-X-ZP.mjs +0 -247
  124. package/dist/in-use-wYEaKQM9.mjs +0 -249
  125. package/dist/ownership-PUP4Dwai.mjs +0 -1138
  126. package/dist/server-expo-BeYwP_Xy.mjs +0 -2
  127. package/dist/slot-launch-BIWEW-wI.mjs +0 -19
  128. package/dist/start-Rw2GD3nV.mjs +0 -2
  129. package/dist/stats-CaSwmsSZ.mjs +0 -62
  130. package/dist/stats-D8rUTPHd.mjs +0 -368
  131. package/dist/stim-desktop-CXt8-Z3J.mjs +0 -40
  132. package/dist/worktree-3cBa-bQt.mjs +0 -2
  133. package/dist/{metro-store-DzeWkfqW.mjs → metro-store-CDDZHtPl.mjs} +1 -1
@@ -0,0 +1,259 @@
1
+ import { _ as loadConfig$1, d as getConfigDir } from "./config-D0DbpZtM.mjs";
2
+ import { E as withDirLock } from "./workspace-state-CL2V2Ons.mjs";
3
+ import { _ as findPeer, b as realIo, g as endpoint, v as parseMachine$1 } from "./client-C2IS36Qf.mjs";
4
+ import { mkdirSync, renameSync, rmSync, writeFileSync } from "node:fs";
5
+ import { acceptsShape, deviceHostMachinesClaims, deviceHostMachinesFile, deviceHostMachinesLock, isJsonObject, readDeviceHostMachines, settingDefinition } from "@stim-cli/core/state";
6
+ import { releaseClaim, tryAcquireClaim } from "@stim-cli/core/ownership-claim";
7
+ import { hostname } from "node:os";
8
+ //#region src/device-host/machines.ts
9
+ function note(title, detail, fix = null) {
10
+ return {
11
+ code: "device-host-machine",
12
+ level: "note",
13
+ title,
14
+ detail,
15
+ fix
16
+ };
17
+ }
18
+ const approval = (machine, id) => `A person on ${machine} approves it with \`stim-server devices grant ${id} --device-host\`.`;
19
+ function configuredMachines() {
20
+ const hosting = loadConfig$1()?.hosting;
21
+ if (hosting !== void 0 && !isJsonObject(hosting)) return null;
22
+ const machines = hosting?.machines;
23
+ if (machines === void 0) return [];
24
+ return acceptsShape(settingDefinition("hosting.machines"), machines) ? machines : null;
25
+ }
26
+ function store(machines) {
27
+ withDirLock(deviceHostMachinesLock(), () => {
28
+ const file = deviceHostMachinesFile();
29
+ const tmp = `${file}.${process.pid}.${Math.random().toString(36).slice(2)}.tmp`;
30
+ try {
31
+ writeFileSync(tmp, `${JSON.stringify({
32
+ version: 1,
33
+ machines
34
+ }, null, 2)}\n`, { mode: 384 });
35
+ renameSync(tmp, file);
36
+ } finally {
37
+ rmSync(tmp, { force: true });
38
+ }
39
+ }, { ensureParent: () => mkdirSync(getConfigDir(), { recursive: true }) });
40
+ }
41
+ async function request(machine, peer, port, deviceName, io) {
42
+ const reply = await io.hello(endpoint(peer, port), {
43
+ request: "device-host",
44
+ deviceName
45
+ });
46
+ if (!("result" in reply) || reply.result?.approval?.state !== "pending" || typeof reply.result.deviceToken !== "string" || !reply.result.deviceToken || typeof reply.result.device?.id !== "string" || !reply.result.device.id || typeof reply.result.approval.expiresAt !== "string" || !reply.result.approval.expiresAt) return {
47
+ report: {
48
+ machine,
49
+ dnsName: peer.dnsName,
50
+ state: "unreachable"
51
+ },
52
+ finding: note(`Could not ask ${machine} for hosting access`, "The worker did not return a pending request.")
53
+ };
54
+ const credential = {
55
+ machine,
56
+ nodeId: peer.nodeId,
57
+ dnsName: peer.dnsName,
58
+ deviceId: reply.result.device.id,
59
+ deviceToken: reply.result.deviceToken,
60
+ state: "pending",
61
+ requestedAt: (/* @__PURE__ */ new Date()).toISOString()
62
+ };
63
+ return {
64
+ report: {
65
+ machine,
66
+ dnsName: peer.dnsName,
67
+ state: "pending",
68
+ deviceId: credential.deviceId,
69
+ requestedAt: credential.requestedAt
70
+ },
71
+ finding: note(`Asked ${machine} for hosting access`, `The request lapses at ${reply.result.approval.expiresAt}.`, approval(machine, credential.deviceId)),
72
+ credential
73
+ };
74
+ }
75
+ /** Reports separately approved hosting machines. Only --fix asks or forgets credentials; every token stays pinned. */
76
+ async function inspectDeviceHostMachines({ fix }, io = realIo, entries = configuredMachines()) {
77
+ if (entries === null) return {
78
+ findings: [note("Invalid hosting.machines setting", "Use a hosting object with machines as an array of tailnet names. Existing hosting credentials and pinned nodes are preserved.", "Run `stim guide settings` and correct the setting before running doctor again.")],
79
+ machines: []
80
+ };
81
+ const unavailable = (state, finding) => ({
82
+ findings: [finding],
83
+ machines: entries.map((machine) => ({
84
+ machine,
85
+ state
86
+ }))
87
+ });
88
+ const unreadable = () => unavailable("credentials-unavailable", note("Hosting credentials are unreadable", `Stim preserves ${deviceHostMachinesFile()} and its pinned nodes.`, "Restore the existing file from a trusted backup or restore read access before running doctor again."));
89
+ if (!entries.length) {
90
+ if (!fix) return {
91
+ findings: [],
92
+ machines: []
93
+ };
94
+ try {
95
+ if (!readDeviceHostMachines().length) return {
96
+ findings: [],
97
+ machines: []
98
+ };
99
+ } catch {
100
+ return unreadable();
101
+ }
102
+ }
103
+ const claim = tryAcquireClaim({
104
+ root: deviceHostMachinesClaims(),
105
+ mode: "exclusive",
106
+ label: "hosting machine approval"
107
+ });
108
+ if (!claim.acquired) {
109
+ releaseClaim(claim.pending);
110
+ return unavailable("busy", note("Hosting machine approval is in use", "Another doctor run holds the hosting credential claim. Run doctor again after it finishes."));
111
+ }
112
+ try {
113
+ let credentials;
114
+ try {
115
+ credentials = readDeviceHostMachines();
116
+ } catch {
117
+ return unreadable();
118
+ }
119
+ if (fix) {
120
+ const kept = credentials.filter((each) => entries.includes(each.machine));
121
+ if (kept.length !== credentials.length) {
122
+ store(kept);
123
+ credentials = kept;
124
+ }
125
+ }
126
+ if (!entries.length) return {
127
+ findings: [],
128
+ machines: []
129
+ };
130
+ const status = io.status();
131
+ if (!isJsonObject(status)) return unavailable("tailscale-off", note("Hosting machines are unreachable", "hosting.machines names hosting machines, but Tailscale is not running."));
132
+ const self = isJsonObject(status.Self) ? status.Self : {};
133
+ const deviceName = (typeof self.HostName === "string" && self.HostName ? self.HostName : hostname()).replace(/[\p{Cc}\p{Cf}]/gu, "").trim().slice(0, 64) || "Mac";
134
+ const inspected = {
135
+ findings: [],
136
+ machines: []
137
+ };
138
+ const namedNodes = /* @__PURE__ */ new Set();
139
+ for (const machine of new Set(entries)) {
140
+ const parsed = parseMachine$1(machine);
141
+ if (!parsed) {
142
+ inspected.machines.push({
143
+ machine,
144
+ state: "invalid"
145
+ });
146
+ inspected.findings.push(note(`Hosting machine ${machine} is not a tailnet name`, "Expected `name` or `name:port`."));
147
+ continue;
148
+ }
149
+ const current = io.status();
150
+ if (!isJsonObject(current)) {
151
+ inspected.machines.push({
152
+ machine,
153
+ state: "tailscale-off"
154
+ });
155
+ inspected.findings.push(note(`Hosting machine ${machine} is unreachable`, "Tailscale stopped before this connection."));
156
+ continue;
157
+ }
158
+ const peer = findPeer(current, parsed.name);
159
+ if (peer === "missing" || peer === "ambiguous") {
160
+ inspected.machines.push({
161
+ machine,
162
+ state: "not-on-tailnet"
163
+ });
164
+ inspected.findings.push(note(`Hosting machine ${machine} is not on this tailnet`, peer === "missing" ? "No peer has that name." : "Several peers match that name."));
165
+ continue;
166
+ }
167
+ const nodeRoute = `${peer.nodeId}:${parsed.port}`;
168
+ if (namedNodes.has(nodeRoute)) {
169
+ inspected.machines.push({
170
+ machine,
171
+ dnsName: peer.dnsName,
172
+ state: "invalid"
173
+ });
174
+ inspected.findings.push(note(`Hosting machine ${machine} repeats a named node`, "Name each tailnet node and serve port only once in hosting.machines."));
175
+ continue;
176
+ }
177
+ namedNodes.add(nodeRoute);
178
+ const credential = credentials.find((each) => each.machine === machine);
179
+ const known = {
180
+ machine,
181
+ dnsName: peer.dnsName,
182
+ ...credential ? {
183
+ deviceId: credential.deviceId,
184
+ requestedAt: credential.requestedAt
185
+ } : {}
186
+ };
187
+ if (credential && credential.nodeId !== peer.nodeId) {
188
+ inspected.machines.push({
189
+ ...known,
190
+ state: "node-changed"
191
+ });
192
+ inspected.findings.push(note(`Hosting machine ${machine} is a different tailnet node`, "Stim refuses to connect or send the saved token.", `If that Mac was replaced, remove ${machine} from hosting.machines, run \`stim doctor --fix\`, then add it back and run \`stim doctor --fix\` again to request approval on the new node.`));
193
+ continue;
194
+ }
195
+ let ask = !credential && fix;
196
+ if (credential) {
197
+ const reply = await io.hello(endpoint(peer, parsed.port), { deviceToken: credential.deviceToken });
198
+ if ("result" in reply && reply.result?.device?.id === credential.deviceId && Array.isArray(reply.result.capabilities) && reply.result.capabilities.includes("device-host")) {
199
+ if (credential.state !== "approved") {
200
+ credentials = credentials.map((each) => each.machine === machine ? {
201
+ ...each,
202
+ state: "approved"
203
+ } : each);
204
+ store(credentials);
205
+ }
206
+ const host = reply.result.host;
207
+ if (host && (host.screenRecording === false || host.accessibility === false)) {
208
+ const panes = [...host.screenRecording === false ? ["Screen & System Audio Recording (Screen Recording on macOS 14)"] : [], ...host.accessibility === false ? ["Device Control and Data Access (Accessibility on macOS 26 and earlier)"] : []];
209
+ const detail = [...host.screenRecording === false ? ["Viewing hosted macOS apps needs Screen Recording."] : [], ...host.accessibility === false ? ["Controlling them needs the control permission."] : []];
210
+ inspected.findings.push(note(`Hosting machine ${machine} needs ${panes.join(" and ")} for ${host.name}`, detail.join(" "), `On ${machine}, approve ${host.name} in System Settings > Privacy & Security, or run \`stim-server service install\` there again to show the requests.`));
211
+ }
212
+ inspected.machines.push({
213
+ ...known,
214
+ state: "approved"
215
+ });
216
+ continue;
217
+ }
218
+ if ("error" in reply && reply.error?.code === "approval-pending") {
219
+ inspected.machines.push({
220
+ ...known,
221
+ state: "pending"
222
+ });
223
+ inspected.findings.push(note(`Hosting machine ${machine} has not approved this Mac yet`, `Requested at ${credential.requestedAt}.`, approval(machine, credential.deviceId)));
224
+ continue;
225
+ }
226
+ const revoked = "error" in reply && reply.error?.code === "unauthorized";
227
+ ask = revoked && fix;
228
+ if (!ask) {
229
+ inspected.machines.push({
230
+ ...known,
231
+ state: revoked ? "revoked" : "unreachable"
232
+ });
233
+ inspected.findings.push(note(`Hosting machine ${machine} ${revoked ? "no longer accepts this Mac" : "did not confirm hosting access"}`, "The saved token and pinned node are preserved.", revoked ? "Run `stim doctor --fix` to ask again." : `Check stim-server and its tailnet serve route on ${machine}, then run doctor again.`));
234
+ continue;
235
+ }
236
+ }
237
+ if (ask) {
238
+ const result = await request(machine, peer, parsed.port, deviceName, io);
239
+ if (result.credential) {
240
+ credentials = [...credentials.filter((each) => each.machine !== machine), result.credential];
241
+ store(credentials);
242
+ }
243
+ inspected.machines.push(result.report);
244
+ inspected.findings.push(result.finding);
245
+ } else {
246
+ inspected.machines.push({
247
+ ...known,
248
+ state: "not-asked"
249
+ });
250
+ inspected.findings.push(note(`Hosting machine ${machine} has not approved this Mac`, "This Mac has not asked for hosting access.", "Run `stim doctor --fix` to ask."));
251
+ }
252
+ }
253
+ return inspected;
254
+ } finally {
255
+ releaseClaim(claim.acquired);
256
+ }
257
+ }
258
+ //#endregion
259
+ export { inspectDeviceHostMachines as n, configuredMachines as t };