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,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
- }