harnery 0.40.0 → 0.42.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 (595) hide show
  1. package/README.md +1 -1
  2. package/dist/commander.js +4 -0
  3. package/dist/commands/agents.d.ts.map +1 -1
  4. package/dist/commands/agents.js +34 -20
  5. package/dist/commands/artifacts.d.ts.map +1 -1
  6. package/dist/commands/artifacts.js +113 -12
  7. package/dist/commands/browse-ai.d.ts.map +1 -1
  8. package/dist/commands/browse-ai.js +4 -0
  9. package/dist/commands/browse.d.ts +164 -0
  10. package/dist/commands/browse.d.ts.map +1 -1
  11. package/dist/commands/browse.js +388 -45
  12. package/dist/commands/checkpoint.js +8 -12
  13. package/dist/commands/claude-desktop.d.ts.map +1 -1
  14. package/dist/commands/claude-desktop.js +52 -0
  15. package/dist/commands/deinit.d.ts +1 -1
  16. package/dist/commands/deinit.d.ts.map +1 -1
  17. package/dist/commands/deinit.js +8 -4
  18. package/dist/commands/disk.d.ts +6 -0
  19. package/dist/commands/disk.d.ts.map +1 -0
  20. package/dist/commands/disk.js +80 -0
  21. package/dist/commands/docs.d.ts.map +1 -1
  22. package/dist/commands/docs.js +2 -0
  23. package/dist/commands/doctor.d.ts +8 -0
  24. package/dist/commands/doctor.d.ts.map +1 -1
  25. package/dist/commands/doctor.js +58 -3
  26. package/dist/commands/fetch.d.ts.map +1 -1
  27. package/dist/commands/fetch.js +10 -0
  28. package/dist/commands/files.d.ts +16 -0
  29. package/dist/commands/files.d.ts.map +1 -1
  30. package/dist/commands/files.js +54 -2
  31. package/dist/commands/init.d.ts +21 -5
  32. package/dist/commands/init.d.ts.map +1 -1
  33. package/dist/commands/init.js +271 -109
  34. package/dist/commands/instructions.js +5 -4
  35. package/dist/commands/ledger-v3.d.ts.map +1 -1
  36. package/dist/commands/ledger-v3.js +2 -1
  37. package/dist/commands/rm.d.ts +4 -0
  38. package/dist/commands/rm.d.ts.map +1 -0
  39. package/dist/commands/rm.js +87 -0
  40. package/dist/commands/servers.d.ts +7 -0
  41. package/dist/commands/servers.d.ts.map +1 -0
  42. package/dist/commands/servers.js +394 -0
  43. package/dist/commands/tunnel.d.ts.map +1 -1
  44. package/dist/commands/tunnel.js +82 -2
  45. package/dist/commands/webview.d.ts +4 -0
  46. package/dist/commands/webview.d.ts.map +1 -0
  47. package/dist/commands/webview.js +94 -0
  48. package/dist/core/adapter.d.ts +50 -1
  49. package/dist/core/adapter.d.ts.map +1 -1
  50. package/dist/core/adapter.js +59 -1
  51. package/dist/core/adapters/attestation.d.ts.map +1 -1
  52. package/dist/core/adapters/attestation.js +3 -2
  53. package/dist/core/adapters/profiles.d.ts +29 -3
  54. package/dist/core/adapters/profiles.d.ts.map +1 -1
  55. package/dist/core/adapters/profiles.js +53 -1
  56. package/dist/core/adapters/registry.d.ts.map +1 -1
  57. package/dist/core/adapters/registry.js +33 -0
  58. package/dist/core/adapters/types.d.ts +9 -0
  59. package/dist/core/adapters/types.d.ts.map +1 -1
  60. package/dist/core/agents/canonical-emit.d.ts +1 -1
  61. package/dist/core/agents/canonical-emit.d.ts.map +1 -1
  62. package/dist/core/agents/canonical-emit.js +2 -7
  63. package/dist/core/agents/cli.js +25 -16
  64. package/dist/core/agents/coord-client.d.ts.map +1 -1
  65. package/dist/core/agents/coord-client.js +7 -2
  66. package/dist/core/agents/render/session-context.d.ts.map +1 -1
  67. package/dist/core/agents/render/session-context.js +2 -0
  68. package/dist/core/agents/rules/claim-conflict.d.ts.map +1 -1
  69. package/dist/core/agents/rules/claim-conflict.js +3 -9
  70. package/dist/core/agents/rules/commit-conflict.d.ts.map +1 -1
  71. package/dist/core/agents/rules/commit-conflict.js +2 -8
  72. package/dist/core/agents/rules/stop-hook.d.ts +2 -0
  73. package/dist/core/agents/rules/stop-hook.d.ts.map +1 -1
  74. package/dist/core/agents/rules/stop-hook.js +1 -1
  75. package/dist/core/agents/session-events.d.ts +6 -2
  76. package/dist/core/agents/session-events.d.ts.map +1 -1
  77. package/dist/core/agents/session-events.js +105 -26
  78. package/dist/core/agents/session-finalization-state-v3.d.ts.map +1 -1
  79. package/dist/core/agents/session-finalization-state-v3.js +2 -1
  80. package/dist/core/agents/session-finalizer-v3.d.ts.map +1 -1
  81. package/dist/core/agents/session-finalizer-v3.js +5 -4
  82. package/dist/core/agents/session-name-display.d.ts +28 -0
  83. package/dist/core/agents/session-name-display.d.ts.map +1 -1
  84. package/dist/core/agents/session-name-display.js +43 -0
  85. package/dist/core/agents/state/heartbeat-reader.d.ts +7 -0
  86. package/dist/core/agents/state/heartbeat-reader.d.ts.map +1 -1
  87. package/dist/core/agents/state/heartbeat-writer.d.ts +10 -0
  88. package/dist/core/agents/state/heartbeat-writer.d.ts.map +1 -1
  89. package/dist/core/agents/state/heartbeat-writer.js +21 -2
  90. package/dist/core/agents/state/live-coordination-view.d.ts +20 -0
  91. package/dist/core/agents/state/live-coordination-view.d.ts.map +1 -1
  92. package/dist/core/agents/state/live-coordination-view.js +61 -0
  93. package/dist/core/agents/state/live-coordination-writer.js +3 -0
  94. package/dist/core/agents/state/stale-sweep.d.ts.map +1 -1
  95. package/dist/core/agents/state/stale-sweep.js +2 -10
  96. package/dist/core/agents/turn-changes.d.ts +17 -0
  97. package/dist/core/agents/turn-changes.d.ts.map +1 -0
  98. package/dist/core/agents/turn-changes.js +76 -0
  99. package/dist/core/artifacts/delivery-card.d.ts.map +1 -1
  100. package/dist/core/artifacts/delivery-card.js +11 -3
  101. package/dist/core/artifacts/index.d.ts +140 -4
  102. package/dist/core/artifacts/index.d.ts.map +1 -1
  103. package/dist/core/artifacts/index.js +526 -52
  104. package/dist/core/config.d.ts +73 -11
  105. package/dist/core/config.d.ts.map +1 -1
  106. package/dist/core/config.js +142 -3
  107. package/dist/core/context/index.d.ts.map +1 -1
  108. package/dist/core/context/index.js +2 -1
  109. package/dist/core/conversations/archive.d.ts.map +1 -1
  110. package/dist/core/conversations/archive.js +4 -3
  111. package/dist/core/diagnostics/bundle.d.ts.map +1 -1
  112. package/dist/core/diagnostics/bundle.js +5 -4
  113. package/dist/core/events/legacy-storage/canary.d.ts.map +1 -1
  114. package/dist/core/events/legacy-storage/canary.js +5 -4
  115. package/dist/core/events/legacy-storage/compression.d.ts.map +1 -1
  116. package/dist/core/events/legacy-storage/compression.js +2 -1
  117. package/dist/core/events/v3/adapter-id.d.ts +10 -2
  118. package/dist/core/events/v3/adapter-id.d.ts.map +1 -1
  119. package/dist/core/events/v3/adapter-id.js +16 -0
  120. package/dist/core/events/v3/authority-outbox.d.ts.map +1 -1
  121. package/dist/core/events/v3/authority-outbox.js +2 -1
  122. package/dist/core/events/v3/bootstrap.d.ts.map +1 -1
  123. package/dist/core/events/v3/bootstrap.js +5 -4
  124. package/dist/core/events/v3/capabilities.d.ts.map +1 -1
  125. package/dist/core/events/v3/capabilities.js +17 -0
  126. package/dist/core/events/v3/contract.d.ts +5 -0
  127. package/dist/core/events/v3/contract.d.ts.map +1 -1
  128. package/dist/core/events/v3/contract.js +7 -1
  129. package/dist/core/events/v3/control-witness.d.ts.map +1 -1
  130. package/dist/core/events/v3/control-witness.js +3 -2
  131. package/dist/core/events/v3/coordination-transaction-recovery.d.ts.map +1 -1
  132. package/dist/core/events/v3/coordination-transaction-recovery.js +4 -3
  133. package/dist/core/events/v3/fingerprint-keys.d.ts.map +1 -1
  134. package/dist/core/events/v3/fingerprint-keys.js +7 -6
  135. package/dist/core/events/v3/generated.d.ts +1 -1
  136. package/dist/core/events/v3/generated.js +1 -1
  137. package/dist/core/events/v3/live-feed.d.ts.map +1 -1
  138. package/dist/core/events/v3/live-feed.js +5 -4
  139. package/dist/core/events/v3/producers/command-recorder.d.ts.map +1 -1
  140. package/dist/core/events/v3/producers/command-recorder.js +8 -7
  141. package/dist/core/events/v3/producers/coordination-recorder.d.ts.map +1 -1
  142. package/dist/core/events/v3/producers/coordination-recorder.js +8 -7
  143. package/dist/core/events/v3/producers/diagnostic-summaries.d.ts.map +1 -1
  144. package/dist/core/events/v3/producers/diagnostic-summaries.js +5 -4
  145. package/dist/core/events/v3/producers/hook-base.d.ts +1 -0
  146. package/dist/core/events/v3/producers/hook-base.d.ts.map +1 -1
  147. package/dist/core/events/v3/producers/hook-base.js +10 -4
  148. package/dist/core/events/v3/producers/hook.d.ts +2 -0
  149. package/dist/core/events/v3/producers/hook.d.ts.map +1 -1
  150. package/dist/core/events/v3/producers/hook.js +16 -1
  151. package/dist/core/events/v3/producers/intake.d.ts.map +1 -1
  152. package/dist/core/events/v3/producers/intake.js +16 -6
  153. package/dist/core/events/v3/producers/recorder.d.ts +2 -4
  154. package/dist/core/events/v3/producers/recorder.d.ts.map +1 -1
  155. package/dist/core/events/v3/producers/recorder.js +125 -101
  156. package/dist/core/events/v3/projection.js +9 -1
  157. package/dist/core/events/v3/recovery.d.ts.map +1 -1
  158. package/dist/core/events/v3/recovery.js +4 -3
  159. package/dist/core/events/v3/support-storage/inventory.d.ts.map +1 -1
  160. package/dist/core/events/v3/support-storage/inventory.js +2 -1
  161. package/dist/core/events/v3/support-storage/maintenance.d.ts.map +1 -1
  162. package/dist/core/events/v3/support-storage/maintenance.js +4 -3
  163. package/dist/core/events/v3/support-storage/pack-reader.d.ts.map +1 -1
  164. package/dist/core/events/v3/support-storage/pack-reader.js +4 -3
  165. package/dist/core/events/v3/support-storage/pack-writer.d.ts.map +1 -1
  166. package/dist/core/events/v3/support-storage/pack-writer.js +6 -5
  167. package/dist/core/events/v3/tool-line-changes.d.ts +8 -0
  168. package/dist/core/events/v3/tool-line-changes.d.ts.map +1 -0
  169. package/dist/core/events/v3/tool-line-changes.js +135 -0
  170. package/dist/core/events/v3/writer.d.ts.map +1 -1
  171. package/dist/core/events/v3/writer.js +8 -7
  172. package/dist/core/governor/planning.d.ts.map +1 -1
  173. package/dist/core/governor/planning.js +6 -5
  174. package/dist/core/governor/service.d.ts.map +1 -1
  175. package/dist/core/governor/service.js +12 -11
  176. package/dist/core/governor/state.d.ts.map +1 -1
  177. package/dist/core/governor/state.js +7 -6
  178. package/dist/core/guard/evaluator.js +1 -0
  179. package/dist/core/guard/storage.d.ts.map +1 -1
  180. package/dist/core/guard/storage.js +3 -2
  181. package/dist/core/hooks/adapter/behaviors/claude-code.d.ts +4 -0
  182. package/dist/core/hooks/adapter/behaviors/claude-code.d.ts.map +1 -0
  183. package/dist/core/hooks/adapter/behaviors/claude-code.js +31 -0
  184. package/dist/core/hooks/adapter/behaviors/codex.d.ts +15 -0
  185. package/dist/core/hooks/adapter/behaviors/codex.d.ts.map +1 -0
  186. package/dist/core/hooks/adapter/behaviors/codex.js +82 -0
  187. package/dist/core/hooks/adapter/behaviors/cursor.d.ts +7 -0
  188. package/dist/core/hooks/adapter/behaviors/cursor.d.ts.map +1 -0
  189. package/dist/core/hooks/adapter/behaviors/cursor.js +35 -0
  190. package/dist/core/hooks/adapter/behaviors/index.d.ts +11 -0
  191. package/dist/core/hooks/adapter/behaviors/index.d.ts.map +1 -0
  192. package/dist/core/hooks/adapter/behaviors/index.js +20 -0
  193. package/dist/core/hooks/adapter/behaviors/openclaw.d.ts +7 -0
  194. package/dist/core/hooks/adapter/behaviors/openclaw.d.ts.map +1 -0
  195. package/dist/core/hooks/adapter/behaviors/openclaw.js +34 -0
  196. package/dist/core/hooks/adapter/behaviors/opencode.d.ts +7 -0
  197. package/dist/core/hooks/adapter/behaviors/opencode.d.ts.map +1 -0
  198. package/dist/core/hooks/adapter/behaviors/opencode.js +34 -0
  199. package/dist/core/hooks/adapter/behaviors/types.d.ts +89 -0
  200. package/dist/core/hooks/adapter/behaviors/types.d.ts.map +1 -0
  201. package/dist/core/hooks/adapter/behaviors/types.js +1 -0
  202. package/dist/core/hooks/adapter/detect.d.ts +1 -1
  203. package/dist/core/hooks/adapter/detect.d.ts.map +1 -1
  204. package/dist/core/hooks/adapter/detect.js +2 -3
  205. package/dist/core/hooks/adapter/events.d.ts +46 -1
  206. package/dist/core/hooks/adapter/events.d.ts.map +1 -1
  207. package/dist/core/hooks/adapter/events.js +36 -0
  208. package/dist/core/hooks/adapter/opencode-plugin.d.ts +60 -0
  209. package/dist/core/hooks/adapter/opencode-plugin.d.ts.map +1 -0
  210. package/dist/core/hooks/adapter/opencode-plugin.js +129 -0
  211. package/dist/core/hooks/adapter/output.d.ts +7 -0
  212. package/dist/core/hooks/adapter/output.d.ts.map +1 -1
  213. package/dist/core/hooks/adapter/output.js +8 -1
  214. package/dist/core/hooks/adapter/runtime-telemetry.js +3 -1
  215. package/dist/core/hooks/adapter/wiring.d.ts +52 -8
  216. package/dist/core/hooks/adapter/wiring.d.ts.map +1 -1
  217. package/dist/core/hooks/adapter/wiring.js +133 -12
  218. package/dist/core/hooks/cli.js +676 -531
  219. package/dist/core/hooks/effects/image-capture.d.ts.map +1 -1
  220. package/dist/core/hooks/effects/image-capture.js +2 -1
  221. package/dist/core/hooks/prompt-context/contract.d.ts.map +1 -1
  222. package/dist/core/hooks/prompt-context/contract.js +1 -0
  223. package/dist/core/hooks/resolve/transcript.d.ts +1 -1
  224. package/dist/core/hooks/resolve/transcript.d.ts.map +1 -1
  225. package/dist/core/hooks/resolve/transcript.js +35 -4
  226. package/dist/core/hooks/run-markers.d.ts +37 -0
  227. package/dist/core/hooks/run-markers.d.ts.map +1 -0
  228. package/dist/core/hooks/run-markers.js +109 -0
  229. package/dist/core/hooks/session-name-presence.d.ts +3 -1
  230. package/dist/core/hooks/session-name-presence.d.ts.map +1 -1
  231. package/dist/core/hooks/session-name-presence.js +7 -2
  232. package/dist/core/hooks/shell-waiter.d.ts +2 -0
  233. package/dist/core/hooks/shell-waiter.d.ts.map +1 -0
  234. package/dist/core/hooks/shell-waiter.js +173 -0
  235. package/dist/core/resources/service.d.ts.map +1 -1
  236. package/dist/core/resources/service.js +5 -4
  237. package/dist/core/semantic/review.d.ts.map +1 -1
  238. package/dist/core/semantic/review.js +5 -4
  239. package/dist/core/semantic/service.d.ts.map +1 -1
  240. package/dist/core/semantic/service.js +15 -14
  241. package/dist/core/semantic/storage.d.ts.map +1 -1
  242. package/dist/core/semantic/storage.js +5 -4
  243. package/dist/core/servers/index.d.ts +211 -0
  244. package/dist/core/servers/index.d.ts.map +1 -0
  245. package/dist/core/servers/index.js +560 -0
  246. package/dist/core/servers/net.d.ts +58 -0
  247. package/dist/core/servers/net.d.ts.map +1 -0
  248. package/dist/core/servers/net.js +270 -0
  249. package/dist/core/servers/tunnels.d.ts +14 -0
  250. package/dist/core/servers/tunnels.d.ts.map +1 -0
  251. package/dist/core/servers/tunnels.js +33 -0
  252. package/dist/core/storage/atomic-json.d.ts.map +1 -1
  253. package/dist/core/storage/atomic-json.js +7 -3
  254. package/dist/core/storage/builtins.js +1 -0
  255. package/dist/core/storage/durable-history.d.ts.map +1 -1
  256. package/dist/core/storage/durable-history.js +6 -5
  257. package/dist/core/storage/maintenance-providers.d.ts.map +1 -1
  258. package/dist/core/storage/maintenance-providers.js +2 -1
  259. package/dist/core/storage/maintenance.d.ts.map +1 -1
  260. package/dist/core/storage/maintenance.js +7 -6
  261. package/dist/core/storage/metrics.d.ts.map +1 -1
  262. package/dist/core/storage/metrics.js +5 -1
  263. package/dist/core/storage/modes.d.ts +17 -0
  264. package/dist/core/storage/modes.d.ts.map +1 -0
  265. package/dist/core/storage/modes.js +47 -0
  266. package/dist/core/storage/process-log.d.ts.map +1 -1
  267. package/dist/core/storage/process-log.js +3 -2
  268. package/dist/core/storage/receipts.d.ts.map +1 -1
  269. package/dist/core/storage/receipts.js +4 -3
  270. package/dist/core/storage/segments.d.ts.map +1 -1
  271. package/dist/core/storage/segments.js +7 -6
  272. package/dist/core/supervisor/hook-health.d.ts +2 -1
  273. package/dist/core/supervisor/hook-health.d.ts.map +1 -1
  274. package/dist/core/supervisor/hook-health.js +4 -3
  275. package/dist/core/supervisor/service.d.ts.map +1 -1
  276. package/dist/core/supervisor/service.js +7 -6
  277. package/dist/core/work/state.d.ts.map +1 -1
  278. package/dist/core/work/state.js +8 -7
  279. package/dist/core/workflow/adapters.d.ts +7 -0
  280. package/dist/core/workflow/adapters.d.ts.map +1 -1
  281. package/dist/core/workflow/adapters.js +9 -0
  282. package/dist/core/workflow/approvals.d.ts.map +1 -1
  283. package/dist/core/workflow/approvals.js +6 -5
  284. package/dist/core/workflow/billing.d.ts.map +1 -1
  285. package/dist/core/workflow/billing.js +33 -4
  286. package/dist/core/workflow/durable-record.d.ts.map +1 -1
  287. package/dist/core/workflow/durable-record.js +4 -3
  288. package/dist/core/workflow/engine.d.ts.map +1 -1
  289. package/dist/core/workflow/engine.js +30 -1
  290. package/dist/core/workflow/live-session-v3.d.ts.map +1 -1
  291. package/dist/core/workflow/live-session-v3.js +2 -3
  292. package/dist/core/workflow/run-state.d.ts.map +1 -1
  293. package/dist/core/workflow/run-state.js +3 -2
  294. package/dist/core/workflow/sandbox-projection.d.ts +13 -2
  295. package/dist/core/workflow/sandbox-projection.d.ts.map +1 -1
  296. package/dist/core/workflow/sandbox-projection.js +23 -0
  297. package/dist/core/workflow/spawn-claude.d.ts.map +1 -1
  298. package/dist/core/workflow/spawn-claude.js +6 -1
  299. package/dist/core/workflow/spawn-codex.d.ts +2 -0
  300. package/dist/core/workflow/spawn-codex.d.ts.map +1 -1
  301. package/dist/core/workflow/spawn-codex.js +20 -1
  302. package/dist/core/workflow/spawn-cursor.d.ts.map +1 -1
  303. package/dist/core/workflow/spawn-cursor.js +6 -1
  304. package/dist/core/workflow/spawn-opencode.d.ts +36 -0
  305. package/dist/core/workflow/spawn-opencode.d.ts.map +1 -0
  306. package/dist/core/workflow/spawn-opencode.js +135 -0
  307. package/dist/core/workflow/transcript.d.ts.map +1 -1
  308. package/dist/core/workflow/transcript.js +3 -2
  309. package/dist/core/workflow/types.d.ts +47 -2
  310. package/dist/core/workflow/types.d.ts.map +1 -1
  311. package/dist/core/workflow/worker-access.d.ts +92 -0
  312. package/dist/core/workflow/worker-access.d.ts.map +1 -0
  313. package/dist/core/workflow/worker-access.js +450 -0
  314. package/dist/core/workflow/workspaces/leases.d.ts.map +1 -1
  315. package/dist/core/workflow/workspaces/leases.js +5 -4
  316. package/dist/core/workflow/workspaces/local-git.d.ts.map +1 -1
  317. package/dist/core/workflow/workspaces/local-git.js +3 -2
  318. package/dist/core/workflow/workspaces/paths.d.ts.map +1 -1
  319. package/dist/core/workflow/workspaces/paths.js +2 -1
  320. package/dist/core/workflow/workspaces/state.d.ts.map +1 -1
  321. package/dist/core/workflow/workspaces/state.js +10 -9
  322. package/dist/lazy-commands.js +8 -1
  323. package/dist/lib/agent-browser/client.d.ts +9 -0
  324. package/dist/lib/agent-browser/client.d.ts.map +1 -1
  325. package/dist/lib/agent-browser/client.js +13 -0
  326. package/dist/lib/browser/batch-steps.d.ts +18 -0
  327. package/dist/lib/browser/batch-steps.d.ts.map +1 -0
  328. package/dist/lib/browser/batch-steps.js +82 -0
  329. package/dist/lib/browser/client.d.ts +35 -1
  330. package/dist/lib/browser/client.d.ts.map +1 -1
  331. package/dist/lib/browser/client.js +117 -8
  332. package/dist/lib/browser/collect/collector.d.ts +99 -0
  333. package/dist/lib/browser/collect/collector.d.ts.map +1 -0
  334. package/dist/lib/browser/collect/collector.js +202 -0
  335. package/dist/lib/browser/collect/fields.d.ts +31 -0
  336. package/dist/lib/browser/collect/fields.d.ts.map +1 -0
  337. package/dist/lib/browser/collect/fields.js +75 -0
  338. package/dist/lib/browser/collect/index.d.ts +6 -0
  339. package/dist/lib/browser/collect/index.d.ts.map +1 -0
  340. package/dist/lib/browser/collect/index.js +5 -0
  341. package/dist/lib/browser/collect/page-driver.d.ts +14 -0
  342. package/dist/lib/browser/collect/page-driver.d.ts.map +1 -0
  343. package/dist/lib/browser/collect/page-driver.js +306 -0
  344. package/dist/lib/browser/collect/presets.d.ts +52 -0
  345. package/dist/lib/browser/collect/presets.d.ts.map +1 -0
  346. package/dist/lib/browser/collect/presets.js +176 -0
  347. package/dist/lib/browser/collect/scroll-plan.d.ts +85 -0
  348. package/dist/lib/browser/collect/scroll-plan.d.ts.map +1 -0
  349. package/dist/lib/browser/collect/scroll-plan.js +118 -0
  350. package/dist/lib/browser/identity.d.ts +25 -0
  351. package/dist/lib/browser/identity.d.ts.map +1 -0
  352. package/dist/lib/browser/identity.js +66 -0
  353. package/dist/lib/browser/index.d.ts +3 -2
  354. package/dist/lib/browser/index.d.ts.map +1 -1
  355. package/dist/lib/browser/index.js +2 -1
  356. package/dist/lib/browser/launch-args.d.ts +26 -0
  357. package/dist/lib/browser/launch-args.d.ts.map +1 -1
  358. package/dist/lib/browser/launch-args.js +41 -1
  359. package/dist/lib/browser/page-review-judge.d.ts +2 -0
  360. package/dist/lib/browser/page-review-judge.d.ts.map +1 -1
  361. package/dist/lib/browser/page-review-judge.js +13 -0
  362. package/dist/lib/browser/qa-run-contracts.d.ts +10 -0
  363. package/dist/lib/browser/qa-run-contracts.d.ts.map +1 -1
  364. package/dist/lib/browser/qa-run.d.ts.map +1 -1
  365. package/dist/lib/browser/qa-run.js +1 -0
  366. package/dist/lib/browser/user-agent.d.ts +53 -0
  367. package/dist/lib/browser/user-agent.d.ts.map +1 -0
  368. package/dist/lib/browser/user-agent.js +79 -0
  369. package/dist/lib/browser/windows-chrome.d.ts +59 -0
  370. package/dist/lib/browser/windows-chrome.d.ts.map +1 -0
  371. package/dist/lib/browser/windows-chrome.js +179 -0
  372. package/dist/lib/claude-desktop-share.d.ts +136 -0
  373. package/dist/lib/claude-desktop-share.d.ts.map +1 -0
  374. package/dist/lib/claude-desktop-share.js +394 -0
  375. package/dist/lib/disk-usage.d.ts +50 -0
  376. package/dist/lib/disk-usage.d.ts.map +1 -0
  377. package/dist/lib/disk-usage.js +303 -0
  378. package/dist/lib/docs-lint.d.ts +6 -0
  379. package/dist/lib/docs-lint.d.ts.map +1 -1
  380. package/dist/lib/docs-lint.js +8 -3
  381. package/dist/lib/docs-metadata-managed.d.ts +1 -0
  382. package/dist/lib/docs-metadata-managed.d.ts.map +1 -1
  383. package/dist/lib/docs-metadata-managed.js +17 -1
  384. package/dist/lib/guarded-remove.d.ts +34 -0
  385. package/dist/lib/guarded-remove.d.ts.map +1 -0
  386. package/dist/lib/guarded-remove.js +310 -0
  387. package/dist/lib/identities/assume.d.ts.map +1 -1
  388. package/dist/lib/identities/assume.js +4 -9
  389. package/dist/lib/instructions/apply.d.ts.map +1 -1
  390. package/dist/lib/instructions/apply.js +2 -0
  391. package/dist/lib/instructions/templates.js +8 -8
  392. package/dist/lib/pace/index.d.ts +2 -0
  393. package/dist/lib/pace/index.d.ts.map +1 -0
  394. package/dist/lib/pace/index.js +1 -0
  395. package/dist/lib/pace/pace.d.ts +95 -0
  396. package/dist/lib/pace/pace.d.ts.map +1 -0
  397. package/dist/lib/pace/pace.js +313 -0
  398. package/dist/lib/tunnel/error-page.d.ts +1 -1
  399. package/dist/lib/tunnel/error-page.d.ts.map +1 -1
  400. package/dist/lib/tunnel/error-page.js +19 -8
  401. package/dist/lib/tunnel/forward-headers.d.ts +11 -0
  402. package/dist/lib/tunnel/forward-headers.d.ts.map +1 -0
  403. package/dist/lib/tunnel/forward-headers.js +17 -0
  404. package/dist/lib/tunnel/gate.js +34 -10
  405. package/dist/lib/tunnel/path-scope.d.ts +22 -0
  406. package/dist/lib/tunnel/path-scope.d.ts.map +1 -0
  407. package/dist/lib/tunnel/path-scope.js +62 -0
  408. package/dist/lib/tunnel/state.d.ts +5 -0
  409. package/dist/lib/tunnel/state.d.ts.map +1 -1
  410. package/dist/lib/tunnel/state.js +17 -3
  411. package/dist/lib/webview/index.d.ts +2 -0
  412. package/dist/lib/webview/index.d.ts.map +1 -0
  413. package/dist/lib/webview/index.js +1 -0
  414. package/dist/lib/webview/webview.d.ts +116 -0
  415. package/dist/lib/webview/webview.d.ts.map +1 -0
  416. package/dist/lib/webview/webview.js +289 -0
  417. package/opencode-plugin/package.json +19 -0
  418. package/opencode-plugin/src/index.ts +791 -0
  419. package/package.json +16 -4
  420. package/schemas/config.schema.json +104 -0
  421. package/schemas/event-v3.schema.json +164 -0
  422. package/src/commander.ts +26 -0
  423. package/src/commands/agents.ts +47 -18
  424. package/src/commands/artifacts.ts +171 -19
  425. package/src/commands/browse-ai.ts +8 -0
  426. package/src/commands/browse.ts +570 -48
  427. package/src/commands/checkpoint.ts +7 -9
  428. package/src/commands/claude-desktop.ts +61 -0
  429. package/src/commands/deinit.ts +9 -4
  430. package/src/commands/disk.ts +114 -0
  431. package/src/commands/docs.ts +2 -0
  432. package/src/commands/doctor.ts +63 -3
  433. package/src/commands/fetch.ts +14 -0
  434. package/src/commands/files.ts +93 -2
  435. package/src/commands/init.ts +334 -122
  436. package/src/commands/instructions.ts +8 -4
  437. package/src/commands/ledger-v3.ts +2 -1
  438. package/src/commands/rm.ts +115 -0
  439. package/src/commands/servers.ts +506 -0
  440. package/src/commands/tunnel.ts +102 -2
  441. package/src/commands/webview.ts +159 -0
  442. package/src/core/adapter.ts +102 -1
  443. package/src/core/adapters/attestation.ts +3 -2
  444. package/src/core/adapters/profiles.ts +63 -1
  445. package/src/core/adapters/registry.ts +37 -0
  446. package/src/core/adapters/types.ts +10 -0
  447. package/src/core/agents/canonical-emit.ts +2 -5
  448. package/src/core/agents/cli.ts +26 -17
  449. package/src/core/agents/coord-client.ts +9 -3
  450. package/src/core/agents/render/session-context.ts +1 -0
  451. package/src/core/agents/rules/claim-conflict.ts +3 -8
  452. package/src/core/agents/rules/commit-conflict.ts +2 -7
  453. package/src/core/agents/rules/stop-hook.ts +3 -1
  454. package/src/core/agents/session-events.ts +120 -26
  455. package/src/core/agents/session-finalization-state-v3.ts +2 -1
  456. package/src/core/agents/session-finalizer-v3.ts +5 -4
  457. package/src/core/agents/session-name-display.ts +48 -0
  458. package/src/core/agents/state/heartbeat-reader.ts +7 -0
  459. package/src/core/agents/state/heartbeat-writer.ts +24 -2
  460. package/src/core/agents/state/live-coordination-view.ts +74 -0
  461. package/src/core/agents/state/live-coordination-writer.ts +3 -0
  462. package/src/core/agents/state/stale-sweep.ts +2 -9
  463. package/src/core/agents/turn-changes.ts +97 -0
  464. package/src/core/artifacts/delivery-card.ts +12 -3
  465. package/src/core/artifacts/index.ts +701 -47
  466. package/src/core/config.ts +206 -4
  467. package/src/core/context/index.ts +2 -1
  468. package/src/core/conversations/archive.ts +4 -3
  469. package/src/core/diagnostics/bundle.ts +5 -3
  470. package/src/core/events/legacy-storage/canary.ts +5 -4
  471. package/src/core/events/legacy-storage/compression.ts +2 -1
  472. package/src/core/events/v3/adapter-id.ts +29 -1
  473. package/src/core/events/v3/authority-outbox.ts +2 -1
  474. package/src/core/events/v3/bootstrap.ts +5 -4
  475. package/src/core/events/v3/capabilities.ts +17 -0
  476. package/src/core/events/v3/contract.ts +9 -1
  477. package/src/core/events/v3/control-witness.ts +3 -2
  478. package/src/core/events/v3/coordination-transaction-recovery.ts +4 -3
  479. package/src/core/events/v3/fingerprint-keys.ts +7 -6
  480. package/src/core/events/v3/generated.ts +1 -1
  481. package/src/core/events/v3/live-feed.ts +5 -4
  482. package/src/core/events/v3/producers/command-recorder.ts +8 -6
  483. package/src/core/events/v3/producers/coordination-recorder.ts +8 -7
  484. package/src/core/events/v3/producers/diagnostic-summaries.ts +5 -4
  485. package/src/core/events/v3/producers/hook-base.ts +11 -4
  486. package/src/core/events/v3/producers/hook.ts +19 -1
  487. package/src/core/events/v3/producers/intake.ts +18 -6
  488. package/src/core/events/v3/producers/recorder.ts +139 -114
  489. package/src/core/events/v3/projection.ts +11 -1
  490. package/src/core/events/v3/recovery.ts +4 -3
  491. package/src/core/events/v3/support-storage/inventory.ts +2 -1
  492. package/src/core/events/v3/support-storage/maintenance.ts +8 -3
  493. package/src/core/events/v3/support-storage/pack-reader.ts +4 -3
  494. package/src/core/events/v3/support-storage/pack-writer.ts +6 -5
  495. package/src/core/events/v3/tool-line-changes.ts +139 -0
  496. package/src/core/events/v3/writer.ts +8 -7
  497. package/src/core/governor/planning.ts +6 -5
  498. package/src/core/governor/service.ts +12 -11
  499. package/src/core/governor/state.ts +7 -6
  500. package/src/core/guard/evaluator.ts +1 -0
  501. package/src/core/guard/storage.ts +3 -2
  502. package/src/core/hooks/adapter/behaviors/claude-code.ts +33 -0
  503. package/src/core/hooks/adapter/behaviors/codex.ts +96 -0
  504. package/src/core/hooks/adapter/behaviors/cursor.ts +37 -0
  505. package/src/core/hooks/adapter/behaviors/index.ts +31 -0
  506. package/src/core/hooks/adapter/behaviors/openclaw.ts +36 -0
  507. package/src/core/hooks/adapter/behaviors/opencode.ts +36 -0
  508. package/src/core/hooks/adapter/behaviors/types.ts +110 -0
  509. package/src/core/hooks/adapter/detect.ts +2 -3
  510. package/src/core/hooks/adapter/events.ts +72 -1
  511. package/src/core/hooks/adapter/opencode-plugin.ts +177 -0
  512. package/src/core/hooks/adapter/output.ts +8 -1
  513. package/src/core/hooks/adapter/runtime-telemetry.ts +3 -1
  514. package/src/core/hooks/adapter/wiring.ts +198 -16
  515. package/src/core/hooks/cli.ts +776 -539
  516. package/src/core/hooks/effects/image-capture.ts +2 -1
  517. package/src/core/hooks/prompt-context/contract.ts +1 -0
  518. package/src/core/hooks/resolve/transcript.ts +42 -5
  519. package/src/core/hooks/run-markers.ts +132 -0
  520. package/src/core/hooks/session-name-presence.ts +10 -3
  521. package/src/core/hooks/shell-waiter.ts +166 -0
  522. package/src/core/resources/service.ts +5 -4
  523. package/src/core/semantic/review.ts +5 -4
  524. package/src/core/semantic/service.ts +15 -14
  525. package/src/core/semantic/storage.ts +5 -4
  526. package/src/core/servers/index.ts +712 -0
  527. package/src/core/servers/net.ts +283 -0
  528. package/src/core/servers/tunnels.ts +39 -0
  529. package/src/core/storage/atomic-json.ts +7 -3
  530. package/src/core/storage/builtins.ts +1 -0
  531. package/src/core/storage/durable-history.ts +6 -5
  532. package/src/core/storage/maintenance-providers.ts +2 -1
  533. package/src/core/storage/maintenance.ts +7 -6
  534. package/src/core/storage/metrics.ts +5 -1
  535. package/src/core/storage/modes.ts +53 -0
  536. package/src/core/storage/process-log.ts +3 -2
  537. package/src/core/storage/receipts.ts +4 -3
  538. package/src/core/storage/segments.ts +7 -6
  539. package/src/core/supervisor/hook-health.ts +4 -4
  540. package/src/core/supervisor/service.ts +7 -6
  541. package/src/core/work/state.ts +8 -7
  542. package/src/core/workflow/adapters.ts +15 -0
  543. package/src/core/workflow/approvals.ts +6 -5
  544. package/src/core/workflow/billing.ts +34 -4
  545. package/src/core/workflow/durable-record.ts +4 -3
  546. package/src/core/workflow/engine.ts +38 -1
  547. package/src/core/workflow/live-session-v3.ts +2 -3
  548. package/src/core/workflow/run-state.ts +3 -2
  549. package/src/core/workflow/sandbox-projection.ts +38 -2
  550. package/src/core/workflow/spawn-claude.ts +5 -1
  551. package/src/core/workflow/spawn-codex.ts +18 -1
  552. package/src/core/workflow/spawn-cursor.ts +5 -1
  553. package/src/core/workflow/spawn-opencode.ts +153 -0
  554. package/src/core/workflow/transcript.ts +3 -2
  555. package/src/core/workflow/types.ts +62 -2
  556. package/src/core/workflow/worker-access.ts +525 -0
  557. package/src/core/workflow/workspaces/leases.ts +5 -4
  558. package/src/core/workflow/workspaces/local-git.ts +3 -2
  559. package/src/core/workflow/workspaces/paths.ts +2 -1
  560. package/src/core/workflow/workspaces/state.ts +10 -9
  561. package/src/lazy-commands.ts +11 -1
  562. package/src/lib/agent-browser/client.ts +18 -0
  563. package/src/lib/browser/batch-steps.ts +79 -0
  564. package/src/lib/browser/client.ts +147 -9
  565. package/src/lib/browser/collect/collector.ts +306 -0
  566. package/src/lib/browser/collect/fields.ts +87 -0
  567. package/src/lib/browser/collect/index.ts +47 -0
  568. package/src/lib/browser/collect/page-driver.ts +327 -0
  569. package/src/lib/browser/collect/presets.ts +237 -0
  570. package/src/lib/browser/collect/scroll-plan.ts +179 -0
  571. package/src/lib/browser/identity.ts +64 -0
  572. package/src/lib/browser/index.ts +16 -1
  573. package/src/lib/browser/launch-args.ts +53 -1
  574. package/src/lib/browser/page-review-judge.ts +16 -0
  575. package/src/lib/browser/qa-run-contracts.ts +11 -0
  576. package/src/lib/browser/qa-run.ts +1 -0
  577. package/src/lib/browser/user-agent.ts +130 -0
  578. package/src/lib/browser/windows-chrome.ts +227 -0
  579. package/src/lib/claude-desktop-share.ts +511 -0
  580. package/src/lib/disk-usage.ts +347 -0
  581. package/src/lib/docs-lint.ts +8 -3
  582. package/src/lib/docs-metadata-managed.ts +21 -0
  583. package/src/lib/guarded-remove.ts +376 -0
  584. package/src/lib/identities/assume.ts +7 -7
  585. package/src/lib/instructions/apply.ts +2 -0
  586. package/src/lib/instructions/templates.ts +8 -8
  587. package/src/lib/pace/index.ts +14 -0
  588. package/src/lib/pace/pace.ts +370 -0
  589. package/src/lib/tunnel/error-page.ts +25 -9
  590. package/src/lib/tunnel/forward-headers.ts +16 -0
  591. package/src/lib/tunnel/gate.ts +39 -10
  592. package/src/lib/tunnel/path-scope.ts +73 -0
  593. package/src/lib/tunnel/state.ts +20 -3
  594. package/src/lib/webview/index.ts +13 -0
  595. package/src/lib/webview/webview.ts +457 -0
