arc402-cli 0.9.18 → 0.10.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 (358) hide show
  1. package/README.md +41 -2
  2. package/dist/abis.d.ts +1 -0
  3. package/dist/abis.d.ts.map +1 -1
  4. package/dist/abis.js +45 -14
  5. package/dist/abis.js.map +1 -1
  6. package/dist/bundler.d.ts +1 -1
  7. package/dist/bundler.d.ts.map +1 -1
  8. package/dist/bundler.js +61 -27
  9. package/dist/bundler.js.map +1 -1
  10. package/dist/client.d.ts +1 -1
  11. package/dist/client.d.ts.map +1 -1
  12. package/dist/client.js +9 -5
  13. package/dist/client.js.map +1 -1
  14. package/dist/coinbase-smart-wallet.js +4 -1
  15. package/dist/coinbase-smart-wallet.js.map +1 -1
  16. package/dist/commands/accept.js +28 -25
  17. package/dist/commands/accept.js.map +1 -1
  18. package/dist/commands/agent-handshake.js +18 -15
  19. package/dist/commands/agent-handshake.js.map +1 -1
  20. package/dist/commands/agent.js +104 -98
  21. package/dist/commands/agent.js.map +1 -1
  22. package/dist/commands/agreements.js +98 -62
  23. package/dist/commands/agreements.js.map +1 -1
  24. package/dist/commands/arbitrator.js +81 -45
  25. package/dist/commands/arbitrator.js.map +1 -1
  26. package/dist/commands/arena-handshake.d.ts.map +1 -1
  27. package/dist/commands/arena-handshake.js +35 -53
  28. package/dist/commands/arena-handshake.js.map +1 -1
  29. package/dist/commands/arena.js +18 -12
  30. package/dist/commands/arena.js.map +1 -1
  31. package/dist/commands/backup.js +36 -30
  32. package/dist/commands/backup.js.map +1 -1
  33. package/dist/commands/cancel.js +18 -15
  34. package/dist/commands/cancel.js.map +1 -1
  35. package/dist/commands/channel.js +81 -45
  36. package/dist/commands/channel.js.map +1 -1
  37. package/dist/commands/coldstart.js +34 -31
  38. package/dist/commands/coldstart.js.map +1 -1
  39. package/dist/commands/compute.d.ts +14 -0
  40. package/dist/commands/compute.d.ts.map +1 -0
  41. package/dist/commands/compute.js +466 -0
  42. package/dist/commands/compute.js.map +1 -0
  43. package/dist/commands/config.js +30 -24
  44. package/dist/commands/config.js.map +1 -1
  45. package/dist/commands/contract-interaction.js +15 -12
  46. package/dist/commands/contract-interaction.js.map +1 -1
  47. package/dist/commands/daemon.d.ts.map +1 -1
  48. package/dist/commands/daemon.js +135 -98
  49. package/dist/commands/daemon.js.map +1 -1
  50. package/dist/commands/deliver.js +76 -37
  51. package/dist/commands/deliver.js.map +1 -1
  52. package/dist/commands/discover.js +27 -24
  53. package/dist/commands/discover.js.map +1 -1
  54. package/dist/commands/dispute.js +110 -104
  55. package/dist/commands/dispute.js.map +1 -1
  56. package/dist/commands/doctor.js +55 -16
  57. package/dist/commands/doctor.js.map +1 -1
  58. package/dist/commands/endpoint.js +95 -56
  59. package/dist/commands/endpoint.js.map +1 -1
  60. package/dist/commands/feed.js +18 -11
  61. package/dist/commands/feed.js.map +1 -1
  62. package/dist/commands/hire.js +40 -37
  63. package/dist/commands/hire.js.map +1 -1
  64. package/dist/commands/migrate.js +33 -30
  65. package/dist/commands/migrate.js.map +1 -1
  66. package/dist/commands/negotiate.d.ts.map +1 -1
  67. package/dist/commands/negotiate.js +36 -34
  68. package/dist/commands/negotiate.js.map +1 -1
  69. package/dist/commands/openshell.js +104 -68
  70. package/dist/commands/openshell.js.map +1 -1
  71. package/dist/commands/owner.js +20 -17
  72. package/dist/commands/owner.js.map +1 -1
  73. package/dist/commands/policy.js +43 -41
  74. package/dist/commands/policy.js.map +1 -1
  75. package/dist/commands/relay.d.ts.map +1 -1
  76. package/dist/commands/relay.js +51 -18
  77. package/dist/commands/relay.js.map +1 -1
  78. package/dist/commands/remediate.js +23 -20
  79. package/dist/commands/remediate.js.map +1 -1
  80. package/dist/commands/reputation.js +27 -25
  81. package/dist/commands/reputation.js.map +1 -1
  82. package/dist/commands/setup.js +104 -65
  83. package/dist/commands/setup.js.map +1 -1
  84. package/dist/commands/trust.js +20 -17
  85. package/dist/commands/trust.js.map +1 -1
  86. package/dist/commands/verify.js +21 -18
  87. package/dist/commands/verify.js.map +1 -1
  88. package/dist/commands/wallet.d.ts.map +1 -1
  89. package/dist/commands/wallet.js +645 -679
  90. package/dist/commands/wallet.js.map +1 -1
  91. package/dist/commands/watch.js +36 -33
  92. package/dist/commands/watch.js.map +1 -1
  93. package/dist/commands/watchtower.js +73 -37
  94. package/dist/commands/watchtower.js.map +1 -1
  95. package/dist/commands/workroom.d.ts.map +1 -1
  96. package/dist/commands/workroom.js +282 -143
  97. package/dist/commands/workroom.js.map +1 -1
  98. package/dist/config.d.ts +3 -0
  99. package/dist/config.d.ts.map +1 -1
  100. package/dist/config.js +71 -22
  101. package/dist/config.js.map +1 -1
  102. package/dist/daemon/compute-metering.d.ts +61 -0
  103. package/dist/daemon/compute-metering.d.ts.map +1 -0
  104. package/dist/daemon/compute-metering.js +299 -0
  105. package/dist/daemon/compute-metering.js.map +1 -0
  106. package/dist/daemon/compute-session.d.ts +100 -0
  107. package/dist/daemon/compute-session.d.ts.map +1 -0
  108. package/dist/daemon/compute-session.js +231 -0
  109. package/dist/daemon/compute-session.js.map +1 -0
  110. package/dist/daemon/config.d.ts +19 -1
  111. package/dist/daemon/config.d.ts.map +1 -1
  112. package/dist/daemon/config.js +90 -16
  113. package/dist/daemon/config.js.map +1 -1
  114. package/dist/daemon/credentials.d.ts +24 -0
  115. package/dist/daemon/credentials.d.ts.map +1 -0
  116. package/dist/daemon/credentials.js +80 -0
  117. package/dist/daemon/credentials.js.map +1 -0
  118. package/dist/daemon/delivery-client.d.ts +35 -0
  119. package/dist/daemon/delivery-client.d.ts.map +1 -0
  120. package/dist/daemon/delivery-client.js +231 -0
  121. package/dist/daemon/delivery-client.js.map +1 -0
  122. package/dist/daemon/file-delivery.d.ts +98 -0
  123. package/dist/daemon/file-delivery.d.ts.map +1 -0
  124. package/dist/daemon/file-delivery.js +461 -0
  125. package/dist/daemon/file-delivery.js.map +1 -0
  126. package/dist/daemon/hire-listener.d.ts +3 -3
  127. package/dist/daemon/hire-listener.d.ts.map +1 -1
  128. package/dist/daemon/hire-listener.js +47 -13
  129. package/dist/daemon/hire-listener.js.map +1 -1
  130. package/dist/daemon/index.d.ts +2 -1
  131. package/dist/daemon/index.d.ts.map +1 -1
  132. package/dist/daemon/index.js +526 -53
  133. package/dist/daemon/index.js.map +1 -1
  134. package/dist/daemon/job-lifecycle.d.ts +1 -1
  135. package/dist/daemon/job-lifecycle.d.ts.map +1 -1
  136. package/dist/daemon/job-lifecycle.js +51 -11
  137. package/dist/daemon/job-lifecycle.js.map +1 -1
  138. package/dist/daemon/notify.d.ts +1 -1
  139. package/dist/daemon/notify.d.ts.map +1 -1
  140. package/dist/daemon/notify.js +53 -19
  141. package/dist/daemon/notify.js.map +1 -1
  142. package/dist/daemon/token-metering.js +47 -8
  143. package/dist/daemon/token-metering.js.map +1 -1
  144. package/dist/daemon/userops.d.ts +2 -2
  145. package/dist/daemon/userops.d.ts.map +1 -1
  146. package/dist/daemon/userops.js +27 -23
  147. package/dist/daemon/userops.js.map +1 -1
  148. package/dist/daemon/wallet-monitor.d.ts +1 -1
  149. package/dist/daemon/wallet-monitor.d.ts.map +1 -1
  150. package/dist/daemon/wallet-monitor.js +12 -8
  151. package/dist/daemon/wallet-monitor.js.map +1 -1
  152. package/dist/daemon/worker-executor.d.ts +71 -0
  153. package/dist/daemon/worker-executor.d.ts.map +1 -0
  154. package/dist/daemon/worker-executor.js +382 -0
  155. package/dist/daemon/worker-executor.js.map +1 -0
  156. package/dist/drain-v4.js +64 -26
  157. package/dist/drain-v4.js.map +1 -1
  158. package/dist/endpoint-config.js +63 -20
  159. package/dist/endpoint-config.js.map +1 -1
  160. package/dist/endpoint-notify.js +48 -9
  161. package/dist/endpoint-notify.js.map +1 -1
  162. package/dist/index.js +50 -18
  163. package/dist/index.js.map +1 -1
  164. package/dist/openshell-runtime.d.ts.map +1 -1
  165. package/dist/openshell-runtime.js +82 -38
  166. package/dist/openshell-runtime.js.map +1 -1
  167. package/dist/program.d.ts.map +1 -1
  168. package/dist/program.js +85 -78
  169. package/dist/program.js.map +1 -1
  170. package/dist/repl.js +31 -25
  171. package/dist/repl.js.map +1 -1
  172. package/dist/signing.js +6 -3
  173. package/dist/signing.js.map +1 -1
  174. package/dist/telegram-notify.js +40 -3
  175. package/dist/telegram-notify.js.map +1 -1
  176. package/dist/tui/App.d.ts.map +1 -1
  177. package/dist/tui/App.js +56 -89
  178. package/dist/tui/App.js.map +1 -1
  179. package/dist/tui/Footer.js +7 -4
  180. package/dist/tui/Footer.js.map +1 -1
  181. package/dist/tui/Header.d.ts +1 -1
  182. package/dist/tui/Header.d.ts.map +1 -1
  183. package/dist/tui/Header.js +14 -9
  184. package/dist/tui/Header.js.map +1 -1
  185. package/dist/tui/InputLine.d.ts +2 -1
  186. package/dist/tui/InputLine.d.ts.map +1 -1
  187. package/dist/tui/InputLine.js +47 -97
  188. package/dist/tui/InputLine.js.map +1 -1
  189. package/dist/tui/Viewport.d.ts +1 -2
  190. package/dist/tui/Viewport.d.ts.map +1 -1
  191. package/dist/tui/Viewport.js +26 -6
  192. package/dist/tui/Viewport.js.map +1 -1
  193. package/dist/tui/WalletConnectPairing.js +19 -16
  194. package/dist/tui/WalletConnectPairing.js.map +1 -1
  195. package/dist/tui/components/Button.js +9 -6
  196. package/dist/tui/components/Button.js.map +1 -1
  197. package/dist/tui/components/CeremonyView.js +8 -5
  198. package/dist/tui/components/CeremonyView.js.map +1 -1
  199. package/dist/tui/components/CompletionDropdown.js +9 -6
  200. package/dist/tui/components/CompletionDropdown.js.map +1 -1
  201. package/dist/tui/components/ConfirmPrompt.js +8 -5
  202. package/dist/tui/components/ConfirmPrompt.js.map +1 -1
  203. package/dist/tui/components/CustomTextInput.js +14 -11
  204. package/dist/tui/components/CustomTextInput.js.map +1 -1
  205. package/dist/tui/components/InteractiveTable.js +12 -9
  206. package/dist/tui/components/InteractiveTable.js.map +1 -1
  207. package/dist/tui/components/StepSpinner.js +13 -10
  208. package/dist/tui/components/StepSpinner.js.map +1 -1
  209. package/dist/tui/components/Toast.js +12 -8
  210. package/dist/tui/components/Toast.js.map +1 -1
  211. package/dist/tui/index.d.ts.map +1 -1
  212. package/dist/tui/index.js +21 -28
  213. package/dist/tui/index.js.map +1 -1
  214. package/dist/tui/useChat.js +19 -13
  215. package/dist/tui/useChat.js.map +1 -1
  216. package/dist/tui/useCommand.d.ts +2 -3
  217. package/dist/tui/useCommand.d.ts.map +1 -1
  218. package/dist/tui/useCommand.js +24 -100
  219. package/dist/tui/useCommand.js.map +1 -1
  220. package/dist/tui/useNotifications.js +8 -5
  221. package/dist/tui/useNotifications.js.map +1 -1
  222. package/dist/tui/useScroll.d.ts.map +1 -1
  223. package/dist/tui/useScroll.js +12 -15
  224. package/dist/tui/useScroll.js.map +1 -1
  225. package/dist/ui/banner.d.ts +0 -12
  226. package/dist/ui/banner.d.ts.map +1 -1
  227. package/dist/ui/banner.js +19 -35
  228. package/dist/ui/banner.js.map +1 -1
  229. package/dist/ui/colors.js +19 -13
  230. package/dist/ui/colors.js.map +1 -1
  231. package/dist/ui/format.js +14 -6
  232. package/dist/ui/format.js.map +1 -1
  233. package/dist/ui/qr-render.js +11 -4
  234. package/dist/ui/qr-render.js.map +1 -1
  235. package/dist/ui/rpc-fallback.js +11 -6
  236. package/dist/ui/rpc-fallback.js.map +1 -1
  237. package/dist/ui/spinner.js +12 -6
  238. package/dist/ui/spinner.js.map +1 -1
  239. package/dist/ui/tree.js +6 -3
  240. package/dist/ui/tree.js.map +1 -1
  241. package/dist/utils/format.js +41 -27
  242. package/dist/utils/format.js.map +1 -1
  243. package/dist/utils/hash.js +42 -4
  244. package/dist/utils/hash.js.map +1 -1
  245. package/dist/utils/time.js +6 -2
  246. package/dist/utils/time.js.map +1 -1
  247. package/dist/wallet-router.d.ts +1 -1
  248. package/dist/wallet-router.d.ts.map +1 -1
  249. package/dist/wallet-router.js +19 -12
  250. package/dist/wallet-router.js.map +1 -1
  251. package/dist/walletconnect-session.d.ts +1 -1
  252. package/dist/walletconnect-session.d.ts.map +1 -1
  253. package/dist/walletconnect-session.js +11 -6
  254. package/dist/walletconnect-session.js.map +1 -1
  255. package/dist/walletconnect.d.ts +5 -6
  256. package/dist/walletconnect.d.ts.map +1 -1
  257. package/dist/walletconnect.js +35 -32
  258. package/dist/walletconnect.js.map +1 -1
  259. package/package.json +11 -10
  260. package/INK6-UX-SPEC.md +0 -446
  261. package/MIGRATION-SPEC.md +0 -108
  262. package/TUI-SPEC.md +0 -214
  263. package/scripts/authorize-machine-key.ts +0 -43
  264. package/scripts/drain-wallet.ts +0 -149
  265. package/scripts/execute-spend-only.ts +0 -81
  266. package/scripts/register-agent-userop.ts +0 -186
  267. package/src/abis.ts +0 -187
  268. package/src/bundler.ts +0 -235
  269. package/src/client.ts +0 -36
  270. package/src/coinbase-smart-wallet.ts +0 -51
  271. package/src/commands/accept.ts +0 -64
  272. package/src/commands/agent-handshake.ts +0 -72
  273. package/src/commands/agent.ts +0 -691
  274. package/src/commands/agreements.ts +0 -350
  275. package/src/commands/arbitrator.ts +0 -180
  276. package/src/commands/arena-handshake.ts +0 -274
  277. package/src/commands/arena.ts +0 -122
  278. package/src/commands/backup.ts +0 -117
  279. package/src/commands/cancel.ts +0 -35
  280. package/src/commands/channel.ts +0 -218
  281. package/src/commands/coldstart.ts +0 -165
  282. package/src/commands/config.ts +0 -68
  283. package/src/commands/contract-interaction.ts +0 -166
  284. package/src/commands/daemon.ts +0 -1054
  285. package/src/commands/deliver.ts +0 -148
  286. package/src/commands/discover.ts +0 -350
  287. package/src/commands/dispute.ts +0 -375
  288. package/src/commands/doctor.ts +0 -172
  289. package/src/commands/endpoint.ts +0 -620
  290. package/src/commands/feed.ts +0 -229
  291. package/src/commands/hire.ts +0 -245
  292. package/src/commands/migrate.ts +0 -177
  293. package/src/commands/negotiate.ts +0 -272
  294. package/src/commands/openshell.ts +0 -1055
  295. package/src/commands/owner.ts +0 -35
  296. package/src/commands/policy.ts +0 -263
  297. package/src/commands/relay.ts +0 -277
  298. package/src/commands/remediate.ts +0 -24
  299. package/src/commands/reputation.ts +0 -79
  300. package/src/commands/setup.ts +0 -343
  301. package/src/commands/trust.ts +0 -27
  302. package/src/commands/verify.ts +0 -91
  303. package/src/commands/wallet.ts +0 -3548
  304. package/src/commands/watch.ts +0 -220
  305. package/src/commands/watchtower.ts +0 -248
  306. package/src/commands/workroom.ts +0 -963
  307. package/src/config.ts +0 -220
  308. package/src/daemon/config.ts +0 -344
  309. package/src/daemon/hire-listener.ts +0 -226
  310. package/src/daemon/index.ts +0 -1089
  311. package/src/daemon/job-lifecycle.ts +0 -215
  312. package/src/daemon/notify.ts +0 -297
  313. package/src/daemon/token-metering.ts +0 -183
  314. package/src/daemon/userops.ts +0 -119
  315. package/src/daemon/wallet-monitor.ts +0 -90
  316. package/src/drain-v4.ts +0 -159
  317. package/src/endpoint-config.ts +0 -83
  318. package/src/endpoint-notify.ts +0 -129
  319. package/src/index.ts +0 -74
  320. package/src/openshell-runtime.ts +0 -281
  321. package/src/program.ts +0 -88
  322. package/src/repl.ts +0 -178
  323. package/src/signing.ts +0 -28
  324. package/src/telegram-notify.ts +0 -88
  325. package/src/tui/App.tsx +0 -263
  326. package/src/tui/Footer.tsx +0 -18
  327. package/src/tui/Header.tsx +0 -45
  328. package/src/tui/InputLine.tsx +0 -243
  329. package/src/tui/Viewport.tsx +0 -51
  330. package/src/tui/WalletConnectPairing.tsx +0 -114
  331. package/src/tui/components/Button.tsx +0 -38
  332. package/src/tui/components/CeremonyView.tsx +0 -39
  333. package/src/tui/components/CompletionDropdown.tsx +0 -56
  334. package/src/tui/components/ConfirmPrompt.tsx +0 -36
  335. package/src/tui/components/CustomTextInput.tsx +0 -132
  336. package/src/tui/components/InteractiveTable.tsx +0 -106
  337. package/src/tui/components/StepSpinner.tsx +0 -84
  338. package/src/tui/components/Toast.tsx +0 -59
  339. package/src/tui/index.tsx +0 -90
  340. package/src/tui/useChat.ts +0 -103
  341. package/src/tui/useCommand.ts +0 -238
  342. package/src/tui/useNotifications.ts +0 -28
  343. package/src/tui/useScroll.ts +0 -69
  344. package/src/ui/banner.ts +0 -78
  345. package/src/ui/colors.ts +0 -30
  346. package/src/ui/format.ts +0 -78
  347. package/src/ui/qr-render.ts +0 -92
  348. package/src/ui/rpc-fallback.ts +0 -59
  349. package/src/ui/spinner.ts +0 -56
  350. package/src/ui/tree.ts +0 -16
  351. package/src/utils/format.ts +0 -48
  352. package/src/utils/hash.ts +0 -5
  353. package/src/utils/time.ts +0 -15
  354. package/src/wallet-router.ts +0 -178
  355. package/src/walletconnect-session.ts +0 -27
  356. package/src/walletconnect.ts +0 -309
  357. package/test/time.test.js +0 -11
  358. package/tsconfig.json +0 -33
