@needmoretruth/nmts-cli 0.17.2 → 0.34.1

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 (419) hide show
  1. package/AGENTS.md +124 -516
  2. package/CHANGELOG.md +98 -0
  3. package/README.ko.md +374 -467
  4. package/README.md +384 -465
  5. package/dist/account-proof.d.ts +29 -0
  6. package/dist/account-proof.js +6 -6
  7. package/dist/account.d.ts +18 -0
  8. package/dist/account.js +5 -5
  9. package/dist/agent-host.d.ts +71 -0
  10. package/dist/agent-host.js +169 -0
  11. package/dist/api-advice.d.ts +2 -0
  12. package/dist/api-advice.js +210 -0
  13. package/dist/api-key.d.ts +79 -0
  14. package/dist/api-key.js +7 -7
  15. package/dist/api-refusal.d.ts +14 -0
  16. package/dist/api-refusal.js +8 -0
  17. package/dist/api.d.ts +114 -0
  18. package/dist/api.js +59 -162
  19. package/dist/args.d.ts +160 -0
  20. package/dist/args.js +118 -30
  21. package/dist/artifact-about.d.ts +49 -0
  22. package/dist/autonomy.d.ts +39 -0
  23. package/dist/autonomy.js +110 -32
  24. package/dist/code-access.d.ts +29 -0
  25. package/dist/code-access.js +3 -3
  26. package/dist/code-vault.d.ts +38 -0
  27. package/dist/code-vault.js +8 -8
  28. package/dist/collision.d.ts +67 -0
  29. package/dist/collision.js +1 -1
  30. package/dist/commands/accept-terms.d.ts +11 -0
  31. package/dist/commands/accept-terms.js +106 -0
  32. package/dist/commands/balance.d.ts +7 -0
  33. package/dist/commands/balance.js +54 -1
  34. package/dist/commands/create-code-file.d.ts +24 -0
  35. package/dist/commands/create-code-file.js +93 -0
  36. package/dist/commands/create-link.d.ts +10 -0
  37. package/dist/commands/create-link.js +232 -0
  38. package/dist/commands/create.d.ts +20 -0
  39. package/dist/commands/create.js +43 -102
  40. package/dist/commands/credits.d.ts +9 -0
  41. package/dist/commands/credits.js +110 -0
  42. package/dist/commands/delete-account.d.ts +11 -0
  43. package/dist/commands/delete-account.js +63 -0
  44. package/dist/commands/deposit.d.ts +7 -0
  45. package/dist/commands/deposit.js +85 -0
  46. package/dist/commands/devices.d.ts +12 -0
  47. package/dist/commands/devices.js +144 -0
  48. package/dist/commands/documents.d.ts +35 -0
  49. package/dist/commands/documents.js +212 -0
  50. package/dist/commands/env.d.ts +5 -0
  51. package/dist/commands/env.js +10 -2
  52. package/dist/commands/erase.d.ts +13 -0
  53. package/dist/commands/erase.js +193 -0
  54. package/dist/commands/expiring.d.ts +19 -0
  55. package/dist/commands/extend.d.ts +33 -0
  56. package/dist/commands/extend.js +54 -15
  57. package/dist/commands/get.d.ts +18 -0
  58. package/dist/commands/key-manage.d.ts +11 -0
  59. package/dist/commands/key-manage.js +162 -0
  60. package/dist/commands/key.d.ts +28 -0
  61. package/dist/commands/key.js +249 -0
  62. package/dist/commands/kit.d.ts +11 -0
  63. package/dist/commands/kit.js +7 -7
  64. package/dist/commands/listfile.d.ts +13 -0
  65. package/dist/commands/listfile.js +12 -5
  66. package/dist/commands/login.d.ts +18 -0
  67. package/dist/commands/login.js +19 -19
  68. package/dist/commands/logout.d.ts +1 -0
  69. package/dist/commands/logout.js +1 -1
  70. package/dist/commands/losses.d.ts +12 -0
  71. package/dist/commands/losses.js +180 -0
  72. package/dist/commands/ls.d.ts +23 -0
  73. package/dist/commands/marks-dispatch.d.ts +2 -0
  74. package/dist/commands/marks-dispatch.js +51 -0
  75. package/dist/commands/marks.d.ts +46 -0
  76. package/dist/commands/marks.js +80 -0
  77. package/dist/commands/mcp.d.ts +24 -0
  78. package/dist/commands/mcp.js +70 -5
  79. package/dist/commands/mode.d.ts +8 -0
  80. package/dist/commands/mode.js +60 -24
  81. package/dist/commands/on-collision.d.ts +6 -0
  82. package/dist/commands/organise.d.ts +46 -0
  83. package/dist/commands/padding.d.ts +7 -0
  84. package/dist/commands/padding.js +114 -0
  85. package/dist/commands/public-code.d.ts +9 -0
  86. package/dist/commands/public-code.js +8 -8
  87. package/dist/commands/pull.d.ts +27 -0
  88. package/dist/commands/push-wallet.d.ts +19 -0
  89. package/dist/commands/push-wallet.js +69 -0
  90. package/dist/commands/push.d.ts +47 -0
  91. package/dist/commands/push.js +37 -7
  92. package/dist/commands/put-wallet.d.ts +77 -0
  93. package/dist/commands/put-wallet.js +316 -0
  94. package/dist/commands/put.d.ts +56 -0
  95. package/dist/commands/put.js +53 -6
  96. package/dist/commands/rebuild.d.ts +18 -0
  97. package/dist/commands/rebuild.js +108 -10
  98. package/dist/commands/receive.d.ts +24 -0
  99. package/dist/commands/recovery-dispatch.d.ts +2 -0
  100. package/dist/commands/recovery-dispatch.js +34 -0
  101. package/dist/commands/recovery-list.d.ts +11 -0
  102. package/dist/commands/recovery-list.js +6 -6
  103. package/dist/commands/recovery.d.ts +25 -0
  104. package/dist/commands/recovery.js +2 -2
  105. package/dist/commands/rollback.d.ts +9 -0
  106. package/dist/commands/rollback.js +118 -0
  107. package/dist/commands/s3.d.ts +23 -0
  108. package/dist/commands/s3.js +6 -6
  109. package/dist/commands/settings.d.ts +5 -0
  110. package/dist/commands/settings.js +21 -6
  111. package/dist/commands/share-dispatch.d.ts +2 -0
  112. package/dist/commands/share-dispatch.js +46 -0
  113. package/dist/commands/share.d.ts +14 -0
  114. package/dist/commands/share.js +13 -3
  115. package/dist/commands/shares-sent.d.ts +18 -0
  116. package/dist/commands/shares-sent.js +95 -0
  117. package/dist/commands/support.d.ts +24 -0
  118. package/dist/commands/support.js +321 -0
  119. package/dist/commands/sweep.d.ts +11 -0
  120. package/dist/commands/tip.d.ts +11 -0
  121. package/dist/commands/tip.js +86 -0
  122. package/dist/commands/trash.d.ts +17 -0
  123. package/dist/commands/trash.js +1 -1
  124. package/dist/commands/trial.d.ts +7 -0
  125. package/dist/commands/trial.js +16 -18
  126. package/dist/commands/unlock.d.ts +16 -0
  127. package/dist/commands/unlock.js +159 -0
  128. package/dist/commands/update.d.ts +42 -0
  129. package/dist/commands/update.js +1 -1
  130. package/dist/commands/usage.d.ts +8 -0
  131. package/dist/commands/verify.d.ts +18 -0
  132. package/dist/commands/verify.js +10 -6
  133. package/dist/commands/wallet-activity.d.ts +26 -0
  134. package/dist/commands/wallet-activity.js +117 -0
  135. package/dist/commands/wallet-donate.d.ts +26 -0
  136. package/dist/commands/wallet-donate.js +163 -0
  137. package/dist/commands/wallet-hall.d.ts +35 -0
  138. package/dist/commands/wallet-hall.js +214 -0
  139. package/dist/commands/wallet-send.d.ts +22 -0
  140. package/dist/commands/wallet-send.js +153 -0
  141. package/dist/commands/wallet-storage-ops.d.ts +24 -0
  142. package/dist/commands/wallet-storage-ops.js +215 -0
  143. package/dist/commands/wallet-storage.d.ts +18 -0
  144. package/dist/commands/wallet-storage.js +95 -0
  145. package/dist/commands/wallet-swap.d.ts +32 -0
  146. package/dist/commands/wallet-swap.js +287 -0
  147. package/dist/commands/wallet.d.ts +36 -0
  148. package/dist/commands/wallet.js +57 -15
  149. package/dist/commands/whoami.d.ts +10 -0
  150. package/dist/commands/whoami.js +24 -6
  151. package/dist/consent.d.ts +140 -0
  152. package/dist/consent.js +89 -30
  153. package/dist/credentials.d.ts +146 -0
  154. package/dist/credentials.js +10 -10
  155. package/dist/crypto-surface.d.ts +197 -0
  156. package/dist/crypto.d.ts +81 -0
  157. package/dist/crypto.js +13 -0
  158. package/dist/deposit.d.ts +25 -0
  159. package/dist/deposit.js +78 -0
  160. package/dist/download-part.d.ts +40 -0
  161. package/dist/download-sink.d.ts +76 -0
  162. package/dist/download.d.ts +79 -0
  163. package/dist/download.js +3 -3
  164. package/dist/drive-paths.d.ts +73 -0
  165. package/dist/environment.d.ts +62 -0
  166. package/dist/environment.js +29 -9
  167. package/dist/errors.d.ts +22 -0
  168. package/dist/errors.js +3 -3
  169. package/dist/exit.d.ts +44 -0
  170. package/dist/expiry.d.ts +58 -0
  171. package/dist/extend-budget.d.ts +35 -0
  172. package/dist/extend-budget.js +81 -0
  173. package/dist/extend-chain.d.ts +43 -0
  174. package/dist/extend-chain.js +40 -3
  175. package/dist/extend-plan.d.ts +148 -0
  176. package/dist/extend-plan.js +1 -1
  177. package/dist/gate.d.ts +18 -0
  178. package/dist/gate.js +100 -0
  179. package/dist/guards.d.ts +2 -0
  180. package/dist/help.d.ts +20 -0
  181. package/dist/help.js +199 -33
  182. package/dist/human-check.d.ts +23 -0
  183. package/dist/index.d.ts +42 -0
  184. package/dist/index.js +49 -0
  185. package/dist/item-trash.d.ts +1 -0
  186. package/dist/kit-file.d.ts +56 -0
  187. package/dist/kit-file.js +10 -10
  188. package/dist/list-file.d.ts +88 -0
  189. package/dist/list-file.js +90 -7
  190. package/dist/list-view-find.d.ts +15 -0
  191. package/dist/list-view-order.d.ts +32 -0
  192. package/dist/main.d.ts +12 -0
  193. package/dist/main.js +112 -113
  194. package/dist/manifest-chunk-cache.d.ts +14 -0
  195. package/dist/manifest-chunk-cache.js +103 -0
  196. package/dist/manifest-chunk-flow.d.ts +81 -0
  197. package/dist/manifest-chunk-flow.js +307 -0
  198. package/dist/manifest-create.d.ts +23 -0
  199. package/dist/manifest-create.js +26 -30
  200. package/dist/manifest-write.d.ts +161 -0
  201. package/dist/manifest-write.js +42 -33
  202. package/dist/manifest.d.ts +82 -0
  203. package/dist/manifest.js +69 -21
  204. package/dist/mark-render.d.ts +26 -0
  205. package/dist/mcp-args.d.ts +17 -0
  206. package/dist/mcp-ask.d.ts +43 -0
  207. package/dist/mcp-ask.js +100 -0
  208. package/dist/mcp-tools/context.d.ts +46 -0
  209. package/dist/mcp-tools/credits.d.ts +3 -0
  210. package/dist/mcp-tools/credits.js +61 -0
  211. package/dist/mcp-tools/files.d.ts +3 -0
  212. package/dist/mcp-tools/files.js +34 -0
  213. package/dist/mcp-tools/organise.d.ts +3 -0
  214. package/dist/mcp-tools/organise.js +82 -2
  215. package/dist/mcp-tools/reads.d.ts +3 -0
  216. package/dist/mcp-tools/reads.js +132 -4
  217. package/dist/mcp-tools/share.d.ts +3 -0
  218. package/dist/mcp-tools/share.js +26 -7
  219. package/dist/mcp-tools/support.d.ts +3 -0
  220. package/dist/mcp-tools/support.js +140 -0
  221. package/dist/mcp-tools/tiers.d.ts +31 -0
  222. package/dist/mcp-tools/tiers.js +147 -0
  223. package/dist/mcp.d.ts +80 -0
  224. package/dist/mcp.js +110 -9
  225. package/dist/net-retry.d.ts +38 -0
  226. package/dist/network.d.ts +10 -0
  227. package/dist/notice.d.ts +7 -0
  228. package/dist/notice.js +7 -7
  229. package/dist/product.d.ts +29 -0
  230. package/dist/product.js +1 -1
  231. package/dist/progress.d.ts +37 -0
  232. package/dist/prompt.d.ts +31 -0
  233. package/dist/prompt.js +1 -1
  234. package/dist/rebuild-key-check.d.ts +26 -0
  235. package/dist/rebuild-key-check.js +90 -0
  236. package/dist/rebuild.d.ts +87 -0
  237. package/dist/rebuild.js +26 -4
  238. package/dist/recovery-assemble.d.ts +40 -0
  239. package/dist/recovery-assemble.js +1 -1
  240. package/dist/recovery-build.d.ts +40 -0
  241. package/dist/recovery-map-file.d.ts +53 -0
  242. package/dist/recovery-map-file.js +4 -4
  243. package/dist/recovery-map.d.ts +197 -0
  244. package/dist/recovery-release.d.ts +104 -0
  245. package/dist/recovery-seq.d.ts +10 -0
  246. package/dist/recovery-source.d.ts +50 -0
  247. package/dist/redact.d.ts +70 -0
  248. package/dist/redact.js +212 -0
  249. package/dist/registration.d.ts +30 -0
  250. package/dist/registration.js +5 -5
  251. package/dist/risk.d.ts +380 -0
  252. package/dist/risk.js +206 -0
  253. package/dist/run-log.d.ts +78 -0
  254. package/dist/run-log.js +301 -0
  255. package/dist/s3/listing.d.ts +47 -0
  256. package/dist/s3/multipart.d.ts +21 -0
  257. package/dist/s3/response-sink.d.ts +8 -0
  258. package/dist/s3/same-file.d.ts +54 -0
  259. package/dist/s3/server.d.ts +58 -0
  260. package/dist/s3/server.js +2 -2
  261. package/dist/s3/sigv4.d.ts +46 -0
  262. package/dist/s3/sigv4.js +1 -1
  263. package/dist/s3/staging.d.ts +10 -0
  264. package/dist/s3/xml.d.ts +28 -0
  265. package/dist/safe-path.d.ts +41 -0
  266. package/dist/seal.d.ts +120 -0
  267. package/dist/secret-reader.d.ts +28 -0
  268. package/dist/server.d.ts +9 -0
  269. package/dist/session.d.ts +32 -0
  270. package/dist/session.js +1 -1
  271. package/dist/setup-questions.d.ts +7 -0
  272. package/dist/share.d.ts +108 -0
  273. package/dist/share.js +1 -1
  274. package/dist/shared/lib/crypto/size-padding.d.ts +55 -0
  275. package/dist/shared/lib/crypto/size-padding.js +5 -0
  276. package/dist/shared/lib/drive/manifest-chunks.d.ts +95 -0
  277. package/dist/shared/lib/drive/manifest-chunks.js +252 -0
  278. package/dist/shared/lib/drive/manifest-codec.d.ts +214 -0
  279. package/dist/shared/lib/drive/manifest-codec.js +7 -7
  280. package/dist/shared/lib/drive/manifest-index.d.ts +98 -0
  281. package/dist/shared/lib/drive/manifest-ops.d.ts +167 -0
  282. package/dist/shared/lib/drive/manifest-ops.js +9 -4
  283. package/dist/shared/lib/drive/manifest-pack.d.ts +65 -0
  284. package/dist/shared/lib/drive/manifest-pack.js +287 -0
  285. package/dist/shared/lib/drive/manifest-settings.d.ts +113 -0
  286. package/dist/shared/lib/drive/manifest-settings.js +87 -6
  287. package/dist/shared/lib/drive/name-conflict.d.ts +76 -0
  288. package/dist/shared/lib/drive/rebuild-verify.d.ts +73 -0
  289. package/dist/shared/lib/drive/rebuild-verify.js +112 -0
  290. package/dist/shared/lib/drive/unique-name.d.ts +9 -0
  291. package/dist/shared/lib/drive/zstd.d.ts +27 -0
  292. package/dist/shared/lib/drive/zstd.js +74 -0
  293. package/dist/shared/lib/extend/epochs.d.ts +205 -0
  294. package/dist/shared/lib/net/retry-budget.d.ts +79 -0
  295. package/dist/shared/lib/share/shared-file-info.d.ts +21 -0
  296. package/dist/shared/lib/storage-control/chain.d.ts +57 -0
  297. package/dist/shared/lib/storage-control/chain.js +82 -0
  298. package/dist/shared/lib/storage-control/plan.d.ts +40 -0
  299. package/dist/shared/lib/storage-control/plan.js +72 -0
  300. package/dist/shared/lib/storage-control/reuse.d.ts +72 -0
  301. package/dist/shared/lib/storage-control/reuse.js +95 -0
  302. package/dist/shared/lib/storage-network.d.ts +25 -0
  303. package/dist/shared/lib/upload/part-plan.d.ts +24 -0
  304. package/dist/shared/lib/wallet/activity.d.ts +138 -0
  305. package/dist/shared/lib/wallet/activity.js +208 -0
  306. package/dist/shared/lib/wallet/send-rules.d.ts +68 -0
  307. package/dist/shared/lib/wallet/send-rules.js +116 -0
  308. package/dist/shared/lib/wallet/swap-rules.d.ts +115 -0
  309. package/dist/shared/lib/wallet/swap-rules.js +199 -0
  310. package/dist/shared/lib/wallet/tip.d.ts +14 -0
  311. package/dist/shared/lib/wallet/tip.js +34 -0
  312. package/dist/shared/lib/wallet/venue-ids.d.ts +23 -0
  313. package/dist/shared/lib/wallet/venue-ids.js +53 -0
  314. package/dist/standing-tip.d.ts +24 -0
  315. package/dist/standing-tip.js +52 -0
  316. package/dist/stdout.d.ts +38 -0
  317. package/dist/storage-control-chain.d.ts +38 -0
  318. package/dist/storage-control-chain.js +78 -0
  319. package/dist/sui-rpc.d.ts +15 -0
  320. package/dist/sui-rpc.js +59 -0
  321. package/dist/support-attach.d.ts +24 -0
  322. package/dist/support-attach.js +72 -0
  323. package/dist/support-copy.d.ts +42 -0
  324. package/dist/support-copy.js +109 -0
  325. package/dist/support-wire.d.ts +49 -0
  326. package/dist/support-wire.js +194 -0
  327. package/dist/trash-sweep.d.ts +55 -0
  328. package/dist/units.d.ts +2 -0
  329. package/dist/update-check.d.ts +50 -0
  330. package/dist/update-source.d.ts +63 -0
  331. package/dist/upload-api.d.ts +3 -0
  332. package/dist/upload-file.d.ts +97 -0
  333. package/dist/upload-file.js +3 -2
  334. package/dist/upload-price.d.ts +50 -0
  335. package/dist/upload-steps.d.ts +26 -0
  336. package/dist/upload-steps.js +29 -9
  337. package/dist/upload-store.d.ts +182 -0
  338. package/dist/upload-wallet-chain.d.ts +54 -0
  339. package/dist/upload-wallet-chain.js +203 -0
  340. package/dist/upload-wallet-plan.d.ts +128 -0
  341. package/dist/upload-wallet-plan.js +184 -0
  342. package/dist/upload-wallet.d.ts +24 -0
  343. package/dist/upload-wallet.js +208 -0
  344. package/dist/upload-wire.d.ts +244 -0
  345. package/dist/upload.d.ts +18 -0
  346. package/dist/upload.js +10 -0
  347. package/dist/usage-report.d.ts +35 -0
  348. package/dist/wallet-activity-chain.d.ts +5 -0
  349. package/dist/wallet-activity-chain.js +31 -0
  350. package/dist/wallet-chain.d.ts +19 -0
  351. package/dist/wallet-chain.js +2 -2
  352. package/dist/wallet-grant.d.ts +50 -0
  353. package/dist/wallet-grant.js +218 -0
  354. package/dist/wallet-send-chain.d.ts +24 -0
  355. package/dist/wallet-send-chain.js +49 -0
  356. package/dist/wallet-sign.d.ts +133 -0
  357. package/dist/wallet-sign.js +317 -0
  358. package/dist/wallet-storage-chain.d.ts +3 -0
  359. package/dist/wallet-storage-chain.js +20 -0
  360. package/dist/wallet-swap-chain.d.ts +52 -0
  361. package/dist/wallet-swap-chain.js +186 -0
  362. package/dist/wallet-swap-quote.d.ts +22 -0
  363. package/dist/wallet-swap-quote.js +126 -0
  364. package/dist/wallet.d.ts +135 -0
  365. package/dist/wallet.js +5 -5
  366. package/dist/walrus-write.d.ts +56 -0
  367. package/dist/walrus-write.js +5 -4
  368. package/dist/walrus.d.ts +86 -0
  369. package/dist/walrus.js +48 -10
  370. package/dist/zstd-node.d.ts +11 -0
  371. package/dist/zstd-node.js +71 -0
  372. package/docs/commands/accept-terms.md +15 -0
  373. package/docs/commands/create.md +17 -0
  374. package/docs/commands/credits.md +34 -0
  375. package/docs/commands/delete-account.md +14 -0
  376. package/docs/commands/deposit.md +27 -0
  377. package/docs/commands/devices.md +9 -0
  378. package/docs/commands/documents.md +10 -0
  379. package/docs/commands/env.md +21 -0
  380. package/docs/commands/extend.md +27 -0
  381. package/docs/commands/folders.md +10 -0
  382. package/docs/commands/get.md +14 -0
  383. package/docs/commands/key.md +14 -0
  384. package/docs/commands/login.md +23 -0
  385. package/docs/commands/logout.md +11 -0
  386. package/docs/commands/losses.md +13 -0
  387. package/docs/commands/ls.md +16 -0
  388. package/docs/commands/marks.md +9 -0
  389. package/docs/commands/mcp.md +33 -0
  390. package/docs/commands/mode.md +29 -0
  391. package/docs/commands/on-collision.md +13 -0
  392. package/docs/commands/padding.md +13 -0
  393. package/docs/commands/public-code.md +9 -0
  394. package/docs/commands/pull.md +9 -0
  395. package/docs/commands/push.md +12 -0
  396. package/docs/commands/put.md +36 -0
  397. package/docs/commands/rebuild.md +13 -0
  398. package/docs/commands/recovery.md +18 -0
  399. package/docs/commands/s3.md +17 -0
  400. package/docs/commands/share.md +15 -0
  401. package/docs/commands/support.md +16 -0
  402. package/docs/commands/tip.md +21 -0
  403. package/docs/commands/trash.md +25 -0
  404. package/docs/commands/trial.md +12 -0
  405. package/docs/commands/unlock.md +25 -0
  406. package/docs/commands/update.md +14 -0
  407. package/docs/commands/usage.md +14 -0
  408. package/docs/commands/verify.md +18 -0
  409. package/docs/commands/wallet.md +67 -0
  410. package/docs/commands/whoami.md +12 -0
  411. package/package.json +67 -8
  412. package/server.json +28 -0
  413. package/vendor/nmts-crypto/nmts_crypto_wasm.d.ts +23 -2
  414. package/vendor/nmts-crypto/nmts_crypto_wasm.js +44 -2
  415. package/vendor/nmts-crypto/nmts_crypto_wasm_bg.wasm +0 -0
  416. package/vendor/nmts-crypto/nmts_crypto_wasm_bg.wasm.d.ts +1 -0
  417. package/vendor/nmts-crypto/package.json +1 -1
  418. package/dist/commands/consent.js +0 -77
  419. package/dist/extend-sign.js +0 -130
