@cortexkit/opencode-antigravity-auth 3.0.4 → 3.0.6

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 (370) hide show
  1. package/README.md +38 -352
  2. package/dist/cli.js +9199 -8799
  3. package/dist/cli.js.map +4 -4
  4. package/dist/cli.meta.json +1286 -1064
  5. package/dist/index.js +13641 -14559
  6. package/dist/index.js.map +4 -4
  7. package/dist/index.meta.json +1333 -1342
  8. package/dist/server.js +9578 -9987
  9. package/dist/server.js.map +4 -4
  10. package/dist/server.meta.json +1 -1
  11. package/dist/src/auth-method-labels.d.ts +3 -0
  12. package/dist/src/auth-method-labels.d.ts.map +1 -0
  13. package/dist/src/auth-method-labels.js +5 -0
  14. package/dist/src/auth-method-labels.js.map +1 -0
  15. package/dist/src/cli.d.ts +3 -1
  16. package/dist/src/cli.d.ts.map +1 -1
  17. package/dist/src/cli.js +98 -12
  18. package/dist/src/cli.js.map +1 -1
  19. package/dist/src/common-auth-embedded/claustrum/consumer.d.ts +33 -3
  20. package/dist/src/common-auth-embedded/claustrum/consumer.js +96 -1
  21. package/dist/src/common-auth-embedded/claustrum/custody.d.ts +4 -1
  22. package/dist/src/common-auth-embedded/claustrum/enrollment.d.ts +6 -1
  23. package/dist/src/common-auth-embedded/claustrum/enrollment.js +6 -1
  24. package/dist/src/common-auth-embedded/claustrum/index.d.ts +2 -1
  25. package/dist/src/common-auth-embedded/claustrum/index.js +5 -3
  26. package/dist/src/common-auth-embedded/claustrum/insula.d.ts +69 -0
  27. package/dist/src/common-auth-embedded/claustrum/insula.js +152 -0
  28. package/dist/src/common-auth-embedded/claustrum/roster.d.ts +13 -0
  29. package/dist/src/common-auth-embedded/claustrum/roster.js +33 -3
  30. package/dist/src/common-auth-embedded/fs/refresh-file-lock.js +20 -11
  31. package/dist/src/common-auth-embedded/quota/codec.d.ts +2 -0
  32. package/dist/src/common-auth-embedded/quota/codec.js +2 -1
  33. package/dist/src/common-auth-embedded/quota/format.d.ts +26 -0
  34. package/dist/src/common-auth-embedded/quota/format.js +78 -42
  35. package/dist/src/common-auth-embedded/quota/index.d.ts +4 -4
  36. package/dist/src/common-auth-embedded/quota/index.js +2 -2
  37. package/dist/src/common-auth-embedded/quota/map.d.ts +11 -0
  38. package/dist/src/common-auth-embedded/quota/map.js +36 -1
  39. package/dist/src/common-auth-embedded/quota/merge.d.ts +3 -1
  40. package/dist/src/common-auth-embedded/quota/merge.js +21 -5
  41. package/dist/src/common-auth-embedded/quota/projection.d.ts +2 -1
  42. package/dist/src/common-auth-embedded/quota/projection.js +3 -1
  43. package/dist/src/common-auth-embedded/setup/command-runner.js +49 -0
  44. package/dist/src/common-auth-embedded/setup/command.d.ts +3 -0
  45. package/dist/src/common-auth-embedded/setup/command.js +215 -0
  46. package/dist/src/common-auth-embedded/setup/config-write.js +60 -0
  47. package/dist/src/common-auth-embedded/setup/detect.d.ts +6 -0
  48. package/dist/src/common-auth-embedded/setup/detect.js +224 -0
  49. package/dist/src/common-auth-embedded/setup/enroll.js +70 -0
  50. package/dist/src/common-auth-embedded/setup/index.d.ts +5 -0
  51. package/dist/src/common-auth-embedded/setup/index.js +4 -0
  52. package/dist/src/common-auth-embedded/setup/paths.js +33 -0
  53. package/dist/src/common-auth-embedded/setup/process-fence.d.ts +43 -0
  54. package/dist/src/common-auth-embedded/setup/process-fence.js +270 -0
  55. package/dist/src/common-auth-embedded/setup/prompts.js +26 -0
  56. package/dist/src/common-auth-embedded/setup/register.d.ts +11 -0
  57. package/dist/src/common-auth-embedded/setup/register.js +130 -0
  58. package/dist/src/common-auth-embedded/setup/types.d.ts +136 -0
  59. package/dist/src/common-auth-embedded/source-output.json +228 -80
  60. package/dist/src/common-auth-embedded/store/schema.d.ts +2 -0
  61. package/dist/src/common-auth-embedded/store/schema.js +3 -2
  62. package/dist/src/ga/rpc/protocol.d.ts +6 -10
  63. package/dist/src/ga/rpc/protocol.d.ts.map +1 -1
  64. package/dist/src/ga/rpc/protocol.js +65 -13
  65. package/dist/src/ga/rpc/protocol.js.map +1 -1
  66. package/dist/src/ga/server/auth.d.ts +8 -3
  67. package/dist/src/ga/server/auth.d.ts.map +1 -1
  68. package/dist/src/ga/server/auth.js +25 -9
  69. package/dist/src/ga/server/auth.js.map +1 -1
  70. package/dist/src/ga/server/index.d.ts +39 -12
  71. package/dist/src/ga/server/index.d.ts.map +1 -1
  72. package/dist/src/ga/server/index.js +229 -55
  73. package/dist/src/ga/server/index.js.map +1 -1
  74. package/dist/src/ga/server/pool-login.d.ts +22 -0
  75. package/dist/src/ga/server/pool-login.d.ts.map +1 -0
  76. package/dist/src/ga/server/pool-login.js +150 -0
  77. package/dist/src/ga/server/pool-login.js.map +1 -0
  78. package/dist/src/ga/tui/host-ga.d.ts +2 -5
  79. package/dist/src/ga/tui/host-ga.d.ts.map +1 -1
  80. package/dist/src/ga/tui/host-ga.js +17 -49
  81. package/dist/src/ga/tui/host-ga.js.map +1 -1
  82. package/dist/src/plugin/accounts.d.ts +1 -1
  83. package/dist/src/plugin/accounts.d.ts.map +1 -1
  84. package/dist/src/plugin/accounts.js +1 -0
  85. package/dist/src/plugin/accounts.js.map +1 -1
  86. package/dist/src/plugin/background-vault-quota-refresh.d.ts +2 -0
  87. package/dist/src/plugin/background-vault-quota-refresh.d.ts.map +1 -1
  88. package/dist/src/plugin/background-vault-quota-refresh.js +125 -10
  89. package/dist/src/plugin/background-vault-quota-refresh.js.map +1 -1
  90. package/dist/src/plugin/command-apply.d.ts +2 -2
  91. package/dist/src/plugin/command-apply.d.ts.map +1 -1
  92. package/dist/src/plugin/command-apply.js +3 -10
  93. package/dist/src/plugin/command-apply.js.map +1 -1
  94. package/dist/src/plugin/commands.d.ts +1 -0
  95. package/dist/src/plugin/commands.d.ts.map +1 -1
  96. package/dist/src/plugin/commands.js +2 -2
  97. package/dist/src/plugin/commands.js.map +1 -1
  98. package/dist/src/plugin/config/operator-settings-schema.d.ts +0 -4
  99. package/dist/src/plugin/config/operator-settings-schema.d.ts.map +1 -1
  100. package/dist/src/plugin/config/operator-settings-schema.js +0 -5
  101. package/dist/src/plugin/config/operator-settings-schema.js.map +1 -1
  102. package/dist/src/plugin/config/schema.d.ts +0 -7
  103. package/dist/src/plugin/config/schema.d.ts.map +1 -1
  104. package/dist/src/plugin/config/schema.js +0 -43
  105. package/dist/src/plugin/config/schema.js.map +1 -1
  106. package/dist/src/plugin/config/writer.d.ts +1 -1
  107. package/dist/src/plugin/config/writer.js +1 -1
  108. package/dist/src/plugin/fetch/retry-state.d.ts +19 -3
  109. package/dist/src/plugin/fetch/retry-state.d.ts.map +1 -1
  110. package/dist/src/plugin/fetch/retry-state.js +0 -6
  111. package/dist/src/plugin/fetch/retry-state.js.map +1 -1
  112. package/dist/src/plugin/fetch-interceptor.d.ts.map +1 -1
  113. package/dist/src/plugin/fetch-interceptor.js +0 -3
  114. package/dist/src/plugin/fetch-interceptor.js.map +1 -1
  115. package/dist/src/plugin/fetch-routing.d.ts +0 -16
  116. package/dist/src/plugin/fetch-routing.d.ts.map +1 -1
  117. package/dist/src/plugin/fetch-routing.js +0 -49
  118. package/dist/src/plugin/fetch-routing.js.map +1 -1
  119. package/dist/src/plugin/ga-location-services.d.ts +14 -9
  120. package/dist/src/plugin/ga-location-services.d.ts.map +1 -1
  121. package/dist/src/plugin/ga-location-services.js +120 -40
  122. package/dist/src/plugin/ga-location-services.js.map +1 -1
  123. package/dist/src/plugin/google-origin.d.ts +7 -0
  124. package/dist/src/plugin/google-origin.d.ts.map +1 -0
  125. package/dist/src/plugin/google-origin.js +14 -0
  126. package/dist/src/plugin/google-origin.js.map +1 -0
  127. package/dist/src/plugin/index.d.ts.map +1 -1
  128. package/dist/src/plugin/index.js +15 -4
  129. package/dist/src/plugin/index.js.map +1 -1
  130. package/dist/src/plugin/oauth-methods.d.ts.map +1 -1
  131. package/dist/src/plugin/oauth-methods.js +0 -33
  132. package/dist/src/plugin/oauth-methods.js.map +1 -1
  133. package/dist/src/plugin/operator-settings.d.ts +1 -1
  134. package/dist/src/plugin/operator-settings.d.ts.map +1 -1
  135. package/dist/src/plugin/operator-settings.js +1 -8
  136. package/dist/src/plugin/operator-settings.js.map +1 -1
  137. package/dist/src/plugin/quota.d.ts +11 -7
  138. package/dist/src/plugin/quota.d.ts.map +1 -1
  139. package/dist/src/plugin/quota.js +128 -102
  140. package/dist/src/plugin/quota.js.map +1 -1
  141. package/dist/src/plugin/request.d.ts +5 -3
  142. package/dist/src/plugin/request.d.ts.map +1 -1
  143. package/dist/src/plugin/request.js +87 -168
  144. package/dist/src/plugin/request.js.map +1 -1
  145. package/dist/src/plugin/server.d.ts.map +1 -1
  146. package/dist/src/plugin/server.js +60 -53
  147. package/dist/src/plugin/server.js.map +1 -1
  148. package/dist/src/plugin/shared/advisory-repository.d.ts +20 -0
  149. package/dist/src/plugin/shared/advisory-repository.d.ts.map +1 -0
  150. package/dist/src/plugin/shared/advisory-repository.js +91 -0
  151. package/dist/src/plugin/shared/advisory-repository.js.map +1 -0
  152. package/dist/src/plugin/shared/request-services.d.ts +19 -25
  153. package/dist/src/plugin/shared/request-services.d.ts.map +1 -1
  154. package/dist/src/plugin/shared/request-services.js +105 -188
  155. package/dist/src/plugin/shared/request-services.js.map +1 -1
  156. package/dist/src/plugin/shared/runtime.js +4 -2
  157. package/dist/src/plugin/shared/runtime.js.map +1 -1
  158. package/dist/src/plugin/shared/vault-request-credentials.d.ts +4 -1
  159. package/dist/src/plugin/shared/vault-request-credentials.d.ts.map +1 -1
  160. package/dist/src/plugin/shared/vault-request-credentials.js +41 -7
  161. package/dist/src/plugin/shared/vault-request-credentials.js.map +1 -1
  162. package/dist/src/plugin/storage.d.ts +2 -2
  163. package/dist/src/plugin/storage.d.ts.map +1 -1
  164. package/dist/src/plugin/storage.js.map +1 -1
  165. package/dist/src/plugin/vault-custody.d.ts.map +1 -1
  166. package/dist/src/plugin/vault-custody.js +147 -35
  167. package/dist/src/plugin/vault-custody.js.map +1 -1
  168. package/dist/src/plugin/vault-quota-outcome.d.ts +19 -0
  169. package/dist/src/plugin/vault-quota-outcome.d.ts.map +1 -0
  170. package/dist/src/plugin/vault-quota-outcome.js +47 -0
  171. package/dist/src/plugin/vault-quota-outcome.js.map +1 -0
  172. package/dist/src/quota-presentation.d.ts +29 -1
  173. package/dist/src/quota-presentation.d.ts.map +1 -1
  174. package/dist/src/quota-presentation.js +52 -17
  175. package/dist/src/quota-presentation.js.map +1 -1
  176. package/dist/src/setup.d.ts +15 -0
  177. package/dist/src/setup.d.ts.map +1 -0
  178. package/dist/src/setup.js +320 -0
  179. package/dist/src/setup.js.map +1 -0
  180. package/dist/src/sidebar-projection.d.ts +1 -1
  181. package/dist/src/sidebar-projection.d.ts.map +1 -1
  182. package/dist/src/sidebar-state.d.ts +1 -1
  183. package/dist/src/sidebar-state.d.ts.map +1 -1
  184. package/dist/src/sidebar-state.js +19 -1
  185. package/dist/src/sidebar-state.js.map +1 -1
  186. package/dist/src/tui.d.ts.map +1 -1
  187. package/dist/src/tui.js +205 -110
  188. package/dist/src/tui.js.map +1 -1
  189. package/dist/tui-build-map.json +37 -37
  190. package/dist/tui-ga-build-map.json +33 -33
  191. package/dist/types/src/auth-method-labels.d.ts +3 -0
  192. package/dist/types/src/auth-method-labels.d.ts.map +1 -0
  193. package/dist/types/src/cli.d.ts +3 -1
  194. package/dist/types/src/cli.d.ts.map +1 -1
  195. package/dist/types/src/common-auth-embedded/auth-menu/terminal.d.ts +43 -0
  196. package/dist/types/src/common-auth-embedded/claustrum/consumer.d.ts +132 -0
  197. package/dist/types/src/common-auth-embedded/claustrum/custody.d.ts +178 -0
  198. package/dist/types/src/common-auth-embedded/claustrum/enrollment.d.ts +164 -0
  199. package/dist/types/src/common-auth-embedded/claustrum/errors.d.ts +16 -0
  200. package/dist/types/src/common-auth-embedded/claustrum/host-slot.d.ts +39 -0
  201. package/dist/types/src/common-auth-embedded/claustrum/index.d.ts +19 -0
  202. package/dist/types/src/common-auth-embedded/claustrum/insula.d.ts +69 -0
  203. package/dist/types/src/common-auth-embedded/claustrum/interlock.d.ts +27 -0
  204. package/dist/types/src/common-auth-embedded/claustrum/roster.d.ts +221 -0
  205. package/dist/types/src/common-auth-embedded/opencode2/errors.d.ts +25 -0
  206. package/dist/types/src/common-auth-embedded/opencode2/index.d.ts +8 -0
  207. package/dist/types/src/common-auth-embedded/opencode2/install.d.ts +55 -0
  208. package/dist/types/src/common-auth-embedded/opencode2/integration.d.ts +112 -0
  209. package/dist/types/src/common-auth-embedded/opencode2/sse.d.ts +12 -0
  210. package/dist/types/src/common-auth-embedded/opencode2/types.d.ts +413 -0
  211. package/dist/types/src/common-auth-embedded/quota/codec.d.ts +2 -0
  212. package/dist/types/src/common-auth-embedded/quota/format.d.ts +26 -0
  213. package/dist/types/src/common-auth-embedded/quota/index.d.ts +4 -4
  214. package/dist/types/src/common-auth-embedded/quota/map.d.ts +11 -0
  215. package/dist/types/src/common-auth-embedded/quota/merge.d.ts +3 -1
  216. package/dist/types/src/common-auth-embedded/quota/projection.d.ts +2 -1
  217. package/dist/types/src/common-auth-embedded/routing/admission.d.ts +93 -0
  218. package/dist/types/src/common-auth-embedded/routing/index.d.ts +8 -0
  219. package/dist/types/src/common-auth-embedded/routing/ordered.d.ts +47 -0
  220. package/dist/types/src/common-auth-embedded/routing/pins.d.ts +22 -0
  221. package/dist/types/src/common-auth-embedded/routing/sticky.d.ts +158 -0
  222. package/dist/types/src/common-auth-embedded/setup/command.d.ts +3 -0
  223. package/dist/types/src/common-auth-embedded/setup/detect.d.ts +6 -0
  224. package/dist/types/src/common-auth-embedded/setup/index.d.ts +5 -0
  225. package/dist/types/src/common-auth-embedded/setup/process-fence.d.ts +43 -0
  226. package/dist/types/src/common-auth-embedded/setup/register.d.ts +11 -0
  227. package/dist/types/src/common-auth-embedded/setup/types.d.ts +136 -0
  228. package/dist/types/src/common-auth-embedded/store/schema.d.ts +2 -0
  229. package/dist/types/src/ga/rpc/protocol.d.ts +6 -10
  230. package/dist/types/src/ga/rpc/protocol.d.ts.map +1 -1
  231. package/dist/types/src/ga/server/auth.d.ts +8 -3
  232. package/dist/types/src/ga/server/auth.d.ts.map +1 -1
  233. package/dist/types/src/ga/server/index.d.ts +39 -12
  234. package/dist/types/src/ga/server/index.d.ts.map +1 -1
  235. package/dist/types/src/ga/server/pool-login.d.ts +22 -0
  236. package/dist/types/src/ga/server/pool-login.d.ts.map +1 -0
  237. package/dist/types/src/plugin/accounts.d.ts +1 -1
  238. package/dist/types/src/plugin/accounts.d.ts.map +1 -1
  239. package/dist/types/src/plugin/background-vault-quota-refresh.d.ts +2 -0
  240. package/dist/types/src/plugin/background-vault-quota-refresh.d.ts.map +1 -1
  241. package/dist/types/src/plugin/command-apply.d.ts +2 -2
  242. package/dist/types/src/plugin/command-apply.d.ts.map +1 -1
  243. package/dist/types/src/plugin/commands.d.ts +1 -0
  244. package/dist/types/src/plugin/commands.d.ts.map +1 -1
  245. package/dist/types/src/plugin/config/operator-settings-schema.d.ts +0 -4
  246. package/dist/types/src/plugin/config/operator-settings-schema.d.ts.map +1 -1
  247. package/dist/types/src/plugin/config/schema.d.ts +0 -7
  248. package/dist/types/src/plugin/config/schema.d.ts.map +1 -1
  249. package/dist/types/src/plugin/config/writer.d.ts +1 -1
  250. package/dist/types/src/plugin/fetch/retry-state.d.ts +19 -3
  251. package/dist/types/src/plugin/fetch/retry-state.d.ts.map +1 -1
  252. package/dist/types/src/plugin/fetch-interceptor.d.ts.map +1 -1
  253. package/dist/types/src/plugin/fetch-routing.d.ts +0 -16
  254. package/dist/types/src/plugin/fetch-routing.d.ts.map +1 -1
  255. package/dist/types/src/plugin/ga-location-services.d.ts +14 -9
  256. package/dist/types/src/plugin/ga-location-services.d.ts.map +1 -1
  257. package/dist/types/src/plugin/google-origin.d.ts +7 -0
  258. package/dist/types/src/plugin/google-origin.d.ts.map +1 -0
  259. package/dist/types/src/plugin/index.d.ts.map +1 -1
  260. package/dist/types/src/plugin/oauth-methods.d.ts.map +1 -1
  261. package/dist/types/src/plugin/operator-settings.d.ts +1 -1
  262. package/dist/types/src/plugin/operator-settings.d.ts.map +1 -1
  263. package/dist/types/src/plugin/quota.d.ts +11 -7
  264. package/dist/types/src/plugin/quota.d.ts.map +1 -1
  265. package/dist/types/src/plugin/request.d.ts +5 -3
  266. package/dist/types/src/plugin/request.d.ts.map +1 -1
  267. package/dist/types/src/plugin/server.d.ts.map +1 -1
  268. package/dist/types/src/plugin/shared/advisory-repository.d.ts +20 -0
  269. package/dist/types/src/plugin/shared/advisory-repository.d.ts.map +1 -0
  270. package/dist/types/src/plugin/shared/request-services.d.ts +19 -25
  271. package/dist/types/src/plugin/shared/request-services.d.ts.map +1 -1
  272. package/dist/types/src/plugin/shared/vault-request-credentials.d.ts +4 -1
  273. package/dist/types/src/plugin/shared/vault-request-credentials.d.ts.map +1 -1
  274. package/dist/types/src/plugin/storage.d.ts +2 -2
  275. package/dist/types/src/plugin/storage.d.ts.map +1 -1
  276. package/dist/types/src/plugin/vault-custody.d.ts.map +1 -1
  277. package/dist/types/src/plugin/vault-quota-outcome.d.ts +19 -0
  278. package/dist/types/src/plugin/vault-quota-outcome.d.ts.map +1 -0
  279. package/dist/types/src/setup.d.ts +15 -0
  280. package/dist/types/src/setup.d.ts.map +1 -0
  281. package/dist/types/src/sidebar-state.d.ts +1 -1
  282. package/dist/types/src/sidebar-state.d.ts.map +1 -1
  283. package/package.json +5 -4
  284. package/src/common-auth-embedded/claustrum/consumer.d.ts +33 -3
  285. package/src/common-auth-embedded/claustrum/consumer.js +96 -1
  286. package/src/common-auth-embedded/claustrum/custody.d.ts +4 -1
  287. package/src/common-auth-embedded/claustrum/enrollment.d.ts +6 -1
  288. package/src/common-auth-embedded/claustrum/enrollment.js +6 -1
  289. package/src/common-auth-embedded/claustrum/index.d.ts +2 -1
  290. package/src/common-auth-embedded/claustrum/index.js +5 -3
  291. package/src/common-auth-embedded/claustrum/insula.d.ts +69 -0
  292. package/src/common-auth-embedded/claustrum/insula.js +152 -0
  293. package/src/common-auth-embedded/claustrum/roster.d.ts +13 -0
  294. package/src/common-auth-embedded/claustrum/roster.js +33 -3
  295. package/src/common-auth-embedded/fs/refresh-file-lock.js +20 -11
  296. package/src/common-auth-embedded/quota/codec.d.ts +2 -0
  297. package/src/common-auth-embedded/quota/codec.js +2 -1
  298. package/src/common-auth-embedded/quota/format.d.ts +26 -0
  299. package/src/common-auth-embedded/quota/format.js +78 -42
  300. package/src/common-auth-embedded/quota/index.d.ts +4 -4
  301. package/src/common-auth-embedded/quota/index.js +2 -2
  302. package/src/common-auth-embedded/quota/map.d.ts +11 -0
  303. package/src/common-auth-embedded/quota/map.js +36 -1
  304. package/src/common-auth-embedded/quota/merge.d.ts +3 -1
  305. package/src/common-auth-embedded/quota/merge.js +21 -5
  306. package/src/common-auth-embedded/quota/projection.d.ts +2 -1
  307. package/src/common-auth-embedded/quota/projection.js +3 -1
  308. package/src/common-auth-embedded/setup/command-runner.js +49 -0
  309. package/src/common-auth-embedded/setup/command.d.ts +3 -0
  310. package/src/common-auth-embedded/setup/command.js +215 -0
  311. package/src/common-auth-embedded/setup/config-write.js +60 -0
  312. package/src/common-auth-embedded/setup/detect.d.ts +6 -0
  313. package/src/common-auth-embedded/setup/detect.js +224 -0
  314. package/src/common-auth-embedded/setup/enroll.js +70 -0
  315. package/src/common-auth-embedded/setup/index.d.ts +5 -0
  316. package/src/common-auth-embedded/setup/index.js +4 -0
  317. package/src/common-auth-embedded/setup/paths.js +33 -0
  318. package/src/common-auth-embedded/setup/process-fence.d.ts +43 -0
  319. package/src/common-auth-embedded/setup/process-fence.js +270 -0
  320. package/src/common-auth-embedded/setup/prompts.js +26 -0
  321. package/src/common-auth-embedded/setup/register.d.ts +11 -0
  322. package/src/common-auth-embedded/setup/register.js +130 -0
  323. package/src/common-auth-embedded/setup/types.d.ts +136 -0
  324. package/src/common-auth-embedded/source-output.json +228 -80
  325. package/src/common-auth-embedded/store/schema.d.ts +2 -0
  326. package/src/common-auth-embedded/store/schema.js +3 -2
  327. package/src/sidebar-state.ts +19 -2
  328. package/src/tui-compiled/common-auth-embedded/quota/codec.js +2 -1
  329. package/src/tui-compiled/common-auth-embedded/quota/format.js +78 -42
  330. package/src/tui-compiled/common-auth-embedded/quota/index.js +2 -2
  331. package/src/tui-compiled/common-auth-embedded/quota/map.js +36 -1
  332. package/src/tui-compiled/common-auth-embedded/quota/merge.js +21 -5
  333. package/src/tui-compiled/common-auth-embedded/quota/projection.js +3 -1
  334. package/src/tui-compiled/quota-presentation.js +42 -9
  335. package/src/tui-compiled/sidebar-state.js +15 -1
  336. package/src/tui-compiled/tui.js +516 -334
  337. package/src/tui-ga-compiled/host-ga.js +11 -38
  338. package/src/tui-ga-compiled/shared/1ff34afa7c42d196-projection.js +3 -1
  339. package/src/tui-ga-compiled/shared/77138df80c7ae006-map.js +36 -1
  340. package/src/tui-ga-compiled/shared/98cc0c186c46c42d-quota-presentation.js +42 -9
  341. package/src/tui-ga-compiled/shared/aef2402f8fc342f0-format.js +78 -42
  342. package/src/tui-ga-compiled/shared/bf17cbee28e58197-index.js +2 -2
  343. package/src/tui-ga-compiled/shared/ca21dc417b36dc5d-codec.js +2 -1
  344. package/src/tui-ga-compiled/shared/ecc214300932dfb6-merge.js +21 -5
  345. package/src/tui-ga-raw/host-ga.tsx +31 -62
  346. package/src/tui-ga-raw/shared/1ff34afa7c42d196-projection.js +3 -1
  347. package/src/tui-ga-raw/shared/77138df80c7ae006-map.js +36 -1
  348. package/src/tui-ga-raw/shared/98cc0c186c46c42d-quota-presentation.js +42 -9
  349. package/src/tui-ga-raw/shared/aef2402f8fc342f0-format.js +78 -42
  350. package/src/tui-ga-raw/shared/bf17cbee28e58197-index.js +2 -2
  351. package/src/tui-ga-raw/shared/ca21dc417b36dc5d-codec.js +2 -1
  352. package/src/tui-ga-raw/shared/ecc214300932dfb6-merge.js +21 -5
  353. package/src/tui-raw/common-auth-embedded/quota/codec.js +2 -1
  354. package/src/tui-raw/common-auth-embedded/quota/format.js +78 -42
  355. package/src/tui-raw/common-auth-embedded/quota/index.js +2 -2
  356. package/src/tui-raw/common-auth-embedded/quota/map.js +36 -1
  357. package/src/tui-raw/common-auth-embedded/quota/merge.js +21 -5
  358. package/src/tui-raw/common-auth-embedded/quota/projection.js +3 -1
  359. package/src/tui-raw/quota-presentation.js +42 -9
  360. package/src/tui-raw/sidebar-state.js +15 -1
  361. package/src/tui-raw/tui.tsx +423 -218
  362. package/src/tui.tsx +423 -218
  363. package/dist/src/tui/vault-setup.d.ts +0 -98
  364. package/dist/src/tui/vault-setup.d.ts.map +0 -1
  365. package/dist/src/tui/vault-setup.js +0 -198
  366. package/dist/src/tui/vault-setup.js.map +0 -1
  367. package/dist/types/src/plugin/transform/model-resolver.d.ts +0 -2
  368. package/dist/types/src/plugin/transform/model-resolver.d.ts.map +0 -1
  369. package/dist/types/src/quota-presentation.d.ts +0 -18
  370. package/dist/types/src/quota-presentation.d.ts.map +0 -1