@@ -0,0 +1,270 @@
1
+ /**
2
+ * Local socket and process observation for the server registry.
3
+ *
4
+ * Linux reads procfs directly (no `ss`/`lsof` dependency, works under WSL).
5
+ * macOS shells out to `lsof` and `ps`. Other platforms report `unsupported`
6
+ * so callers can say the scan did not run rather than implying it found
7
+ * nothing.
8
+ */
9
+ import { spawnSync } from "node:child_process";
10
+ import { readdirSync, readFileSync, readlinkSync } from "node:fs";
11
+ export function scanSupport() {
12
+ if (process.platform === "linux")
13
+ return "procfs";
14
+ if (process.platform === "darwin")
15
+ return "lsof";
16
+ return "unsupported";
17
+ }
18
+ /** Parse `/proc/net/tcp` or `/proc/net/tcp6` content. */
19
+ export function parseProcNetTcp(content) {
20
+ const rows = [];
21
+ for (const line of content.split("\n").slice(1)) {
22
+ const fields = line.trim().split(/\s+/);
23
+ if (fields.length < 10)
24
+ continue;
25
+ const [address, portHex] = (fields[1] ?? "").split(":");
26
+ if (!address || !portHex)
27
+ continue;
28
+ rows.push({
29
+ localAddress: decodeProcAddress(address),
30
+ localPort: Number.parseInt(portHex, 16),
31
+ state: fields[3] ?? "",
32
+ inode: fields[9] ?? "",
33
+ });
34
+ }
35
+ return rows;
36
+ }
37
+ function decodeProcAddress(hex) {
38
+ if (hex.length === 8) {
39
+ const bytes = hex.match(/../g)?.map((pair) => Number.parseInt(pair, 16)) ?? [];
40
+ return bytes.reverse().join(".");
41
+ }
42
+ if (/^0+$/.test(hex))
43
+ return "::";
44
+ if (hex === "00000000000000000000000001000000")
45
+ return "::1";
46
+ if (hex.startsWith("0000000000000000FFFF0000"))
47
+ return decodeProcAddress(hex.slice(24));
48
+ return `ipv6:${hex.toLowerCase()}`;
49
+ }
50
+ function readProcSockets() {
51
+ const rows = [];
52
+ for (const file of ["/proc/net/tcp", "/proc/net/tcp6"]) {
53
+ try {
54
+ rows.push(...parseProcNetTcp(readFileSync(file, "utf8")));
55
+ }
56
+ catch {
57
+ // tcp6 is absent on IPv6-disabled kernels.
58
+ }
59
+ }
60
+ return rows;
61
+ }
62
+ /** Map socket inodes to the pids holding them (only processes we may read). */
63
+ function socketOwners(inodes) {
64
+ const owners = new Map();
65
+ if (inodes.size === 0)
66
+ return owners;
67
+ let entries;
68
+ try {
69
+ entries = readdirSync("/proc");
70
+ }
71
+ catch {
72
+ return owners;
73
+ }
74
+ for (const entry of entries) {
75
+ if (!/^\d+$/.test(entry))
76
+ continue;
77
+ let fds;
78
+ try {
79
+ fds = readdirSync(`/proc/${entry}/fd`);
80
+ }
81
+ catch {
82
+ continue;
83
+ }
84
+ for (const fd of fds) {
85
+ let target;
86
+ try {
87
+ target = readlinkSync(`/proc/${entry}/fd/${fd}`);
88
+ }
89
+ catch {
90
+ continue;
91
+ }
92
+ const match = /^socket:\[(\d+)\]$/.exec(target);
93
+ if (match?.[1] && inodes.has(match[1]) && !owners.has(match[1])) {
94
+ owners.set(match[1], Number(entry));
95
+ }
96
+ }
97
+ if (owners.size === inodes.size)
98
+ break;
99
+ }
100
+ return owners;
101
+ }
102
+ /** Listening TCP sockets whose owning process this user can see. */
103
+ export function listListeningSockets() {
104
+ const support = scanSupport();
105
+ if (support === "procfs") {
106
+ const listening = readProcSockets().filter((row) => row.state === "0A");
107
+ const owners = socketOwners(new Set(listening.map((row) => row.inode)));
108
+ const seen = new Set();
109
+ const sockets = [];
110
+ for (const row of listening) {
111
+ const pid = owners.get(row.inode);
112
+ if (!pid)
113
+ continue;
114
+ const key = `${pid}:${row.localPort}`;
115
+ if (seen.has(key))
116
+ continue;
117
+ seen.add(key);
118
+ sockets.push({ pid, port: row.localPort, address: row.localAddress });
119
+ }
120
+ return sockets.sort((a, b) => a.port - b.port);
121
+ }
122
+ if (support === "lsof")
123
+ return lsofListeningSockets();
124
+ return [];
125
+ }
126
+ /**
127
+ * Every listening TCP port on this machine, including ports whose owner this
128
+ * user cannot see (containers, other users). Used to avoid port collisions.
129
+ */
130
+ export function listListeningPorts() {
131
+ const support = scanSupport();
132
+ if (support === "procfs")
133
+ return new Set(readProcSockets()
134
+ .filter((row) => row.state === "0A")
135
+ .map((row) => row.localPort));
136
+ if (support === "lsof")
137
+ return new Set(listListeningSockets().map((socket) => socket.port));
138
+ return new Set();
139
+ }
140
+ /** Parse `lsof -Fpn` output for listening sockets. */
141
+ export function parseLsofListen(output) {
142
+ const sockets = [];
143
+ const seen = new Set();
144
+ let pid = 0;
145
+ for (const line of output.split("\n")) {
146
+ if (line.startsWith("p"))
147
+ pid = Number(line.slice(1));
148
+ else if (line.startsWith("n") && pid > 0) {
149
+ const match = /^(.*):(\d+)$/.exec(line.slice(1));
150
+ if (!match?.[2])
151
+ continue;
152
+ const port = Number(match[2]);
153
+ const key = `${pid}:${port}`;
154
+ if (seen.has(key))
155
+ continue;
156
+ seen.add(key);
157
+ sockets.push({ pid, port, address: (match[1] ?? "").replace(/^\[|\]$/g, "") });
158
+ }
159
+ }
160
+ return sockets.sort((a, b) => a.port - b.port);
161
+ }
162
+ /**
163
+ * Count established server-side connections per local port. A browser tab
164
+ * holding a live-reload socket or keep-alive connection counts as activity.
165
+ */
166
+ export function establishedConnectionCounts(ports) {
167
+ const counts = new Map();
168
+ const wanted = new Set(ports.filter((port) => Number.isInteger(port) && port > 0));
169
+ if (wanted.size === 0)
170
+ return counts;
171
+ const support = scanSupport();
172
+ if (support === "procfs") {
173
+ for (const row of readProcSockets()) {
174
+ // 01 ESTABLISHED; 03 SYN_RECV, where a deferred-accept server parks a
175
+ // connected client until its first bytes arrive.
176
+ if ((row.state !== "01" && row.state !== "03") || !wanted.has(row.localPort))
177
+ continue;
178
+ counts.set(row.localPort, (counts.get(row.localPort) ?? 0) + 1);
179
+ }
180
+ return counts;
181
+ }
182
+ if (support === "lsof")
183
+ return lsofConnectionCounts(wanted);
184
+ return counts;
185
+ }
186
+ /** Listening sockets via `lsof` (the macOS path; also runs wherever lsof exists). */
187
+ export function lsofListeningSockets() {
188
+ return parseLsofListen(run("lsof", ["-nP", "-iTCP", "-sTCP:LISTEN", "-Fpn"]));
189
+ }
190
+ /** Server-side established connections per wanted local port, via `lsof`. */
191
+ export function lsofConnectionCounts(wanted) {
192
+ const counts = new Map();
193
+ const output = run("lsof", ["-nP", "-iTCP", "-sTCP:ESTABLISHED", "-Fn"]);
194
+ for (const line of output.split("\n")) {
195
+ const match = /^n.*?:(\d+)->/.exec(line);
196
+ const port = match?.[1] ? Number(match[1]) : 0;
197
+ if (wanted.has(port))
198
+ counts.set(port, (counts.get(port) ?? 0) + 1);
199
+ }
200
+ return counts;
201
+ }
202
+ /** Parent, command line, and working directory via `ps` and `lsof` (the macOS path). */
203
+ export function psProcessInfo(pid) {
204
+ const ps = run("ps", ["-o", "ppid=,command=", "-p", String(pid)]).trim();
205
+ if (!ps)
206
+ return null;
207
+ const match = /^(\d+)\s+(.*)$/.exec(ps);
208
+ const cwdLine = run("lsof", ["-a", "-p", String(pid), "-d", "cwd", "-Fn"])
209
+ .split("\n")
210
+ .find((line) => line.startsWith("n"));
211
+ return {
212
+ pid,
213
+ ppid: match?.[1] ? Number(match[1]) : null,
214
+ command: match?.[2] ?? ps,
215
+ cwd: cwdLine ? cwdLine.slice(1) : null,
216
+ };
217
+ }
218
+ export function readProcessInfo(pid) {
219
+ if (process.platform === "linux") {
220
+ try {
221
+ const stat = readFileSync(`/proc/${pid}/stat`, "utf8");
222
+ const afterComm = stat.slice(stat.lastIndexOf(")") + 2).split(" ");
223
+ const ppid = Number(afterComm[1]);
224
+ const command = readFileSync(`/proc/${pid}/cmdline`, "utf8").split("\0").join(" ").trim();
225
+ let cwd = null;
226
+ try {
227
+ cwd = readlinkSync(`/proc/${pid}/cwd`);
228
+ }
229
+ catch {
230
+ cwd = null;
231
+ }
232
+ return { pid, ppid: Number.isInteger(ppid) ? ppid : null, command, cwd };
233
+ }
234
+ catch {
235
+ return null;
236
+ }
237
+ }
238
+ if (process.platform === "darwin")
239
+ return psProcessInfo(pid);
240
+ return null;
241
+ }
242
+ /** Parse `ps -o etime=` output (`[[dd-]hh:]mm:ss`) into seconds. */
243
+ export function parseElapsed(value) {
244
+ const match = /^\s*(?:(\d+)-)?(?:(\d+):)?(\d+):(\d+)\s*$/.exec(value);
245
+ if (!match)
246
+ return null;
247
+ const [, days, hours, minutes, seconds] = match;
248
+ return (Number(days ?? 0) * 86_400 + Number(hours ?? 0) * 3_600 + Number(minutes) * 60 + Number(seconds));
249
+ }
250
+ /** When a process started, from its elapsed run time; null when unavailable. */
251
+ export function processStartedAt(pid, now = Date.now()) {
252
+ if (process.platform !== "linux" && process.platform !== "darwin")
253
+ return null;
254
+ const elapsed = parseElapsed(run("ps", ["-o", "etime=", "-p", String(pid)]));
255
+ return elapsed === null ? null : new Date(now - elapsed * 1_000).toISOString();
256
+ }
257
+ /** The pid followed by its ancestors, nearest first (bounded). */
258
+ export function ancestry(pid, maxHops = 32) {
259
+ const chain = [];
260
+ let current = pid;
261
+ while (current && current > 1 && chain.length < maxHops && !chain.includes(current)) {
262
+ chain.push(current);
263
+ current = readProcessInfo(current)?.ppid ?? null;
264
+ }
265
+ return chain;
266
+ }
267
+ function run(command, args) {
268
+ const result = spawnSync(command, args, { encoding: "utf8", timeout: 10_000 });
269
+ return result.status === 0 || result.stdout ? (result.stdout ?? "") : "";
270
+ }
@@ -0,0 +1,14 @@
1
+ /**
2
+ * Tunnels as registry services.
3
+ *
4
+ * `tunnel up` and `tunnel reload` register the instance; `tunnel down`
5
+ * removes it. Tunnels started before the registry existed are adopted the next
6
+ * time the registry is read, so a long-lived tunnel never shows as an
7
+ * unregistered listener.
8
+ */
9
+ import { type TunnelState } from "../../lib/tunnel/state.js";
10
+ import type { RegisterServerInput } from "./index.js";
11
+ export declare function tunnelServerId(name: string): string;
12
+ /** The registry input for one tunnel instance. */
13
+ export declare function tunnelServerInput(state: TunnelState, coordRoot: string): RegisterServerInput;
14
+ //# sourceMappingURL=tunnels.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"tunnels.d.ts","sourceRoot":"","sources":["../../../src/core/servers/tunnels.ts"],"names":[],"mappings":"AAAA;;;;;;;GAOG;AAGH,OAAO,EAAe,KAAK,WAAW,EAAE,MAAM,2BAA2B,CAAC;AAE1E,OAAO,KAAK,EAAE,mBAAmB,EAAE,MAAM,YAAY,CAAC;AAEtD,wBAAgB,cAAc,CAAC,IAAI,EAAE,MAAM,GAAG,MAAM,CAEnD;AAED,kDAAkD;AAClD,wBAAgB,iBAAiB,CAAC,KAAK,EAAE,WAAW,EAAE,SAAS,EAAE,MAAM,GAAG,mBAAmB,CAmB5F"}
@@ -0,0 +1,33 @@
1
+ /**
2
+ * Tunnels as registry services.
3
+ *
4
+ * `tunnel up` and `tunnel reload` register the instance; `tunnel down`
5
+ * removes it. Tunnels started before the registry existed are adopted the next
6
+ * time the registry is read, so a long-lived tunnel never shows as an
7
+ * unregistered listener.
8
+ */
9
+ import { resolve } from "node:path";
10
+ import { gateLogFile } from "../../lib/tunnel/state.js";
11
+ import { resolveBinName } from "../config.js";
12
+ export function tunnelServerId(name) {
13
+ return `tunnel-${name.toLowerCase().replace(/[^a-z0-9._-]+/g, "-")}`;
14
+ }
15
+ /** The registry input for one tunnel instance. */
16
+ export function tunnelServerInput(state, coordRoot) {
17
+ const helpers = [state.cloudflared_pid, state.provider_pid].filter((pid) => typeof pid === "number" && pid > 0);
18
+ return {
19
+ id: tunnelServerId(state.name),
20
+ kind: "service",
21
+ type: "tunnel",
22
+ label: `Tunnel ${state.name} → ${state.target}${state.vhost ? ` (${state.vhost})` : ""}`,
23
+ url: state.url,
24
+ port: state.gate_port,
25
+ pid: state.gate_pid,
26
+ ...(helpers.length ? { pids: helpers } : {}),
27
+ log: resolve(coordRoot, ".cache", "tunnel", gateLogFile(state.name)),
28
+ cwd: coordRoot,
29
+ stop_argv: [resolveBinName(coordRoot), "tunnel", "down", "--name", state.name],
30
+ started_at: state.started_at,
31
+ owner: null,
32
+ };
33
+ }
@@ -1 +1 @@
1
- {"version":3,"file":"atomic-json.d.ts","sourceRoot":"","sources":["../../../src/core/storage/atomic-json.ts"],"names":[],"mappings":"AAGA,qFAAqF;AACrF,wBAAgB,sBAAsB,CAAC,IAAI,EAAE,MAAM,EAAE,KAAK,EAAE,OAAO,GAAG,IAAI,CAUzE"}
1
+ {"version":3,"file":"atomic-json.d.ts","sourceRoot":"","sources":["../../../src/core/storage/atomic-json.ts"],"names":[],"mappings":"AAIA,qFAAqF;AACrF,wBAAgB,sBAAsB,CAAC,IAAI,EAAE,MAAM,EAAE,KAAK,EAAE,OAAO,GAAG,IAAI,CAazE"}
@@ -1,12 +1,16 @@
1
1
  import { chmodSync, mkdirSync, renameSync, writeFileSync } from "node:fs";
