arc402-cli 0.9.19 → 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 (359) 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.d.ts.map +1 -1
  161. package/dist/endpoint-notify.js +49 -15
  162. package/dist/endpoint-notify.js.map +1 -1
  163. package/dist/index.js +50 -18
  164. package/dist/index.js.map +1 -1
  165. package/dist/openshell-runtime.d.ts.map +1 -1
  166. package/dist/openshell-runtime.js +82 -38
  167. package/dist/openshell-runtime.js.map +1 -1
  168. package/dist/program.d.ts.map +1 -1
  169. package/dist/program.js +85 -78
  170. package/dist/program.js.map +1 -1
  171. package/dist/repl.js +31 -25
  172. package/dist/repl.js.map +1 -1
  173. package/dist/signing.js +6 -3
  174. package/dist/signing.js.map +1 -1
  175. package/dist/telegram-notify.js +40 -3
  176. package/dist/telegram-notify.js.map +1 -1
  177. package/dist/tui/App.d.ts.map +1 -1
  178. package/dist/tui/App.js +56 -89
  179. package/dist/tui/App.js.map +1 -1
  180. package/dist/tui/Footer.js +7 -4
  181. package/dist/tui/Footer.js.map +1 -1
  182. package/dist/tui/Header.d.ts +1 -1
  183. package/dist/tui/Header.d.ts.map +1 -1
  184. package/dist/tui/Header.js +14 -9
  185. package/dist/tui/Header.js.map +1 -1
  186. package/dist/tui/InputLine.d.ts +2 -1
  187. package/dist/tui/InputLine.d.ts.map +1 -1
  188. package/dist/tui/InputLine.js +47 -97
  189. package/dist/tui/InputLine.js.map +1 -1
  190. package/dist/tui/Viewport.d.ts +1 -2
  191. package/dist/tui/Viewport.d.ts.map +1 -1
  192. package/dist/tui/Viewport.js +26 -6
  193. package/dist/tui/Viewport.js.map +1 -1
  194. package/dist/tui/WalletConnectPairing.js +19 -16
  195. package/dist/tui/WalletConnectPairing.js.map +1 -1
  196. package/dist/tui/components/Button.js +9 -6
  197. package/dist/tui/components/Button.js.map +1 -1
  198. package/dist/tui/components/CeremonyView.js +8 -5
  199. package/dist/tui/components/CeremonyView.js.map +1 -1
  200. package/dist/tui/components/CompletionDropdown.js +9 -6
  201. package/dist/tui/components/CompletionDropdown.js.map +1 -1
  202. package/dist/tui/components/ConfirmPrompt.js +8 -5
  203. package/dist/tui/components/ConfirmPrompt.js.map +1 -1
  204. package/dist/tui/components/CustomTextInput.js +14 -11
  205. package/dist/tui/components/CustomTextInput.js.map +1 -1
  206. package/dist/tui/components/InteractiveTable.js +12 -9
  207. package/dist/tui/components/InteractiveTable.js.map +1 -1
  208. package/dist/tui/components/StepSpinner.js +13 -10
  209. package/dist/tui/components/StepSpinner.js.map +1 -1
  210. package/dist/tui/components/Toast.js +12 -8
  211. package/dist/tui/components/Toast.js.map +1 -1
  212. package/dist/tui/index.d.ts.map +1 -1
  213. package/dist/tui/index.js +21 -28
  214. package/dist/tui/index.js.map +1 -1
  215. package/dist/tui/useChat.js +19 -13
  216. package/dist/tui/useChat.js.map +1 -1
  217. package/dist/tui/useCommand.d.ts +2 -3
  218. package/dist/tui/useCommand.d.ts.map +1 -1
  219. package/dist/tui/useCommand.js +24 -100
  220. package/dist/tui/useCommand.js.map +1 -1
  221. package/dist/tui/useNotifications.js +8 -5
  222. package/dist/tui/useNotifications.js.map +1 -1
  223. package/dist/tui/useScroll.d.ts.map +1 -1
  224. package/dist/tui/useScroll.js +12 -15
  225. package/dist/tui/useScroll.js.map +1 -1
  226. package/dist/ui/banner.d.ts +0 -12
  227. package/dist/ui/banner.d.ts.map +1 -1
  228. package/dist/ui/banner.js +19 -35
  229. package/dist/ui/banner.js.map +1 -1
  230. package/dist/ui/colors.js +19 -13
  231. package/dist/ui/colors.js.map +1 -1
  232. package/dist/ui/format.js +14 -6
  233. package/dist/ui/format.js.map +1 -1
  234. package/dist/ui/qr-render.js +11 -4
  235. package/dist/ui/qr-render.js.map +1 -1
  236. package/dist/ui/rpc-fallback.js +11 -6
  237. package/dist/ui/rpc-fallback.js.map +1 -1
  238. package/dist/ui/spinner.js +12 -6
  239. package/dist/ui/spinner.js.map +1 -1
  240. package/dist/ui/tree.js +6 -3
  241. package/dist/ui/tree.js.map +1 -1
  242. package/dist/utils/format.js +41 -27
  243. package/dist/utils/format.js.map +1 -1
  244. package/dist/utils/hash.js +42 -4
  245. package/dist/utils/hash.js.map +1 -1
  246. package/dist/utils/time.js +6 -2
  247. package/dist/utils/time.js.map +1 -1
  248. package/dist/wallet-router.d.ts +1 -1
  249. package/dist/wallet-router.d.ts.map +1 -1
  250. package/dist/wallet-router.js +19 -12
  251. package/dist/wallet-router.js.map +1 -1
  252. package/dist/walletconnect-session.d.ts +1 -1
  253. package/dist/walletconnect-session.d.ts.map +1 -1
  254. package/dist/walletconnect-session.js +11 -6
  255. package/dist/walletconnect-session.js.map +1 -1
  256. package/dist/walletconnect.d.ts +5 -6
  257. package/dist/walletconnect.d.ts.map +1 -1
  258. package/dist/walletconnect.js +35 -32
  259. package/dist/walletconnect.js.map +1 -1
  260. package/package.json +11 -10
  261. package/INK6-UX-SPEC.md +0 -446
  262. package/MIGRATION-SPEC.md +0 -108
  263. package/TUI-SPEC.md +0 -214
  264. package/scripts/authorize-machine-key.ts +0 -43
  265. package/scripts/drain-wallet.ts +0 -149
  266. package/scripts/execute-spend-only.ts +0 -81
  267. package/scripts/register-agent-userop.ts +0 -186
  268. package/src/abis.ts +0 -187
  269. package/src/bundler.ts +0 -235
  270. package/src/client.ts +0 -36
  271. package/src/coinbase-smart-wallet.ts +0 -51
  272. package/src/commands/accept.ts +0 -64
  273. package/src/commands/agent-handshake.ts +0 -72
  274. package/src/commands/agent.ts +0 -691
  275. package/src/commands/agreements.ts +0 -350
  276. package/src/commands/arbitrator.ts +0 -180
  277. package/src/commands/arena-handshake.ts +0 -274
  278. package/src/commands/arena.ts +0 -122
  279. package/src/commands/backup.ts +0 -117
  280. package/src/commands/cancel.ts +0 -35
  281. package/src/commands/channel.ts +0 -218
  282. package/src/commands/coldstart.ts +0 -165
  283. package/src/commands/config.ts +0 -68
  284. package/src/commands/contract-interaction.ts +0 -166
  285. package/src/commands/daemon.ts +0 -1054
  286. package/src/commands/deliver.ts +0 -148
  287. package/src/commands/discover.ts +0 -350
  288. package/src/commands/dispute.ts +0 -375
  289. package/src/commands/doctor.ts +0 -172
  290. package/src/commands/endpoint.ts +0 -620
  291. package/src/commands/feed.ts +0 -229
  292. package/src/commands/hire.ts +0 -245
  293. package/src/commands/migrate.ts +0 -177
  294. package/src/commands/negotiate.ts +0 -272
  295. package/src/commands/openshell.ts +0 -1055
  296. package/src/commands/owner.ts +0 -35
  297. package/src/commands/policy.ts +0 -263
  298. package/src/commands/relay.ts +0 -277
  299. package/src/commands/remediate.ts +0 -24
  300. package/src/commands/reputation.ts +0 -79
  301. package/src/commands/setup.ts +0 -343
  302. package/src/commands/trust.ts +0 -27
  303. package/src/commands/verify.ts +0 -91
  304. package/src/commands/wallet.ts +0 -3548
  305. package/src/commands/watch.ts +0 -220
  306. package/src/commands/watchtower.ts +0 -248
  307. package/src/commands/workroom.ts +0 -963
  308. package/src/config.ts +0 -220
  309. package/src/daemon/config.ts +0 -344
  310. package/src/daemon/hire-listener.ts +0 -226
  311. package/src/daemon/index.ts +0 -1089
  312. package/src/daemon/job-lifecycle.ts +0 -215
  313. package/src/daemon/notify.ts +0 -297
  314. package/src/daemon/token-metering.ts +0 -183
  315. package/src/daemon/userops.ts +0 -119
  316. package/src/daemon/wallet-monitor.ts +0 -90
  317. package/src/drain-v4.ts +0 -159
  318. package/src/endpoint-config.ts +0 -83
  319. package/src/endpoint-notify.ts +0 -134
  320. package/src/index.ts +0 -74
  321. package/src/openshell-runtime.ts +0 -281
  322. package/src/program.ts +0 -88
  323. package/src/repl.ts +0 -178
  324. package/src/signing.ts +0 -28
  325. package/src/telegram-notify.ts +0 -88
  326. package/src/tui/App.tsx +0 -263
  327. package/src/tui/Footer.tsx +0 -18
  328. package/src/tui/Header.tsx +0 -45
  329. package/src/tui/InputLine.tsx +0 -243
  330. package/src/tui/Viewport.tsx +0 -51
  331. package/src/tui/WalletConnectPairing.tsx +0 -114
  332. package/src/tui/components/Button.tsx +0 -38
  333. package/src/tui/components/CeremonyView.tsx +0 -39
  334. package/src/tui/components/CompletionDropdown.tsx +0 -56
  335. package/src/tui/components/ConfirmPrompt.tsx +0 -36
  336. package/src/tui/components/CustomTextInput.tsx +0 -132
  337. package/src/tui/components/InteractiveTable.tsx +0 -106
  338. package/src/tui/components/StepSpinner.tsx +0 -84
  339. package/src/tui/components/Toast.tsx +0 -59
  340. package/src/tui/index.tsx +0 -90
  341. package/src/tui/useChat.ts +0 -103
  342. package/src/tui/useCommand.ts +0 -238
  343. package/src/tui/useNotifications.ts +0 -28
  344. package/src/tui/useScroll.ts +0 -69
  345. package/src/ui/banner.ts +0 -78
  346. package/src/ui/colors.ts +0 -30
  347. package/src/ui/format.ts +0 -78
  348. package/src/ui/qr-render.ts +0 -92
  349. package/src/ui/rpc-fallback.ts +0 -59
  350. package/src/ui/spinner.ts +0 -56
  351. package/src/ui/tree.ts +0 -16
  352. package/src/utils/format.ts +0 -48
  353. package/src/utils/hash.ts +0 -5
  354. package/src/utils/time.ts +0 -15
  355. package/src/wallet-router.ts +0 -178
  356. package/src/walletconnect-session.ts +0 -27
  357. package/src/walletconnect.ts +0 -309
  358. package/test/time.test.js +0 -11
  359. package/tsconfig.json +0 -33