@@ -0,0 +1,224 @@
1
+ import { accessSync, constants, existsSync, readFileSync, realpathSync, statSync, } from 'node:fs';
2
+ import { mkdtemp, rm } from 'node:fs/promises';
3
+ import { tmpdir } from 'node:os';
4
+ import { join } from 'node:path';
5
+ import { parse } from 'jsonc-parser';
6
+ import { connectClaustrumEnrollmentClient } from '../claustrum/enrollment.js';
7
+ import { defaultCommandRunner, runResolvedCommand } from './command-runner.js';
8
+ import { setupPaths } from './paths.js';
9
+ function stat(path, kind) {
10
+ try {
11
+ return statSync(path)[kind]();
12
+ }
13
+ catch {
14
+ return false;
15
+ }
16
+ }
17
+ export const defaultSetupFileSystem = {
18
+ exists: existsSync,
19
+ isFile: (path) => stat(path, 'isFile'),
20
+ isDirectory: (path) => stat(path, 'isDirectory'),
21
+ isExecutable(path) {
22
+ try {
23
+ accessSync(path, constants.X_OK);
24
+ return stat(path, 'isFile');
25
+ }
26
+ catch {
27
+ return false;
28
+ }
29
+ },
30
+ readText: (path) => readFileSync(path, 'utf8'),
31
+ realpath: realpathSync,
32
+ };
33
+ export function findExecutableOnPath(name, io = {}) {
34
+ const { env, platform, path, cwd } = setupPaths(io);
35
+ const fs = io.fs ?? defaultSetupFileSystem;
36
+ const value = Object.entries(env).find(([key]) => platform === 'win32' ? key.toUpperCase() === 'PATH' : key === 'PATH')?.[1] ?? '';
37
+ // npm also writes an extensionless POSIX shim on Windows; prefer a runnable launcher.
38
+ const suffixes = platform === 'win32' ? ['.exe', '.cmd', '.bat', ''] : [''];
39
+ for (const entry of value.split(platform === 'win32' ? ';' : ':')) {
40
+ const dir = entry.trim().replace(/^"|"$/g, '');
41
+ if (!dir)
42
+ continue;
43
+ for (const suffix of suffixes) {
44
+ const candidate = path.resolve(cwd, dir, name + suffix);
45
+ if (platform === 'win32' ? fs.isFile(candidate) : fs.isExecutable(candidate))
46
+ return candidate;
47
+ }
48
+ }
49
+ return null;
50
+ }
51
+ export function openCodeDesktopMarkers(io = {}) {
52
+ const { platform, home, env, path } = setupPaths(io);
53
+ if (platform === 'darwin')
54
+ return [
55
+ '/Applications/OpenCode.app',
56
+ '/Applications/OpenCode Beta.app',
57
+ path.join(home, 'Applications', 'OpenCode.app'),
58
+ path.join(home, 'Applications', 'OpenCode Beta.app'),
59
+ ];
60
+ if (platform === 'win32') {
61
+ const local = env.LOCALAPPDATA || path.join(home, 'AppData', 'Local');
62
+ return [
63
+ path.join(local, 'Programs', 'opencode'),
64
+ path.join(local, 'opencode'),
65
+ ];
66
+ }
67
+ return [
68
+ '/opt/OpenCode',
69
+ '/usr/lib/opencode',
70
+ path.join(home, '.local', 'share', 'applications', 'opencode.desktop'),
71
+ ];
72
+ }
73
+ function launcherTarget(file, io) {
74
+ const fs = io.fs ?? defaultSetupFileSystem;
75
+ const { path } = setupPaths(io);
76
+ try {
77
+ const source = fs.readText(file);
78
+ if (source.length > 64 * 1024)
79
+ return file;
80
+ const operands = [...source.matchAll(/"%~?dp0%?\\([^"%\r\n]+)"/g)];
81
+ if (!operands.length)
82
+ operands.push(...source.matchAll(/"\$basedir\/([^"$\r\n]+)"/g));
83
+ const relative = operands.at(-1)?.[1];
84
+ if (relative) {
85
+ const target = path.join(path.dirname(file), ...relative.split(/[/\\]+/));
86
+ if (fs.isFile(target))
87
+ return fs.realpath(target);
88
+ }
89
+ return fs.realpath(file);
90
+ }
91
+ catch {
92
+ return file;
93
+ }
94
+ }
95
+ function diskGeneration(file, io) {
96
+ const fs = io.fs ?? defaultSetupFileSystem;
97
+ const { path } = setupPaths(io);
98
+ let dir = path.dirname(launcherTarget(file, io));
99
+ for (;;) {
100
+ try {
101
+ const metadata = JSON.parse(fs.readText(path.join(dir, 'package.json')));
102
+ if (['@opencode/cli', '@opencode-ai/cli'].includes(metadata.name))
103
+ return '2';
104
+ if (metadata.name === 'opencode-ai')
105
+ return /^(?:[2-9]\d*|1\d+)\.|^0\.0\.0-(?:beta|dev)-/.test(metadata.version ?? '')
106
+ ? '2'
107
+ : '1';
108
+ }
109
+ catch {
110
+ /* No owning package at this level. */
111
+ }
112
+ const parent = path.dirname(dir);
113
+ if (parent === dir)
114
+ return null;
115
+ dir = parent;
116
+ }
117
+ }
118
+ export function detectOpenCodeGeneration(io = {}) {
119
+ const first = findExecutableOnPath('opencode', io);
120
+ const second = findExecutableOnPath('opencode2', io);
121
+ const shared = first && second && launcherTarget(first, io) === launcherTarget(second, io);
122
+ const fs = io.fs ?? defaultSetupFileSystem;
123
+ const { path, opencode } = setupPaths(io);
124
+ let inferred = '1';
125
+ for (const suffix of ['jsonc', 'json']) {
126
+ const file = path.join(opencode, `opencode.${suffix}`);
127
+ if (!fs.exists(file))
128
+ continue;
129
+ try {
130
+ if (Object.hasOwn(parse(fs.readText(file)) ?? {}, 'plugins'))
131
+ inferred = '2';
132
+ }
133
+ catch {
134
+ /* OpenCode registration rejects malformed config before writing it. */
135
+ }
136
+ break;
137
+ }
138
+ const generation = first
139
+ ? (diskGeneration(first, io) ?? (shared ? '2' : inferred))
140
+ : null;
141
+ if (second && generation === '1' && !shared)
142
+ return 'ambiguous';
143
+ return second || shared ? '2' : (generation ?? inferred);
144
+ }
145
+ export async function detectHosts(plugin, io = {}) {
146
+ const fs = io.fs ?? defaultSetupFileSystem;
147
+ const { env, platform, opencode: configDir, pi: agentDir } = setupPaths(io);
148
+ const runner = io.runner ?? defaultCommandRunner;
149
+ const opencode = findExecutableOnPath('opencode', io) ??
150
+ findExecutableOnPath('opencode2', io);
151
+ const pi = findExecutableOnPath('pi', io);
152
+ const ck = findExecutableOnPath('ck', io);
153
+ const version = async (file) => {
154
+ if (!file)
155
+ return null;
156
+ let root;
157
+ try {
158
+ root = await mkdtemp(join(tmpdir(), 'common-auth-setup-version-'));
159
+ // A diagnostic host launch must not create state in the user's profile, even on a dry run.
160
+ const probeEnv = {
161
+ ...env,
162
+ HOME: root,
163
+ USERPROFILE: root,
164
+ XDG_CONFIG_HOME: root,
165
+ XDG_DATA_HOME: root,
166
+ XDG_STATE_HOME: root,
167
+ XDG_CACHE_HOME: root,
168
+ OPENCODE_CONFIG_DIR: root,
169
+ OPENCODE_CONFIG: undefined,
170
+ OPENCODE_CONFIG_CONTENT: undefined,
171
+ OPENCODE_AUTH_CONTENT: undefined,
172
+ PI_CODING_AGENT_DIR: root,
173
+ };
174
+ const result = await runResolvedCommand(runner, platform, file, ['--version'], probeEnv, 2000);
175
+ return result.exitCode === 0
176
+ ? (/\b\d+\.\d+\.\d+(?:-[\w.-]+)?/.exec(result.stdout)?.[0] ?? null)
177
+ : null;
178
+ }
179
+ catch {
180
+ return null;
181
+ }
182
+ finally {
183
+ if (root)
184
+ await rm(root, { recursive: true, force: true }).catch(() => { });
185
+ }
186
+ };
187
+ let available = false;
188
+ if (ck && fs.exists(plugin.vault.connectionFile)) {
189
+ try {
190
+ const connect = io.connect ?? connectClaustrumEnrollmentClient;
191
+ const client = await connect({
192
+ connectionFile: plugin.vault.connectionFile,
193
+ handshakeTimeoutMs: 2000,
194
+ });
195
+ client.close();
196
+ available = true;
197
+ }
198
+ catch {
199
+ available = false;
200
+ }
201
+ }
202
+ const [openCodeVersion, piVersion] = await Promise.all([
203
+ version(opencode),
204
+ version(pi),
205
+ ]);
206
+ return {
207
+ opencode: {
208
+ installed: fs.isDirectory(configDir) ||
209
+ openCodeDesktopMarkers(io).some((marker) => fs.exists(marker)) ||
210
+ opencode !== null,
211
+ executable: opencode,
212
+ version: openCodeVersion,
213
+ directory: configDir,
214
+ generation: detectOpenCodeGeneration(io),
215
+ },
216
+ pi: {
217
+ installed: pi !== null || fs.isDirectory(agentDir),
218
+ executable: pi,
219
+ version: piVersion,
220
+ directory: agentDir,
221
+ },
222
+ claustrum: { available, executable: ck },
223
+ };
224
+ }
@@ -0,0 +1,70 @@
1
+ import { setTimeout as delay } from 'node:timers/promises';
2
+ import { writeEnrollmentTokenFile } from '@cortexkit/claustrum-client';
3
+ import { printLine } from '../auth-menu/terminal.js';
4
+ import { ClaustrumEnrollmentManager, connectClaustrumEnrollmentClient, hostEnrollmentPaths, } from '../claustrum/enrollment.js';
5
+ import { ProcessFenceViolationError, ProcessInspectionError, } from './process-fence.js';
6
+ /** Enroll an independently revocable host; plugin callbacks choose its credential store and account permissions. */
7
+ export async function connectSetupHost(plugin, host, io, terminal, fence) {
8
+ const { name, paths: input } = plugin.vault.hosts[host];
9
+ const paths = hostEnrollmentPaths(input);
10
+ await fence();
11
+ const client = await (io.connect ?? connectClaustrumEnrollmentClient)({
12
+ connectionFile: plugin.vault.connectionFile,
13
+ handshakeTimeoutMs: 2000,
14
+ }).catch(() => {
15
+ throw new Error('Claustrum connection failed; start ck and rerun setup.');
16
+ });
17
+ try {
18
+ const manager = new ClaustrumEnrollmentManager({
19
+ proposedName: name,
20
+ paths,
21
+ client: {
22
+ enrollPropose: async (input) => {
23
+ await fence();
24
+ return client.enrollPropose(input);
25
+ },
26
+ enrollPoll: async (input) => {
27
+ await fence();
28
+ return client.enrollPoll(input);
29
+ },
30
+ },
31
+ writeTokenFile: async (path, file) => {
32
+ await fence();
33
+ await writeEnrollmentTokenFile(path, file);
34
+ },
35
+ });
36
+ let printedRequest;
37
+ for (let tick = 0; tick < 300; tick++) {
38
+ await fence();
39
+ const status = await manager.reconcile();
40
+ if (status.state === 'approved') {
41
+ printLine(terminal, `Connected ${host} to Claustrum.`);
42
+ return;
43
+ }
44
+ if (status.state !== 'pending' && status.state !== 'busy')
45
+ throw new Error('Claustrum enrollment refused; inspect its status with ck before rerunning setup.');
46
+ if (status.state === 'pending' &&
47
+ status.requestId &&
48
+ status.requestId !== printedRequest) {
49
+ if (!/^[a-zA-Z0-9_-]+$/.test(status.requestId))
50
+ throw new Error('Invalid enrollment request id.');
51
+ printedRequest = status.requestId;
52
+ printLine(terminal, 'Waiting for approval. In another terminal, run:');
53
+ printLine(terminal, ` ck auth enroll approve --request-id ${status.requestId} --name ${name}`);
54
+ printLine(terminal, `Enrollment files: ${paths.statePath}, ${paths.tokenPath}`);
55
+ }
56
+ await (io.wait ?? delay)(1000);
57
+ }
58
+ throw new Error('Claustrum approval is still pending; approve with ck and rerun setup.');
59
+ }
60
+ catch (error) {
61
+ if (error instanceof ProcessFenceViolationError ||
62
+ error instanceof ProcessInspectionError)
63
+ throw error;
64
+ // Enrollment exceptions can carry request secrets or bearer tokens; never display them.
65
+ throw new Error('Claustrum enrollment did not complete. Inspect and approve with ck, then rerun setup.');
66
+ }
67
+ finally {
68
+ client.close();
69
+ }
70
+ }
@@ -0,0 +1,5 @@
1
+ export { AMBIGUOUS_OPENCODE_MESSAGE, runSetup } from './command.js';
2
+ export { detectHosts, detectOpenCodeGeneration, findExecutableOnPath, openCodeDesktopMarkers, } from './detect.js';
3
+ export { assertHostsStopped, createProcessFence, listSetupProcesses, ProcessFenceViolationError, ProcessInspectionError, type ProcessInspectionStep, } from './process-fence.js';
4
+ export { type PlannedWrite, planOpenCodeRegistration, registerOpenCode, registerPi, updatePluginConfig, } from './register.js';
5
+ export type { CommandResult, CommandRunner, HostDetection, OpenCodeGeneration, ProcessFence, SetupCallbackContext, SetupDetection, SetupEnvironment, SetupFileSystem, SetupHost, SetupIO, SetupPlugin, SetupResult, } from './types.js';
@@ -0,0 +1,4 @@
1
+ export { AMBIGUOUS_OPENCODE_MESSAGE, runSetup } from './command.js';
2
+ export { detectHosts, detectOpenCodeGeneration, findExecutableOnPath, openCodeDesktopMarkers, } from './detect.js';
3
+ export { assertHostsStopped, createProcessFence, listSetupProcesses, ProcessFenceViolationError, ProcessInspectionError, } from './process-fence.js';
4
+ export { planOpenCodeRegistration, registerOpenCode, registerPi, updatePluginConfig, } from './register.js';
@@ -0,0 +1,33 @@
1
+ import { homedir } from 'node:os';
2
+ import { posix, win32 } from 'node:path';
3
+ import { fileURLToPath } from 'node:url';
4
+ export function setupPaths(io = {}) {
5
+ const env = io.env ?? process.env;
6
+ const platform = io.platform ?? process.platform;
7
+ const path = platform === 'win32' ? win32 : posix;
8
+ const home = io.home ?? (platform === 'win32' ? env.USERPROFILE : env.HOME) ?? homedir();
9
+ const cwd = io.cwd ?? process.cwd();
10
+ const absolute = (value) => path.resolve(cwd, value);
11
+ const config = env.OPENCODE_CONFIG_DIR?.trim();
12
+ const xdg = env.XDG_CONFIG_HOME?.trim();
13
+ let agent = env.PI_CODING_AGENT_DIR?.trim() || path.join(home, '.pi', 'agent');
14
+ if (agent === '~')
15
+ agent = home;
16
+ else if (/^~[/\\]/.test(agent))
17
+ agent = path.join(home, agent.slice(2));
18
+ if (agent.startsWith('file://'))
19
+ agent = fileURLToPath(agent);
20
+ return {
21
+ env,
22
+ platform,
23
+ path,
24
+ home,
25
+ cwd,
26
+ opencode: config
27
+ ? absolute(config)
28
+ : xdg
29
+ ? path.join(absolute(xdg), 'opencode')
30
+ : path.join(home, '.config', 'opencode'),
31
+ pi: absolute(agent),
32
+ };
33
+ }
@@ -0,0 +1,43 @@
1
+ import type { CommandRunner, ProcessFence, SetupEnvironment } from './types.js';
2
+ export interface ProcessInspectionStep {
3
+ step: 'tasklist' | 'CIM' | 'ps';
4
+ exitCode: number | null;
5
+ signal: NodeJS.Signals | null;
6
+ timedOut: boolean;
7
+ durationMs: number;
8
+ }
9
+ export declare class ProcessInspectionError extends Error implements ProcessInspectionStep {
10
+ readonly code = "process-inspection-failed";
11
+ readonly step: ProcessInspectionStep['step'];
12
+ readonly exitCode: number | null;
13
+ readonly signal: NodeJS.Signals | null;
14
+ readonly timedOut: boolean;
15
+ readonly durationMs: number;
16
+ constructor(details: ProcessInspectionStep);
17
+ get refusalText(): string;
18
+ }
19
+ export declare class ProcessFenceViolationError extends Error {
20
+ readonly activeHosts: Array<{
21
+ pid: number;
22
+ command: string;
23
+ }>;
24
+ constructor(activeHosts: Array<{
25
+ pid: number;
26
+ command: string;
27
+ }>);
28
+ }
29
+ /** List processes before filtering hosts; Windows PID 0 is a valid idle-process row. */
30
+ export declare function listSetupProcesses(runner?: CommandRunner, options?: {
31
+ platform?: string;
32
+ env?: SetupEnvironment;
33
+ onStep?: (details: ProcessInspectionStep) => void;
34
+ /** False skips the Windows PowerShell query for Node and Bun command lines. */
35
+ inspectRuntimes?: boolean;
36
+ }): Promise<Array<{
37
+ pid: number;
38
+ command: string;
39
+ }>>;
40
+ export declare function createProcessFence(runner?: CommandRunner, options?: {
41
+ platform?: string;
42
+ }): ProcessFence;
43
+ export declare function assertHostsStopped(fence: ProcessFence, env?: SetupEnvironment): Promise<void>;
@@ -0,0 +1,270 @@
1
+ import { defaultCommandRunner } from './command-runner.js';
2
+ // A cold PowerShell/WMI query took 13.8 s on Windows Server 2022; warm queries
3
+ // took less than 0.5 s. This is the product's one-shot latency budget, not a test
4
+ // deadline: 45 s is about three times the worst measured cold start.
5
+ const WINDOWS_CIM_TIMEOUT_MS = 45_000;
6
+ const HOSTS = new Set(['opencode', 'litecode', 'opencode2', 'pi']);
7
+ const RUNTIMES = new Set(['node', 'bun']);
8
+ const PI_SCRIPT_PATTERN = /(?:^|[/\\])pi-coding-agent[/\\]dist[/\\](?:(?:bundle|bun)[/\\])?cli\.m?js$/i;
9
+ /** Splits a command line into arguments, keeping double-quoted ones whole. */
10
+ function commandArguments(command) {
11
+ return [...command.matchAll(/"([^"]*)"|(\S+)/g)].map((match) => match[1] ?? match[2] ?? '');
12
+ }
13
+ function executableName(argument) {
14
+ return (argument.split(/[/\\]/).pop() ?? '')
15
+ .toLowerCase()
16
+ .replace(/\.(?:exe|cmd|bat|m?js)$/, '');
17
+ }
18
+ // Node and Bun options whose value is the next argument, so that value is not
19
+ // mistaken for the script (`node --require ./preload.cjs …/opencode`).
20
+ const VALUE_OPTIONS = new Set([
21
+ '-r',
22
+ '--require',
23
+ '--import',
24
+ '--loader',
25
+ '--experimental-loader',
26
+ '-C',
27
+ '--conditions',
28
+ '--env-file',
29
+ '--title',
30
+ '--input-type',
31
+ '--preload',
32
+ '--cwd',
33
+ '-c',
34
+ '--config',
35
+ '--tsconfig-override',
36
+ '-d',
37
+ '--define',
38
+ '-l',
39
+ '--main-fields',
40
+ ]);
41
+ // Options that run inline code instead of a script file.
42
+ const INLINE_OPTIONS = new Set(['-e', '--eval', '-p', '--print']);
43
+ /** The script a Node or Bun runtime was started with, if any. */
44
+ function runtimeScript(runtime, args) {
45
+ for (let index = 0; index < args.length; index++) {
46
+ const argument = args[index] ?? '';
47
+ if (argument === '--')
48
+ return args[index + 1];
49
+ if (INLINE_OPTIONS.has(argument))
50
+ return undefined;
51
+ if (argument.startsWith('-')) {
52
+ if (!argument.includes('=') && VALUE_OPTIONS.has(argument))
53
+ index++;
54
+ continue;
55
+ }
56
+ // `bun run <script>` names the script after the subcommand.
57
+ if (runtime === 'bun' && argument === 'run')
58
+ continue;
59
+ return argument;
60
+ }
61
+ return undefined;
62
+ }
63
+ /**
64
+ * Names the host a process runs, judged by what it executes: the program
65
+ * itself, or the script a Node or Bun runtime was started with. Any other
66
+ * argument is ignored, so a shell whose command line merely mentions an
67
+ * `opencode` folder (`bash -c "cd …/opencode && …"`) is not a running host.
68
+ * `ps` prints arguments unquoted, so on macOS and Linux a program or script
69
+ * path containing spaces is not recognized; npm and Bun install OpenCode and Pi
70
+ * under paths without spaces.
71
+ */
72
+ function hostName(command) {
73
+ const [program, ...rest] = commandArguments(command);
74
+ if (program === undefined)
75
+ return null;
76
+ const name = executableName(program);
77
+ if (HOSTS.has(name))
78
+ return name;
79
+ if (!RUNTIMES.has(name))
80
+ return null;
81
+ const script = runtimeScript(name, rest);
82
+ if (script === undefined)
83
+ return null;
84
+ const scriptName = executableName(script);
85
+ if (HOSTS.has(scriptName))
86
+ return scriptName;
87
+ return PI_SCRIPT_PATTERN.test(script) ? 'pi' : null;
88
+ }
89
+ export class ProcessInspectionError extends Error {
90
+ code = 'process-inspection-failed';
91
+ step;
92
+ exitCode;
93
+ signal;
94
+ timedOut;
95
+ durationMs;
96
+ constructor(details) {
97
+ super('Process inspection failed; setup cannot prove hosts are stopped.');
98
+ this.name = 'ProcessInspectionError';
99
+ this.step = details.step;
100
+ this.exitCode = details.exitCode;
101
+ this.signal = details.signal;
102
+ this.timedOut = details.timedOut;
103
+ this.durationMs = details.durationMs;
104
+ }
105
+ get refusalText() {
106
+ const outcome = this.timedOut
107
+ ? 'timed out'
108
+ : this.signal
109
+ ? `signal ${this.signal}`
110
+ : this.exitCode === null
111
+ ? 'could not start or complete'
112
+ : this.exitCode === 0
113
+ ? 'invalid output (exit code 0)'
114
+ : `exit code ${this.exitCode}`;
115
+ return `${this.message} ${this.step}: ${outcome} after ${Math.round(this.durationMs)} ms.`;
116
+ }
117
+ }
118
+ export class ProcessFenceViolationError extends Error {
119
+ activeHosts;
120
+ constructor(activeHosts) {
121
+ // Process arguments may contain credentials; report only the recognized host name.
122
+ const safeHosts = activeHosts.map((host) => ({
123
+ pid: host.pid,
124
+ command: hostName(host.command) ?? 'host',
125
+ }));
126
+ super(`OpenCode or Pi processes are currently running:\n${safeHosts.map((host) => ` - PID ${host.pid}: ${host.command}`).join('\n')}\n\nPlease quit all OpenCode, LiteCode, and Pi processes before running setup.`);
127
+ this.activeHosts = safeHosts;
128
+ this.name = 'ProcessFenceViolationError';
129
+ }
130
+ }
131
+ /** List processes before filtering hosts; Windows PID 0 is a valid idle-process row. */
132
+ export async function listSetupProcesses(runner = defaultCommandRunner, options = {}) {
133
+ const windows = (options.platform ?? process.platform) === 'win32';
134
+ let inspection = {
135
+ step: windows ? 'tasklist' : 'ps',
136
+ exitCode: null,
137
+ signal: null,
138
+ timedOut: false,
139
+ durationMs: 0,
140
+ };
141
+ const inspect = async (step, file, args, timeoutMs) => {
142
+ const started = performance.now();
143
+ inspection = {
144
+ step,
145
+ exitCode: null,
146
+ signal: null,
147
+ timedOut: false,
148
+ durationMs: 0,
149
+ };
150
+ try {
151
+ const result = await runner.run(file, args, {
152
+ env: options.env,
153
+ timeoutMs,
154
+ });
155
+ inspection = {
156
+ step,
157
+ exitCode: result.exitCode,
158
+ signal: result.signal ?? null,
159
+ timedOut: result.timedOut ?? false,
160
+ durationMs: result.durationMs ?? performance.now() - started,
161
+ };
162
+ return result;
163
+ }
164
+ finally {
165
+ if (inspection.exitCode === null)
166
+ inspection.durationMs = performance.now() - started;
167
+ options.onStep?.({ ...inspection });
168
+ }
169
+ };
170
+ try {
171
+ const result = await inspect(windows ? 'tasklist' : 'ps', windows ? 'tasklist.exe' : 'ps', windows ? ['/fo', 'csv', '/nh'] : ['-eo', 'pid,command']);
172
+ if (result.exitCode !== 0)
173
+ throw new ProcessInspectionError(inspection);
174
+ const processes = [];
175
+ for (const line of result.stdout.split(/\r?\n/)) {
176
+ const trimmed = line.trim();
177
+ if (!trimmed)
178
+ continue;
179
+ let pid;
180
+ let command;
181
+ if (windows) {
182
+ const match = /^"([^"]+)","(\d+)"(?:,|$)/.exec(trimmed);
183
+ if (!match)
184
+ throw new ProcessInspectionError(inspection);
185
+ command = match[1] ?? '';
186
+ pid = Number(match[2]);
187
+ }
188
+ else {
189
+ const match = /^(\d+)\s+(.+)$/.exec(trimmed);
190
+ if (!match) {
191
+ if (/^PID\s+COMMAND$/i.test(trimmed))
192
+ continue;
193
+ throw new ProcessInspectionError(inspection);
194
+ }
195
+ pid = Number(match[1]);
196
+ command = match[2] ?? '';
197
+ }
198
+ if (!Number.isSafeInteger(pid) || pid < 0)
199
+ throw new ProcessInspectionError(inspection);
200
+ processes.push({ pid, command });
201
+ }
202
+ if (!processes.length)
203
+ throw new ProcessInspectionError(inspection);
204
+ // tasklist identifies native hosts, but npm Pi/OpenCode scripts appear as Node or Bun.
205
+ const runtimes = processes.filter((entry) => entry.pid !== process.pid && /^(?:node|bun)\.exe$/i.test(entry.command));
206
+ if (windows && runtimes.length && options.inspectRuntimes !== false) {
207
+ const details = await inspect('CIM', 'powershell.exe', [
208
+ '-NoProfile',
209
+ '-NonInteractive',
210
+ '-Command',
211
+ "$ErrorActionPreference = 'Stop'; Get-CimInstance Win32_Process -Filter \"Name = 'node.exe' OR Name = 'bun.exe'\" | Select-Object ProcessId,CommandLine | ConvertTo-Json -Compress",
212
+ ], WINDOWS_CIM_TIMEOUT_MS);
213
+ if (details.exitCode !== 0)
214
+ throw new ProcessInspectionError(inspection);
215
+ const value = JSON.parse(details.stdout || 'null');
216
+ const rows = value === null ? [] : Array.isArray(value) ? value : [value];
217
+ const commands = new Map();
218
+ for (const row of rows) {
219
+ if (!row ||
220
+ typeof row !== 'object' ||
221
+ !('ProcessId' in row) ||
222
+ !('CommandLine' in row) ||
223
+ !Number.isSafeInteger(row.ProcessId))
224
+ throw new ProcessInspectionError(inspection);
225
+ if (typeof row.CommandLine === 'string')
226
+ commands.set(Number(row.ProcessId), row.CommandLine);
227
+ else if (runtimes.some((entry) => entry.pid === row.ProcessId))
228
+ throw new ProcessInspectionError(inspection);
229
+ }
230
+ for (const entry of runtimes) {
231
+ // A process absent from the later CIM snapshot already exited.
232
+ entry.command = commands.get(entry.pid) ?? '';
233
+ }
234
+ }
235
+ return processes;
236
+ }
237
+ catch (error) {
238
+ if (error instanceof ProcessInspectionError)
239
+ throw error;
240
+ throw new ProcessInspectionError(inspection);
241
+ }
242
+ }
243
+ export function createProcessFence(runner = defaultCommandRunner, options = {}) {
244
+ const isHost = (entry) => entry.pid !== process.pid && hostName(entry.command) !== null;
245
+ return {
246
+ async listRunningHosts(env) {
247
+ return (await listSetupProcesses(runner, { ...options, env })).filter(isHost);
248
+ },
249
+ async previewRunningHosts(env) {
250
+ const processes = await listSetupProcesses(runner, {
251
+ ...options,
252
+ env,
253
+ inspectRuntimes: false,
254
+ });
255
+ const windows = (options.platform ?? process.platform) === 'win32';
256
+ return {
257
+ hosts: processes.filter(isHost),
258
+ uncheckedRuntimes: windows
259
+ ? processes.filter((entry) => entry.pid !== process.pid &&
260
+ /^(?:node|bun)\.exe$/i.test(entry.command)).length
261
+ : 0,
262
+ };
263
+ },
264
+ };
265
+ }
266
+ export async function assertHostsStopped(fence, env) {
267
+ const active = await fence.listRunningHosts(env);
268
+ if (active.length)
269
+ throw new ProcessFenceViolationError(active);
270
+ }
@@ -0,0 +1,26 @@
1
+ import { select } from '../auth-menu/select.js';
2
+ /** Reuse the terminal selector for a toggle list with an explicit final choice. */
3
+ export async function selectSetupHosts(terminal, found) {
4
+ const selected = new Set(found);
5
+ for (;;) {
6
+ const choice = await select(terminal, [
7
+ ...['opencode', 'pi'].map((host) => ({
8
+ value: host,
9
+ label: `[${selected.has(host) ? 'x' : ' '}] ${host === 'opencode' ? 'OpenCode' : 'Pi'}`,
10
+ hint: found.includes(host) ? 'found' : 'not found',
11
+ })),
12
+ { value: 'done', label: 'Continue with selected hosts' },
13
+ ], {
14
+ message: 'Select hosts to set up',
15
+ subtitle: 'Enter toggles a host; choose Continue when ready.',
16
+ });
17
+ if (choice === null)
18
+ return null;
19
+ if (choice === 'done')
20
+ return [...selected];
21
+ if (selected.has(choice))
22
+ selected.delete(choice);
23
+ else
24
+ selected.add(choice);
25
+ }
26
+ }