@@ -1,3 +1,42 @@
1
+ "use strict";
2
+ var __createBinding = (this && this.__createBinding) || (Object.create ? (function(o, m, k, k2) {
3
+ if (k2 === undefined) k2 = k;
4
+ var desc = Object.getOwnPropertyDescriptor(m, k);
5
+ if (!desc || ("get" in desc ? !m.__esModule : desc.writable || desc.configurable)) {
6
+ desc = { enumerable: true, get: function() { return m[k]; } };
7
+ }
8
+ Object.defineProperty(o, k2, desc);
9
+ }) : (function(o, m, k, k2) {
10
+ if (k2 === undefined) k2 = k;
11
+ o[k2] = m[k];
12
+ }));
13
+ var __setModuleDefault = (this && this.__setModuleDefault) || (Object.create ? (function(o, v) {
14
+ Object.defineProperty(o, "default", { enumerable: true, value: v });
15
+ }) : function(o, v) {
16
+ o["default"] = v;
17
+ });
18
+ var __importStar = (this && this.__importStar) || (function () {
19
+ var ownKeys = function(o) {
20
+ ownKeys = Object.getOwnPropertyNames || function (o) {
21
+ var ar = [];
22
+ for (var k in o) if (Object.prototype.hasOwnProperty.call(o, k)) ar[ar.length] = k;
23
+ return ar;
24
+ };
25
+ return ownKeys(o);
26
+ };
27
+ return function (mod) {
28
+ if (mod && mod.__esModule) return mod;
29
+ var result = {};
30
+ if (mod != null) for (var k = ownKeys(mod), i = 0; i < k.length; i++) if (k[i] !== "default") __createBinding(result, mod, k[i]);
31
+ __setModuleDefault(result, mod);
32
+ return result;
33
+ };
34
+ })();
35
+ var __importDefault = (this && this.__importDefault) || function (mod) {
36
+ return (mod && mod.__esModule) ? mod : { "default": mod };
37
+ };
38
+ Object.defineProperty(exports, "__esModule", { value: true });
39
+ exports.runDaemon = runDaemon;
1
40
  /**
2
41
  * ARC-402 Daemon — main process entry point.
3
42
  *
@@ -7,22 +46,26 @@
7
46
  * IPC: Unix socket at ~/.arc402/daemon.sock (JSON-lines protocol).
8
47
  * Signals: SIGTERM → graceful shutdown.
9
48
  */