2
2
  import { dirname } from "node:path";
3
+ import { stateDirMode, stateFileMode } from "./modes.js";
3
4
  /** Write one private JSON projection without exposing a partial frame to readers. */
4
5
  export function writePrivateJsonAtomic(path, value) {
5
- mkdirSync(dirname(path), { recursive: true, mode: 0o700 });
6
+ mkdirSync(dirname(path), { recursive: true, mode: stateDirMode() });
6
7
  const temporary = `${path}.tmp.${process.pid}.${Date.now()}`;
7
- writeFileSync(temporary, `${JSON.stringify(value)}\n`, { encoding: "utf8", mode: 0o600 });
8
+ writeFileSync(temporary, `${JSON.stringify(value)}\n`, {
9
+ encoding: "utf8",
10
+ mode: stateFileMode(),
11
+ });
8
12
  try {
9
- chmodSync(temporary, 0o600);
13
+ chmodSync(temporary, stateFileMode());
10
14
  }
11
15
  catch {
12
16
  // Windows does not expose POSIX modes. The atomic write still applies.
@@ -369,6 +369,7 @@ function cacheFamilies() {
369
369
  ["pid-map-cache", ".harnery/pid-map", "active native process observations"],
370
370
  ["remote-presence-cache", ".harnery/presence/remote", "presence relay observations"],
371
371
  ["event-v3-live-display", ".harnery/live/v3", "Event Ledger V3 canonical events"],
372
+ ["local-server-registry", ".harnery/servers", "running local server processes"],
372
373
  ];
373
374
  return [
374
375
  ...definitions.map(([id, root, source]) => family({
@@ -1 +1 @@
1
- {"version":3,"file":"durable-history.d.ts","sourceRoot":"","sources":["../../../src/core/storage/durable-history.ts"],"names":[],"mappings":"AAuBA,eAAO,MAAM,8BAA8B,EAAG,4BAAqC,CAAC;AAEpF,MAAM,WAAW,qBAAqB;IACpC,gBAAgB,EAAE,MAAM,CAAC;IACzB,iBAAiB,EAAE,MAAM,CAAC;IAC1B,KAAK,CAAC,EAAE,CAAC,QAAQ,EAAE,2BAA2B,KAAK,IAAI,CAAC;IACxD,wEAAwE;IACxE,UAAU,CAAC,EAAE,uBAAuB,CAAC;CACtC;AAED,MAAM,MAAM,uBAAuB,GAAG,CACpC,EAAE,EAAE,MAAM,EACV,MAAM,EAAE,MAAM,EACd,MAAM,EAAE,MAAM,EACd,MAAM,EAAE,MAAM,KACX,MAAM,CAAC;AAEZ,MAAM,MAAM,2BAA2B,GACnC,sBAAsB,GACtB,eAAe,GACf,0BAA0B,GAC1B,yBAAyB,GACzB,uBAAuB,CAAC;AAE5B,MAAM,WAAW,2BAA2B;IAC1C,MAAM,EAAE,OAAO,8BAA8B,CAAC;IAC9C,OAAO,EAAE,QAAQ,CAAC;IAClB,YAAY,EAAE,MAAM,CAAC;IACrB,OAAO,EAAE,OAAO,CAAC;IACjB,MAAM,EAAE,IAAI,CAAC;CACd;AAED,MAAM,WAAW,yBAAyB;IACxC,gBAAgB,EAAE,MAAM,CAAC;IACzB,WAAW,CAAC,EAAE,MAAM,CAAC;CACtB;AAED,MAAM,WAAW,oBAAoB,CAAC,CAAC;IACrC,MAAM,CAAC,EAAE,SAAS,OAAO,EAAE,CAAC;IAC5B,MAAM,EAAE,CAAC,CAAC;CACX;AAED,wBAAgB,0BAA0B,CACxC,SAAS,EAAE,MAAM,EACjB,MAAM,EAAE,OAAO,EACf,OAAO,EAAE,qBAAqB,GAC7B,2BAA2B,CA+B7B;AAED,wBAAgB,wBAAwB,CACtC,IAAI,EAAE,MAAM,EACZ,MAAM,EAAE,OAAO,EACf,cAAc,EAAE,MAAM,EACtB,KAAK,CAAC,EAAE,qBAAqB,CAAC,OAAO,CAAC,GACrC,MAAM,CAQR;AAED,wBAAgB,wBAAwB,CACtC,UAAU,EAAE,MAAM,EAClB,MAAM,EAAE,OAAO,EACf,OAAO,EAAE,qBAAqB,GAC7B,2BAA2B,CA8B7B;AAED,wBAAgB,wBAAwB,CAAC,CAAC,EAAE,CAAC,EAC3C,IAAI,EAAE,MAAM,EACZ,OAAO,EAAE,yBAAyB,EAClC,MAAM,EAAE,CAAC,OAAO,EAAE,SAAS,CAAC,EAAE,KAAK,oBAAoB,CAAC,CAAC,CAAC,EAC1D,KAAK,CAAC,EAAE,qBAAqB,CAAC,OAAO,CAAC,GACrC,CAAC,CAcH;AAED,wBAAuB,oBAAoB,CAAC,CAAC,EAC3C,SAAS,EAAE,MAAM,EACjB,OAAO,EAAE,yBAAyB,GACjC,cAAc,CAAC,CAAC,CAAC,CAYnB;AAED,wBAAgB,sBAAsB,CAAC,CAAC,EACtC,SAAS,EAAE,MAAM,EACjB,OAAO,EAAE,yBAAyB,GACjC,CAAC,EAAE,CAgBL;AAED,wBAAgB,sBAAsB,CAAC,CAAC,EAAE,IAAI,EAAE,MAAM,EAAE,OAAO,EAAE,yBAAyB,GAAG,CAAC,EAAE,CAgB/F;AAED,wBAAgB,0BAA0B,CAAC,CAAC,EAC1C,UAAU,EAAE,MAAM,EAClB,OAAO,EAAE,yBAAyB,GACjC,CAAC,EAAE,CAwBL;AAED,wBAAsB,yBAAyB,CAC7C,IAAI,EAAE,MAAM,EACZ,OAAO,EAAE,SAAS,OAAO,EAAE,EAC3B,cAAc,EAAE,MAAM,EACtB,KAAK,CAAC,EAAE,qBAAqB,CAAC,OAAO,CAAC,GACrC,OAAO,CAAC,IAAI,CAAC,CA2Bf;AAED,wBAAgB,mBAAmB,CAAC,SAAS,EAAE,MAAM,GAAG,MAAM,EAAE,CAqB/D"}
1
+ {"version":3,"file":"durable-history.d.ts","sourceRoot":"","sources":["../../../src/core/storage/durable-history.ts"],"names":[],"mappings":"AAwBA,eAAO,MAAM,8BAA8B,EAAG,4BAAqC,CAAC;AAEpF,MAAM,WAAW,qBAAqB;IACpC,gBAAgB,EAAE,MAAM,CAAC;IACzB,iBAAiB,EAAE,MAAM,CAAC;IAC1B,KAAK,CAAC,EAAE,CAAC,QAAQ,EAAE,2BAA2B,KAAK,IAAI,CAAC;IACxD,wEAAwE;IACxE,UAAU,CAAC,EAAE,uBAAuB,CAAC;CACtC;AAED,MAAM,MAAM,uBAAuB,GAAG,CACpC,EAAE,EAAE,MAAM,EACV,MAAM,EAAE,MAAM,EACd,MAAM,EAAE,MAAM,EACd,MAAM,EAAE,MAAM,KACX,MAAM,CAAC;AAEZ,MAAM,MAAM,2BAA2B,GACnC,sBAAsB,GACtB,eAAe,GACf,0BAA0B,GAC1B,yBAAyB,GACzB,uBAAuB,CAAC;AAE5B,MAAM,WAAW,2BAA2B;IAC1C,MAAM,EAAE,OAAO,8BAA8B,CAAC;IAC9C,OAAO,EAAE,QAAQ,CAAC;IAClB,YAAY,EAAE,MAAM,CAAC;IACrB,OAAO,EAAE,OAAO,CAAC;IACjB,MAAM,EAAE,IAAI,CAAC;CACd;AAED,MAAM,WAAW,yBAAyB;IACxC,gBAAgB,EAAE,MAAM,CAAC;IACzB,WAAW,CAAC,EAAE,MAAM,CAAC;CACtB;AAED,MAAM,WAAW,oBAAoB,CAAC,CAAC;IACrC,MAAM,CAAC,EAAE,SAAS,OAAO,EAAE,CAAC;IAC5B,MAAM,EAAE,CAAC,CAAC;CACX;AAED,wBAAgB,0BAA0B,CACxC,SAAS,EAAE,MAAM,EACjB,MAAM,EAAE,OAAO,EACf,OAAO,EAAE,qBAAqB,GAC7B,2BAA2B,CA+B7B;AAED,wBAAgB,wBAAwB,CACtC,IAAI,EAAE,MAAM,EACZ,MAAM,EAAE,OAAO,EACf,cAAc,EAAE,MAAM,EACtB,KAAK,CAAC,EAAE,qBAAqB,CAAC,OAAO,CAAC,GACrC,MAAM,CAQR;AAED,wBAAgB,wBAAwB,CACtC,UAAU,EAAE,MAAM,EAClB,MAAM,EAAE,OAAO,EACf,OAAO,EAAE,qBAAqB,GAC7B,2BAA2B,CA8B7B;AAED,wBAAgB,wBAAwB,CAAC,CAAC,EAAE,CAAC,EAC3C,IAAI,EAAE,MAAM,EACZ,OAAO,EAAE,yBAAyB,EAClC,MAAM,EAAE,CAAC,OAAO,EAAE,SAAS,CAAC,EAAE,KAAK,oBAAoB,CAAC,CAAC,CAAC,EAC1D,KAAK,CAAC,EAAE,qBAAqB,CAAC,OAAO,CAAC,GACrC,CAAC,CAcH;AAED,wBAAuB,oBAAoB,CAAC,CAAC,EAC3C,SAAS,EAAE,MAAM,EACjB,OAAO,EAAE,yBAAyB,GACjC,cAAc,CAAC,CAAC,CAAC,CAYnB;AAED,wBAAgB,sBAAsB,CAAC,CAAC,EACtC,SAAS,EAAE,MAAM,EACjB,OAAO,EAAE,yBAAyB,GACjC,CAAC,EAAE,CAgBL;AAED,wBAAgB,sBAAsB,CAAC,CAAC,EAAE,IAAI,EAAE,MAAM,EAAE,OAAO,EAAE,yBAAyB,GAAG,CAAC,EAAE,CAgB/F;AAED,wBAAgB,0BAA0B,CAAC,CAAC,EAC1C,UAAU,EAAE,MAAM,EAClB,OAAO,EAAE,yBAAyB,GACjC,CAAC,EAAE,CAwBL;AAED,wBAAsB,yBAAyB,CAC7C,IAAI,EAAE,MAAM,EACZ,OAAO,EAAE,SAAS,OAAO,EAAE,EAC3B,cAAc,EAAE,MAAM,EACtB,KAAK,CAAC,EAAE,qBAAqB,CAAC,OAAO,CAAC,GACrC,OAAO,CAAC,IAAI,CAAC,CA2Bf;AAED,wBAAgB,mBAAmB,CAAC,SAAS,EAAE,MAAM,GAAG,MAAM,EAAE,CAqB/D"}
@@ -2,6 +2,7 @@ import { randomUUID } from "node:crypto";
2
2
  import { closeSync, existsSync, constants as fsConstants, fstatSync, fsyncSync, lstatSync, mkdirSync, openSync, readdirSync, readFileSync, readSync, realpathSync, renameSync, rmSync, statSync, writeSync, } from "node:fs";
3
3
  import { open, rename, rm } from "node:fs/promises";
4
4
  import { basename, dirname, isAbsolute, join, relative } from "node:path";
5
+ import { stateDirMode, stateFileMode } from "./modes.js";
5
6
  export const HARNERY_DURABLE_HISTORY_SCHEMA = "harnery.durable-history/v1";
6
7
  export function appendDurableHistoryRecord(objectDir, record, options) {
7
8
  validateOptions(options);
@@ -174,7 +175,7 @@ export async function rewriteCrashSafeJsonlFile(path, records, maxRecordBytes, f
174
175
  rejectExistingSymlink(path);
175
176
  const temp = `${path}.rewrite-${process.pid}`;
176
177
  await withLeaseAsync(`${path}.lease`, async () => {
177
- const handle = await open(temp, fsConstants.O_WRONLY | fsConstants.O_CREAT | fsConstants.O_EXCL | noFollowFlag(), 0o600);
178
+ const handle = await open(temp, fsConstants.O_WRONLY | fsConstants.O_CREAT | fsConstants.O_EXCL | noFollowFlag(), stateFileMode());
178
179
  try {
179
180
  await writeAll(handle, Buffer.from(body, "utf8"));
180
181
  await handle.sync();
@@ -220,7 +221,7 @@ export function durableHistoryPaths(objectDir) {
220
221
  function appendAndSync(path, line, fault, writer = nativeWriteSync) {
221
222
  const parent = captureDirectoryIdentity(dirname(path));
222
223
  rejectExistingSymlink(path);
223
- const fd = openSync(path, fsConstants.O_RDWR | fsConstants.O_APPEND | fsConstants.O_CREAT | noFollowFlag(), 0o600);
224
+ const fd = openSync(path, fsConstants.O_RDWR | fsConstants.O_APPEND | fsConstants.O_CREAT | noFollowFlag(), stateFileMode());
224
225
  try {
225
226
  assertOpenFileIdentity(path, fd, parent);
226
227
  assertCompleteTail(fd, path);
@@ -235,7 +236,7 @@ function appendAndSync(path, line, fault, writer = nativeWriteSync) {
235
236
  }
236
237
  }
237
238
  function ensurePrivateDirectory(path) {
238
- mkdirSync(path, { recursive: true, mode: 0o700 });
239
+ mkdirSync(path, { recursive: true, mode: stateDirMode() });
239
240
  return captureDirectoryIdentity(path);
240
241
  }
241
242
  function regularFileBytes(path) {
@@ -395,7 +396,7 @@ function acquireLease(lease) {
395
396
  };
396
397
  let claimed;
397
398
  try {
398
- mkdirSync(lease, { mode: 0o700 });
399
+ mkdirSync(lease, { mode: stateDirMode() });
399
400
  assertDirectoryWithinParent(lease, parent);
400
401
  claimed = captureDirectoryIdentity(lease);
401
402
  writeOwner(join(lease, "owner.json"), owner);
@@ -421,7 +422,7 @@ function acquireLease(lease) {
421
422
  }
422
423
  function writeOwner(path, owner) {
423
424
  const parent = captureDirectoryIdentity(dirname(path));
424
- const fd = openSync(path, fsConstants.O_WRONLY | fsConstants.O_CREAT | fsConstants.O_EXCL | noFollowFlag(), 0o600);
425
+ const fd = openSync(path, fsConstants.O_WRONLY | fsConstants.O_CREAT | fsConstants.O_EXCL | noFollowFlag(), stateFileMode());
425
426
  try {
426
427
  assertOpenFileIdentity(path, fd, parent);
427
428
  writeAllSync(fd, Buffer.from(`${JSON.stringify(owner)}\n`, "utf8"), nativeWriteSync);
@@ -1 +1 @@
1
- {"version":3,"file":"maintenance-providers.d.ts","sourceRoot":"","sources":["../../../src/core/storage/maintenance-providers.ts"],"names":[],"mappings":"AAGA,OAAO,EAAwB,KAAK,qBAAqB,EAAE,MAAM,cAAc,CAAC;AAGhF,OAAO,EAEL,KAAK,iCAAiC,EACtC,KAAK,wBAAwB,EAC7B,KAAK,0BAA0B,EAGhC,MAAM,kBAAkB,CAAC;AAI1B,eAAO,MAAM,gCAAgC,EAAE,wBAI7C,CAAC;AAEH,MAAM,WAAW,2BAA2B;IAC1C,OAAO,IAAI,OAAO,CAAC;IACnB,MAAM,IAAI,OAAO,CAAC;IAClB,SAAS,IAAI,OAAO,CAAC;CACtB;AAED,MAAM,WAAW,+BAA+B;IAC9C,OAAO,EAAE,qBAAqB,CAAC;IAC/B,SAAS,EAAE,SAAS,0BAA0B,EAAE,CAAC;CAClD;AAED,wBAAgB,kCAAkC,CAChD,QAAQ,EAAE,2BAA2B,GACpC,SAAS,0BAA0B,EAAE,CAMvC;AAED,mFAAmF;AACnF,wBAAgB,uCAAuC,CACrD,OAAO,EAAE,qBAAqB,GAC7B,SAAS,0BAA0B,EAAE,CAYvC;AAED,wBAAgB,qCAAqC,CACnD,SAAS,EAAE,MAAM,EACjB,QAAQ,EAAE,2BAA2B,GACpC,+BAA+B,CAMjC;AAED;;;;GAIG;AACH,wBAAsB,2BAA2B,CAC/C,WAAW,EAAE,+BAA+B,EAC5C,OAAO,GAAE;IAAE,GAAG,CAAC,EAAE,IAAI,CAAC;IAAC,MAAM,CAAC,EAAE,wBAAwB,CAAA;CAAO,GAC9D,OAAO,CAAC,iCAAiC,CAAC,CAS5C"}
1
+ {"version":3,"file":"maintenance-providers.d.ts","sourceRoot":"","sources":["../../../src/core/storage/maintenance-providers.ts"],"names":[],"mappings":"AAGA,OAAO,EAAwB,KAAK,qBAAqB,EAAE,MAAM,cAAc,CAAC;AAGhF,OAAO,EAEL,KAAK,iCAAiC,EACtC,KAAK,wBAAwB,EAC7B,KAAK,0BAA0B,EAGhC,MAAM,kBAAkB,CAAC;AAK1B,eAAO,MAAM,gCAAgC,EAAE,wBAI7C,CAAC;AAEH,MAAM,WAAW,2BAA2B;IAC1C,OAAO,IAAI,OAAO,CAAC;IACnB,MAAM,IAAI,OAAO,CAAC;IAClB,SAAS,IAAI,OAAO,CAAC;CACtB;AAED,MAAM,WAAW,+BAA+B;IAC9C,OAAO,EAAE,qBAAqB,CAAC;IAC/B,SAAS,EAAE,SAAS,0BAA0B,EAAE,CAAC;CAClD;AAED,wBAAgB,kCAAkC,CAChD,QAAQ,EAAE,2BAA2B,GACpC,SAAS,0BAA0B,EAAE,CAMvC;AAED,mFAAmF;AACnF,wBAAgB,uCAAuC,CACrD,OAAO,EAAE,qBAAqB,GAC7B,SAAS,0BAA0B,EAAE,CAYvC;AAED,wBAAgB,qCAAqC,CACnD,SAAS,EAAE,MAAM,EACjB,QAAQ,EAAE,2BAA2B,GACpC,+BAA+B,CAMjC;AAED;;;;GAIG;AACH,wBAAsB,2BAA2B,CAC/C,WAAW,EAAE,+BAA+B,EAC5C,OAAO,GAAE;IAAE,GAAG,CAAC,EAAE,IAAI,CAAC;IAAC,MAAM,CAAC,EAAE,wBAAwB,CAAA;CAAO,GAC9D,OAAO,CAAC,iCAAiC,CAAC,CAS5C"}
@@ -5,6 +5,7 @@ import { createStorageCatalog } from "./catalog.js";
5
5
  import { HARNERY_STRUCTURED_LOG_PROVIDER_ID } from "./contract.js";
6
6
  import { createStructuredLogRetentionProvider } from "./log-retention.js";
7
7
  import { HARNERY_MAINTENANCE_CURSOR_SCHEMA, readMaintenanceTransaction, runAutomaticMaintenanceSlice, } from "./maintenance.js";
8
+ import { stateFileMode } from "./modes.js";
8
9
  const STALE_RUNNING_CLAIM_MS = 10 * 60 * 1_000;
9
10
  export const SESSION_START_MAINTENANCE_BUDGET = Object.freeze({
10
11
  max_duration_ms: 250,
@@ -133,7 +134,7 @@ function recoverInterruptedDailyClaim(coordRoot, now) {
133
134
  }
134
135
  function atomicCursor(path, cursor) {
135
136
  const temporary = `${path}.tmp-${process.pid}-${randomUUID()}`;
136
- writeFileSync(temporary, `${JSON.stringify(cursor, null, 2)}\n`, { mode: 0o600 });
137
+ writeFileSync(temporary, `${JSON.stringify(cursor, null, 2)}\n`, { mode: stateFileMode() });
137
138
  renameSync(temporary, path);
138
139
  }
139
140
  function disabledResult() {
@@ -1 +1 @@
1
- {"version":3,"file":"maintenance.d.ts","sourceRoot":"","sources":["../../../src/core/storage/maintenance.ts"],"names":[],"mappings":"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"}
1
+ {"version":3,"file":"maintenance.d.ts","sourceRoot":"","sources":["../../../src/core/storage/maintenance.ts"],"names":[],"mappings":"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"}
@@ -3,6 +3,7 @@ import { appendFileSync, closeSync, existsSync, fsyncSync, lstatSync, mkdirSync,
3
3
  import { basename, dirname, join, resolve } from "node:path";
4
4
  import { acquireNoClobberLease } from "../workflow/workspaces/leases.js";
5
5
  import { HARNERY_STRUCTURED_LOG_PROVIDER_ID, } from "./contract.js";
6
+ import { stateDirMode, stateFileMode } from "./modes.js";
6
7
  export const HARNERY_MAINTENANCE_TRANSACTION_SCHEMA = "harnery.storage-maintenance-transaction/v1";
7
8
  export const HARNERY_MAINTENANCE_RECEIPT_SCHEMA = "harnery.storage-maintenance-receipt/v1";
8
9
  export const HARNERY_MAINTENANCE_CURSOR_SCHEMA = "harnery.storage-maintenance-cursor/v1";
@@ -413,7 +414,7 @@ function writeReceipt(coordRoot, transactionId, action, mutation, now) {
413
414
  committed_at: now.toISOString(),
414
415
  };
415
416
  const path = receiptPath(coordRoot, transactionId, action.action_id);
416
- mkdirSync(dirname(path), { recursive: true, mode: 0o700 });
417
+ mkdirSync(dirname(path), { recursive: true, mode: stateDirMode() });
417
418
  writeExclusiveDurable(path, `${JSON.stringify(receipt, null, 2)}\n`);
418
419
  }
419
420
  function writeTransaction(coordRoot, transaction, replace) {
@@ -434,12 +435,12 @@ function updateTransaction(transaction, now, state, reasonCodes = transaction.re
434
435
  }
435
436
  function writeRunOutcome(coordRoot, transaction, now) {
436
437
  const root = join(resolve(coordRoot), ".harnery", "logs", "storage-maintenance");
437
- mkdirSync(root, { recursive: true, mode: 0o700 });
438
+ mkdirSync(root, { recursive: true, mode: stateDirMode() });
438
439
  const active = join(root, "active.jsonl");
439
440
  if (existsSync(active) && statSync(active).size > 1_048_576) {
440
441
  renameSync(active, join(root, `sealed-${now.toISOString().replaceAll(/[:.]/g, "-")}.jsonl`));
441
442
  }
442
- appendFileSync(active, `${JSON.stringify({ ts: now.toISOString(), transaction_id: transaction.transaction_id, state: transaction.state, actions: transaction.actions.length, files: transaction.actions.reduce((n, action) => n + action.files, 0), bytes: transaction.actions.reduce((n, action) => n + action.bytes, 0), reason_codes: transaction.reason_codes })}\n`, { encoding: "utf8", mode: 0o600 });
443
+ appendFileSync(active, `${JSON.stringify({ ts: now.toISOString(), transaction_id: transaction.transaction_id, state: transaction.state, actions: transaction.actions.length, files: transaction.actions.reduce((n, action) => n + action.files, 0), bytes: transaction.actions.reduce((n, action) => n + action.bytes, 0), reason_codes: transaction.reason_codes })}\n`, { encoding: "utf8", mode: stateFileMode() });
443
444
  }
444
445
  function readDailyCursor(coordRoot) {
445
446
  const path = join(resolve(coordRoot), ".harnery", "maintenance", "cursors", "daily.json");
@@ -554,9 +555,9 @@ function readJsonFile(path) {
554
555
  return JSON.parse(readFileSync(path, "utf8"));
555
556
  }
556
557
  function atomicJson(path, value, fsync) {
557
- mkdirSync(dirname(path), { recursive: true, mode: 0o700 });
558
+ mkdirSync(dirname(path), { recursive: true, mode: stateDirMode() });
558
559
  const temporary = `${path}.tmp-${process.pid}-${randomUUID()}`;
559
- const fd = openSync(temporary, "wx", 0o600);
560
+ const fd = openSync(temporary, "wx", stateFileMode());
560
561
  try {
561
562
  writeFileSync(fd, `${JSON.stringify(value, null, 2)}\n`, "utf8");
562
563
  if (fsync)
@@ -568,7 +569,7 @@ function atomicJson(path, value, fsync) {
568
569
  renameSync(temporary, path);
569
570
  }
570
571
  function writeExclusiveDurable(path, value) {
571
- const fd = openSync(path, "wx", 0o600);
572
+ const fd = openSync(path, "wx", stateFileMode());
572
573
  try {
573
574
  writeFileSync(fd, value, "utf8");
574
575
  fsyncSync(fd);
@@ -1 +1 @@
1
- {"version":3,"file":"metrics.d.ts","sourceRoot":"","sources":["../../../src/core/storage/metrics.ts"],"names":[],"mappings":"AAGA,MAAM,WAAW,sBAAsB;IACrC,QAAQ,CAAC,EAAE,MAAM,CAAC;IAClB,OAAO,CAAC,EAAE,MAAM,CAAC;IACjB,QAAQ,CAAC,EAAE,MAAM,CAAC;IAClB,MAAM,CAAC,EAAE,MAAM,CAAC;IAChB,OAAO,CAAC,EAAE,MAAM,CAAC;IACjB,SAAS,CAAC,EAAE,MAAM,CAAC;IACnB,OAAO,CAAC,EAAE,MAAM,CAAC;IACjB,cAAc,CAAC,EAAE,MAAM,CAAC;IACxB,cAAc,CAAC,EAAE,MAAM,CAAC;IACxB,aAAa,CAAC,EAAE,MAAM,CAAC;IACvB,SAAS,CAAC,EAAE,MAAM,CAAC;IACnB,QAAQ,CAAC,EAAE,MAAM,CAAC,MAAM,EAAE,MAAM,CAAC,CAAC;IAClC,iBAAiB,CAAC,EAAE,MAAM,CAAC;IAC3B,gBAAgB,CAAC,EAAE,MAAM,CAAC;IAC1B,KAAK,CAAC,EAAE;QACN,KAAK,EAAE,MAAM,CAAC;QACd,cAAc,EAAE,MAAM,CAAC;QACvB,UAAU,EAAE,MAAM,CAAC;QACnB,WAAW,EAAE,MAAM,CAAC;KACrB,CAAC;CACH;AAED,MAAM,WAAW,mBAAmB;IAClC,MAAM,EAAE,wBAAwB,CAAC;IACjC,UAAU,EAAE,MAAM,CAAC;IACnB,iBAAiB,EAAE,MAAM,CAAC;IAC1B,aAAa,EAAE,MAAM,CAAC;IACtB,uBAAuB,CAAC,EAAE,MAAM,CAAC;IACjC,QAAQ,EAAE;QACR,QAAQ,EAAE,MAAM,CAAC;QACjB,OAAO,EAAE,MAAM,CAAC;QAChB,QAAQ,EAAE,MAAM,CAAC;QACjB,MAAM,EAAE,MAAM,CAAC;QACf,OAAO,EAAE,MAAM,CAAC;QAChB,SAAS,EAAE,MAAM,CAAC;QAClB,OAAO,EAAE,MAAM,CAAC;QAChB,cAAc,EAAE,MAAM,CAAC;QACvB,cAAc,EAAE,MAAM,CAAC;QACvB,aAAa,EAAE,MAAM,CAAC;QACtB,SAAS,EAAE,MAAM,CAAC;KACnB,CAAC;IACF,QAAQ,EAAE,MAAM,CAAC,MAAM,EAAE,MAAM,CAAC,CAAC;IACjC,wBAAwB,EAAE,SAAS,MAAM,EAAE,CAAC;IAC5C,uBAAuB,EAAE,SAAS,MAAM,EAAE,CAAC;IAC3C,KAAK,CAAC,EAAE,sBAAsB,CAAC,OAAO,CAAC,CAAC;CACzC;AAID,qBAAa,qBAAqB;;IAIhC,SAAS,CAAC,CAAC,SAAS,MAAM,sBAAsB,EAAE,GAAG,EAAE,CAAC,EAAE,MAAM,SAAI,GAAG,IAAI;IAO3E,OAAO,CAAC,MAAM,EAAE,MAAM,EAAE,MAAM,SAAI,GAAG,IAAI;IAMzC,YAAY,CAAC,KAAK,EAAE,MAAM,EAAE,aAAa,EAAE,MAAM,EAAE,GAAG,EAAE,IAAI,GAAG,IAAI;IAUnE,cAAc,CAAC,IAAI,EAAE,mBAAmB,GAAG,kBAAkB,EAAE,YAAY,EAAE,MAAM,GAAG,IAAI;IAI1F,IAAI,IAAI,sBAAsB;CAM/B;AAED,wBAAgB,mBAAmB,CACjC,IAAI,EAAE,MAAM,EACZ,KAAK,EAAE,sBAAsB,EAC7B,GAAG,OAAa,GACf;IAAE,MAAM,EAAE,OAAO,CAAC;IAAC,gBAAgB,EAAE,OAAO,CAAA;CAAE,CAqBhD;AAED,wBAAgB,kBAAkB,CAAC,IAAI,EAAE,MAAM,GAAG,mBAAmB,GAAG,SAAS,CAOhF"}
1
+ {"version":3,"file":"metrics.d.ts","sourceRoot":"","sources":["../../../src/core/storage/metrics.ts"],"names":[],"mappings":"AAIA,MAAM,WAAW,sBAAsB;IACrC,QAAQ,CAAC,EAAE,MAAM,CAAC;IAClB,OAAO,CAAC,EAAE,MAAM,CAAC;IACjB,QAAQ,CAAC,EAAE,MAAM,CAAC;IAClB,MAAM,CAAC,EAAE,MAAM,CAAC;IAChB,OAAO,CAAC,EAAE,MAAM,CAAC;IACjB,SAAS,CAAC,EAAE,MAAM,CAAC;IACnB,OAAO,CAAC,EAAE,MAAM,CAAC;IACjB,cAAc,CAAC,EAAE,MAAM,CAAC;IACxB,cAAc,CAAC,EAAE,MAAM,CAAC;IACxB,aAAa,CAAC,EAAE,MAAM,CAAC;IACvB,SAAS,CAAC,EAAE,MAAM,CAAC;IACnB,QAAQ,CAAC,EAAE,MAAM,CAAC,MAAM,EAAE,MAAM,CAAC,CAAC;IAClC,iBAAiB,CAAC,EAAE,MAAM,CAAC;IAC3B,gBAAgB,CAAC,EAAE,MAAM,CAAC;IAC1B,KAAK,CAAC,EAAE;QACN,KAAK,EAAE,MAAM,CAAC;QACd,cAAc,EAAE,MAAM,CAAC;QACvB,UAAU,EAAE,MAAM,CAAC;QACnB,WAAW,EAAE,MAAM,CAAC;KACrB,CAAC;CACH;AAED,MAAM,WAAW,mBAAmB;IAClC,MAAM,EAAE,wBAAwB,CAAC;IACjC,UAAU,EAAE,MAAM,CAAC;IACnB,iBAAiB,EAAE,MAAM,CAAC;IAC1B,aAAa,EAAE,MAAM,CAAC;IACtB,uBAAuB,CAAC,EAAE,MAAM,CAAC;IACjC,QAAQ,EAAE;QACR,QAAQ,EAAE,MAAM,CAAC;QACjB,OAAO,EAAE,MAAM,CAAC;QAChB,QAAQ,EAAE,MAAM,CAAC;QACjB,MAAM,EAAE,MAAM,CAAC;QACf,OAAO,EAAE,MAAM,CAAC;QAChB,SAAS,EAAE,MAAM,CAAC;QAClB,OAAO,EAAE,MAAM,CAAC;QAChB,cAAc,EAAE,MAAM,CAAC;QACvB,cAAc,EAAE,MAAM,CAAC;QACvB,aAAa,EAAE,MAAM,CAAC;QACtB,SAAS,EAAE,MAAM,CAAC;KACnB,CAAC;IACF,QAAQ,EAAE,MAAM,CAAC,MAAM,EAAE,MAAM,CAAC,CAAC;IACjC,wBAAwB,EAAE,SAAS,MAAM,EAAE,CAAC;IAC5C,uBAAuB,EAAE,SAAS,MAAM,EAAE,CAAC;IAC3C,KAAK,CAAC,EAAE,sBAAsB,CAAC,OAAO,CAAC,CAAC;CACzC;AAID,qBAAa,qBAAqB;;IAIhC,SAAS,CAAC,CAAC,SAAS,MAAM,sBAAsB,EAAE,GAAG,EAAE,CAAC,EAAE,MAAM,SAAI,GAAG,IAAI;IAO3E,OAAO,CAAC,MAAM,EAAE,MAAM,EAAE,MAAM,SAAI,GAAG,IAAI;IAMzC,YAAY,CAAC,KAAK,EAAE,MAAM,EAAE,aAAa,EAAE,MAAM,EAAE,GAAG,EAAE,IAAI,GAAG,IAAI;IAUnE,cAAc,CAAC,IAAI,EAAE,mBAAmB,GAAG,kBAAkB,EAAE,YAAY,EAAE,MAAM,GAAG,IAAI;IAI1F,IAAI,IAAI,sBAAsB;CAM/B;AAED,wBAAgB,mBAAmB,CACjC,IAAI,EAAE,MAAM,EACZ,KAAK,EAAE,sBAAsB,EAC7B,GAAG,OAAa,GACf;IAAE,MAAM,EAAE,OAAO,CAAC;IAAC,gBAAgB,EAAE,OAAO,CAAA;CAAE,CAwBhD;AAED,wBAAgB,kBAAkB,CAAC,IAAI,EAAE,MAAM,GAAG,mBAAmB,GAAG,SAAS,CAOhF"}
@@ -1,5 +1,6 @@
1
1
  import { randomUUID } from "node:crypto";
2
2
  import { existsSync, readFileSync, renameSync, writeFileSync } from "node:fs";
3
+ import { stateFileMode } from "./modes.js";
3
4
  const HISTOGRAM_BUCKETS = [1, 2, 5, 10, 25, 50, 100, 250, 500, 1_000, 5_000];
4
5
  export class LogMetricsAccumulator {
5
6
  #delta = {};
@@ -54,7 +55,10 @@ export function mergeMetricsSidecar(path, delta, now = new Date()) {
54
55
  const merged = mergeMetrics(current, delta, now);
55
56
  const temporary = `${path}.tmp-${process.pid}-${randomUUID()}`;
56
57
  try {
57
- writeFileSync(temporary, `${JSON.stringify(merged)}\n`, { encoding: "utf8", mode: 0o600 });
58
+ writeFileSync(temporary, `${JSON.stringify(merged)}\n`, {
59
+ encoding: "utf8",
60
+ mode: stateFileMode(),
61
+ });
58
62
  renameSync(temporary, path);
59
63
  return { merged: true, generation_reset: generationReset };
60
64
  }
@@ -0,0 +1,17 @@
1
+ /** The sharing mode for this process, resolved once. Tests reset it with `resetStorageSharing`. */
2
+ export declare function stateSharing(): "private" | "group";
3
+ export declare function resetStorageSharing(): void;
4
+ /**
5
+ * Mode for a directory of project state. Group mode includes setgid: Harnery chmods directories
6
+ * after creating them, and a plain 0770 would clear the bit, so files made inside would take the
7
+ * writer's own group instead of the project's, and other users could not read them.
8
+ */
9
+ export declare function stateDirMode(): number;
10
+ /** Mode for a file of project state. */
11
+ export declare function stateFileMode(): number;
12
+ /**
13
+ * True when a state file or directory is readable or writable by someone it should not be: anyone
14
+ * but the owner in private mode, anyone outside the owner and group in group mode.
15
+ */
16
+ export declare function stateModeTooOpen(mode: number): boolean;
17
+ //# sourceMappingURL=modes.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"modes.d.ts","sourceRoot":"","sources":["../../../src/core/storage/modes.ts"],"names":[],"mappings":"AAgBA,mGAAmG;AACnG,wBAAgB,YAAY,IAAI,SAAS,GAAG,OAAO,CASlD;AAED,wBAAgB,mBAAmB,IAAI,IAAI,CAE1C;AAED;;;;GAIG;AACH,wBAAgB,YAAY,IAAI,MAAM,CAErC;AAED,wCAAwC;AACxC,wBAAgB,aAAa,IAAI,MAAM,CAEtC;AAED;;;GAGG;AACH,wBAAgB,gBAAgB,CAAC,IAAI,EAAE,MAAM,GAAG,OAAO,CAEtD"}
@@ -0,0 +1,47 @@
1
+ /**
2
+ * The permission modes for everything Harnery writes as project state under `.harnery/`.
3
+ *
4
+ * `private` (the default) is owner-only: 0700 directories and 0600 files, exactly as before this
5
+ * module existed. `group` is for a project several Unix users share through one group, such as a
6
+ * workspace that several people's agents work in at once: 2770 (setgid) and 0660, with nothing ever granted
7
+ * to other users. Every state write takes its mode from here, and every integrity check that
8
+ * rejects a loosely permissioned file asks `stateModeTooOpen`, so the two cannot disagree.
9
+ *
10
+ * Personal state outside the project (browser cookies, sessions, pacing ledgers in the user's home)
11
+ * is not project state and stays owner-only regardless.
12
+ */
13
+ import { storageSharing } from "../config.js";
14
+ let resolved;
15
+ /** The sharing mode for this process, resolved once. Tests reset it with `resetStorageSharing`. */
16
+ export function stateSharing() {
17
+ if (resolved === undefined) {
18
+ resolved = storageSharing();
19
+ // A umask that strips group bits would quietly turn every group file back into an owner-only
20
+ // one, and the next user's write would fail. Keep the process's other-bits mask as it was.
21
+ if (resolved === "group" && typeof process.umask === "function")
22
+ process.umask(process.umask() & ~0o070);
23
+ }
24
+ return resolved;
25
+ }
26
+ export function resetStorageSharing() {
27
+ resolved = undefined;
28
+ }
29
+ /**
30
+ * Mode for a directory of project state. Group mode includes setgid: Harnery chmods directories
31
+ * after creating them, and a plain 0770 would clear the bit, so files made inside would take the
32
+ * writer's own group instead of the project's, and other users could not read them.
33
+ */
34
+ export function stateDirMode() {
35
+ return stateSharing() === "group" ? 0o2770 : 0o700;
36
+ }
37
+ /** Mode for a file of project state. */
38
+ export function stateFileMode() {
39
+ return stateSharing() === "group" ? 0o660 : 0o600;
40
+ }
41
+ /**
42
+ * True when a state file or directory is readable or writable by someone it should not be: anyone
43
+ * but the owner in private mode, anyone outside the owner and group in group mode.
44
+ */
45
+ export function stateModeTooOpen(mode) {
46
+ return (mode & (stateSharing() === "group" ? 0o007 : 0o077)) !== 0;
47
+ }
@@ -1 +1 @@
1
- {"version":3,"file":"process-log.d.ts","sourceRoot":"","sources":["../../../src/core/storage/process-log.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,KAAK,YAAY,EAAoB,MAAM,oBAAoB,CAAC;AAgBzE,MAAM,WAAW,uBAAuB;IACtC,IAAI,EAAE,MAAM,CAAC;IACb,SAAS,EAAE,MAAM,CAAC;IAClB,OAAO,CAAC,EAAE,MAAM,CAAC;IACjB,OAAO,CAAC,EAAE,OAAO,CAAC;CACnB;AAED,MAAM,WAAW,4BAA4B;IAC3C,UAAU,EAAE,MAAM,CAAC;IACnB,YAAY,CAAC,EAAE,MAAM,CAAC;IACtB,SAAS,EAAE,MAAM,CAAC;IAClB,QAAQ,EAAE,MAAM,CAAC;IACjB,WAAW,EAAE,MAAM,CAAC;IACpB,GAAG,CAAC,EAAE,QAAQ,CAAC,MAAM,CAAC,MAAM,EAAE,MAAM,GAAG,SAAS,CAAC,CAAC,CAAC;CACpD;AAED,MAAM,WAAW,sBAAsB;IACrC,IAAI,EAAE,MAAM,CAAC;IACb,OAAO,EAAE,MAAM,CAAC;IAChB,SAAS,CAAC,EAAE,MAAM,EAAE,CAAC;IACrB,GAAG,CAAC,EAAE,QAAQ,CAAC,MAAM,CAAC,MAAM,EAAE,MAAM,GAAG,SAAS,CAAC,CAAC,CAAC;IACnD,SAAS,CAAC,EAAE,MAAM,CAAC;IACnB,OAAO,CAAC,EAAE,MAAM,CAAC;CAClB;AAKD,kFAAkF;AAClF,wBAAgB,qBAAqB,CAAC,OAAO,EAAE,4BAA4B,GAAG,MAAM,CAcnF;AAED,qBAAa,gBAAgB;;gBAIf,OAAO,EAAE,uBAAuB;IAa5C,MAAM,CAAC,IAAI,EAAE,MAAM,GAAG,IAAI;IAuB1B,eAAe,IAAI,IAAI;IAKvB,KAAK,IAAI,IAAI;IACb,KAAK,IAAI,IAAI;CAWd;AAED,6FAA6F;AAC7F,wBAAgB,oBAAoB,CAAC,OAAO,EAAE,sBAAsB,GAAG,YAAY,CAqBlF;AAED,mFAAmF;AACnF,wBAAgB,sBAAsB,CAAC,OAAO,EAAE,sBAAsB,GAAG,MAAM,GAAG,IAAI,CAgBrF"}
1
+ {"version":3,"file":"process-log.d.ts","sourceRoot":"","sources":["../../../src/core/storage/process-log.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,KAAK,YAAY,EAAoB,MAAM,oBAAoB,CAAC;AAiBzE,MAAM,WAAW,uBAAuB;IACtC,IAAI,EAAE,MAAM,CAAC;IACb,SAAS,EAAE,MAAM,CAAC;IAClB,OAAO,CAAC,EAAE,MAAM,CAAC;IACjB,OAAO,CAAC,EAAE,OAAO,CAAC;CACnB;AAED,MAAM,WAAW,4BAA4B;IAC3C,UAAU,EAAE,MAAM,CAAC;IACnB,YAAY,CAAC,EAAE,MAAM,CAAC;IACtB,SAAS,EAAE,MAAM,CAAC;IAClB,QAAQ,EAAE,MAAM,CAAC;IACjB,WAAW,EAAE,MAAM,CAAC;IACpB,GAAG,CAAC,EAAE,QAAQ,CAAC,MAAM,CAAC,MAAM,EAAE,MAAM,GAAG,SAAS,CAAC,CAAC,CAAC;CACpD;AAED,MAAM,WAAW,sBAAsB;IACrC,IAAI,EAAE,MAAM,CAAC;IACb,OAAO,EAAE,MAAM,CAAC;IAChB,SAAS,CAAC,EAAE,MAAM,EAAE,CAAC;IACrB,GAAG,CAAC,EAAE,QAAQ,CAAC,MAAM,CAAC,MAAM,EAAE,MAAM,GAAG,SAAS,CAAC,CAAC,CAAC;IACnD,SAAS,CAAC,EAAE,MAAM,CAAC;IACnB,OAAO,CAAC,EAAE,MAAM,CAAC;CAClB;AAKD,kFAAkF;AAClF,wBAAgB,qBAAqB,CAAC,OAAO,EAAE,4BAA4B,GAAG,MAAM,CAcnF;AAED,qBAAa,gBAAgB;;gBAIf,OAAO,EAAE,uBAAuB;IAa5C,MAAM,CAAC,IAAI,EAAE,MAAM,GAAG,IAAI;IAuB1B,eAAe,IAAI,IAAI;IAKvB,KAAK,IAAI,IAAI;IACb,KAAK,IAAI,IAAI;CAWd;AAED,6FAA6F;AAC7F,wBAAgB,oBAAoB,CAAC,OAAO,EAAE,sBAAsB,GAAG,YAAY,CAqBlF;AAED,mFAAmF;AACnF,wBAAgB,sBAAsB,CAAC,OAAO,EAAE,sBAAsB,GAAG,MAAM,GAAG,IAAI,CAgBrF"}