@@ -0,0 +1,180 @@
1
+ // `nmts losses` — the storage bought with this account's credits that the chain no longer knows.
2
+ //
3
+ // ⛔ IT REPORTS, IT DOES NOT REPAIR. Once the chain has stopped serving a storage object nothing
4
+ // this tool or the server does brings the bytes back, and the row is the record of a purchase
5
+ // that produced nothing. What the command is for is that somebody finds out from us rather
6
+ // than from a download that stops coming back.
7
+ //
8
+ // ⛔ THERE IS NO FILE NAME AND THERE CANNOT BE ONE. The answer names on-chain STORAGE OBJECTS; the
9
+ // pairing that would resolve one to a file is server-side, has no route, and the drive's own
10
+ // list is sealed with a key the server never sees. Printing a guessed name would be worse than
11
+ // printing none, so the line prints the public object id and says why that is all there is.
12
+ //
13
+ // ⚠ AN EMPTY LIST IS NOT "NOTHING IS GONE". The daily round samples fifty objects at random, so an
14
+ // object nobody has drawn yet has not been asked about. The route's own note says a client must
15
+ // not print the second sentence, and the wording here does not.
16
+ //
17
+ // ⛔ THE THREE ACTS ARE ONE COMMAND BECAUSE THEY ARE ONE SUBJECT, and exactly one of them runs per
18
+ // call. Re-checking asks the chain the same question the daily round asks, now. Dismissing is a
19
+ // person saying they have read the line — see the mode check below, which is the reason this
20
+ // command imports the autonomy module at all.
21
+ import { request, ServerError } from "../api.js";
22
+ import { NmtsError } from "../errors.js";
23
+ import { isRecord } from "../guards.js";
24
+ import { BINARY_NAME } from "../product.js";
25
+ import { openSession } from "../session.js";
26
+ /**
27
+ * The refusal for an id this account holds no line for.
28
+ *
29
+ * ⛔ ONE TEXT FOR BOTH ARMS. The server answers 404 to a re-check and to a dismiss for the same
30
+ * reason — the account does not hold that loss — and two wordings for one cause is how a caller
31
+ * ends up branching on which command it happened to run.
32
+ */
33
+ function noSuchLine(id) {
34
+ return new NmtsError(`NMTS holds no loss line for ${id} on this account.`, {
35
+ exitCode: 4,
36
+ nextStep: `Run \`${BINARY_NAME} losses\` to see the lines that exist.`,
37
+ });
38
+ }
39
+ /** `unknown` off the wire, read as the rows the route declares. */
40
+ function rowsOf(answer) {
41
+ const list = isRecord(answer) ? answer["losses"] : undefined;
42
+ if (!Array.isArray(list)) {
43
+ throw new NmtsError(`The server's answer did not carry a list of losses.`, {
44
+ exitCode: 1,
45
+ nextStep: `Nothing was changed. Report it rather than retrying — the shape, not the network, is wrong.`,
46
+ });
47
+ }
48
+ return list.map((row) => {
49
+ const id = isRecord(row) ? row["blob_object_id"] : undefined;
50
+ const seen = isRecord(row) ? row["first_seen"] : undefined;
51
+ const notice = isRecord(row) ? row["required_notice"] : undefined;
52
+ const restricted = isRecord(row) ? row["restricted"] : undefined;
53
+ if (typeof id !== "string" || typeof seen !== "string") {
54
+ throw new NmtsError(`The server listed a loss this version cannot read.`, {
55
+ exitCode: 1,
56
+ nextStep: `Nothing was changed. A newer version of this tool may understand it.`,
57
+ });
58
+ }
59
+ // ⚠ A flag that did not arrive as a boolean is read as false, and that is the only place here
60
+ // where a missing field is filled in: both mean "this line carries no extra sentence", and
61
+ // the sentences they add are additions to a line that is already correct without them.
62
+ return {
63
+ blob_object_id: id,
64
+ first_seen: seen,
65
+ required_notice: notice === true,
66
+ restricted: restricted === true,
67
+ };
68
+ });
69
+ }
70
+ /** The UTC day of an RFC 3339 instant, `YYYY-MM-DD`. */
71
+ function utcDay(instant) {
72
+ const at = new Date(instant);
73
+ if (Number.isNaN(at.getTime())) {
74
+ throw new NmtsError(`The server dated a loss with something that is not a time.`, {
75
+ exitCode: 1,
76
+ nextStep: `Nothing was changed. Report it rather than retrying.`,
77
+ });
78
+ }
79
+ return at.toISOString().slice(0, 10);
80
+ }
81
+ export async function losses(options = {}) {
82
+ const say = options.write ?? ((line) => process.stdout.write(`${line}\n`));
83
+ if (options.recheck !== undefined && options.dismiss !== undefined) {
84
+ throw new NmtsError(`--recheck and --dismiss are two different acts, and one run does one.`, {
85
+ exitCode: 2,
86
+ nextStep: `Run one, read what it says, then run the other.`,
87
+ });
88
+ }
89
+ const session = await openSession({ server: options.server, network: options.network });
90
+ if (options.recheck !== undefined) {
91
+ const id = options.recheck;
92
+ let answer;
93
+ try {
94
+ answer = await request(session.server, "/v1/storage-loss/recheck", {
95
+ token: session.apiKey,
96
+ method: "POST",
97
+ body: { blob_object_id: id },
98
+ });
99
+ }
100
+ catch (error) {
101
+ if (error instanceof ServerError && error.status === 404)
102
+ throw noSuchLine(id);
103
+ throw error;
104
+ }
105
+ const result = isRecord(answer) ? answer["result"] : undefined;
106
+ if (result !== "found" && result !== "still_missing" && result !== "unread") {
107
+ throw new NmtsError(`The server answered the re-check with something this version cannot read.`, {
108
+ exitCode: 1,
109
+ nextStep: `Nothing was decided about the storage. A newer version of this tool may understand it.`,
110
+ });
111
+ }
112
+ const said = result;
113
+ if (options.json === true) {
114
+ say(JSON.stringify({ blob_object_id: id, result: said }));
115
+ return 0;
116
+ }
117
+ if (said === "found")
118
+ say(`The chain knows ${id} again. Its line came off.`);
119
+ else if (said === "still_missing")
120
+ say(`The chain still does not know ${id}. The line stays.`);
121
+ else
122
+ say(`The chain could not be read just now. Nothing changed.`);
123
+ return 0;
124
+ }
125
+ if (options.dismiss !== undefined) {
126
+ const id = options.dismiss;
127
+ try {
128
+ await request(session.server, `/v1/storage-loss/${encodeURIComponent(id)}`, {
129
+ token: session.apiKey,
130
+ method: "DELETE",
131
+ });
132
+ }
133
+ catch (error) {
134
+ if (error instanceof ServerError && error.status === 404)
135
+ throw noSuchLine(id);
136
+ throw error;
137
+ }
138
+ if (options.json === true) {
139
+ say(JSON.stringify({ blob_object_id: id, dismissed: true }));
140
+ return 0;
141
+ }
142
+ say(`Took the line for ${id} off. The incident stays in a record that names nobody; if the same ` +
143
+ `storage is found and lost again, it is shown again.`);
144
+ return 0;
145
+ }
146
+ const answer = await request(session.server, "/v1/storage-loss", { token: session.apiKey });
147
+ if (options.json === true) {
148
+ // ⛔ THE SERVER'S OBJECT, UNCHANGED. A reader of this arm is reading the route, and a shape
149
+ // rewritten here would be a second wire to keep in step with the first.
150
+ say(JSON.stringify(answer));
151
+ return 0;
152
+ }
153
+ const rows = rowsOf(answer);
154
+ if (rows.length === 0) {
155
+ say(`The daily check has found nothing missing for this account.`);
156
+ say(`It samples the storage NMTS bought with your credits once a day and asks the chain whether ` +
157
+ `it is still there.`);
158
+ return 0;
159
+ }
160
+ say(rows.length === 1
161
+ ? `The chain no longer knows one storage object your credits paid for. That is what the ` +
162
+ `check measured; it did not try the download. The file may no longer come back, and ` +
163
+ `NMTS cannot restore it.`
164
+ : `The chain no longer knows ${rows.length} storage objects your credits paid for. That is ` +
165
+ `what the check measured; it did not try the download. Those files may no longer come ` +
166
+ `back, and NMTS cannot restore them.`);
167
+ say(``);
168
+ for (const row of rows) {
169
+ say(`${row.blob_object_id} first missed ${utcDay(row.first_seen)}` +
170
+ (row.required_notice ? ` · shown because the law requires it` : ``) +
171
+ (row.restricted ? ` · kept but not used while you contest it` : ``));
172
+ }
173
+ say(``);
174
+ say(`The date is when a check first could not find it, not when the storage went. There is no ` +
175
+ `file name: the server cannot pair the object with a file, and NMTS cannot see inside files.`);
176
+ say(`\`${BINARY_NAME} losses --recheck <id>\` asks the chain again now. \`${BINARY_NAME} losses ` +
177
+ `--dismiss <id>\` takes a line off once you have read it; the incident stays in a record ` +
178
+ `that names nobody.`);
179
+ return 0;
180
+ }
@@ -0,0 +1,23 @@
1
+ export interface LsOptions {
2
+ server?: string | undefined;
3
+ network?: string | undefined;
4
+ /** Machine-readable output. For an agent this is the shape to parse; the table is for a person. */
5
+ json?: boolean;
6
+ /** Include entries that are in the trash. */
7
+ all?: boolean;
8
+ /**
9
+ * Keep only files whose name contains this text, case-insensitively.
10
+ *
11
+ * Taken as plain text rather than a parsed key so this command owns the refusal for a query that
12
+ * cannot mean anything — see `list-view-find.ts` for what a query does and does not match.
13
+ */
14
+ find?: string | undefined;
15
+ /** `name`, `size` or `date`. Absent = the path order this command has always printed. */
16
+ sort?: string | undefined;
17
+ /** Reverse whichever order is in effect. */
18
+ desc?: boolean;
19
+ write?: (line: string) => void;
20
+ /** The instant the trash countdown is measured against. Passed in so one listing means one moment. */
21
+ now?: number;
22
+ }
23
+ export declare function ls(options?: LsOptions): Promise<number>;
@@ -0,0 +1,2 @@
1
+ import type { ParsedArgs } from "../args.ts";
2
+ export declare function runMarks(command: string, args: ParsedArgs): Promise<number>;
@@ -0,0 +1,51 @@
1
+ // The six mark verbs, dispatched here rather than in `main.ts`.
2
+ //
3
+ // ⛔ WHY A SECOND SWITCH. `main.ts` is measured (`check:size`) and had no room for `nmts support`;
4
+ // these six cases were the one contiguous block that shares a file, an option shape and a
5
+ // reason to be read together — `label --rename` and `unlabel --all` are sweeps over the whole
6
+ // account wearing the verbs of a per-file mark, and the guard that keeps them from being
7
+ // reached by accident is the comment below, which moved with them.
8
+ export async function runMarks(command, args) {
9
+ switch (command) {
10
+ case "star": {
11
+ const { star } = await import("./marks.js");
12
+ return await star(args.operands, { server: args.server, network: args.network, json: args.json });
13
+ }
14
+ case "unstar": {
15
+ const { unstar } = await import("./marks.js");
16
+ return await unstar(args.operands, { server: args.server, network: args.network, json: args.json });
17
+ }
18
+ case "pin": {
19
+ const { pin } = await import("./marks.js");
20
+ return await pin(args.operands, { server: args.server, network: args.network, json: args.json });
21
+ }
22
+ case "unpin": {
23
+ const { unpin } = await import("./marks.js");
24
+ return await unpin(args.operands, { server: args.server, network: args.network, json: args.json });
25
+ }
26
+ case "label": {
27
+ const options = { server: args.server, network: args.network, json: args.json };
28
+ // ⛔ `--rename` IS A DIFFERENT COMMAND WEARING THE SAME VERB, and it is dispatched here so
29
+ // that the label sweep cannot be reached by accident: `label <name> <files>` puts a mark
30
+ // on the files it names, and `label --rename <old> <new>` touches every file in the
31
+ // account. One takes paths and the other refuses them.
32
+ if (args.rename !== undefined) {
33
+ const { labelRename } = await import("./marks.js");
34
+ return await labelRename(args.rename, args.operands[0], options);
35
+ }
36
+ const { label } = await import("./marks.js");
37
+ return await label(args.operands[0], args.operands.slice(1), options);
38
+ }
39
+ case "unlabel": {
40
+ const options = { server: args.server, network: args.network, json: args.json };
41
+ if (args.all) {
42
+ const { unlabelAll } = await import("./marks.js");
43
+ return await unlabelAll(args.operands[0], options);
44
+ }
45
+ const { unlabel } = await import("./marks.js");
46
+ return await unlabel(args.operands[0], args.operands.slice(1), options);
47
+ }
48
+ default:
49
+ throw new Error(`not a mark verb: ${command}`);
50
+ }
51
+ }
@@ -0,0 +1,46 @@
1
+ export interface MarkOptions {
2
+ server?: string | undefined;
3
+ network?: string | undefined;
4
+ json?: boolean;
5
+ write?: (line: string) => void;
6
+ }
7
+ /** Star one or more files: they show in the drive's favourites as well as in their own folder. */
8
+ export declare function star(paths: readonly string[], options?: MarkOptions): Promise<number>;
9
+ /** Take the star off. */
10
+ export declare function unstar(paths: readonly string[], options?: MarkOptions): Promise<number>;
11
+ /** Hold one or more files at the top of the folder they are in. */
12
+ export declare function pin(paths: readonly string[], options?: MarkOptions): Promise<number>;
13
+ /** Let them fall back into the ordinary order. */
14
+ export declare function unpin(paths: readonly string[], options?: MarkOptions): Promise<number>;
15
+ /**
16
+ * Put one label on one or more files.
17
+ *
18
+ * ⚠ A LABEL EXISTS EXACTLY AS LONG AS SOME FILE WEARS IT. There is no registry to add it to and
19
+ * none to clean up: two devices inventing the same label converge on it instead of colliding,
20
+ * and the last `unlabel` is what makes it stop existing.
21
+ */
22
+ export declare function label(name: string | undefined, paths: readonly string[], options?: MarkOptions): Promise<number>;
23
+ /** Take one label off one or more files. */
24
+ export declare function unlabel(name: string | undefined, paths: readonly string[], options?: MarkOptions): Promise<number>;
25
+ /**
26
+ * `nmts label --rename <old> <new>` — one label's name, changed on every file that wears it.
27
+ *
28
+ * ⛔ IT IS A SWEEP, AND IT NAMES NO PATHS. A label has no registry to rename it in (see `label`
29
+ * above): it exists on the files, so renaming it means touching every file that wears it. That
30
+ * is why this is a different entry point rather than a switch on `label` — one takes the files
31
+ * it is given, and this one takes whatever the account holds.
32
+ *
33
+ * ⛔ RENAMING ONTO A LABEL THAT ALREADY EXISTS MERGES THE TWO. A file wearing both would otherwise
34
+ * end up wearing one label twice, which shows a doubled row and counts the file twice. The
35
+ * intent does that; it is written down here because it is the behaviour somebody has to be able
36
+ * to predict before typing this.
37
+ */
38
+ export declare function labelRename(from: string | undefined, to: string | undefined, options?: MarkOptions): Promise<number>;
39
+ /**
40
+ * `nmts unlabel <name> --all` — one label, taken off every file that wears it.
41
+ *
42
+ * ⛔ THIS IS WHAT MAKES A LABEL STOP EXISTING, and it is the whole reason the sweep is worth a
43
+ * flag: a label with no registry can only be removed by finding every file wearing it, and
44
+ * doing that by hand is how one file keeps a label nobody can see any more.
45
+ */
46
+ export declare function unlabelAll(name: string | undefined, options?: MarkOptions): Promise<number>;
@@ -50,6 +50,86 @@ export async function label(name, paths, options = {}) {
50
50
  export async function unlabel(name, paths, options = {}) {
51
51
  return run("unlabel", paths, name, options);
52
52
  }
53
+ /**
54
+ * `nmts label --rename <old> <new>` — one label's name, changed on every file that wears it.
55
+ *
56
+ * ⛔ IT IS A SWEEP, AND IT NAMES NO PATHS. A label has no registry to rename it in (see `label`
57
+ * above): it exists on the files, so renaming it means touching every file that wears it. That
58
+ * is why this is a different entry point rather than a switch on `label` — one takes the files
59
+ * it is given, and this one takes whatever the account holds.
60
+ *
61
+ * ⛔ RENAMING ONTO A LABEL THAT ALREADY EXISTS MERGES THE TWO. A file wearing both would otherwise
62
+ * end up wearing one label twice, which shows a doubled row and counts the file twice. The
63
+ * intent does that; it is written down here because it is the behaviour somebody has to be able
64
+ * to predict before typing this.
65
+ */
66
+ export async function labelRename(from, to, options = {}) {
67
+ const say = options.write ?? ((line) => process.stdout.write(`${line}\n`));
68
+ // ⚠ Trimmed here as well as inside the intent, so the text compared against what a file wears
69
+ // is the same text that gets stored. ` work ` and `work` are one label.
70
+ const old = from === undefined ? "" : from.trim();
71
+ const fresh = to === undefined ? "" : to.trim();
72
+ if (old === "" || fresh === "") {
73
+ throw new NmtsError("`nmts label --rename` needs the label to rename, then its new name.", {
74
+ exitCode: 2,
75
+ nextStep: "For example: nmts label --rename work archive",
76
+ });
77
+ }
78
+ const session = await openSession(options);
79
+ const at = Date.now();
80
+ let files = 0;
81
+ // ⛔ COUNTED INSIDE THE ATTEMPT, like every other question about the list. On a lost
82
+ // compare-and-swap the list is read again, and how many files wear a label is a fact about
83
+ // the version that was read — another device may have added one since.
84
+ await applyToList(session, (now) => {
85
+ files = now.filter((e) => (e.labels ?? []).includes(old)).length;
86
+ return { op: "labelRename", from: old, to: fresh, at };
87
+ });
88
+ if (options.json) {
89
+ say(JSON.stringify({ label: old, renamed_to: fresh, files }));
90
+ return 0;
91
+ }
92
+ if (files === 0) {
93
+ say(`No file carries the label "${old}".`);
94
+ return 0;
95
+ }
96
+ say(`Renamed the label "${old}" to "${fresh}" on ${files} ${files === 1 ? "file" : "files"}.`);
97
+ return 0;
98
+ }
99
+ /**
100
+ * `nmts unlabel <name> --all` — one label, taken off every file that wears it.
101
+ *
102
+ * ⛔ THIS IS WHAT MAKES A LABEL STOP EXISTING, and it is the whole reason the sweep is worth a
103
+ * flag: a label with no registry can only be removed by finding every file wearing it, and
104
+ * doing that by hand is how one file keeps a label nobody can see any more.
105
+ */
106
+ export async function unlabelAll(name, options = {}) {
107
+ const say = options.write ?? ((line) => process.stdout.write(`${line}\n`));
108
+ const text = name === undefined ? "" : name.trim();
109
+ if (text === "") {
110
+ throw new NmtsError("`nmts unlabel --all` needs the label to take off.", {
111
+ exitCode: 2,
112
+ nextStep: "For example: nmts unlabel work --all",
113
+ });
114
+ }
115
+ const session = await openSession(options);
116
+ const at = Date.now();
117
+ let files = 0;
118
+ await applyToList(session, (now) => {
119
+ files = now.filter((e) => (e.labels ?? []).includes(text)).length;
120
+ return { op: "labelDelete", label: text, at };
121
+ });
122
+ if (options.json) {
123
+ say(JSON.stringify({ label: text, removed_from: files }));
124
+ return 0;
125
+ }
126
+ if (files === 0) {
127
+ say(`No file carries the label "${text}".`);
128
+ return 0;
129
+ }
130
+ say(`Took the label "${text}" off ${files} ${files === 1 ? "file" : "files"}.`);
131
+ return 0;
132
+ }
53
133
  async function run(verb, paths, name, options) {
54
134
  const say = options.write ?? ((line) => process.stdout.write(`${line}\n`));
55
135
  const on = !verb.startsWith("un");
@@ -0,0 +1,24 @@
1
+ import { destinationFor } from "../safe-path.ts";
2
+ export { destinationFor };
3
+ export interface McpOptions {
4
+ server?: string | undefined;
5
+ network?: string | undefined;
6
+ /** Where fetched files land. Defaults to the working directory the person started this in. */
7
+ out?: string | undefined;
8
+ /** Overridable so a test can drive both ends without pipes. */
9
+ input?: NodeJS.ReadableStream;
10
+ output?: (line: string) => void;
11
+ note?: (line: string) => void;
12
+ }
13
+ /**
14
+ * Every schema this program actually serves, for the gate that checks they can be enforced.
15
+ *
16
+ * ⛔ IT BUILDS THE REAL TABLE rather than restating it. A hand-kept list of tool names in a test is
17
+ * a list that goes stale the day somebody adds a tool, and the failure is a tool nobody checks.
18
+ * The context here is a placeholder — no tool reads it while its schema is being looked at.
19
+ */
20
+ export declare function mcpToolSchemas(): {
21
+ name: string;
22
+ inputSchema: Record<string, unknown>;
23
+ }[];
24
+ export declare function mcp(options?: McpOptions): Promise<number>;
@@ -35,16 +35,21 @@ import { requireAccountCode } from "../code-access.js";
35
35
  import { API_KEY_ENV_VAR, CODE_ENV_VAR, readCredentialsFile, resolveApiKey } from "../credentials.js";
36
36
  import { NmtsError } from "../errors.js";
37
37
  import { serve } from "../mcp.js";
38
+ import { describeSighting } from "../agent-host.js";
38
39
  // ⚠ Re-exported so callers that knew it here keep working; the rule itself lives one level up now.
39
40
  import { destinationFor } from "../safe-path.js";
40
41
  export { destinationFor };
41
42
  import { BINARY_NAME, PRODUCT_NAME, VERSION } from "../product.js";
42
43
  import { resolveNetwork } from "../network.js";
43
44
  import { resolveServer } from "../server.js";
45
+ import { creditTools } from "../mcp-tools/credits.js";
44
46
  import { fileTools } from "../mcp-tools/files.js";
45
47
  import { organiseTools } from "../mcp-tools/organise.js";
46
48
  import { readTools } from "../mcp-tools/reads.js";
47
49
  import { shareTools } from "../mcp-tools/share.js";
50
+ import { withTiers } from "../mcp-tools/tiers.js";
51
+ import { supportTools } from "../mcp-tools/support.js";
52
+ import { currentMode } from "../autonomy.js";
48
53
  /**
49
54
  * Which account this server is holding, answered without asking anything.
50
55
  *
@@ -56,7 +61,7 @@ import { shareTools } from "../mcp-tools/share.js";
56
61
  function whoami(ctx) {
57
62
  return {
58
63
  name: "nmts_whoami",
59
- description: "Which NMTS account this machine holds the code for. Derived here, offline: it says " +
64
+ description: "Which NMTS account this machine holds the NMTS key for. Derived here, offline: it says " +
60
65
  "nothing about whether that account exists on the server or has credits.",
61
66
  inputSchema: { type: "object", properties: {}, additionalProperties: false },
62
67
  async run() {
@@ -77,8 +82,22 @@ function whoami(ctx) {
77
82
  * The context here is a placeholder — no tool reads it while its schema is being looked at.
78
83
  */
79
84
  export function mcpToolSchemas() {
80
- const ctx = { server: "https://example.invalid", network: "testnet", outDir: "/", accountId: "-" };
81
- const all = [whoami(ctx), ...readTools(ctx), ...fileTools(ctx), ...organiseTools(ctx), ...shareTools(ctx)];
85
+ const ctx = {
86
+ server: "https://example.invalid",
87
+ network: "testnet",
88
+ outDir: "/",
89
+ accountId: "-",
90
+ asker: () => null,
91
+ };
92
+ const all = [
93
+ whoami(ctx),
94
+ ...readTools(ctx),
95
+ ...fileTools(ctx),
96
+ ...organiseTools(ctx),
97
+ ...creditTools(ctx),
98
+ ...shareTools(ctx),
99
+ ...supportTools(ctx),
100
+ ];
82
101
  return all.map((t) => ({ name: t.name, inputSchema: t.inputSchema }));
83
102
  }
84
103
  export async function mcp(options = {}) {
@@ -109,7 +128,21 @@ export async function mcp(options = {}) {
109
128
  if (!statSync(outDir).isDirectory()) {
110
129
  throw new NmtsError(`${outDir} is not a directory.`, { exitCode: 2 });
111
130
  }
112
- const ctx = { server, network, outDir, accountId: identity.accountId };
131
+ /**
132
+ * How this session asks the person a question, filled in when the client says whether it can.
133
+ *
134
+ * ⛔ IT STARTS AS "NO WAY TO ASK" AND THAT IS THE RIGHT STARTING POINT. A tool call cannot
135
+ * arrive before `initialize`, so this is only ever read after the client has spoken; if a
136
+ * client somehow skipped that, the tools that need an answer refuse rather than assume one.
137
+ */
138
+ let asker = null;
139
+ const ctx = {
140
+ server,
141
+ network,
142
+ outDir,
143
+ accountId: identity.accountId,
144
+ asker: () => asker,
145
+ };
113
146
  /**
114
147
  * The whole surface, in one place.
115
148
  *
@@ -123,8 +156,17 @@ export async function mcp(options = {}) {
123
156
  ...readTools(ctx),
124
157
  ...fileTools(ctx),
125
158
  ...organiseTools(ctx),
159
+ ...creditTools(ctx),
126
160
  ...shareTools(ctx),
161
+ // ⛔ LAST, AND NOT BECAUSE IT MATTERS LEAST. The order is the order a client shows them in,
162
+ // and writing to the developer is the one thing here that is not about this account's
163
+ // files at all — a model scanning the list should meet it after everything the work
164
+ // itself needs.
165
+ ...supportTools(ctx),
127
166
  ];
167
+ // ⛔ THE TIER GATE, AROUND EVERY TOOL (`mcp-tools/tiers.ts`): the same table the command line
168
+ // reads, asked over elicitation instead of a terminal.
169
+ const gated = withTiers(tools, ctx.asker);
128
170
  // ⛔ To stderr, deliberately. A person starting this by hand should see what it is; a client
129
171
  // reading stdout must see nothing but protocol.
130
172
  note(`${PRODUCT_NAME} · ${identity.accountId} · ${network} · files land in ${outDir}`);
@@ -132,8 +174,31 @@ export async function mcp(options = {}) {
132
174
  await serve({
133
175
  input: options.input ?? process.stdin,
134
176
  output: options.output ?? ((line) => process.stdout.write(`${line}\n`)),
135
- tools,
177
+ tools: gated,
136
178
  info: { name: BINARY_NAME, version: VERSION },
179
+ // ⛔ WHO CONNECTED, SAID ONCE, TO STDERR. It is the only moment this is knowable: the name
180
+ // travels in `initialize` rather than in the environment, which is why it survives the
181
+ // three hosts that clear the environment before starting a server. A person reading the
182
+ // log of a server they did not start themselves has nowhere else to learn it.
183
+ onClient: (client) => {
184
+ if (client.host !== null)
185
+ note(`Client: ${describeSighting(client.host)}`);
186
+ else if (client.name !== null)
187
+ note(`Client: ${client.name} — not an agent this version knows by name`);
188
+ },
189
+ // ⛔ AND WHETHER IT CAN BE ASKED ANYTHING, said once for the same reason. A person watching
190
+ // this log needs to know before the first share, not when it is refused.
191
+ onAsker: (built) => {
192
+ asker = built;
193
+ // ⚠ A MODE THAT IS ON DECIDES THIS, so it is read here rather than assumed. Saying "every
194
+ // share will ask you" to somebody who turned a mode on would be telling them the opposite
195
+ // of what their own setting does.
196
+ if (currentMode() !== "default")
197
+ return;
198
+ note(built === null
199
+ ? "This client cannot show you a question, so sharing is refused here. Share from a terminal."
200
+ : "This client can show you a question; every share will ask you first.");
201
+ },
137
202
  });
138
203
  return 0;
139
204
  }
@@ -0,0 +1,8 @@
1
+ export interface ModeOptions {
2
+ json?: boolean;
3
+ write?: (line: string) => void;
4
+ now?: () => Date;
5
+ /** Injected in tests: answers the one question. Its presence also stands in for a terminal. */
6
+ readLine?: ((question: string) => Promise<string>) | undefined;
7
+ }
8
+ export declare function mode(wanted: string | undefined, target: string | undefined, options?: ModeOptions): Promise<number>;