@pugi/cli 0.1.0-beta.99 → 1.0.0-alpha.10

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 (448) hide show
  1. package/LICENSE +1 -1
  2. package/README.md +11 -191
  3. package/bin/pugi +8 -0
  4. package/package.json +15 -71
  5. package/postinstall.mjs +31 -0
  6. package/CHANGELOG.md +0 -132
  7. package/THIRD_PARTY_NOTICES.md +0 -40
  8. package/assets/pugi-mascot.ansi +0 -16
  9. package/assets/pugi-prozr2-mascot.ansi +0 -9
  10. package/bin/run.js +0 -34
  11. package/dist/commands/deploy.js +0 -439
  12. package/dist/commands/flatten.js +0 -191
  13. package/dist/commands/jobs-watch.js +0 -201
  14. package/dist/commands/jobs.js +0 -260
  15. package/dist/commands/retro.js +0 -210
  16. package/dist/commands/smoke.js +0 -133
  17. package/dist/core/agent-progress/cleanup.js +0 -134
  18. package/dist/core/agent-progress/schema.js +0 -144
  19. package/dist/core/agent-progress/writer.js +0 -101
  20. package/dist/core/agents/adaptive-router.js +0 -330
  21. package/dist/core/agents/loader.js +0 -104
  22. package/dist/core/agents/query-decomposer.js +0 -297
  23. package/dist/core/agents/registry.js +0 -69
  24. package/dist/core/approvals/shortcut-resolver.js +0 -98
  25. package/dist/core/artifact-chain/dispatcher.js +0 -148
  26. package/dist/core/artifact-chain/exporter.js +0 -164
  27. package/dist/core/artifact-chain/state.js +0 -243
  28. package/dist/core/artifact-chain/steps.js +0 -169
  29. package/dist/core/ask-user/question.js +0 -92
  30. package/dist/core/audit/audit-trail.js +0 -275
  31. package/dist/core/auth/ensure-authenticated.js +0 -129
  32. package/dist/core/auth/env-provider.js +0 -238
  33. package/dist/core/auto-open-browser.js +0 -128
  34. package/dist/core/auto-update/channels.js +0 -122
  35. package/dist/core/auto-update/checker.js +0 -241
  36. package/dist/core/auto-update/state.js +0 -235
  37. package/dist/core/bare-mode/index.js +0 -107
  38. package/dist/core/bash/redirect.js +0 -281
  39. package/dist/core/bash-classifier.js +0 -1397
  40. package/dist/core/checkpoint/resumer.js +0 -149
  41. package/dist/core/checkpoint/rewinder.js +0 -291
  42. package/dist/core/checkpoints/shadow-git.js +0 -670
  43. package/dist/core/citations/parser.js +0 -109
  44. package/dist/core/classifier/yolo-classifier.js +0 -88
  45. package/dist/core/clipboard.js +0 -70
  46. package/dist/core/codegraph/decision-store.js +0 -248
  47. package/dist/core/codegraph/detect-repo.js +0 -459
  48. package/dist/core/codegraph/install.js +0 -134
  49. package/dist/core/codegraph/offer-hook.js +0 -220
  50. package/dist/core/compact/auto-trigger.js +0 -96
  51. package/dist/core/compact/buffer-rewriter.js +0 -115
  52. package/dist/core/compact/summarizer.js +0 -208
  53. package/dist/core/compact/token-counter.js +0 -108
  54. package/dist/core/consensus/anvil-fanout.js +0 -276
  55. package/dist/core/consensus/diff-capture.js +0 -491
  56. package/dist/core/consensus/rubric.js +0 -233
  57. package/dist/core/context/builder.js +0 -114
  58. package/dist/core/context/compaction-events.js +0 -99
  59. package/dist/core/context/compaction.js +0 -602
  60. package/dist/core/context/index.js +0 -28
  61. package/dist/core/context/invariants.js +0 -250
  62. package/dist/core/context/markdown-loader.js +0 -288
  63. package/dist/core/context/markdown-traverse.js +0 -255
  64. package/dist/core/context/pugiignore.js +0 -316
  65. package/dist/core/context/repo-skeleton.js +0 -533
  66. package/dist/core/context/tool-eviction.js +0 -55
  67. package/dist/core/context/watcher.js +0 -342
  68. package/dist/core/context/working-set.js +0 -165
  69. package/dist/core/coordinator/agent-tools.js +0 -77
  70. package/dist/core/coordinator/agent-toolset.js +0 -65
  71. package/dist/core/coordinator/fsm.js +0 -73
  72. package/dist/core/coordinator/mode-fsm.js +0 -70
  73. package/dist/core/cost/rate-card.js +0 -129
  74. package/dist/core/cost/tracker.js +0 -221
  75. package/dist/core/credentials.js +0 -355
  76. package/dist/core/cron/scheduler.js +0 -138
  77. package/dist/core/denial-tracking/index.js +0 -8
  78. package/dist/core/denial-tracking/state.js +0 -264
  79. package/dist/core/diagnostics/probe-runner.js +0 -93
  80. package/dist/core/diagnostics/probes/api.js +0 -46
  81. package/dist/core/diagnostics/probes/auth.js +0 -93
  82. package/dist/core/diagnostics/probes/bare-mode.js +0 -42
  83. package/dist/core/diagnostics/probes/cli-version.js +0 -127
  84. package/dist/core/diagnostics/probes/config.js +0 -72
  85. package/dist/core/diagnostics/probes/denial-tracking.js +0 -57
  86. package/dist/core/diagnostics/probes/disk.js +0 -81
  87. package/dist/core/diagnostics/probes/engine-live.js +0 -46
  88. package/dist/core/diagnostics/probes/git.js +0 -65
  89. package/dist/core/diagnostics/probes/hooks.js +0 -118
  90. package/dist/core/diagnostics/probes/mcp.js +0 -75
  91. package/dist/core/diagnostics/probes/node.js +0 -59
  92. package/dist/core/diagnostics/probes/pnpm.js +0 -36
  93. package/dist/core/diagnostics/probes/pugi-md.js +0 -89
  94. package/dist/core/diagnostics/probes/sandbox.js +0 -72
  95. package/dist/core/diagnostics/probes/session.js +0 -74
  96. package/dist/core/diagnostics/probes/status-snapshot.js +0 -488
  97. package/dist/core/diagnostics/probes/workspace.js +0 -63
  98. package/dist/core/diagnostics/types.js +0 -70
  99. package/dist/core/dispatch/cache-cleanup.js +0 -197
  100. package/dist/core/dispatch/cache-handoff.js +0 -295
  101. package/dist/core/edits/apply-patch-layer-e.js +0 -189
  102. package/dist/core/edits/dispatch.js +0 -511
  103. package/dist/core/edits/format-detector.js +0 -260
  104. package/dist/core/edits/format-matrix.js +0 -26
  105. package/dist/core/edits/fuzzy-ladder.js +0 -650
  106. package/dist/core/edits/index.js +0 -19
  107. package/dist/core/edits/journal.js +0 -199
  108. package/dist/core/edits/layer-a-apply.js +0 -217
  109. package/dist/core/edits/layer-a-fuzzy-apply.js +0 -198
  110. package/dist/core/edits/layer-b-apply.js +0 -211
  111. package/dist/core/edits/layer-c-apply.js +0 -160
  112. package/dist/core/edits/layer-d-ast.js +0 -572
  113. package/dist/core/edits/marker-parser.js +0 -401
  114. package/dist/core/edits/security-gate.js +0 -223
  115. package/dist/core/edits/verify-hook.js +0 -273
  116. package/dist/core/edits/worktree.js +0 -322
  117. package/dist/core/engine/adapter-runner.js +0 -8
  118. package/dist/core/engine/anvil-client.js +0 -344
  119. package/dist/core/engine/auto-compact.js +0 -179
  120. package/dist/core/engine/budgets.js +0 -195
  121. package/dist/core/engine/context-prefix.js +0 -155
  122. package/dist/core/engine/index.js +0 -12
  123. package/dist/core/engine/intensity.js +0 -163
  124. package/dist/core/engine/intent.js +0 -260
  125. package/dist/core/engine/native-pugi.js +0 -1616
  126. package/dist/core/engine/noop.js +0 -27
  127. package/dist/core/engine/prompts.js +0 -236
  128. package/dist/core/engine/strip-internal-fields.js +0 -124
  129. package/dist/core/engine/tool-bridge.js +0 -2173
  130. package/dist/core/engine/verification-patterns.js +0 -195
  131. package/dist/core/evaluation/golden-dataset.js +0 -293
  132. package/dist/core/feedback/queue.js +0 -177
  133. package/dist/core/feedback/submitter.js +0 -145
  134. package/dist/core/file-cache.js +0 -141
  135. package/dist/core/flatten/flatten-repo.js +0 -439
  136. package/dist/core/format/osc8-link.js +0 -28
  137. package/dist/core/hook-chains.js +0 -392
  138. package/dist/core/hooks/citation-verify-hook.js +0 -138
  139. package/dist/core/hooks/citation-verify.js +0 -112
  140. package/dist/core/hooks/events.js +0 -46
  141. package/dist/core/hooks/index.js +0 -15
  142. package/dist/core/hooks/registry.js +0 -216
  143. package/dist/core/hooks/runner.js +0 -236
  144. package/dist/core/hooks/v2/event-emitter.js +0 -115
  145. package/dist/core/hooks/v2/executor.js +0 -282
  146. package/dist/core/hooks/v2/index.js +0 -25
  147. package/dist/core/hooks/v2/lifecycle.js +0 -104
  148. package/dist/core/hooks/v2/loader.js +0 -216
  149. package/dist/core/hooks/v2/matcher.js +0 -125
  150. package/dist/core/hooks/v2/trust.js +0 -143
  151. package/dist/core/hooks/v2/types.js +0 -86
  152. package/dist/core/hooks/worktree-events.js +0 -158
  153. package/dist/core/hooks.js +0 -415
  154. package/dist/core/image/renderer.js +0 -71
  155. package/dist/core/index-store.js +0 -260
  156. package/dist/core/init/detector.js +0 -582
  157. package/dist/core/init/template-renderer.js +0 -242
  158. package/dist/core/jobs/registry.js +0 -462
  159. package/dist/core/ledger/results-tsv.js +0 -142
  160. package/dist/core/log-discipline/stdout-redirect.js +0 -51
  161. package/dist/core/lsp/cache.js +0 -105
  162. package/dist/core/lsp/client.js +0 -1229
  163. package/dist/core/lsp/language-detect.js +0 -66
  164. package/dist/core/lsp/post-edit-diagnostics.js +0 -171
  165. package/dist/core/lsp/server-detect.js +0 -173
  166. package/dist/core/lsp/symbol-cache.js +0 -162
  167. package/dist/core/lsp/symbol-tools.js +0 -664
  168. package/dist/core/mcp/client.js +0 -385
  169. package/dist/core/mcp/http-server.js +0 -553
  170. package/dist/core/mcp/orchestrator-config.js +0 -192
  171. package/dist/core/mcp/orchestrator-tools.js +0 -806
  172. package/dist/core/mcp/permission.js +0 -190
  173. package/dist/core/mcp/registry.js +0 -193
  174. package/dist/core/mcp/server-tools.js +0 -219
  175. package/dist/core/mcp/server.js +0 -397
  176. package/dist/core/mcp/trust.js +0 -91
  177. package/dist/core/memory/dual-write.js +0 -416
  178. package/dist/core/memory/passive-extract.js +0 -130
  179. package/dist/core/memory/phase1-kinds.js +0 -20
  180. package/dist/core/memory/secret-scanner.js +0 -304
  181. package/dist/core/memory-sync/queue.js +0 -170
  182. package/dist/core/metrics/extract.js +0 -113
  183. package/dist/core/modes/roo-modes.js +0 -68
  184. package/dist/core/onboarding/ensure-initialized.js +0 -133
  185. package/dist/core/onboarding/marker.js +0 -111
  186. package/dist/core/onboarding/telemetry-state.js +0 -108
  187. package/dist/core/output-style/presets.js +0 -176
  188. package/dist/core/output-style/state.js +0 -185
  189. package/dist/core/path-security.js +0 -345
  190. package/dist/core/permission.js +0 -369
  191. package/dist/core/permissions/auto-classifier.js +0 -124
  192. package/dist/core/permissions/bash-parser.js +0 -371
  193. package/dist/core/permissions/circuit-breaker.js +0 -83
  194. package/dist/core/permissions/constrained-edit.js +0 -91
  195. package/dist/core/permissions/gate.js +0 -278
  196. package/dist/core/permissions/index.js +0 -20
  197. package/dist/core/permissions/mode.js +0 -174
  198. package/dist/core/permissions/network-egress.js +0 -137
  199. package/dist/core/permissions/state.js +0 -241
  200. package/dist/core/permissions/tool-class.js +0 -107
  201. package/dist/core/plan-mode/ui-state.js +0 -51
  202. package/dist/core/plans/plan-artifact.js +0 -721
  203. package/dist/core/policy-limits/etag-store.js +0 -122
  204. package/dist/core/prd-check/parser.js +0 -215
  205. package/dist/core/prd-check/reporter.js +0 -127
  206. package/dist/core/prd-check/session-review.js +0 -557
  207. package/dist/core/prd-check/verifiers.js +0 -223
  208. package/dist/core/prompt-cache/client-cache.js +0 -99
  209. package/dist/core/prompts/assembly.js +0 -29
  210. package/dist/core/prompts/registry.js +0 -364
  211. package/dist/core/pugi-gitignore.js +0 -52
  212. package/dist/core/pugi-md/cc-compat-rules.js +0 -735
  213. package/dist/core/pugi-md/context-injector.js +0 -76
  214. package/dist/core/pugi-md/walk-up.js +0 -207
  215. package/dist/core/python/uv-installer.js +0 -270
  216. package/dist/core/python/uv-resolver.js +0 -83
  217. package/dist/core/rate-limit/narrator.js +0 -146
  218. package/dist/core/recipes/cli-types.js +0 -20
  219. package/dist/core/recipes/loader.js +0 -103
  220. package/dist/core/recipes/runner.js +0 -345
  221. package/dist/core/recipes/schema.js +0 -587
  222. package/dist/core/release-notes/parser.js +0 -241
  223. package/dist/core/release-notes/state.js +0 -116
  224. package/dist/core/repl/ask.js +0 -512
  225. package/dist/core/repl/cancellation.js +0 -98
  226. package/dist/core/repl/cap-warning.js +0 -91
  227. package/dist/core/repl/clipboard-read.js +0 -174
  228. package/dist/core/repl/dispatch-fsm.js +0 -220
  229. package/dist/core/repl/engine-bridge.js +0 -303
  230. package/dist/core/repl/history-search.js +0 -175
  231. package/dist/core/repl/history.js +0 -182
  232. package/dist/core/repl/kill-ring.js +0 -138
  233. package/dist/core/repl/model-pricing.js +0 -135
  234. package/dist/core/repl/privacy-banner.js +0 -71
  235. package/dist/core/repl/session.js +0 -4962
  236. package/dist/core/repl/slash-commands.js +0 -747
  237. package/dist/core/repl/store/index.js +0 -12
  238. package/dist/core/repl/store/jsonl-log.js +0 -321
  239. package/dist/core/repl/store/lockfile.js +0 -155
  240. package/dist/core/repl/store/session-store.js +0 -821
  241. package/dist/core/repl/store/types.js +0 -44
  242. package/dist/core/repl/store/uuid-v7.js +0 -68
  243. package/dist/core/repl/tool-route.js +0 -382
  244. package/dist/core/repl/workspace-context.js +0 -206
  245. package/dist/core/repo-map/build.js +0 -125
  246. package/dist/core/repo-map/cache.js +0 -185
  247. package/dist/core/repo-map/extractor.js +0 -254
  248. package/dist/core/repo-map/formatter.js +0 -145
  249. package/dist/core/repo-map/page-rank.js +0 -105
  250. package/dist/core/repo-map/scanner.js +0 -211
  251. package/dist/core/retro/git-collector.js +0 -251
  252. package/dist/core/retro/health-card.js +0 -25
  253. package/dist/core/retro/metrics.js +0 -342
  254. package/dist/core/retro/narrative.js +0 -249
  255. package/dist/core/retro/plane-collector.js +0 -274
  256. package/dist/core/retro/pr-issue-link.js +0 -65
  257. package/dist/core/retro/types.js +0 -16
  258. package/dist/core/retry-budget/budget.js +0 -284
  259. package/dist/core/retry-budget/index.js +0 -5
  260. package/dist/core/retry-budget/retry-cap.js +0 -74
  261. package/dist/core/routing/lead-worker.js +0 -43
  262. package/dist/core/routing/pre-flight-estimator.js +0 -108
  263. package/dist/core/runs/run-tree.js +0 -103
  264. package/dist/core/sandboxing/adapter.js +0 -29
  265. package/dist/core/sandboxing/index.js +0 -49
  266. package/dist/core/sandboxing/none.js +0 -19
  267. package/dist/core/sandboxing/seatbelt.js +0 -183
  268. package/dist/core/security/injection-scanner.js +0 -367
  269. package/dist/core/security/output-filter.js +0 -418
  270. package/dist/core/session/env-file.js +0 -105
  271. package/dist/core/session/section-budgets.js +0 -140
  272. package/dist/core/session.js +0 -377
  273. package/dist/core/settings.js +0 -400
  274. package/dist/core/share/formatter.js +0 -271
  275. package/dist/core/share/redactor.js +0 -221
  276. package/dist/core/share/uploader.js +0 -267
  277. package/dist/core/skills/defaults.js +0 -457
  278. package/dist/core/skills/loader.js +0 -454
  279. package/dist/core/skills/sources.js +0 -480
  280. package/dist/core/skills/trust.js +0 -172
  281. package/dist/core/smoke/headless-driver.js +0 -174
  282. package/dist/core/smoke/orchestrator.js +0 -194
  283. package/dist/core/smoke/runner.js +0 -238
  284. package/dist/core/smoke/scenario-parser.js +0 -316
  285. package/dist/core/statusline.js +0 -99
  286. package/dist/core/subagents/dispatcher-real.js +0 -600
  287. package/dist/core/subagents/dispatcher.js +0 -352
  288. package/dist/core/subagents/index.js +0 -39
  289. package/dist/core/subagents/isolation-matrix.js +0 -213
  290. package/dist/core/subagents/spawn.js +0 -101
  291. package/dist/core/telemetry/emitter.js +0 -229
  292. package/dist/core/telemetry/queue.js +0 -251
  293. package/dist/core/theme/context.js +0 -91
  294. package/dist/core/theme/presets.js +0 -228
  295. package/dist/core/theme/state.js +0 -181
  296. package/dist/core/todos/invariant.js +0 -10
  297. package/dist/core/todos/state.js +0 -177
  298. package/dist/core/tool-schema/compressor.js +0 -89
  299. package/dist/core/transport/version-interceptor.js +0 -166
  300. package/dist/core/trust.js +0 -109
  301. package/dist/core/tui/thinking-block.js +0 -64
  302. package/dist/core/vim/keymap.js +0 -288
  303. package/dist/core/vim/state.js +0 -92
  304. package/dist/core/watch-markers/marker-watcher.js +0 -133
  305. package/dist/core/worktree/include-parser.js +0 -249
  306. package/dist/core/worktree-manager/cleanup.js +0 -123
  307. package/dist/core/worktree-manager/manager.js +0 -303
  308. package/dist/index.js +0 -44
  309. package/dist/runtime/bootstrap.js +0 -190
  310. package/dist/runtime/cli.js +0 -8121
  311. package/dist/runtime/commands/agents.js +0 -385
  312. package/dist/runtime/commands/budget.js +0 -192
  313. package/dist/runtime/commands/cancel.js +0 -231
  314. package/dist/runtime/commands/chain.js +0 -489
  315. package/dist/runtime/commands/codegraph-status.js +0 -227
  316. package/dist/runtime/commands/compact.js +0 -297
  317. package/dist/runtime/commands/config.js +0 -595
  318. package/dist/runtime/commands/cost.js +0 -199
  319. package/dist/runtime/commands/delegate.js +0 -312
  320. package/dist/runtime/commands/dispatch.js +0 -126
  321. package/dist/runtime/commands/doctor.js +0 -579
  322. package/dist/runtime/commands/feedback.js +0 -184
  323. package/dist/runtime/commands/hooks.js +0 -187
  324. package/dist/runtime/commands/init.js +0 -254
  325. package/dist/runtime/commands/lsp.js +0 -368
  326. package/dist/runtime/commands/mcp.js +0 -935
  327. package/dist/runtime/commands/memory.js +0 -582
  328. package/dist/runtime/commands/model.js +0 -237
  329. package/dist/runtime/commands/onboarding.js +0 -275
  330. package/dist/runtime/commands/patch.js +0 -128
  331. package/dist/runtime/commands/permissions.js +0 -112
  332. package/dist/runtime/commands/plan.js +0 -143
  333. package/dist/runtime/commands/prd-check.js +0 -285
  334. package/dist/runtime/commands/privacy.js +0 -107
  335. package/dist/runtime/commands/recipe.js +0 -325
  336. package/dist/runtime/commands/redo-blob-store.js +0 -92
  337. package/dist/runtime/commands/redo.js +0 -361
  338. package/dist/runtime/commands/release-notes.js +0 -229
  339. package/dist/runtime/commands/repo-map.js +0 -95
  340. package/dist/runtime/commands/report.js +0 -299
  341. package/dist/runtime/commands/resume.js +0 -118
  342. package/dist/runtime/commands/review-consensus.js +0 -414
  343. package/dist/runtime/commands/rewind.js +0 -333
  344. package/dist/runtime/commands/roster.js +0 -117
  345. package/dist/runtime/commands/sessions.js +0 -163
  346. package/dist/runtime/commands/share.js +0 -316
  347. package/dist/runtime/commands/skills.js +0 -401
  348. package/dist/runtime/commands/status.js +0 -186
  349. package/dist/runtime/commands/stickers.js +0 -82
  350. package/dist/runtime/commands/style.js +0 -194
  351. package/dist/runtime/commands/theme.js +0 -196
  352. package/dist/runtime/commands/undo.js +0 -361
  353. package/dist/runtime/commands/update.js +0 -289
  354. package/dist/runtime/commands/vim.js +0 -140
  355. package/dist/runtime/commands/worktree.js +0 -177
  356. package/dist/runtime/commands/worktrees.js +0 -155
  357. package/dist/runtime/deprecation-warning.js +0 -69
  358. package/dist/runtime/engine-exit-code.js +0 -50
  359. package/dist/runtime/headless-repl.js +0 -195
  360. package/dist/runtime/headless.js +0 -548
  361. package/dist/runtime/load-hooks-or-exit.js +0 -71
  362. package/dist/runtime/plan-decompose.js +0 -531
  363. package/dist/runtime/sigint-guard.js +0 -272
  364. package/dist/runtime/stream-renderer.js +0 -195
  365. package/dist/runtime/update-check.js +0 -294
  366. package/dist/runtime/version.js +0 -65
  367. package/dist/runtime/worktree-bootstrap.js +0 -579
  368. package/dist/skills/bundled/batch.js +0 -617
  369. package/dist/skills/bundled/index.js +0 -45
  370. package/dist/skills/bundled/loop.js +0 -358
  371. package/dist/skills/bundled/remember.js +0 -383
  372. package/dist/skills/bundled/simplify.js +0 -289
  373. package/dist/skills/bundled/skillify.js +0 -373
  374. package/dist/skills/bundled/stuck.js +0 -558
  375. package/dist/skills/bundled/verify.js +0 -439
  376. package/dist/testing/vcr.js +0 -486
  377. package/dist/tools/agent-tool.js +0 -229
  378. package/dist/tools/apply-patch.js +0 -556
  379. package/dist/tools/ask-user-question.js +0 -337
  380. package/dist/tools/ask-user.js +0 -115
  381. package/dist/tools/bash.js +0 -1238
  382. package/dist/tools/brief.js +0 -224
  383. package/dist/tools/cron.js +0 -433
  384. package/dist/tools/enter-worktree.js +0 -250
  385. package/dist/tools/exit-worktree.js +0 -147
  386. package/dist/tools/file-tools.js +0 -553
  387. package/dist/tools/http-request.js +0 -336
  388. package/dist/tools/lsp-tools.js +0 -565
  389. package/dist/tools/mcp-tool.js +0 -260
  390. package/dist/tools/multi-edit.js +0 -361
  391. package/dist/tools/powershell.js +0 -268
  392. package/dist/tools/registry.js +0 -166
  393. package/dist/tools/server-tools.js +0 -892
  394. package/dist/tools/skill-tool.js +0 -96
  395. package/dist/tools/sleep.js +0 -99
  396. package/dist/tools/synthetic-output.js +0 -133
  397. package/dist/tools/tasks.js +0 -208
  398. package/dist/tools/todo-write.js +0 -184
  399. package/dist/tools/verify-plan-execution.js +0 -295
  400. package/dist/tools/web-fetch-injection-scanner.js +0 -207
  401. package/dist/tools/web-fetch.js +0 -720
  402. package/dist/tools/web-search.js +0 -458
  403. package/dist/tui/agent-progress-card.js +0 -111
  404. package/dist/tui/agent-tree-pane.js +0 -9
  405. package/dist/tui/agent-tree.js +0 -87
  406. package/dist/tui/ask-cli.js +0 -52
  407. package/dist/tui/ask-modal.js +0 -211
  408. package/dist/tui/ask-user-question-chips.js +0 -315
  409. package/dist/tui/ask-user-question-prompt.js +0 -203
  410. package/dist/tui/compact-banner.js +0 -81
  411. package/dist/tui/conversation-pane.js +0 -164
  412. package/dist/tui/cost-table.js +0 -111
  413. package/dist/tui/device-flow.js +0 -142
  414. package/dist/tui/doctor-table.js +0 -46
  415. package/dist/tui/feedback-prompt.js +0 -156
  416. package/dist/tui/input-box.js +0 -732
  417. package/dist/tui/login-picker.js +0 -69
  418. package/dist/tui/markdown-render.js +0 -266
  419. package/dist/tui/multi-file-diff-approval.js +0 -375
  420. package/dist/tui/onboarding-wizard.js +0 -240
  421. package/dist/tui/permissions-picker.js +0 -86
  422. package/dist/tui/render.js +0 -160
  423. package/dist/tui/repl-render.js +0 -770
  424. package/dist/tui/repl-splash-art.js +0 -64
  425. package/dist/tui/repl-splash-mascot.js +0 -154
  426. package/dist/tui/repl-splash.js +0 -117
  427. package/dist/tui/repl.js +0 -378
  428. package/dist/tui/slash-palette.js +0 -106
  429. package/dist/tui/splash-data.js +0 -61
  430. package/dist/tui/splash.js +0 -31
  431. package/dist/tui/status-bar.js +0 -209
  432. package/dist/tui/status-table.js +0 -7
  433. package/dist/tui/stickers-art.js +0 -136
  434. package/dist/tui/style-table.js +0 -28
  435. package/dist/tui/theme-table.js +0 -29
  436. package/dist/tui/thinking-spinner.js +0 -123
  437. package/dist/tui/tool-stream-pane.js +0 -140
  438. package/dist/tui/update-banner.js +0 -33
  439. package/dist/tui/vim-input.js +0 -267
  440. package/dist/tui/welcome-banner.js +0 -107
  441. package/dist/tui/welcome-data.js +0 -293
  442. package/dist/tui/workspace-context.js +0 -105
  443. package/docs/examples/codegraph.mcp.json +0 -10
  444. package/test/scenarios/codegen-create-file.scenario.txt +0 -13
  445. package/test/scenarios/compact-force.scenario.txt +0 -12
  446. package/test/scenarios/identity.scenario.txt +0 -11
  447. package/test/scenarios/persona-handoff.scenario.txt +0 -12
  448. package/test/scenarios/walkback.scenario.txt +0 -12
