@runweave/server-linux-arm64 0.0.0-stage → 0.1.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (112) hide show
  1. package/manifest.json +1993 -0
  2. package/native.tar.gz +0 -0
  3. package/package.json +17 -4
  4. package/payload/app-server/build-info.json +8 -0
  5. package/payload/app-server/configuration-compatibility.json +1 -0
  6. package/payload/app-server/index.cjs +43560 -0
  7. package/payload/app-server/index.cjs.map +1 -0
  8. package/payload/backend/activity-sqlite-worker.cjs +6730 -0
  9. package/payload/backend/build-info.json +8 -0
  10. package/payload/backend/dev-resources/control.cjs +14727 -0
  11. package/payload/backend/evolution-sqlite-worker.cjs +2073 -0
  12. package/payload/backend/index.cjs +135608 -0
  13. package/payload/backend/ios-simulators/device_shutdown.py +22 -0
  14. package/payload/backend/ios-simulators/monitor.py +204 -0
  15. package/payload/backend/ios-simulators/pool.py +600 -0
  16. package/payload/backend/scheduled-tasks-sqlite-worker.cjs +29203 -0
  17. package/payload/bin/runtime.cjs +95 -0
  18. package/payload/frontend/dist/assets/_baseUniq-BJ9V9bG-.js +1 -0
  19. package/payload/frontend/dist/assets/access-DYFqfdy3.js +1 -0
  20. package/payload/frontend/dist/assets/advanced-C4Sx575S.js +1 -0
  21. package/payload/frontend/dist/assets/appearance-Bhq5haQK.js +1 -0
  22. package/payload/frontend/dist/assets/arc-Bihx3tKA.js +1 -0
  23. package/payload/frontend/dist/assets/architectureDiagram-Q4EWVU46-63rNkvm4.js +36 -0
  24. package/payload/frontend/dist/assets/blockDiagram-DXYQGD6D-BlolQExt.js +132 -0
  25. package/payload/frontend/dist/assets/browser-CIEzmzuD.js +8 -0
  26. package/payload/frontend/dist/assets/c4Diagram-AHTNJAMY-DJtJ952u.js +10 -0
  27. package/payload/frontend/dist/assets/channel-Mm4Vb-2P.js +1 -0
  28. package/payload/frontend/dist/assets/chunk-4BX2VUAB-ChncjhEG.js +1 -0
  29. package/payload/frontend/dist/assets/chunk-4TB4RGXK-C6ipd8Rb.js +206 -0
  30. package/payload/frontend/dist/assets/chunk-55IACEB6-D9P1TLAl.js +1 -0
  31. package/payload/frontend/dist/assets/chunk-EDXVE4YY-NqBFXrAb.js +1 -0
  32. package/payload/frontend/dist/assets/chunk-FMBD7UC4-DDP02KGl.js +15 -0
  33. package/payload/frontend/dist/assets/chunk-OYMX7WX6-BH7IIwJs.js +231 -0
  34. package/payload/frontend/dist/assets/chunk-QZHKN3VN-BQs-0fGA.js +1 -0
  35. package/payload/frontend/dist/assets/chunk-YZCP3GAM-BjN5B1FZ.js +1 -0
  36. package/payload/frontend/dist/assets/classDiagram-6PBFFD2Q-BiLH0Poy.js +1 -0
  37. package/payload/frontend/dist/assets/classDiagram-v2-HSJHXN6E-BiLH0Poy.js +1 -0
  38. package/payload/frontend/dist/assets/clone-qIEEEAzl.js +1 -0
  39. package/payload/frontend/dist/assets/companion-BLgWW1ka.css +1 -0
  40. package/payload/frontend/dist/assets/companion-CRS3Tmyt.js +2 -0
  41. package/payload/frontend/dist/assets/connection-BK8OyohU.js +12 -0
  42. package/payload/frontend/dist/assets/connections-BMlDGuxr.js +1 -0
  43. package/payload/frontend/dist/assets/cose-bilkent-S5V4N54A-NPOCJBiA.js +1 -0
  44. package/payload/frontend/dist/assets/css.worker-B4z49cGk.js +93 -0
  45. package/payload/frontend/dist/assets/cytoscape.esm-DxGcaOPV.js +331 -0
  46. package/payload/frontend/dist/assets/dagre-KV5264BT-COIvyDWn.js +4 -0
  47. package/payload/frontend/dist/assets/defaultLocale-DX6XiGOO.js +1 -0
  48. package/payload/frontend/dist/assets/desktop-ByVdibdg.js +1 -0
  49. package/payload/frontend/dist/assets/diagram-5BDNPKRD-S_8jRdqp.js +10 -0
  50. package/payload/frontend/dist/assets/diagram-G4DWMVQ6-C42mxsNM.js +24 -0
  51. package/payload/frontend/dist/assets/diagram-MMDJMWI5-BJM6otf0.js +43 -0
  52. package/payload/frontend/dist/assets/diagram-TYMM5635-By5p6aCA.js +24 -0
  53. package/payload/frontend/dist/assets/editor.worker-DyuDvpVp.js +26 -0
  54. package/payload/frontend/dist/assets/erDiagram-SMLLAGMA-U0Ye_786.js +85 -0
  55. package/payload/frontend/dist/assets/flowDiagram-DWJPFMVM-CUkOR4uD.js +162 -0
  56. package/payload/frontend/dist/assets/ganttDiagram-T4ZO3ILL-CRlDiioi.js +292 -0
  57. package/payload/frontend/dist/assets/gitGraphDiagram-UUTBAWPF-DV4Ea1j2.js +106 -0
  58. package/payload/frontend/dist/assets/graph-Bn4s-NIu.js +1 -0
  59. package/payload/frontend/dist/assets/html.worker-DtiGdgqp.js +470 -0
  60. package/payload/frontend/dist/assets/image-0wCxVgo2.js +1 -0
  61. package/payload/frontend/dist/assets/index-BJDOs8Sk.css +1 -0
  62. package/payload/frontend/dist/assets/index-D9-cSGu-.js +49 -0
  63. package/payload/frontend/dist/assets/index-De2lxGIa.js +455 -0
  64. package/payload/frontend/dist/assets/infoDiagram-42DDH7IO-ut--ZHxq.js +2 -0
  65. package/payload/frontend/dist/assets/init-Gi6I4Gst.js +1 -0
  66. package/payload/frontend/dist/assets/ishikawaDiagram-UXIWVN3A-DbJ9qouY.js +70 -0
  67. package/payload/frontend/dist/assets/journeyDiagram-VCZTEJTY-CZ5a4nqq.js +139 -0
  68. package/payload/frontend/dist/assets/json.worker-leyajbqV.js +58 -0
  69. package/payload/frontend/dist/assets/kanban-definition-6JOO6SKY-CagFKide.js +89 -0
  70. package/payload/frontend/dist/assets/katex-DkKDou_j.js +257 -0
  71. package/payload/frontend/dist/assets/layout-DJ8E_yHX.js +1 -0
  72. package/payload/frontend/dist/assets/linear-Dn6DMk6q.js +1 -0
  73. package/payload/frontend/dist/assets/main-C-ZLrzMh.css +33 -0
  74. package/payload/frontend/dist/assets/main-T426svZw.js +693 -0
  75. package/payload/frontend/dist/assets/min-DnGEZSmi.js +1 -0
  76. package/payload/frontend/dist/assets/mindmap-definition-QFDTVHPH-Dy5F9V5f.js +96 -0
  77. package/payload/frontend/dist/assets/monitoring-BdNkTyog.js +1 -0
  78. package/payload/frontend/dist/assets/notifications-incoktxl.js +1 -0
  79. package/payload/frontend/dist/assets/ordinal-Cboi1Yqb.js +1 -0
  80. package/payload/frontend/dist/assets/pieDiagram-DEJITSTG-yXPGxeUi.js +30 -0
  81. package/payload/frontend/dist/assets/quadrantDiagram-34T5L4WZ-D4cCRjRq.js +7 -0
  82. package/payload/frontend/dist/assets/record-content-D1WJhPcw.js +1 -0
  83. package/payload/frontend/dist/assets/requirementDiagram-MS252O5E-mq9zSUQY.js +84 -0
  84. package/payload/frontend/dist/assets/sankeyDiagram-XADWPNL6-CLpI-tDz.js +10 -0
  85. package/payload/frontend/dist/assets/sequenceDiagram-FGHM5R23-B-T8p6AJ.js +157 -0
  86. package/payload/frontend/dist/assets/shortcuts-BNrV46nh.js +1 -0
  87. package/payload/frontend/dist/assets/stateDiagram-FHFEXIEX-l2_t6o5K.js +1 -0
  88. package/payload/frontend/dist/assets/stateDiagram-v2-QKLJ7IA2-BXh3ccaZ.js +1 -0
  89. package/payload/frontend/dist/assets/status-CP5f7C2Y.js +1 -0
  90. package/payload/frontend/dist/assets/suiji-BAD1Bzfb.js +1 -0
  91. package/payload/frontend/dist/assets/svg-G8v0TLQu.js +21 -0
  92. package/payload/frontend/dist/assets/tabs-CuKPIDlT.js +1 -0
  93. package/payload/frontend/dist/assets/timeline-definition-GMOUNBTQ-CSaExDd9.js +120 -0
  94. package/payload/frontend/dist/assets/ts.worker-59MjiAqk.js +67731 -0
  95. package/payload/frontend/dist/assets/vennDiagram-DHZGUBPP-x-fCoh_Q.js +34 -0
  96. package/payload/frontend/dist/assets/wardley-RL74JXVD-B4O75ZAB.js +162 -0
  97. package/payload/frontend/dist/assets/wardleyDiagram-NUSXRM2D-CdXssvxH.js +20 -0
  98. package/payload/frontend/dist/assets/workbox-window.prod.es5-BIl4cyR9.js +2 -0
  99. package/payload/frontend/dist/assets/xychartDiagram-5P7HB3ND-DwTtw7p0.js +7 -0
  100. package/payload/frontend/dist/build-info.json +8 -0
  101. package/payload/frontend/dist/companion.html +15 -0
  102. package/payload/frontend/dist/icons/apple-touch-icon.png +0 -0
  103. package/payload/frontend/dist/icons/icon-192.png +0 -0
  104. package/payload/frontend/dist/icons/icon-512.png +0 -0
  105. package/payload/frontend/dist/icons/maskable-icon-512.png +0 -0
  106. package/payload/frontend/dist/index.html +19 -0
  107. package/payload/frontend/dist/manifest.webmanifest +28 -0
  108. package/payload/frontend/dist/sw.js +1 -0
  109. package/payload/frontend/dist/workbox-632bafe5.js +1 -0
  110. package/payload/server/index.cjs +8620 -0
  111. package/payload/start.mjs +50 -0
  112. package/README.md +0 -3
