@quickchatai/quickreview 1.1.0 → 1.3.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 (471) hide show
  1. package/README.md +137 -57
  2. package/bin/qcr.js +1 -1
  3. package/config.example.toml +60 -14
  4. package/deploy/ansible/README.md +20 -12
  5. package/deploy/ansible/inventory.example.ini +1 -1
  6. package/deploy/collect-secrets.sh +1 -1
  7. package/deploy/qcr-update.sh +1 -1
  8. package/dist/extensions/cli/home.js +14 -0
  9. package/dist/extensions/cli/home.js.map +1 -0
  10. package/dist/extensions/cli/login-route.js +5 -0
  11. package/dist/extensions/cli/login-route.js.map +1 -0
  12. package/dist/extensions/cli/selfimprove.js +18 -0
  13. package/dist/extensions/cli/selfimprove.js.map +1 -0
  14. package/dist/extensions/home.js +350 -0
  15. package/dist/extensions/home.js.map +1 -0
  16. package/dist/extensions/login-route.js +180 -0
  17. package/dist/extensions/login-route.js.map +1 -0
  18. package/dist/extensions/onboarding.js +35 -11
  19. package/dist/extensions/onboarding.js.map +1 -1
  20. package/dist/extensions/selfimprove.js +49 -0
  21. package/dist/extensions/selfimprove.js.map +1 -0
  22. package/dist/extensions/setup-scan.js +23 -592
  23. package/dist/extensions/setup-scan.js.map +1 -1
  24. package/dist/extensions/setup.js +2 -47
  25. package/dist/extensions/setup.js.map +1 -1
  26. package/dist/src/archive/restore.js +18 -15
  27. package/dist/src/archive/restore.js.map +1 -1
  28. package/dist/src/botworker.js +13 -2
  29. package/dist/src/botworker.js.map +1 -1
  30. package/dist/src/channelfs.js +3 -26
  31. package/dist/src/channelfs.js.map +1 -1
  32. package/dist/src/ciretry.js +2 -1
  33. package/dist/src/ciretry.js.map +1 -1
  34. package/dist/src/cli.js +54 -61
  35. package/dist/src/cli.js.map +1 -1
  36. package/dist/src/cliops.js +3 -2
  37. package/dist/src/cliops.js.map +1 -1
  38. package/dist/src/commands.js +25 -2
  39. package/dist/src/commands.js.map +1 -1
  40. package/dist/src/config.js +32 -2
  41. package/dist/src/config.js.map +1 -1
  42. package/dist/src/daemon.js +50 -8
  43. package/dist/src/daemon.js.map +1 -1
  44. package/dist/src/debuground.js +1 -0
  45. package/dist/src/debuground.js.map +1 -1
  46. package/dist/src/debugroundpi.js +6 -1
  47. package/dist/src/debugroundpi.js.map +1 -1
  48. package/dist/src/dispatch.js +5 -4
  49. package/dist/src/dispatch.js.map +1 -1
  50. package/dist/src/engine/caserunner-sdk.js +15 -251
  51. package/dist/src/engine/caserunner-sdk.js.map +1 -1
  52. package/dist/src/engine/debugpi.js +17 -5
  53. package/dist/src/engine/debugpi.js.map +1 -1
  54. package/dist/src/execboundary.js +10 -3
  55. package/dist/src/execboundary.js.map +1 -1
  56. package/dist/src/github.js +51 -16
  57. package/dist/src/github.js.map +1 -1
  58. package/dist/src/githubtoken.js +346 -0
  59. package/dist/src/githubtoken.js.map +1 -0
  60. package/dist/src/home/adapters.js +349 -0
  61. package/dist/src/home/adapters.js.map +1 -0
  62. package/dist/src/home/advanced.js +318 -0
  63. package/dist/src/home/advanced.js.map +1 -0
  64. package/dist/src/home/advancedtools.js +57 -0
  65. package/dist/src/home/advancedtools.js.map +1 -0
  66. package/dist/src/home/autoreview.js +325 -0
  67. package/dist/src/home/autoreview.js.map +1 -0
  68. package/dist/src/home/daemonstatus.js +32 -0
  69. package/dist/src/home/daemonstatus.js.map +1 -0
  70. package/dist/src/home/devicelogin.js +61 -0
  71. package/dist/src/home/devicelogin.js.map +1 -0
  72. package/dist/src/home/launch.js +202 -0
  73. package/dist/src/home/launch.js.map +1 -0
  74. package/dist/src/home/loginowner.js +205 -0
  75. package/dist/src/home/loginowner.js.map +1 -0
  76. package/dist/src/home/memory.js +122 -0
  77. package/dist/src/home/memory.js.map +1 -0
  78. package/dist/src/home/model.js +811 -0
  79. package/dist/src/home/model.js.map +1 -0
  80. package/dist/src/home/panel.js +520 -0
  81. package/dist/src/home/panel.js.map +1 -0
  82. package/dist/src/home/ports.js +19 -0
  83. package/dist/src/home/ports.js.map +1 -0
  84. package/dist/src/home/review.js +163 -0
  85. package/dist/src/home/review.js.map +1 -0
  86. package/dist/src/home/reviews.js +478 -0
  87. package/dist/src/home/reviews.js.map +1 -0
  88. package/dist/src/home/setup.js +507 -0
  89. package/dist/src/home/setup.js.map +1 -0
  90. package/dist/src/home/setupadapters.js +214 -0
  91. package/dist/src/home/setupadapters.js.map +1 -0
  92. package/dist/src/home/setupcard.js +199 -0
  93. package/dist/src/home/setupcard.js.map +1 -0
  94. package/dist/src/home/setuptools.js +45 -0
  95. package/dist/src/home/setuptools.js.map +1 -0
  96. package/dist/src/home/spend.js +160 -0
  97. package/dist/src/home/spend.js.map +1 -0
  98. package/dist/src/home/switches.js +209 -0
  99. package/dist/src/home/switches.js.map +1 -0
  100. package/dist/src/home/switchon.js +439 -0
  101. package/dist/src/home/switchon.js.map +1 -0
  102. package/dist/src/home/toolnames.js +41 -0
  103. package/dist/src/home/toolnames.js.map +1 -0
  104. package/dist/src/home/tune.js +341 -0
  105. package/dist/src/home/tune.js.map +1 -0
  106. package/dist/src/home/words.js +7 -0
  107. package/dist/src/home/words.js.map +1 -0
  108. package/dist/src/homes.js +14 -0
  109. package/dist/src/homes.js.map +1 -1
  110. package/dist/src/install.js +1 -1
  111. package/dist/src/install.js.map +1 -1
  112. package/dist/src/ipc/workerspec.js +8 -0
  113. package/dist/src/ipc/workerspec.js.map +1 -1
  114. package/dist/src/live/publish.js +1 -1
  115. package/dist/src/live/publish.js.map +1 -1
  116. package/dist/src/livecli.js +1 -1
  117. package/dist/src/livecli.js.map +1 -1
  118. package/dist/src/loginhint.js +8 -3
  119. package/dist/src/loginhint.js.map +1 -1
  120. package/dist/src/loginrefresh/handover.js +121 -0
  121. package/dist/src/loginrefresh/handover.js.map +1 -0
  122. package/dist/src/loginrefresh/lock.js +54 -3
  123. package/dist/src/loginrefresh/lock.js.map +1 -1
  124. package/dist/src/loginrefresh/pirefresh.js +3 -0
  125. package/dist/src/loginrefresh/pirefresh.js.map +1 -1
  126. package/dist/src/loginrefresh/refresher.js +33 -5
  127. package/dist/src/loginrefresh/refresher.js.map +1 -1
  128. package/dist/src/loginrefresh/supervisor.js +18 -1
  129. package/dist/src/loginrefresh/supervisor.js.map +1 -1
  130. package/dist/src/npmverbs.js +46 -14
  131. package/dist/src/npmverbs.js.map +1 -1
  132. package/dist/src/onboard/choices.js +35 -4
  133. package/dist/src/onboard/choices.js.map +1 -1
  134. package/dist/src/onboard/engine.js +32 -306
  135. package/dist/src/onboard/engine.js.map +1 -1
  136. package/dist/src/onboard/pipin.js +22 -0
  137. package/dist/src/onboard/pipin.js.map +1 -0
  138. package/dist/src/onboard/stepforward.js +41 -0
  139. package/dist/src/onboard/stepforward.js.map +1 -0
  140. package/dist/src/onboard/steps/appslug.js +4 -1
  141. package/dist/src/onboard/steps/appslug.js.map +1 -1
  142. package/dist/src/onboard/steps/bringup.js +3 -2
  143. package/dist/src/onboard/steps/bringup.js.map +1 -1
  144. package/dist/src/onboard/steps/compose.js +29 -0
  145. package/dist/src/onboard/steps/compose.js.map +1 -1
  146. package/dist/src/onboard/steps/configfill.js +120 -39
  147. package/dist/src/onboard/steps/configfill.js.map +1 -1
  148. package/dist/src/onboard/steps/githubaccount.js +595 -0
  149. package/dist/src/onboard/steps/githubaccount.js.map +1 -0
  150. package/dist/src/onboard/steps/githubapp.js +65 -7
  151. package/dist/src/onboard/steps/githubapp.js.map +1 -1
  152. package/dist/src/onboard/steps/golive.js +2 -0
  153. package/dist/src/onboard/steps/golive.js.map +1 -1
  154. package/dist/src/onboard/steps/index.js +11 -0
  155. package/dist/src/onboard/steps/index.js.map +1 -1
  156. package/dist/src/onboard/steps/ingress.js +80 -25
  157. package/dist/src/onboard/steps/ingress.js.map +1 -1
  158. package/dist/src/onboard/steps/llmauth.js +103 -30
  159. package/dist/src/onboard/steps/llmauth.js.map +1 -1
  160. package/dist/src/onboard/steps/loginshare.js +213 -0
  161. package/dist/src/onboard/steps/loginshare.js.map +1 -0
  162. package/dist/src/onboard/steps/memory.js +67 -3
  163. package/dist/src/onboard/steps/memory.js.map +1 -1
  164. package/dist/src/onboard/steps/proof.js +366 -56
  165. package/dist/src/onboard/steps/proof.js.map +1 -1
  166. package/dist/src/onboard/steps/repoconfig.js +72 -0
  167. package/dist/src/onboard/steps/repoconfig.js.map +1 -0
  168. package/dist/src/onboard/steps/topology.js +6 -6
  169. package/dist/src/onboard/steps/topology.js.map +1 -1
  170. package/dist/src/onboard/steps/transport.js +9 -1
  171. package/dist/src/onboard/steps/transport.js.map +1 -1
  172. package/dist/src/onboard/steps/tuiroute.js +102 -0
  173. package/dist/src/onboard/steps/tuiroute.js.map +1 -0
  174. package/dist/src/onboard/steps/verifyup.js +17 -1
  175. package/dist/src/onboard/steps/verifyup.js.map +1 -1
  176. package/dist/src/onboard/toolnames.js +30 -0
  177. package/dist/src/onboard/toolnames.js.map +1 -0
  178. package/dist/src/operatorwrite.js +23 -0
  179. package/dist/src/operatorwrite.js.map +1 -0
  180. package/dist/src/outcomes.js +4 -1
  181. package/dist/src/outcomes.js.map +1 -1
  182. package/dist/src/piagentdir.js +13 -0
  183. package/dist/src/piagentdir.js.map +1 -0
  184. package/dist/src/pilogin.js +31 -16
  185. package/dist/src/pilogin.js.map +1 -1
  186. package/dist/src/posting-journal.js +2 -1
  187. package/dist/src/posting-journal.js.map +1 -1
  188. package/dist/src/posting-outbox.js +6 -2
  189. package/dist/src/posting-outbox.js.map +1 -1
  190. package/dist/src/posting-receipt.js +14 -1
  191. package/dist/src/posting-receipt.js.map +1 -1
  192. package/dist/src/qcrbin.js +16 -11
  193. package/dist/src/qcrbin.js.map +1 -1
  194. package/dist/src/recheck.js +2 -1
  195. package/dist/src/recheck.js.map +1 -1
  196. package/dist/src/reconcile.js +22 -2
  197. package/dist/src/reconcile.js.map +1 -1
  198. package/dist/src/reviewargs.js +122 -0
  199. package/dist/src/reviewargs.js.map +1 -0
  200. package/dist/src/reviewcli.js +7 -161
  201. package/dist/src/reviewcli.js.map +1 -1
  202. package/dist/src/reviewdetach.js +76 -11
  203. package/dist/src/reviewdetach.js.map +1 -1
  204. package/dist/src/reviewhistory.js +32 -6
  205. package/dist/src/reviewhistory.js.map +1 -1
  206. package/dist/src/reviewnow.js +45 -0
  207. package/dist/src/reviewnow.js.map +1 -0
  208. package/dist/src/scancli.js +39 -691
  209. package/dist/src/scancli.js.map +1 -1
  210. package/dist/src/selfimprove.js +66 -0
  211. package/dist/src/selfimprove.js.map +1 -0
  212. package/dist/src/setup/adapters.js +5 -223
  213. package/dist/src/setup/adapters.js.map +1 -1
  214. package/dist/src/setup/caserunner.js +15 -249
  215. package/dist/src/setup/caserunner.js.map +1 -1
  216. package/dist/src/setup/engine.js +32 -341
  217. package/dist/src/setup/engine.js.map +1 -1
  218. package/dist/src/setup/facts.js +3 -592
  219. package/dist/src/setup/facts.js.map +1 -1
  220. package/dist/src/setup/findings.js +3 -947
  221. package/dist/src/setup/findings.js.map +1 -1
  222. package/dist/src/setup/presentation.js +3 -8
  223. package/dist/src/setup/presentation.js.map +1 -1
  224. package/dist/src/setup/scan.js +3 -724
  225. package/dist/src/setup/scan.js.map +1 -1
  226. package/dist/src/setup/scanbuild.js +9 -92
  227. package/dist/src/setup/scanbuild.js.map +1 -1
  228. package/dist/src/setup/scanlease.js +3 -250
  229. package/dist/src/setup/scanlease.js.map +1 -1
  230. package/dist/src/setup/scanreport.js +3 -288
  231. package/dist/src/setup/scanreport.js.map +1 -1
  232. package/dist/src/setup/scanrun.js +3 -1732
  233. package/dist/src/setup/scanrun.js.map +1 -1
  234. package/dist/src/setup/scantree.js +3 -256
  235. package/dist/src/setup/scantree.js.map +1 -1
  236. package/dist/src/setup/stage2request.js +3 -258
  237. package/dist/src/setup/stage2request.js.map +1 -1
  238. package/dist/src/setup/unitcut.js +3 -436
  239. package/dist/src/setup/unitcut.js.map +1 -1
  240. package/dist/src/state.js +2 -0
  241. package/dist/src/state.js.map +1 -1
  242. package/dist/src/statemachine.js +4 -1
  243. package/dist/src/statemachine.js.map +1 -1
  244. package/dist/src/takeover.js +1 -0
  245. package/dist/src/takeover.js.map +1 -1
  246. package/dist/src/takeoverpi.js +15 -1
  247. package/dist/src/takeoverpi.js.map +1 -1
  248. package/dist/src/tui/app.js +49 -0
  249. package/dist/src/tui/app.js.map +1 -1
  250. package/dist/src/tui/board.js +88 -12
  251. package/dist/src/tui/board.js.map +1 -1
  252. package/dist/src/tui/cmdbar.js +4 -1
  253. package/dist/src/tui/cmdbar.js.map +1 -1
  254. package/dist/src/tui/companion.js +76 -11
  255. package/dist/src/tui/companion.js.map +1 -1
  256. package/dist/src/tui/connect.js +7 -1
  257. package/dist/src/tui/connect.js.map +1 -1
  258. package/dist/src/tui/deploytab.js +2 -2
  259. package/dist/src/tui/deploytab.js.map +1 -1
  260. package/dist/src/tui/filters.js +5 -2
  261. package/dist/src/tui/filters.js.map +1 -1
  262. package/dist/src/tui/ghread.js +61 -5
  263. package/dist/src/tui/ghread.js.map +1 -1
  264. package/dist/src/tui/index.js +109 -20
  265. package/dist/src/tui/index.js.map +1 -1
  266. package/dist/src/tui/memforward.js +39 -2
  267. package/dist/src/tui/memforward.js.map +1 -1
  268. package/dist/src/tui/memory.js +3 -16
  269. package/dist/src/tui/memory.js.map +1 -1
  270. package/dist/src/tui/memoryurl.js +22 -0
  271. package/dist/src/tui/memoryurl.js.map +1 -0
  272. package/dist/src/tui/model.js +25 -0
  273. package/dist/src/tui/model.js.map +1 -1
  274. package/dist/src/tui/prpause.js +7 -0
  275. package/dist/src/tui/prpause.js.map +1 -1
  276. package/dist/src/tui/remote.js +7 -1
  277. package/dist/src/tui/remote.js.map +1 -1
  278. package/dist/src/tui/route.js +143 -0
  279. package/dist/src/tui/route.js.map +1 -0
  280. package/dist/src/tui/setupstate.js +32 -0
  281. package/dist/src/tui/setupstate.js.map +1 -0
  282. package/dist/src/tui/sshtriage.js +102 -5
  283. package/dist/src/tui/sshtriage.js.map +1 -1
  284. package/dist/src/tui/theme.js +2 -1
  285. package/dist/src/tui/theme.js.map +1 -1
  286. package/dist/src/tui/unwedge.js +2 -12
  287. package/dist/src/tui/unwedge.js.map +1 -1
  288. package/dist/src/verdicts.js +17 -5
  289. package/dist/src/verdicts.js.map +1 -1
  290. package/dist/src/version.js +1 -1
  291. package/dist/src/version.js.map +1 -1
  292. package/dist/src/webhook.js +12 -1
  293. package/dist/src/webhook.js.map +1 -1
  294. package/dist/src/wire.js +34 -8
  295. package/dist/src/wire.js.map +1 -1
  296. package/dist/src/workerworld.js +11 -1
  297. package/dist/src/workerworld.js.map +1 -1
  298. package/docker/README.md +1 -1
  299. package/docker/companion/entrypoint.sh +20 -1
  300. package/docker/entrypoint.sh +57 -6
  301. package/docker-compose.yml +16 -1
  302. package/extensions/cli/home.ts +14 -0
  303. package/extensions/cli/login-route.ts +10 -0
  304. package/extensions/cli/selfimprove.ts +18 -0
  305. package/extensions/home.ts +484 -0
  306. package/extensions/login-route.ts +220 -0
  307. package/extensions/onboarding.ts +41 -11
  308. package/extensions/selfimprove.ts +65 -0
  309. package/extensions/setup-scan.ts +79 -766
  310. package/extensions/setup.ts +14 -70
  311. package/package.json +6 -4
  312. package/prompts/onboarding.md +58 -18
  313. package/schemas/review-result.v1.json +60 -0
  314. package/scripts/deploy.sh +8 -6
  315. package/scripts/mint-token.sh +25 -4
  316. package/scripts/qcr-host.sh +28 -5
  317. package/scripts/vm-ghcr-login.sh +7 -4
  318. package/src/archive/restore.ts +18 -21
  319. package/src/botworker.ts +13 -2
  320. package/src/channelfs.ts +3 -26
  321. package/src/ciretry.ts +2 -1
  322. package/src/cli.ts +59 -67
  323. package/src/cliops.ts +3 -2
  324. package/src/commands.ts +28 -2
  325. package/src/config.ts +62 -4
  326. package/src/daemon.ts +58 -7
  327. package/src/debuground.ts +3 -0
  328. package/src/debugroundpi.ts +12 -1
  329. package/src/dispatch.ts +5 -4
  330. package/src/engine/caserunner-sdk.ts +29 -314
  331. package/src/engine/debugpi.ts +17 -5
  332. package/src/execboundary.ts +16 -4
  333. package/src/github.ts +57 -15
  334. package/src/githubtoken.ts +435 -0
  335. package/src/home/adapters.ts +418 -0
  336. package/src/home/advanced.ts +421 -0
  337. package/src/home/advancedtools.ts +96 -0
  338. package/src/home/autoreview.ts +385 -0
  339. package/src/home/daemonstatus.ts +55 -0
  340. package/src/home/devicelogin.ts +107 -0
  341. package/src/home/launch.ts +257 -0
  342. package/src/home/loginowner.ts +248 -0
  343. package/src/home/memory.ts +176 -0
  344. package/src/home/model.ts +965 -0
  345. package/src/home/panel.ts +666 -0
  346. package/src/home/ports.ts +338 -0
  347. package/src/home/review.ts +206 -0
  348. package/src/home/reviews.ts +565 -0
  349. package/src/home/setup.ts +689 -0
  350. package/src/home/setupadapters.ts +217 -0
  351. package/src/home/setupcard.ts +288 -0
  352. package/src/home/setuptools.ts +57 -0
  353. package/src/home/spend.ts +194 -0
  354. package/src/home/switches.ts +293 -0
  355. package/src/home/switchon.ts +554 -0
  356. package/src/home/toolnames.ts +46 -0
  357. package/src/home/tune.ts +405 -0
  358. package/src/home/words.ts +8 -0
  359. package/src/homes.ts +17 -0
  360. package/src/install.ts +1 -1
  361. package/src/ipc/workerspec.ts +15 -0
  362. package/src/live/publish.ts +4 -1
  363. package/src/livecli.ts +6 -1
  364. package/src/loginhint.ts +8 -3
  365. package/src/loginrefresh/handover.ts +138 -0
  366. package/src/loginrefresh/lock.ts +72 -3
  367. package/src/loginrefresh/pirefresh.ts +3 -0
  368. package/src/loginrefresh/refresher.ts +34 -5
  369. package/src/loginrefresh/supervisor.ts +25 -2
  370. package/src/npmverbs.ts +55 -13
  371. package/src/onboard/choices.ts +40 -4
  372. package/src/onboard/engine.ts +70 -421
  373. package/src/onboard/pipin.ts +31 -0
  374. package/src/onboard/stepforward.ts +61 -0
  375. package/src/onboard/steps/appslug.ts +4 -1
  376. package/src/onboard/steps/bringup.ts +3 -2
  377. package/src/onboard/steps/compose.ts +31 -0
  378. package/src/onboard/steps/configfill.ts +144 -40
  379. package/src/onboard/steps/githubaccount.ts +716 -0
  380. package/src/onboard/steps/githubapp.ts +92 -8
  381. package/src/onboard/steps/golive.ts +2 -0
  382. package/src/onboard/steps/index.ts +11 -0
  383. package/src/onboard/steps/ingress.ts +98 -31
  384. package/src/onboard/steps/llmauth.ts +114 -29
  385. package/src/onboard/steps/loginshare.ts +258 -0
  386. package/src/onboard/steps/memory.ts +76 -3
  387. package/src/onboard/steps/proof.ts +473 -55
  388. package/src/onboard/steps/repoconfig.ts +85 -0
  389. package/src/onboard/steps/topology.ts +7 -6
  390. package/src/onboard/steps/transport.ts +15 -0
  391. package/src/onboard/steps/tuiroute.ts +119 -0
  392. package/src/onboard/steps/verifyup.ts +20 -1
  393. package/src/onboard/toolnames.ts +34 -0
  394. package/src/operatorwrite.ts +25 -0
  395. package/src/outcomes.ts +8 -1
  396. package/src/piagentdir.ts +12 -0
  397. package/src/pilogin.ts +32 -16
  398. package/src/posting-journal.ts +6 -1
  399. package/src/posting-outbox.ts +10 -2
  400. package/src/posting-receipt.ts +17 -0
  401. package/src/qcrbin.ts +16 -11
  402. package/src/recheck.ts +2 -1
  403. package/src/reconcile.ts +29 -3
  404. package/src/reviewargs.ts +119 -0
  405. package/src/reviewcli.ts +6 -167
  406. package/src/reviewdetach.ts +107 -13
  407. package/src/reviewhistory.ts +20 -6
  408. package/src/reviewnow.ts +76 -0
  409. package/src/scancli.ts +75 -826
  410. package/src/selfimprove.ts +90 -0
  411. package/src/setup/adapters.ts +13 -221
  412. package/src/setup/caserunner.ts +34 -273
  413. package/src/setup/engine.ts +62 -496
  414. package/src/setup/facts.ts +3 -627
  415. package/src/setup/findings.ts +3 -1264
  416. package/src/setup/presentation.ts +3 -18
  417. package/src/setup/scan.ts +3 -1033
  418. package/src/setup/scanbuild.ts +20 -114
  419. package/src/setup/scanlease.ts +3 -297
  420. package/src/setup/scanreport.ts +3 -373
  421. package/src/setup/scanrun.ts +3 -2268
  422. package/src/setup/scantree.ts +3 -259
  423. package/src/setup/stage2request.ts +3 -347
  424. package/src/setup/unitcut.ts +3 -523
  425. package/src/state.ts +43 -0
  426. package/src/statemachine.ts +4 -1
  427. package/src/takeover.ts +5 -0
  428. package/src/takeoverpi.ts +16 -2
  429. package/src/tui/app.ts +47 -0
  430. package/src/tui/board.ts +111 -14
  431. package/src/tui/cmdbar.ts +4 -1
  432. package/src/tui/companion.ts +80 -11
  433. package/src/tui/connect.ts +7 -1
  434. package/src/tui/deploytab.ts +2 -2
  435. package/src/tui/filters.ts +7 -3
  436. package/src/tui/ghread.ts +74 -7
  437. package/src/tui/index.ts +117 -23
  438. package/src/tui/memforward.ts +52 -3
  439. package/src/tui/memory.ts +3 -15
  440. package/src/tui/memoryurl.ts +22 -0
  441. package/src/tui/model.ts +36 -2
  442. package/src/tui/prpause.ts +11 -2
  443. package/src/tui/remote.ts +9 -1
  444. package/src/tui/route.ts +173 -0
  445. package/src/tui/setupstate.ts +56 -0
  446. package/src/tui/sshtriage.ts +127 -6
  447. package/src/tui/theme.ts +2 -1
  448. package/src/tui/unwedge.ts +2 -14
  449. package/src/verdicts.ts +23 -5
  450. package/src/version.ts +1 -1
  451. package/src/webhook.ts +10 -1
  452. package/src/wire.ts +42 -9
  453. package/src/workerworld.ts +16 -2
  454. package/dist/src/live/projection.js +0 -450
  455. package/dist/src/live/projection.js.map +0 -1
  456. package/dist/src/live/read.js +0 -60
  457. package/dist/src/live/read.js.map +0 -1
  458. package/dist/src/onboard/launch.js +0 -83
  459. package/dist/src/onboard/launch.js.map +0 -1
  460. package/dist/src/setup/ledger.js +0 -207
  461. package/dist/src/setup/ledger.js.map +0 -1
  462. package/dist/src/setup/stage2.js +0 -617
  463. package/dist/src/setup/stage2.js.map +0 -1
  464. package/dist/src/setup/textsniff.js +0 -89
  465. package/dist/src/setup/textsniff.js.map +0 -1
  466. package/src/live/projection.ts +0 -491
  467. package/src/live/read.ts +0 -86
  468. package/src/onboard/launch.ts +0 -115
  469. package/src/setup/ledger.ts +0 -324
  470. package/src/setup/stage2.ts +0 -926
  471. package/src/setup/textsniff.ts +0 -95
