@elaraai/e3-rack 0.0.0-bootstrap.0 → 1.0.94

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (306) hide show
  1. package/README.md +407 -2
  2. package/dist/src/client/client.spec.d.ts +6 -0
  3. package/dist/src/client/client.spec.d.ts.map +1 -0
  4. package/dist/src/client/client.spec.js +150 -0
  5. package/dist/src/client/client.spec.js.map +1 -0
  6. package/dist/src/client/connect.d.ts +52 -0
  7. package/dist/src/client/connect.d.ts.map +1 -0
  8. package/dist/src/client/connect.js +112 -0
  9. package/dist/src/client/connect.js.map +1 -0
  10. package/dist/src/client/hub-client.d.ts +57 -0
  11. package/dist/src/client/hub-client.d.ts.map +1 -0
  12. package/dist/src/client/hub-client.js +87 -0
  13. package/dist/src/client/hub-client.js.map +1 -0
  14. package/dist/src/client/local-http.d.ts +78 -0
  15. package/dist/src/client/local-http.d.ts.map +1 -0
  16. package/dist/src/client/local-http.js +149 -0
  17. package/dist/src/client/local-http.js.map +1 -0
  18. package/dist/src/client/session-attempts.d.ts +20 -0
  19. package/dist/src/client/session-attempts.d.ts.map +1 -0
  20. package/dist/src/client/session-attempts.js +88 -0
  21. package/dist/src/client/session-attempts.js.map +1 -0
  22. package/dist/src/client/session-data-server.d.ts +37 -0
  23. package/dist/src/client/session-data-server.d.ts.map +1 -0
  24. package/dist/src/client/session-data-server.js +280 -0
  25. package/dist/src/client/session-data-server.js.map +1 -0
  26. package/dist/src/client/session-data-server.spec.d.ts +6 -0
  27. package/dist/src/client/session-data-server.spec.d.ts.map +1 -0
  28. package/dist/src/client/session-data-server.spec.js +192 -0
  29. package/dist/src/client/session-data-server.spec.js.map +1 -0
  30. package/dist/src/client/session.d.ts +119 -0
  31. package/dist/src/client/session.d.ts.map +1 -0
  32. package/dist/src/client/session.js +290 -0
  33. package/dist/src/client/session.js.map +1 -0
  34. package/dist/src/hub/config.d.ts +74 -0
  35. package/dist/src/hub/config.d.ts.map +1 -0
  36. package/dist/src/hub/config.js +159 -0
  37. package/dist/src/hub/config.js.map +1 -0
  38. package/dist/src/hub/fair-lease-store.d.ts +36 -0
  39. package/dist/src/hub/fair-lease-store.d.ts.map +1 -0
  40. package/dist/src/hub/fair-lease-store.js +73 -0
  41. package/dist/src/hub/fair-lease-store.js.map +1 -0
  42. package/dist/src/hub/hub.d.ts +91 -0
  43. package/dist/src/hub/hub.d.ts.map +1 -0
  44. package/dist/src/hub/hub.js +641 -0
  45. package/dist/src/hub/hub.js.map +1 -0
  46. package/dist/src/hub/hub.spec.d.ts +6 -0
  47. package/dist/src/hub/hub.spec.d.ts.map +1 -0
  48. package/dist/src/hub/hub.spec.js +363 -0
  49. package/dist/src/hub/hub.spec.js.map +1 -0
  50. package/dist/src/hub/infrastructure.spec.d.ts +6 -0
  51. package/dist/src/hub/infrastructure.spec.d.ts.map +1 -0
  52. package/dist/src/hub/infrastructure.spec.js +211 -0
  53. package/dist/src/hub/infrastructure.spec.js.map +1 -0
  54. package/dist/src/hub/lock.d.ts +62 -0
  55. package/dist/src/hub/lock.d.ts.map +1 -0
  56. package/dist/src/hub/lock.js +165 -0
  57. package/dist/src/hub/lock.js.map +1 -0
  58. package/dist/src/hub/main.d.ts +16 -0
  59. package/dist/src/hub/main.d.ts.map +1 -0
  60. package/dist/src/hub/main.js +56 -0
  61. package/dist/src/hub/main.js.map +1 -0
  62. package/dist/src/hub/session-bridge.d.ts +116 -0
  63. package/dist/src/hub/session-bridge.d.ts.map +1 -0
  64. package/dist/src/hub/session-bridge.js +336 -0
  65. package/dist/src/hub/session-bridge.js.map +1 -0
  66. package/dist/src/identity/file-identity-store.d.ts +18 -0
  67. package/dist/src/identity/file-identity-store.d.ts.map +1 -0
  68. package/dist/src/identity/file-identity-store.js +34 -0
  69. package/dist/src/identity/file-identity-store.js.map +1 -0
  70. package/dist/src/identity/file-identity-store.spec.d.ts +6 -0
  71. package/dist/src/identity/file-identity-store.spec.d.ts.map +1 -0
  72. package/dist/src/identity/file-identity-store.spec.js +59 -0
  73. package/dist/src/identity/file-identity-store.spec.js.map +1 -0
  74. package/dist/src/identity/in-memory-identity-store.d.ts +48 -0
  75. package/dist/src/identity/in-memory-identity-store.d.ts.map +1 -0
  76. package/dist/src/identity/in-memory-identity-store.js +102 -0
  77. package/dist/src/identity/in-memory-identity-store.js.map +1 -0
  78. package/dist/src/identity/machine-identity.d.ts +134 -0
  79. package/dist/src/identity/machine-identity.d.ts.map +1 -0
  80. package/dist/src/identity/machine-identity.js +65 -0
  81. package/dist/src/identity/machine-identity.js.map +1 -0
  82. package/dist/src/index.d.ts +34 -0
  83. package/dist/src/index.d.ts.map +1 -0
  84. package/dist/src/index.js +34 -0
  85. package/dist/src/index.js.map +1 -0
  86. package/dist/src/lease/closure.d.ts +96 -0
  87. package/dist/src/lease/closure.d.ts.map +1 -0
  88. package/dist/src/lease/closure.js +192 -0
  89. package/dist/src/lease/closure.js.map +1 -0
  90. package/dist/src/lease/closure.spec.d.ts +6 -0
  91. package/dist/src/lease/closure.spec.d.ts.map +1 -0
  92. package/dist/src/lease/closure.spec.js +35 -0
  93. package/dist/src/lease/closure.spec.js.map +1 -0
  94. package/dist/src/lease/coordinator.d.ts +34 -0
  95. package/dist/src/lease/coordinator.d.ts.map +1 -0
  96. package/dist/src/lease/coordinator.js +42 -0
  97. package/dist/src/lease/coordinator.js.map +1 -0
  98. package/dist/src/lease/in-memory-lease-store.d.ts +58 -0
  99. package/dist/src/lease/in-memory-lease-store.d.ts.map +1 -0
  100. package/dist/src/lease/in-memory-lease-store.js +132 -0
  101. package/dist/src/lease/in-memory-lease-store.js.map +1 -0
  102. package/dist/src/lease/lease-store.d.ts +169 -0
  103. package/dist/src/lease/lease-store.d.ts.map +1 -0
  104. package/dist/src/lease/lease-store.js +94 -0
  105. package/dist/src/lease/lease-store.js.map +1 -0
  106. package/dist/src/lease/lease-store.spec.d.ts +6 -0
  107. package/dist/src/lease/lease-store.spec.d.ts.map +1 -0
  108. package/dist/src/lease/lease-store.spec.js +8 -0
  109. package/dist/src/lease/lease-store.spec.js.map +1 -0
  110. package/dist/src/lease/rack-dispatch.d.ts +105 -0
  111. package/dist/src/lease/rack-dispatch.d.ts.map +1 -0
  112. package/dist/src/lease/rack-dispatch.js +6 -0
  113. package/dist/src/lease/rack-dispatch.js.map +1 -0
  114. package/dist/src/mutation-queue.d.ts +13 -0
  115. package/dist/src/mutation-queue.d.ts.map +1 -0
  116. package/dist/src/mutation-queue.js +17 -0
  117. package/dist/src/mutation-queue.js.map +1 -0
  118. package/dist/src/paths.d.ts +56 -0
  119. package/dist/src/paths.d.ts.map +1 -0
  120. package/dist/src/paths.js +82 -0
  121. package/dist/src/paths.js.map +1 -0
  122. package/dist/src/protocol/control.d.ts +295 -0
  123. package/dist/src/protocol/control.d.ts.map +1 -0
  124. package/dist/src/protocol/control.js +74 -0
  125. package/dist/src/protocol/control.js.map +1 -0
  126. package/dist/src/protocol/index.d.ts +9 -0
  127. package/dist/src/protocol/index.d.ts.map +1 -0
  128. package/dist/src/protocol/index.js +9 -0
  129. package/dist/src/protocol/index.js.map +1 -0
  130. package/dist/src/protocol/rack-wire.d.ts +357 -0
  131. package/dist/src/protocol/rack-wire.d.ts.map +1 -0
  132. package/dist/src/protocol/rack-wire.js +262 -0
  133. package/dist/src/protocol/rack-wire.js.map +1 -0
  134. package/dist/src/protocol/rack-wire.spec.d.ts +6 -0
  135. package/dist/src/protocol/rack-wire.spec.d.ts.map +1 -0
  136. package/dist/src/protocol/rack-wire.spec.js +14 -0
  137. package/dist/src/protocol/rack-wire.spec.js.map +1 -0
  138. package/dist/src/protocol/registration.d.ts +70 -0
  139. package/dist/src/protocol/registration.d.ts.map +1 -0
  140. package/dist/src/protocol/registration.js +67 -0
  141. package/dist/src/protocol/registration.js.map +1 -0
  142. package/dist/src/protocol/session-data.d.ts +69 -0
  143. package/dist/src/protocol/session-data.d.ts.map +1 -0
  144. package/dist/src/protocol/session-data.js +26 -0
  145. package/dist/src/protocol/session-data.js.map +1 -0
  146. package/dist/src/protocol/task-envelope.d.ts +198 -0
  147. package/dist/src/protocol/task-envelope.d.ts.map +1 -0
  148. package/dist/src/protocol/task-envelope.js +93 -0
  149. package/dist/src/protocol/task-envelope.js.map +1 -0
  150. package/dist/src/protocol/wire-golden.d.ts +8 -0
  151. package/dist/src/protocol/wire-golden.d.ts.map +1 -0
  152. package/dist/src/protocol/wire-golden.js +34 -0
  153. package/dist/src/protocol/wire-golden.js.map +1 -0
  154. package/dist/src/protocol/wire-samples.d.ts +11 -0
  155. package/dist/src/protocol/wire-samples.d.ts.map +1 -0
  156. package/dist/src/protocol/wire-samples.js +52 -0
  157. package/dist/src/protocol/wire-samples.js.map +1 -0
  158. package/dist/src/registry/file-rack-registry.d.ts +68 -0
  159. package/dist/src/registry/file-rack-registry.d.ts.map +1 -0
  160. package/dist/src/registry/file-rack-registry.js +138 -0
  161. package/dist/src/registry/file-rack-registry.js.map +1 -0
  162. package/dist/src/registry/file-rack-registry.spec.d.ts +6 -0
  163. package/dist/src/registry/file-rack-registry.spec.d.ts.map +1 -0
  164. package/dist/src/registry/file-rack-registry.spec.js +50 -0
  165. package/dist/src/registry/file-rack-registry.spec.js.map +1 -0
  166. package/dist/src/registry/rack-registry.d.ts +64 -0
  167. package/dist/src/registry/rack-registry.d.ts.map +1 -0
  168. package/dist/src/registry/rack-registry.js +65 -0
  169. package/dist/src/registry/rack-registry.js.map +1 -0
  170. package/dist/src/registry/rack-registry.spec.d.ts +6 -0
  171. package/dist/src/registry/rack-registry.spec.d.ts.map +1 -0
  172. package/dist/src/registry/rack-registry.spec.js +8 -0
  173. package/dist/src/registry/rack-registry.spec.js.map +1 -0
  174. package/dist/src/routing/eligibility.d.ts +38 -0
  175. package/dist/src/routing/eligibility.d.ts.map +1 -0
  176. package/dist/src/routing/eligibility.js +78 -0
  177. package/dist/src/routing/eligibility.js.map +1 -0
  178. package/dist/src/routing/host-coupling.d.ts +26 -0
  179. package/dist/src/routing/host-coupling.d.ts.map +1 -0
  180. package/dist/src/routing/host-coupling.js +62 -0
  181. package/dist/src/routing/host-coupling.js.map +1 -0
  182. package/dist/src/routing/policy.d.ts +188 -0
  183. package/dist/src/routing/policy.d.ts.map +1 -0
  184. package/dist/src/routing/policy.js +212 -0
  185. package/dist/src/routing/policy.js.map +1 -0
  186. package/dist/src/routing/routing.spec.d.ts +6 -0
  187. package/dist/src/routing/routing.spec.d.ts.map +1 -0
  188. package/dist/src/routing/routing.spec.js +100 -0
  189. package/dist/src/routing/routing.spec.js.map +1 -0
  190. package/dist/src/routing/tiers.d.ts +22 -0
  191. package/dist/src/routing/tiers.d.ts.map +1 -0
  192. package/dist/src/routing/tiers.js +26 -0
  193. package/dist/src/routing/tiers.js.map +1 -0
  194. package/dist/src/runner/api-server.d.ts +45 -0
  195. package/dist/src/runner/api-server.d.ts.map +1 -0
  196. package/dist/src/runner/api-server.js +21 -0
  197. package/dist/src/runner/api-server.js.map +1 -0
  198. package/dist/src/runner/capacity.d.ts +13 -0
  199. package/dist/src/runner/capacity.d.ts.map +1 -0
  200. package/dist/src/runner/capacity.js +18 -0
  201. package/dist/src/runner/capacity.js.map +1 -0
  202. package/dist/src/runner/rack-body.d.ts +43 -0
  203. package/dist/src/runner/rack-body.d.ts.map +1 -0
  204. package/dist/src/runner/rack-body.js +208 -0
  205. package/dist/src/runner/rack-body.js.map +1 -0
  206. package/dist/src/runner/rack-runner.d.ts +62 -0
  207. package/dist/src/runner/rack-runner.d.ts.map +1 -0
  208. package/dist/src/runner/rack-runner.js +75 -0
  209. package/dist/src/runner/rack-runner.js.map +1 -0
  210. package/dist/src/runner/rack-runner.spec.d.ts +6 -0
  211. package/dist/src/runner/rack-runner.spec.d.ts.map +1 -0
  212. package/dist/src/runner/rack-runner.spec.js +302 -0
  213. package/dist/src/runner/rack-runner.spec.js.map +1 -0
  214. package/dist/src/runner/split.spec.d.ts +6 -0
  215. package/dist/src/runner/split.spec.d.ts.map +1 -0
  216. package/dist/src/runner/split.spec.js +188 -0
  217. package/dist/src/runner/split.spec.js.map +1 -0
  218. package/dist/src/runner-event.d.ts +261 -0
  219. package/dist/src/runner-event.d.ts.map +1 -0
  220. package/dist/src/runner-event.js +332 -0
  221. package/dist/src/runner-event.js.map +1 -0
  222. package/dist/src/server/beast2.d.ts +19 -0
  223. package/dist/src/server/beast2.d.ts.map +1 -0
  224. package/dist/src/server/beast2.js +18 -0
  225. package/dist/src/server/beast2.js.map +1 -0
  226. package/dist/src/server/body-limit.d.ts +16 -0
  227. package/dist/src/server/body-limit.d.ts.map +1 -0
  228. package/dist/src/server/body-limit.js +53 -0
  229. package/dist/src/server/body-limit.js.map +1 -0
  230. package/dist/src/server/body-limit.spec.d.ts +2 -0
  231. package/dist/src/server/body-limit.spec.d.ts.map +1 -0
  232. package/dist/src/server/body-limit.spec.js +32 -0
  233. package/dist/src/server/body-limit.spec.js.map +1 -0
  234. package/dist/src/server/bounded.d.ts +16 -0
  235. package/dist/src/server/bounded.d.ts.map +1 -0
  236. package/dist/src/server/bounded.js +39 -0
  237. package/dist/src/server/bounded.js.map +1 -0
  238. package/dist/src/server/dispatch.d.ts +137 -0
  239. package/dist/src/server/dispatch.d.ts.map +1 -0
  240. package/dist/src/server/dispatch.js +267 -0
  241. package/dist/src/server/dispatch.js.map +1 -0
  242. package/dist/src/server/env-publication.d.ts +45 -0
  243. package/dist/src/server/env-publication.d.ts.map +1 -0
  244. package/dist/src/server/env-publication.js +10 -0
  245. package/dist/src/server/env-publication.js.map +1 -0
  246. package/dist/src/server/index.d.ts +16 -0
  247. package/dist/src/server/index.d.ts.map +1 -0
  248. package/dist/src/server/index.js +17 -0
  249. package/dist/src/server/index.js.map +1 -0
  250. package/dist/src/server/protocol.spec.d.ts +6 -0
  251. package/dist/src/server/protocol.spec.d.ts.map +1 -0
  252. package/dist/src/server/protocol.spec.js +78 -0
  253. package/dist/src/server/protocol.spec.js.map +1 -0
  254. package/dist/src/server/rack-routes.d.ts +175 -0
  255. package/dist/src/server/rack-routes.d.ts.map +1 -0
  256. package/dist/src/server/rack-routes.js +755 -0
  257. package/dist/src/server/rack-routes.js.map +1 -0
  258. package/dist/src/server/rack-routes.spec.d.ts +6 -0
  259. package/dist/src/server/rack-routes.spec.d.ts.map +1 -0
  260. package/dist/src/server/rack-routes.spec.js +477 -0
  261. package/dist/src/server/rack-routes.spec.js.map +1 -0
  262. package/dist/src/server/storage-bridge.d.ts +140 -0
  263. package/dist/src/server/storage-bridge.d.ts.map +1 -0
  264. package/dist/src/server/storage-bridge.js +6 -0
  265. package/dist/src/server/storage-bridge.js.map +1 -0
  266. package/dist/src/state-file.d.ts +10 -0
  267. package/dist/src/state-file.d.ts.map +1 -0
  268. package/dist/src/state-file.js +38 -0
  269. package/dist/src/state-file.js.map +1 -0
  270. package/dist/src/testing/in-memory.d.ts +116 -0
  271. package/dist/src/testing/in-memory.d.ts.map +1 -0
  272. package/dist/src/testing/in-memory.js +193 -0
  273. package/dist/src/testing/in-memory.js.map +1 -0
  274. package/dist/src/testing/index.d.ts +14 -0
  275. package/dist/src/testing/index.d.ts.map +1 -0
  276. package/dist/src/testing/index.js +14 -0
  277. package/dist/src/testing/index.js.map +1 -0
  278. package/dist/src/testing/lease-store-contract.d.ts +14 -0
  279. package/dist/src/testing/lease-store-contract.d.ts.map +1 -0
  280. package/dist/src/testing/lease-store-contract.js +78 -0
  281. package/dist/src/testing/lease-store-contract.js.map +1 -0
  282. package/dist/src/testing/protocol-suite.d.ts +38 -0
  283. package/dist/src/testing/protocol-suite.d.ts.map +1 -0
  284. package/dist/src/testing/protocol-suite.js +207 -0
  285. package/dist/src/testing/protocol-suite.js.map +1 -0
  286. package/dist/src/testing/rack-registry-contract.d.ts +15 -0
  287. package/dist/src/testing/rack-registry-contract.d.ts.map +1 -0
  288. package/dist/src/testing/rack-registry-contract.js +106 -0
  289. package/dist/src/testing/rack-registry-contract.js.map +1 -0
  290. package/dist/src/testing/test-rack-agent.d.ts +121 -0
  291. package/dist/src/testing/test-rack-agent.d.ts.map +1 -0
  292. package/dist/src/testing/test-rack-agent.js +316 -0
  293. package/dist/src/testing/test-rack-agent.js.map +1 -0
  294. package/dist/src/tls/tls.d.ts +67 -0
  295. package/dist/src/tls/tls.d.ts.map +1 -0
  296. package/dist/src/tls/tls.js +200 -0
  297. package/dist/src/tls/tls.js.map +1 -0
  298. package/dist/src/tls/tls.spec.d.ts +6 -0
  299. package/dist/src/tls/tls.spec.d.ts.map +1 -0
  300. package/dist/src/tls/tls.spec.js +101 -0
  301. package/dist/src/tls/tls.spec.js.map +1 -0
  302. package/dist/src/version.d.ts +9 -0
  303. package/dist/src/version.d.ts.map +1 -0
  304. package/dist/src/version.js +10 -0
  305. package/dist/src/version.js.map +1 -0
  306. package/package.json +67 -7
