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,620 +0,0 @@
1
- import { Command } from "commander";
2
- import { ethers } from "ethers";
3
- import { AgentRegistryClient } from "@arc402/sdk";
4
- import {
5
- buildEndpointConfig,
6
- DEFAULT_LOCAL_INGRESS_TARGET,
7
- ENDPOINT_CONFIG_PATH,
8
- loadEndpointConfig,
9
- normalizeAgentName,
10
- saveEndpointConfig,
11
- } from "../endpoint-config.js";
12
- import { configExists, getSubdomainApi, loadConfig, NETWORK_DEFAULTS } from "../config.js";
13
- import { DAEMON_PID } from "../daemon/config.js";
14
- import { detectDockerAccess, readOpenShellConfig, runCmd } from "../openshell-runtime.js";
15
- import { getClient } from "../client.js";
16
- import * as dns from "dns/promises";
17
- import * as fs from "fs";
18
- import * as net from "net";
19
- import chalk from "chalk";
20
- import { c } from '../ui/colors.js';
21
-
22
- interface DoctorCheck {
23
- layer: string;
24
- label: string;
25
- ok: boolean;
26
- detail: string;
27
- fix?: string;
28
- }
29
-
30
- function readWalletAddress(): string | undefined {
31
- if (!configExists()) return undefined;
32
- try {
33
- const config = loadConfig();
34
- if (config.walletContractAddress) return config.walletContractAddress;
35
- if (config.privateKey) return new ethers.Wallet(config.privateKey).address;
36
- } catch {
37
- return undefined;
38
- }
39
- return undefined;
40
- }
41
-
42
- function readSubdomainApi(): string {
43
- if (!configExists()) return "https://api.arc402.xyz";
44
- try {
45
- return getSubdomainApi(loadConfig());
46
- } catch {
47
- return "https://api.arc402.xyz";
48
- }
49
- }
50
-
51
- function readAgentRegistryAddress(): string | undefined {
52
- if (!configExists()) return undefined;
53
- try {
54
- const config = loadConfig();
55
- return config.agentRegistryV2Address ?? NETWORK_DEFAULTS[config.network]?.agentRegistryV2Address;
56
- } catch {
57
- return undefined;
58
- }
59
- }
60
-
61
- function isProcessAlive(pid: number): boolean {
62
- try {
63
- process.kill(pid, 0);
64
- return true;
65
- } catch {
66
- return false;
67
- }
68
- }
69
-
70
- async function checkLocalTarget(target: string): Promise<{ ok: boolean; detail: string }> {
71
- try {
72
- const url = new URL(target);
73
- const host = url.hostname;
74
- const port = Number(url.port || (url.protocol === "https:" ? 443 : 80));
75
- const socket = new net.Socket();
76
- socket.setTimeout(1500);
77
- return await new Promise<{ ok: boolean; detail: string }>((resolve) => {
78
- socket.once("connect", () => {
79
- socket.destroy();
80
- resolve({ ok: true, detail: `${host}:${port} accepted TCP connection` });
81
- });
82
- socket.once("timeout", () => {
83
- socket.destroy();
84
- resolve({ ok: false, detail: `${host}:${port} timed out` });
85
- });
86
- socket.once("error", (err) => {
87
- socket.destroy();
88
- resolve({ ok: false, detail: `${host}:${port} unreachable (${err.message})` });
89
- });
90
- socket.connect(port, host);
91
- });
92
- } catch (err) {
93
- return { ok: false, detail: `invalid URL: ${err instanceof Error ? err.message : String(err)}` };
94
- }
95
- }
96
-
97
- function checkDaemon(): DoctorCheck {
98
- if (!fs.existsSync(DAEMON_PID)) {
99
- return {
100
- layer: "runtime",
101
- label: "Daemon",
102
- ok: false,
103
- detail: "no PID file found",
104
- fix: "Run `arc402 openshell init` if needed, then `arc402 daemon start`.",
105
- };
106
- }
107
-
108
- const rawPid = fs.readFileSync(DAEMON_PID, "utf-8").trim();
109
- const pid = Number(rawPid);
110
- if (!Number.isFinite(pid) || pid <= 0) {
111
- return {
112
- layer: "runtime",
113
- label: "Daemon",
114
- ok: false,
115
- detail: `invalid PID file contents: ${JSON.stringify(rawPid)}`,
116
- fix: "Remove the stale PID file and restart the daemon.",
117
- };
118
- }
119
-
120
- if (!isProcessAlive(pid)) {
121
- return {
122
- layer: "runtime",
123
- label: "Daemon",
124
- ok: false,
125
- detail: `stale PID file (${pid})`,
126
- fix: "Remove the stale PID file and restart with `arc402 daemon start`.",
127
- };
128
- }
129
-
130
- return {
131
- layer: "runtime",
132
- label: "Daemon",
133
- ok: true,
134
- detail: `running (PID ${pid})`,
135
- };
136
- }
137
-
138
- function checkOpenShell(): DoctorCheck {
139
- const config = readOpenShellConfig();
140
- const docker = detectDockerAccess();
141
- if (!config?.sandbox?.name) {
142
- return {
143
- layer: "runtime",
144
- label: "OpenShell runtime",
145
- ok: false,
146
- detail: "not configured for launch",
147
- fix: "Run `arc402 openshell init` so ARC-402 runtime stays sandboxed.",
148
- };
149
- }
150
- if (!docker.ok) {
151
- return {
152
- layer: "runtime",
153
- label: "OpenShell runtime",
154
- ok: false,
155
- detail: `configured, but Docker/OpenShell substrate is unhealthy: ${docker.detail}`,
156
- fix: "Restore Docker/OpenShell health, then re-run `arc402 openshell status`.",
157
- };
158
- }
159
- return {
160
- layer: "runtime",
161
- label: "OpenShell runtime",
162
- ok: true,
163
- detail: `${config.sandbox.name} configured; Docker ${docker.detail}`,
164
- };
165
- }
166
-
167
- function checkCloudflared(endpointTunnelTarget?: string): DoctorCheck {
168
- const which = runCmd("which", ["cloudflared"]);
169
- if (!which.ok || !which.stdout) {
170
- return {
171
- layer: "ingress",
172
- label: "Tunnel binary",
173
- ok: false,
174
- detail: "cloudflared not found in PATH",
175
- fix: "Install cloudflared on the host machine for the launch-default ingress path.",
176
- };
177
- }
178
-
179
- const ps = runCmd("bash", ["-lc", "ps -ef | grep '[c]loudflared tunnel' | head -1"]);
180
- if (!ps.ok || !ps.stdout) {
181
- return {
182
- layer: "ingress",
183
- label: "Tunnel process",
184
- ok: false,
185
- detail: endpointTunnelTarget
186
- ? `cloudflared is installed, but no tunnel process was detected for ${endpointTunnelTarget}`
187
- : "cloudflared is installed, but no tunnel process was detected",
188
- fix: "Start your host-managed tunnel (for example `cloudflared tunnel run ...`).",
189
- };
190
- }
191
-
192
- return {
193
- layer: "ingress",
194
- label: "Tunnel process",
195
- ok: true,
196
- detail: `detected: ${ps.stdout}`,
197
- };
198
- }
199
-
200
- async function checkPublicHostname(endpoint: ReturnType<typeof loadEndpointConfig>): Promise<DoctorCheck> {
201
- if (!endpoint) {
202
- return {
203
- layer: "public",
204
- label: "Public hostname",
205
- ok: false,
206
- detail: "cannot resolve because endpoint config is missing",
207
- fix: "Run `arc402 endpoint init <agentname>` first.",
208
- };
209
- }
210
-
211
- try {
212
- const results = await dns.lookup(endpoint.hostname, { all: true });
213
- if (!results.length) {
214
- return {
215
- layer: "public",
216
- label: "Public hostname",
217
- ok: false,
218
- detail: `${endpoint.hostname} did not resolve`,
219
- fix: endpoint.claimedAt
220
- ? "Verify the claimed hostname is live in DNS / Cloudflare and that propagation is complete."
221
- : "Claim the hostname first, then wait for DNS to propagate.",
222
- };
223
- }
224
-
225
- const addresses = results.map((entry) => entry.address).join(", ");
226
- return {
227
- layer: "public",
228
- label: "Public hostname",
229
- ok: true,
230
- detail: `${endpoint.hostname} resolves (${addresses})`,
231
- };
232
- } catch (err) {
233
- return {
234
- layer: "public",
235
- label: "Public hostname",
236
- ok: false,
237
- detail: `${endpoint.hostname} not resolvable yet (${err instanceof Error ? err.message : String(err)})`,
238
- fix: endpoint.claimedAt
239
- ? "If the claim succeeded, verify DNS propagation / Cloudflare routing rather than the local runtime."
240
- : "Claim the hostname first, then re-run status/doctor.",
241
- };
242
- }
243
- }
244
-
245
- async function checkAgentRegistryParity(endpoint: ReturnType<typeof loadEndpointConfig>): Promise<DoctorCheck> {
246
- if (!endpoint) {
247
- return {
248
- layer: "registry",
249
- label: "AgentRegistry parity",
250
- ok: false,
251
- detail: "endpoint config missing, so local ↔ registry parity cannot be checked",
252
- fix: "Run `arc402 endpoint init <agentname>` first.",
253
- };
254
- }
255
-
256
- const walletAddress = endpoint.walletAddress ?? readWalletAddress();
257
- if (!walletAddress) {
258
- return {
259
- layer: "registry",
260
- label: "AgentRegistry parity",
261
- ok: false,
262
- detail: "no wallet address resolved from local config, so registry parity proof is partial",
263
- fix: "Run `arc402 config init` (or set walletContractAddress/privateKey) so ARC-402 can compare local endpoint identity against AgentRegistry.",
264
- };
265
- }
266
-
267
- const registryAddress = readAgentRegistryAddress();
268
- if (!registryAddress) {
269
- return {
270
- layer: "registry",
271
- label: "AgentRegistry parity",
272
- ok: false,
273
- detail: "AgentRegistry address missing from config, so on-chain endpoint parity cannot be checked",
274
- fix: "Set `agentRegistryV2Address` in ARC-402 config or select a known network config.",
275
- };
276
- }
277
-
278
- try {
279
- const config = loadConfig();
280
- const { provider } = await getClient(config);
281
- const registry = new AgentRegistryClient(registryAddress, provider);
282
- const agent = await registry.getAgent(walletAddress);
283
-
284
- if (!agent.active && !agent.endpoint) {
285
- return {
286
- layer: "registry",
287
- label: "AgentRegistry parity",
288
- ok: false,
289
- detail: `${walletAddress} is not actively registered with an endpoint in AgentRegistry`,
290
- fix: `Register or update AgentRegistry with \`${endpoint.publicUrl}\` once local ingress is ready.`,
291
- };
292
- }
293
-
294
- if (agent.endpoint === endpoint.publicUrl) {
295
- return {
296
- layer: "registry",
297
- label: "AgentRegistry parity",
298
- ok: true,
299
- detail: `on-chain endpoint matches local canonical URL (${agent.endpoint || endpoint.publicUrl})`,
300
- };
301
- }
302
-
303
- if (!agent.endpoint) {
304
- return {
305
- layer: "registry",
306
- label: "AgentRegistry parity",
307
- ok: false,
308
- detail: `wallet is registered, but no public endpoint is stored on-chain yet (local expects ${endpoint.publicUrl})`,
309
- fix: `Run \`arc402 agent update --name <name> --service-type <type> --endpoint ${endpoint.publicUrl}\` when you want AgentRegistry parity.`,
310
- };
311
- }
312
-
313
- return {
314
- layer: "registry",
315
- label: "AgentRegistry parity",
316
- ok: false,
317
- detail: `mismatch: local canonical URL is ${endpoint.publicUrl}, but AgentRegistry has ${agent.endpoint}`,
318
- fix: `Update AgentRegistry or re-init local endpoint config so the public identity matches one source of truth.`,
319
- };
320
- } catch (err) {
321
- return {
322
- layer: "registry",
323
- label: "AgentRegistry parity",
324
- ok: false,
325
- detail: `could not prove on-chain parity (${err instanceof Error ? err.message : String(err)})`,
326
- fix: "Check RPC / wallet / registry config. If local runtime is healthy, this is a registry-proof gap rather than an ingress failure.",
327
- };
328
- }
329
- }
330
-
331
- async function buildDoctorChecks(endpoint = loadEndpointConfig()): Promise<DoctorCheck[]> {
332
- const checks: DoctorCheck[] = [];
333
-
334
- if (!endpoint) {
335
- checks.push({
336
- layer: "config",
337
- label: "Endpoint config",
338
- ok: false,
339
- detail: `missing (${ENDPOINT_CONFIG_PATH})`,
340
- fix: "Run `arc402 endpoint init <agentname>` first.",
341
- });
342
- checks.push(await checkAgentRegistryParity(endpoint));
343
- checks.push(await checkPublicHostname(endpoint));
344
- return checks;
345
- }
346
-
347
- checks.push({
348
- layer: "config",
349
- label: "Endpoint config",
350
- ok: true,
351
- detail: `${endpoint.publicUrl} → ${endpoint.localIngressTarget}`,
352
- });
353
-
354
- if (endpoint.walletAddress) {
355
- checks.push({
356
- layer: "config",
357
- label: "Wallet binding",
358
- ok: true,
359
- detail: `endpoint config bound to ${endpoint.walletAddress}`,
360
- });
361
- } else {
362
- checks.push({
363
- layer: "config",
364
- label: "Wallet binding",
365
- ok: false,
366
- detail: "endpoint config exists, but no wallet address is recorded for parity checks",
367
- fix: "Set walletContractAddress/privateKey in ARC-402 config and re-run `arc402 endpoint init --force <agentname>` or claim again.",
368
- });
369
- }
370
-
371
- checks.push(checkOpenShell());
372
- checks.push(checkDaemon());
373
-
374
- const localTarget = await checkLocalTarget(endpoint.localIngressTarget);
375
- checks.push({
376
- layer: "ingress",
377
- label: "Local ingress target",
378
- ok: localTarget.ok,
379
- detail: localTarget.detail,
380
- fix: localTarget.ok ? undefined : "Ensure your host ingress target is listening and forwards to the ARC-402 surface you intend to expose.",
381
- });
382
-
383
- checks.push(checkCloudflared(endpoint.tunnelTarget));
384
-
385
- if (endpoint.claimedAt) {
386
- checks.push({
387
- layer: "public",
388
- label: "Subdomain claim",
389
- ok: true,
390
- detail: `claimed at ${endpoint.claimedAt}`,
391
- });
392
- } else {
393
- checks.push({
394
- layer: "public",
395
- label: "Subdomain claim",
396
- ok: false,
397
- detail: "not claimed yet",
398
- fix: `Run \`arc402 endpoint claim ${endpoint.agentName}${endpoint.tunnelTarget ? "" : " --tunnel-target <https://...>"}\`.`,
399
- });
400
- }
401
-
402
- checks.push(await checkPublicHostname(endpoint));
403
- checks.push(await checkAgentRegistryParity(endpoint));
404
-
405
- return checks;
406
- }
407
-
408
- async function claimSubdomain(subdomain: string, walletAddress: string, tunnelTarget: string, apiBase: string): Promise<void> {
409
- const normalized = normalizeAgentName(subdomain);
410
- console.log(`\nClaiming canonical endpoint: https://${normalized}.arc402.xyz`);
411
- console.log(` Wallet: ${walletAddress}`);
412
- console.log(` Tunnel target: ${tunnelTarget}`);
413
- console.log(` API: ${apiBase}`);
414
-
415
- const tryPaths = [
416
- { path: "/register-subdomain", body: { subdomain: normalized, walletAddress, tunnelTarget } },
417
- { path: "/register", body: { subdomain: normalized, walletAddress, tunnelTarget } },
418
- ];
419
-
420
- let lastError = "unknown error";
421
- for (const candidate of tryPaths) {
422
- try {
423
- const res = await fetch(`${apiBase}${candidate.path}`, {
424
- method: "POST",
425
- headers: { "Content-Type": "application/json" },
426
- body: JSON.stringify(candidate.body),
427
- });
428
- const body = await res.json() as Record<string, unknown>;
429
- if (res.ok) {
430
- console.log(chalk.green(`✓ Subdomain claimed: ${body["subdomain"] ?? `${normalized}.arc402.xyz`}`));
431
- return;
432
- }
433
- lastError = `${candidate.path}: ${String(body["error"] ?? res.statusText)}`;
434
- } catch (err) {
435
- lastError = `${candidate.path}: ${err instanceof Error ? err.message : String(err)}`;
436
- }
437
- }
438
-
439
- throw new Error(lastError);
440
- }
441
-
442
- export function registerEndpointCommands(program: Command): void {
443
- const endpoint = program
444
- .command("endpoint")
445
- .description("Canonical public endpoint scaffold for ARC-402 launch: public ingress identity outside the sandbox, runtime still sandboxed inside OpenShell.");
446
-
447
- endpoint
448
- .command("init [agentName]")
449
- .description("Scaffold the canonical endpoint config for <agentname>.arc402.xyz and the host-managed ingress target. This does not claim DNS or open outbound sandbox policy.")
450
- .option("--local-ingress-target <url>", "Host ingress target the tunnel/proxy should forward into", DEFAULT_LOCAL_INGRESS_TARGET)
451
- .option("--tunnel-target <url>", "Public tunnel target / route metadata if already known (must be https://... for claim flows)")
452
- .option("--force", "Overwrite the existing endpoint scaffold")
453
- .action((agentName: string | undefined, opts) => {
454
- const existing = loadEndpointConfig();
455
- if (existing && !opts.force && !agentName) {
456
- console.log(`Endpoint config already exists at ${ENDPOINT_CONFIG_PATH}`);
457
- console.log(` Public URL: ${existing.publicUrl}`);
458
- console.log(` Local target: ${existing.localIngressTarget}`);
459
- console.log("Use --force to replace it, or pass a new agent name explicitly.");
460
- return;
461
- }
462
-
463
- const chosenName = agentName ?? existing?.agentName;
464
- if (!chosenName) {
465
- console.error("Agent name is required the first time. Example: arc402 endpoint init gigabrain");
466
- process.exit(1);
467
- }
468
-
469
- const walletAddress = readWalletAddress();
470
- const cfg = buildEndpointConfig({
471
- agentName: chosenName,
472
- localIngressTarget: opts.localIngressTarget,
473
- tunnelTarget: opts.tunnelTarget,
474
- walletAddress,
475
- subdomainApi: readSubdomainApi(),
476
- existing,
477
- notes: "Launch default: host-managed Cloudflare Tunnel outside the sandbox. Public ingress identity is separate from OpenShell outbound policy.",
478
- });
479
- saveEndpointConfig(cfg);
480
-
481
- console.log(c.success + c.white(' Endpoint scaffold written: ' + ENDPOINT_CONFIG_PATH));
482
- console.log(` Agent name: ${cfg.agentName}`);
483
- console.log(` Hostname: ${cfg.hostname}`);
484
- console.log(` Public URL: ${cfg.publicUrl}`);
485
- console.log(` Tunnel mode: ${cfg.tunnelMode}`);
486
- console.log(` Local target: ${cfg.localIngressTarget}`);
487
- if (cfg.tunnelTarget) console.log(` Tunnel target: ${cfg.tunnelTarget}`);
488
- console.log(` Wallet: ${cfg.walletAddress ?? "not yet resolved"}`);
489
- console.log("\nArchitecture truth:");
490
- console.log(" • ARC-402 runtime stays inside the OpenShell sandbox.");
491
- console.log(" • This command only locks the public-ingress identity + host target.");
492
- console.log(" • Sandbox outbound policy remains separate: use `arc402 openshell policy ...` for peer/API allowlists.");
493
- console.log("\nNext:");
494
- console.log(` 1. Start your host-managed tunnel toward ${cfg.localIngressTarget}`);
495
- console.log(` 2. Claim the canonical hostname: arc402 endpoint claim ${cfg.agentName}${cfg.tunnelTarget ? "" : " --tunnel-target <https://your-tunnel.example.com>"}`);
496
- console.log(" 3. Verify the whole chain: arc402 endpoint status");
497
- });
498
-
499
- endpoint
500
- .command("status")
501
- .description("Show the current endpoint scaffold and whether local runtime/ingress pieces line up. Useful now even before DNS automation is complete.")
502
- .action(async () => {
503
- const cfg = loadEndpointConfig();
504
- if (!cfg) {
505
- console.error(`No endpoint config found at ${ENDPOINT_CONFIG_PATH}`);
506
- console.error("Run: arc402 endpoint init <agentname>");
507
- process.exit(1);
508
- }
509
-
510
- const checks = await buildDoctorChecks(cfg);
511
- const allGood = checks.every((check) => check.ok);
512
- const brokenLayers = Array.from(new Set(checks.filter((check) => !check.ok).map((check) => check.layer)));
513
-
514
- console.log('\n ' + c.mark + c.white(' ARC-402 Endpoint Status'));
515
- console.log("─────────────────────");
516
- console.log(`Agent name: ${cfg.agentName}`);
517
- console.log(`Hostname: ${cfg.hostname}`);
518
- console.log(`Public URL: ${cfg.publicUrl}`);
519
- console.log(`Tunnel mode: ${cfg.tunnelMode}`);
520
- console.log(`Local target: ${cfg.localIngressTarget}`);
521
- console.log(`Tunnel target: ${cfg.tunnelTarget ?? "not set"}`);
522
- console.log(`Claimed at: ${cfg.claimedAt ?? "not yet claimed"}`);
523
- console.log(`Config file: ${ENDPOINT_CONFIG_PATH}`);
524
- console.log(`\nReadiness: ${allGood ? chalk.green("fully proven for current launch scope") : chalk.yellow("partial proof / needs attention")}`);
525
- if (brokenLayers.length) {
526
- console.log(`Broken layers: ${brokenLayers.join(", ")}`);
527
- }
528
- console.log();
529
-
530
- for (const check of checks) {
531
- console.log(`${check.ok ? chalk.green("✓") : chalk.yellow("!")} [${check.layer}] ${check.label.padEnd(20)} ${check.detail}`);
532
- }
533
-
534
- console.log("\nWhat this proves now:");
535
- console.log(" • canonical endpoint identity is locked locally");
536
- console.log(" • runtime sandboxing is checked separately from ingress");
537
- console.log(" • local ingress target + daemon/tunnel wiring can be diagnosed without pretending every external layer is automated");
538
- console.log(" • AgentRegistry/public-hostname parity is checked when config + RPC + wallet context make proof possible");
539
- });
540
-
541
- endpoint
542
- .command("claim <agentName>")
543
- .description("Claim the canonical <agentname>.arc402.xyz hostname and lock the local endpoint config to it. Uses the launch-default host-managed ingress model.")
544
- .requiredOption("--tunnel-target <url>", "Public tunnel target registered behind the canonical hostname (must start with https://)")
545
- .action(async (agentName: string, opts) => {
546
- if (!opts.tunnelTarget.startsWith("https://")) {
547
- console.error("--tunnel-target must start with https://");
548
- process.exit(1);
549
- }
550
-
551
- const walletAddress = readWalletAddress();
552
- if (!walletAddress) {
553
- console.error("No wallet address could be resolved from ARC-402 config.");
554
- console.error("Run `arc402 config init` (or set walletContractAddress/privateKey) first.");
555
- process.exit(1);
556
- }
557
-
558
- const existing = loadEndpointConfig();
559
- const normalized = normalizeAgentName(agentName);
560
- const apiBase = readSubdomainApi();
561
- await claimSubdomain(normalized, walletAddress, opts.tunnelTarget, apiBase);
562
-
563
- const cfg = buildEndpointConfig({
564
- agentName: normalized,
565
- localIngressTarget: existing?.localIngressTarget ?? DEFAULT_LOCAL_INGRESS_TARGET,
566
- tunnelTarget: opts.tunnelTarget,
567
- walletAddress,
568
- subdomainApi: apiBase,
569
- existing,
570
- claimedAt: new Date().toISOString(),
571
- notes: existing?.notes,
572
- });
573
- saveEndpointConfig(cfg);
574
-
575
- console.log(c.success + c.white(' Endpoint config locked to ' + cfg.publicUrl));
576
- console.log(` Hostname: ${cfg.hostname}`);
577
- console.log(` Tunnel target: ${cfg.tunnelTarget}`);
578
- console.log(` Wallet: ${cfg.walletAddress}`);
579
- console.log("\nOptional next step if you have not updated AgentRegistry yet:");
580
- console.log(` arc402 agent update --name <name> --service-type <type> --endpoint ${cfg.publicUrl}`);
581
- });
582
-
583
- endpoint
584
- .command("doctor")
585
- .description("Diagnose the broken layer without blurring ingress, runtime sandbox, or public identity.")
586
- .action(async () => {
587
- const checks = await buildDoctorChecks();
588
- console.log("ARC-402 Endpoint Doctor");
589
- console.log("─────────────────────");
590
-
591
- const failuresByLayer = new Map<string, number>();
592
- let failures = 0;
593
- for (const check of checks) {
594
- if (check.ok) {
595
- console.log(`${chalk.green("✓")} [${check.layer}] ${check.label}: ${check.detail}`);
596
- continue;
597
- }
598
- failures += 1;
599
- failuresByLayer.set(check.layer, (failuresByLayer.get(check.layer) ?? 0) + 1);
600
- console.log(`${chalk.red("✗")} [${check.layer}] ${check.label}: ${check.detail}`);
601
- if (check.fix) console.log(` Fix: ${check.fix}`);
602
- }
603
-
604
- if (failures === 0) {
605
- console.log(chalk.green("\nNo obvious scaffold-layer breakage detected."));
606
- } else {
607
- console.log(chalk.yellow(`\n${failures} check(s) failed across ${failuresByLayer.size} layer(s): ${Array.from(failuresByLayer.keys()).join(", ")}.`));
608
- }
609
-
610
- console.log("\nLayer model:");
611
- console.log(" 1. config / local source of truth");
612
- console.log(" 2. public identity (`agentname.arc402.xyz`)");
613
- console.log(" 3. host-managed ingress / tunnel");
614
- console.log(" 4. local ingress target");
615
- console.log(" 5. ARC-402 runtime inside OpenShell");
616
- console.log(" 6. AgentRegistry/public-endpoint parity");
617
- console.log(" 7. sandbox outbound policy (separate; not implied by public ingress)");
618
- console.log("\nIf only the registry/public checks fail while local runtime is healthy, the proof is partial rather than the stack being fully down.");
619
- });
620
- }