@@ -1,375 +0,0 @@
1
- import { jsx as _jsx, jsxs as _jsxs } from "react/jsx-runtime";
2
- /**
3
- * MultiFileDiffApproval — side-by-side multi-file diff approval modal
4
- * (PUGI-68).
5
- *
6
- * When the engine proposes a batch of edits that touches more than one
7
- * file, the operator needs to review every diff in a single coherent
8
- * view, then accept-all / reject-all / per-file approve before the
9
- * dispatcher applies anything. The single-file approval surfaces in
10
- * the AskModal / PlanReviewModal family are insufficient — a per-file
11
- * back-to-back prompt loses the cross-file context the operator needs
12
- * to spot a regression that spans modules.
13
- *
14
- * Layout (matches the AskUserQuestionChips PUGI-130 side-by-side
15
- * precedent, see `ask-user-question-chips.tsx`):
16
- *
17
- * ┌─ Multi-file diff review ───────────────────────────────────────┐
18
- * │ ┌─ Files ─────────────┐ ┌─ Diff: src/foo/bar.ts ─────────────┐ │
19
- * │ │ ▸ • src/foo/bar.ts │ │ --- src/foo/bar.ts │ │
20
- * │ │ ✓ src/baz.ts │ │ +++ src/foo/bar.ts │ │
21
- * │ │ ✗ src/qux.ts │ │ @@ -1,4 +1,4 @@ │ │
22
- * │ │ • src/x/y.ts │ │ -const x = 1; │ │
23
- * │ │ │ │ +const x = 2; │ │
24
- * │ └─────────────────────┘ └────────────────────────────────────┘ │
25
- * │ 1/4 approved · 1/4 rejected · 2 remaining · Enter when done │
26
- * └────────────────────────────────────────────────────────────────┘
27
- *
28
- * Key bindings:
29
- * - ↑ / ↓ ............ navigate the file list
30
- * - a ................ approve the highlighted file
31
- * - r ................ reject the highlighted file
32
- * - A (shift+a) ...... approve every file in the batch
33
- * - R (shift+r) ...... reject every file in the batch
34
- * - PgUp / PgDn ...... scroll the diff pane
35
- * - Enter ............ finalise — emit per-file verdicts
36
- * - Esc .............. cancel the whole batch (every file → rejected)
37
- *
38
- * Contract notes:
39
- * - The component is PURE (Ink-style). It mounts useState for cursor,
40
- * per-file verdict map, and diff-pane scroll offset. Emits exactly
41
- * one `onResolve` callback when the operator presses Enter (or Esc
42
- * for a cancel).
43
- * - Per-file diff bodies are rendered verbatim from the provided
44
- * unified-diff text — the component does NOT compute diffs from raw
45
- * file contents. Callers (typically the dispatcher result transcript)
46
- * own the diff text generation.
47
- * - Long file paths are truncated middle-style so prefix + suffix stay
48
- * visible (the parts the operator scans for module scope + filename).
49
- * - Long diff bodies scroll via a single-axis offset; horizontal
50
- * overflow is left to Ink's text wrapping per line. No mouse support.
51
- *
52
- * Brand voice gate: ASCII glyphs only (✓ / ✗ kept for status — already
53
- * shipped в other TUI components like agent-progress-card). No banned
54
- * brand words, no em-dashes, no attribution to external AIs.
55
- */
56
- import { useEffect, useMemo, useRef, useState } from 'react';
57
- import { Box, Text, useInput } from 'ink';
58
- /* ------------------------------------------------------------------ */
59
- /* Defensive caps */
60
- /* ------------------------------------------------------------------ */
61
- /** Maximum chars rendered per file path in the left pane. */
62
- export const MULTI_FILE_DIFF_PATH_CAP = 48;
63
- /** Visible rows in the diff pane viewport. */
64
- export const MULTI_FILE_DIFF_PANE_HEIGHT = 18;
65
- /** Width hint for the left file-list column (used for path truncation). */
66
- export const MULTI_FILE_DIFF_LEFT_WIDTH = 32;
67
- /** Hard cap on diff body length (chars) — defends against runaway model output. */
68
- export const MULTI_FILE_DIFF_BODY_CHAR_CAP = 200_000;
69
- /* ------------------------------------------------------------------ */
70
- /* Helpers */
71
- /* ------------------------------------------------------------------ */
72
- /**
73
- * Middle-truncate a long file path so both prefix (module scope) and
74
- * suffix (filename) stay visible. Mirrors the macOS `truncate=middle`
75
- * convention. Appends `…` in the middle when truncation happens.
76
- *
77
- * Examples (cap = 24):
78
- * "src/foo/bar/baz/qux.ts" → "src/foo/bar/baz/qux.ts" (fits)
79
- * "src/a-long-module/b/c/d.ts" → "src/a-long-mo…/b/c/d.ts" (cut middle)
80
- *
81
- * Exported so the spec can assert the contract directly.
82
- */
83
- export function truncateMiddle(raw, cap) {
84
- if (cap <= 1)
85
- return '…';
86
- if (raw.length <= cap)
87
- return raw;
88
- // Reserve one slot for the ellipsis; balance prefix/suffix around it.
89
- // The suffix gets one extra char on odd budgets so the filename stays
90
- // longer (operators scan filenames more than the path prefix).
91
- const remaining = cap - 1;
92
- const prefixLen = Math.floor(remaining / 2);
93
- const suffixLen = remaining - prefixLen;
94
- return `${raw.slice(0, prefixLen)}…${raw.slice(raw.length - suffixLen)}`;
95
- }
96
- /**
97
- * Defensive char cap on the diff body. Schema-level caps live upstream;
98
- * this is belt + braces against a malformed dispatcher transcript that
99
- * could otherwise exhaust the terminal scrollback.
100
- */
101
- export function clampDiffBody(raw) {
102
- if (raw.length <= MULTI_FILE_DIFF_BODY_CHAR_CAP)
103
- return raw;
104
- return `${raw.slice(0, MULTI_FILE_DIFF_BODY_CHAR_CAP - 1)}…`;
105
- }
106
- export function classifyDiffLine(line) {
107
- if (line.startsWith('+++') || line.startsWith('---'))
108
- return 'file-header';
109
- if (line.startsWith('@@'))
110
- return 'hunk-header';
111
- if (line.startsWith('+'))
112
- return 'addition';
113
- if (line.startsWith('-'))
114
- return 'deletion';
115
- return 'context';
116
- }
117
- /** Inline helper — return per-line render props for a diff line. */
118
- function renderProps(kind) {
119
- switch (kind) {
120
- case 'file-header':
121
- return { bold: true };
122
- case 'hunk-header':
123
- return { color: 'blue', bold: true };
124
- case 'addition':
125
- return { color: 'green' };
126
- case 'deletion':
127
- return { color: 'red' };
128
- case 'context':
129
- return { dimColor: true };
130
- }
131
- }
132
- /**
133
- * Public verdict-encoder mirror of the AskModal / PlanReviewModal
134
- * encoders. Surfaces a single human-readable summary string the caller
135
- * can inject as the next operator turn or log to a session journal.
136
- *
137
- * - `cancelled` → "[MULTI-DIFF-VERDICT:cancelled]"
138
- * - all approved → "[MULTI-DIFF-VERDICT:all-approved] file1; file2"
139
- * - all rejected → "[MULTI-DIFF-VERDICT:all-rejected] file1; file2"
140
- * - mixed → "[MULTI-DIFF-VERDICT:mixed] +file1; -file2; ?file3"
141
- *
142
- * Each per-file token in mixed mode is prefixed `+` (approved), `-`
143
- * (rejected), or `?` (still pending — operator hit Enter без deciding).
144
- */
145
- export function encodeMultiFileDiffVerdict(result) {
146
- if (result.cancelled)
147
- return '[MULTI-DIFF-VERDICT:cancelled]';
148
- const total = result.verdicts.length;
149
- if (total === 0)
150
- return '[MULTI-DIFF-VERDICT:empty]';
151
- const allApproved = result.verdicts.every((v) => v.verdict === 'approved');
152
- const allRejected = result.verdicts.every((v) => v.verdict === 'rejected');
153
- if (allApproved) {
154
- return `[MULTI-DIFF-VERDICT:all-approved] ${result.verdicts
155
- .map((v) => v.path)
156
- .join('; ')}`;
157
- }
158
- if (allRejected) {
159
- return `[MULTI-DIFF-VERDICT:all-rejected] ${result.verdicts
160
- .map((v) => v.path)
161
- .join('; ')}`;
162
- }
163
- const tokens = result.verdicts.map((v) => {
164
- const prefix = v.verdict === 'approved' ? '+' : v.verdict === 'rejected' ? '-' : '?';
165
- return `${prefix}${v.path}`;
166
- });
167
- return `[MULTI-DIFF-VERDICT:mixed] ${tokens.join('; ')}`;
168
- }
169
- /* ------------------------------------------------------------------ */
170
- /* Component */
171
- /* ------------------------------------------------------------------ */
172
- /**
173
- * Build the result object for a given verdict map + entries vector.
174
- * Hoisted because both the commit (Enter) and cancel (Esc) paths need
175
- * to project the same shape — cancel just overrides every verdict to
176
- * `rejected` and stamps `cancelled: true`.
177
- */
178
- function buildResult(entries, verdicts, cancelled) {
179
- const projected = entries.map((entry, idx) => ({
180
- path: entry.path,
181
- verdict: verdicts[idx] ?? 'pending',
182
- }));
183
- return {
184
- verdicts: projected,
185
- approvedPaths: projected
186
- .filter((v) => v.verdict === 'approved')
187
- .map((v) => v.path),
188
- rejectedPaths: projected
189
- .filter((v) => v.verdict === 'rejected')
190
- .map((v) => v.path),
191
- cancelled,
192
- };
193
- }
194
- export function MultiFileDiffApproval(props) {
195
- // FIX ( triple-review): the previous `useMemo(() => props.entries,
196
- // [props.entries])` was a no-op — it returned the same reference it
197
- // depended on, so the memo never produced a stable identity gain. We
198
- // reference `props.entries` directly now; downstream useEffect /
199
- // useMemo hooks key on the real prop, not a redundant wrapper.
200
- const entries = props.entries;
201
- const paneHeight = props.paneHeight ?? MULTI_FILE_DIFF_PANE_HEIGHT;
202
- const [cursor, setCursor] = useState(0);
203
- const [verdicts, setVerdicts] = useState(() => entries.map(() => 'pending'));
204
- const [scrollOffset, setScrollOffset] = useState(0);
205
- // FIX ( triple-review, P1): the lazy useState initialiser
206
- // captures `entries.length` ONCE at mount. If the caller swaps in
207
- // a different entries array (length mismatch), the verdicts vector
208
- // would drift — `setVerdictAt` could index out of range or
209
- // `buildResult` could project a `pending` for a real entry whose
210
- // verdict the operator already set. Re-sync on length change while
211
- // preserving existing per-index verdicts (forgiving variant A).
212
- useEffect(() => {
213
- setVerdicts((prev) => {
214
- if (prev.length === entries.length)
215
- return prev;
216
- return entries.map((_, i) => prev[i] ?? 'pending');
217
- });
218
- // Also clamp the cursor so it never points past the new end.
219
- setCursor((c) => {
220
- if (entries.length === 0)
221
- return 0;
222
- return Math.min(c, entries.length - 1);
223
- });
224
- }, [entries.length, entries]);
225
- // FIX ( triple-review, P1): `commit()` is called from inside
226
- // the useInput closure, which captures the `verdicts` value at the
227
- // render time the closure was created. With rapid keypresses (e.g.
228
- // `a` then Enter on the same React tick), React has scheduled the
229
- // setVerdicts update but the closure still sees the previous array.
230
- // The emitted MultiFileDiffResult would drop the latest verdict.
231
- // Fix: track verdicts via a ref synced in a useEffect — the commit
232
- // path reads `verdictsRef.current` so it always sees the latest map.
233
- const verdictsRef = useRef(verdicts);
234
- useEffect(() => {
235
- verdictsRef.current = verdicts;
236
- }, [verdicts]);
237
- // Pre-split the active diff body into lines for the right pane. The
238
- // body is clamped defensively before splitting so a runaway model
239
- // payload cannot exhaust the terminal scrollback. useMemo here keeps
240
- // the line array stable across navigation re-renders on the SAME
241
- // file — only the cursor changes when the operator presses ↑/↓ on
242
- // the same diff body.
243
- const activeEntry = entries[cursor];
244
- const activeLines = useMemo(() => {
245
- const body = clampDiffBody(activeEntry?.diff ?? '');
246
- if (body.length === 0)
247
- return [];
248
- return body.split('\n');
249
- }, [activeEntry?.diff]);
250
- function commit(cancelled = false) {
251
- // Read the freshest verdict map via ref — the closure-captured
252
- // `verdicts` state could be one render behind on rapid keypresses.
253
- const latest = verdictsRef.current;
254
- const finalVerdicts = cancelled
255
- ? entries.map(() => 'rejected')
256
- : latest;
257
- props.onResolve(buildResult(entries, finalVerdicts, cancelled));
258
- }
259
- function setVerdictAt(idx, verdict) {
260
- setVerdicts((prev) => {
261
- const next = prev.slice();
262
- next[idx] = verdict;
263
- return next;
264
- });
265
- }
266
- function setAllVerdicts(verdict) {
267
- setVerdicts(() => entries.map(() => verdict));
268
- }
269
- useInput((input, key) => {
270
- // Esc cancels the whole batch (every file → rejected). Mirrors the
271
- // AskModal cancel contract so operator muscle memory transfers.
272
- if (key.escape) {
273
- commit(true);
274
- return;
275
- }
276
- // Enter commits the current verdict map. Pending files stay
277
- // pending — the caller decides whether `pending` is treated as
278
- // approve or reject (dispatcher policy lives upstream).
279
- if (key.return) {
280
- commit(false);
281
- return;
282
- }
283
- // ↑ / ↓ navigate file list. Reset scroll on file change so the
284
- // operator sees the diff header again, not a stale offset from
285
- // the previous file.
286
- if (key.upArrow) {
287
- if (entries.length === 0)
288
- return;
289
- setCursor((c) => (c - 1 + entries.length) % entries.length);
290
- setScrollOffset(0);
291
- return;
292
- }
293
- if (key.downArrow) {
294
- if (entries.length === 0)
295
- return;
296
- setCursor((c) => (c + 1) % entries.length);
297
- setScrollOffset(0);
298
- return;
299
- }
300
- // PgUp / PgDn scroll the diff pane by a near-full viewport. We
301
- // keep one row of overlap so the operator's eye anchors across
302
- // pages. Clamped to [0, max] so over-scroll stops at the bottom
303
- // line instead of producing an empty pane.
304
- if (key.pageUp) {
305
- setScrollOffset((o) => Math.max(0, o - Math.max(1, paneHeight - 1)));
306
- return;
307
- }
308
- if (key.pageDown) {
309
- setScrollOffset((o) => {
310
- const maxOffset = Math.max(0, activeLines.length - paneHeight);
311
- return Math.min(maxOffset, o + Math.max(1, paneHeight - 1));
312
- });
313
- return;
314
- }
315
- // Capital A / R = bulk verdict. Lowercase a / r = per-file. The
316
- // order matters: Ink delivers SHIFTed keys as the upper-case
317
- // glyph in `input`, so we can match с a direct equality.
318
- if (input === 'A') {
319
- setAllVerdicts('approved');
320
- return;
321
- }
322
- if (input === 'R') {
323
- setAllVerdicts('rejected');
324
- return;
325
- }
326
- if (input === 'a') {
327
- setVerdictAt(cursor, 'approved');
328
- return;
329
- }
330
- if (input === 'r') {
331
- setVerdictAt(cursor, 'rejected');
332
- return;
333
- }
334
- }, { isActive: props.inert !== true });
335
- const approvedCount = verdicts.filter((v) => v === 'approved').length;
336
- const rejectedCount = verdicts.filter((v) => v === 'rejected').length;
337
- const pendingCount = verdicts.filter((v) => v === 'pending').length;
338
- const total = entries.length;
339
- // Diff pane viewport: a window of `paneHeight` lines starting at
340
- // scrollOffset. Empty entries render с a placeholder so the operator
341
- // sees the file is intentionally empty (vs the modal being broken).
342
- const visibleLines = activeLines.slice(scrollOffset, scrollOffset + paneHeight);
343
- const diffPaneTitle = activeEntry
344
- ? `Diff: ${truncateMiddle(activeEntry.path, MULTI_FILE_DIFF_PATH_CAP)}`
345
- : 'Diff';
346
- return (_jsxs(Box, { flexDirection: "column", borderStyle: "round", borderColor: "cyan", paddingX: 1, children: [_jsxs(Box, { children: [_jsx(Text, { bold: true, color: "cyan", children: '? ' }), _jsx(Text, { bold: true, children: `Multi-file diff review (${total} ${total === 1 ? 'file' : 'files'})` })] }), _jsxs(Box, { flexDirection: "row", marginTop: 1, children: [_jsxs(Box, { flexDirection: "column", borderStyle: "single", borderColor: "gray", paddingX: 1, marginRight: 1, minWidth: MULTI_FILE_DIFF_LEFT_WIDTH, children: [_jsx(Box, { children: _jsx(Text, { bold: true, dimColor: true, children: 'Files' }) }), entries.map((entry, idx) => {
347
- const isHighlighted = idx === cursor;
348
- const verdict = verdicts[idx] ?? 'pending';
349
- // Badge: ✓ approved (green), ✗ rejected (red), • pending (dim).
350
- // The badge sits BEFORE the cursor arrow so the operator can
351
- // skim status without scanning the cursor column.
352
- let badgeGlyph = '•';
353
- let badgeColor;
354
- let badgeDim = true;
355
- if (verdict === 'approved') {
356
- badgeGlyph = '✓';
357
- badgeColor = 'green';
358
- badgeDim = false;
359
- }
360
- else if (verdict === 'rejected') {
361
- badgeGlyph = '✗';
362
- badgeColor = 'red';
363
- badgeDim = false;
364
- }
365
- // Path budget = left width minus borders, cursor arrow (2),
366
- // badge + space (2), padding (2). Defensive floor at 8 chars.
367
- const pathBudget = Math.max(8, MULTI_FILE_DIFF_LEFT_WIDTH - 4 - 2 - 2);
368
- return (_jsxs(Box, { children: [_jsx(Text, { color: isHighlighted ? 'cyan' : undefined, bold: isHighlighted, children: isHighlighted ? '▸ ' : ' ' }), _jsx(Text, { color: badgeColor, dimColor: badgeDim, bold: !badgeDim, children: `${badgeGlyph} ` }), _jsx(Text, { color: isHighlighted ? 'cyan' : undefined, bold: isHighlighted, children: truncateMiddle(entry.path, pathBudget) }), entry.hint !== undefined && entry.hint.length > 0 ? (_jsx(Text, { dimColor: true, italic: true, children: ` (${entry.hint})` })) : null] }, `file-${idx}-${entry.path}`));
369
- })] }), _jsxs(Box, { flexDirection: "column", borderStyle: "single", borderColor: "gray", paddingX: 1, flexGrow: 1, children: [_jsxs(Box, { children: [_jsx(Text, { bold: true, dimColor: true, children: diffPaneTitle }), activeLines.length > paneHeight ? (_jsx(Text, { dimColor: true, children: ` · lines ${scrollOffset + 1}-${Math.min(scrollOffset + paneHeight, activeLines.length)}/${activeLines.length}` })) : null] }), visibleLines.length === 0 ? (_jsx(Text, { dimColor: true, italic: true, children: '(empty diff)' })) : (visibleLines.map((line, idx) => {
370
- const kind = classifyDiffLine(line);
371
- const rp = renderProps(kind);
372
- return (_jsx(Text, { color: rp.color, bold: rp.bold, dimColor: rp.dimColor, children: line.length > 0 ? line : ' ' }, `diff-${cursor}-${scrollOffset + idx}`));
373
- }))] })] }), _jsxs(Box, { marginTop: 1, flexDirection: "column", children: [_jsxs(Box, { children: [_jsx(Text, { color: "green", children: `${approvedCount}/${total} approved` }), _jsx(Text, { dimColor: true, children: ' · ' }), _jsx(Text, { color: "red", children: `${rejectedCount}/${total} rejected` }), _jsx(Text, { dimColor: true, children: ' · ' }), _jsx(Text, { children: `${pendingCount} remaining` }), _jsx(Text, { dimColor: true, children: ' · Enter when done' })] }), _jsx(Box, { children: _jsx(Text, { dimColor: true, children: '[↑↓] navigate · [a] approve · [r] reject · [A] all · [R] none · [PgUp/PgDn] scroll · [Esc] cancel' }) })] })] }));
374
- }
375
- //# sourceMappingURL=multi-file-diff-approval.js.map
@@ -1,240 +0,0 @@
1
- import { jsx as _jsx, jsxs as _jsxs } from "react/jsx-runtime";
2
- /**
3
- * — Onboarding Ink wizard.
4
- *
5
- * Six-screen interactive walk:
6
- *
7
- * 1. Welcome + auth status (single Enter to continue)
8
- * 2. Default permission mode (4-row picker)
9
- * 3. Output style preset (5-row picker)
10
- * 4. MCP server pointer (informational, Enter to continue)
11
- * 5. Telemetry consent (3-row picker)
12
- * 6. Recap card (Enter to commit + exit)
13
- *
14
- * Driven entirely by Ink's `useInput`. The component does NOT perform
15
- * any fs writes — it resolves the verdict back to the caller
16
- * (`runOnboardingCommand`), which translates verdicts into L6 / L18 /
17
- * telemetry-state mutations. Single source of truth: the runner.
18
- *
19
- * Each picker step pre-selects the CURRENT persisted value (from the
20
- * snapshot passed in props) so pressing Enter on Step 2/3/5 keeps the
21
- * current value — that is the idempotency contract.
22
- *
23
- * Cancellation:
24
- * - Esc / Ctrl-C at any step → verdict.cancelled = true, the runner
25
- * skips ALL writes (including the marker touch) so the next bare
26
- * `pugi` invocation still surfaces the first-run hint.
27
- *
28
- * Keystrokes:
29
- * - ↑/↓ or j/k — move selection in pickers.
30
- * - Enter — confirm step (keep current = pass through; new pick
31
- * = update verdict for that tier).
32
- * - 's' — skip current step explicitly (verdict slot stays null).
33
- * - Esc / 'q' — cancel the wizard.
34
- */
35
- import { useState } from 'react';
36
- import { Box, Text, render, useApp, useInput } from 'ink';
37
- import { PERMISSION_MODES, PERMISSION_MODE_GLOSS, } from '../core/permissions/index.js';
38
- import { OUTPUT_STYLES, OUTPUT_STYLE_SLUGS, } from '../core/output-style/presets.js';
39
- import { TELEMETRY_CHOICES, } from '../core/onboarding/telemetry-state.js';
40
- const EMPTY_DRAFT = {
41
- permissionMode: null,
42
- outputStyle: null,
43
- telemetry: null,
44
- };
45
- /**
46
- * Lookup the snapshot value's index within the picker rows so the
47
- * initial cursor sits on the current value. Returns 0 (safe default)
48
- * when the snapshot value is outside the closed list — should never
49
- * happen given the type guards in the state modules, but the index
50
- * fallback keeps Ink from crashing on a malformed config.
51
- */
52
- function indexOf(rows, value) {
53
- const idx = rows.indexOf(value);
54
- return idx === -1 ? 0 : idx;
55
- }
56
- /**
57
- * The wizard component. Pure: no fs, no env, no network. Verdicts
58
- * flow up via `onComplete`; the caller owns the writes.
59
- */
60
- export function OnboardingWizard(props) {
61
- const { snapshot, onComplete } = props;
62
- const [step, setStep] = useState(1);
63
- const [permissionIdx, setPermissionIdx] = useState(indexOf(PERMISSION_MODES, snapshot.permissionMode));
64
- const [styleIdx, setStyleIdx] = useState(indexOf(OUTPUT_STYLE_SLUGS, snapshot.outputStyle));
65
- const [telemetryIdx, setTelemetryIdx] = useState(indexOf(TELEMETRY_CHOICES, snapshot.telemetry));
66
- const [draft, setDraft] = useState(EMPTY_DRAFT);
67
- const finish = (final, cancelled) => {
68
- onComplete({
69
- permissionMode: final.permissionMode,
70
- outputStyle: final.outputStyle,
71
- telemetry: final.telemetry,
72
- cancelled,
73
- });
74
- };
75
- useInput((input, key) => {
76
- // Universal cancel.
77
- if (key.escape || (key.ctrl && input === 'c')) {
78
- finish(EMPTY_DRAFT, true);
79
- return;
80
- }
81
- // Universal skip — Enter on a picker means "keep current"; explicit
82
- // 's' makes the skip intent obvious in the recap.
83
- const isAdvance = key.return;
84
- const moveUp = key.upArrow || input === 'k';
85
- const moveDown = key.downArrow || input === 'j';
86
- const explicitSkip = input === 's';
87
- switch (step) {
88
- case 1: {
89
- if (isAdvance)
90
- setStep(2);
91
- return;
92
- }
93
- case 2: {
94
- if (moveUp) {
95
- setPermissionIdx((i) => (i === 0 ? PERMISSION_MODES.length - 1 : i - 1));
96
- return;
97
- }
98
- if (moveDown) {
99
- setPermissionIdx((i) => (i === PERMISSION_MODES.length - 1 ? 0 : i + 1));
100
- return;
101
- }
102
- if (isAdvance || explicitSkip) {
103
- const picked = PERMISSION_MODES[permissionIdx];
104
- const verdict = explicitSkip || picked === snapshot.permissionMode ? null : picked ?? null;
105
- setDraft((d) => ({ ...d, permissionMode: verdict }));
106
- setStep(3);
107
- return;
108
- }
109
- return;
110
- }
111
- case 3: {
112
- if (moveUp) {
113
- setStyleIdx((i) => (i === 0 ? OUTPUT_STYLE_SLUGS.length - 1 : i - 1));
114
- return;
115
- }
116
- if (moveDown) {
117
- setStyleIdx((i) => (i === OUTPUT_STYLE_SLUGS.length - 1 ? 0 : i + 1));
118
- return;
119
- }
120
- if (isAdvance || explicitSkip) {
121
- const picked = OUTPUT_STYLE_SLUGS[styleIdx];
122
- const verdict = explicitSkip || picked === snapshot.outputStyle ? null : picked ?? null;
123
- setDraft((d) => ({ ...d, outputStyle: verdict }));
124
- setStep(4);
125
- return;
126
- }
127
- return;
128
- }
129
- case 4: {
130
- if (isAdvance)
131
- setStep(5);
132
- return;
133
- }
134
- case 5: {
135
- if (moveUp) {
136
- setTelemetryIdx((i) => (i === 0 ? TELEMETRY_CHOICES.length - 1 : i - 1));
137
- return;
138
- }
139
- if (moveDown) {
140
- setTelemetryIdx((i) => (i === TELEMETRY_CHOICES.length - 1 ? 0 : i + 1));
141
- return;
142
- }
143
- if (isAdvance || explicitSkip) {
144
- const picked = TELEMETRY_CHOICES[telemetryIdx];
145
- const verdict = explicitSkip || picked === snapshot.telemetry ? null : picked ?? null;
146
- setDraft((d) => ({ ...d, telemetry: verdict }));
147
- setStep(6);
148
- return;
149
- }
150
- return;
151
- }
152
- case 6: {
153
- if (isAdvance)
154
- finish(draft, false);
155
- return;
156
- }
157
- }
158
- });
159
- return (_jsxs(Box, { flexDirection: "column", paddingX: 2, paddingY: 1, children: [_jsx(StepHeader, { step: step }), _jsxs(Box, { marginTop: 1, flexDirection: "column", children: [step === 1 && _jsx(WelcomeStep, { snapshot: snapshot }), step === 2 && (_jsx(ModeStep, { current: snapshot.permissionMode, selectedIdx: permissionIdx })), step === 3 && (_jsx(StyleStep, { current: snapshot.outputStyle, currentSource: snapshot.outputStyleSource, selectedIdx: styleIdx })), step === 4 && _jsx(McpStep, {}), step === 5 && (_jsx(TelemetryStep, { current: snapshot.telemetry, selectedIdx: telemetryIdx })), step === 6 && _jsx(RecapStep, { snapshot: snapshot, draft: draft })] }), _jsx(FooterHints, { step: step })] }));
160
- }
161
- function StepHeader({ step }) {
162
- const titles = {
163
- 1: 'Welcome to Pugi',
164
- 2: 'Step 2 / 5 — Default permission mode',
165
- 3: 'Step 3 / 5 — Output style',
166
- 4: 'Step 4 / 5 — MCP servers',
167
- 5: 'Step 5 / 5 — Telemetry consent',
168
- 6: 'Setup complete',
169
- };
170
- return (_jsx(Text, { bold: true, color: "cyan", children: titles[step] }));
171
- }
172
- function WelcomeStep({ snapshot }) {
173
- return (_jsxs(Box, { flexDirection: "column", children: [_jsx(Text, { children: "Brief it. It ships." }), _jsx(Box, { marginTop: 1, children: _jsx(Text, { dimColor: true, children: snapshot.authPresent
174
- ? 'You are signed in. The wizard configures local defaults; values persist to ~/.pugi/config.json.'
175
- : 'You are NOT signed in. The wizard still configures local defaults, but you should run `pugi login` after.' }) })] }));
176
- }
177
- function ModeStep({ current, selectedIdx, }) {
178
- return (_jsx(Box, { flexDirection: "column", children: PERMISSION_MODES.map((mode, idx) => (_jsx(PickerRow, { isSelected: idx === selectedIdx, isCurrent: mode === current, title: mode, gloss: PERMISSION_MODE_GLOSS[mode] }, mode))) }));
179
- }
180
- function StyleStep({ current, currentSource, selectedIdx, }) {
181
- return (_jsxs(Box, { flexDirection: "column", children: [OUTPUT_STYLE_SLUGS.map((slug, idx) => (_jsx(PickerRow, { isSelected: idx === selectedIdx, isCurrent: slug === current, title: slug, gloss: OUTPUT_STYLES[slug].gloss }, slug))), _jsx(Box, { marginTop: 1, children: _jsx(Text, { dimColor: true, children: currentSource === 'workspace'
182
- ? 'Active style is currently a workspace override. The wizard writes the user-tier default.'
183
- : `Active source: ${currentSource}.` }) })] }));
184
- }
185
- function McpStep() {
186
- return (_jsxs(Box, { flexDirection: "column", children: [_jsx(Text, { children: "MCP servers extend Pugi with extra tools (filesystem, browser, custom APIs)." }), _jsx(Box, { marginTop: 1, children: _jsx(Text, { dimColor: true, children: "Add one with:" }) }), _jsx(Text, { children: ' pugi mcp add <name> <command>' }), _jsx(Text, { children: ' pugi mcp list' }), _jsx(Box, { marginTop: 1, children: _jsx(Text, { dimColor: true, children: "You can skip for now and add servers later." }) })] }));
187
- }
188
- function TelemetryStep({ current, selectedIdx, }) {
189
- const gloss = {
190
- off: 'No telemetry of any kind.',
191
- anonymous: 'Counts + error categories only; no payloads.',
192
- community: 'Anonymous + opt-in usage panels.',
193
- };
194
- return (_jsx(Box, { flexDirection: "column", children: TELEMETRY_CHOICES.map((choice, idx) => (_jsx(PickerRow, { isSelected: idx === selectedIdx, isCurrent: choice === current, title: choice, gloss: gloss[choice] }, choice))) }));
195
- }
196
- function RecapStep({ snapshot, draft, }) {
197
- const finalMode = draft.permissionMode ?? snapshot.permissionMode;
198
- const finalStyle = draft.outputStyle ?? snapshot.outputStyle;
199
- const finalTelemetry = draft.telemetry ?? snapshot.telemetry;
200
- return (_jsxs(Box, { flexDirection: "column", children: [_jsx(Text, { children: ` Permission mode: ${finalMode}${draft.permissionMode === null ? ' (unchanged)' : ''}` }), _jsx(Text, { children: ` Output style: ${finalStyle}${draft.outputStyle === null ? ' (unchanged)' : ''}` }), _jsx(Text, { children: ` Telemetry: ${finalTelemetry}${draft.telemetry === null ? ' (unchanged)' : ''}` }), _jsx(Box, { marginTop: 1, children: _jsx(Text, { dimColor: true, children: "Press Enter to write defaults + exit. Esc to cancel without saving." }) })] }));
201
- }
202
- function PickerRow({ isSelected, isCurrent, title, gloss, }) {
203
- const indicator = isSelected ? '▸ ' : ' ';
204
- const currentTag = isCurrent ? ' [current]' : '';
205
- return (_jsxs(Text, { children: [_jsxs(Text, { color: isSelected ? 'cyan' : undefined, bold: isSelected, children: [indicator, title.padEnd(18, ' ')] }), _jsx(Text, { dimColor: true, children: `${gloss}${currentTag}` })] }));
206
- }
207
- function FooterHints({ step }) {
208
- const hint = step === 1 || step === 4
209
- ? 'Enter continue Esc cancel'
210
- : step === 6
211
- ? 'Enter commit + exit Esc cancel'
212
- : '↑/↓ select Enter confirm s skip Esc cancel';
213
- return (_jsx(Box, { marginTop: 1, children: _jsx(Text, { dimColor: true, children: hint }) }));
214
- }
215
- /**
216
- * Mount the wizard, await the operator's verdict, unmount Ink, return
217
- * the verdict to the runner. Wrapped in a `useApp` consumer so we can
218
- * call `exit()` and let `waitUntilExit()` resolve cleanly.
219
- */
220
- export async function renderOnboardingWizard(opts) {
221
- return new Promise((resolvePromise) => {
222
- let resolved = false;
223
- const handleComplete = (verdict) => {
224
- if (resolved)
225
- return;
226
- resolved = true;
227
- app.unmount();
228
- resolvePromise(verdict);
229
- };
230
- const Wrapper = () => {
231
- const { exit } = useApp();
232
- return (_jsx(OnboardingWizard, { snapshot: opts.snapshot, onComplete: (verdict) => {
233
- handleComplete(verdict);
234
- exit();
235
- } }));
236
- };
237
- const app = render(_jsx(Wrapper, {}));
238
- });
239
- }
240
- //# sourceMappingURL=onboarding-wizard.js.map