@@ -0,0 +1,217 @@
1
+ // The setup checklist's real ports (src/home/setup.ts), and the one function
2
+ // that turns a process's environment into them: the env shim
3
+ // (extensions/cli/home.ts) calls `homeSetupFromEnv(process.env, VERSION)`.
4
+ //
5
+ // first-run checks the plugin's pi-version and git steps, over a
6
+ // PluginHost of this process (its PATH, the running pi)
7
+ // repository pick `gh`: the person's recently pushed repositories, the
8
+ // chosen one's canonical name and default branch, and the
9
+ // account's login and name
10
+ // the write the app config the home's repo port reads
11
+ // (locateConfig: $QCR_CONFIG, else the install home's
12
+ // config.toml), patched the way the onboarding config
13
+ // fill patches it (src/onboard/steps/configfill.ts):
14
+ // comment-preserving, only the keys that change, never
15
+ // dry_run. A fresh config starts from the shipped
16
+ // template, whose dry_run = true it keeps (invariant 6).
17
+ // timezone the machine's IANA zone, as Intl resolves it
18
+ //
19
+ // The silent defaults ride on the repository write: the base branch is the
20
+ // chosen repository's (always: it belongs to that repository), and the
21
+ // timezone and the owner's name and login fill a value only while it is
22
+ // empty (or the config is new), so an owner's own choice is never overwritten.
23
+ import { readFileSync } from "node:fs";
24
+ import { homedir } from "node:os";
25
+ import { join } from "node:path";
26
+ import { assetRoot } from "@quickchatai/pi-quickreview/src/assetroot.js";
27
+ import { nodeRunner } from "@quickchatai/pi-quickreview/src/plugin/runner.js";
28
+ import type { PluginHost } from "@quickchatai/pi-quickreview/src/plugin/session.js";
29
+ import { declaredPiRange } from "@quickchatai/pi-quickreview/src/plugin/versiongate.js";
30
+ import { writeAtomic } from "@quickchatai/pi-quickreview/src/setupchecklist.js";
31
+ import { locateConfig, stateHome } from "../homes.js";
32
+ import { piAgentDir } from "../piagentdir.js";
33
+ import { execRunner, type Runner, type RunResult } from "./adapters.js";
34
+ import { known, unknown, type Known } from "./ports.js";
35
+ import type { HomeSetupPorts, RepoPickPort, RepoWrite } from "./setup.js";
36
+
37
+ type Env = Readonly<Record<string, string | undefined>>;
38
+
39
+ const firstLine = (s: string): string => s.trim().split("\n")[0]?.trim() || "no output";
40
+ const message = (err: unknown): string => (err instanceof Error ? err.message : String(err));
41
+
42
+ /** gh's words for "you are not signed in". */
43
+ const SIGNED_OUT = /gh auth login|not logged in|authentication required|HTTP 401|bad credentials/i;
44
+
45
+ function ghWhy(r: RunResult): string {
46
+ if (r.missing) return "gh is not installed";
47
+ if (SIGNED_OUT.test(r.stderr)) return "gh is signed out: run `gh auth login`";
48
+ return firstLine(r.stderr);
49
+ }
50
+
51
+ /** The machine's IANA timezone, or null when Intl cannot say. */
52
+ export function systemTimezone(): string | null {
53
+ try {
54
+ const tz = Intl.DateTimeFormat().resolvedOptions().timeZone;
55
+ return typeof tz === "string" && tz !== "" ? tz : null;
56
+ } catch {
57
+ return null;
58
+ }
59
+ }
60
+
61
+ /** A file's text; null only when it does not exist. Any other failure
62
+ * throws: a config that exists and cannot be read is never "no config", or
63
+ * the template would be written over it. */
64
+ function readIfThere(path: string): string | null {
65
+ try {
66
+ return readFileSync(path, "utf8");
67
+ } catch (err) {
68
+ if ((err as NodeJS.ErrnoException | null)?.code === "ENOENT") return null;
69
+ throw err;
70
+ }
71
+ }
72
+
73
+ export function repoPickPort(o: {
74
+ runner: Runner;
75
+ configPath: () => string;
76
+ templatePath: () => string;
77
+ read?: (path: string) => string | null;
78
+ write?: (path: string, text: string) => void;
79
+ }): RepoPickPort {
80
+ const read = o.read ?? readIfThere;
81
+ const write = o.write ?? writeAtomic;
82
+ return {
83
+ recent: async () => {
84
+ const r = await o.runner.run("gh", [
85
+ "repo",
86
+ "list",
87
+ "--limit",
88
+ "8",
89
+ "--json",
90
+ "nameWithOwner",
91
+ ]);
92
+ if (r.code !== 0) return unknown(ghWhy(r));
93
+ try {
94
+ const rows = JSON.parse(r.stdout) as unknown;
95
+ if (!Array.isArray(rows)) return unknown("gh's answer is not a list");
96
+ return known(
97
+ rows.flatMap((x: { nameWithOwner?: unknown }) =>
98
+ typeof x?.nameWithOwner === "string" ? [x.nameWithOwner] : [],
99
+ ),
100
+ );
101
+ } catch (err) {
102
+ return unknown(`gh's answer is not JSON: ${message(err)}`);
103
+ }
104
+ },
105
+ describe: async (repo) => {
106
+ const r = await o.runner.run("gh", [
107
+ "repo",
108
+ "view",
109
+ repo,
110
+ "--json",
111
+ "nameWithOwner,defaultBranchRef",
112
+ ]);
113
+ if (r.code !== 0) return { ok: false, why: ghWhy(r) };
114
+ try {
115
+ const v = JSON.parse(r.stdout) as {
116
+ nameWithOwner?: unknown;
117
+ defaultBranchRef?: { name?: unknown } | null;
118
+ };
119
+ const branch = v.defaultBranchRef?.name;
120
+ return {
121
+ ok: true,
122
+ repo: typeof v.nameWithOwner === "string" ? v.nameWithOwner : repo,
123
+ defaultBranch: typeof branch === "string" && branch !== "" ? branch : null,
124
+ };
125
+ } catch (err) {
126
+ return { ok: false, why: `gh's answer is not JSON: ${message(err)}` };
127
+ }
128
+ },
129
+ profile: async (): Promise<Known<{ login: string; name: string | null }>> => {
130
+ const r = await o.runner.run("gh", ["api", "user"]);
131
+ if (r.code !== 0) return unknown(ghWhy(r));
132
+ try {
133
+ const v = JSON.parse(r.stdout) as { login?: unknown; name?: unknown };
134
+ if (typeof v.login !== "string") return unknown("gh's account has no login");
135
+ return known({
136
+ login: v.login,
137
+ name: typeof v.name === "string" && v.name.trim() !== "" ? v.name.trim() : null,
138
+ });
139
+ } catch (err) {
140
+ return unknown(`gh's answer is not JSON: ${message(err)}`);
141
+ }
142
+ },
143
+ write: async (choice): Promise<RepoWrite> => {
144
+ let path: string;
145
+ try {
146
+ path = o.configPath();
147
+ } catch (err) {
148
+ return { ok: false, why: message(err) };
149
+ }
150
+ let existing: string | null;
151
+ let template: string | null = "";
152
+ try {
153
+ existing = read(path);
154
+ } catch (err) {
155
+ return { ok: false, why: `can't read ${path} (${message(err)}); nothing was written` };
156
+ }
157
+ try {
158
+ if (existing === null) template = read(o.templatePath());
159
+ } catch {
160
+ template = null;
161
+ }
162
+ if (template === null)
163
+ return { ok: false, why: `there is no ${path} and the shipped template is not readable` };
164
+ // the config fill's writer, loaded only when a repository is written
165
+ const { renderRepoConfig } = await import("../onboard/steps/repoconfig.js");
166
+ const r = renderRepoConfig(existing, template, choice);
167
+ if (!r.ok) return r;
168
+ try {
169
+ if (r.text !== existing) write(path, r.text);
170
+ } catch (err) {
171
+ return { ok: false, why: `can't write ${path}: ${message(err)}` };
172
+ }
173
+ return { ok: true, path, wrote: r.wrote };
174
+ },
175
+ };
176
+ }
177
+
178
+ /** The PluginHost the first-run checks read: this process's PATH and the
179
+ * running pi (its version, which the env shim reads off pi). Only the
180
+ * plugin's pi-version and git steps run over it, so its auth answers
181
+ * nothing. */
182
+ export function firstRunHost(env: Env, piVersion: string): PluginHost {
183
+ return {
184
+ cwd: join(stateHome(env), "home"),
185
+ env,
186
+ home: (env["HOME"] ?? "").trim() || homedir(),
187
+ piVersion,
188
+ agentDir: piAgentDir(env),
189
+ auth: {
190
+ logins: () => ({}),
191
+ configured: () => false,
192
+ refresh: () => Promise.reject(new Error("the home's first-run checks hold no login")),
193
+ },
194
+ runner: nodeRunner(env),
195
+ shutdown: new AbortController().signal,
196
+ };
197
+ }
198
+
199
+ /** The setup's options from a process's environment and the running pi's
200
+ * version: the env shim's one call. */
201
+ export function homeSetupFromEnv(env: Env, piVersion: string): HomeSetupPorts {
202
+ let range: string | null = null;
203
+ try {
204
+ range = declaredPiRange();
205
+ } catch {
206
+ range = null;
207
+ }
208
+ return {
209
+ ...(range !== null ? { firstRun: { host: firstRunHost(env, piVersion), range } } : {}),
210
+ repos: repoPickPort({
211
+ runner: execRunner,
212
+ configPath: () => locateConfig({ env }).path,
213
+ templatePath: () => join(assetRoot(), "config.example.toml"),
214
+ }),
215
+ timezone: systemTimezone,
216
+ };
217
+ }
@@ -0,0 +1,288 @@
1
+ // The setup card: on a machine that is not set up, the home opens on this,
2
+ // centred at half the terminal's width and about half its height, instead of the panel. It draws the setup checklist
3
+ // (src/home/setup.ts) in pi's theme tokens; when the last step is done the
4
+ // extension swaps it for the panel at the top right.
5
+ //
6
+ // ╭─ quickreview ──────────────────────────── setup ─╮
7
+ // │ Welcome to quickreview 1 of 3 done │
8
+ // │ ✓ Sign in to OpenAI ChatGPT · signed in with pi │
9
+ // │ ▸ Connect GitHub alt+n check │ the next step
10
+ // │ gh is signed out: run `gh auth login` … │
11
+ // │ ○ Choose a repository │
12
+ // ├──────────────────────────────────────────────────┤
13
+ // │ the notice, then the key hints │
14
+ // ╰──────────────────────────────────────────────────╯
15
+ import type { Theme } from "@earendil-works/pi-coding-agent";
16
+ import type { Component, TuiMouseEvent, TuiMouseEventResult } from "@earendil-works/pi-tui";
17
+ import {
18
+ matchesKey,
19
+ truncateToWidth,
20
+ visibleWidth,
21
+ wrapTextWithAnsi,
22
+ } from "@earendil-works/pi-tui";
23
+ import type { HomeModel } from "./model.js";
24
+ import { loginFailureText, type HomeSetup, type SetupStepView } from "./setup.js";
25
+
26
+ type Fg = Parameters<Theme["fg"]>[0];
27
+
28
+ /** Where the card sits: centred, half the width. */
29
+ export const SETUP_OVERLAY = {
30
+ anchor: "center",
31
+ width: "50%",
32
+ minWidth: 80,
33
+ nonCapturing: true,
34
+ } as const;
35
+
36
+ /** The share of the terminal's height the card fills. */
37
+ export const CARD_HEIGHT = 0.5;
38
+ /** Sub-rows (instructions, the device code) are indented under the label. */
39
+ const INDENT = " ";
40
+ const NOTICE_ROWS = 3;
41
+ const SPIN = ["⠋", "⠙", "⠹", "⠸", "⠼", "⠴", "⠦", "⠧", "⠇", "⠏"];
42
+
43
+ export interface CardHost {
44
+ setup: HomeSetup;
45
+ model: HomeModel;
46
+ focused(): boolean;
47
+ /** The terminal's height. */
48
+ rows(): number;
49
+ unfocus(): void;
50
+ frame(): number;
51
+ /** Run the next step (⏎ while the card is focused). */
52
+ next(): void;
53
+ }
54
+
55
+ /** What each step's key does, in the hint beside it. */
56
+ const VERB: Record<SetupStepView["id"], string> = {
57
+ login: "sign in",
58
+ github: "check",
59
+ repo: "choose",
60
+ };
61
+
62
+ export class SetupCard implements Component {
63
+ constructor(
64
+ private readonly th: Theme,
65
+ private readonly host: CardHost,
66
+ ) {}
67
+
68
+ private c(color: Fg, s: string): string {
69
+ return this.th.fg(color, s);
70
+ }
71
+
72
+ private spin(): string {
73
+ return SPIN[this.host.frame() % SPIN.length]!;
74
+ }
75
+
76
+ private edge(s: string): string {
77
+ return this.c(this.host.focused() ? "borderAccent" : "borderMuted", s);
78
+ }
79
+
80
+ /** The key that runs the next step now. */
81
+ private key(): string {
82
+ return this.host.focused() ? "⏎" : "alt+n";
83
+ }
84
+
85
+ private row(w: number, left: string, right = "", selected = false): string {
86
+ const inner = w - 4;
87
+ const r = right ? ` ${right}` : "";
88
+ const l = truncateToWidth(left, Math.max(1, inner - visibleWidth(r)), "…");
89
+ const gap = Math.max(0, inner - visibleWidth(l) - visibleWidth(r));
90
+ let text = ` ${l}${" ".repeat(gap)}${r} `;
91
+ if (selected) text = this.th.bg("selectedBg", text);
92
+ return `${this.edge("│")}${text}${this.edge("│")}`;
93
+ }
94
+
95
+ /** Text under a step, wrapped inside the frame. */
96
+ private sub(w: number, text: string, color: Fg = "muted"): string[] {
97
+ const room = Math.max(10, w - 4 - INDENT.length);
98
+ return wrapTextWithAnsi(text, room).map((l) => this.row(w, `${INDENT}${this.c(color, l)}`));
99
+ }
100
+
101
+ private top(w: number): string {
102
+ const left = `${this.edge("╭─ ")}${this.th.bold(this.c("accent", "quickreview"))} `;
103
+ const right = ` ${this.c("muted", "setup")}${this.edge(" ─╮")}`;
104
+ const fill = Math.max(0, w - visibleWidth(left) - visibleWidth(right));
105
+ return `${left}${this.edge("─".repeat(fill))}${right}`;
106
+ }
107
+
108
+ private rule(w: number): string {
109
+ return this.edge(`├${"─".repeat(Math.max(0, w - 2))}┤`);
110
+ }
111
+
112
+ private bottom(w: number): string {
113
+ return this.edge(`╰${"─".repeat(Math.max(0, w - 2))}╯`);
114
+ }
115
+
116
+ private stepRows(w: number, s: SetupStepView): string[] {
117
+ const v = this.host.setup.view();
118
+ const out: string[] = [];
119
+ const k = this.key();
120
+ let mark: string;
121
+ let label: string;
122
+ let right = "";
123
+ if (s.state === "done") {
124
+ mark = this.c("success", "✓");
125
+ label = this.c("muted", s.title);
126
+ right = this.c("muted", s.found ?? "done");
127
+ } else if (s.state === "running") {
128
+ mark = this.c("accent", this.spin());
129
+ label = this.th.bold(this.c("text", s.title));
130
+ right = this.c("dim", v.login.code ? "waiting for you…" : "starting…");
131
+ } else if (s.unknown !== undefined) {
132
+ mark = this.c("dim", "?");
133
+ label = s.next ? this.th.bold(this.c("text", s.title)) : this.c("text", s.title);
134
+ right = s.next
135
+ ? `${this.c("accent", k)} ${this.c("muted", VERB[s.id])}`
136
+ : this.c("dim", "unknown");
137
+ } else if (s.next) {
138
+ mark = this.c("accent", "▸");
139
+ label = this.th.bold(this.c("text", s.title));
140
+ right = `${this.c("accent", k)} ${this.c("muted", VERB[s.id])}`;
141
+ } else {
142
+ mark = this.c("dim", "○");
143
+ label = this.c("dim", s.title);
144
+ }
145
+ out.push(this.row(w, ` ${mark} ${label}`, right, s.next));
146
+ if (s.state === "done") return out;
147
+ if (s.id === "login") out.push(...this.loginRows(w, s));
148
+ else if (s.unknown !== undefined)
149
+ out.push(...this.sub(w, `Unknown — ${s.unknown}.`, "warning"));
150
+ else if (s.next && s.id === "github" && s.missing)
151
+ out.push(...this.sub(w, `${capital(s.missing)}, then ${k} checks again.`, "warning"));
152
+ else if (s.next && s.id === "repo")
153
+ out.push(
154
+ ...this.sub(
155
+ w,
156
+ "One of your recently pushed repositories, or paste any owner/name or GitHub URL.",
157
+ ),
158
+ );
159
+ return out;
160
+ }
161
+
162
+ private loginRows(w: number, s: SetupStepView): string[] {
163
+ const v = this.host.setup.view();
164
+ const k = this.key();
165
+ const out: string[] = [];
166
+ const chatgpt = v.provider === "OpenAI";
167
+ const setting = "Device-code login must be on first: ChatGPT → Settings → Security.";
168
+ if (s.state === "running") {
169
+ const code = v.login.code;
170
+ if (!code) {
171
+ if (chatgpt) out.push(...this.sub(w, setting));
172
+ out.push(
173
+ this.row(
174
+ w,
175
+ `${INDENT}${this.c("accent", this.spin())} ${this.c("dim", "asking for a code…")}`,
176
+ ),
177
+ );
178
+ return out;
179
+ }
180
+ out.push(this.row(w, ""));
181
+ out.push(
182
+ this.row(
183
+ w,
184
+ `${INDENT}${this.c("muted", "1 Open ")} ${this.c("accent", code.verificationUri)}`,
185
+ ),
186
+ );
187
+ out.push(
188
+ this.row(
189
+ w,
190
+ `${INDENT}${this.c("muted", "2 Enter")} ${this.th.bold(this.c("text", code.userCode))}`,
191
+ ),
192
+ );
193
+ out.push(this.row(w, ""));
194
+ if (chatgpt) out.push(...this.sub(w, setting, "dim"));
195
+ out.push(
196
+ this.row(
197
+ w,
198
+ `${INDENT}${this.c("accent", this.spin())} ${this.c("dim", "waiting for you to approve…")}`,
199
+ ),
200
+ );
201
+ return out;
202
+ }
203
+ if (v.login.failure) out.push(...this.sub(w, loginFailureText(v.login.failure, k), "warning"));
204
+ if (s.unknown !== undefined) out.push(...this.sub(w, `Unknown — ${s.unknown}.`, "warning"));
205
+ if (s.next && chatgpt && v.login.failure?.kind !== "not_enabled")
206
+ out.push(...this.sub(w, setting));
207
+ return out;
208
+ }
209
+
210
+ private hints(w: number): string {
211
+ const k = (key: string, label: string): string =>
212
+ `${this.c("accent", key)} ${this.c("muted", label)}`;
213
+ return this.row(
214
+ w,
215
+ this.host.focused()
216
+ ? `${k("⏎", "next step")} ${k("esc", "back to the chat")}`
217
+ : `${k("alt+n", "next step")} ${k("f2", "focus the card")} ${this.c("dim", "· or just type to ask pi")}`,
218
+ );
219
+ }
220
+
221
+ render(width: number): string[] {
222
+ const w = Math.max(40, width);
223
+ const v = this.host.setup.view();
224
+ const body = [
225
+ this.row(w, ""),
226
+ this.row(
227
+ w,
228
+ ` ${this.th.bold(this.c("text", "Welcome to quickreview"))}`,
229
+ this.c("muted", `${v.done} of ${v.total} done `),
230
+ ),
231
+ this.row(
232
+ w,
233
+ ` ${this.c("muted", "Sign in once, choose a repository, and review your first pull request.")}`,
234
+ ),
235
+ this.row(w, ""),
236
+ ];
237
+ for (const c of v.checks) {
238
+ body.push(
239
+ this.row(
240
+ w,
241
+ ` ${this.c("warning", "✗")} ${this.th.bold(this.c("text", c.title))}`,
242
+ c.next ? `${this.c("accent", this.key())} ${this.c("muted", "check")}` : "",
243
+ c.next,
244
+ ),
245
+ );
246
+ body.push(
247
+ ...this.sub(
248
+ w,
249
+ `${capital(c.why)}${c.next ? `, then ${this.key()} checks again.` : "."}`,
250
+ "warning",
251
+ ),
252
+ );
253
+ }
254
+ for (const s of v.steps) body.push(...this.stepRows(w, s));
255
+ body.push(this.row(w, ""));
256
+ const foot = [this.rule(w)];
257
+ const n = this.host.model.notice;
258
+ if (n) {
259
+ const color: Fg = n.kind === "ok" ? "success" : n.kind === "warn" ? "warning" : "text";
260
+ for (const l of wrapTextWithAnsi(n.text, w - 4).slice(0, NOTICE_ROWS))
261
+ foot.push(this.row(w, this.c(color, l)));
262
+ }
263
+ foot.push(this.hints(w), this.bottom(w));
264
+ const target = Math.round(this.host.rows() * CARD_HEIGHT);
265
+ const spare = Math.max(0, target - 1 - body.length - foot.length);
266
+ const blank = (k: number): string[] => Array.from({ length: k }, () => this.row(w, ""));
267
+ return [
268
+ this.top(w),
269
+ ...blank(Math.floor(spare / 2)),
270
+ ...body,
271
+ ...blank(Math.ceil(spare / 2)),
272
+ ...foot,
273
+ ].map((l) => truncateToWidth(l, w));
274
+ }
275
+
276
+ handleInput(data: string): void {
277
+ if (matchesKey(data, "escape")) this.host.unfocus();
278
+ else if (matchesKey(data, "enter")) this.host.next();
279
+ }
280
+
281
+ handleMouse(e: TuiMouseEvent): TuiMouseEventResult | undefined {
282
+ return e.type === "click" ? { focus: true } : undefined;
283
+ }
284
+
285
+ invalidate(): void {}
286
+ }
287
+
288
+ const capital = (s: string): string => (s ? `${s[0]!.toUpperCase()}${s.slice(1)}` : s);
@@ -0,0 +1,57 @@
1
+ // The setup checklist's `home_*` tools: each step's action, as the model in
2
+ // the chat calls it. The keys call the same HomeSetup methods
3
+ // (extensions/home.ts), so a key and a tool never do two different things.
4
+ import { textResult, type QcrTool } from "@quickchatai/pi-quickreview/extensions/pi-tool.js";
5
+ import type { HomeSetup } from "./setup.js";
6
+ import type { HOME_SETUP_TOOL_NAMES } from "./toolnames.js";
7
+
8
+ export type HomeSetupToolName = (typeof HOME_SETUP_TOOL_NAMES)[number];
9
+
10
+ const NO_PARAMS = { type: "object", properties: {}, additionalProperties: false } as const;
11
+
12
+ /** One definition per HOME_SETUP_TOOL_NAMES entry. */
13
+ export function setupTools(setup: HomeSetup): {
14
+ [N in HomeSetupToolName]: QcrTool & { name: N };
15
+ } {
16
+ return {
17
+ home_setup_next: {
18
+ name: "home_setup_next",
19
+ label: "Home: next setup step",
20
+ description:
21
+ "Run the next step of the quickreview home's setup checklist (sign in, connect GitHub, choose a repository), as alt+n does. Answers what happened, or that setup is done.",
22
+ parameters: NO_PARAMS,
23
+ execute: async () => textResult(await setup.next()),
24
+ },
25
+ home_sign_in: {
26
+ name: "home_sign_in",
27
+ label: "Home: sign in",
28
+ description:
29
+ "Start pi's own device-code login for the provider the chat runs on. Answers with the URL and the code to enter once pi has them; the sign-in finishes in the background when the person approves it. Device-code login must be on in ChatGPT → Settings → Security.",
30
+ parameters: NO_PARAMS,
31
+ execute: async () => textResult(await setup.signIn()),
32
+ },
33
+ home_check_github: {
34
+ name: "home_check_github",
35
+ label: "Home: check GitHub",
36
+ description:
37
+ "Check again whether gh is installed and signed in. When it is not, the answer says what to run.",
38
+ parameters: NO_PARAMS,
39
+ execute: async () => textResult(await setup.checkGithub()),
40
+ },
41
+ home_choose_repo: {
42
+ name: "home_choose_repo",
43
+ label: "Home: choose a repository",
44
+ description:
45
+ "Set the repository the home reviews: owner/name or any GitHub URL of it. It is written to the qcr config's [github] repo. Without `repo`, answers the person's recently pushed repositories to choose from.",
46
+ parameters: {
47
+ type: "object",
48
+ properties: {
49
+ repo: { type: "string", description: "owner/name, or a GitHub URL of the repository." },
50
+ },
51
+ additionalProperties: false,
52
+ },
53
+ execute: async (_id, p) =>
54
+ textResult(await setup.chooseRepo(typeof p["repo"] === "string" ? p["repo"] : undefined)),
55
+ },
56
+ };
57
+ }