@@ -0,0 +1,22 @@
1
+ """Shut down a leased simulator before its pool ownership is released."""
2
+ import time
3
+
4
+ from pool import capture, devices, fail
5
+
6
+
7
+ def shutdown_simulator(udid):
8
+ deadline = time.monotonic() + 30
9
+ shutdown_sent = False
10
+ while True:
11
+ device = devices().get(udid)
12
+ if not device or not device.get("isAvailable"):
13
+ fail("cleanup_incomplete", "Simulator is unavailable; keep lease for inspection")
14
+ if device["state"] == "Shutdown":
15
+ return
16
+ if device["state"] == "Booted" and not shutdown_sent:
17
+ capture(["xcrun", "simctl", "shutdown", udid])
18
+ shutdown_sent = True
19
+ continue
20
+ if time.monotonic() >= deadline:
21
+ fail("cleanup_incomplete", "Simulator did not shut down; keep lease for inspection")
22
+ time.sleep(0.2)
@@ -0,0 +1,204 @@
1
+ """Read-only pool projection and ownership-checked release; no adoption or startup."""
2
+ import hashlib
3
+ import json
4
+ import os
5
+ from pathlib import Path
6
+ import re
7
+ import subprocess
8
+ import sys
9
+
10
+ import pool
11
+
12
+ MAX_BYTES = 1024 * 1024
13
+
14
+
15
+ def safe_read(path):
16
+ path = Path(path).absolute()
17
+ for parent in [*reversed(path.parents), path]:
18
+ if parent.is_symlink():
19
+ raise ValueError("Resource path contains a symbolic link")
20
+ descriptor = os.open(path, os.O_RDONLY | os.O_NOFOLLOW)
21
+ try:
22
+ stat = os.fstat(descriptor)
23
+ if stat.st_size > MAX_BYTES:
24
+ raise ValueError("Resource record exceeds size limit")
25
+ with os.fdopen(descriptor, "r", closefd=False) as stream:
26
+ result = json.load(stream)
27
+ named = path.stat(follow_symlinks=False)
28
+ if (named.st_ino, named.st_dev) != (stat.st_ino, stat.st_dev):
29
+ raise ValueError("Resource changed while reading")
30
+ return result
31
+ finally:
32
+ os.close(descriptor)
33
+
34
+
35
+ def owner_version(owner):
36
+ return hashlib.sha256(json.dumps([owner.get(key) for key in
37
+ ("schemaVersion", "repositoryId", "worktree", "taskDir", "udid", "lease", "app", "slot", "startedAt")],
38
+ ensure_ascii=False, separators=(",", ":")).encode()).hexdigest()
39
+
40
+
41
+ def unknown_group(reason):
42
+ return {"sourceState": "unavailable", "reason": reason, "resources": [],
43
+ "counts": dict.fromkeys(("total", "busy", "free", "blocked", "unknown"))}
44
+
45
+
46
+ def valid_owner(owner, repository, slot, udid):
47
+ if not isinstance(owner, dict) or owner.get("schemaVersion") != 1 or owner.get("kind") != "simulator-pool":
48
+ return False
49
+ return (owner.get("repositoryId") == repository and owner.get("udid", "").upper() == udid
50
+ and owner.get("slot", owner.get("app")) == slot and owner.get("app") in pool.APPS
51
+ and all(isinstance(owner.get(key), str) and owner[key] for key in ("lease", "taskDir", "worktree")))
52
+
53
+
54
+ def projection():
55
+ registry_root = pool.BASE / "ios-simulators"
56
+ if not registry_root.exists():
57
+ return {"sourceState": "ready", "reason": "尚未配置受管理的模拟器", "resources": [],
58
+ "counts": {"total": 0, "busy": 0, "free": 0, "blocked": 0, "unknown": 0}}
59
+ if registry_root.is_symlink():
60
+ return unknown_group("模拟器 registry 不允许符号链接")
61
+ registrations = {}
62
+ failures = []
63
+ entries = list(registry_root.iterdir())
64
+ if len(entries) > 256:
65
+ failures.append("模拟器 registry 超过扫描上限")
66
+ for entry in entries[:256]:
67
+ if not re.fullmatch(r"[a-f0-9]{64}", entry.name):
68
+ continue
69
+ try:
70
+ record = safe_read(entry / "pool.json")
71
+ if (record.get("schemaVersion") != 1 or record.get("repositoryId") != entry.name
72
+ or set(record.get("slots", {})) != set(pool.APPS)):
73
+ raise ValueError("Unknown registry schema")
74
+ for slot, value in record["slots"].items():
75
+ udid = value.get("udid", "").upper()
76
+ pool.udid_path(udid)
77
+ registrations.setdefault(udid, []).append((entry.name, slot, value))
78
+ except (OSError, ValueError, pool.PoolError):
79
+ failures.append("部分模拟器登记损坏或不可读取")
80
+ if not registrations and failures:
81
+ return unknown_group(";".join(sorted(set(failures))))
82
+ if not registrations:
83
+ return {"sourceState": "ready", "reason": "尚未配置受管理的模拟器", "resources": [],
84
+ "counts": {"total": 0, "busy": 0, "free": 0, "blocked": 0, "unknown": 0}}
85
+ available = pool.devices()
86
+ try:
87
+ tool = subprocess.run(["agent-device", "--version"], text=True, capture_output=True, timeout=5)
88
+ tool_ready = tool.returncode == 0 and tool.stdout.strip() == "0.21.3"
89
+ except (OSError, subprocess.TimeoutExpired):
90
+ tool_ready = False
91
+ resources = []
92
+ for udid, records in sorted(registrations.items()):
93
+ repository, slot, value = records[0]
94
+ device = available.get(udid)
95
+ resource = {"id": "simulator:" + udid, "kind": "simulator", "label": device.get("name") if device else value.get("name", udid),
96
+ "state": "unknown", "owner": None, "ownershipVersion": None,
97
+ "details": {"path": None, "udid": udid, "deviceState": device and device.get("state"), "ports": [], "processes": []},
98
+ "release": {"action": None, "disabledReason": None}, "operation": None, "reason": None}
99
+ lock = pool.udid_path(udid)
100
+ try:
101
+ owner = safe_read(lock / "owner.json") if lock.exists() else None
102
+ if len(records) != 1:
103
+ raise ValueError("同一物理 UDID 存在冲突登记")
104
+ if not device or not device.get("isAvailable"):
105
+ raise ValueError("模拟器不可用,请检查 Xcode 设备状态")
106
+ if owner is None:
107
+ # A foreign XCTest runner is occupancy even without our owner lock.
108
+ pool.check_external_runner(udid)
109
+ resource["state"] = "free"
110
+ else:
111
+ if not valid_owner(owner, repository, slot, udid):
112
+ raise ValueError("占用身份与模拟器登记不一致")
113
+ version = owner_version(owner)
114
+ resource["ownershipVersion"] = version
115
+ resource["owner"] = {"id": owner["lease"], "task": Path(owner["taskDir"]).name,
116
+ "worktree": Path(owner["worktree"]).name, "startedAt": owner.get("startedAt"),
117
+ "lastActivityAt": owner.get("lastActivityAt")}
118
+ resource["details"]["path"] = owner["taskDir"]
119
+ runner_path = Path.home() / ".agent-device/apple-runner/leases" / (udid + ".json")
120
+ if runner_path.exists():
121
+ runner = safe_read(runner_path)
122
+ pid = runner.get("runnerPid")
123
+ if isinstance(pid, int) and pid > 1 and pool.identity(pid):
124
+ owned = runner.get("ownerStateDir") == str(Path(owner["taskDir"]) / "state") and runner.get("runnerStartTime") == pool.identity(pid)
125
+ resource["details"]["processes"].append({"name": "XCTest Runner", "pid": pid, "ownership": "owned" if owned else "unknown", "cpuPercent": None, "rssBytes": None})
126
+ if not owned:
127
+ raise ValueError("Runner 身份与任务不一致")
128
+ active = bool(pool.active_operation(owner))
129
+ unresolved = pool.unsettled(owner)
130
+ residual = bool(owner.get("finishedAt") or (pool.idle_seconds(owner) or 0) >= pool.IDLE_SECONDS)
131
+ resource["state"] = "blocked" if unresolved and not active or residual else "busy"
132
+ reason = "自有子进程尚未确认退出" if unresolved else "任务残留占用,需要确认清理" if residual else None
133
+ for child in owner.get("children", []):
134
+ pid = child.get("pid")
135
+ if isinstance(pid, int) and pool.group_alive(pid):
136
+ resource["details"]["processes"].append({"name": child.get("program", "Runner"), "pid": pid,
137
+ "ownership": "owned" if child.get("startIdentity") and pool.identity(pid) == child["startIdentity"] else "unknown",
138
+ "cpuPercent": None, "rssBytes": None})
139
+ allowed = not active and not unresolved and tool_ready
140
+ try:
141
+ lease = safe_read(Path(owner["taskDir"]) / "simulator-lease.json")
142
+ if owner_version(lease) != version:
143
+ raise ValueError("任务资料与当前占用不一致")
144
+ pool.task(owner["taskDir"], allow_finished=True)
145
+ except (OSError, ValueError, pool.PoolError):
146
+ allowed = False
147
+ reason = "任务目录或 lease 无法核实,请检查占用资料"
148
+ if owner_version(safe_read(lock / "owner.json")) != version:
149
+ raise ValueError("读取期间占用者变化")
150
+ resource["reason"] = reason
151
+ resource["release"] = {"action": ("release-occupancy" if residual else "stop-and-release") if allowed else None,
152
+ "disabledReason": None if allowed else reason or ("自动化操作仍在运行,请稍后手动刷新" if active else "清理需要 agent-device 0.21.3")}
153
+ except (OSError, ValueError, pool.PoolError) as error:
154
+ resource["state"] = "unknown"
155
+ resource["reason"] = str(error)
156
+ resource["owner"] = None
157
+ resource["ownershipVersion"] = None
158
+ resource["details"]["path"] = None
159
+ resource["details"]["processes"] = []
160
+ resource["release"] = {"action": None, "disabledReason": resource["reason"]}
161
+ resources.append(resource)
162
+ counts = {"total": len(resources), "busy": 0, "free": 0, "blocked": 0, "unknown": 0}
163
+ for resource in resources:
164
+ counts[resource["state"]] += 1
165
+ return {"sourceState": "partial" if failures or counts["unknown"] else "ready", "reason": ";".join(sorted(set(failures))) or None,
166
+ "resources": resources, "counts": counts}
167
+
168
+
169
+ def release(request):
170
+ resource = next((item for item in projection()["resources"] if item["id"] == request["resourceId"]), None)
171
+ if not resource:
172
+ pool.fail("resource_missing", "资源不存在")
173
+ # The Node side validates its Backend generation; Python validates the lease under its UDID guard.
174
+ expected = resource["ownershipVersion"]
175
+ bound = hashlib.sha256(json.dumps([request["generation"], expected], separators=(",", ":")).encode()).hexdigest()
176
+ if bound != request["expectedOwnershipVersion"]:
177
+ pool.fail("owner_changed", "占用者已变化,请刷新后重新确认")
178
+ if resource["ownershipVersion"] != expected or resource["release"]["action"] != request["action"]:
179
+ pool.fail("owner_changed", "占用或清理条件已变化,请刷新后重新确认")
180
+ root = resource["details"]["path"]
181
+
182
+ def verify(owner):
183
+ current = safe_read(pool.udid_path(owner["udid"]) / "owner.json")
184
+ if owner_version(current) != expected or owner_version(owner) != expected:
185
+ pool.fail("owner_changed", "占用者已变化,未执行释放")
186
+ if pool.active_operation(current) or pool.unsettled(current):
187
+ pool.fail("cleanup_incomplete", "自动化操作或子进程仍在运行")
188
+ if owner_version(safe_read(Path(root) / "simulator-lease.json")) != expected:
189
+ pool.fail("owner_changed", "任务 lease 已变化")
190
+
191
+ pool.finish(root, recovering=request["action"] == "release-occupancy", verify_owner=verify)
192
+ if pool.udid_path(resource["details"]["udid"]).exists():
193
+ pool.fail("cleanup_incomplete", "owner lock 仍存在,释放尚未确认")
194
+ return {"state": "released", "message": "模拟器任务已停止并释放"}
195
+
196
+
197
+ if __name__ == "__main__":
198
+ try:
199
+ result = release(json.load(sys.stdin)) if sys.argv[1:] == ["release"] else projection()
200
+ print(json.dumps(result, ensure_ascii=False))
201
+ except Exception as error:
202
+ print(json.dumps({"state": "blocked", "message": str(error),
203
+ "status": 409 if isinstance(error, pool.PoolError) and error.code == "owner_changed" else 200}, ensure_ascii=False))
204
+ sys.exit(1)