@@ -0,0 +1,112 @@
1
+ /**
2
+ * Copyright (c) 2025 Elara AI Pty Ltd
3
+ * Licensed under BSL 1.1. See LICENSE for details.
4
+ */
5
+ import { spawn } from 'node:child_process';
6
+ import { open } from 'node:fs/promises';
7
+ import { createRequire } from 'node:module';
8
+ import { join } from 'node:path';
9
+ import { setTimeout as delay } from 'node:timers/promises';
10
+ import { IntegerType, compareFor, printFor } from '@elaraai/east';
11
+ import { ensureRackHome, rackHome, HUB_LOG_FILE } from '../paths.js';
12
+ import { HUB_PROTOCOL } from '../version.js';
13
+ import { HubClient } from './hub-client.js';
14
+ import { RackHubError } from './local-http.js';
15
+ /** Reports a running hub whose protocol cannot serve this e3 release. */
16
+ export class RackHubOutdatedError extends RackHubError {
17
+ /** @param message - The mismatch and how to replace the hub */
18
+ constructor(message) { super('protocol_mismatch', message); this.name = 'RackHubOutdatedError'; }
19
+ }
20
+ /** Reports unavailable rack service; a task runner may safely run locally. */
21
+ export class RackHubUnavailableError extends RackHubError {
22
+ /** @param message - Transport failure and diagnostic log path */
23
+ constructor(message) { super('unavailable', message); this.name = 'RackHubUnavailableError'; }
24
+ }
25
+ /**
26
+ * Spawns a detached hub through this package's published entry point.
27
+ * Several callers may spawn concurrently; the hub lock elects one winner.
28
+ * @param home - Private state home and log destination
29
+ * @returns After the child was spawned and its inherited log descriptor closed
30
+ */
31
+ export async function spawnHub(home = rackHome()) {
32
+ ensureRackHome(home);
33
+ const file = await open(join(home, HUB_LOG_FILE), 'a', 0o600);
34
+ try {
35
+ const main = createRequire(import.meta.url).resolve('@elaraai/e3-rack/hub-main');
36
+ const child = spawn(process.execPath, [main, '--background'], { detached: true, windowsHide: true,
37
+ stdio: ['ignore', file.fd, file.fd], env: { ...process.env, E3_RACK_HOME: home } });
38
+ await new Promise((resolve, reject) => { child.once('spawn', resolve); child.once('error', reject); });
39
+ child.unref();
40
+ }
41
+ finally {
42
+ await file.close();
43
+ }
44
+ }
45
+ /**
46
+ * Finds or starts the shared hub and negotiates its exact control protocol.
47
+ *
48
+ * @remarks
49
+ * This wire has no cross-protocol decoder. A newer protocol is refused too,
50
+ * without draining it. An older hub is asked to drain and the caller runs
51
+ * locally this time. A dead hub is never silently reattached mid-session.
52
+ * @param options - Startup policy, deadline and progress sink
53
+ * @returns A ready typed client
54
+ * @throws {RackHubOutdatedError} On an incompatible control protocol
55
+ * @throws {RackHubUnavailableError} On startup, connection or drain timeout
56
+ * @example
57
+ * const hub = await connectHub({ log: console.log });
58
+ */
59
+ export async function connectHub(options = {}) {
60
+ const home = ensureRackHome(options.home ?? rackHome());
61
+ const timeout = options.timeoutMs ?? 10000;
62
+ if (!Number.isFinite(timeout) || timeout <= 0)
63
+ throw new RangeError('Rack hub timeout must be positive');
64
+ const deadline = Date.now() + timeout;
65
+ const client = new HubClient(home);
66
+ let spawned = false;
67
+ let last = 'hub did not answer';
68
+ while (Date.now() < deadline) {
69
+ if (options.signal?.aborted === true)
70
+ throw new RackHubUnavailableError('Rack hub connection was abandoned: the run was aborted');
71
+ try {
72
+ const hello = await client.hello(Math.max(1, Math.min(1000, deadline - Date.now())));
73
+ const order = compareFor(IntegerType)(hello.protocol, BigInt(HUB_PROTOCOL));
74
+ if (order !== 0) {
75
+ if (order < 0)
76
+ await client.drain();
77
+ throw new RackHubOutdatedError(`The running rack hub (e3 ${hello.version}, protocol ${printFor(IntegerType)(hello.protocol)}) is ${order < 0 ? 'older' : 'newer'} than this e3 (protocol ${HUB_PROTOCOL}). ` +
78
+ (order < 0 ? 'It will exit once idle — run `e3 rack stop` to replace it now.' : 'Use a matching e3 release or stop the hub before replacing it.'));
79
+ }
80
+ if (!hello.draining)
81
+ return client;
82
+ if (options.spawn === false)
83
+ throw new RackHubUnavailableError('The running rack hub is draining');
84
+ last = 'the running rack hub is draining';
85
+ spawned = false;
86
+ }
87
+ catch (err) {
88
+ if (err instanceof RackHubOutdatedError || err instanceof RackHubUnavailableError)
89
+ throw err;
90
+ last = err instanceof Error ? err.message : String(err);
91
+ const absent = err instanceof RackHubError && ['ENOENT', 'ECONNREFUSED', 'EPIPE', 'ECONNRESET'].includes(err.code);
92
+ if (!absent)
93
+ break;
94
+ if (options.spawn === false)
95
+ break;
96
+ if (!spawned) {
97
+ options.log?.('starting rack hub…');
98
+ try {
99
+ await spawnHub(home);
100
+ }
101
+ catch (error) {
102
+ last = error instanceof Error ? error.message : String(error);
103
+ break;
104
+ }
105
+ spawned = true;
106
+ }
107
+ }
108
+ await delay(Math.max(1, Math.min(100, deadline - Date.now())), undefined, { signal: options.signal }).catch(() => { });
109
+ }
110
+ throw new RackHubUnavailableError(`Rack hub unavailable: ${last}. See ${join(home, HUB_LOG_FILE)}`);
111
+ }
112
+ //# sourceMappingURL=connect.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"connect.js","sourceRoot":"","sources":["../../../src/client/connect.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,57 @@
1
+ /**
2
+ * Copyright (c) 2025 Elara AI Pty Ltd
3
+ * Licensed under BSL 1.1. See LICENSE for details.
4
+ */
5
+ import { type ValueTypeOf } from '@elaraai/east';
6
+ import { AttachLeaseResultType, CancelLeaseResultType, CreateLeaseResultType, HubEnrollResultType, HubEnrollType, HubHelloType, HubStatusType, OpenSessionResultType, RemoveRackResultType, SessionPollResultType, type CreateLease, type HubConfig, type OpenSession } from '../protocol/control.js';
7
+ import { RackRegistrationType, type RackSecurityPolicy } from '../protocol/registration.js';
8
+ /**
9
+ * Calls the typed control API of the single user-wide hub.
10
+ * Use connectHub to discover/start the process and negotiate its protocol.
11
+ * @example
12
+ * const client = new HubClient();
13
+ * console.log(await client.status());
14
+ */
15
+ export declare class HubClient {
16
+ readonly home: string;
17
+ /** Private control socket or Windows pipe. */
18
+ readonly socketPath: string;
19
+ /** @param home - The shared state home whose hub to call */
20
+ constructor(home?: string);
21
+ /** Reads the fixed version handshake within the caller's startup deadline. */
22
+ hello(timeoutMs?: number): Promise<ValueTypeOf<typeof HubHelloType>>;
23
+ /** Reads listener readiness, attached sessions and fleet capacity. */
24
+ status(): Promise<ValueTypeOf<typeof HubStatusType>>;
25
+ /** Mints a one-time enrollment token for the configured private-network listener. */
26
+ enroll(request?: ValueTypeOf<typeof HubEnrollType>): Promise<ValueTypeOf<typeof HubEnrollResultType>>;
27
+ /** Revokes an enrolled rack and ends work it still holds. */
28
+ removeRack(id: string): Promise<ValueTypeOf<typeof RemoveRackResultType>>;
29
+ /** Approves exactly the boot the operator inspected; refuses a newer reboot. */
30
+ approveRack(id: string, bootId: string): Promise<ValueTypeOf<typeof RackRegistrationType>>;
31
+ /** Reads whether a rack's boots after its first need approval before it is leased work. */
32
+ getSecurityPolicy(): Promise<RackSecurityPolicy>;
33
+ /** Sets whether a rack's boots after its first need approval; a rack already admitted keeps its approved boot. */
34
+ setSecurityPolicy(policy: RackSecurityPolicy): Promise<RackSecurityPolicy>;
35
+ /** Reads the effective hub configuration. */
36
+ getConfig(): Promise<HubConfig>;
37
+ /** Persists configuration and rebinds a changed rack listener. */
38
+ setConfig(config: HubConfig): Promise<HubConfig>;
39
+ /** Refuses new sessions and exits after existing sessions finish. */
40
+ drain(): Promise<void>;
41
+ /** Cancels active work and gracefully exits the hub. */
42
+ stop(): Promise<void>;
43
+ /** Registers a live repository data endpoint; RackSession owns its lifecycle. */
44
+ openSession(request: OpenSession): Promise<ValueTypeOf<typeof OpenSessionResultType>>;
45
+ /** Ends a session, transferring shared leases before its data endpoint closes. */
46
+ closeSession(id: string): Promise<void>;
47
+ /** Submits or attaches to a task/unit lease of the session's repository. */
48
+ createLease(id: string, request: CreateLease): Promise<ValueTypeOf<typeof CreateLeaseResultType>>;
49
+ /** Attaches to identical work already queued or held, or answers none; it queues nothing. */
50
+ attachLease(id: string, request: CreateLease): Promise<ValueTypeOf<typeof AttachLeaseResultType>>;
51
+ /** Unsubscribes one session; only its final subscription cancels the lease. */
52
+ cancelLease(id: string, leaseId: string): Promise<ValueTypeOf<typeof CancelLeaseResultType>>;
53
+ /** Polls ordered updates and refreshes the session's liveness. */
54
+ events(id: string, after: bigint, waitMs?: number, signal?: AbortSignal): Promise<ValueTypeOf<typeof SessionPollResultType>>;
55
+ private path;
56
+ }
57
+ //# sourceMappingURL=hub-client.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"hub-client.d.ts","sourceRoot":"","sources":["../../../src/client/hub-client.ts"],"names":[],"mappings":"AAAA;;;GAGG;AAEH,OAAO,EAAQ,KAAK,WAAW,EAAE,MAAM,eAAe,CAAC;AAEvD,OAAO,EAAmB,qBAAqB,EAAE,qBAAqB,EAAE,qBAAqB,EAC5E,mBAAmB,EAAE,aAAa,EAAE,YAAY,EAAE,aAAa,EAAE,qBAAqB,EACrG,oBAAoB,EAAE,qBAAqB,EAAmB,KAAK,WAAW,EAAE,KAAK,SAAS,EAAE,KAAK,WAAW,EAAE,MAAM,wBAAwB,CAAC;AACnJ,OAAO,EAAE,oBAAoB,EAA0B,KAAK,kBAAkB,EAAE,MAAM,6BAA6B,CAAC;AAGpH;;;;;;GAMG;AACH,qBAAa,SAAS;IAIR,QAAQ,CAAC,IAAI;IAHzB,8CAA8C;IAC9C,QAAQ,CAAC,UAAU,EAAE,MAAM,CAAC;IAC5B,4DAA4D;gBACvC,IAAI,SAAa;IAEtC,8EAA8E;IAC9E,KAAK,CAAC,SAAS,SAAQ,GAAG,OAAO,CAAC,WAAW,CAAC,OAAO,YAAY,CAAC,CAAC;IAGnE,sEAAsE;IACtE,MAAM,IAAI,OAAO,CAAC,WAAW,CAAC,OAAO,aAAa,CAAC,CAAC;IACpD,qFAAqF;IACrF,MAAM,CAAC,OAAO,GAAE,WAAW,CAAC,OAAO,aAAa,CAAqC,GAAG,OAAO,CAAC,WAAW,CAAC,OAAO,mBAAmB,CAAC,CAAC;IAGxI,6DAA6D;IAC7D,UAAU,CAAC,EAAE,EAAE,MAAM,GAAG,OAAO,CAAC,WAAW,CAAC,OAAO,oBAAoB,CAAC,CAAC;IAGzE,gFAAgF;IAChF,WAAW,CAAC,EAAE,EAAE,MAAM,EAAE,MAAM,EAAE,MAAM,GAAG,OAAO,CAAC,WAAW,CAAC,OAAO,oBAAoB,CAAC,CAAC;IAG1F,2FAA2F;IAC3F,iBAAiB,IAAI,OAAO,CAAC,kBAAkB,CAAC;IAGhD,kHAAkH;IAClH,iBAAiB,CAAC,MAAM,EAAE,kBAAkB,GAAG,OAAO,CAAC,kBAAkB,CAAC;IAG1E,6CAA6C;IAC7C,SAAS,IAAI,OAAO,CAAC,SAAS,CAAC;IAC/B,kEAAkE;IAClE,SAAS,CAAC,MAAM,EAAE,SAAS,GAAG,OAAO,CAAC,SAAS,CAAC;IAGhD,qEAAqE;IAC/D,KAAK,IAAI,OAAO,CAAC,IAAI,CAAC;IAC5B,wDAAwD;IAClD,IAAI,IAAI,OAAO,CAAC,IAAI,CAAC;IAC3B,iFAAiF;IACjF,WAAW,CAAC,OAAO,EAAE,WAAW,GAAG,OAAO,CAAC,WAAW,CAAC,OAAO,qBAAqB,CAAC,CAAC;IAGrF,kFAAkF;IAC5E,YAAY,CAAC,EAAE,EAAE,MAAM,GAAG,OAAO,CAAC,IAAI,CAAC;IAC7C,4EAA4E;IAC5E,WAAW,CAAC,EAAE,EAAE,MAAM,EAAE,OAAO,EAAE,WAAW,GAAG,OAAO,CAAC,WAAW,CAAC,OAAO,qBAAqB,CAAC,CAAC;IAGjG,6FAA6F;IAC7F,WAAW,CAAC,EAAE,EAAE,MAAM,EAAE,OAAO,EAAE,WAAW,GAAG,OAAO,CAAC,WAAW,CAAC,OAAO,qBAAqB,CAAC,CAAC;IAGjG,+EAA+E;IAC/E,WAAW,CAAC,EAAE,EAAE,MAAM,EAAE,OAAO,EAAE,MAAM,GAAG,OAAO,CAAC,WAAW,CAAC,OAAO,qBAAqB,CAAC,CAAC;IAG5F,kEAAkE;IAClE,MAAM,CAAC,EAAE,EAAE,MAAM,EAAE,KAAK,EAAE,MAAM,EAAE,MAAM,SAAQ,EAAE,MAAM,CAAC,EAAE,WAAW,GAAG,OAAO,CAAC,WAAW,CAAC,OAAO,qBAAqB,CAAC,CAAC;IAI3H,OAAO,CAAC,IAAI;CACb"}
@@ -0,0 +1,87 @@
1
+ /**
2
+ * Copyright (c) 2025 Elara AI Pty Ltd
3
+ * Licensed under BSL 1.1. See LICENSE for details.
4
+ */
5
+ import { none } from '@elaraai/east';
6
+ import { hubSocketPath, rackHome } from '../paths.js';
7
+ import { ApproveRackType, AttachLeaseResultType, CancelLeaseResultType, CreateLeaseResultType, CreateLeaseType, EmptyType, HubConfigType, HubEnrollResultType, HubEnrollType, HubHelloType, HubStatusType, OpenSessionResultType, OpenSessionType, RemoveRackResultType, SessionPollResultType, SessionPollType } from '../protocol/control.js';
8
+ import { RackRegistrationType, RackSecurityPolicyType } from '../protocol/registration.js';
9
+ import { socketRequest } from './local-http.js';
10
+ /**
11
+ * Calls the typed control API of the single user-wide hub.
12
+ * Use connectHub to discover/start the process and negotiate its protocol.
13
+ * @example
14
+ * const client = new HubClient();
15
+ * console.log(await client.status());
16
+ */
17
+ export class HubClient {
18
+ home;
19
+ /** Private control socket or Windows pipe. */
20
+ socketPath;
21
+ /** @param home - The shared state home whose hub to call */
22
+ constructor(home = rackHome()) {
23
+ this.home = home;
24
+ this.socketPath = hubSocketPath(home);
25
+ }
26
+ /** Reads the fixed version handshake within the caller's startup deadline. */
27
+ hello(timeoutMs = 30000) {
28
+ return socketRequest(this.socketPath, 'POST', '/v1/hello', { responseType: HubHelloType, timeoutMs });
29
+ }
30
+ /** Reads listener readiness, attached sessions and fleet capacity. */
31
+ status() { return socketRequest(this.socketPath, 'GET', '/v1/status', { responseType: HubStatusType }); }
32
+ /** Mints a one-time enrollment token for the configured private-network listener. */
33
+ enroll(request = { label: none, ttlMinutes: none }) {
34
+ return socketRequest(this.socketPath, 'POST', '/v1/enroll', { requestType: HubEnrollType, body: request, responseType: HubEnrollResultType });
35
+ }
36
+ /** Revokes an enrolled rack and ends work it still holds. */
37
+ removeRack(id) {
38
+ return socketRequest(this.socketPath, 'DELETE', `/v1/racks/${encodeURIComponent(id)}`, { responseType: RemoveRackResultType });
39
+ }
40
+ /** Approves exactly the boot the operator inspected; refuses a newer reboot. */
41
+ approveRack(id, bootId) {
42
+ return socketRequest(this.socketPath, 'POST', `/v1/racks/${encodeURIComponent(id)}/approve`, { requestType: ApproveRackType, body: { bootId }, responseType: RackRegistrationType });
43
+ }
44
+ /** Reads whether a rack's boots after its first need approval before it is leased work. */
45
+ getSecurityPolicy() {
46
+ return socketRequest(this.socketPath, 'GET', '/v1/security', { responseType: RackSecurityPolicyType });
47
+ }
48
+ /** Sets whether a rack's boots after its first need approval; a rack already admitted keeps its approved boot. */
49
+ setSecurityPolicy(policy) {
50
+ return socketRequest(this.socketPath, 'POST', '/v1/security', { requestType: RackSecurityPolicyType, body: policy, responseType: RackSecurityPolicyType });
51
+ }
52
+ /** Reads the effective hub configuration. */
53
+ getConfig() { return socketRequest(this.socketPath, 'GET', '/v1/config', { responseType: HubConfigType }); }
54
+ /** Persists configuration and rebinds a changed rack listener. */
55
+ setConfig(config) {
56
+ return socketRequest(this.socketPath, 'POST', '/v1/config', { requestType: HubConfigType, body: config, responseType: HubConfigType });
57
+ }
58
+ /** Refuses new sessions and exits after existing sessions finish. */
59
+ async drain() { await socketRequest(this.socketPath, 'POST', '/v1/drain', { responseType: EmptyType }); }
60
+ /** Cancels active work and gracefully exits the hub. */
61
+ async stop() { await socketRequest(this.socketPath, 'POST', '/v1/stop', { responseType: EmptyType }); }
62
+ /** Registers a live repository data endpoint; RackSession owns its lifecycle. */
63
+ openSession(request) {
64
+ return socketRequest(this.socketPath, 'POST', '/v1/sessions', { requestType: OpenSessionType, body: request, responseType: OpenSessionResultType });
65
+ }
66
+ /** Ends a session, transferring shared leases before its data endpoint closes. */
67
+ async closeSession(id) { await socketRequest(this.socketPath, 'DELETE', this.path(id), { responseType: EmptyType }); }
68
+ /** Submits or attaches to a task/unit lease of the session's repository. */
69
+ createLease(id, request) {
70
+ return socketRequest(this.socketPath, 'POST', `${this.path(id)}/leases`, { requestType: CreateLeaseType, body: request, responseType: CreateLeaseResultType });
71
+ }
72
+ /** Attaches to identical work already queued or held, or answers none; it queues nothing. */
73
+ attachLease(id, request) {
74
+ return socketRequest(this.socketPath, 'POST', `${this.path(id)}/leases/attach`, { requestType: CreateLeaseType, body: request, responseType: AttachLeaseResultType });
75
+ }
76
+ /** Unsubscribes one session; only its final subscription cancels the lease. */
77
+ cancelLease(id, leaseId) {
78
+ return socketRequest(this.socketPath, 'POST', `${this.path(id)}/leases/${encodeURIComponent(leaseId)}/cancel`, { responseType: CancelLeaseResultType });
79
+ }
80
+ /** Polls ordered updates and refreshes the session's liveness. */
81
+ events(id, after, waitMs = 20000, signal) {
82
+ return socketRequest(this.socketPath, 'POST', `${this.path(id)}/events`, { requestType: SessionPollType,
83
+ body: { after, waitMs: BigInt(waitMs) }, responseType: SessionPollResultType, timeoutMs: 25000, signal });
84
+ }
85
+ path(id) { return `/v1/sessions/${encodeURIComponent(id)}`; }
86
+ }
87
+ //# sourceMappingURL=hub-client.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"hub-client.js","sourceRoot":"","sources":["../../../src/client/hub-client.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,78 @@
1
+ /**
2
+ * Copyright (c) 2025 Elara AI Pty Ltd
3
+ * Licensed under BSL 1.1. See LICENSE for details.
4
+ */
5
+ import { Server, type IncomingMessage } from 'node:http';
6
+ import type { Server as HttpsServer } from 'node:https';
7
+ import { Readable } from 'node:stream';
8
+ import { type EastType, type ValueTypeOf } from '@elaraai/east';
9
+ import type { Hono } from 'hono';
10
+ /** Reports a control/data transport error without losing its machine-readable cause. */
11
+ export declare class RackHubError extends Error {
12
+ readonly code: string;
13
+ /** @param code - HTTP, protocol or system error code @param message - Actionable explanation */
14
+ constructor(code: string, message: string);
15
+ }
16
+ /** Options shared by typed requests and streamed object transfers. */
17
+ export interface SocketRequestOptions {
18
+ /** Private session credential. */
19
+ bearer?: string;
20
+ /** Whole-request deadline, including response streaming; defaults to 30 seconds. */
21
+ timeoutMs?: number;
22
+ /** Cancels connection, upload and response. */
23
+ signal?: AbortSignal;
24
+ /** Raw object bytes; never encoded in a BEAST2 envelope. */
25
+ rawBody?: Uint8Array | Readable;
26
+ /** Additional HTTP headers for streamed objects. */
27
+ headers?: Record<string, string>;
28
+ }
29
+ /**
30
+ * How long a listener lets a request's body take to arrive: a data URL's whole
31
+ * fifteen minutes, with a minute to spare. Node's default, five minutes, would
32
+ * cut a large upload over a slow link short of the time its URL grants.
33
+ */
34
+ export declare const REQUEST_BODY_TIMEOUT_MS: number;
35
+ /**
36
+ * Starts an HTTP listener on a private Unix socket or Windows named pipe.
37
+ * The caller must hold ownership before removing any stale socket.
38
+ * @param app - Local HTTP application
39
+ * @param path - Socket or pipe
40
+ * @returns The listening server
41
+ * @example
42
+ * const server = await serveOnSocket(app, socketPath);
43
+ */
44
+ export declare function serveOnSocket(app: Hono, path: string): Promise<Server>;
45
+ /**
46
+ * Closes a listener, allowing up to five seconds for active requests.
47
+ * @param server - Owned listener
48
+ * @param socket - Owned socket to remove after closing
49
+ * @returns Completion of shutdown
50
+ */
51
+ export declare function closeSocketServer(server: Server | HttpsServer, socket?: string): Promise<void>;
52
+ /**
53
+ * Streams a local HTTP response with an absolute, abortable deadline.
54
+ * @param socketPath - Unix socket or Windows pipe
55
+ * @param method - HTTP verb
56
+ * @param path - Request path
57
+ * @param options - Credentials, input stream and deadline
58
+ * @returns The raw response; callers consume or destroy it
59
+ * @throws {RackHubError} On timeout or connection failure
60
+ */
61
+ export declare function socketStream(socketPath: string, method: string, path: string, options?: SocketRequestOptions): Promise<IncomingMessage>;
62
+ /**
63
+ * Sends a BEAST2 control message and decodes its standard response envelope.
64
+ * @param socketPath - Unix socket or Windows pipe
65
+ * @param method - HTTP verb
66
+ * @param path - Control route
67
+ * @param options - Request/response schemas, value and transport settings
68
+ * @returns The decoded success value
69
+ * @throws {RackHubError} On an error envelope, HTTP error or deadline
70
+ * @example
71
+ * const hello = await socketRequest(socket, 'POST', '/v1/hello', { responseType: HubHelloType });
72
+ */
73
+ export declare function socketRequest<Req extends EastType, Res extends EastType>(socketPath: string, method: string, path: string, options: SocketRequestOptions & {
74
+ requestType?: Req;
75
+ body?: ValueTypeOf<Req>;
76
+ responseType: Res;
77
+ }): Promise<ValueTypeOf<Res>>;
78
+ //# sourceMappingURL=local-http.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"local-http.d.ts","sourceRoot":"","sources":["../../../src/client/local-http.ts"],"names":[],"mappings":"AAAA;;;GAGG;AAGH,OAAO,EAAW,MAAM,EAAE,KAAK,eAAe,EAAE,MAAM,WAAW,CAAC;AAClE,OAAO,KAAK,EAAE,MAAM,IAAI,WAAW,EAAE,MAAM,YAAY,CAAC;AACxD,OAAO,EAAE,QAAQ,EAAE,MAAM,aAAa,CAAC;AAGvC,OAAO,EAA8C,KAAK,QAAQ,EAAE,KAAK,WAAW,EAAE,MAAM,eAAe,CAAC;AAE5G,OAAO,KAAK,EAAE,IAAI,EAAE,MAAM,MAAM,CAAC;AAEjC,wFAAwF;AACxF,qBAAa,YAAa,SAAQ,KAAK;IAEzB,QAAQ,CAAC,IAAI,EAAE,MAAM;IADjC,gGAAgG;gBAC3E,IAAI,EAAE,MAAM,EAAE,OAAO,EAAE,MAAM;CACnD;AAED,sEAAsE;AACtE,MAAM,WAAW,oBAAoB;IACnC,kCAAkC;IAClC,MAAM,CAAC,EAAE,MAAM,CAAC;IAChB,oFAAoF;IACpF,SAAS,CAAC,EAAE,MAAM,CAAC;IACnB,+CAA+C;IAC/C,MAAM,CAAC,EAAE,WAAW,CAAC;IACrB,4DAA4D;IAC5D,OAAO,CAAC,EAAE,UAAU,GAAG,QAAQ,CAAC;IAChC,oDAAoD;IACpD,OAAO,CAAC,EAAE,MAAM,CAAC,MAAM,EAAE,MAAM,CAAC,CAAC;CAClC;AAED;;;;GAIG;AACH,eAAO,MAAM,uBAAuB,QAAc,CAAC;AAEnD;;;;;;;;GAQG;AACH,wBAAsB,aAAa,CAAC,GAAG,EAAE,IAAI,EAAE,IAAI,EAAE,MAAM,GAAG,OAAO,CAAC,MAAM,CAAC,CAc5E;AAED;;;;;GAKG;AACH,wBAAsB,iBAAiB,CAAC,MAAM,EAAE,MAAM,GAAG,WAAW,EAAE,MAAM,CAAC,EAAE,MAAM,GAAG,OAAO,CAAC,IAAI,CAAC,CASpG;AAED;;;;;;;;GAQG;AACH,wBAAgB,YAAY,CAAC,UAAU,EAAE,MAAM,EAAE,MAAM,EAAE,MAAM,EAAE,IAAI,EAAE,MAAM,EAAE,OAAO,GAAE,oBAAyB,GAAG,OAAO,CAAC,eAAe,CAAC,CAsB3I;AAED;;;;;;;;;;GAUG;AACH,wBAAsB,aAAa,CAAC,GAAG,SAAS,QAAQ,EAAE,GAAG,SAAS,QAAQ,EAC5E,UAAU,EAAE,MAAM,EAAE,MAAM,EAAE,MAAM,EAAE,IAAI,EAAE,MAAM,EAChD,OAAO,EAAE,oBAAoB,GAAG;IAAE,WAAW,CAAC,EAAE,GAAG,CAAC;IAAC,IAAI,CAAC,EAAE,WAAW,CAAC,GAAG,CAAC,CAAC;IAAC,YAAY,EAAE,GAAG,CAAA;CAAE,GAChG,OAAO,CAAC,WAAW,CAAC,GAAG,CAAC,CAAC,CAoB3B"}
@@ -0,0 +1,149 @@
1
+ /**
2
+ * Copyright (c) 2025 Elara AI Pty Ltd
3
+ * Licensed under BSL 1.1. See LICENSE for details.
4
+ */
5
+ import { chmod, unlink } from 'node:fs/promises';
6
+ import { request, Server } from 'node:http';
7
+ import { Readable } from 'node:stream';
8
+ import { pipeline } from 'node:stream/promises';
9
+ import { createAdaptorServer } from '@hono/node-server';
10
+ import { decodeBeast2For, encodeBeast2For, printFor } from '@elaraai/east';
11
+ import { BEAST2_CONTENT_TYPE, ErrorType, ResponseType } from '@elaraai/e3-types';
12
+ /** Reports a control/data transport error without losing its machine-readable cause. */
13
+ export class RackHubError extends Error {
14
+ code;
15
+ /** @param code - HTTP, protocol or system error code @param message - Actionable explanation */
16
+ constructor(code, message) {
17
+ super(message);
18
+ this.code = code;
19
+ this.name = 'RackHubError';
20
+ }
21
+ }
22
+ /**
23
+ * How long a listener lets a request's body take to arrive: a data URL's whole
24
+ * fifteen minutes, with a minute to spare. Node's default, five minutes, would
25
+ * cut a large upload over a slow link short of the time its URL grants.
26
+ */
27
+ export const REQUEST_BODY_TIMEOUT_MS = 16 * 60_000;
28
+ /**
29
+ * Starts an HTTP listener on a private Unix socket or Windows named pipe.
30
+ * The caller must hold ownership before removing any stale socket.
31
+ * @param app - Local HTTP application
32
+ * @param path - Socket or pipe
33
+ * @returns The listening server
34
+ * @example
35
+ * const server = await serveOnSocket(app, socketPath);
36
+ */
37
+ export async function serveOnSocket(app, path) {
38
+ const server = createAdaptorServer({ fetch: app.fetch, serverOptions: { requestTimeout: REQUEST_BODY_TIMEOUT_MS } });
39
+ if (!(server instanceof Server))
40
+ throw new Error('Local rack transport requires HTTP/1');
41
+ try {
42
+ await new Promise((resolve, reject) => {
43
+ server.once('error', reject);
44
+ server.listen(path, () => { server.off('error', reject); resolve(); });
45
+ });
46
+ if (process.platform !== 'win32')
47
+ await chmod(path, 0o600);
48
+ return server;
49
+ }
50
+ catch (err) {
51
+ server.close();
52
+ throw err;
53
+ }
54
+ }
55
+ /**
56
+ * Closes a listener, allowing up to five seconds for active requests.
57
+ * @param server - Owned listener
58
+ * @param socket - Owned socket to remove after closing
59
+ * @returns Completion of shutdown
60
+ */
61
+ export async function closeSocketServer(server, socket) {
62
+ await new Promise((resolve, reject) => {
63
+ const timer = setTimeout(() => server.closeAllConnections(), 5000);
64
+ timer.unref();
65
+ server.close((error) => { clearTimeout(timer); if (error)
66
+ reject(error);
67
+ else
68
+ resolve(); });
69
+ });
70
+ if (socket !== undefined && process.platform !== 'win32') {
71
+ await unlink(socket).catch((err) => { if (err.code !== 'ENOENT')
72
+ throw err; });
73
+ }
74
+ }
75
+ /**
76
+ * Streams a local HTTP response with an absolute, abortable deadline.
77
+ * @param socketPath - Unix socket or Windows pipe
78
+ * @param method - HTTP verb
79
+ * @param path - Request path
80
+ * @param options - Credentials, input stream and deadline
81
+ * @returns The raw response; callers consume or destroy it
82
+ * @throws {RackHubError} On timeout or connection failure
83
+ */
84
+ export function socketStream(socketPath, method, path, options = {}) {
85
+ return new Promise((resolve, reject) => {
86
+ const headers = { ...options.headers, ...(options.bearer === undefined ? {} : { authorization: `Bearer ${options.bearer}` }) };
87
+ const req = request({ socketPath, method, path, headers });
88
+ const fail = (err) => { req.destroy(err); if (options.rawBody instanceof Readable)
89
+ options.rawBody.destroy(err); };
90
+ const timer = setTimeout(() => fail(new RackHubError('timeout', `Rack request ${method} ${path} timed out`)), options.timeoutMs ?? 30_000);
91
+ timer.unref();
92
+ const abort = () => fail(new RackHubError('aborted', `Rack request ${method} ${path} was aborted`));
93
+ const cleanup = () => { clearTimeout(timer); options.signal?.removeEventListener('abort', abort); };
94
+ req.once('error', (err) => { cleanup(); reject(err instanceof RackHubError ? err : new RackHubError(err.code ?? 'transport', err.message)); });
95
+ req.once('response', (response) => {
96
+ response.once('close', cleanup);
97
+ response.once('error', () => { }); // a destroyed response remains observable by its consumer
98
+ resolve(response);
99
+ });
100
+ // Observe source errors before an already-aborted signal can destroy it.
101
+ // Without the pipeline, destroy(error) emits an unhandled stream error.
102
+ if (options.rawBody instanceof Readable)
103
+ void pipeline(options.rawBody, req).catch(fail);
104
+ options.signal?.addEventListener('abort', abort, { once: true });
105
+ if (options.signal?.aborted) {
106
+ abort();
107
+ return;
108
+ }
109
+ if (!(options.rawBody instanceof Readable))
110
+ req.end(options.rawBody);
111
+ });
112
+ }
113
+ /**
114
+ * Sends a BEAST2 control message and decodes its standard response envelope.
115
+ * @param socketPath - Unix socket or Windows pipe
116
+ * @param method - HTTP verb
117
+ * @param path - Control route
118
+ * @param options - Request/response schemas, value and transport settings
119
+ * @returns The decoded success value
120
+ * @throws {RackHubError} On an error envelope, HTTP error or deadline
121
+ * @example
122
+ * const hello = await socketRequest(socket, 'POST', '/v1/hello', { responseType: HubHelloType });
123
+ */
124
+ export async function socketRequest(socketPath, method, path, options) {
125
+ const rawBody = options.requestType === undefined ? options.rawBody : encodeBeast2For(options.requestType)(options.body);
126
+ const response = await socketStream(socketPath, method, path, { ...options, rawBody,
127
+ headers: { ...options.headers, 'content-type': BEAST2_CONTENT_TYPE } });
128
+ const chunks = [];
129
+ let size = 0;
130
+ for await (const chunk of response) {
131
+ const bytes = Buffer.isBuffer(chunk) ? chunk : Buffer.from(chunk);
132
+ size += bytes.length;
133
+ if (size > 16 * 1024 * 1024) {
134
+ response.destroy();
135
+ throw new RackHubError('too_large', 'Rack control response exceeds 16 MiB');
136
+ }
137
+ chunks.push(bytes);
138
+ }
139
+ if ((response.statusCode ?? 500) >= 300) {
140
+ // The hub answers a refusal in plain text: the reason is the message.
141
+ const text = String(response.headers['content-type']).startsWith('text/plain') ? Buffer.concat(chunks).toString('utf8').trim() : '';
142
+ throw new RackHubError(`http_${response.statusCode}`, text !== '' && text.length <= 2000 ? text : `Rack request ${path}: HTTP ${response.statusCode}`);
143
+ }
144
+ const envelope = decodeBeast2For(ResponseType(options.responseType))(Buffer.concat(chunks));
145
+ if (envelope.type === 'error')
146
+ throw new RackHubError(envelope.value.type, printFor(ErrorType)(envelope.value));
147
+ return envelope.value;
148
+ }
149
+ //# sourceMappingURL=local-http.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"local-http.js","sourceRoot":"","sources":["../../../src/client/local-http.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,20 @@
1
+ /**
2
+ * Copyright (c) 2025 Elara AI Pty Ltd
3
+ * Licensed under BSL 1.1. See LICENSE for details.
4
+ */
5
+ import { type StorageBackend } from '@elaraai/e3-core';
6
+ import type { ExecutionOwner } from '@elaraai/e3-types';
7
+ import type { RackAttemptStore } from '../server/rack-routes.js';
8
+ /**
9
+ * Writes rack attempt records with the session's own repository formats.
10
+ * The hub serializes the calls and names itself as the process owner, so
11
+ * another session can take over without an owner-death probe ending the work.
12
+ * @param storage - Session storage backend
13
+ * @param repo - Repository path known only to the session
14
+ * @param owner - Resolves the hub's process identity
15
+ * @returns The current repository's attempt adapter
16
+ * @example
17
+ * const attempts = sessionAttempts(storage, repo, () => hubOwner);
18
+ */
19
+ export declare function sessionAttempts(storage: StorageBackend, repo: string, owner: () => ExecutionOwner): RackAttemptStore;
20
+ //# sourceMappingURL=session-attempts.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"session-attempts.d.ts","sourceRoot":"","sources":["../../../src/client/session-attempts.ts"],"names":[],"mappings":"AAAA;;;GAGG;AAGH,OAAO,EAAoC,KAAK,cAAc,EAAE,MAAM,kBAAkB,CAAC;AACzF,OAAO,KAAK,EAAE,cAAc,EAAE,MAAM,mBAAmB,CAAC;AAIxD,OAAO,KAAK,EAAE,gBAAgB,EAAE,MAAM,0BAA0B,CAAC;AAEjE;;;;;;;;;;GAUG;AACH,wBAAgB,eAAe,CAAC,OAAO,EAAE,cAAc,EAAE,IAAI,EAAE,MAAM,EAAE,KAAK,EAAE,MAAM,cAAc,GAAG,gBAAgB,CAqDpH"}