@@ -1,114 +0,0 @@
1
- import React, { useState, useEffect, useCallback } from "react";
2
- import { Box, Text } from "ink";
3
- import type { WCCallbacks } from "../walletconnect.js";
4
- import { renderQR } from "../ui/qr-render.js";
5
-
6
- export type WCStage = "connecting" | "connected" | "chain-switching" | "ready" | "error";
7
-
8
- interface WalletConnectPairingProps {
9
- projectId: string;
10
- chainId: number;
11
- onComplete: (result: { account: string }) => void;
12
- onError: (err: string) => void;
13
- /** Called once the component mounts — parent passes the connect function */
14
- connect: (callbacks: WCCallbacks) => Promise<{ account: string }>;
15
- }
16
-
17
- /**
18
- * Renders WalletConnect pairing inside the Ink TUI viewport:
19
- * - ASCII QR code
20
- * - Deep links for MetaMask, Rainbow, Trust, etc.
21
- * - Status transitions: connecting → connected → chain-switching → ready
22
- */
23
- export function WalletConnectPairing({
24
- onComplete,
25
- onError,
26
- connect,
27
- }: WalletConnectPairingProps) {
28
- const [stage, setStage] = useState<WCStage>("connecting");
29
- const [uri, setUri] = useState<string | null>(null);
30
- const [links, setLinks] = useState<Record<string, string>>({});
31
- const [account, setAccount] = useState<string | null>(null);
32
- const [qrLines, setQrLines] = useState<string[]>([]);
33
- const [detail, setDetail] = useState<string>("");
34
-
35
- const handleUri = useCallback((wcUri: string, wcLinks: Record<string, string>) => {
36
- setUri(wcUri);
37
- setLinks(wcLinks);
38
- // Generate ASCII QR using our compact renderer
39
- try {
40
- const lines = renderQR(wcUri);
41
- setQrLines(lines);
42
- } catch {
43
- // QR rendering is best-effort
44
- }
45
- }, []);
46
-
47
- const handleStatus = useCallback((status: WCStage, statusDetail?: string) => {
48
- setStage(status);
49
- if (statusDetail) setDetail(statusDetail);
50
- if (status === "connected" && statusDetail) {
51
- setAccount(statusDetail);
52
- }
53
- }, []);
54
-
55
- useEffect(() => {
56
- const callbacks: WCCallbacks = {
57
- onUri: handleUri,
58
- onStatus: handleStatus,
59
- };
60
- connect(callbacks)
61
- .then((result) => onComplete(result))
62
- .catch((err: unknown) => onError(err instanceof Error ? err.message : String(err)));
63
- }, [connect, handleUri, handleStatus, onComplete, onError]);
64
-
65
- const statusIcon = stage === "error" ? "✗" : stage === "ready" ? "✓" : "◈";
66
- const statusColor = stage === "error" ? "red" : stage === "ready" ? "green" : "cyan";
67
-
68
- const statusMessages: Record<WCStage, string> = {
69
- connecting: "Waiting for wallet approval...",
70
- connected: `Connected: ${account ?? ""}`,
71
- "chain-switching": `Switching chain${detail ? `: ${detail}` : ""}...`,
72
- ready: `Ready — ${account ?? ""}`,
73
- error: detail || "Connection failed",
74
- };
75
-
76
- return (
77
- <Box flexDirection="column" paddingLeft={1}>
78
- <Text color="cyan" bold>WalletConnect Pairing</Text>
79
- <Text> </Text>
80
-
81
- {/* Status */}
82
- <Box>
83
- <Text color={statusColor}>{statusIcon} </Text>
84
- <Text>{statusMessages[stage]}</Text>
85
- </Box>
86
- <Text> </Text>
87
-
88
- {/* Deep links */}
89
- {uri && stage === "connecting" && (
90
- <>
91
- <Text dimColor>Tap a link for your wallet app:</Text>
92
- <Text> </Text>
93
- {Object.entries(links).map(([name, link]) => (
94
- <Box key={name} flexDirection="column">
95
- <Text color="white">{name}:</Text>
96
- <Text dimColor>{link}</Text>
97
- <Text> </Text>
98
- </Box>
99
- ))}
100
-
101
- {/* QR code */}
102
- {qrLines.length > 0 && (
103
- <>
104
- <Text dimColor>Or scan QR:</Text>
105
- {qrLines.map((line, i) => (
106
- <Text key={i}>{line}</Text>
107
- ))}
108
- </>
109
- )}
110
- </>
111
- )}
112
- </Box>
113
- );
114
- }
@@ -1,38 +0,0 @@
1
- import React from "react";
2
- import { Box, Text, useFocus, useInput } from "ink";
3
-
4
- export interface ButtonProps {
5
- label: string;
6
- onPress: () => void;
7
- variant?: "primary" | "danger" | "dim";
8
- }
9
-
10
- const VARIANT_COLORS: Record<string, string> = {
11
- primary: "cyan",
12
- danger: "red",
13
- dim: "gray",
14
- };
15
-
16
- export function Button({ label, onPress, variant = "primary" }: ButtonProps) {
17
- const { isFocused } = useFocus();
18
-
19
- useInput(
20
- (_input, key) => {
21
- if (key.return) {
22
- onPress();
23
- }
24
- },
25
- { isActive: isFocused }
26
- );
27
-
28
- const color = isFocused ? VARIANT_COLORS[variant] ?? "cyan" : "white";
29
-
30
- return (
31
- <Box>
32
- <Text color={color} bold={isFocused}>
33
- {isFocused ? "▸ " : " "}
34
- {label}
35
- </Text>
36
- </Box>
37
- );
38
- }
@@ -1,39 +0,0 @@
1
- import React from "react";
2
- import { Box, Text } from "ink";
3
- import { StepSpinner } from "./StepSpinner.js";
4
- import type { StepStatus } from "./StepSpinner.js";
5
-
6
- export interface CeremonyStep {
7
- label: string;
8
- status: StepStatus;
9
- detail?: string;
10
- error?: string;
11
- }
12
-
13
- export interface CeremonyViewProps {
14
- title: string;
15
- steps: CeremonyStep[];
16
- }
17
-
18
- export function CeremonyView({ title, steps }: CeremonyViewProps) {
19
- return (
20
- <Box flexDirection="column">
21
- <Box marginBottom={1}>
22
- <Text bold color="cyan">
23
- ◈ {title}
24
- </Text>
25
- </Box>
26
- {steps.map((step, i) => (
27
- <StepSpinner
28
- key={i}
29
- step={i + 1}
30
- total={steps.length}
31
- label={step.label}
32
- status={step.status}
33
- detail={step.detail}
34
- error={step.error}
35
- />
36
- ))}
37
- </Box>
38
- );
39
- }
@@ -1,56 +0,0 @@
1
- import React from "react";
2
- import { Box, Text } from "ink";
3
-
4
- export interface CompletionDropdownProps {
5
- candidates: string[];
6
- selectedIndex: number;
7
- visible: boolean;
8
- }
9
-
10
- const MAX_VISIBLE = 8;
11
-
12
- export function CompletionDropdown({
13
- candidates,
14
- selectedIndex,
15
- visible,
16
- }: CompletionDropdownProps) {
17
- if (!visible || candidates.length === 0) return null;
18
-
19
- // Window the list if there are too many candidates
20
- let startIdx = 0;
21
- if (candidates.length > MAX_VISIBLE) {
22
- startIdx = Math.max(0, selectedIndex - Math.floor(MAX_VISIBLE / 2));
23
- startIdx = Math.min(startIdx, candidates.length - MAX_VISIBLE);
24
- }
25
- const visibleCandidates = candidates.slice(
26
- startIdx,
27
- startIdx + MAX_VISIBLE
28
- );
29
-
30
- return (
31
- <Box flexDirection="column" marginLeft={4}>
32
- <Box>
33
- <Text dimColor>{"┌─ completions ─"}</Text>
34
- </Box>
35
- {visibleCandidates.map((candidate, i) => {
36
- const actualIdx = startIdx + i;
37
- const isSelected = actualIdx === selectedIndex;
38
- return (
39
- <Box key={candidate}>
40
- <Text dimColor>{"│"}</Text>
41
- <Text color={isSelected ? "cyan" : "white"} bold={isSelected}>
42
- {isSelected ? " ▸ " : " "}
43
- {candidate}
44
- </Text>
45
- </Box>
46
- );
47
- })}
48
- <Box>
49
- <Text dimColor>{"└─"}</Text>
50
- {candidates.length > MAX_VISIBLE && (
51
- <Text dimColor>{" "}({candidates.length} total)</Text>
52
- )}
53
- </Box>
54
- </Box>
55
- );
56
- }
@@ -1,36 +0,0 @@
1
- import React from "react";
2
- import { Box, Text } from "ink";
3
- import { Button } from "./Button.js";
4
-
5
- export interface ConfirmPromptProps {
6
- message: string;
7
- onConfirm: () => void;
8
- onCancel: () => void;
9
- confirmLabel?: string;
10
- cancelLabel?: string;
11
- }
12
-
13
- export function ConfirmPrompt({
14
- message,
15
- onConfirm,
16
- onCancel,
17
- confirmLabel = "Confirm",
18
- cancelLabel = "Cancel",
19
- }: ConfirmPromptProps) {
20
- return (
21
- <Box flexDirection="column">
22
- <Box marginBottom={1}>
23
- <Text bold color="cyan">
24
- ◈ {message}
25
- </Text>
26
- </Box>
27
- <Box gap={2}>
28
- <Button label={confirmLabel} onPress={onConfirm} variant="primary" />
29
- <Button label={cancelLabel} onPress={onCancel} variant="dim" />
30
- </Box>
31
- <Box marginTop={1}>
32
- <Text dimColor>Tab to switch · Enter to select</Text>
33
- </Box>
34
- </Box>
35
- );
36
- }
@@ -1,132 +0,0 @@
1
- import React, { useState, useEffect } from "react";
2
- import { Text, useInput } from "ink";
3
-
4
- interface CustomTextInputProps {
5
- value: string;
6
- onChange: (value: string) => void;
7
- onSubmit?: (value: string) => void;
8
- focus?: boolean;
9
- /** When true, Enter key is NOT handled — let parent handle it (e.g. dropdown selection) */
10
- suppressEnter?: boolean;
11
- }
12
-
13
- /**
14
- * Minimal text input that does NOT intercept Tab, Up, Down, Escape, or Ctrl+C,
15
- * allowing parent useInput handlers to receive those keys.
16
- */
17
- export function CustomTextInput({
18
- value,
19
- onChange,
20
- onSubmit,
21
- focus = true,
22
- suppressEnter = false,
23
- }: CustomTextInputProps) {
24
- const [cursorPos, setCursorPos] = useState(value.length);
25
- const [cursorVisible, setCursorVisible] = useState(true);
26
-
27
- // Keep cursor within bounds when value changes externally
28
- useEffect(() => {
29
- setCursorPos((pos) => Math.min(pos, value.length));
30
- }, [value]);
31
-
32
- // Blink cursor
33
- useEffect(() => {
34
- if (!focus) return;
35
- const timer = setInterval(() => {
36
- setCursorVisible((v) => !v);
37
- }, 530);
38
- return () => clearInterval(timer);
39
- }, [focus]);
40
-
41
- useInput(
42
- (input, key) => {
43
- // Keys we explicitly do NOT handle — let parent see them:
44
- // Tab, Up, Down, Escape, Ctrl+C
45
- if (key.tab || key.upArrow || key.downArrow || key.escape) return;
46
- if (input === "\x03") return; // Ctrl+C
47
-
48
- // Enter/Return — submit (unless suppressed for dropdown selection)
49
- if (key.return) {
50
- if (!suppressEnter) {
51
- onSubmit?.(value);
52
- }
53
- return;
54
- }
55
-
56
- // Backspace
57
- if (key.backspace || key.delete) {
58
- if (cursorPos > 0) {
59
- const next = value.slice(0, cursorPos - 1) + value.slice(cursorPos);
60
- setCursorPos(cursorPos - 1);
61
- onChange(next);
62
- }
63
- return;
64
- }
65
-
66
- // Left arrow
67
- if (key.leftArrow) {
68
- setCursorPos((p) => Math.max(0, p - 1));
69
- return;
70
- }
71
-
72
- // Right arrow
73
- if (key.rightArrow) {
74
- setCursorPos((p) => Math.min(value.length, p + 1));
75
- return;
76
- }
77
-
78
- // Home (Ctrl+A)
79
- if (input === "\x01") {
80
- setCursorPos(0);
81
- return;
82
- }
83
-
84
- // End (Ctrl+E)
85
- if (input === "\x05") {
86
- setCursorPos(value.length);
87
- return;
88
- }
89
-
90
- // Ctrl+U — clear line
91
- if (input === "\x15") {
92
- setCursorPos(0);
93
- onChange("");
94
- return;
95
- }
96
-
97
- // Ctrl+K — kill to end of line
98
- if (input === "\x0B") {
99
- onChange(value.slice(0, cursorPos));
100
- return;
101
- }
102
-
103
- // Ignore other control characters
104
- if (input.length > 0 && input.charCodeAt(0) < 32) return;
105
-
106
- // Regular character input (including paste)
107
- if (input.length > 0) {
108
- const next =
109
- value.slice(0, cursorPos) + input + value.slice(cursorPos);
110
- setCursorPos(cursorPos + input.length);
111
- onChange(next);
112
- }
113
- },
114
- { isActive: focus }
115
- );
116
-
117
- if (!focus) {
118
- return <Text dimColor>{value}</Text>;
119
- }
120
-
121
- const before = value.slice(0, cursorPos);
122
- const cursorChar = cursorPos < value.length ? value[cursorPos] : " ";
123
- const after = value.slice(cursorPos + 1);
124
-
125
- return (
126
- <Text>
127
- {before}
128
- <Text inverse={cursorVisible}>{cursorChar}</Text>
129
- {after}
130
- </Text>
131
- );
132
- }
@@ -1,106 +0,0 @@
1
- import React, { useState } from "react";
2
- import { Box, Text, useInput } from "ink";
3
-
4
- export interface Column {
5
- header: string;
6
- key: string;
7
- width?: number;
8
- align?: "left" | "right";
9
- }
10
-
11
- export interface InteractiveTableProps {
12
- columns: Column[];
13
- rows: Record<string, string>[];
14
- onSelect?: (row: Record<string, string>, index: number) => void;
15
- selectedIndex?: number;
16
- }
17
-
18
- const MAX_VISIBLE_ROWS = 15;
19
-
20
- export function InteractiveTable({
21
- columns,
22
- rows,
23
- onSelect,
24
- selectedIndex: controlledIdx,
25
- }: InteractiveTableProps) {
26
- const [internalIdx, setInternalIdx] = useState(0);
27
- const selectedIndex = controlledIdx ?? internalIdx;
28
-
29
- useInput((_input, key) => {
30
- if (key.upArrow) {
31
- setInternalIdx((i) => Math.max(0, i - 1));
32
- }
33
- if (key.downArrow) {
34
- setInternalIdx((i) => Math.min(rows.length - 1, i + 1));
35
- }
36
- if (key.return && onSelect && rows[selectedIndex]) {
37
- onSelect(rows[selectedIndex], selectedIndex);
38
- }
39
- });
40
-
41
- // Compute column widths
42
- const colWidths = columns.map((col) => {
43
- if (col.width) return col.width;
44
- let max = col.header.length;
45
- for (const row of rows) {
46
- const val = row[col.key] ?? "";
47
- if (val.length > max) max = val.length;
48
- }
49
- return Math.min(max + 2, 30);
50
- });
51
-
52
- const pad = (text: string, width: number, align: "left" | "right" = "left"): string => {
53
- const truncated = text.length > width ? text.slice(0, width - 1) + "…" : text;
54
- if (align === "right") return truncated.padStart(width);
55
- return truncated.padEnd(width);
56
- };
57
-
58
- // Window visible rows
59
- let startRow = 0;
60
- if (rows.length > MAX_VISIBLE_ROWS) {
61
- startRow = Math.max(0, selectedIndex - Math.floor(MAX_VISIBLE_ROWS / 2));
62
- startRow = Math.min(startRow, rows.length - MAX_VISIBLE_ROWS);
63
- }
64
- const visibleRows = rows.slice(startRow, startRow + MAX_VISIBLE_ROWS);
65
-
66
- // Header
67
- const headerLine = columns
68
- .map((col, i) => pad(col.header, colWidths[i], col.align))
69
- .join(" ");
70
- const separatorLine = "─".repeat(headerLine.length);
71
-
72
- return (
73
- <Box flexDirection="column">
74
- <Box>
75
- <Text bold color="white">{" "}{headerLine}</Text>
76
- </Box>
77
- <Box>
78
- <Text dimColor> {separatorLine}</Text>
79
- </Box>
80
- {visibleRows.map((row, vi) => {
81
- const actualIdx = startRow + vi;
82
- const isSelected = actualIdx === selectedIndex;
83
- const line = columns
84
- .map((col, i) => pad(row[col.key] ?? "", colWidths[i], col.align))
85
- .join(" ");
86
- return (
87
- <Box key={actualIdx}>
88
- <Text color={isSelected ? "cyan" : "white"} bold={isSelected}>
89
- {isSelected ? "▸" : " "} {line}
90
- </Text>
91
- </Box>
92
- );
93
- })}
94
- {rows.length > MAX_VISIBLE_ROWS && (
95
- <Box>
96
- <Text dimColor>{" "}({rows.length} rows · ↑↓ navigate · Enter select)</Text>
97
- </Box>
98
- )}
99
- {rows.length <= MAX_VISIBLE_ROWS && rows.length > 0 && (
100
- <Box>
101
- <Text dimColor> (↑↓ navigate · Enter select)</Text>
102
- </Box>
103
- )}
104
- </Box>
105
- );
106
- }
@@ -1,84 +0,0 @@
1
- import React, { useState, useEffect } from "react";
2
- import { Box, Text } from "ink";
3
-
4
- const SPINNER_FRAMES = ["◈", "◇", "◆", "◇"];
5
- const SPINNER_INTERVAL = 120;
6
-
7
- export type StepStatus = "pending" | "running" | "done" | "error";
8
-
9
- export interface StepSpinnerProps {
10
- step: number;
11
- total: number;
12
- label: string;
13
- status: StepStatus;
14
- detail?: string;
15
- error?: string;
16
- }
17
-
18
- export function StepSpinner({
19
- step,
20
- total,
21
- label,
22
- status,
23
- detail,
24
- error,
25
- }: StepSpinnerProps) {
26
- const [frame, setFrame] = useState(0);
27
-
28
- useEffect(() => {
29
- if (status !== "running") return;
30
- const timer = setInterval(() => {
31
- setFrame((f) => (f + 1) % SPINNER_FRAMES.length);
32
- }, SPINNER_INTERVAL);
33
- return () => clearInterval(timer);
34
- }, [status]);
35
-
36
- const prefix = `Step ${step}/${total}`;
37
-
38
- if (status === "pending") {
39
- return (
40
- <Box>
41
- <Text dimColor> {prefix} — {label}</Text>
42
- </Box>
43
- );
44
- }
45
-
46
- if (status === "running") {
47
- return (
48
- <Box flexDirection="column">
49
- <Box>
50
- <Text color="cyan"> {SPINNER_FRAMES[frame]} {prefix} — {label}...</Text>
51
- </Box>
52
- </Box>
53
- );
54
- }
55
-
56
- if (status === "done") {
57
- return (
58
- <Box flexDirection="column">
59
- <Box>
60
- <Text color="green"> ✓ {prefix} — {label}</Text>
61
- </Box>
62
- {detail && (
63
- <Box>
64
- <Text dimColor> └ {detail}</Text>
65
- </Box>
66
- )}
67
- </Box>
68
- );
69
- }
70
-
71
- // error
72
- return (
73
- <Box flexDirection="column">
74
- <Box>
75
- <Text color="red"> ✗ {prefix} — {label}</Text>
76
- </Box>
77
- {error && (
78
- <Box>
79
- <Text color="red"> └ {error}</Text>
80
- </Box>
81
- )}
82
- </Box>
83
- );
84
- }
@@ -1,59 +0,0 @@
1
- import React, { useEffect } from "react";
2
- import { Box, Text } from "ink";
3
-
4
- export type ToastVariant = "info" | "success" | "warning" | "error";
5
-
6
- export interface ToastData {
7
- id: string;
8
- message: string;
9
- variant: ToastVariant;
10
- duration?: number;
11
- }
12
-
13
- export interface ToastProps {
14
- toast: ToastData;
15
- onDismiss: (id: string) => void;
16
- }
17
-
18
- const VARIANT_CONFIG: Record<ToastVariant, { icon: string; color: string }> = {
19
- info: { icon: "◈", color: "cyan" },
20
- success: { icon: "✓", color: "green" },
21
- warning: { icon: "⚠", color: "yellow" },
22
- error: { icon: "✗", color: "red" },
23
- };
24
-
25
- export function Toast({ toast, onDismiss }: ToastProps) {
26
- const { icon, color } = VARIANT_CONFIG[toast.variant];
27
-
28
- useEffect(() => {
29
- const timer = setTimeout(() => {
30
- onDismiss(toast.id);
31
- }, toast.duration ?? 5000);
32
- return () => clearTimeout(timer);
33
- }, [toast.id, toast.duration, onDismiss]);
34
-
35
- return (
36
- <Box>
37
- <Text color={color}>
38
- {icon} {toast.message}
39
- </Text>
40
- </Box>
41
- );
42
- }
43
-
44
- export interface ToastContainerProps {
45
- toasts: ToastData[];
46
- onDismiss: (id: string) => void;
47
- }
48
-
49
- export function ToastContainer({ toasts, onDismiss }: ToastContainerProps) {
50
- if (toasts.length === 0) return null;
51
-
52
- return (
53
- <Box flexDirection="column">
54
- {toasts.map((toast) => (
55
- <Toast key={toast.id} toast={toast} onDismiss={onDismiss} />
56
- ))}
57
- </Box>
58
- );
59
- }