@kaeawc/auto-mobile 0.0.92 → 0.0.94
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/build-info.json +12 -12
- package/dist/schemas/test-plan.schema.json +370 -52
- package/dist/src/ble-peripheral.py +153 -0
- package/dist/src/{chunk-r14wwk37.js → chunk-026y62r9.js} +12 -12
- package/dist/src/chunk-0jyfg947.js +4 -0
- package/dist/src/{chunk-950qcq1e.js → chunk-0zfpp1wh.js} +4 -4
- package/dist/src/chunk-13qxf7ym.js +7 -0
- package/dist/src/chunk-1scenrk7.js +4 -0
- package/dist/src/chunk-1vb5ph1k.js +4 -0
- package/dist/src/chunk-20g565q7.js +5 -0
- package/dist/src/chunk-21h6dhdm.js +5 -0
- package/dist/src/{chunk-2e6s75qv.js → chunk-25mfpthk.js} +8 -8
- package/dist/src/{chunk-9rkfyt6q.js → chunk-2b39zyxc.js} +3 -3
- package/dist/src/chunk-2gzd6wbd.js +4 -0
- package/dist/src/{chunk-eka89q3k.js → chunk-3dntffy9.js} +1 -1
- package/dist/src/chunk-3gfczcsn.js +4 -0
- package/dist/src/chunk-3h5jz1vb.js +9 -0
- package/dist/src/chunk-41zcy6b3.js +5 -0
- package/dist/src/chunk-47n9m2de.js +4 -0
- package/dist/src/chunk-4vxeq0vd.js +58 -0
- package/dist/src/chunk-59dx6qaf.js +4 -0
- package/dist/src/chunk-5sdf9y92.js +4 -0
- package/dist/src/chunk-5wk1t46v.js +5 -0
- package/dist/src/chunk-661c50hh.js +17 -0
- package/dist/src/chunk-68n6bjjd.js +21 -0
- package/dist/src/{chunk-zg67wjkh.js → chunk-69pmjdf2.js} +3 -3
- package/dist/src/chunk-6hrj3jt6.js +145 -0
- package/dist/src/{chunk-b4cxdzwy.js → chunk-6myr26wx.js} +8 -8
- package/dist/src/chunk-6n96k09n.js +4 -0
- package/dist/src/chunk-6vwrbkre.js +4 -0
- package/dist/src/chunk-6wk0yrab.js +4 -0
- package/dist/src/chunk-6yhm9een.js +4 -0
- package/dist/src/chunk-7k7gjg2t.js +7 -0
- package/dist/src/chunk-7n5fz68h.js +4 -0
- package/dist/src/chunk-8cvnpnbp.js +4 -0
- package/dist/src/chunk-8kzv7rk7.js +4 -0
- package/dist/src/chunk-8nj68t1v.js +167 -0
- package/dist/src/{chunk-r20pe1nv.js → chunk-96r3bpg7.js} +3 -3
- package/dist/src/chunk-97x887te.js +4 -0
- package/dist/src/{chunk-sz1a7p43.js → chunk-99a6tbvd.js} +1 -1
- package/dist/src/chunk-9p5d2994.js +5 -0
- package/dist/src/{chunk-w7zsh13a.js → chunk-9q265er0.js} +4 -4
- package/dist/src/chunk-9xgnrv5w.js +5 -0
- package/dist/src/chunk-9xgsmshb.js +5 -0
- package/dist/src/chunk-a02d1wgv.js +4 -0
- package/dist/src/{chunk-km0dy5vc.js → chunk-a9ps00a1.js} +10 -10
- package/dist/src/chunk-aewdveet.js +5 -0
- package/dist/src/chunk-b3tdtq7r.js +9 -0
- package/dist/src/chunk-bn7jx7a2.js +4 -0
- package/dist/src/chunk-bnyw27ja.js +4 -0
- package/dist/src/{chunk-s1zq65ny.js → chunk-bpwsg76p.js} +2 -2
- package/dist/src/chunk-bvranw3g.js +4 -0
- package/dist/src/chunk-c25a84zb.js +4 -0
- package/dist/src/chunk-c27yv1dx.js +5 -0
- package/dist/src/chunk-c3ewxm4x.js +5 -0
- package/dist/src/chunk-cb1ga9rd.js +7 -0
- package/dist/src/chunk-cn7fwy7k.js +4 -0
- package/dist/src/chunk-cnvy4a64.js +4 -0
- package/dist/src/chunk-cqhw4yr6.js +5 -0
- package/dist/src/{chunk-v90es00d.js → chunk-ctmfshjc.js} +2 -2
- package/dist/src/chunk-ctwmhz13.js +4 -0
- package/dist/src/{chunk-qv2918jt.js → chunk-d3jx9bz5.js} +2 -2
- package/dist/src/{chunk-wry6skrm.js → chunk-d6rb08ga.js} +1 -1
- package/dist/src/chunk-ddqhj4eg.js +5 -0
- package/dist/src/{chunk-d57432wq.js → chunk-ddrhs1c3.js} +2 -2
- package/dist/src/chunk-dnjnh9p6.js +4 -0
- package/dist/src/{chunk-ajsrz473.js → chunk-dw5rwgya.js} +3 -3
- package/dist/src/chunk-e0870khr.js +5 -0
- package/dist/src/chunk-ea3k10kj.js +4 -0
- package/dist/src/chunk-emv82m1w.js +7 -0
- package/dist/src/chunk-f3m6pdnx.js +4 -0
- package/dist/src/chunk-f84z32cb.js +4 -0
- package/dist/src/chunk-fpczgf0z.js +4 -0
- package/dist/src/chunk-g2js4c2v.js +971 -0
- package/dist/src/chunk-g3af2qbk.js +5 -0
- package/dist/src/chunk-gadtna7s.js +11 -0
- package/dist/src/{chunk-c9nk1r78.js → chunk-gcyx407v.js} +3 -3
- package/dist/src/{chunk-jdqvcq0a.js → chunk-gfpntwc1.js} +3 -3
- package/dist/src/chunk-gmnm5e3e.js +4 -0
- package/dist/src/chunk-gp6vb5gf.js +4 -0
- package/dist/src/chunk-gppgy7pa.js +4 -0
- package/dist/src/chunk-hegfz0ae.js +5 -0
- package/dist/src/chunk-hpzxdp1k.js +17 -0
- package/dist/src/{chunk-2v7tw1nj.js → chunk-j69g8b50.js} +3 -3
- package/dist/src/chunk-jvstjnqm.js +19 -0
- package/dist/src/chunk-jzqrv78s.js +4 -0
- package/dist/src/chunk-k2948b8d.js +4 -0
- package/dist/src/chunk-k4ftd40d.js +4 -0
- package/dist/src/chunk-kd9vfaxh.js +5 -0
- package/dist/src/{chunk-34zxqcmq.js → chunk-kdczmgwk.js} +3 -3
- package/dist/src/chunk-ke3wn14v.js +4 -0
- package/dist/src/chunk-kh5n7m6w.js +4 -0
- package/dist/src/{chunk-0dfnyfkh.js → chunk-khejfph4.js} +3 -3
- package/dist/src/chunk-kny2xemh.js +4 -0
- package/dist/src/chunk-knyzw9md.js +4 -0
- package/dist/src/chunk-mbzpt2hp.js +4 -0
- package/dist/src/chunk-mm8rcxad.js +4 -0
- package/dist/src/chunk-nc4516tx.js +4 -0
- package/dist/src/{chunk-stfzjr9y.js → chunk-ntfrqrqn.js} +5 -5
- package/dist/src/chunk-nz5h2j52.js +4 -0
- package/dist/src/chunk-p22s97qy.js +4 -0
- package/dist/src/chunk-p9kt1sgr.js +6 -0
- package/dist/src/{chunk-9y5bcy28.js → chunk-pf282r5g.js} +4 -4
- package/dist/src/chunk-pnd4mrxy.js +4 -0
- package/dist/src/chunk-pqqteyj6.js +4 -0
- package/dist/src/chunk-qj1tbnv2.js +8 -0
- package/dist/src/chunk-qnh9egwr.js +4 -0
- package/dist/src/chunk-qy3khhf8.js +8 -0
- package/dist/src/chunk-r0vp315h.js +11 -0
- package/dist/src/chunk-r4j43b9s.js +237 -0
- package/dist/src/{chunk-4pfftt07.js → chunk-r54cxxze.js} +3 -3
- package/dist/src/chunk-r6pvhj33.js +325 -0
- package/dist/src/chunk-rb7aa5gr.js +54 -0
- package/dist/src/chunk-rdj50kb4.js +4 -0
- package/dist/src/chunk-rnd4vcas.js +4 -0
- package/dist/src/chunk-s3y3zfcx.js +14 -0
- package/dist/src/chunk-s4g43k75.js +5 -0
- package/dist/src/chunk-sfqe223f.js +311 -0
- package/dist/src/chunk-sqdrxjw5.js +7 -0
- package/dist/src/{chunk-0w1spptt.js → chunk-t54k47em.js} +4 -4
- package/dist/src/chunk-tek4pnvv.js +26 -0
- package/dist/src/chunk-tn74y7af.js +4 -0
- package/dist/src/chunk-tvq0nzam.js +5 -0
- package/dist/src/chunk-tx4f0h9c.js +6 -0
- package/dist/src/chunk-vdqag3fj.js +5 -0
- package/dist/src/chunk-vz5zzs57.js +4 -0
- package/dist/src/chunk-w4s2vfpj.js +4 -0
- package/dist/src/chunk-w5yypt53.js +42 -0
- package/dist/src/{chunk-r0f1q783.js → chunk-w68v64vh.js} +3 -3
- package/dist/src/chunk-whwj0pdk.js +5 -0
- package/dist/src/chunk-wnmqt1dc.js +4 -0
- package/dist/src/{chunk-8en08r7q.js → chunk-wpe46vsa.js} +3 -3
- package/dist/src/chunk-wxdjeb4k.js +27 -0
- package/dist/src/chunk-xcqzwf9j.js +247 -0
- package/dist/src/chunk-xezekwwn.js +5 -0
- package/dist/src/chunk-xf19m15s.js +4 -0
- package/dist/src/chunk-xghbxha4.js +4 -0
- package/dist/src/{chunk-jhnbfj19.js → chunk-xn9m3xc2.js} +5 -5
- package/dist/src/{chunk-a4k9rt7z.js → chunk-yqfz4vts.js} +3 -3
- package/dist/src/chunk-z8tvs8nk.js +5 -0
- package/dist/src/chunk-zm2rehqb.js +5 -0
- package/dist/src/chunk-zs6dqm35.js +4 -0
- package/dist/src/daemon/processEntry.js +2 -2
- package/dist/src/index.js +4 -4
- package/dist/src/runtime/bunRuntimeGuard.js +2 -2
- package/dist/src/utils/workers/iosBundleExtractWorker.js +2 -2
- package/ios/CameraPosterInjection/Injection/CameraPosterInjection.m +466 -0
- package/package.json +4 -3
- package/schemas/test-plan.schema.json +370 -52
- package/dist/src/chunk-09442h7v.js +0 -4
- package/dist/src/chunk-0e4gm1kj.js +0 -5
- package/dist/src/chunk-0eb8576f.js +0 -4
- package/dist/src/chunk-0rjm4nx7.js +0 -5
- package/dist/src/chunk-1zmh2eak.js +0 -4
- package/dist/src/chunk-28k63ha3.js +0 -5
- package/dist/src/chunk-2d4wmp8b.js +0 -4
- package/dist/src/chunk-32jpxz2y.js +0 -323
- package/dist/src/chunk-3jmvqygr.js +0 -238
- package/dist/src/chunk-3swvfhqt.js +0 -5
- package/dist/src/chunk-44bt78m9.js +0 -5
- package/dist/src/chunk-488vt2bp.js +0 -4
- package/dist/src/chunk-4fgdhcwx.js +0 -5
- package/dist/src/chunk-4jp2se4w.js +0 -4
- package/dist/src/chunk-4vhr9e4t.js +0 -4
- package/dist/src/chunk-4xd6zs3y.js +0 -15
- package/dist/src/chunk-51567pg8.js +0 -4
- package/dist/src/chunk-5agqsfev.js +0 -4
- package/dist/src/chunk-5d706gmr.js +0 -4
- package/dist/src/chunk-5kd4rqk7.js +0 -5
- package/dist/src/chunk-61t538bm.js +0 -4
- package/dist/src/chunk-6d3mmqxt.js +0 -54
- package/dist/src/chunk-6hyt398x.js +0 -5
- package/dist/src/chunk-6mnr8kpm.js +0 -4
- package/dist/src/chunk-79q5xsdc.js +0 -42
- package/dist/src/chunk-7bdgand3.js +0 -4
- package/dist/src/chunk-84cp9dw5.js +0 -4
- package/dist/src/chunk-86f2h5ww.js +0 -5
- package/dist/src/chunk-8cghfzb2.js +0 -19
- package/dist/src/chunk-9tf2p9y9.js +0 -5
- package/dist/src/chunk-a2sc4jm0.js +0 -5
- package/dist/src/chunk-aa5ng3d1.js +0 -4
- package/dist/src/chunk-b3h0a6ca.js +0 -4
- package/dist/src/chunk-b6a737qt.js +0 -4
- package/dist/src/chunk-bn64x5z5.js +0 -5
- package/dist/src/chunk-bvh649za.js +0 -12
- package/dist/src/chunk-c9tyfg4j.js +0 -26
- package/dist/src/chunk-cfsdfqnm.js +0 -4
- package/dist/src/chunk-cxyf04jc.js +0 -7
- package/dist/src/chunk-da08tx5v.js +0 -4
- package/dist/src/chunk-f2tc08m2.js +0 -4
- package/dist/src/chunk-f8tnk179.js +0 -5
- package/dist/src/chunk-f9s1kkhx.js +0 -5
- package/dist/src/chunk-fbp8a4rx.js +0 -4
- package/dist/src/chunk-fd2z0sze.js +0 -4
- package/dist/src/chunk-fk927f4q.js +0 -54
- package/dist/src/chunk-fxmr3a0f.js +0 -4
- package/dist/src/chunk-gaqwhd44.js +0 -4
- package/dist/src/chunk-ggtd5x5a.js +0 -5
- package/dist/src/chunk-gndcfrm7.js +0 -4
- package/dist/src/chunk-h3n4adc6.js +0 -310
- package/dist/src/chunk-h5pjbb83.js +0 -4
- package/dist/src/chunk-hgnnh302.js +0 -4
- package/dist/src/chunk-hmke8nhx.js +0 -5
- package/dist/src/chunk-j2bx12hn.js +0 -4
- package/dist/src/chunk-j70y1a2g.js +0 -4
- package/dist/src/chunk-js1jpyxp.js +0 -6
- package/dist/src/chunk-kbjq0qvb.js +0 -4
- package/dist/src/chunk-kfwx57xd.js +0 -4
- package/dist/src/chunk-kzwctna2.js +0 -4
- package/dist/src/chunk-m9ehyehy.js +0 -4
- package/dist/src/chunk-mct91p1f.js +0 -4
- package/dist/src/chunk-mf9spd4g.js +0 -5
- package/dist/src/chunk-mgrcansb.js +0 -4
- package/dist/src/chunk-mqc1d0eb.js +0 -6
- package/dist/src/chunk-n1zmpk0z.js +0 -4
- package/dist/src/chunk-ncyjf63g.js +0 -4
- package/dist/src/chunk-nr64d21q.js +0 -973
- package/dist/src/chunk-nwm2pq5v.js +0 -168
- package/dist/src/chunk-pm06b05d.js +0 -9
- package/dist/src/chunk-q50s00ry.js +0 -4
- package/dist/src/chunk-qwye1958.js +0 -14
- package/dist/src/chunk-r8z9pfve.js +0 -5
- package/dist/src/chunk-rdpgkjf6.js +0 -4
- package/dist/src/chunk-rkr0dks9.js +0 -5
- package/dist/src/chunk-rn84t3sf.js +0 -11
- package/dist/src/chunk-s123kn7n.js +0 -4
- package/dist/src/chunk-s73qn3fx.js +0 -4
- package/dist/src/chunk-sjn0nj4p.js +0 -5
- package/dist/src/chunk-sns0c35v.js +0 -7
- package/dist/src/chunk-t4dr5c8v.js +0 -8
- package/dist/src/chunk-tc8k9c1j.js +0 -4
- package/dist/src/chunk-teznhase.js +0 -4
- package/dist/src/chunk-ty9xgmz4.js +0 -4
- package/dist/src/chunk-tyazf3sk.js +0 -145
- package/dist/src/chunk-v6npjrjm.js +0 -5
- package/dist/src/chunk-vbvtzkwz.js +0 -5
- package/dist/src/chunk-vefd8qee.js +0 -8
- package/dist/src/chunk-vs9r72ta.js +0 -17
- package/dist/src/chunk-w2mwa0jk.js +0 -4
- package/dist/src/chunk-w88k0bgr.js +0 -4
- package/dist/src/chunk-wzdt0enk.js +0 -4
- package/dist/src/chunk-xhhv854c.js +0 -4
- package/dist/src/chunk-y58270hd.js +0 -4
- package/dist/src/chunk-yk0hmbex.js +0 -4
- package/dist/src/chunk-ympy4fdz.js +0 -28
- package/dist/src/chunk-yw436axy.js +0 -4
- package/dist/src/chunk-z04jrpjy.js +0 -5
- package/dist/src/chunk-z2xznczw.js +0 -4
- package/dist/src/chunk-z4xnrgps.js +0 -4
- package/dist/src/chunk-z7csyszv.js +0 -4
- package/dist/src/chunk-z8t0v07j.js +0 -11
- package/dist/src/chunk-z916af47.js +0 -228
- package/dist/src/chunk-zcr8he8q.js +0 -5
- package/dist/src/chunk-zd9vmkzn.js +0 -9
- package/dist/src/chunk-zj939v0h.js +0 -5
- package/dist/src/chunk-zkdjwtc1.js +0 -4
- package/dist/src/chunk-zkv5kzt6.js +0 -4
|
@@ -0,0 +1,153 @@
|
|
|
1
|
+
"""Bumble peripheral owned by one AutoMobile session. Stdout is JSON lines only."""
|
|
2
|
+
|
|
3
|
+
import asyncio
|
|
4
|
+
import json
|
|
5
|
+
import sys
|
|
6
|
+
|
|
7
|
+
# Stdin EOF is only watched once the transport is open, so a hung open must end on its own.
|
|
8
|
+
OPEN_TRANSPORT_TIMEOUT_S = 20
|
|
9
|
+
|
|
10
|
+
|
|
11
|
+
def emit(event, command_id=None, **fields):
|
|
12
|
+
print(json.dumps({"event": event, **({"id": command_id} if command_id is not None else {}), **fields}), flush=True)
|
|
13
|
+
|
|
14
|
+
|
|
15
|
+
async def open_transport_bounded(opener, spec, timeout_s=OPEN_TRANSPORT_TIMEOUT_S):
|
|
16
|
+
# TimeoutError has an empty message, which would surface as a bare "BLE sidecar: ".
|
|
17
|
+
try:
|
|
18
|
+
return await asyncio.wait_for(opener(spec), timeout_s)
|
|
19
|
+
except asyncio.TimeoutError:
|
|
20
|
+
raise TimeoutError(f"Timed out after {timeout_s} s opening BLE transport {spec}") from None
|
|
21
|
+
|
|
22
|
+
|
|
23
|
+
def decode_value(value):
|
|
24
|
+
return bytes.fromhex(value["value"]) if value.get("encoding") == "hex" else value["value"].encode("utf-8")
|
|
25
|
+
|
|
26
|
+
|
|
27
|
+
async def main():
|
|
28
|
+
# Imports stay inside the error boundary so a damaged venv reports a protocol error.
|
|
29
|
+
from bumble.device import Device
|
|
30
|
+
from bumble.transport import open_transport
|
|
31
|
+
from bumble.core import AdvertisingData, UUID
|
|
32
|
+
from bumble.gatt import Service, Characteristic
|
|
33
|
+
from bumble.profiles.battery_service import BatteryService
|
|
34
|
+
from bumble.profiles.heart_rate_service import HeartRateService
|
|
35
|
+
from bumble.hci import Address
|
|
36
|
+
|
|
37
|
+
config_line = await asyncio.to_thread(sys.stdin.readline)
|
|
38
|
+
if not config_line:
|
|
39
|
+
return
|
|
40
|
+
config = json.loads(config_line)
|
|
41
|
+
transport = await open_transport_bounded(open_transport, config["transport"])
|
|
42
|
+
async with transport as (source, sink):
|
|
43
|
+
device = Device.with_hci(config["name"], Address(config["address"]), source, sink)
|
|
44
|
+
level = [87]
|
|
45
|
+
heart_rate = [72]
|
|
46
|
+
services = []
|
|
47
|
+
characteristics = {}
|
|
48
|
+
battery = None
|
|
49
|
+
if "battery" in config["presets"]:
|
|
50
|
+
# BatteryService reads and notifies through its callback, not characteristic.value.
|
|
51
|
+
battery = BatteryService(lambda _: level[0])
|
|
52
|
+
services.append(battery)
|
|
53
|
+
characteristics["battery"] = battery.battery_level_characteristic
|
|
54
|
+
if "heartRate" in config["presets"]:
|
|
55
|
+
heart = HeartRateService(read_heart_rate_measurement=lambda _: HeartRateService.HeartRateMeasurement(heart_rate[0]))
|
|
56
|
+
services.append(heart)
|
|
57
|
+
characteristics["heartRate"] = heart.heart_rate_measurement_characteristic
|
|
58
|
+
for service in config.get("services") or []:
|
|
59
|
+
custom = []
|
|
60
|
+
for spec in service["characteristics"]:
|
|
61
|
+
properties = Characteristic.Properties(0)
|
|
62
|
+
if "read" in spec["properties"]:
|
|
63
|
+
properties |= Characteristic.Properties.READ
|
|
64
|
+
if "notify" in spec["properties"]:
|
|
65
|
+
properties |= Characteristic.Properties.NOTIFY
|
|
66
|
+
characteristic = Characteristic(spec["uuid"], properties, Characteristic.READABLE if "read" in spec["properties"] else 0, decode_value(spec["initialValue"]) if "initialValue" in spec else b"")
|
|
67
|
+
key = str(UUID(spec["uuid"]))
|
|
68
|
+
if key in characteristics:
|
|
69
|
+
raise ValueError("Duplicate custom characteristic UUID")
|
|
70
|
+
characteristics[key] = characteristic
|
|
71
|
+
custom.append(characteristic)
|
|
72
|
+
services.append(Service(service["uuid"], custom))
|
|
73
|
+
device.add_services(services)
|
|
74
|
+
connections = {}
|
|
75
|
+
subscriptions = set()
|
|
76
|
+
|
|
77
|
+
def status():
|
|
78
|
+
return {"running": True, "advertising": not connections and bool(device.is_advertising), "connected": list(connections.values()), "subscribed": sorted({uuid for _, uuid in subscriptions}), "pythonReady": True, "bumbleReady": True}
|
|
79
|
+
|
|
80
|
+
def on_connection(connection):
|
|
81
|
+
connections[connection.handle] = str(connection.peer_address)
|
|
82
|
+
emit("connected", status=status())
|
|
83
|
+
|
|
84
|
+
def on_disconnection(_reason):
|
|
85
|
+
connections.pop(connection.handle, None)
|
|
86
|
+
subscriptions.difference_update({entry for entry in subscriptions if entry[0] == connection.handle})
|
|
87
|
+
emit("disconnected", status=status())
|
|
88
|
+
|
|
89
|
+
connection.on("disconnection", on_disconnection)
|
|
90
|
+
|
|
91
|
+
def on_subscription(bearer, characteristic, notify_enabled, indicate_enabled):
|
|
92
|
+
connection = getattr(bearer, "connection", bearer)
|
|
93
|
+
entry = (connection.handle, str(characteristic.uuid))
|
|
94
|
+
if notify_enabled or indicate_enabled:
|
|
95
|
+
subscriptions.add(entry)
|
|
96
|
+
else:
|
|
97
|
+
subscriptions.discard(entry)
|
|
98
|
+
|
|
99
|
+
device.on("connection", on_connection)
|
|
100
|
+
device.on("characteristic_subscription", on_subscription)
|
|
101
|
+
await device.power_on()
|
|
102
|
+
advertising = [(AdvertisingData.COMPLETE_LOCAL_NAME, config["name"].encode("utf-8"))]
|
|
103
|
+
preset_uuids = b""
|
|
104
|
+
if battery:
|
|
105
|
+
preset_uuids += bytes([0x0F, 0x18])
|
|
106
|
+
if "heartRate" in config["presets"]:
|
|
107
|
+
preset_uuids += bytes([0x0D, 0x18])
|
|
108
|
+
if preset_uuids:
|
|
109
|
+
advertising.append((AdvertisingData.INCOMPLETE_LIST_OF_16_BIT_SERVICE_CLASS_UUIDS, preset_uuids))
|
|
110
|
+
device.advertising_data = bytes(AdvertisingData(advertising))
|
|
111
|
+
# A connection pauses advertising; restart after disconnection.
|
|
112
|
+
await device.start_advertising(auto_restart=True)
|
|
113
|
+
emit("advertising", status=status())
|
|
114
|
+
emit("ready", status=status())
|
|
115
|
+
while line := await asyncio.to_thread(sys.stdin.readline):
|
|
116
|
+
command = {}
|
|
117
|
+
try:
|
|
118
|
+
command = json.loads(line)
|
|
119
|
+
action = command["action"]
|
|
120
|
+
if action == "stop":
|
|
121
|
+
emit("stopped", command.get("id"))
|
|
122
|
+
return
|
|
123
|
+
if action == "status":
|
|
124
|
+
emit("status", command["id"], status=status())
|
|
125
|
+
continue
|
|
126
|
+
if action != "notify":
|
|
127
|
+
raise ValueError("Unknown sidecar action")
|
|
128
|
+
key = command["characteristic"]
|
|
129
|
+
if key not in ("battery", "heartRate"):
|
|
130
|
+
key = str(UUID(key))
|
|
131
|
+
characteristic = characteristics[key]
|
|
132
|
+
if not characteristic.properties & Characteristic.Properties.NOTIFY:
|
|
133
|
+
raise ValueError("Characteristic does not support notify")
|
|
134
|
+
if key == "battery":
|
|
135
|
+
if not 0 <= command["level"] <= 100:
|
|
136
|
+
raise ValueError("Battery level must be 0-100")
|
|
137
|
+
level[0] = command["level"]
|
|
138
|
+
elif key == "heartRate":
|
|
139
|
+
heart_rate[0] = command["bpm"]
|
|
140
|
+
else:
|
|
141
|
+
characteristic.value = decode_value(command["value"])
|
|
142
|
+
await device.notify_subscribers(characteristic)
|
|
143
|
+
emit("notified", command["id"], status=status())
|
|
144
|
+
except Exception as error:
|
|
145
|
+
emit("error", command.get("id"), message=str(error))
|
|
146
|
+
|
|
147
|
+
|
|
148
|
+
if __name__ == "__main__":
|
|
149
|
+
try:
|
|
150
|
+
asyncio.run(main())
|
|
151
|
+
except Exception as error:
|
|
152
|
+
emit("error", message=str(error))
|
|
153
|
+
sys.exit(1)
|
|
@@ -1,18 +1,18 @@
|
|
|
1
1
|
// @bun
|
|
2
|
-
import{
|
|
3
|
-
`);if(t[t.length-1]==="")t.pop();return t}function gt(s,t){return/^[\x20-\x7E]+$/.test(t)&&!/[\\^#]/.test(t)&&!(s==="unzip"&&t.startsWith("-"))}function bt(s,t,e){let r=Le(t),n=Le(e);if(r.length!==n.length)throw new
|
|
2
|
+
import{Z5,Cv,Dv,yt,zV,Q5}from"./chunk-kh5n7m6w.js";import{D,d,Z,_w,xw,tt,ca,Mt,c3,vL,xT}from"./chunk-zm2rehqb.js";import*as _ from"fs/promises";import*as te from"fs";import*as b from"path";import*as Ne from"child_process";import*as st from"crypto";import*as ot from"readline";function T(s){let{name:t,inputSchema:e,description:r,run:n,...i}=s;if(e.type!=="object")throw Error(`JSON schema for tool "${t}" must be an object, but got ${e.type}`);return{...i,type:"custom",name:t,input_schema:e,description:r,run:n,parse:(o)=>o}}var L=Dv.promises,G=448,mt=384;function ie(s,t){let e=yt.relative(s,t);return e===""||!e.startsWith(".."+yt.sep)&&e!==".."&&!yt.isAbsolute(e)}async function we(s,t){for(let e of s)if(ie(await H(yt.resolve(e)),t))return e;return}var ut=40;function K(s){let t=s?.code;return typeof t==="string"?t:void 0}async function H(s){let t=[],e=s,r=0;for(;;){let n;try{n=await L.realpath(e)}catch(i){let o;try{o=(await L.lstat(e)).isSymbolicLink()}catch(a){let c=K(a);if(c!=="ENOENT"&&c!=="ENOTDIR")throw a;let f=yt.dirname(e);if(f===e)throw a;t.push(yt.basename(e)),e=f;continue}if(!o)throw i;if(++r>ut)throw Object.assign(Error("too many levels of symbolic links"),{code:"ELOOP"});e=yt.resolve(yt.dirname(e),await L.readlink(e));continue}return t.length?yt.join(n,...t.reverse()):n}}async function Te(s,t,e){let r=e?.allowedRoots??[],n=await H(yt.resolve(s)),i;try{i=await H(yt.resolve(n,t))}catch(a){throw new Mt(U(a,`path ${JSON.stringify(t)}`))}if(ie(n,i)||await we(r,i)!==void 0)return i;let o=r.length?"the session's working directory and its other permitted directories":"the session's working directory";throw new Mt(`path ${JSON.stringify(t)} is outside ${o}`)}async function _e(s,t){let e=yt.dirname(s),r=yt.join(e,`.tmp-${process.pid}-${Cv.randomUUID()}`),n=await L.stat(s).then((o)=>o.mode&511,()=>{return}),i;try{if(i=await L.open(r,"wx",mt),n!==void 0)await i.chmod(n);await i.writeFile(t,"utf-8"),await i.sync(),await i.close(),i=void 0,await L.rename(r,s)}catch(o){if(i)await i.close().catch(()=>{});throw await L.unlink(r).catch(()=>{}),o}}function U(s,t){let e=K(s);switch(e){case"ENOENT":return`${t}: no such file or directory`;case"EACCES":case"EPERM":return`${t}: permission denied`;case"ENOTDIR":return`${t}: not a directory`;case"EISDIR":return`${t}: is a directory`;case"ELOOP":return`${t}: too many levels of symbolic links`;case"ENAMETOOLONG":return`${t}: file name too long`;case"ENOSPC":return`${t}: no space left on device`;case"EMFILE":case"ENFILE":return`${t}: too many open files`;default:return`${t}: ${e!==void 0?`i/o error (${e})`:"i/o error"}`}}var M=Dv.promises,pt=Q5.promisify(Z5.execFile);async function wt(s){let{client:t,sessionId:e}=s;if(!t)return async()=>{};let r=tt(t),n=s.session;if(!n){if(e===void 0)return async()=>{};r.warn("AgentToolContext.sessionId is deprecated and costs an extra session fetch; fetch the session once and set `session` instead",{component:"agent-tool-context"}),n=await t.beta.sessions.retrieve(e)}let i=yt.resolve(s.workdir,"skills"),o=[];for(let a of n.agent.skills)try{let c=await t.beta.skills.versions.retrieve(a.version,{skill_id:a.skill_id}),f=yt.basename(c.name.trim());if(f===""||f==="."||f==="..")f=a.skill_id;let l=yt.resolve(i,f);if(l!==i&&!l.startsWith(i+yt.sep)){r.warn("skill name escapes the skills dir; skipping",{component:"agent-tool-context",name:c.name});continue}let h=await t.beta.skills.versions.download(c.id,{skill_id:a.skill_id});await M.rm(l,{recursive:!0,force:!0}),await M.mkdir(l,{recursive:!0,mode:G}),o.push(l),await Ae(h,l),r.info("downloaded skill",{component:"agent-tool-context",skill_id:a.skill_id,version:c.id,dest:l})}catch(c){r.warn("failed to download skill",{component:"agent-tool-context",skill_id:a.skill_id,error:String(c)})}return async()=>{for(let a of o)await M.rm(a,{recursive:!0,force:!0}).catch((c)=>{r.warn("failed to clean up skill",{component:"agent-tool-context",dest:a,error:String(c)})})}}function _t(s){for(let t of s){let e=t.trim();if(!e)continue;if(yt.isAbsolute(e)||e.split(/[\\/]/).includes(".."))throw new Z(`refusing to extract unsafe archive member: ${e}`)}}var ge="skill archive listing is inconsistent; refusing to extract",St={unzip:new Set(["-","d","?"]),tar:new Set(["-","d","C"])};function Le(s){let t=s.split(`
|
|
3
|
+
`);if(t[t.length-1]==="")t.pop();return t}function gt(s,t){return/^[\x20-\x7E]+$/.test(t)&&!/[\\^#]/.test(t)&&!(s==="unzip"&&t.startsWith("-"))}function bt(s,t,e){let r=Le(t),n=Le(e);if(r.length!==n.length)throw new Z(ge);let i=[],o=[];return r.forEach((a,c)=>{if(St[s].has(n[c].charAt(0))){i.push(a);return}if(!gt(s,a))throw new Z(`refusing to extract archive: cannot safely exclude member ${JSON.stringify(a)}`);o.push(a)}),{plain:i,special:o}}async function $e(s){for(let t of await M.readdir(s,{withFileTypes:!0}))if(t.isDirectory())await $e(yt.join(s,t.name));else if(!t.isFile())throw new Z(ge)}async function Se(s,t){try{let{stdout:e}=await pt(s,t);return e}catch(e){if(K(e)==="ENOENT")throw new Z(`skill extraction requires the \`${s}\` command, but it was not found on PATH`);throw e}}function Et(s){let t,e=!1;for(let r of s){let n=r.trim().split("/").filter((o)=>o!==""&&o!==".");if(n.length===0)continue;let i=n[0];if(t===void 0)t=i;else if(i!==t)return"";if(n.length>1)e=!0}return t!==void 0&&e?t:""}async function Ae(s,t){let e=yt.join(t,`.skill-archive-${process.pid}-${Date.now()}`);if(!s.body)throw new Z("skill download response had no body");await zV.promises.pipeline(zV.Readable.fromWeb(s.body),Dv.createWriteStream(e));let r=yt.join(yt.dirname(t),`.skill-stage-${process.pid}-${Date.now()}`),n=yt.join(yt.dirname(t),`.skill-exclude-${process.pid}-${Date.now()}`);try{let i=await vt(e,4),o=i.length>=4&&i[0]===80&&i[1]===75&&i[2]===3&&i[3]===4,a=o?"unzip":"tar",c=await Se(a,o?["-Z1",e]:["-tf",e]),f=await Se(a,o?["-Z","--h","--t",e]:["-tvf",e]),{plain:l,special:h}=bt(a,c,f);_t([...l,...h]);let y=Et(l);if(await M.mkdir(r,{recursive:!0,mode:G}),l.length>0)await Se(a,await Ot(a,e,r,h,n));await $e(r);let S=y?yt.join(r,y):r,N=await M.readdir(S).catch((E)=>{throw K(E)==="ENOENT"?new Z(ge):E});for(let E of N)await M.rename(yt.join(S,E),yt.join(t,E))}finally{await M.rm(e,{force:!0}),await M.rm(n,{force:!0}),await M.rm(r,{recursive:!0,force:!0})}}async function Ot(s,t,e,r,n){let i=r.map((o)=>o.replace(/[*?[\\]/g,"\\$&"));if(s==="unzip")return["-oq",t,"-d",e,...i.length>0?["-x",...i]:[]];if(i.length===0)return["-xf",t,"-C",e];return await M.writeFile(n,i.join(`
|
|
4
4
|
`)+`
|
|
5
|
-
`,{flag:"wx",mode:384}),["-xf",t,"-C",e,"-X",n]}async function
|
|
6
|
-
${s}`,"utf-8").digest("hex")}var Wt=30000,Ut=100,jt=20,Bt=16,Yt=32,qt=8,zt=50;class A extends
|
|
7
|
-
${e.memoryStoreId}`);for await(let[r,n]of d(this,u,"m",fe).call(this,e.memoryStoreId,"full"))if(await d(this,u,"m",Ie).call(this,e,r,n.content??""))e.baseline.set(r,n.content_sha256)},qe=async function(e,r,n,i,o){let a=e.baseline.get(r);if(i!==void 0)e.pendingDeletes.delete(r);if(!n){if(i===void 0){e.pendingDeletes.delete(r);return}if(a!==void 0){if(i===a){let y=await d(this,u,"m",ze).call(this,e,r,a);if(y===void 0)return;if(y===a)return a;i=y}if(e.readOnly)d(this,m,"f").warn("memory deleted remotely but edited locally; keeping the file, which a read-only store cannot push",{path:r,memory_store_id:e.memoryStoreId});else if(e.refusedShas.get(r)!==i)d(this,m,"f").info("memory deleted remotely but edited locally; re-creating it from the file",{path:r,memory_store_id:e.memoryStoreId})}if(e.readOnly)return;if(e.refusedShas.get(r)===i)return;return await d(this,u,"m",he).call(this,e,r,i,void 0)}let c=n.content_sha256,f=c!==a,l=i!==void 0&&i!==a&&i!==c,h=!e.readOnly&&l;if(i===void 0&&a!==void 0){if(f)d(this,m,"f").warn("memory deleted locally but changed remotely; restoring the remote version",{path:r,memory_store_id:e.memoryStoreId}),e.pendingDeletes.delete(r),o.push([r,n]);return a}if(f){if(i===c)return c;if(l)d(this,m,"f").warn("memory changed both locally and remotely; keeping the remote version",{path:r,memory_store_id:e.memoryStoreId});return o.push([r,n]),a}if(h){if(e.refusedShas.get(r)===i)return c;return await d(this,u,"m",he).call(this,e,r,i,n)??c}return c},ze=async function(e,r,n){let i;try{i=await e.files.hashFile(r)}catch(o){if(!(o instanceof p)&&!Y(o))throw o;return n}if(i===null)return;if(i!==n)return i;try{await e.files.remove(r)}catch(o){if(!(o instanceof p)&&!Y(o))throw o;return d(this,m,"f").warn("failed to remove memory deleted remotely",{path:r,memory_store_id:e.memoryStoreId,error:String(o)}),n}return},Ie=async function(e,r,n){try{await e.files.put(r,n)}catch(i){if(!(i instanceof p)&&!Y(i))throw i;return d(this,m,"f").warn("failed to write memory",{path:r,memory_store_id:e.memoryStoreId,error:String(i)}),!1}return!0},He=async function(e,r){if(r.length===0)return;let n=async(a,c)=>{let f;try{f=await d(this,k,"f").beta.memoryStores.memories.retrieve(c.id,{memory_store_id:e.memoryStoreId,view:"full"})}catch(l){if(
|
|
8
|
-
`),ee=102400,Xt=2000,Jt=200;class ct extends
|
|
5
|
+
`,{flag:"wx",mode:384}),["-xf",t,"-C",e,"-X",n]}async function vt(s,t){let e=await M.open(s,"r");try{let r=Buffer.alloc(t),{bytesRead:n}=await e.read(r,0,t,0);return r.subarray(0,n)}finally{await e.close()}}var w=Dv.promises,j=Dv.constants,Fe=448,kt=384,It=448,Ee=j.O_NOFOLLOW??0,Rt=j.O_NONBLOCK??0,p=(()=>{class s extends Error{constructor(t,e){super(`path ${JSON.stringify(e)} ${t}`);this.name="FileStoreError",this.reason=t,this.relPath=e}}return s.ESCAPES_ROOT="escapes the store root",s.IS_A_SYMLINK="is a symlink",s.NOT_A_FILE="is not a regular file",s.NOT_A_DIRECTORY="is not a directory",s.NOT_UTF8="is not valid utf-8",s.MOVE_DESTINATION_EXISTS="already exists",s})();function Oe(s){return s.startsWith("/")&&!s.split("/").includes("..")}var be=(()=>{class s{constructor(t,e,r=!1){this.hashes=new Map,this.rootPath=t,this.removedOnDispose=e,this.decoder=r?new TextDecoder("utf-8",{fatal:!0}):void 0}static async open(t,e){if(!Nt())throw Error("FileStore requires O_NOFOLLOW support on this platform");let r=!1;try{await w.lstat(t)}catch(n){if(n.code!=="ENOENT")throw n;r=!0}return new s(yt.resolve(t),r,e?.utf8??!1)}async createRoot(){await Tt(this.rootPath)}root(){return{path:this.rootPath,removedOnDispose:this.removedOnDispose}}async dispose(){if(!this.removedOnDispose)return;await w.rm(this.rootPath,{recursive:!0,force:!0})}async put(t,e,r){let n=t.replace(/\\/g,"/");if(n.endsWith("/")||n.endsWith("/.")||n===""||n===".")throw new p(p.NOT_A_FILE,t);let i=this.resolveUnderRoot(t),o=typeof e==="string"?_w(e):e;this.requireUtf8(t,o),await xe(this.rootPath,yt.dirname(i)),await Lt(i,o,r?.executable??!1)}async get(t){let e=this.resolveUnderRoot(t),r;try{r=await Pe(t,e)}catch(i){if(i.code==="ENOENT")return null;throw i}let n;try{let i=await r.readFile();n=new Uint8Array(i.buffer,i.byteOffset,i.byteLength)}finally{await r.close()}return this.requireUtf8(t,n),n}async ls(t="/"){let e=this.resolveUnderRoot(t);return new Set((await De(this.rootPath,t,e)).map(([r])=>r))}async findSymlinks(t="/"){let e=this.resolveUnderRoot(t);return At(this.rootPath,t,e)}async hashtree(t="/"){let e=this.resolveUnderRoot(t),r=se.nowNs(),n=Object.create(null);for(let[i,o]of await De(this.rootPath,t,e)){let a=await this.hashViaCache(i,o,r);if(a!==null)n[i]=a}return n}async hashFile(t){let e=this.resolveUnderRoot(t),r;try{r=await w.lstat(e,{bigint:!0})}catch(i){if(i.code==="ENOENT")return null;throw i}if(r.isSymbolicLink())throw new p(p.IS_A_SYMLINK,t);if(!r.isFile())throw new p(p.NOT_A_FILE,t);let n=yt.relative(this.rootPath,e).split(yt.sep).join("/");return this.hashViaCache(n,e,se.nowNs())}async move(t,e){let r=this.resolveUnderRoot(t),n=this.resolveUnderRoot(e);if(r===this.rootPath||n===this.rootPath)return;if(await w.stat(n).then(()=>!0,()=>!1))throw new p(p.MOVE_DESTINATION_EXISTS,e);await xe(this.rootPath,yt.dirname(n)),await w.rename(r,n)}async remove(t){let e=this.resolveUnderRoot(t);if(e===this.rootPath)return;let r;try{r=await w.lstat(e,{bigint:!0})}catch(n){if(n.code==="ENOENT")return;throw n}if(r.isDirectory())await w.rm(e,{recursive:!0,force:!0});else try{await w.unlink(e)}catch(n){if(n.code!=="ENOENT")throw n}}resolveUnderRoot(t){let e=t.replace(/\\/g,"/").replace(/^\/+/,""),r=e.split("/").filter((n)=>n!==""&&n!==".");if(yt.posix.isAbsolute(e)||r.includes(".."))throw new p(p.ESCAPES_ROOT,t);return r.length===0?this.rootPath:yt.join(this.rootPath,...r)}requireUtf8(t,e){if(!this.decoder)return;try{this.decoder.decode(e)}catch{throw new p(p.NOT_UTF8,t)}}async hashViaCache(t,e,r){let n;try{n=await w.lstat(e,{bigint:!0})}catch(a){if(a.code==="ENOENT")return null;throw a}if(!n.isFile())return null;let i=this.hashes.get(t),o;if(i!==void 0&&Dt(i,n))o=i.sha;else try{o=await se.hashFile(e)}catch(a){let c=a.code;if(c==="ENOENT"||a instanceof p)return null;if(c==="ELOOP"||c==="EMLINK")return null;throw a}if(Ct(n,r))this.hashes.set(t,{mtimeNs:n.mtimeNs,ctimeNs:n.ctimeNs,size:n.size,sha:o});return o}}return s.isPathLegal=Oe,s})();function Nt(){return Ee!==0}async function Tt(s){let t=[],e=s;for(;;){try{await w.stat(e);break}catch(n){let i=n.code;if(i!=="ENOENT"&&i!=="ENOTDIR"&&i!=="ELOOP")throw n}t.push(e);let r=yt.dirname(e);if(r===e)break;e=r}for(let r of t.reverse())try{await w.mkdir(r,{mode:Fe})}catch(n){if(n.code!=="EEXIST")throw n}}async function xe(s,t){let e=yt.relative(s,t);if(e==="")return;let r=s;for(let n of e.split(yt.sep)){r=yt.join(r,n);try{await w.mkdir(r,{mode:Fe})}catch(i){if(i.code!=="EEXIST")throw i}}}async function Lt(s,t,e){let r=e?It:kt,n=yt.join(yt.dirname(s),`.fs-${Cv.randomBytes(8).toString("hex")}.tmp`),i;try{i=await w.open(n,j.O_WRONLY|j.O_CREAT|j.O_EXCL|Ee,r),await i.writeFile(t),await i.close(),i=void 0,await w.rename(n,s)}catch(o){if(i)await i.close().catch(()=>{});throw await w.unlink(n).catch(()=>{}),o}}async function Pe(s,t){let e;try{e=await w.open(t,j.O_RDONLY|Ee|Rt)}catch(r){let n=r.code;if(n==="ELOOP"||n==="EMLINK")throw new p(p.IS_A_SYMLINK,s);throw r}try{if(!(await e.stat()).isFile())throw new p(p.NOT_A_FILE,s)}catch(r){throw await e.close().catch(()=>{}),r}return e}async function $t(s){let t=Cv.createHash("sha256"),e=await Pe(yt.basename(s),s),r=new Uint8Array(1048576);try{for(;;){let{bytesRead:n}=await e.read(r,0,r.length);if(n===0)break;t.update(r.subarray(0,n))}}finally{await e.close()}return t.digest("hex")}async function De(s,t,e){if(!await xt(t,e))return[];let r=[];return await We(e,(n,i)=>{if(i.isFile())r.push([yt.relative(s,n).split(yt.sep).join("/"),n])}),r.sort(),r}async function At(s,t,e){let r=(o)=>yt.relative(s,o).split(yt.sep).join("/"),n;try{n=await w.lstat(e,{bigint:!0})}catch(o){let a=o.code;if(a==="ENOENT"||a==="ENOTDIR")return new Set;throw o}if(n.isSymbolicLink())return new Set([r(e)]);if(!n.isDirectory())throw new p(p.NOT_A_DIRECTORY,t);let i=new Set;return await We(e,(o,a)=>{if(a.isSymbolicLink())i.add(r(o))}),i}async function xt(s,t){let e;try{e=await w.lstat(t,{bigint:!0})}catch(r){let n=r.code;if(n==="ENOENT"||n==="ENOTDIR")return!1;throw r}if(!e.isDirectory())throw new p(p.NOT_A_DIRECTORY,s);return!0}async function We(s,t){let e=[s];while(e.length){let r=e.pop(),n;try{n=await w.readdir(r,{withFileTypes:!0})}catch(i){if(i.code==="ENOENT")continue;throw i}for(let i of n){let o=yt.join(r,i.name);if(t(o,i),i.isDirectory()&&!i.isSymbolicLink())e.push(o)}}}function Dt(s,t){return t.mtimeNs===s.mtimeNs&&t.ctimeNs===s.ctimeNs&&t.size===s.size}function Ct(s,t){return(s.mtimeNs>s.ctimeNs?s.mtimeNs:s.ctimeNs)<t-se.timestampTrustMarginNs}var Ft=2000000000n,se={hashFile:$t,timestampTrustMarginNs:Ft,nowNs:()=>BigInt(Date.now())*1000000n},Ue=be,Ce=Symbol.asyncDispose;if(Ce)Object.defineProperty(be.prototype,Ce,{value:be.prototype.dispose,configurable:!0,writable:!0});var u,k,oe,V,ae,m,B,ce,I,je,le,Be,Ye,Me,ve,ke,qe,ze,Ie,He,Ge,fe,he,Ke,Ve,Pt=30000,q=".anthropic-memory-store",Je=1;function Xe(s){return Cv.createHash("sha256").update(`version ${Je}
|
|
6
|
+
${s}`,"utf-8").digest("hex")}var Wt=30000,Ut=100,jt=20,Bt=16,Yt=32,qt=8,zt=50;class A extends Z{constructor(s,t){super(s);if(this.name="SessionMemoryError",t!==void 0)this.cause=t}}class Ze{constructor(s,t,e){this.mode=s,this.cap=t,this.waiveWindow=e,this.attempted=0,this.capped=0,this.suppressed=0}takeSlot(){if(this.attempted>=this.cap)return this.capped++,!1;return this.attempted++,!0}}var Ht=(()=>{class s{constructor(t,e){u.add(this),k.set(this,void 0),oe.set(this,void 0),V.set(this,void 0),ae.set(this,void 0),m.set(this,void 0),B.set(this,void 0),ce.set(this,!1),I.set(this,[]),D(this,k,t,"f"),D(this,oe,e.workdir,"f"),D(this,V,e.syncIntervalMs??c3,"f"),vL(d(this,V,"f"),"syncIntervalMs"),D(this,ae,e.syncDeletions??"enabled","f"),D(this,m,tt(t),"f"),D(this,B,Date.now(),"f")}get roots(){return d(this,I,"f").map((t)=>t.files.root().path)}get readOnlyRoots(){return d(this,I,"f").filter((t)=>t.readOnly).map((t)=>t.files.root().path)}async download(t){for(let e of t.resources){if(e.type!=="memory_store")continue;let r=d(this,u,"m",je).call(this,e),n;try{if(n={memoryStoreId:e.memory_store_id,files:await Ue.open(r,{utf8:!0}),readOnly:e.access==="read_only",baseline:new Map,refusedShas:new Map,pendingDeletes:new Map,sentShas:new Map},!n.files.root().removedOnDispose)throw new A(`something already exists at the memory store's path: ${r} (memory_store_id=${e.memory_store_id}); it must not exist when the session starts`);try{await n.files.createRoot()}catch(i){if(!Y(i))throw i;throw new A(`cannot create the memory store's folder: ${r} (memory_store_id=${e.memory_store_id}): ${i}; the worker host must make this mount path writable`,i)}await d(this,u,"m",ke).call(this,n),d(this,m,"f").info("downloaded memories",{count:n.baseline.size,memory_store_id:n.memoryStoreId,dest:n.files.root().path}),d(this,I,"f").push(n)}catch(i){if(n)await n.files.dispose().catch(()=>{});if(i instanceof A)throw i;throw new A(`failed to download memory store memory_store_id=${e.memory_store_id}: ${i}`,i)}}D(this,B,Date.now(),"f")}async finish(){if(d(this,ce,"f"))throw new Z("finish() was already called: it is the session's last sync and runs once");D(this,ce,!0,"f"),await this.syncAll(!0)}async syncAll(t){await Promise.all(d(this,I,"f").map((e)=>d(this,u,"m",Be).call(this,e,t))),D(this,B,Date.now(),"f")}async syncIfDue(){if(Date.now()-d(this,B,"f")<d(this,V,"f"))return;await this.syncAll(!1)}async flushWrites(t){await Promise.all(d(this,I,"f").map((e)=>d(this,u,"m",Ye).call(this,e,t)))}async dispose(){for(let t of d(this,I,"f")){let e=t.files.root();try{let r=await d(this,u,"m",le).call(this,t);if(!r.markerOk&&Object.keys(r.files).length>0){d(this,m,"f").warn(`${r.distrustReason}; leaving the memory store folder on disk`,{root:e.path,memory_store_id:t.memoryStoreId});continue}await t.files.dispose()}catch(r){if(!(r instanceof p)&&!Y(r))throw r;d(this,m,"f").warn("failed to remove the memory store folder",{root:t.files.root().path,memory_store_id:t.memoryStoreId,error:String(r)});continue}if(e.removedOnDispose)d(this,m,"f").info("removed memory store dir",{dest:e.path,memory_store_id:t.memoryStoreId})}}}return k=new WeakMap,oe=new WeakMap,V=new WeakMap,ae=new WeakMap,m=new WeakMap,B=new WeakMap,ce=new WeakMap,I=new WeakMap,u=new WeakSet,je=function(e){if(e.mount_path){if(!Oe(e.mount_path))throw new A(`memory store mount_path is not a clean absolute path: ${JSON.stringify(e.mount_path)} (memory_store_id=${e.memory_store_id})`);return e.mount_path}return yt.join(d(this,oe,"f"),"memory",e.name||e.memory_store_id)},le=async function(e){let r=await e.files.hashtree(),n=r[q];if(delete r[q],n===Xe(e.memoryStoreId))return{files:r,markerOk:!0,distrustReason:null};return{files:r,markerOk:!1,distrustReason:n!==void 0?"the marker file does not match this store":"the marker file is gone"}},Be=async function(e,r){try{let n=await d(this,u,"m",le).call(this,e),i=n.files;if(!n.markerOk){if(Object.keys(i).length>0){d(this,m,"f").warn(`${n.distrustReason}; leaving the memory store folder as found and not syncing`,{root:e.files.root().path,memory_store_id:e.memoryStoreId});return}await d(this,u,"m",Me).call(this,e,"the folder or its marker is gone");return}let o=new Map;for await(let[h,y]of d(this,u,"m",fe).call(this,e.memoryStoreId))o.set(h,y);if(d(this,u,"m",ve).call(this,e,o),Object.keys(i).length===0&&e.baseline.size>1){await d(this,u,"m",Me).call(this,e,"every memory file is gone at once");return}let a=new Ze(d(this,ae,"f"),Math.max(qt,Math.min(zt,Math.floor(e.baseline.size/4))),r),c=[],f=new Map,l=[...new Set([...o.keys(),...Object.keys(i),...e.baseline.keys()])].sort();for(let h of l){let y=o.get(h),S=i[h],N=e.baseline.get(h),E;if(S===void 0&&N!==void 0&&y!==void 0&&y.content_sha256===N&&!e.readOnly)E=await d(this,u,"m",Ke).call(this,e,h,y,N,a);else E=await d(this,u,"m",qe).call(this,e,h,y,S,c);if(E!==void 0)f.set(h,E)}if(e.baseline=f,await d(this,u,"m",He).call(this,e,c),a.suppressed>0)d(this,m,"f").debug("remote deletes are disabled; locally deleted memories stay on the server",{count:a.suppressed,memory_store_id:e.memoryStoreId});if(a.capped>0)d(this,m,"f").warn(`delete cap reached: ${a.mode==="log_only"?"would send":"sent"} ${a.attempted} deletes, held ${a.capped} for later syncs`,{memory_store_id:e.memoryStoreId})}catch(n){d(this,m,"f").warn("memory sync failed",{memory_store_id:e.memoryStoreId,error:String(n)})}},Ye=async function(e,r){let n=new Map,i=new Set,o=async()=>{if(e.readOnly)return;let a=await d(this,u,"m",le).call(this,e);if(!a.markerOk){d(this,m,"f").warn(`${a.distrustReason}; not uploading anything from the memory store folder`,{root:e.files.root().path,memory_store_id:e.memoryStoreId});return}for(let[l,h]of Object.entries(a.files))if((h!==e.baseline.get(l)||e.sentShas.has(l))&&e.refusedShas.get(l)!==h)n.set(l,h),i.add(l);if(n.size===0||r?.aborted)return;let c=new Map;for await(let[l,h]of d(this,u,"m",fe).call(this,e.memoryStoreId)){if(r?.aborted)return;c.set(l,h)}d(this,u,"m",ve).call(this,e,c);let f=[];for(let l of[...n.keys()].sort()){let h=n.get(l),y=e.baseline.get(l),S=c.get(l);if(h===y){i.delete(l);continue}if(S!==void 0&&S.content_sha256===h){e.baseline.set(l,S.content_sha256),i.delete(l);continue}if(S!==void 0&&S.content_sha256!==y){d(this,m,"f").warn("memory changed both locally and remotely; the flush leaves the remote version",{path:l,memory_store_id:e.memoryStoreId}),i.delete(l);continue}f.push([l,h,S])}await d(this,u,"m",Ge).call(this,e,f,i,r)};try{if(await Gt(o(),r),r?.aborted&&i.size>0)d(this,m,"f").warn(`memory flush cut off part-way; ${i.size} of ${n.size} changed files had not finished uploading`,{memory_store_id:e.memoryStoreId})}catch(a){d(this,m,"f").warn("memory flush failed",{memory_store_id:e.memoryStoreId,error:String(a)})}},Me=async function(e,r){d(this,m,"f").warn(`${r}; re-downloading the memory store folder instead of syncing`,{root:e.files.root().path,memory_store_id:e.memoryStoreId}),await e.files.createRoot(),await d(this,u,"m",ke).call(this,e)},ve=function(e,r){for(let[n,i]of e.sentShas)if(r.get(n)?.content_sha256===i)e.baseline.set(n,i);e.sentShas.clear()},ke=async function(e){e.baseline=new Map,e.sentShas.clear(),e.pendingDeletes.clear(),await e.files.put(q,`version ${Je}
|
|
7
|
+
${e.memoryStoreId}`);for await(let[r,n]of d(this,u,"m",fe).call(this,e.memoryStoreId,"full"))if(await d(this,u,"m",Ie).call(this,e,r,n.content??""))e.baseline.set(r,n.content_sha256)},qe=async function(e,r,n,i,o){let a=e.baseline.get(r);if(i!==void 0)e.pendingDeletes.delete(r);if(!n){if(i===void 0){e.pendingDeletes.delete(r);return}if(a!==void 0){if(i===a){let y=await d(this,u,"m",ze).call(this,e,r,a);if(y===void 0)return;if(y===a)return a;i=y}if(e.readOnly)d(this,m,"f").warn("memory deleted remotely but edited locally; keeping the file, which a read-only store cannot push",{path:r,memory_store_id:e.memoryStoreId});else if(e.refusedShas.get(r)!==i)d(this,m,"f").info("memory deleted remotely but edited locally; re-creating it from the file",{path:r,memory_store_id:e.memoryStoreId})}if(e.readOnly)return;if(e.refusedShas.get(r)===i)return;return await d(this,u,"m",he).call(this,e,r,i,void 0)}let c=n.content_sha256,f=c!==a,l=i!==void 0&&i!==a&&i!==c,h=!e.readOnly&&l;if(i===void 0&&a!==void 0){if(f)d(this,m,"f").warn("memory deleted locally but changed remotely; restoring the remote version",{path:r,memory_store_id:e.memoryStoreId}),e.pendingDeletes.delete(r),o.push([r,n]);return a}if(f){if(i===c)return c;if(l)d(this,m,"f").warn("memory changed both locally and remotely; keeping the remote version",{path:r,memory_store_id:e.memoryStoreId});return o.push([r,n]),a}if(h){if(e.refusedShas.get(r)===i)return c;return await d(this,u,"m",he).call(this,e,r,i,n)??c}return c},ze=async function(e,r,n){let i;try{i=await e.files.hashFile(r)}catch(o){if(!(o instanceof p)&&!Y(o))throw o;return n}if(i===null)return;if(i!==n)return i;try{await e.files.remove(r)}catch(o){if(!(o instanceof p)&&!Y(o))throw o;return d(this,m,"f").warn("failed to remove memory deleted remotely",{path:r,memory_store_id:e.memoryStoreId,error:String(o)}),n}return},Ie=async function(e,r,n){try{await e.files.put(r,n)}catch(i){if(!(i instanceof p)&&!Y(i))throw i;return d(this,m,"f").warn("failed to write memory",{path:r,memory_store_id:e.memoryStoreId,error:String(i)}),!1}return!0},He=async function(e,r){if(r.length===0)return;let n=async(a,c)=>{let f;try{f=await d(this,k,"f").beta.memoryStores.memories.retrieve(c.id,{memory_store_id:e.memoryStoreId,view:"full"})}catch(l){if(ca(l,404))return;d(this,m,"f").warn("failed to fetch memory content",{path:a,memory_store_id:e.memoryStoreId,error:String(l)});return}if(await d(this,u,"m",Ie).call(this,e,a,f.content??""))e.baseline.set(a,f.content_sha256)},i=r[Symbol.iterator](),o=async()=>{for(let[a,c]of i)await n(a,c)};await Promise.all(Array.from({length:Math.min(Bt,r.length)},o))},Ge=async function(e,r,n,i){let o=r[Symbol.iterator](),a=async()=>{for(let[c,f,l]of o){if(i?.aborted)return;let h=await d(this,u,"m",he).call(this,e,c,f,l);if(n.delete(c),h!==void 0)e.baseline.set(c,h)}};await Promise.all(Array.from({length:Math.min(Yt,r.length)},a))},fe=async function*(e,r="basic"){let n=r==="basic"?Ut:jt;for await(let i of d(this,k,"f").beta.memoryStores.memories.list(e,{view:r,limit:n})){if(i.type!=="memory")continue;let o=i.path.replace(/^\/+/,"");if(o===q){d(this,m,"f").warn("the server listed the reserved marker path; skipping",{path:i.path,memory_store_id:e});continue}yield[o,i]}},he=async function t(e,r,n,i){try{let o=await e.files.get(r);if(o===null)return;let a=xw(o);e.sentShas.set(r,Cv.createHash("sha256").update(a,"utf-8").digest("hex"));let c=i?await d(this,k,"f").beta.memoryStores.memories.update(i.id,{memory_store_id:e.memoryStoreId,content:a,precondition:{type:"content_sha256",content_sha256:i.content_sha256}}):await d(this,k,"f").beta.memoryStores.memories.create(e.memoryStoreId,{path:"/"+r,content:a});return e.refusedShas.delete(r),e.sentShas.delete(r),c.content_sha256}catch(o){if(i&&ca(o,404))return await d(this,u,"m",t).call(this,e,r,n,void 0);let a=o instanceof p||ca(o,400)||ca(o,413);if(i&&ca(o,409))d(this,m,"f").warn("memory changed both locally and remotely; the upload was refused and the local edit loses",{path:r,memory_store_id:e.memoryStoreId});else if(a&&n!==void 0)e.refusedShas.set(r,n),d(this,m,"f").warn("the server rejected this memory file, so it stays un-synced until its content changes",{path:r,memory_store_id:e.memoryStoreId,rejection:String(o)});else d(this,m,"f").warn("failed to upload memory",{path:r,memory_store_id:e.memoryStoreId,error:String(o)});return}},Ke=async function(e,r,n,i,o){if(o.mode==="disabled")return o.suppressed++,i;let a=e.pendingDeletes.get(r);if(a===void 0)a=Date.now(),e.pendingDeletes.set(r,a);if(!o.waiveWindow&&Date.now()-a<Wt)return i;let c,f;try{c=await e.files.hashFile(q)===Xe(e.memoryStoreId),f=await e.files.hashFile(r)===null}catch(h){if(!(h instanceof p)&&!Y(h))throw h;c=f=!1}if(!c)return i;if(!f)return e.pendingDeletes.delete(r),i;if(!o.takeSlot())return i;if(o.mode==="log_only")return d(this,m,"f").info("log-only: sync would delete this memory on the server",{path:r,memory_store_id:e.memoryStoreId}),i;let l=await d(this,u,"m",Ve).call(this,e,r,n,i);if(l===void 0)e.pendingDeletes.delete(r);return l},Ve=async function(e,r,n,i){try{await d(this,k,"f").beta.memoryStores.memories.delete(n.id,{memory_store_id:e.memoryStoreId,expected_content_sha256:i})}catch(o){if(ca(o,404))return;if(ca(o,409)||ca(o,412))d(this,m,"f").warn("memory deleted locally but changed remotely; keeping the remote version",{path:r,memory_store_id:e.memoryStoreId});else d(this,m,"f").warn("failed to delete memory",{path:r,memory_store_id:e.memoryStoreId,error:String(o)});return i}d(this,m,"f").info("propagated local deletion",{path:r,memory_store_id:e.memoryStoreId});return},s})();function Y(s){return typeof s==="object"&&s!==null&&typeof s.code==="string"}async function Gt(s,t){if(!t){await s;return}let e,r=new Promise((n)=>{if(e=n,t.aborted)n()});t.addEventListener("abort",e,{once:!0});try{await Promise.race([s,r])}finally{t.removeEventListener("abort",e)}}var de,g,O,X,x,v,Re,me,J,ue,pe,C,F,z,P,Q,R,Qe,et,rt=102400,at=120000,Kt=262144,Vt=65536,nt=Buffer.from(`
|
|
8
|
+
`),ee=102400,Xt=2000,Jt=200;class ct extends Z{constructor(s){super(`bash command timed out after ${s}ms`);this.name="BashTimeoutError",this.timeoutMs=s}}var Zt=/\x1b\[[0-9;?]*[ -/]*[@-~]/g,Qt=_.glob;function lt(s){return s===void 0?Kt:s}function W(s){if(s===void 0)return;throw new Z("The `unrestrictedPaths` option you passed to the agent toolset (AgentToolContext) is no longer supported. The toolset's file tools (read, write, edit, glob, grep) are now always confined to the working directory plus the directories listed in `allowedRoots`. Remove `unrestrictedPaths` from your context; to let the file tools reach any other directory, add it to `allowedRoots`.")}function qr(s){return[rr(s),nr(s),or(s),ar(s),lr(s),fr(s)]}async function re(s,t){return W(s.unrestrictedPaths),Te(s.workdir,t,{allowedRoots:s.allowedRoots??[]})}function ft(s,t){return we(s.readOnlyRoots??[],t)}function er(){let s={};for(let[t,e]of Object.entries(process.env)){if(t.startsWith("ANTHROPIC_"))continue;s[t]=e}return s}var tr=(()=>{class s{constructor(t,e=er()){de.add(this),g.set(this,void 0),O.set(this,""),X.set(this,!1),x.set(this,!1),v.set(this,null),D(this,g,Ne.spawn("/bin/bash",["--noprofile","--norc"],{cwd:t,env:{...e,PS1:"",PS2:"",TERM:"dumb"},stdio:["pipe","pipe","pipe"],detached:!0}),"f"),d(this,g,"f").stdout.setEncoding("utf8"),d(this,g,"f").stderr.setEncoding("utf8"),d(this,g,"f").stdout.on("data",(r)=>d(this,de,"m",Re).call(this,r)),d(this,g,"f").stderr.on("data",(r)=>d(this,de,"m",Re).call(this,r)),d(this,g,"f").once("close",()=>{D(this,x,!0,"f");let r=d(this,v,"f");D(this,v,null,"f"),r?.resolve()})}get closed(){return d(this,x,"f")}async exec(t,e={}){if(d(this,x,"f"))throw new Z("bash session terminated");let r=e.timeoutMs??at,n=e.signal;n?.throwIfAborted(),D(this,O,"","f"),D(this,X,!1,"f");let i=`__ANT_CMD_${st.randomUUID()}_DONE__`,o=`${i.slice(0,8)}''${i.slice(8)}`,a=`{ ${t}
|
|
9
9
|
} </dev/null 2>&1; printf '\\n${o}%d\\n' $?
|
|
10
|
-
`;if(d(this,g,"f").stdin.write(a),d(this,O,"f").indexOf(i)<0){let{promise:S,resolve:N}=
|
|
11
|
-
${y}`;return{output:y,exitCode:h}}close(){if(d(this,x,"f"))return;
|
|
10
|
+
`;if(d(this,g,"f").stdin.write(a),d(this,O,"f").indexOf(i)<0){let{promise:S,resolve:N}=xT();D(this,v,{sentinel:i,resolve:N},"f");let E,ne;try{await Promise.race([S,new Promise((dt,ye)=>{E=setTimeout(()=>ye(new ct(r)),r)}),new Promise((dt,ye)=>{if(!n)return;ne=()=>ye(n.reason),n.addEventListener("abort",ne,{once:!0})})])}finally{if(E)clearTimeout(E);if(ne&&n)n.removeEventListener("abort",ne);D(this,v,null,"f")}}let c=d(this,O,"f").indexOf(i);if(c<0)throw new Z("bash session terminated");let l=d(this,O,"f").slice(c+i.length).match(/^(-?\d+)/),h=l?parseInt(l[1],10):-1,y=d(this,O,"f").slice(0,c).replace(Zt,"").replace(/\n+$/,"");if(d(this,X,"f"))y=`[output truncated]
|
|
11
|
+
${y}`;return{output:y,exitCode:h}}close(){if(d(this,x,"f"))return;D(this,x,!0,"f");let t=d(this,v,"f");D(this,v,null,"f"),t?.resolve(),d(this,g,"f").stdout.destroy(),d(this,g,"f").stderr.destroy(),d(this,g,"f").stdin.destroy();try{process.kill(-d(this,g,"f").pid,"SIGKILL")}catch{d(this,g,"f").kill("SIGKILL")}d(this,g,"f").unref()}}return g=new WeakMap,O=new WeakMap,X=new WeakMap,x=new WeakMap,v=new WeakMap,de=new WeakSet,Re=function(e){if(D(this,O,d(this,O,"f")+e,"f"),d(this,O,"f").length>rt)D(this,O,d(this,O,"f").slice(d(this,O,"f").length-rt),"f"),D(this,X,!0,"f");if(d(this,v,"f")&&d(this,O,"f").indexOf(d(this,v,"f").sentinel)>=0){let r=d(this,v,"f");D(this,v,null,"f"),r.resolve()}},s})();function rr(s){W(s.unrestrictedPaths);let t,e=Promise.resolve();return T({name:"bash",description:"Run a bash command in a persistent shell. State (cwd, env vars) persists across calls.",inputSchema:{type:"object",properties:{command:{type:"string",description:"The command to run"},restart:{type:"boolean",description:"Restart the persistent shell before running"},timeout_ms:{type:"integer",description:"Per-call timeout in milliseconds"}}},run:async({command:r,restart:n,timeout_ms:i},o)=>{let a=e,c=xT();e=c.promise;try{await a}catch{}try{if(n)t?.close(),t=void 0;if(!r){if(n)return"bash session restarted";throw new Mt("bash: command is required")}t??(t=new tr(s.workdir,s.env));try{let{output:f,exitCode:l}=await t.exec(r,{timeoutMs:i??at,signal:o?.signal});if(l!==0)throw new Mt(f||`exit ${l}`);return f}catch(f){if(f instanceof Mt)throw f;throw t.close(),t=void 0,new Mt(`bash: ${f instanceof Error?f.message:String(f)}`)}}finally{c.resolve()}},close:()=>{t?.close(),t=void 0}})}function nr(s){return W(s.unrestrictedPaths),T({name:"read",description:"Read a UTF-8 text file relative to the workdir.",inputSchema:{type:"object",properties:{file_path:{type:"string"},view_range:{type:"array",items:{type:"integer"},description:"[start_line, end_line] 1-indexed inclusive"}},required:["file_path"]},run:async({file_path:t,view_range:e})=>{if(!t)throw new Mt("read: file_path is required");let r=await re(s,t);if(e?.length&&e.length!==2)throw new Mt("read: view_range must be [start_line, end_line]");let n;try{let l=await _.stat(r);if(!l.isFile())throw new Mt(`read: ${t} is not a regular file`);let h=lt(s.maxFileBytes);if(h!==null&&l.size>h){if(!e?.length)throw new Mt(`read: ${t} is ${l.size} bytes, exceeds ${h}-byte limit. Use the view_range parameter to read specific line ranges, e.g. view_range: [1, 500].`);let[y,S]=e;return await ir(r,t,y,S,h)}n=await _.readFile(r,"utf8")}catch(l){if(l instanceof Mt)throw l;throw new Mt(`read: ${U(l,t)}`)}if(!e?.length)return n;let[i,o]=e,a=n.split(`
|
|
12
12
|
`),c=Math.max(0,i-1),f=o>0?o:a.length;return a.slice(c,f).join(`
|
|
13
|
-
`)}})}async function ir(s,t,e,r,n){let i=new sr(t,e,r,n);if(i.rangeIsEmpty())return"";let o=te.createReadStream(s,{highWaterMark:Vt});try{for await(let a of o)if(i.collectFrom(a),i.rangeIsCollected())break}finally{o.destroy()}return i.text()}var sr=(()=>{class s{constructor(t,e,r,n){me.add(this),
|
|
14
|
-
`)}})}function fr(s){return W(s.unrestrictedPaths),T({name:"grep",description:"Search file contents for a regex. Uses ripgrep if available, otherwise a built-in walker.",inputSchema:{type:"object",properties:{pattern:{type:"string"},path:{type:"string"}},required:["pattern"]},run:async({pattern:t,path:e},r)=>{if(!t)throw new
|
|
15
|
-
[output truncated at ${ee} bytes]`);if(l===0)return n(a);if(l===1)return n("no matches");i(new
|
|
13
|
+
`)}})}async function ir(s,t,e,r,n){let i=new sr(t,e,r,n);if(i.rangeIsEmpty())return"";let o=te.createReadStream(s,{highWaterMark:Vt});try{for await(let a of o)if(i.collectFrom(a),i.rangeIsCollected())break}finally{o.destroy()}return i.text()}var sr=(()=>{class s{constructor(t,e,r,n){me.add(this),J.set(this,void 0),ue.set(this,void 0),pe.set(this,void 0),C.set(this,void 0),F.set(this,void 0),z.set(this,void 0),P.set(this,0),Q.set(this,[]),R.set(this,0),D(this,J,t,"f"),D(this,ue,e,"f"),D(this,pe,r,"f"),D(this,C,Math.max(0,e-1),"f"),D(this,F,r>0?r:1/0,"f"),D(this,z,n,"f")}rangeIsEmpty(){return d(this,F,"f")<=d(this,C,"f")}rangeIsCollected(){return d(this,P,"f")>=d(this,F,"f")}collectFrom(t){var e;let r=0;while(r<t.length&&!this.rangeIsCollected()){let n=t.indexOf(10,r),i=n<0?t.length:n;if(d(this,P,"f")>=d(this,C,"f"))d(this,me,"m",Qe).call(this,t.subarray(r,i),n>=0);if(n<0)break;D(this,P,(e=d(this,P,"f"),e++,e),"f"),r=n+1}}text(){return Buffer.concat(d(this,Q,"f"),d(this,R,"f")).toString("utf8")}}return J=new WeakMap,ue=new WeakMap,pe=new WeakMap,C=new WeakMap,F=new WeakMap,z=new WeakMap,P=new WeakMap,Q=new WeakMap,R=new WeakMap,me=new WeakSet,Qe=function(e,r){if(d(this,Q,"f").push(e),D(this,R,d(this,R,"f")+e.length,"f"),r&&d(this,P,"f")+1<d(this,F,"f"))d(this,Q,"f").push(nt),D(this,R,d(this,R,"f")+nt.length,"f");if(d(this,R,"f")>d(this,z,"f"))throw d(this,me,"m",et).call(this)},et=function(){if(d(this,F,"f")-d(this,C,"f")===1)return new Mt(`read: line ${d(this,C,"f")+1} of ${d(this,J,"f")} alone exceeds ${d(this,z,"f")}-byte limit. The read tool cannot return part of a line, so view_range cannot narrow this further.`);return new Mt(`read: view_range [${d(this,ue,"f")}, ${d(this,pe,"f")}] of ${d(this,J,"f")} exceeds ${d(this,z,"f")}-byte limit. Narrow the view_range to read a smaller portion.`)},s})();function or(s){return W(s.unrestrictedPaths),T({name:"write",description:"Write a UTF-8 text file relative to the workdir, creating parent directories as needed.",inputSchema:{type:"object",properties:{file_path:{type:"string"},content:{type:"string"}},required:["file_path","content"]},run:async({file_path:t,content:e})=>{if(!t)throw new Mt("write: file_path is required");let r=await re(s,t),n=await ft(s,r);if(n!==void 0)throw new Mt(`write: ${t} is inside read-only directory ${n}`);try{await _.mkdir(b.dirname(r),{recursive:!0,mode:G}),await _e(r,e??"")}catch(i){throw new Mt(`write: ${U(i,t)}`)}return`wrote ${Buffer.byteLength(e??"")} bytes to ${t}`}})}function ar(s){return W(s.unrestrictedPaths),T({name:"edit",description:"Replace old_string with new_string in a file. old_string must be unique unless replace_all.",inputSchema:{type:"object",properties:{file_path:{type:"string"},old_string:{type:"string"},new_string:{type:"string"},replace_all:{type:"boolean"}},required:["file_path","old_string","new_string"]},run:async({file_path:t,old_string:e,new_string:r,replace_all:n})=>{if(!t)throw new Mt("edit: file_path is required");if(!e)throw new Mt("edit: old_string is required");let i=await re(s,t),o=await ft(s,i);if(o!==void 0)throw new Mt(`edit: ${t} is inside read-only directory ${o}`);let a;try{let l=await _.stat(i);if(!l.isFile())throw new Mt(`edit: ${t} is not a regular file`);let h=lt(s.maxFileBytes);if(h!==null&&l.size>h)throw new Mt(`edit: ${t} is ${l.size} bytes, exceeds ${h}-byte limit. The edit tool loads the whole file and cannot modify a file this large.`);a=await _.readFile(i,"utf8")}catch(l){if(l instanceof Mt)throw l;throw new Mt(`edit: ${U(l,t)}`)}let c=a.split(e).length-1;if(c===0)throw new Mt(`edit: old_string not found in ${t}`);let f;if(n)f=a.split(e).join(r);else{if(c>1)throw new Mt(`edit: old_string appears ${c} times in ${t} (must be unique)`);f=a.replace(e,()=>r)}try{await _e(i,f)}catch(l){throw new Mt(`edit: write: ${U(l,t)}`)}return`edited ${t} (${n?c:1} replacement(s))`}})}function cr(s){return s.split(/[\\/{},]/).includes("..")}function lr(s){return W(s.unrestrictedPaths),T({name:"glob",description:"Match files under the workdir against a glob pattern. Results are mtime-sorted, newest first.",inputSchema:{type:"object",properties:{pattern:{type:"string"},path:{type:"string",description:"Directory to search in. Defaults to the workdir."}},required:["pattern"]},run:async({pattern:t,path:e})=>{if(!t)throw new Mt("glob: pattern is required");if(b.isAbsolute(t))throw new Mt("glob: absolute pattern not permitted; pass a relative pattern (and optionally path)");if(cr(t))throw new Mt('glob: ".." is not permitted in the pattern');let r=e?await re(s,e):b.resolve(s.workdir),n=e?r:await H(r),i=[],o=ht;try{for await(let a of Qt(t,{cwd:r,withFileTypes:!0,exclude:(c)=>c.name===".git"||c.name==="node_modules"})){if(o--<=0)break;if(!a.isFile())continue;let c=b.join(a.parentPath,a.name),f;try{f=await _.realpath(c)}catch{continue}if(!ie(n,f))continue;let l=0;try{l=(await _.stat(c)).mtimeMs}catch{}i.push({path:c,mtime:l})}}catch(a){throw new Mt(`glob: ${a instanceof Error?a.message:String(a)}`)}if(i.length===0)return"no matches";return i.sort((a,c)=>c.mtime-a.mtime),i.slice(0,Jt).map((a)=>a.path).join(`
|
|
14
|
+
`)}})}function fr(s){return W(s.unrestrictedPaths),T({name:"grep",description:"Search file contents for a regex. Uses ripgrep if available, otherwise a built-in walker.",inputSchema:{type:"object",properties:{pattern:{type:"string"},path:{type:"string"}},required:["pattern"]},run:async({pattern:t,path:e},r)=>{if(!t)throw new Mt("grep: pattern is required");let n=b.resolve(s.workdir);if(e)n=await re(s,e);let i=await pr();return i?hr(i,t,n,r?.signal):dr(t,n,r?.signal)}})}function hr(s,t,e,r){return new Promise((n,i)=>{let o=Ne.spawn(s,["-n","--no-heading","-e",t,"--",e],{...r?{signal:r}:{}}),a="",c="",f=!1;o.stdout.on("data",(l)=>{if(f)return;if(a+=l,a.length>ee)f=!0,a=a.slice(0,ee),o.kill("SIGKILL")}),o.stderr.on("data",(l)=>c+=l),o.on("close",(l)=>{if(r?.aborted)return i(new Mt("grep: aborted"));if(f)return n(a+`
|
|
15
|
+
[output truncated at ${ee} bytes]`);if(l===0)return n(a);if(l===1)return n("no matches");i(new Mt(`grep: rg failed: ${c||`exit ${l}`}`))}),o.on("error",(l)=>{if(r?.aborted)return i(new Mt("grep: aborted"));i(new Mt(`grep: rg failed: ${l.message}`))})})}async function dr(s,t,e){let r;try{r=new RegExp(s)}catch(c){throw new Mt(`grep: invalid regex: ${c instanceof Error?c.message:String(c)}`)}let n=[],i=ee,o=(c)=>{if(i-=c.length+1,i<0)return n.push(`[output truncated at ${ee} bytes]`),!1;return n.push(c),!0};if((await _.stat(t).catch(()=>null))?.isFile())await it(t,r,o);else await ur(t,"",(c)=>it(b.join(t,c),r,o),e);if(e?.aborted)throw new Mt("grep: aborted");if(n.length===0)return"no matches";return n.join(`
|
|
16
16
|
`)}async function it(s,t,e){let r=te.createReadStream(s,{encoding:"utf8"}),n=ot.createInterface({input:r,crlfDelay:1/0}),i=0;try{for await(let o of n){if(i++,o.length>Xt)continue;if(t.test(o)&&!e(`${s}:${i}:${o}`))return!1}}catch{}finally{r.destroy()}return!0}var mr=40,ht=50000;async function ur(s,t,e,r){let n=ht;async function i(o,a){if(a>mr)return!0;if(r?.aborted)return!1;let c;try{c=await _.readdir(b.join(s,o),{withFileTypes:!0})}catch{return!0}for(let f of c){if(f.name===".git"||f.name==="node_modules")continue;if(n--<=0)return!1;if(r?.aborted)return!1;let l=o?b.join(o,f.name):f.name;if(f.isDirectory()){if(!await i(l,a+1))return!1}else if(f.isFile()){if(await e(l)===!1)return!1}}return!0}await i(t,0)}async function pr(){let s=(process.env.PATH??"").split(b.delimiter);for(let t of s){let e=b.join(t,"rg");try{return await _.access(e,te.constants.X_OK),e}catch{}}return null}export{Pt as MEMORY_FLUSH_TIMEOUT_MS,A as SessionMemoryError,Ht as SessionMemoryStores,qr as betaAgentToolset20260401,wt as setupSkills};
|
|
17
17
|
|
|
18
|
-
//# debugId=
|
|
18
|
+
//# debugId=5327896E889FB04464756E2164756E21
|
|
@@ -1,10 +1,10 @@
|
|
|
1
1
|
// @bun
|
|
2
|
-
function
|
|
2
|
+
function lce(e){if(e.bun)return null;return`auto-mobile requires the Bun runtime (>= 1.4.4), but it was started with ${e.node?`Node.js ${e.node}`:"this JavaScript runtime"}.
|
|
3
3
|
Run it with Bun instead:
|
|
4
4
|
bun dist/src/index.js <args>
|
|
5
5
|
bunx @kaeawc/auto-mobile@latest <args>
|
|
6
6
|
Install Bun from https://bun.sh.
|
|
7
|
-
`}function
|
|
8
|
-
export{
|
|
7
|
+
`}function uce(e){let t=lce(e.versions);if(t===null)return!0;return e.writeStderr(t),e.exit(1),!1}uce({versions:process.versions,writeStderr:(e)=>{process.stderr.write(e)},exit:(e)=>process.exit(e)});
|
|
8
|
+
export{lce,uce};
|
|
9
9
|
|
|
10
|
-
//# debugId=
|
|
10
|
+
//# debugId=229C66A3215CA55264756E2164756E21
|
|
@@ -0,0 +1,7 @@
|
|
|
1
|
+
// @bun
|
|
2
|
+
import{i,Tr,Q,e}from"./chunk-r0vp315h.js";import{h,I}from"./chunk-5wk1t46v.js";import{_e}from"./chunk-r6pvhj33.js";import{Ca,fQ}from"./chunk-8nj68t1v.js";import{Nr,Pl,qs,v,En,L,b,VD,pn,bd,Mk,t$,fj,$Y,N,rs,QR,pi,ry,ny,eE,E}from"./chunk-sfqe223f.js";import{n,a,m,S,s,Ne,p}from"./chunk-w5yypt53.js";import{ai}from"./chunk-4vxeq0vd.js";import{lp,wh,sl,oV,sV,HQ,Rh,Am,o5}from"./chunk-yqfz4vts.js";import{lB}from"./chunk-69pmjdf2.js";import{r,t,u}from"./chunk-2b39zyxc.js";import{promises as Xe}from"fs";import*as ae from"path";var q=Ne(n(),n()),ee=S(n()),st=s({snapshotName:n(),timestamp:n(),deviceId:n(),deviceName:n(),platform:p(["android","ios"]),deviceType:n().optional(),osVersion:n().optional(),snapshotType:p(["vm","adb","simctl","app_data"]),includeAppData:m(),includeSettings:m(),packages:ee.optional(),foregroundApp:n().optional(),settings:s({global:q.optional(),secure:q.optional(),system:q.optional()}).optional(),iosSettings:s({values:q,ui:s({appearance:p(["light","dark"]).optional(),contentSize:n().optional()}).optional()}).optional(),appDataBackup:s({backupFile:n().optional(),backedUpPackages:ee.optional(),skippedPackages:ee.optional(),failedPackages:ee.optional(),totalPackages:a().optional(),backupTimedOut:m().optional(),backupMethod:p(["root_pull","none","simctl_copy"]).optional(),bundleStatuses:S(s({bundleId:n(),status:p(["captured","skipped-no-container","not-installed","failed"])})).optional()}).optional(),fixture:s({avdName:n(),systemImageId:n(),avdConfigHash:n(),emulatorVersion:n(),userdataGeneration:n()}).optional()});function rt(o,c){let d;try{d=JSON.parse(c)}catch(f){return e.warn(`[DeviceSnapshotRepository] Failed to parse manifest for ${o}: ${r(f)}`),null}let l=st.safeParse(d);if(l.success)return l.data;return e.warn(`[DeviceSnapshotRepository] Manifest for ${o} failed validation: ${l.error.message}`),typeof d==="object"&&d!==null&&!Array.isArray(d)?d:null}function Ie(o){let c=rt(o.snapshot_name,o.manifest_json);if(!c)return null;return{snapshotName:o.snapshot_name,deviceId:o.device_id,deviceName:o.device_name,platform:o.platform,snapshotType:o.snapshot_type,includeAppData:Boolean(o.include_app_data),includeSettings:Boolean(o.include_settings),createdAt:o.created_at,lastAccessedAt:o.last_accessed_at,sizeBytes:o.size_unknown?null:o.size_bytes,pendingReclaim:Boolean(o.pending_reclaim),...o.pending_reclaim_reason===null?{}:{pendingReclaimReason:o.pending_reclaim_reason},manifest:c}}var pt={deviceId:(o,c)=>{o.device_id=c},deviceName:(o,c)=>{o.device_name=c},platform:(o,c)=>{o.platform=c},snapshotType:(o,c)=>{o.snapshot_type=c},includeAppData:(o,c)=>{o.include_app_data=c?1:0},includeSettings:(o,c)=>{o.include_settings=c?1:0},createdAt:(o,c)=>{o.created_at=c},lastAccessedAt:(o,c)=>{o.last_accessed_at=c},pendingReclaim:(o,c)=>{o.pending_reclaim=c?1:0},pendingReclaimReason:(o,c)=>{o.pending_reclaim_reason=c},manifest:(o,c)=>{o.manifest_json=JSON.stringify(c)}};function ct(o){let c={};for(let[d,l]of Object.entries(pt)){let f=o[d];if(f!==void 0)l(c,f)}if(o.sizeBytes!==void 0)c.size_bytes=o.sizeBytes??0,c.size_unknown=o.sizeBytes===null?1:0;return c}class me{db;constructor({db:o}={}){this.db=o??null}getDb(){return this.db??_e()}async insertSnapshot(o){let c=await this.getDb(),d={snapshot_name:o.snapshotName,device_id:o.deviceId,device_name:o.deviceName,platform:o.platform,snapshot_type:o.snapshotType,include_app_data:o.includeAppData?1:0,include_settings:o.includeSettings?1:0,created_at:o.createdAt,last_accessed_at:o.lastAccessedAt,size_bytes:o.sizeBytes??0,size_unknown:o.sizeBytes===null?1:0,pending_reclaim:o.pendingReclaim?1:0,pending_reclaim_reason:o.pendingReclaimReason??null,manifest_json:JSON.stringify(o.manifest)};await c.insertInto("device_snapshots").values(d).onConflict((l)=>l.column("snapshot_name").doUpdateSet({device_id:d.device_id,device_name:d.device_name,platform:d.platform,snapshot_type:d.snapshot_type,include_app_data:d.include_app_data,include_settings:d.include_settings,last_accessed_at:d.last_accessed_at,size_bytes:d.size_bytes,size_unknown:d.size_unknown,pending_reclaim:d.pending_reclaim,pending_reclaim_reason:d.pending_reclaim_reason,manifest_json:d.manifest_json})).execute()}async updateSnapshot(o,c){let d=await this.getDb(),l=ct(c);if(Object.keys(l).length===0)return;await d.updateTable("device_snapshots").set(l).where("snapshot_name","=",o).execute()}async getSnapshot(o){let d=await(await this.getDb()).selectFrom("device_snapshots").selectAll().where("snapshot_name","=",o).executeTakeFirst();return d?Ie(d):null}async listSnapshots(o={}){let d=(await this.getDb()).selectFrom("device_snapshots").selectAll();if(o.deviceId)d=d.where("device_id","=",o.deviceId);if(o.platform)d=d.where("platform","=",o.platform);if(o.snapshotType)d=d.where("snapshot_type","=",o.snapshotType);if(o.pendingReclaim!==void 0)d=d.where("pending_reclaim","=",o.pendingReclaim?1:0);if(o.orderByLastAccessed)d=d.orderBy("last_accessed_at",o.orderByLastAccessed);if(o.orderByCreatedAt)d=d.orderBy("created_at",o.orderByCreatedAt);if(o.limit&&o.limit>0)d=d.limit(o.limit);return(await d.execute()).map((f)=>Ie(f)).filter((f)=>Boolean(f))}async touchSnapshot(o,c){await this.updateSnapshot(o,{lastAccessedAt:c})}async deleteSnapshot(o){let d=await(await this.getDb()).deleteFrom("device_snapshots").where("snapshot_name","=",o).executeTakeFirst();return Number(d.numDeletedRows??0)>0}}function te(o,c){if(typeof o==="boolean")return o;if(typeof o==="string"){let d=o.trim().toLowerCase();if(d==="true")return!0;if(d==="false")return!1}return c}function he(o,c,d){if(o===void 0||o===null||o==="")return c;let l=typeof o==="string"?Number(o):o;if(!Number.isFinite(l)||l<=0)return c;let f=d?l:Math.round(l);return f>0?f:c}function dt(o,c){if(o===void 0||o===null||o==="")return;let d=typeof o==="string"?Number(o):o;if(!Number.isFinite(d)||d<=0)return;let l=c?d:Math.round(d);return l>0?l:void 0}function z(o){let c=o&&typeof o==="object"?o:{};return{includeAppData:te(c.includeAppData,Ca.includeAppData),includeSettings:te(c.includeSettings,Ca.includeSettings),useVmSnapshot:te(c.useVmSnapshot,Ca.useVmSnapshot),strictBackupMode:te(c.strictBackupMode,Ca.strictBackupMode),vmSnapshotTimeoutMs:he(c.vmSnapshotTimeoutMs,Ca.vmSnapshotTimeoutMs,!1),maxVmSnapshotsPerAvd:he(c.maxVmSnapshotsPerAvd,Ca.maxVmSnapshotsPerAvd,!1),maxVmArchiveSizeMb:dt(c.maxVmArchiveSizeMb,!0),maxArchiveSizeMb:he(c.maxArchiveSizeMb,Ca.maxArchiveSizeMb,!0)}}var fI={ARCHIVE:"automobile:deviceSnapshots/archive"};function be(o,c,d){return fj(c,{simctl:o}).terminateApp(d)}var ut=[{domain:".GlobalPreferences",key:"AppleLocale"}];async function mt(o,c){let d={};try{let l=(await o.executeCommandArgs(["ui",c,"appearance"])).stdout.trim();if(l==="light"||l==="dark")d.appearance=l}catch(l){e.warn(`[iOS] Failed to read appearance: ${l}`)}try{let l=(await o.executeCommandArgs(["ui",c,"content_size"])).stdout.trim();if(l)d.contentSize=l}catch(l){e.warn(`[iOS] Failed to read content_size: ${l}`)}return Object.keys(d).length>0?d:void 0}async function Pe(o,c){let d={};for(let{domain:l,key:f}of ut)try{let y=(await o.executeCommandArgs(["spawn",c,"defaults","read",l,f])).stdout.trim();if(y)d[`${l}/${f}`]=y}catch(g){e.debug(`[iOS] No value for ${l}/${f}: ${g}`)}return{values:d,ui:await mt(o,c)}}async function xe(o,c,d){for(let[l,f]of Object.entries(d.values)){let g=l.indexOf("/");if(g<0)continue;let y=l.slice(0,g),D=l.slice(g+1);try{await o.executeCommandArgs(["spawn",c,"defaults","write",y,D,f])}catch(w){e.warn(`[iOS] Failed to write ${y}/${D}: ${w}`)}}if(d.ui?.appearance)try{await o.executeCommandArgs(["ui",c,"appearance",d.ui.appearance])}catch(l){e.warn(`[iOS] Failed to restore appearance: ${l}`)}if(d.ui?.contentSize)try{await o.executeCommandArgs(["ui",c,"content_size",d.ui.contentSize])}catch(l){e.warn(`[iOS] Failed to restore content_size: ${l}`)}}class Ce{options;kind="simulator";constructor(o){this.options=o}getDeviceInfo(){return this.options.simctl.getDeviceInfo(this.options.deviceId)}getRuntimes(){return this.options.simctl.getRuntimes()}captureSettings(){return Pe(this.options.simctl,this.options.deviceId)}restoreSettings(o){return xe(this.options.simctl,this.options.deviceId,o)}getAppDataContainerPath(o){return t$(this.options.simctl,this.options.deviceId,o,this.options.containerOwnership)}terminateAppIfRunning(o){return be(this.options.simctl,this.options.deviceId,o)}listAppsOrThrow(){return new VD(this.options.deviceId,this.options.simctl).listApps()}listApps(){return $Y(this.options.deviceId,this.options).listApps()}}function ne(o,c){return En(o)?{kind:"physical"}:new Ce({deviceId:o,simctl:c.simctl,containerOwnership:c.containerOwnership})}import{promises as B}from"fs";import*as ie from"path";var le="isVmSnapshotSaveDispatched";class fe{iosCaptureContainerFiles;consoleBusyRegistry;device;adb;emulator;store;iosSnapshotBackend;constructor(o,c={}){let{adbFactory:d=v,emulator:l,store:f=new Rh,simctl:g,consoleBusyRegistry:y=qs}=c;this.iosCaptureContainerFiles=c.iosCaptureContainerFiles??{mkdir:async(D)=>{await B.mkdir(D,{recursive:!0})},cp:(D,w)=>B.cp(D,w,{recursive:!0}),pathExists:rs},this.consoleBusyRegistry=y,this.device=o,this.adb=d.create(o),this.emulator=l||new pi,this.store=f,this.iosSnapshotBackend=ne(o.deviceId,{simctl:g||new L(o),containerOwnership:c.containerOwnership})}get simulatorSnapshotBackend(){if(this.iosSnapshotBackend.kind==="physical")throw Error("Snapshot app listing is not supported for physical iOS devices");return this.iosSnapshotBackend}async capture(o){return this.execute(o)}async execute(o){switch(wh(o.snapshotName),this.device.platform){case"android":return this.executeAndroid(o);case"ios":if(this.iosSnapshotBackend.kind==="physical")throw new t(`Device snapshots are not supported on physical iOS devices (${this.device.deviceId}); they require a Simulator (simctl).`);return this.executeIos(o);default:throw new t(`Snapshot capture is not supported for platform '${this.device.platform}'`)}}async executeAndroid(o){let{snapshotName:c,includeAppData:d=!0,includeSettings:l=!0,useVmSnapshot:f=!0,vmSnapshotTimeoutMs:g=30000}=o;e.info(`Capturing snapshot '${c}' for device ${this.device.deviceId}`);let y=this.device.deviceId.startsWith("emulator-"),D=f&&y,w;if(D)w=await this.captureVmSnapshot(c,l,g);else w=await this.captureSettingsSnapshot(c,d,l);return e.info(`Snapshot '${c}' captured successfully (type: ${w.snapshotType})`),{snapshotName:w.snapshotName,timestamp:w.timestamp,snapshotType:w.snapshotType,manifest:w}}async captureVmSnapshot(o,c,d){e.info(`Using VM snapshot for emulator ${this.device.deviceId}`);let l=!1;try{let f=ry("save",o);e.info(`Executing: adb -s ${this.device.deviceId} ${f}`);let g;try{g=await this.consoleBusyRegistry.runExclusive(this.device.deviceId,()=>this.adb.execute(f.split(" "),{timeoutMs:d,waitForProcessSettlementAfterAbort:!0,beforeDispatch:async()=>{l=!0}}))}catch(R){throw Error(eE("save",o,R))}let y=ny("save",o,g);if(!y.ok)throw Error(y.errorMessage);e.info("VM snapshot saved successfully");let D;if(c)D=await this.captureSettings();let w=await this.getForegroundApp();return{snapshotName:o,timestamp:new Date().toISOString(),deviceId:this.device.deviceId,deviceName:this.device.name,platform:"android",snapshotType:"vm",includeAppData:!0,includeSettings:c,foregroundApp:w,settings:D}}catch(f){let g=r(f);e.error(`Failed to capture VM snapshot: ${g}`);let y=new t(`Failed to capture VM snapshot: ${g}`);if(l)Object.assign(y,{[le]:!0});throw y}}async captureSettingsSnapshot(o,c,d){if(e.info(`Using settings-only snapshot for device ${this.device.deviceId}`),c)e.warn("App-data snapshots are not supported on non-VM Android (the adb backup path was removed in #5708); capturing settings only. Use a VM snapshot on an emulator to capture app data.");try{let l=await this.getForegroundApp(),f;if(d)f=await this.captureSettings(),await this.saveSettings(o,f);return{snapshotName:o,timestamp:new Date().toISOString(),deviceId:this.device.deviceId,deviceName:this.device.name,platform:"android",snapshotType:"adb",includeAppData:!1,includeSettings:d,foregroundApp:l,settings:f}}catch(l){throw e.error(`Failed to capture settings snapshot: ${r(l)}`,l),u(l,"Failed to capture settings snapshot")}}async getForegroundApp(){try{return(await this.adb.getForegroundApp())?.packageName}catch(o){e.warn(`Failed to get foreground app: ${o}`);return}}async captureSettings(){e.info("Capturing device settings");let o=["global","secure","system"],c={};for(let d of o)await this.captureSettingsNamespace(d,c);return c}async captureSettingsNamespace(o,c){try{let d=!1;try{let f=await E.getInstance(this.device).requestSettingsList(o);if(f.success&&f.entries)c[o]=f.entries,d=!0}catch(l){e.debug(`[CaptureSnapshot] a11y settings list failed for ${o}: ${l}`)}if(!d){let l=await this.adb.executeCommand(`shell settings list ${o}`);c[o]=this.parseSettings(l.stdout)}e.info(`Captured ${Object.keys(c[o]).length} ${o} settings`)}catch(d){e.warn(`Failed to capture ${o} settings: ${d}`),c[o]={}}}parseSettings(o){let c={};for(let d of o.split(`
|
|
3
|
+
`)){let l=d.trim();if(!l)continue;let f=l.match(/^(.+?)=(.*)$/);if(f)c[f[1]]=f[2]}return c}async saveSettings(o,c){let d=this.getAndroidPathOptions(),l=this.store.getSnapshotPathWithOptions(o,d);await B.mkdir(l,{recursive:!0});let f=this.store.getSettingsPath(o,d);await B.writeFile(f,JSON.stringify(c,null,2),"utf-8"),e.info(`Saved settings to ${f}`)}getAndroidPathOptions(){if(this.device.deviceId.startsWith("emulator-"))return{platform:"android",avdName:this.device.name};return}async executeIos(o){let{snapshotName:c,includeAppData:d=!0,includeSettings:l=!0,useVmSnapshot:f=!0,strictBackupMode:g=!1,appBundleIds:y}=o;if(e.info(`[iOS] Capturing snapshot '${c}' for simulator ${this.device.deviceId}`),f)e.info("[iOS] useVmSnapshot is ignored; using app container backups for portability");let D=await this.getIosDeviceMetadata(),w=this.getIosPathOptions(),A;if(l)A=await this.simulatorSnapshotBackend.captureSettings();let R=d?await this.captureIosAppData(c,y,g,w):void 0,P={snapshotName:c,timestamp:new Date().toISOString(),deviceId:this.device.deviceId,deviceName:this.device.name,platform:"ios",deviceType:D.deviceType,osVersion:D.osVersion,snapshotType:"app_data",includeAppData:d,includeSettings:l,...A?{iosSettings:A}:{},appDataBackup:R};return await this.saveIosMetadata(c,P,w),e.info(`[iOS] Snapshot '${c}' captured successfully (type: ${P.snapshotType})`),{snapshotName:P.snapshotName,timestamp:P.timestamp,snapshotType:P.snapshotType,manifest:P}}getIosPathOptions(){return{platform:"ios",deviceId:this.device.deviceId}}async captureIosAppData(o,c,d,l){let f=Array.from(new Set((c??[]).map((y)=>y.trim()).filter(Boolean)));if(f.length===0)throw new t("No app bundle IDs provided for iOS app-data capture. Pass appBundleIds with at least one installed app, or set includeAppData:false for a settings-only snapshot.");e.info("[iOS] Capturing app data containers");let g=this.store.getAppDataPath(o,l);await B.mkdir(g,{recursive:!0});try{return await this.backupIosAppContainers(f,d,g)}catch(y){throw await this.store.deleteSnapshotData(o,l),y}}async backupIosAppContainers(o,c,d){let l=await this.getInstalledIosBundleIds(),f=[],g=[],y=[],D=[];for(let w of o){if(!l.has(w)){e.warn(`[iOS] ${w} is not installed; skipping app data capture`),D.push(w),f.push({bundleId:w,status:"not-installed"});continue}try{let A=await this.simulatorSnapshotBackend.getAppDataContainerPath(w);if(!A){e.warn(`[iOS] ${w} has no data container; skipping app data capture`),y.push(w),f.push({bundleId:w,status:"skipped-no-container"});continue}e.info(`[iOS] Backing up app data: ${w}`),await this.copyIosAppContainer(A,d,w),g.push(w),f.push({bundleId:w,status:"captured"})}catch(A){if(A instanceof bd)throw A;e.warn(`[iOS] Failed to backup app data for ${w}: ${A}`),D.push(w),f.push({bundleId:w,status:"failed"})}}if(c&&g.length<o.length){let w=new Set(g),A=o.filter((R)=>!w.has(R));throw new t(`Failed to backup app data for ${A.length} of ${o.length} requested app(s) in strictBackupMode (all-or-nothing): ${A.join(", ")}.`)}if(g.length===0){let w=[`iOS app-data capture backed up 0 of ${o.length} requested app(s) (${o.join(", ")}).`];if(D.length>0)w.push(`Failed: ${D.join(", ")}.`);if(y.length>0)w.push(`Skipped (no data container): ${y.join(", ")}.`);throw w.push("Pass appBundleIds for installed apps that have a data container, or set includeAppData:false for a settings-only snapshot."),new t(w.join(" "))}return{backupMethod:"simctl_copy",totalPackages:o.length,backedUpPackages:g,skippedPackages:y,failedPackages:D,bundleStatuses:f}}async getInstalledIosBundleIds(){let o;try{o=await this.simulatorSnapshotBackend.listAppsOrThrow()}catch(d){throw u(d,"Failed to list installed iOS apps to validate appBundleIds")}let c=new Set;for(let d of o){let l=pn(d);if(l)c.add(l)}return c}async copyIosAppContainer(o,c,d){let l=ie.join(c,d);await this.iosCaptureContainerFiles.mkdir(l);for(let f of Mk){let g=ie.join(o,f),y=ie.join(l,f);if(await this.iosCaptureContainerFiles.pathExists(g))await this.iosCaptureContainerFiles.cp(g,y)}}async getIosDeviceMetadata(){try{let o=await this.simulatorSnapshotBackend.getDeviceInfo();if(!o)return{};let c=o.deviceTypeIdentifier??o.model,d=o.os_version;if(!d&&o.runtime){let f=(await this.simulatorSnapshotBackend.getRuntimes()).find((g)=>g.identifier===o.runtime);d=f?.version||f?.name}return{deviceType:c,osVersion:d}}catch(o){return e.warn(`[iOS] Failed to read simulator metadata: ${o}`),{}}}async saveIosMetadata(o,c,d){let l=this.store.getSnapshotPathWithOptions(o,d);await B.mkdir(l,{recursive:!0});let f=this.store.getMetadataPath(o,d);await B.writeFile(f,JSON.stringify(c,null,2),"utf-8"),e.info(`[iOS] Wrote metadata to ${f}`)}}import{promises as $e}from"fs";import*as oe from"path";function Oe(o){let c=o.trim(),d=c.match(/^(\d+)(?:\.(\d+))?(?:\.\d+)?$/)??c.match(/^[iI][oO][sS][- _]?(\d+)(?:[.\-_ ](\d+))?(?:[.\-_ ]\d+)?$/)??c.match(/^com\.apple\.CoreSimulator\.SimRuntime\.[iI][oO][sS]-(\d+)(?:-(\d+))?(?:-\d+)?$/);if(!d)return null;let l=Number(d[1]),f=d[2]===void 0?void 0:Number(d[2]);return Number.isFinite(l)&&(f===void 0||Number.isFinite(f))?{major:l,minor:f}:null}var ht=new Set(["global","secure","system"]);function lt(o){return ht.has(o)}function ft(o,c,d,l){let f=o==="vm"&&!c,g=d?"useVmSnapshot is disabled":`device ${l} is not an emulator`;return{snapshotType:c?"vm":"adb",restoreMode:c?"vm":"settings_only",...f?{restoreNote:`VM state was not restored; only captured Android settings were applied because ${g}.`}:{}}}class Se{windowCacheInvalidator=new ai;consoleBusyRegistry;device;adb;emulator;store;timer;iosSnapshotBackend;iosRestoreOperations;constructor(o,c={}){let{adbFactory:d=v,emulator:l,timer:f=i,store:g=new Rh,simctl:y,consoleBusyRegistry:D=qs,iosRestoreOperations:w}=c;this.consoleBusyRegistry=D,this.device=o,this.adb=d.create(o),this.emulator=l||new pi,this.store=g,this.timer=f,this.iosSnapshotBackend=ne(o.deviceId,{simctl:y||new L(o),containerOwnership:c.containerOwnership}),this.iosRestoreOperations=w??{pathExists:rs,terminateAppIfRunning:(A,R)=>this.simulatorSnapshotBackend.terminateAppIfRunning(R),getAppDataContainerPath:(A,R)=>this.simulatorSnapshotBackend.getAppDataContainerPath(R),rm:(A,R)=>$e.rm(A,R),cp:(A,R,P)=>$e.cp(A,R,P)}}get simulatorSnapshotBackend(){if(this.iosSnapshotBackend.kind==="physical")throw Error("Snapshot app listing is not supported for physical iOS devices");return this.iosSnapshotBackend}async restore(o){return this.execute(o)}async execute(o){switch(wh(o.snapshotName),this.device.platform){case"android":return this.executeAndroid(o);case"ios":if(this.iosSnapshotBackend.kind==="physical")throw new t(`Device snapshots are not supported on physical iOS devices (${this.device.deviceId}); they require a Simulator (simctl).`);return this.executeIos(o);default:throw new t(`Snapshot restore is not supported for platform '${this.device.platform}'`)}}async executeAndroid(o){let{snapshotName:c,manifest:d,useVmSnapshot:l=!0,vmSnapshotTimeoutMs:f=30000,onVmSnapshotLoaded:g,onBeforeVmSnapshotLoad:y}=o;if(e.info(`Restoring snapshot '${c}' (type: ${d.snapshotType}) to device ${this.device.deviceId}`),d.platform!==this.device.platform)throw new t(`Snapshot platform '${d.platform}' does not match device platform '${this.device.platform}'`);let D=this.device.deviceId.startsWith("emulator-"),w=l&&d.snapshotType==="vm"&&D,A=[];if(w)await this.restoreVmSnapshot(c,d,f,{onVmSnapshotLoaded:g,onBeforeVmSnapshotLoad:y});else A=await this.restoreSettingsSnapshot(d);if(A.length===0)e.info(`Snapshot '${c}' restored successfully`);else e.warn(`Snapshot '${c}' partially restored: ${A.length} item(s) failed`);return{...ft(d.snapshotType,w,D,this.device.deviceId),restoredAt:new Date().toISOString(),success:A.length===0,failures:A}}async restoreVmSnapshot(o,c,d,{onVmSnapshotLoaded:l,onBeforeVmSnapshotLoad:f}={}){e.info(`Restoring VM snapshot for emulator ${this.device.deviceId}`);try{let g=ry("load",o);e.info(`Executing: adb -s ${this.device.deviceId} ${g}`),await f?.();let y;try{y=await this.consoleBusyRegistry.runExclusive(this.device.deviceId,()=>this.adb.execute(g.split(" "),{timeoutMs:d,waitForProcessSettlementAfterAbort:!0}))}catch(w){throw Error(eE("load",o,w))}let D=ny("load",o,y);if(!D.ok)throw Object.assign(Error(D.errorMessage),{isDefinitiveVmSnapshotLoadFailure:!0});e.info("VM snapshot restored successfully"),await l?.(),await this.emulator.waitForEmulatorReady(c.deviceName,d,null,{targetDeviceId:this.device.deviceId,options:{skipWakeAndUnlock:!0}}),e.info("VM snapshot restoration complete")}catch(g){let y=r(g);e.error(`Failed to restore VM snapshot: ${y}`);let D=`Failed to restore VM snapshot '${o}' on device ${this.device.deviceId}`,w=g instanceof t?new t(`${D}: ${g.message}`,{cause:g}):u(g,D);if(g instanceof Error&&g.isDefinitiveVmSnapshotLoadFailure===!0)Object.assign(w,{isDefinitiveVmSnapshotLoadFailure:!0});throw w}}async restoreSettingsSnapshot(o){e.info(`Restoring settings-only snapshot for device ${this.device.deviceId}`);try{let c=[];if(o.includeSettings&&o.settings)c=await this.restoreSettings(o.settings);if(o.foregroundApp)await this.restoreForegroundApp(o.foregroundApp);return e.info("Settings snapshot restoration complete"),c}catch(c){throw e.error(`Failed to restore settings snapshot: ${r(c)}`,c),u(c,"Failed to restore settings snapshot")}}async restoreSettings(o){e.info("Restoring device settings");let c=[];for(let[d,l]of Object.entries(o)){if(!l||Object.keys(l).length===0)continue;e.info(`Restoring ${Object.keys(l).length} ${d} settings`);let f=0,g=0;if(!lt(d)){g=Object.keys(l).length,e.warn(`Skipping unsupported settings namespace ${d}`);for(let y of Object.keys(l))c.push({kind:"android_setting",namespace:d,key:y,reason:"unsupported settings namespace"});e.info(`${d} settings restored: ${f} succeeded, ${g} failed`);continue}for(let[y,D]of Object.entries(l)){if(!/^[A-Za-z0-9_.:-]+$/.test(y)){g++,e.warn(`Failed to restore ${d} setting ${y}: invalid settings key`),c.push({kind:"android_setting",namespace:d,key:y,reason:"invalid settings key"});continue}try{await this.applyAndroidSetting(d,y,D),f++}catch(w){g++,e.warn(`Failed to restore ${d} setting ${y}: ${w}`),c.push({kind:"android_setting",namespace:d,key:y,reason:r(w)})}}e.info(`${d} settings restored: ${f} succeeded, ${g} failed`)}return c}async applyAndroidSetting(o,c,d){let l=!1;try{if((await E.getInstance(this.device).requestSettingsPut(o,c,d,{valueType:"string"})).success)l=!0}catch(f){e.debug(`[RestoreSnapshot] a11y settings put failed for ${o}/${c}: ${f}`)}if(!l)await this.adb.executeCommand(`shell settings put ${o} ${b(c)} ${b(d)}`)}async restoreForegroundApp(o){e.info(`Restoring foreground app: ${o}`);try{await this.adb.executeCommand(`shell am start -a android.intent.action.MAIN -c android.intent.category.LAUNCHER ${b(o)}`),e.info(`Launched ${o}`)}catch(c){e.warn(`Failed to restore foreground app: ${c}`)}finally{this.windowCacheInvalidator.invalidate(this.device,!0)}}async executeIos(o){let{snapshotName:c,manifest:d}=o;if(e.info(`[iOS] Restoring snapshot '${c}' (type: ${d.snapshotType})`),d.platform!=="ios")throw new t(`Snapshot platform '${d.platform}' does not match device platform '${this.device.platform}'`);if(d.snapshotType!=="app_data")throw new t(`Unsupported iOS snapshot type '${d.snapshotType}'. Re-capture using app container backups.`);if(await this.validateIosSnapshotCompatibility(d),d.includeSettings&&d.iosSettings)await this.simulatorSnapshotBackend.restoreSettings(d.iosSettings);let l=await this.restoreIosAppData(c,d);if(l.length===0)e.info(`[iOS] Snapshot '${c}' restored successfully`);else e.warn(`[iOS] Snapshot '${c}' partially restored: ${l.length} bundle(s) failed`);return{snapshotType:d.snapshotType,restoredAt:new Date().toISOString(),success:l.length===0,failures:l}}getIosPathOptions(o){return{platform:"ios",deviceId:o??this.device.deviceId}}async restoreIosAppData(o,c){if(!c.includeAppData)return e.info("[iOS] Snapshot does not include app data; skipping restore"),[];let d=await this.resolveIosAppDataPath(o,c);if(!d)return e.warn(`[iOS] App data directory not found for snapshot '${o}'`),[];if(c.appDataBackup?.backupMethod==="none")return e.info("[iOS] Snapshot app data backup method is 'none'; skipping restore"),[];let l=await this.resolveIosSnapshotBundleIds(d,c);if(l.length===0)return e.warn("[iOS] No app bundle IDs found to restore"),[];let f=await this.getInstalledIosBundleIds();if(f.size>0){let y=l.filter((D)=>!f.has(D));if(y.length>0)throw new t(`App(s) not installed on simulator: ${y.join(", ")}. Please reinstall and retry restore.`)}else e.warn("[iOS] Unable to verify installed apps; proceeding with restore");let g=[];for(let y of l)try{await this.restoreIosBundleContainer(y,d)}catch(D){e.warn(`[iOS] Failed to restore app data for ${y}: ${D}`),g.push({kind:"ios_bundle",bundleId:y,reason:r(D)})}return g}async resolveIosAppDataPath(o,c){let d=this.store.getAppDataPath(o,this.getIosPathOptions(c.deviceId));if(await this.iosRestoreOperations.pathExists(d))return d;if(!c.deviceId||c.deviceId===this.device.deviceId)return;let l=this.store.getAppDataPath(o,this.getIosPathOptions(this.device.deviceId));if(!await this.iosRestoreOperations.pathExists(l))return;return e.info(`[iOS] App data not found for '${c.deviceId}', using current device path '${this.device.deviceId}'`),l}async restoreIosBundleContainer(o,c){await this.iosRestoreOperations.terminateAppIfRunning(this.device.deviceId,o);let d=await this.iosRestoreOperations.getAppDataContainerPath(this.device.deviceId,o);if(!d)throw new t(`App data container not found for ${o}`);let l=oe.join(c,o);for(let f of Mk){let g=oe.join(l,f);if(!await this.iosRestoreOperations.pathExists(g))continue;let y=oe.join(d,f);await this.iosRestoreOperations.rm(y,{recursive:!0,force:!0});try{await this.iosRestoreOperations.cp(g,y,{recursive:!0})}catch(D){throw new t(`Existing destination data was wiped/deleted and is now gone at '${y}'; restore copy failed: ${r(D)}`,{cause:D})}}}async validateIosSnapshotCompatibility(o){if(!o.osVersion){e.warn("[iOS] Snapshot OS version missing; skipping compatibility check");return}let c=Oe(o.osVersion);if(!c)throw new t(`Snapshot manifest osVersion '${o.osVersion}' is not an iOS version. Expected an iOS version such as '26.5', 'iOS 26.5' or 'com.apple.CoreSimulator.SimRuntime.iOS-26-5'.`);let d=await this.getIosDeviceOsVersion();if(!d){e.warn("[iOS] Unable to read simulator OS version; skipping compatibility check");return}let l=Oe(d);if(!l)throw new t(`Simulator OS version '${d}' is not an iOS version. Expected an iOS version such as '26.5', 'iOS 26.5' or 'com.apple.CoreSimulator.SimRuntime.iOS-26-5'.`);if(c.major!==l.major)throw new t(`Snapshot iOS version '${o.osVersion}' is incompatible with simulator iOS '${d}'. Please restore on an iOS ${c.major}.x simulator.`)}async getIosDeviceOsVersion(){try{let o=await this.simulatorSnapshotBackend.getDeviceInfo();if(!o)return;let c=o.os_version;if(!c&&o.runtime){let l=(await this.simulatorSnapshotBackend.getRuntimes()).find((f)=>f.identifier===o.runtime);c=l?.version||l?.name}return c}catch(o){e.warn(`[iOS] Failed to read simulator OS version: ${o}`);return}}async getInstalledIosBundleIds(){try{let c=(await this.simulatorSnapshotBackend.listApps()).map((d)=>d.bundleId||d.CFBundleIdentifier).filter((d)=>typeof d==="string"&&d.length>0);return new Set(c)}catch(o){return e.warn(`[iOS] Failed to list installed apps: ${o}`),new Set}}async resolveIosSnapshotBundleIds(o,c){let d=c.appDataBackup?.backedUpPackages;if(d&&d.length>0)return d;try{return(await Tr(o)).filter((f)=>f.isDirectory()).map((f)=>f.name)}catch(l){return e.warn(`[iOS] Failed to read app data bundles: ${l}`),[]}}}import{readFile as gt,stat as yt}from"fs/promises";import{isAbsolute as Ve,join as Be,resolve as wt}from"path";import{createHash as St}from"crypto";import{join as vt}from"path";var ve="userdata-qemu.img",Me=(o)=>St("sha256").update(o).digest("hex");class ge{deps;constructor(o){this.deps=o}async currentIdentity(o){let c=await this.deps.avdDirectory.resolveAvdDirectory(o);if(!c)throw new t(`AVD '${o}' is not on this host`);let d=await this.deps.config.readConfig(o);if(!d?.systemImagePackage||!d.systemImagePath)throw new t(`AVD '${o}' lacks system-image metadata in config.ini`);let l=await this.deps.imageMetadata(d.systemImagePath),f=(await this.deps.emulatorVersion()).split(`
|
|
4
|
+
`)[0]?.trim()??"";if(!f)throw new t("Could not read the emulator version for the fixture identity");let g=this.deps.userdataImage?.(c)??vt(c,ve),y=await this.deps.fileIdentity(g);return{avdName:o,systemImageId:`${d.systemImagePackage}:${Me(l)}`,avdConfigHash:Me(JSON.stringify(d.hardware??{})),emulatorVersion:f,userdataGeneration:y?`${y.ino}:${y.birthtimeMs}`:"none"}}}var Dt=1e4;function ke(){let o=new Nr,c=new pi;return new ge({config:o,avdDirectory:o,imageMetadata:async(d)=>gt(Rt(d,Ve(d)?void 0:Pl()?.androidHome),"utf8"),userdataImage:(d)=>It(d,I(h.EMULATOR_ARGS)),emulatorVersion:async()=>{let d=await c.executeCommand(["-version"],Dt);return d.error?"":d.stdout},fileIdentity:(d)=>At(d)})}async function At(o,c=yt){try{let d=await c(o);return{ino:d.ino,birthtimeMs:d.birthtimeMs}}catch(d){if(d.code!=="ENOENT")throw d;return e.debug(`[DeviceSnapshot] no userdata image at ${o}`),null}}function Rt(o,c){if(Ve(o))return Be(o,"source.properties");if(!c)throw new t("A snapshot fixture needs installed system-image metadata");return wt(c,o,"source.properties")}function It(o,c){let d=c?QR(c):[],l=d.indexOf("-data");if(l===-1)return Be(o,ve);let f=d[l+1];if(!f||f.startsWith("-"))throw new t("AUTOMOBILE_EMULATOR_ARGS passes -data without a path, so a fixture cannot tell which userdata image the emulator runs");return f}async function Ee(o,c){let d=await c.currentIdentity(o.avdName),l=[];if(d.avdName!==o.avdName)l.push("avd-changed");if(d.systemImageId!==o.systemImageId)l.push("system-image-changed");if(d.avdConfigHash!==o.avdConfigHash)l.push("avd-config-changed");if(d.emulatorVersion!==o.emulatorVersion)l.push("emulator-version-changed");if(d.userdataGeneration!==o.userdataGeneration)l.push("userdata-wiped");return l.length===0?{valid:!0}:{valid:!1,reasons:l}}function bt(o,c){return o.platform==="android"&&o.deviceId.startsWith("emulator-")&&c}async function Fe(o,c){let{device:d,snapshotName:l,useVmSnapshot:f,fixture:g}=o;if(!g)return;if(!bt(d,f))throw new lp("fixture_requires_vm_snapshot",l,`Snapshot '${l}' cannot be a fixture: fixtures are Android emulator VM snapshots only. Capture on an emulator without useVmSnapshot: false.`);let y=await c.currentIdentity(d.name);return{identity:y,confirmUnchanged:async()=>(await Te(y,l,c),y)}}async function Te(o,c,d){let l=await Ee(o,d);if(!l.valid)throw new lp("fixture_invalidated",c,`Fixture '${c}' no longer matches AVD '${o.avdName}' (${l.reasons.join(", ")}). Capture it again with fixture: true.`,l.reasons)}async function ze(o,c,d,l){let f=o.manifest.fixture;if(c.fixture&&!f)throw new lp("snapshot_not_a_fixture",o.snapshotName,`Snapshot '${o.snapshotName}' was not captured as a fixture. Capture it again with fixture: true.`);if(!f)return;if(c.fixture&&!d)throw new lp("fixture_requires_vm_snapshot",o.snapshotName,`Fixture '${o.snapshotName}' reloads its VM snapshot; restore it without useVmSnapshot: false.`);await Te(f,o.snapshotName,l)}function Pt(o,c){if(o.platform!==c.platform)return!1;if(c.platform==="ios")return o.deviceId===c.deviceId;let d=c.deviceId.startsWith("emulator-"),l=o.deviceId.startsWith("emulator-");if(!d)return o.deviceId===c.deviceId;return l&&o.deviceName===c.name||o.deviceId.length===0&&o.deviceName===c.name||o.deviceId===c.deviceId&&o.deviceName.length===0}function tH(o,c,d="restored"){if(Pt(o,c))return;let l=`${o.platform} device '${o.deviceName||"unknown"}' (${o.deviceId||"unknown ID"})`,f=`${c.platform} device '${c.name}' (${c.deviceId})`;throw new t(`Snapshot '${o.snapshotName}' belongs to ${l} and cannot be ${d==="restored"?"restored to":"deleted on"} ${f}. `+(d==="restored"?"Restore it on its original device or capture a snapshot for the target device.":"Delete it on its original device."))}function Le(o,c){return`${o}\x00${c}`}async function je(o,c){let d=new Set(o.filter((f)=>f.platform==="android"&&f.snapshotType==="vm").map((f)=>Le(f.deviceName,f.snapshotName))),l=[];try{for(let f of await c.listKnownAvdNames()){let g=await c.listAvdSnapshotDirectories(f);l.push(...g.filter((y)=>y.snapshotName!==Am&&!d.has(Le(f,y.snapshotName))).map((y)=>({avdName:f,...y})))}}catch(f){e.warn(`[DeviceSnapshot] Failed to scan for orphaned in-AVD snapshots: ${f}`,f)}return{count:l.length,totalSizeBytes:l.reduce((f,g)=>f+(g.sizeBytes??0),0),unsizedCount:l.filter((f)=>f.sizeBytes===null).length,entries:l}}var j={prepareForIncarnationChange:async()=>{},invalidate:async()=>{},settleIncarnationChange:async()=>{}};function LX(o){let c=j;return j=o,()=>{j=c}}var rH={prepareForIncarnationChange:(...o)=>j.prepareForIncarnationChange(...o),invalidate:(...o)=>j.invalidate(...o),settleIncarnationChange:(...o)=>j.settleIncarnationChange(...o)};var ye=null,xt="manifest.json",Ct=500,$t=50,Ot=64,Ue=!1,We=0;function re(o){if(Ue)return;Ue=!0;let c=We;o.timer.sleep(Ct).then(()=>{if(c!==We)return;Nt().catch((d)=>{e.warn("[DeviceSnapshot] Startup snapshot journal sweep failed",d)})}).catch((d)=>{e.warn("[DeviceSnapshot] Startup snapshot journal sweep delay failed",d)})}async function Nt(){let{snapshotStore:o}=await _i(),{entries:c,truncated:d}=await o.listLeftoverSnapshotJournals({maxEntries:$t,maxScopeDirectories:Ot}),l={recovered:0,failed:0,skippedLocked:0,truncated:d};for(let{snapshotName:f,options:g}of c){if(J.has(f)){l.skippedLocked++;continue}try{await G(f,()=>o.recoverSnapshotData(f,g)),l.recovered++}catch(y){e.warn(`[DeviceSnapshot] Failed to recover snapshot '${f}' in scope ${JSON.stringify(g??"flat")}`,y),l.failed++}}if(d)e.warn("[DeviceSnapshot] Snapshot journal sweep truncated; remaining artifacts are left to lazy recovery");if(l.recovered||l.failed||l.skippedLocked)e.info(`[DeviceSnapshot] Snapshot journal sweep: ${l.recovered} recovered, ${l.failed} failed, ${l.skippedLocked} locked`);return l}var J=new Map,Mt=new Map,Vt="archive-budget",Bt=new Map,kt="config-update",Et=new Map,H=new Map,we=new Map;function _t(o,c){let d=H.get(o)??new Map;d.set(c,(d.get(c)??0)+1),H.set(o,d)}function Ft(o,c){let d=H.get(o);if(!d)return;let l=d.get(c);if(l===void 0)return;if(l===1)d.delete(c);else d.set(c,l-1);if(d.size===0)H.delete(o)}function Tt(o){let c=H.get(o);return new Set([...c??new Map].filter(([,d])=>d>0).map(([d])=>d))}function zt(o,c){let d=Tt(o);if(c!==void 0)d.add(c);return d}async function Lt(o,c,d,l){if(!Ze(o,d))return l();_t(o.name,c);try{return await l()}finally{Ft(o.name,c)}}function Ze(o,c){return o.platform==="android"&&o.deviceId.startsWith("emulator-")&&c}function pe(o,c,d){let f=(o.get(c)??Promise.resolve()).then(d,d),g=f.then(()=>{return},()=>{return});return o.set(c,g),g.finally(()=>{if(o.get(c)===g)o.delete(c)}),f}function G(o,c){return pe(J,o,c)}function jt(o){return pe(Mt,Vt,o)}function Ut(o){return pe(Bt,kt,o)}function Wt(o,c){return pe(Et,o,c)}function ce(o){if(o.platform==="ios")return{platform:"ios",deviceId:o.deviceId};if(o.platform==="android"&&o.deviceId?.startsWith("emulator-")&&o.avdName)return{platform:"android",avdName:o.avdName};return}async function _i(){if(!ye)ye={snapshotRepository:new me,configRepository:fQ(),snapshotStore:new Rh,avdSnapshots:new o5(new Rh),timer:i,vmRetentionRetryBackoff:Q({initialDelayMs:100,maxDelayMs:5000}),now:()=>new Date,createCaptureProvider:(o,c,d)=>new fe(o,{timer:c,store:d}),createRestoreProvider:(o,c,d)=>new Se(o,{timer:c,store:d}),deviceIncarnationInvalidator:rH,fixtureIdentityProbe:ke()};return ye}function Ht(o){return{includeAppData:o.includeAppData,includeSettings:o.includeSettings,useVmSnapshot:o.useVmSnapshot,strictBackupMode:o.strictBackupMode,vmSnapshotTimeoutMs:o.vmSnapshotTimeoutMs,maxVmSnapshotsPerAvd:o.maxVmSnapshotsPerAvd,maxVmArchiveSizeMb:o.maxVmArchiveSizeMb,maxArchiveSizeMb:o.maxArchiveSizeMb}}function Jt(o,c){return{includeAppData:c.includeAppData??o.includeAppData,includeSettings:c.includeSettings??o.includeSettings,useVmSnapshot:c.useVmSnapshot??o.useVmSnapshot,strictBackupMode:c.strictBackupMode??o.strictBackupMode,vmSnapshotTimeoutMs:c.vmSnapshotTimeoutMs??o.vmSnapshotTimeoutMs,maxVmSnapshotsPerAvd:c.maxVmSnapshotsPerAvd??o.maxVmSnapshotsPerAvd,maxVmArchiveSizeMb:c.maxVmArchiveSizeMb??o.maxVmArchiveSizeMb,maxArchiveSizeMb:c.maxArchiveSizeMb??o.maxArchiveSizeMb}}function Gt(o){if(o===null)return"unknown";if(o<=0)return"0 B";let c=["B","KB","MB","GB"],d=Math.min(Math.floor(Math.log(o)/Math.log(1024)),c.length-1);return`${(o/Math.pow(1024,d)).toFixed(2)} ${c[d]}`}function Kt(o){return{snapshotName:o.snapshotName,restorable:!o.pendingReclaim,deviceId:o.deviceId,deviceName:o.deviceName,platform:o.platform,snapshotType:o.snapshotType,includeAppData:o.includeAppData,includeSettings:o.includeSettings,createdAt:o.createdAt,lastAccessedAt:o.lastAccessedAt,sizeBytes:o.sizeBytes,sizeLabel:Gt(o.sizeBytes),...o.pendingReclaim?{pendingReclaim:!0,...o.pendingReclaimReason===void 0?{}:{pendingReclaimReason:o.pendingReclaimReason}}:{}}}function k(o){return o.platform==="android"&&o.snapshotType==="vm"}async function qe(o,c,d,{avdSnapshots:l,pathOptions:f}){if(!k(c))return d.getSnapshotSizeBytes(o,f);let g=await l.measureVmSnapshotBytes(c.deviceName,o);if(g===null)e.warn(`[DeviceSnapshot] Could not measure the in-AVD payload of VM snapshot '${o}' for AVD '${c.deviceName}'; recording its size as unknown`);return g}function Yt(o){return typeof o==="object"&&o!==null&&o[le]===!0}async function He(o,c,d,{vmSnapshotTimeoutMs:l,context:f}){try{let g=await d.findLiveEmulatorSerial(o.name);if(!g){e.warn(`[DeviceSnapshot] Skipping cleanup of ${f} VM snapshot '${c}' because AVD '${o.name}' is not live`);return}let y=await d.deleteVmSnapshot(g,c,l,o.name);if(!y.reclaimed)e.warn(`[DeviceSnapshot] Could not clean up ${f} VM snapshot '${c}' on AVD '${o.name}': ${y.reason??"unknown reason"}`)}catch(g){e.warn(`[DeviceSnapshot] Failed to clean up ${f} VM snapshot '${c}' on AVD '${o.name}': ${r(g)}`,g)}}async function Qt({device:o,snapshotName:c,includeSettings:d,snapshotRepository:l,avdSnapshots:f,vmSnapshotTimeoutMs:g,now:y,error:D}){let w=`VM snapshot save was dispatched but capture failed: ${r(D)}`,A=null;try{A=await f.measureVmSnapshotBytes(o.name,c)}catch(P){e.warn(`[DeviceSnapshot] Failed to measure orphaned VM snapshot '${c}' on AVD '${o.name}': ${r(P)}`,P)}let R=y().toISOString();try{let P=await l.getSnapshot(c);if(P&&(!k(P)||P.deviceName!==o.name)){let C=k(P)?`it belongs to AVD '${P.deviceName}' (${P.deviceId})`:"it is a non-VM snapshot record";return e.warn(`[DeviceSnapshot] Same-named capture '${c}' failed on AVD '${o.name}' (${o.deviceId}); preserving the existing row because ${C}: ${w}`),await He(o,c,f,{vmSnapshotTimeoutMs:g,context:"failed same-named"}),!1}return await l.insertSnapshot({snapshotName:c,deviceId:o.deviceId,deviceName:o.name,platform:"android",snapshotType:"vm",includeAppData:!0,includeSettings:d,createdAt:R,lastAccessedAt:R,sizeBytes:A,pendingReclaim:!0,pendingReclaimReason:w,manifest:{snapshotName:c,timestamp:R,deviceId:o.deviceId,deviceName:o.name,platform:"android",snapshotType:"vm",includeAppData:!0,includeSettings:d}}),e.warn(`[DeviceSnapshot] Recorded pending reclaim for orphaned VM snapshot '${c}' on AVD '${o.name}': ${w}`),!0}catch(P){return e.warn(`[DeviceSnapshot] Failed to record pending reclaim for orphaned VM snapshot '${c}' on AVD '${o.name}': ${r(P)}`,P),await He(o,c,f,{vmSnapshotTimeoutMs:g,context:"unrecordable"}),!1}}function Xt(o){if(!o||typeof o!=="object")return!1;let c=o;return typeof c.snapshotName==="string"&&typeof c.timestamp==="string"&&typeof c.deviceId==="string"&&typeof c.deviceName==="string"&&(c.platform==="android"||c.platform==="ios")&&Zt(c.snapshotType)&&typeof c.includeAppData==="boolean"&&typeof c.includeSettings==="boolean"}function Zt(o){return o==="adb"||o==="vm"||o==="simctl"||o==="app_data"}function qt(o){if(!o||typeof o!=="object"||Array.isArray(o))return!1;let c=o;return["global","secure","system"].every((d)=>{let l=c[d];return l===void 0||typeof l==="object"&&l!==null&&!Array.isArray(l)})}function Je(o,c){if(c.snapshotName===o)return c;return{...c,snapshotName:o}}function en(o,c){return Number.isNaN(Date.parse(o))?c:o}async function Ge(o){try{let c=await Xe.readFile(o,"utf-8"),d=JSON.parse(c);if(!Xt(d))return e.warn(`[DeviceSnapshot] Manifest at '${o}' has an unexpected shape`),null;return d}catch(c){if(c.code!=="ENOENT")e.warn(`[DeviceSnapshot] Failed to read manifest at '${o}': ${c}`);return null}}async function tn(o,c,d){let l=await Ge(c.getMetadataPath(o,d));if(l)return Je(o,l);let f=ae.join(c.getSnapshotPathWithOptions(o,d),xt),g=await Ge(f);if(g)return Je(o,g);return null}async function nn(o,c,d,l){let f=c.getSettingsPath(o,d),g;try{g=await Xe.readFile(f,"utf-8")}catch(D){if(D.code!=="ENOENT")e.warn(`[DeviceSnapshot] Failed to read settings for '${o}': ${D}`);return null}let y;try{y=JSON.parse(g)}catch(D){return e.warn(`[DeviceSnapshot] Settings file for '${o}' is not valid JSON: ${D}`),null}if(!qt(y))return e.warn(`[DeviceSnapshot] Settings file for '${o}' has an unexpected shape`),null;return{snapshotName:o,timestamp:l().toISOString(),deviceId:"",deviceName:d?.avdName??"",platform:"android",snapshotType:"adb",includeAppData:!1,includeSettings:!0,settings:y}}async function de(o,c,d,l){let f=await tn(o,c,d);if(f)return f;if(d?.platform==="ios")return null;return nn(o,c,d,l)}async function se(o,c,d,{snapshotRepository:l,now:f,pathOptions:g}){let{avdSnapshots:y}=await _i(),D=await qe(o,c,d,{avdSnapshots:y,pathOptions:g}),w=f().toISOString(),A=en(c.timestamp,w),R={snapshotName:o,deviceId:c.deviceId,deviceName:c.deviceName,platform:c.platform,snapshotType:c.snapshotType,includeAppData:c.includeAppData,includeSettings:c.includeSettings,createdAt:A,lastAccessedAt:A,sizeBytes:D,manifest:c};try{return await l.insertSnapshot(R),R}catch(P){return e.warn(`[DeviceSnapshot] Failed to import legacy snapshot '${o}': ${P}`),l.getSnapshot(o)}}async function s6(o,c,d,l){let f=await de(o,c,void 0,l);if(f)return se(o,f,c,{snapshotRepository:d,now:l});let g=await on(o,c,l);if(!g)return null;return se(o,g.manifest,c,{snapshotRepository:d,now:l,pathOptions:g.pathOptions})}async function*et(o){for(let c of["android","ios"]){let d=ae.join(o.getBasePath(),c),l;try{l=await Tr(d)}catch(f){if(f.code!=="ENOENT")e.warn(`[DeviceSnapshot] Failed to scan ${c} snapshot scope: ${f}`);continue}for(let f of l){if(!f.isDirectory())continue;yield{pathOptions:c==="ios"?{platform:"ios",deviceId:f.name}:{platform:"android",avdName:f.name},scopedDirPath:ae.join(d,f.name)}}}}async function on(o,c,d){for await(let{pathOptions:l}of et(c)){if(!await c.snapshotDirectoryExists(o,l))continue;let g=await de(o,c,l,d);if(g)return{manifest:g,pathOptions:l}}return null}async function an(o,c,d,l){let f;try{f=await Tr(c.getBasePath())}catch(y){if(y.code!=="ENOENT")e.warn(`[DeviceSnapshot] Failed to scan legacy snapshots: ${y}`);return!1}let g=!1;for(let y of f){if(!y.isDirectory())continue;let D=y.name;if(D.endsWith(sl))continue;if(Ae(D))continue;if(l.has(D)||J.has(D))continue;let w=await de(D,c,void 0,d);if(!w)continue;if(await se(D,w,c,{snapshotRepository:o,now:d}))l.add(D),g=!0}return g}async function sn(o,c,d,l){let f=!1;for await(let{pathOptions:g,scopedDirPath:y}of et(c)){let D;try{D=await Tr(y)}catch(w){if(w.code!=="ENOENT")e.warn(`[DeviceSnapshot] Failed to scan snapshots under ${y}: ${w}`);continue}for(let w of D){if(!w.isDirectory())continue;let A=w.name;if(A.endsWith(sl))continue;if(l.has(A)||J.has(A))continue;let R=await de(A,c,g,d);if(!R)continue;if(await se(A,R,c,{snapshotRepository:o,now:d,pathOptions:g}))l.add(A),f=!0}}return f}async function rn(o,c,d,l){let f=await an(o,c,d,l),g=await sn(o,c,d,l);return f||g}async function lm(){await lB([fI.ARCHIVE])}function cn(o){let c=HQ(o);if(c?.kind==="scope-root")throw new t(`Snapshot name '${o}' is reserved. Please choose a different name.`);if(c?.kind==="suffix")throw new t(`Snapshot name '${o}' ends with the reserved '${sl}' suffix (case-insensitively). Please choose a different name.`)}function dn(o){if(o.trim().toLowerCase()===Am.toLowerCase())throw new t(`Snapshot name '${Am}' is reserved for the emulator's own quick-boot snapshot and cannot be used as an AutoMobile capture name.`)}async function tt(o,c){let{snapshotRepository:d,avdSnapshots:l}=await _i(),f=o.deviceName,g=await l.findLiveEmulatorSerial(f);if(g)await d.updateSnapshot(o.snapshotName,{pendingReclaim:!0,pendingReclaimReason:`reclaiming the in-AVD payload on AVD '${f}'`});let y=g?await l.deleteVmSnapshot(g,o.snapshotName,c,f):{reclaimed:!1,reason:`emulator for AVD '${f}' is not running; in-AVD snapshot left in place`};if(y.reclaimed)return!0;return e.warn(`[DeviceSnapshot] Could not reclaim the in-AVD payload of VM snapshot '${o.snapshotName}': ${y.reason}. Keeping the record so the reclaim can be completed when that emulator is next seen live.`),await d.updateSnapshot(o.snapshotName,{pendingReclaim:!0,pendingReclaimReason:y.reason}),!1}var Ke=Symbol("snapshot-record-superseded");function nt(o,c){return o.deviceId===c.deviceId&&o.deviceName===c.deviceName&&o.snapshotType===c.snapshotType&&o.createdAt===c.createdAt&&o.sizeBytes===c.sizeBytes&&o.manifest.timestamp===c.manifest.timestamp}async function nH(o,c){if(J.has(o.snapshotName))return e.debug(`[DeviceSnapshot] Skipping reclaim of '${o.snapshotName}': a capture or restore of that name is in flight`),Ke;return G(o.snapshotName,async()=>{let{snapshotRepository:d}=await _i(),l=await d.getSnapshot(o.snapshotName);if(!l||!nt(l,o))return e.debug(`[DeviceSnapshot] Skipping reclaim of '${o.snapshotName}': the record was replaced after it was selected`),Ke;return c()})}async function un(o,c,d){if(!(d instanceof lp)||d.code!=="fixture_invalidated")throw d;let l=(!k(o)||await tt(o,c))&&await aN(o);throw new lp(d.code,d.snapshotName,`${d.message} ${l?"It was removed.":"Its in-AVD snapshot could not be reclaimed now and is pending."}`,d.reasons)}async function sN(o,c){return await nH(o,async()=>{if(k(o)&&!await tt(o,c))return!1;return aN(o)})===!0}async function aN(o){let{snapshotStore:c}=await _i(),d=ce({platform:o.platform,deviceId:o.deviceId,avdName:o.deviceName}),l=[d];if(d?.platform==="android"&&!Ae(o.snapshotName))l.push(void 0);for(let f of l)try{await c.recoverSnapshotData(o.snapshotName,f)}catch(g){e.warn(`[DeviceSnapshot] Recovery before deletion failed for '${o.snapshotName}' in scope ${JSON.stringify(f??"flat")}`,g);let y=await c.discardSnapshotArtifacts(o.snapshotName,f);if(y.length>0)e.warn(`[DeviceSnapshot] Snapshot artifacts left behind after deletion: ${y.join(", ")}`)}return mn(o)}async function mn(o){let{snapshotRepository:c}=await _i();return await it(o),c.deleteSnapshot(o.snapshotName)}async function it(o,c={}){let{snapshotStore:d}=await _i(),l=ce({platform:o.platform,deviceId:o.deviceId,avdName:o.deviceName});if(d.getSnapshotPathWithOptions(o.snapshotName,l)===c.preserveSnapshotPath)return;if(await d.deleteSnapshotData(o.snapshotName,l),l?.platform==="android"&&!Ae(o.snapshotName)&&d.getSnapshotPath(o.snapshotName)!==c.preserveSnapshotPath)await d.deleteSnapshotData(o.snapshotName)}function Ae(o){return o===sV||o===oV}async function hn(o){let{snapshotRepository:c,avdSnapshots:d}=await _i(),l=[];for(let f of o){if(f.sizeBytes!==null||!k(f)){l.push(f);continue}let g=await G(f.snapshotName,async()=>{let y=await d.measureVmSnapshotBytes(f.deviceName,f.snapshotName),D=await c.getSnapshot(f.snapshotName);if(!D||!nt(D,f)){e.warn(`[DeviceSnapshot] Concurrent replacement detected while re-measuring VM snapshot '${f.snapshotName}'; skipping stale size update.`);return}if(y===null)return D;try{return await c.updateSnapshot(f.snapshotName,{sizeBytes:y}),{...D,sizeBytes:y}}catch(w){return e.warn(`[DeviceSnapshot] Failed to record the re-measured size of VM snapshot '${f.snapshotName}': ${r(w)}`,w),D}});if(g)l.push(g)}return l}async function De(o){return jt(async()=>{let c=Math.max(0,Math.floor(o*1024*1024)),{snapshotRepository:d}=await _i(),{vmSnapshotTimeoutMs:l}=await qc(),f=(await d.listSnapshots({orderByLastAccessed:"asc"})).filter((w)=>w.snapshotType!=="vm"),g=f.reduce((w,A)=>w+(A.sizeBytes??0),0),y=f.filter((w)=>w.sizeBytes===null).length;if(y>0)e.warn(`[DeviceSnapshot] ${y} snapshot record(s) have an unknown size and are excluded from the non-VM archive budget`);if(c===0||g<=c)return{evictedSnapshotNames:[],currentSizeBytes:g,maxSizeBytes:c,unsizedCount:y};let D=[];for(let w of f){if(g<=c)break;try{if(await sN(w,l))D.push(w.snapshotName),g-=w.sizeBytes??0}catch(A){e.warn(`[DeviceSnapshot] Failed to evict snapshot ${w.snapshotName}: ${A}`)}}if(g>c)e.warn(`[DeviceSnapshot] Non-VM archive size ${g} bytes still exceeds limit ${c} bytes after eviction`);if(D.length>0)e.warn(`[DeviceSnapshot] Evicted ${D.length} snapshot(s) under the app_data byte budget (maxArchiveSizeMb=${o}): ${D.join(", ")}`),await lm();return{evictedSnapshotNames:D,currentSizeBytes:g,maxSizeBytes:c,unsizedCount:y}})}function ln(o){if(o.maxVmArchiveSizeMb===void 0)return Number.POSITIVE_INFINITY;return Math.max(0,Math.floor(o.maxVmArchiveSizeMb*1024*1024))}function ot(o){return o.snapshots.reduce((c,d)=>c+(d.sizeBytes??0),0)}function fn(o,c,d){return o!==void 0&&c.maxVmArchiveSizeMb!==void 0&&(o.sizeBytes??0)>d}function Sn(o,c){return o.snapshots.find((d)=>!c.has(d.snapshotName)&&!o.failedNames.has(d.snapshotName))}async function Ye(o,c,d,l){let f=Sn(o,d);if(!f)return"no-candidate";try{if(!await sN(f,c.vmSnapshotTimeoutMs)){let{snapshotRepository:g}=await _i(),y=await g.getSnapshot(f.snapshotName);if(y?.pendingReclaim)return"deferred";if(!y||y.deviceName!==f.deviceName)return o.snapshots=o.snapshots.filter((D)=>D.snapshotName!==f.snapshotName),"removed-concurrently";return o.failedNames.add(f.snapshotName),"failed"}return o.snapshots=o.snapshots.filter((g)=>g.snapshotName!==f.snapshotName),o.evictedSnapshotNames.push(f.snapshotName),(l==="count"?o.countEvictedSnapshotNames:o.byteEvictedSnapshotNames).push(f.snapshotName),"evicted"}catch(g){return e.warn(`[DeviceSnapshot] Failed to evict snapshot ${f.snapshotName}: ${g}`),o.failedNames.add(f.snapshotName),"failed"}}async function vn(o){let{snapshotRepository:c}=await _i(),d=await hn((await c.listSnapshots({snapshotType:"vm"})).filter((l)=>l.deviceName===o&&!l.pendingReclaim&&!l.manifest.fixture));return d.sort((l,f)=>l.lastAccessedAt.localeCompare(f.lastAccessedAt)),{snapshots:d,evictedSnapshotNames:[],countEvictedSnapshotNames:[],byteEvictedSnapshotNames:[],failedNames:new Set}}async function gn(o,c,d,l){while(o.snapshots.length>c.maxVmSnapshotsPerAvd){let f=await Ye(o,c,d,"count");if(f==="deferred"||f==="no-candidate")return}while(ot(o)>l){let f=await Ye(o,c,d,"byte");if(f==="deferred"||f==="no-candidate")return}}function yn(o,c,d){if(o.evictedSnapshotNames.length===0)return;e.warn(`[DeviceSnapshot] Evicted ${o.evictedSnapshotNames.length} VM snapshot(s) for AVD '${c}': ${o.countEvictedSnapshotNames.length} by the per-AVD count retention (maxVmSnapshotsPerAvd=${d.maxVmSnapshotsPerAvd}), ${o.byteEvictedSnapshotNames.length} by the VM byte budget (maxVmArchiveSizeMb=${d.maxVmArchiveSizeMb??"unlimited"}): `+o.evictedSnapshotNames.join(", "))}async function wn(o,c,d,{currentSizeBytes:l,maxSizeBytes:f,excludeFromEviction:g}){let y=d.snapshots.length>c.maxVmSnapshotsPerAvd||c.maxVmArchiveSizeMb!==void 0&&l>f;if(d.failedNames.size===0||!y){we.delete(o);return}let{timer:D,vmRetentionRetryBackoff:w}=await _i(),A=(we.get(o)??0)+1;we.set(o,A),D.setTimeout(()=>{qc().then((R)=>Re(o,R,{excludeFromEviction:g})).catch((R)=>{e.warn(`[DeviceSnapshot] Deferred VM retention retry for AVD '${o}' failed: `+r(R),R)})},w.delayForAttempt(A))}async function Re(o,c,d={}){return Wt(o,async()=>{let l=await vn(o),f=zt(o,d.excludeFromEviction),g=ln(c),y=l.snapshots.filter((C)=>C.sizeBytes===null).length;if(y>0)e.warn(`[DeviceSnapshot] ${y} VM snapshot record(s) have an unknown size and are excluded from the VM retention byte budget`);let D=d.excludeFromEviction?l.snapshots.find((C)=>C.snapshotName===d.excludeFromEviction):void 0,w=fn(D,c,g);if(!w)await gn(l,c,f,g);let A=d.excludeFromEviction?l.snapshots.find((C)=>C.snapshotName===d.excludeFromEviction):void 0,R=d.excludeFromEviction!==void 0&&A===void 0,P=ot(l);if(c.maxVmArchiveSizeMb!==void 0&&P>g)e.warn(`[DeviceSnapshot] VM snapshots for AVD '${o}' total ${P} bytes still exceed limit ${g} bytes after retention`);if(yn(l,o,c),l.evictedSnapshotNames.length>0)await lm();return await wn(o,c,l,{currentSizeBytes:P,maxSizeBytes:g,excludeFromEviction:d.excludeFromEviction}),{evictedSnapshotNames:l.evictedSnapshotNames,currentSizeBytes:P,maxSizeBytes:g,unsizedCount:y,cannotFitExcluded:w,excludedSnapshotMissing:R,excludedSnapshotRecord:A??null,excludedSnapshotSizeBytes:A?.sizeBytes??null,countEvictedSnapshotNames:l.countEvictedSnapshotNames,byteEvictedSnapshotNames:l.byteEvictedSnapshotNames}})}async function Qe(o){let{snapshotRepository:c}=await _i(),d=await c.listSnapshots({snapshotType:"vm"}),l=[...new Set(d.map((g)=>g.deviceName))],f=await Promise.all(l.map((g)=>Re(g,o)));return{evictedSnapshotNames:f.flatMap((g)=>g.evictedSnapshotNames),currentSizeBytes:f.reduce((g,y)=>g+y.currentSizeBytes,0),maxSizeBytes:o.maxVmArchiveSizeMb===void 0?0:o.maxVmArchiveSizeMb*1024*1024,unsizedCount:f.reduce((g,y)=>g+y.unsizedCount,0)}}async function Dn(o){if(o.platform!=="android"||!o.deviceId.startsWith("emulator-")||!o.name)return[];let{snapshotRepository:c,avdSnapshots:d}=await _i(),l;try{l=await c.listSnapshots({pendingReclaim:!0,snapshotType:"vm"})}catch(y){return e.warn(`[DeviceSnapshot] Failed to read pending VM snapshot reclaims: ${y}`,y),[]}let f=[],{vmSnapshotTimeoutMs:g}=await qc();for(let y of l.filter((D)=>D.deviceName===o.name))if(await nH(y,async()=>{let w=await d.deleteVmSnapshot(o.deviceId,y.snapshotName,g,y.deviceName);if(!w.reclaimed)return e.warn(`[DeviceSnapshot] Pending reclaim of VM snapshot '${y.snapshotName}' still incomplete: ${w.reason}`),!1;return aN(y)})===!0)f.push(y.snapshotName);if(f.length>0)e.info(`[DeviceSnapshot] Completed ${f.length} pending VM snapshot reclaim(s) for AVD '${o.name}'`),await lm();return f}async function An(o,c,d){let{snapshotRepository:l,avdSnapshots:f}=await _i(),g=await l.getSnapshot(o);if(!g?.pendingReclaim||!k(g)||g.deviceName===c)return;let y=await f.findLiveEmulatorSerial(g.deviceName),D=y?await f.deleteVmSnapshot(y,o,d,g.deviceName):{reclaimed:!1,reason:`emulator for AVD '${g.deviceName}' is not running`};if(D.reclaimed){e.info(`[DeviceSnapshot] Reclaimed the pending in-AVD payload of '${o}' on AVD '${g.deviceName}' before reusing that name on AVD '${c}'`);return}e.warn(`[DeviceSnapshot] Capturing '${o}' on AVD '${c}' overwrites the only record of a pending reclaim for AVD '${g.deviceName}' (${D.reason}). Its in-AVD payload stays on disk and is reported as an orphan until it is removed manually (see docs/using/test-prep-tools.md).`)}async function qc(){let{configRepository:o}=await _i(),c=await o.getConfig();if(c)return z(c);return z(N.getDeviceSnapshotDefaults())}async function BX(o){return Ut(async()=>{let{configRepository:c,timer:d}=await _i();if(re({timer:d}),o===null){await c.clearConfig();let w=z(N.getDeviceSnapshotDefaults()),[A,R]=await Promise.all([De(w.maxArchiveSizeMb),Qe(w)]);return{config:w,evictedSnapshotNames:[...A.evictedSnapshotNames,...R.evictedSnapshotNames]}}let l=await qc(),f=Jt(Ht(l),o),g=z(f);await c.setConfig(g);let[y,D]=await Promise.all([De(g.maxArchiveSizeMb),Qe(g)]);return{config:g,evictedSnapshotNames:[...y.evictedSnapshotNames,...D.evictedSnapshotNames]}})}async function Rn(o,c,d,l){let f=await De(d.maxArchiveSizeMb);if(o.manifest.snapshotType!=="vm")return f.evictedSnapshotNames;let g=await Re(c.name,d,o.manifest.fixture?{}:{excludeFromEviction:o.snapshotName});if(g.excludedSnapshotMissing)throw new t(`Snapshot '${o.snapshotName}' was removed by a concurrent VM retention sweep before capture could complete; capture did not succeed`);if(!g.cannotFitExcluded)return[...f.evictedSnapshotNames,...g.evictedSnapshotNames];if(l)throw await lm(),new t(`Snapshot '${o.snapshotName}' recapture exceeds the configured maxVmArchiveSizeMb budget for AVD '${c.name}'. The emulator's destructive snapshot save already irreversibly overwrote the prior payload under this name, so the new oversized capture was kept rather than deleting the only remaining usable snapshot.`);let y=g.excludedSnapshotRecord;if(y){if(!await sN(y,d.vmSnapshotTimeoutMs))throw await lm(),new t(`Snapshot '${o.snapshotName}' exceeds maxVmArchiveSizeMb but its VM payload could not be reclaimed; it remains tracked for a later reclaim`)}let D=Math.floor((d.maxVmArchiveSizeMb??0)*1024*1024);throw new t(`Snapshot '${o.snapshotName}' could not be captured because its VM payload (${g.excludedSnapshotSizeBytes??"unknown"} bytes) exceeds the configured maxVmArchiveSizeMb budget for AVD '${c.name}' (${D} bytes)`)}async function In(o,c,d,l){if(wh(c),cn(c),Ze(o,d))dn(c);let{fixtureIdentityProbe:f}=await _i();return Fe({device:o,snapshotName:c,useVmSnapshot:d,fixture:l.fixture},f)}async function $X(o,c){let{snapshotRepository:d,snapshotStore:l,avdSnapshots:f,timer:g,now:y,createCaptureProvider:D}=await _i();re({timer:g});let w=await qc(),A=c.useVmSnapshot??w.useVmSnapshot,R=c.snapshotName??l.generateSnapshotName(o.name),P=await In(o,R,A,c);await Dn(o);let C=ce({platform:o.platform,deviceId:o.deviceId,avdName:o.name}),M={...w,includeAppData:c.includeAppData??w.includeAppData,includeSettings:c.includeSettings??w.includeSettings,useVmSnapshot:A,strictBackupMode:c.strictBackupMode??w.strictBackupMode,vmSnapshotTimeoutMs:c.vmSnapshotTimeoutMs??w.vmSnapshotTimeoutMs};return Lt(o,R,M.useVmSnapshot,async()=>{let _=!1,U=await G(R,async()=>{let V=await d.getSnapshot(R);_=V!==null&&V.deviceName===o.name,await An(R,o.name,M.vmSnapshotTimeoutMs);let ue=D(o,g,l),T,X=!1;try{T=await l.replaceSnapshotData(R,C,async()=>{let x=await ue.capture({snapshotName:R,includeAppData:M.includeAppData,includeSettings:M.includeSettings,useVmSnapshot:M.useVmSnapshot,strictBackupMode:M.strictBackupMode,vmSnapshotTimeoutMs:M.vmSnapshotTimeoutMs,appBundleIds:c.appBundleIds});X=x.manifest.snapshotType==="vm",x.manifest.fixture??=await P?.confirmUnchanged();let W=await qe(R,x.manifest,l,{avdSnapshots:f,pathOptions:C}),Z=x.manifest.timestamp;return await d.insertSnapshot({snapshotName:x.snapshotName,deviceId:x.manifest.deviceId,deviceName:x.manifest.deviceName,platform:x.manifest.platform,snapshotType:x.manifest.snapshotType,includeAppData:x.manifest.includeAppData,includeSettings:x.manifest.includeSettings,createdAt:Z,lastAccessedAt:Z,sizeBytes:W,manifest:x.manifest}),x})}catch(x){if(o.platform==="android"&&o.deviceId.startsWith("emulator-")&&(Yt(x)||X)){if(await Qt({device:o,snapshotName:R,includeSettings:M.includeSettings,snapshotRepository:d,avdSnapshots:f,vmSnapshotTimeoutMs:M.vmSnapshotTimeoutMs,now:y,error:x}))await lm()}throw x}if(V)try{await it(V,{preserveSnapshotPath:l.getSnapshotPathWithOptions(R,C)})}catch(x){e.warn(`[DeviceSnapshot] Failed to retire prior archive data for '${R}': ${r(x)}`,x)}return T}),F=await qc(),K={...M,maxVmSnapshotsPerAvd:F.maxVmSnapshotsPerAvd,maxArchiveSizeMb:F.maxArchiveSizeMb,maxVmArchiveSizeMb:F.maxVmArchiveSizeMb},Y=await Rn(U,o,K,_);return await lm(),{result:U,evictedSnapshotNames:Y}})}async function UX(o,c){let{snapshotRepository:d,snapshotStore:l,timer:f,now:g,createRestoreProvider:y,deviceIncarnationInvalidator:D,fixtureIdentityProbe:w}=await _i();return re({timer:f}),wh(c.snapshotName),G(c.snapshotName,async()=>{let A=await d.getSnapshot(c.snapshotName);if(!A)A=await s6(c.snapshotName,l,d,g);if(!A)throw new t(`Snapshot '${c.snapshotName}' not found`);if(tH(A,o),A.pendingReclaim){let O=A.pendingReclaimReason?`: ${A.pendingReclaimReason}`:"";throw new t(`Snapshot '${A.snapshotName}' is awaiting reclaim after a failed capture${O}`)}let R=await qc(),P=c.useVmSnapshot??R.useVmSnapshot,C=c.vmSnapshotTimeoutMs??R.vmSnapshotTimeoutMs;await ze(A,c,P,w).catch((O)=>un(A,C,O));try{await l.recoverSnapshotData(A.snapshotName,ce({platform:A.platform,deviceId:A.deviceId,avdName:A.deviceName}))}catch(O){throw e.warn(`[DeviceSnapshot] Failed to recover snapshot '${A.snapshotName}' before restore: ${r(O)}`,O),u(O,`Failed to recover snapshot '${A.snapshotName}' before restore`)}let M=y(o,f,l),_=!1,U=!1,F=!1,K=!1,Y=!1,V={},ue=async()=>{if(_||o.platform!=="android"||!o.deviceId.startsWith("emulator-")||A.manifest.snapshotType!=="vm"||!P)return;_=!0,await D.prepareForIncarnationChange(o)},T=async()=>{if(U||o.platform!=="android"||!o.deviceId.startsWith("emulator-")||A.manifest.snapshotType!=="vm"||!P)return;U=!0;let O=await D.invalidate(o);if(typeof O==="string")V={deviceSessionUuid:O}},X=async()=>{F=!0,await T()},x=async()=>{if(!_||K)return;K=!0,await D.settleIncarnationChange(o,{ready:Y})},W;try{W=await M.restore({snapshotName:A.snapshotName,manifest:A.manifest,useVmSnapshot:P,vmSnapshotTimeoutMs:C,onBeforeVmSnapshotLoad:ue,onVmSnapshotLoaded:X}),Y=!0,await T()}catch(O){let at=O instanceof Error&&O.isDefinitiveVmSnapshotLoadFailure===!0;if(F||!at)await T();throw u(O,`Failed to restore snapshot '${A.snapshotName}'`)}finally{await x()}let Z=g().toISOString();return await d.touchSnapshot(A.snapshotName,Z),await lm(),{result:W,manifest:A.manifest,...V}})}async function HX(){let{snapshotRepository:o,snapshotStore:c,now:d,timer:l}=await _i();re({timer:l});let f=await o.listSnapshots({orderByCreatedAt:"desc"}),g=new Set(f.map((P)=>P.snapshotName)),D=await rn(o,c,d,g)?await o.listSnapshots({orderByCreatedAt:"desc"}):f,w=D.map(Kt),A=D.reduce((P,C)=>P+(C.sizeBytes??0),0),R=await je(D,(await _i()).avdSnapshots);return{snapshots:w,count:w.length,totalSizeBytes:A,unsizedCount:D.filter((P)=>P.sizeBytes===null).length,pendingReclaimCount:D.filter((P)=>P.pendingReclaim).length,orphanedAvdSnapshots:R}}
|
|
5
|
+
export{fI,tH,LX,rH,_i,s6,lm,nH,sN,aN,qc,BX,$X,UX,HX};
|
|
6
|
+
|
|
7
|
+
//# debugId=66D5837E885EA02F64756E2164756E21
|
|
@@ -0,0 +1,4 @@
|
|
|
1
|
+
// @bun
|
|
2
|
+
import{_2,G9,dU,Za,py,Ace,my,Mf,Ta}from"./chunk-r6pvhj33.js";import"./chunk-r0vp315h.js";import"./chunk-5wk1t46v.js";export{_2 as DARWIN_PS_LSTART_ENV,Za as compareProcessGenerationTokens,Mf as currentDaemonProcessGenerationToken,G9 as daemonGenerationMatches,dU as darwinProcessGenerationToken,Ace as processGenerationReadIsCheap,my as readDarwinProcessGenerationToken,py as readLinuxProcessGenerationToken,Ta as readProcessGenerationTokenForPid};
|
|
3
|
+
|
|
4
|
+
//# debugId=2DAA040CBF9CA0C764756E2164756E21
|
|
@@ -0,0 +1,4 @@
|
|
|
1
|
+
// @bun
|
|
2
|
+
import{qv,Eo}from"./chunk-t54k47em.js";import"./chunk-cb1ga9rd.js";import"./chunk-sfqe223f.js";import"./chunk-r6pvhj33.js";import"./chunk-w5yypt53.js";import"./chunk-aewdveet.js";import"./chunk-r0vp315h.js";import"./chunk-5wk1t46v.js";export{Eo as Keyboard,qv as KeyboardOpenIndeterminateError};
|
|
3
|
+
|
|
4
|
+
//# debugId=2AEE9D091100E37B64756E2164756E21
|
|
@@ -0,0 +1,5 @@
|
|
|
1
|
+
// @bun
|
|
2
|
+
import{i,Q,e}from"./chunk-r0vp315h.js";import{on}from"./chunk-sfqe223f.js";import{aD}from"./chunk-4vxeq0vd.js";import{Y9,Kb,WO,O2}from"./chunk-r6pvhj33.js";import{im,u}from"./chunk-2b39zyxc.js";var p=300000;class SM{store;windowMs;constructor(r=new aD,t=p){this.store=r,this.windowMs=t}recordFailure(r,t){let a=this.read().filter((o)=>t-o.at<=this.windowMs);a.push({at:t,kind:r});try{this.store.write(JSON.stringify(a))}catch(o){return e.debug(`Failed to persist startup failure tracker: ${o}`),Math.max(a.length,2)}return a.length}reset(){this.store.clear()}read(){let r=this.store.read();if(r===null)return[];try{let t=JSON.parse(r);if(!Array.isArray(t))return[];return t.filter((a)=>typeof a?.at==="number"&&(a.kind==="transient"||a.kind==="permanent"))}catch(t){return e.debug(`Failed to parse startup failure tracker contents: ${t}`),[]}}}var d=Math.max(1000,on-2000);async function UU(r,t,a=i){let o=Y9(r),n=t.recordFailure(o,a.now()),c=O2(r)?`${o}/${Kb}`:o;if(e.error(`Fatal: database initialization failed (${c}; ${n} recent failure(s)); daemon cannot serve queries and will exit for a clean restart: ${im(r)}`),o==="permanent"&&n>1){let l=Q({initialDelayMs:1000,multiplier:2,maxDelayMs:d}).delayForAttempt(n-1);e.error(`Database initialization has failed ${n} times; backing off ${l}ms before exit to avoid a restart hot-loop.`),await a.sleep(l)}let s=u(r,"Database initialization failed at daemon startup");if(O2(r))s.code=Kb;throw s}function bce(r){return O2(r)?WO:1}async function Sce(r,t=new SM,a=i){try{await r()}catch(o){await UU(o,t,a)}}
|
|
3
|
+
export{SM,UU,bce,Sce};
|
|
4
|
+
|
|
5
|
+
//# debugId=50C3DDB444388E7064756E2164756E21
|