10
- import * as fs from "fs";
11
- import * as os from "os";
12
- import * as path from "path";
13
- import * as net from "net";
14
- import * as http from "http";
15
- import { ethers } from "ethers";
16
- import Database from "better-sqlite3";
17
- import * as crypto from "crypto";
18
- import { loadDaemonConfig, loadMachineKey, DAEMON_DIR, DAEMON_PID, DAEMON_LOG, DAEMON_DB, DAEMON_SOCK, } from "./config.js";
19
- import { verifyWallet, getWalletBalance } from "./wallet-monitor.js";
20
- import { buildNotifier } from "./notify.js";
21
- import { HireListener } from "./hire-listener.js";
22
- import { UserOpsManager, buildAcceptCalldata } from "./userops.js";
23
- import { generateReceipt, extractLearnings, cleanJobDirectory } from "./job-lifecycle.js";
49
+ const fs = __importStar(require("fs"));
50
+ const path = __importStar(require("path"));
51
+ const net = __importStar(require("net"));
52
+ const http = __importStar(require("http"));
53
+ const ethers_1 = require("ethers");
54
+ const better_sqlite3_1 = __importDefault(require("better-sqlite3"));
55
+ const crypto = __importStar(require("crypto"));
56
+ const config_1 = require("./config");
57
+ const compute_metering_1 = require("./compute-metering");
58
+ const compute_session_1 = require("./compute-session");
59
+ const wallet_monitor_1 = require("./wallet-monitor");
60
+ const notify_1 = require("./notify");
61
+ const hire_listener_1 = require("./hire-listener");
62
+ const userops_1 = require("./userops");
63
+ const job_lifecycle_1 = require("./job-lifecycle");
64
+ const file_delivery_1 = require("./file-delivery");
65
+ const delivery_client_1 = require("./delivery-client");
66
+ const abis_1 = require("../abis");
24
67
  function openStateDB(dbPath) {
25
- const db = new Database(dbPath);
68
+ const db = new better_sqlite3_1.default(dbPath);
26
69
  db.pragma("journal_mode = WAL");
27
70
  db.exec(`
28
71
  CREATE TABLE IF NOT EXISTS hire_requests (
@@ -77,6 +120,7 @@ function openStateDB(dbPath) {
77
120
  (@id, @agreement_id, @hirer_address, @capability, @price_eth, @deadline_unix, @spec_hash, @status, @created_at, @updated_at, @reject_reason)
78
121
  `);
79
122
  const getHireRequest = db.prepare(`SELECT * FROM hire_requests WHERE id = ?`);
123
+ const getHireRequestByAgreementId = db.prepare(`SELECT * FROM hire_requests WHERE agreement_id = ? ORDER BY created_at DESC LIMIT 1`);
80
124
  const updateStatus = db.prepare(`UPDATE hire_requests SET status = ?, reject_reason = ?, updated_at = ? WHERE id = ?`);
81
125
  const listPending = db.prepare(`SELECT * FROM hire_requests WHERE status = 'pending_approval' ORDER BY created_at ASC`);
82
126
  const listActive = db.prepare(`SELECT * FROM hire_requests WHERE status IN ('accepted', 'delivered') ORDER BY created_at ASC`);
@@ -89,6 +133,9 @@ function openStateDB(dbPath) {
89
133
  getHireRequest(id) {
90
134
  return getHireRequest.get(id);
91
135
  },
136
+ getHireRequestByAgreementId(agreementId) {
137
+ return getHireRequestByAgreementId.get(agreementId);
138
+ },
92
139
  updateHireRequestStatus(id, status, rejectReason) {
93
140
  updateStatus.run(status, rejectReason ?? null, Date.now(), id);
94
141
  },
@@ -108,7 +155,7 @@ function openStateDB(dbPath) {
108
155
  };
109
156
  }
110
157
  // ─── Auth token ───────────────────────────────────────────────────────────────
111
- const DAEMON_TOKEN_FILE = path.join(path.dirname(DAEMON_SOCK), "daemon.token");
158
+ const DAEMON_TOKEN_FILE = path.join(path.dirname(config_1.DAEMON_SOCK), "daemon.token");
112
159
  function generateApiToken() {
113
160
  return crypto.randomBytes(32).toString("hex");
114
161
  }
@@ -126,7 +173,7 @@ function loadApiToken() {
126
173
  }
127
174
  const rateLimitMap = new Map();
128
175
  const RATE_LIMIT = 30;
129
- const RATE_WINDOW_MS = 60_000;
176
+ const RATE_WINDOW_MS = 60000;
130
177
  function checkRateLimit(ip) {
131
178
  const now = Date.now();
132
179
  let bucket = rateLimitMap.get(ip);
@@ -160,8 +207,8 @@ function openLogger(logPath, foreground) {
160
207
  }
161
208
  function startIpcServer(ctx, log, apiToken) {
162
209
  // Remove stale socket
163
- if (fs.existsSync(DAEMON_SOCK)) {
164
- fs.unlinkSync(DAEMON_SOCK);
210
+ if (fs.existsSync(config_1.DAEMON_SOCK)) {
211
+ fs.unlinkSync(config_1.DAEMON_SOCK);
165
212
  }
166
213
  const server = net.createServer((socket) => {
167
214
  let buf = "";
@@ -200,9 +247,9 @@ function startIpcServer(ctx, log, apiToken) {
200
247
  });
201
248
  socket.on("error", () => { });
202
249
  });
203
- server.listen(DAEMON_SOCK, () => {
204
- fs.chmodSync(DAEMON_SOCK, 0o600);
205
- log({ event: "ipc_ready", socket: DAEMON_SOCK });
250
+ server.listen(config_1.DAEMON_SOCK, () => {
251
+ fs.chmodSync(config_1.DAEMON_SOCK, 0o600);
252
+ log({ event: "ipc_ready", socket: config_1.DAEMON_SOCK });
206
253
  });
207
254
  return server;
208
255
  }
@@ -259,7 +306,7 @@ function handleIpcCommand(cmd, ctx, log) {
259
306
  log({ event: "hire_approved", id: cmd.id });
260
307
  // Trigger accept UserOp (fire and forget)
261
308
  if (ctx.userOps && ctx.config.serviceAgreementAddress) {
262
- const callData = buildAcceptCalldata(ctx.config.serviceAgreementAddress, hire.agreement_id ?? cmd.id, ctx.walletAddress);
309
+ const callData = (0, userops_1.buildAcceptCalldata)(ctx.config.serviceAgreementAddress, hire.agreement_id ?? cmd.id, ctx.walletAddress);
263
310
  ctx.userOps.submit(callData, ctx.walletAddress).then((hash) => {
264
311
  log({ event: "userop_submitted", id: cmd.id, hash });
265
312
  }).catch((err) => {
@@ -293,7 +340,7 @@ function handleIpcCommand(cmd, ctx, log) {
293
340
  const now = new Date().toISOString();
294
341
  const startedAt = new Date(hire.created_at).toISOString();
295
342
  // Generate execution receipt
296
- const receipt = generateReceipt({
343
+ const receipt = (0, job_lifecycle_1.generateReceipt)({
297
344
  agreementId: hire.agreement_id ?? cmd.id,
298
345
  deliverableHash: hire.spec_hash ?? "0x0",
299
346
  walletAddress: ctx.walletAddress,
@@ -302,7 +349,7 @@ function handleIpcCommand(cmd, ctx, log) {
302
349
  });
303
350
  log({ event: "receipt_generated", id: cmd.id, receipt_hash: receipt.receipt_hash });
304
351
  // Extract learnings
305
- extractLearnings({
352
+ (0, job_lifecycle_1.extractLearnings)({
306
353
  agreementId: hire.agreement_id ?? cmd.id,
307
354
  taskDescription: hire.capability ?? "unknown",
308
355
  deliverableHash: hire.spec_hash ?? "0x0",
@@ -315,7 +362,7 @@ function handleIpcCommand(cmd, ctx, log) {
315
362
  // Update status to complete
316
363
  ctx.db.updateHireRequestStatus(cmd.id, "complete");
317
364
  // Clean job directory (keep receipt + memory)
318
- cleanJobDirectory(hire.agreement_id ?? cmd.id);
365
+ (0, job_lifecycle_1.cleanJobDirectory)(hire.agreement_id ?? cmd.id);
319
366
  return {
320
367
  ok: true,
321
368
  data: {
@@ -339,15 +386,15 @@ function formatUptime(seconds) {
339
386
  return `${m}m ${s}s`;
340
387
  return `${s}s`;
341
388
  }
342
- export async function runDaemon(foreground = false) {
343
- fs.mkdirSync(DAEMON_DIR, { recursive: true, mode: 0o700 });
344
- const log = openLogger(DAEMON_LOG, foreground);
389
+ async function runDaemon(foreground = false) {
390
+ fs.mkdirSync(config_1.DAEMON_DIR, { recursive: true, mode: 0o700 });
391
+ const log = openLogger(config_1.DAEMON_LOG, foreground);
345
392
  log({ event: "daemon_starting" });
346
393
  // ── Step 1: Load config ──────────────────────────────────────────────────
347
394
  let config;
348
395
  try {
349
- config = loadDaemonConfig();
350
- log({ event: "config_loaded", path: path.join(os.homedir(), ".arc402", "daemon.toml") });
396
+ config = (0, config_1.loadDaemonConfig)();
397
+ log({ event: "config_loaded", path: require("path").join(require("os").homedir(), ".arc402", "daemon.toml") });
351
398
  }
352
399
  catch (err) {
353
400
  process.stderr.write(`Config error: ${err}\n`);
@@ -357,7 +404,7 @@ export async function runDaemon(foreground = false) {
357
404
  let machineKeyAddress;
358
405
  let machinePrivateKey;
359
406
  try {
360
- const mk = loadMachineKey(config);
407
+ const mk = (0, config_1.loadMachineKey)(config);
361
408
  machinePrivateKey = mk.privateKey;
362
409
  machineKeyAddress = mk.address;
363
410
  log({ event: "machine_key_loaded", address: machineKeyAddress });
@@ -367,7 +414,7 @@ export async function runDaemon(foreground = false) {
367
414
  process.exit(1);
368
415
  }
369
416
  // ── Step 3: Connect to RPC ───────────────────────────────────────────────
370
- const provider = new ethers.JsonRpcProvider(config.network.rpc_url);
417
+ const provider = new ethers_1.ethers.JsonRpcProvider(config.network.rpc_url);
371
418
  try {
372
419
  const chainId = (await provider.getNetwork()).chainId;
373
420
  if (Number(chainId) !== config.network.chain_id) {
@@ -383,7 +430,7 @@ export async function runDaemon(foreground = false) {
383
430
  }
384
431
  // ── Step 4+5: Verify wallet ──────────────────────────────────────────────
385
432
  try {
386
- const walletStatus = await verifyWallet(config, provider, machineKeyAddress);
433
+ const walletStatus = await (0, wallet_monitor_1.verifyWallet)(config, provider, machineKeyAddress);
387
434
  log({
388
435
  event: "wallet_verified",
389
436
  address: walletStatus.contractAddress,
@@ -397,7 +444,7 @@ export async function runDaemon(foreground = false) {
397
444
  process.exit(1);
398
445
  }
399
446
  // ── Step 6: Connect bundler ──────────────────────────────────────────────
400
- const userOps = new UserOpsManager(config, provider);
447
+ const userOps = new userops_1.UserOpsManager(config, provider);
401
448
  const bundlerOk = await userOps.pingBundler();
402
449
  if (!bundlerOk) {
403
450
  log({ event: "bundler_warn", msg: "Bundler endpoint unreachable — will retry on demand" });
@@ -407,17 +454,44 @@ export async function runDaemon(foreground = false) {
407
454
  // ── Step 7: Open state DB ────────────────────────────────────────────────
408
455
  let db;
409
456
  try {
410
- db = openStateDB(DAEMON_DB);
411
- log({ event: "state_db_opened", path: DAEMON_DB });
457
+ db = openStateDB(config_1.DAEMON_DB);
458
+ log({ event: "state_db_opened", path: config_1.DAEMON_DB });
412
459
  }
413
460
  catch (err) {
414
461
  process.stderr.write(`State DB error: ${err}\n`);
415
462
  process.exit(1);
416
463
  }
417
464
  // ── Setup notifier ───────────────────────────────────────────────────────
418
- const notifier = buildNotifier(config);
465
+ const notifier = (0, notify_1.buildNotifier)(config);
466
+ // ── File delivery subsystem ──────────────────────────────────────────────
467
+ const fileDelivery = new file_delivery_1.FileDeliveryManager({
468
+ maxFileSizeMb: config.delivery.max_file_size_mb,
469
+ maxJobSizeMb: config.delivery.max_job_size_mb,
470
+ });
471
+ fileDelivery.setPartyResolver((agreementId) => {
472
+ const row = db.getHireRequestByAgreementId(agreementId);
473
+ if (!row)
474
+ return null;
475
+ return {
476
+ hirerAddress: row.hirer_address,
477
+ providerAddress: config.wallet.contract_address,
478
+ };
479
+ });
480
+ const deliveryClient = new delivery_client_1.DeliveryClient({ autoDownload: config.delivery.auto_download });
481
+ deliveryClient.log = log;
482
+ log({ event: "file_delivery_ready", serve_files: config.delivery.serve_files, auto_download: config.delivery.auto_download });
483
+ // ── Compute rental subsystem ─────────────────────────────────────────────
484
+ let computeMetering = null;
485
+ let computeSessions = null;
486
+ // Machine key signer — used for on-chain compute contract calls
487
+ const machineKeySigner = new ethers_1.ethers.Wallet(machinePrivateKey, provider);
488
+ if (config.compute.enabled) {
489
+ computeMetering = new compute_metering_1.ComputeMetering(machinePrivateKey, config.network.chain_id, config.compute.compute_agreement_address || config.wallet.contract_address, config.compute.metering_interval_seconds, config.compute.report_interval_minutes, config.compute.compute_agreement_address ? provider : undefined);
490
+ computeSessions = new compute_session_1.ComputeSessionManager(computeMetering);
491
+ log({ event: "compute_enabled", gpu_spec: config.compute.gpu_spec, rate_wei: config.compute.rate_per_hour_wei });
492
+ }
419
493
  // ── Step 10: Start relay listener ───────────────────────────────────────
420
- const hireListener = new HireListener(config, db, notifier, config.wallet.contract_address);
494
+ const hireListener = new hire_listener_1.HireListener(config, db, notifier, config.wallet.contract_address);
421
495
  const ipcCtx = {
422
496
  db,
423
497
  config,
@@ -436,7 +510,7 @@ export async function runDaemon(foreground = false) {
436
510
  if (!hire || !hire.agreement_id || !config.serviceAgreementAddress)
437
511
  return;
438
512
  try {
439
- const callData = buildAcceptCalldata(config.serviceAgreementAddress, hire.agreement_id, config.wallet.contract_address);
513
+ const callData = (0, userops_1.buildAcceptCalldata)(config.serviceAgreementAddress, hire.agreement_id, config.wallet.contract_address);
440
514
  const hash = await userOps.submit(callData, config.wallet.contract_address);
441
515
  log({ event: "hire_auto_accepted", id: hireId, userop_hash: hash });
442
516
  if (config.notifications.notify_on_hire_accepted) {
@@ -466,7 +540,7 @@ export async function runDaemon(foreground = false) {
466
540
  log({ event: "hire_timeout_rejected", id: req.id });
467
541
  }
468
542
  }
469
- }, 30_000);
543
+ }, 30000);
470
544
  // Rate limit map cleanup — every 5 minutes (prevents unbounded growth)
471
545
  rateLimitCleanupInterval = setInterval(() => {
472
546
  const now = Date.now();
@@ -478,7 +552,7 @@ export async function runDaemon(foreground = false) {
478
552
  // Balance monitor — every 5 minutes
479
553
  const balanceInterval = setInterval(async () => {
480
554
  try {
481
- const balance = await getWalletBalance(config.wallet.contract_address, provider);
555
+ const balance = await (0, wallet_monitor_1.getWalletBalance)(config.wallet.contract_address, provider);
482
556
  const threshold = parseFloat(config.notifications.low_balance_threshold_eth);
483
557
  if (parseFloat(balance) < threshold) {
484
558
  log({ event: "low_balance", balance_eth: balance, threshold_eth: config.notifications.low_balance_threshold_eth });
@@ -489,8 +563,8 @@ export async function runDaemon(foreground = false) {
489
563
  }, 5 * 60 * 1000);
490
564
  // ── Step 11: Write PID file (if not foreground) ──────────────────────────
491
565
  if (!foreground) {
492
- fs.writeFileSync(DAEMON_PID, String(process.pid), { mode: 0o600 });
493
- log({ event: "pid_written", pid: process.pid, path: DAEMON_PID });
566
+ fs.writeFileSync(config_1.DAEMON_PID, String(process.pid), { mode: 0o600 });
567
+ log({ event: "pid_written", pid: process.pid, path: config_1.DAEMON_PID });
494
568
  }
495
569
  // ── Generate and save API token ──────────────────────────────────────────
496
570
  const apiToken = generateApiToken();
@@ -510,7 +584,7 @@ export async function runDaemon(foreground = false) {
510
584
  return;
511
585
  const claimedSigner = req.headers["x-arc402-signer"];
512
586
  try {
513
- const recovered = ethers.verifyMessage(body, sig);
587
+ const recovered = ethers_1.ethers.verifyMessage(body, sig);
514
588
  if (claimedSigner && recovered.toLowerCase() !== claimedSigner.toLowerCase()) {
515
589
  log({ event: "sig_mismatch", claimed: claimedSigner, recovered });
516
590
  }
@@ -577,8 +651,9 @@ export async function runDaemon(foreground = false) {
577
651
  res.end(JSON.stringify({ error: "too_many_requests" }));
578
652
  return;
579
653
  }
580
- // Auth required on all POST endpoints (GET public paths are open)
581
- if (req.method === "POST" || (req.method === "GET" && !PUBLIC_GET_PATHS.has(pathname))) {
654
+ // Auth required on all POST endpoints (GET public paths are open).
655
+ // /job/* GET routes use party auth (verifyPartyAccess) instead of daemon bearer token.
656
+ if (req.method === "POST" || (req.method === "GET" && !PUBLIC_GET_PATHS.has(pathname) && !pathname.startsWith("/job/"))) {
582
657
  const authHeader = req.headers["authorization"] ?? "";
583
658
  const token = authHeader.startsWith("Bearer ") ? authHeader.slice(7) : "";
584
659
  if (token !== apiToken) {
@@ -643,7 +718,7 @@ export async function runDaemon(foreground = false) {
643
718
  return;
644
719
  }
645
720
  // Policy check
646
- const { evaluatePolicy } = await import("./hire-listener.js");
721
+ const { evaluatePolicy } = await Promise.resolve().then(() => __importStar(require("./hire-listener")));
647
722
  const activeCount = db.countActiveHireRequests();
648
723
  const policyResult = evaluatePolicy(proposal, config, activeCount);
649
724
  if (!policyResult.allowed) {
@@ -761,8 +836,9 @@ export async function runDaemon(foreground = false) {
761
836
  const msg = JSON.parse(body);
762
837
  const agreementId = String(msg.agreementId ?? msg.agreement_id ?? "");
763
838
  const deliverableHash = String(msg.deliverableHash ?? msg.deliverable_hash ?? "");
839
+ const filesUrl = String(msg.files_url ?? msg.filesUrl ?? "");
764
840
  const from = String(msg.from ?? "");
765
- log({ event: "delivery_received", agreementId, deliverableHash, from });
841
+ log({ event: "delivery_received", agreementId, deliverableHash, from, has_files_url: !!filesUrl });
766
842
  // Update DB: mark delivered
767
843
  const active = db.listActiveHireRequests();
768
844
  const found = active.find(r => r.agreement_id === agreementId);
@@ -771,6 +847,15 @@ export async function runDaemon(foreground = false) {
771
847
  if (config.notifications.notify_on_delivery) {
772
848
  await notifier.notifyDelivery(agreementId, deliverableHash, "");
773
849
  }
850
+ // Auto-download and verify if files_url provided and auto_download enabled
851
+ if (filesUrl && config.delivery.auto_download) {
852
+ void deliveryClient.handleDeliveryNotification({ agreementId, deliverableHash, filesUrl })
853
+ .then(result => {
854
+ if (result)
855
+ log({ event: "delivery_auto_downloaded", agreementId, ok: result.ok, root_hash_match: result.rootHashMatch, files: result.fileResults.length });
856
+ })
857
+ .catch(err => log({ event: "delivery_download_error", agreementId, error: String(err) }));
858
+ }
774
859
  res.writeHead(200, { "Content-Type": "application/json" });
775
860
  res.end(JSON.stringify({ received: true, agent: config.wallet.contract_address }));
776
861
  }
@@ -895,11 +980,399 @@ export async function runDaemon(foreground = false) {
895
980
  if (statusAuthed) {
896
981
  statusPayload.active_agreements = db.listActiveHireRequests().length;
897
982
  statusPayload.pending_approval = db.listPendingHireRequests().length;
983
+ if (config.delivery.serve_files) {
984
+ const deliveriesDir = path.join(config_1.DAEMON_DIR, "deliveries");
985
+ let totalDeliveries = 0, totalFiles = 0;
986
+ if (fs.existsSync(deliveriesDir)) {
987
+ const entries = fs.readdirSync(deliveriesDir);
988
+ totalDeliveries = entries.length;
989
+ for (const entry of entries) {
990
+ const entryPath = path.join(deliveriesDir, entry);
991
+ if (fs.statSync(entryPath).isDirectory()) {
992
+ totalFiles += fs.readdirSync(entryPath).filter(f => f !== "_manifest.json").length;
993
+ }
994
+ }
995
+ }
996
+ statusPayload.file_delivery = { total_deliveries: totalDeliveries, total_files: totalFiles };
997
+ }
898
998
  }
899
999
  res.writeHead(200, { "Content-Type": "application/json" });
900
1000
  res.end(JSON.stringify(statusPayload));
901
1001
  return;
902
1002
  }
1003
+ // ── Compute rental routes ─────────────────────────────────────────────
1004
+ // POST /compute/propose — client proposes a compute session
1005
+ if (pathname === "/compute/propose" && req.method === "POST") {
1006
+ const body = await readBody(req, res);
1007
+ if (body === null)
1008
+ return;
1009
+ try {
1010
+ const msg = JSON.parse(body);
1011
+ if (!computeSessions) {
1012
+ res.writeHead(503, { "Content-Type": "application/json" });
1013
+ res.end(JSON.stringify({ error: "compute_disabled" }));
1014
+ return;
1015
+ }
1016
+ const proposal = {
1017
+ sessionId: String(msg.sessionId ?? ""),
1018
+ clientAddress: String(msg.clientAddress ?? msg.client ?? ""),
1019
+ providerAddress: config.wallet.contract_address,
1020
+ ratePerHourWei: config.compute.rate_per_hour_wei,
1021
+ maxHours: Number(msg.maxHours ?? 1),
1022
+ gpuSpecHash: String(msg.gpuSpecHash ?? "0x0000000000000000000000000000000000000000000000000000000000000000"),
1023
+ workloadDescription: String(msg.workloadDescription ?? ""),
1024
+ depositAmount: String(msg.depositAmount ?? "0"),
1025
+ proposedAt: Math.floor(Date.now() / 1000),
1026
+ };
1027
+ if (!proposal.sessionId) {
1028
+ res.writeHead(400, { "Content-Type": "application/json" });
1029
+ res.end(JSON.stringify({ error: "sessionId required" }));
1030
+ return;
1031
+ }
1032
+ // Check capacity
1033
+ const activeSessions = computeSessions.countByStatus("active");
1034
+ if (activeSessions >= config.compute.max_concurrent_sessions) {
1035
+ res.writeHead(200, { "Content-Type": "application/json" });
1036
+ res.end(JSON.stringify({ status: "rejected", reason: "at_capacity" }));
1037
+ return;
1038
+ }
1039
+ const result = computeSessions.handleProposal(proposal);
1040
+ if (!result.ok) {
1041
+ res.writeHead(400, { "Content-Type": "application/json" });
1042
+ res.end(JSON.stringify({ error: result.error }));
1043
+ return;
1044
+ }
1045
+ log({ event: "compute_proposed", sessionId: proposal.sessionId, client: proposal.clientAddress });
1046
+ // Auto-accept if configured
1047
+ if (config.compute.auto_accept_compute) {
1048
+ computeSessions.acceptSession(proposal.sessionId);
1049
+ log({ event: "compute_auto_accepted", sessionId: proposal.sessionId });
1050
+ // Wire to on-chain: provider calls acceptSession
1051
+ if (config.compute.compute_agreement_address) {
1052
+ try {
1053
+ const caContract = new ethers_1.ethers.Contract(config.compute.compute_agreement_address, abis_1.COMPUTE_AGREEMENT_ABI, machineKeySigner);
1054
+ const tx = await caContract.acceptSession(proposal.sessionId);
1055
+ await tx.wait();
1056
+ log({ event: "compute_accept_onchain", sessionId: proposal.sessionId, txHash: tx.hash });
1057
+ }
1058
+ catch (onchainErr) {
1059
+ log({ event: "compute_accept_onchain_error", sessionId: proposal.sessionId, error: String(onchainErr) });
1060
+ }
1061
+ }
1062
+ }
1063
+ const status = config.compute.auto_accept_compute ? "accepted" : "proposed";
1064
+ res.writeHead(200, { "Content-Type": "application/json" });
1065
+ res.end(JSON.stringify({ status, sessionId: proposal.sessionId }));
1066
+ }
1067
+ catch (err) {
1068
+ log({ event: "compute_propose_error", error: String(err) });
1069
+ res.writeHead(400, { "Content-Type": "application/json" });
1070
+ res.end(JSON.stringify({ error: "invalid_request" }));
1071
+ }
1072
+ return;
1073
+ }
1074
+ // POST /compute/accept — provider accepts a proposed session
1075
+ if (pathname === "/compute/accept" && req.method === "POST") {
1076
+ const body = await readBody(req, res);
1077
+ if (body === null)
1078
+ return;
1079
+ try {
1080
+ const msg = JSON.parse(body);
1081
+ const sessionId = String(msg.sessionId ?? "");
1082
+ if (!computeSessions) {
1083
+ res.writeHead(503, { "Content-Type": "application/json" });
1084
+ res.end(JSON.stringify({ error: "compute_disabled" }));
1085
+ return;
1086
+ }
1087
+ const result = computeSessions.acceptSession(sessionId);
1088
+ if (!result.ok) {
1089
+ res.writeHead(400, { "Content-Type": "application/json" });
1090
+ res.end(JSON.stringify({ error: result.error }));
1091
+ return;
1092
+ }
1093
+ log({ event: "compute_accepted", sessionId });
1094
+ // Wire to on-chain: provider calls acceptSession
1095
+ if (config.compute.compute_agreement_address) {
1096
+ try {
1097
+ const caContract = new ethers_1.ethers.Contract(config.compute.compute_agreement_address, abis_1.COMPUTE_AGREEMENT_ABI, machineKeySigner);
1098
+ const tx = await caContract.acceptSession(sessionId);
1099
+ await tx.wait();
1100
+ log({ event: "compute_accept_onchain", sessionId, txHash: tx.hash });
1101
+ }
1102
+ catch (onchainErr) {
1103
+ log({ event: "compute_accept_onchain_error", sessionId, error: String(onchainErr) });
1104
+ }
1105
+ }
1106
+ res.writeHead(200, { "Content-Type": "application/json" });
1107
+ res.end(JSON.stringify({ status: "accepted", sessionId }));
1108
+ }
1109
+ catch (err) {
1110
+ log({ event: "compute_accept_error", error: String(err) });
1111
+ res.writeHead(400, { "Content-Type": "application/json" });
1112
+ res.end(JSON.stringify({ error: "invalid_request" }));
1113
+ }
1114
+ return;
1115
+ }
1116
+ // POST /compute/started — provider marks session as started
1117
+ if (pathname === "/compute/started" && req.method === "POST") {
1118
+ const body = await readBody(req, res);
1119
+ if (body === null)
1120
+ return;
1121
+ try {
1122
+ const msg = JSON.parse(body);
1123
+ const sessionId = String(msg.sessionId ?? "");
1124
+ const accessEndpoint = msg.accessEndpoint ? String(msg.accessEndpoint) : undefined;
1125
+ if (!computeSessions) {
1126
+ res.writeHead(503, { "Content-Type": "application/json" });
1127
+ res.end(JSON.stringify({ error: "compute_disabled" }));
1128
+ return;
1129
+ }
1130
+ const result = computeSessions.startSession(sessionId, accessEndpoint);
1131
+ if (!result.ok) {
1132
+ res.writeHead(400, { "Content-Type": "application/json" });
1133
+ res.end(JSON.stringify({ error: result.error }));
1134
+ return;
1135
+ }
1136
+ log({ event: "compute_started", sessionId });
1137
+ // Wire to on-chain: provider calls startSession
1138
+ if (config.compute.compute_agreement_address) {
1139
+ try {
1140
+ const caContract = new ethers_1.ethers.Contract(config.compute.compute_agreement_address, abis_1.COMPUTE_AGREEMENT_ABI, machineKeySigner);
1141
+ const tx = await caContract.startSession(sessionId);
1142
+ await tx.wait();
1143
+ log({ event: "compute_start_onchain", sessionId, txHash: tx.hash });
1144
+ }
1145
+ catch (onchainErr) {
1146
+ log({ event: "compute_start_onchain_error", sessionId, error: String(onchainErr) });
1147
+ }
1148
+ }
1149
+ res.writeHead(200, { "Content-Type": "application/json" });
1150
+ res.end(JSON.stringify({ status: "active", sessionId }));
1151
+ }
1152
+ catch (err) {
1153
+ log({ event: "compute_started_error", error: String(err) });
1154
+ res.writeHead(400, { "Content-Type": "application/json" });
1155
+ res.end(JSON.stringify({ error: "invalid_request" }));
1156
+ }
1157
+ return;
1158
+ }
1159
+ // POST /compute/metrics — get current metrics (polling endpoint)
1160
+ if (pathname === "/compute/metrics" && req.method === "POST") {
1161
+ const body = await readBody(req, res);
1162
+ if (body === null)
1163
+ return;
1164
+ try {
1165
+ const msg = JSON.parse(body);
1166
+ const sessionId = String(msg.sessionId ?? "");
1167
+ if (!computeMetering || !computeSessions) {
1168
+ res.writeHead(503, { "Content-Type": "application/json" });
1169
+ res.end(JSON.stringify({ error: "compute_disabled" }));
1170
+ return;
1171
+ }
1172
+ const session = computeSessions.getSession(sessionId);
1173
+ if (!session) {
1174
+ res.writeHead(404, { "Content-Type": "application/json" });
1175
+ res.end(JSON.stringify({ error: "session_not_found" }));
1176
+ return;
1177
+ }
1178
+ const current = computeMetering.getCurrentMetrics(sessionId);
1179
+ const reports = computeMetering.getUsageReports(sessionId);
1180
+ res.writeHead(200, { "Content-Type": "application/json" });
1181
+ res.end(JSON.stringify({ sessionId, current, reports, consumedMinutes: session.consumedMinutes }));
1182
+ }
1183
+ catch (err) {
1184
+ log({ event: "compute_metrics_error", error: String(err) });
1185
+ res.writeHead(400, { "Content-Type": "application/json" });
1186
+ res.end(JSON.stringify({ error: "invalid_request" }));
1187
+ }
1188
+ return;
1189
+ }
1190
+ // POST /compute/end — either party ends the session
1191
+ if (pathname === "/compute/end" && req.method === "POST") {
1192
+ const body = await readBody(req, res);
1193
+ if (body === null)
1194
+ return;
1195
+ try {
1196
+ const msg = JSON.parse(body);
1197
+ const sessionId = String(msg.sessionId ?? "");
1198
+ if (!computeSessions) {
1199
+ res.writeHead(503, { "Content-Type": "application/json" });
1200
+ res.end(JSON.stringify({ error: "compute_disabled" }));
1201
+ return;
1202
+ }
1203
+ const endResult = await computeSessions.endSession(sessionId);
1204
+ if (!endResult.ok) {
1205
+ res.writeHead(400, { "Content-Type": "application/json" });
1206
+ res.end(JSON.stringify({ error: endResult.error }));
1207
+ return;
1208
+ }
1209
+ const r = endResult.result;
1210
+ log({
1211
+ event: "compute_ended",
1212
+ sessionId,
1213
+ consumedMinutes: r.consumedMinutes,
1214
+ costWei: r.costWei.toString(),
1215
+ refundWei: r.refundWei.toString(),
1216
+ });
1217
+ // Wire to on-chain: call endSession
1218
+ if (config.compute.compute_agreement_address) {
1219
+ try {
1220
+ const caContract = new ethers_1.ethers.Contract(config.compute.compute_agreement_address, abis_1.COMPUTE_AGREEMENT_ABI, machineKeySigner);
1221
+ const tx = await caContract.endSession(sessionId);
1222
+ await tx.wait();
1223
+ log({ event: "compute_end_onchain", sessionId, txHash: tx.hash });
1224
+ }
1225
+ catch (onchainErr) {
1226
+ log({ event: "compute_end_onchain_error", sessionId, error: String(onchainErr) });
1227
+ }
1228
+ }
1229
+ res.writeHead(200, { "Content-Type": "application/json" });
1230
+ res.end(JSON.stringify({
1231
+ status: "completed",
1232
+ sessionId,
1233
+ consumedMinutes: r.consumedMinutes,
1234
+ costWei: r.costWei.toString(),
1235
+ refundWei: r.refundWei.toString(),
1236
+ reports: r.reports,
1237
+ }));
1238
+ }
1239
+ catch (err) {
1240
+ log({ event: "compute_end_error", error: String(err) });
1241
+ res.writeHead(400, { "Content-Type": "application/json" });
1242
+ res.end(JSON.stringify({ error: "invalid_request" }));
1243
+ }
1244
+ return;
1245
+ }
1246
+ // POST /compute/dispute — client disputes a session
1247
+ if (pathname === "/compute/dispute" && req.method === "POST") {
1248
+ const body = await readBody(req, res);
1249
+ if (body === null)
1250
+ return;
1251
+ try {
1252
+ const msg = JSON.parse(body);
1253
+ const sessionId = String(msg.sessionId ?? "");
1254
+ if (!computeSessions) {
1255
+ res.writeHead(503, { "Content-Type": "application/json" });
1256
+ res.end(JSON.stringify({ error: "compute_disabled" }));
1257
+ return;
1258
+ }
1259
+ const result = computeSessions.disputeSession(sessionId);
1260
+ if (!result.ok) {
1261
+ res.writeHead(400, { "Content-Type": "application/json" });
1262
+ res.end(JSON.stringify({ error: result.error }));
1263
+ return;
1264
+ }
1265
+ log({ event: "compute_disputed", sessionId });
1266
+ if (config.notifications.notify_on_dispute) {
1267
+ await notifier.notifyDispute(sessionId, String(msg.from ?? "client"));
1268
+ }
1269
+ // Wire to on-chain: call disputeSession
1270
+ if (config.compute.compute_agreement_address) {
1271
+ try {
1272
+ const caContract = new ethers_1.ethers.Contract(config.compute.compute_agreement_address, abis_1.COMPUTE_AGREEMENT_ABI, machineKeySigner);
1273
+ const tx = await caContract.disputeSession(sessionId);
1274
+ await tx.wait();
1275
+ log({ event: "compute_dispute_onchain", sessionId, txHash: tx.hash });
1276
+ }
1277
+ catch (onchainErr) {
1278
+ log({ event: "compute_dispute_onchain_error", sessionId, error: String(onchainErr) });
1279
+ }
1280
+ }
1281
+ res.writeHead(200, { "Content-Type": "application/json" });
1282
+ res.end(JSON.stringify({ status: "disputed", sessionId }));
1283
+ }
1284
+ catch (err) {
1285
+ log({ event: "compute_dispute_error", error: String(err) });
1286
+ res.writeHead(400, { "Content-Type": "application/json" });
1287
+ res.end(JSON.stringify({ error: "invalid_request" }));
1288
+ }
1289
+ return;
1290
+ }
1291
+ // GET /compute/session/:id — session details
1292
+ if (pathname.startsWith("/compute/session/") && req.method === "GET") {
1293
+ const sessionId = pathname.slice("/compute/session/".length);
1294
+ if (!computeSessions) {
1295
+ res.writeHead(503, { "Content-Type": "application/json" });
1296
+ res.end(JSON.stringify({ error: "compute_disabled" }));
1297
+ return;
1298
+ }
1299
+ const session = computeSessions.getSession(sessionId);
1300
+ if (!session) {
1301
+ res.writeHead(404, { "Content-Type": "application/json" });
1302
+ res.end(JSON.stringify({ error: "session_not_found" }));
1303
+ return;
1304
+ }
1305
+ const current = computeMetering ? computeMetering.getCurrentMetrics(sessionId) : null;
1306
+ res.writeHead(200, { "Content-Type": "application/json" });
1307
+ res.end(JSON.stringify({ session, current }));
1308
+ return;
1309
+ }
1310
+ // GET /compute/sessions — list all sessions
1311
+ if (pathname === "/compute/sessions" && req.method === "GET") {
1312
+ if (!computeSessions) {
1313
+ res.writeHead(503, { "Content-Type": "application/json" });
1314
+ res.end(JSON.stringify({ error: "compute_disabled" }));
1315
+ return;
1316
+ }
1317
+ const sessions = computeSessions.listSessions();
1318
+ res.writeHead(200, { "Content-Type": "application/json" });
1319
+ res.end(JSON.stringify({ sessions, count: sessions.length }));
1320
+ return;
1321
+ }
1322
+ // ── File delivery routes ──────────────────────────────────────────────
1323
+ // POST /job/:id/upload — store a file (daemon auth required via global gate above)
1324
+ if (pathname.startsWith("/job/") && req.method === "POST") {
1325
+ const parts = pathname.split("/");
1326
+ // /job/<id>/upload → ["", "job", "<id>", "upload"]
1327
+ if (parts.length === 4 && parts[3] === "upload") {
1328
+ const agreementId = parts[2];
1329
+ if (!config.delivery.serve_files) {
1330
+ res.writeHead(503, { "Content-Type": "application/json" });
1331
+ res.end(JSON.stringify({ error: "file_delivery_disabled" }));
1332
+ return;
1333
+ }
1334
+ await fileDelivery.handleUpload(req, res, agreementId, log);
1335
+ return;
1336
+ }
1337
+ }
1338
+ // GET /job/:id/files, GET /job/:id/files/:name, GET /job/:id/manifest — party-gated
1339
+ if (pathname.startsWith("/job/") && req.method === "GET") {
1340
+ const parts = pathname.split("/");
1341
+ // /job/<id>/files/<name> → ["", "job", "<id>", "files", "<name>"]
1342
+ if (parts.length === 5 && parts[3] === "files") {
1343
+ const agreementId = parts[2];
1344
+ const filename = decodeURIComponent(parts[4]);
1345
+ if (!config.delivery.serve_files) {
1346
+ res.writeHead(503, { "Content-Type": "application/json" });
1347
+ res.end(JSON.stringify({ error: "file_delivery_disabled" }));
1348
+ return;
1349
+ }
1350
+ fileDelivery.handleDownloadFile(req, res, agreementId, filename, apiToken, log);
1351
+ return;
1352
+ }
1353
+ // /job/<id>/files → ["", "job", "<id>", "files"]
1354
+ if (parts.length === 4 && parts[3] === "files") {
1355
+ const agreementId = parts[2];
1356
+ if (!config.delivery.serve_files) {
1357
+ res.writeHead(503, { "Content-Type": "application/json" });
1358
+ res.end(JSON.stringify({ error: "file_delivery_disabled" }));
1359
+ return;
1360
+ }
1361
+ fileDelivery.handleListFiles(req, res, agreementId, apiToken, log);
1362
+ return;
1363
+ }
1364
+ // /job/<id>/manifest → ["", "job", "<id>", "manifest"]
1365
+ if (parts.length === 4 && parts[3] === "manifest") {
1366
+ const agreementId = parts[2];
1367
+ if (!config.delivery.serve_files) {
1368
+ res.writeHead(503, { "Content-Type": "application/json" });
1369
+ res.end(JSON.stringify({ error: "file_delivery_disabled" }));
1370
+ return;
1371
+ }
1372
+ fileDelivery.handleManifest(req, res, agreementId, apiToken, log);
1373
+ return;
1374
+ }
1375
+ }
903
1376
  // 404
904
1377
  res.writeHead(404, { "Content-Type": "application/json" });
905
1378
  res.end(JSON.stringify({ error: "not_found" }));
@@ -934,13 +1407,13 @@ export async function runDaemon(foreground = false) {
934
1407
  // Close HTTP + IPC
935
1408
  httpServer.close();
936
1409
  ipcServer.close();
937
- if (fs.existsSync(DAEMON_SOCK))
938
- fs.unlinkSync(DAEMON_SOCK);
1410
+ if (fs.existsSync(config_1.DAEMON_SOCK))
1411
+ fs.unlinkSync(config_1.DAEMON_SOCK);
939
1412
  await notifier.notifyStopped();
940
1413
  log({ event: "daemon_stopped" });
941
1414
  // Clean up PID file
942
- if (!foreground && fs.existsSync(DAEMON_PID)) {
943
- fs.unlinkSync(DAEMON_PID);
1415
+ if (!foreground && fs.existsSync(config_1.DAEMON_PID)) {
1416
+ fs.unlinkSync(config_1.DAEMON_PID);
944
1417
  }
945
1418
  db.close();
946
1419
  process.exit(0);