@pugi/cli 0.1.0-beta.9 → 0.1.0-beta.91

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 (411) hide show
  1. package/CHANGELOG.md +132 -0
  2. package/LICENSE +1 -1
  3. package/assets/pugi-prozr2-mascot.ansi +9 -0
  4. package/bin/run.js +33 -1
  5. package/dist/commands/deploy.js +40 -40
  6. package/dist/commands/flatten.js +191 -0
  7. package/dist/commands/jobs-watch.js +201 -0
  8. package/dist/commands/jobs.js +42 -27
  9. package/dist/commands/smoke.js +133 -0
  10. package/dist/core/agent-progress/cleanup.js +134 -0
  11. package/dist/core/agent-progress/schema.js +144 -0
  12. package/dist/core/agent-progress/writer.js +101 -0
  13. package/dist/core/agents/adaptive-router.js +330 -0
  14. package/dist/core/agents/query-decomposer.js +297 -0
  15. package/dist/core/agents/registry.js +3 -3
  16. package/dist/core/approvals/shortcut-resolver.js +98 -0
  17. package/dist/core/artifact-chain/dispatcher.js +148 -0
  18. package/dist/core/artifact-chain/exporter.js +164 -0
  19. package/dist/core/artifact-chain/state.js +243 -0
  20. package/dist/core/artifact-chain/steps.js +169 -0
  21. package/dist/core/ask-user/question.js +92 -0
  22. package/dist/core/audit/audit-trail.js +275 -0
  23. package/dist/core/auth/ensure-authenticated.js +129 -0
  24. package/dist/core/auth/env-provider.js +238 -0
  25. package/dist/core/auto-open-browser.js +4 -4
  26. package/dist/core/auto-update/channels.js +122 -0
  27. package/dist/core/auto-update/checker.js +241 -0
  28. package/dist/core/auto-update/state.js +235 -0
  29. package/dist/core/bare-mode/index.js +107 -0
  30. package/dist/core/bash/redirect.js +281 -0
  31. package/dist/core/bash-classifier.js +436 -40
  32. package/dist/core/checkpoint/resumer.js +149 -0
  33. package/dist/core/checkpoint/rewinder.js +291 -0
  34. package/dist/core/checkpoints/shadow-git.js +670 -0
  35. package/dist/core/citations/parser.js +109 -0
  36. package/dist/core/classifier/yolo-classifier.js +88 -0
  37. package/dist/core/codegraph/decision-store.js +248 -0
  38. package/dist/core/codegraph/detect-repo.js +459 -0
  39. package/dist/core/codegraph/install.js +134 -0
  40. package/dist/core/codegraph/offer-hook.js +220 -0
  41. package/dist/core/compact/auto-trigger.js +96 -0
  42. package/dist/core/compact/buffer-rewriter.js +115 -0
  43. package/dist/core/compact/summarizer.js +208 -0
  44. package/dist/core/compact/token-counter.js +108 -0
  45. package/dist/core/consensus/anvil-fanout.js +25 -25
  46. package/dist/core/consensus/diff-capture.js +121 -12
  47. package/dist/core/consensus/rubric.js +21 -21
  48. package/dist/core/context/builder.js +6 -6
  49. package/dist/core/context/compaction-events.js +8 -8
  50. package/dist/core/context/compaction.js +31 -31
  51. package/dist/core/context/index.js +15 -8
  52. package/dist/core/context/invariants.js +51 -51
  53. package/dist/core/context/markdown-loader.js +28 -10
  54. package/dist/core/context/markdown-traverse.js +255 -0
  55. package/dist/core/context/pugiignore.js +41 -41
  56. package/dist/core/context/repo-skeleton.js +37 -37
  57. package/dist/core/context/tool-eviction.js +55 -0
  58. package/dist/core/context/watcher.js +32 -32
  59. package/dist/core/context/working-set.js +23 -23
  60. package/dist/core/coordinator/agent-tools.js +77 -0
  61. package/dist/core/coordinator/agent-toolset.js +65 -0
  62. package/dist/core/coordinator/fsm.js +73 -0
  63. package/dist/core/coordinator/mode-fsm.js +70 -0
  64. package/dist/core/cost/rate-card.js +129 -0
  65. package/dist/core/cost/tracker.js +221 -0
  66. package/dist/core/credentials.js +13 -13
  67. package/dist/core/cron/scheduler.js +138 -0
  68. package/dist/core/denial-tracking/index.js +8 -0
  69. package/dist/core/denial-tracking/state.js +264 -0
  70. package/dist/core/diagnostics/probe-runner.js +93 -0
  71. package/dist/core/diagnostics/probes/api.js +46 -0
  72. package/dist/core/diagnostics/probes/auth.js +93 -0
  73. package/dist/core/diagnostics/probes/bare-mode.js +42 -0
  74. package/dist/core/diagnostics/probes/cli-version.js +127 -0
  75. package/dist/core/diagnostics/probes/config.js +72 -0
  76. package/dist/core/diagnostics/probes/denial-tracking.js +57 -0
  77. package/dist/core/diagnostics/probes/disk.js +81 -0
  78. package/dist/core/diagnostics/probes/engine-live.js +46 -0
  79. package/dist/core/diagnostics/probes/git.js +65 -0
  80. package/dist/core/diagnostics/probes/hooks.js +118 -0
  81. package/dist/core/diagnostics/probes/mcp.js +75 -0
  82. package/dist/core/diagnostics/probes/node.js +59 -0
  83. package/dist/core/diagnostics/probes/pnpm.js +36 -0
  84. package/dist/core/diagnostics/probes/pugi-md.js +89 -0
  85. package/dist/core/diagnostics/probes/sandbox.js +40 -0
  86. package/dist/core/diagnostics/probes/session.js +74 -0
  87. package/dist/core/diagnostics/probes/status-snapshot.js +488 -0
  88. package/dist/core/diagnostics/probes/workspace.js +63 -0
  89. package/dist/core/diagnostics/types.js +70 -0
  90. package/dist/core/dispatch/cache-cleanup.js +197 -0
  91. package/dist/core/dispatch/cache-handoff.js +295 -0
  92. package/dist/core/edits/apply-patch-layer-e.js +189 -0
  93. package/dist/core/edits/dispatch.js +333 -7
  94. package/dist/core/edits/format-detector.js +260 -0
  95. package/dist/core/edits/format-matrix.js +26 -0
  96. package/dist/core/edits/fuzzy-ladder.js +650 -0
  97. package/dist/core/edits/index.js +5 -1
  98. package/dist/core/edits/journal.js +199 -0
  99. package/dist/core/edits/layer-a-apply.js +15 -15
  100. package/dist/core/edits/layer-a-fuzzy-apply.js +198 -0
  101. package/dist/core/edits/layer-b-apply.js +9 -9
  102. package/dist/core/edits/layer-c-apply.js +6 -6
  103. package/dist/core/edits/layer-d-ast.js +557 -14
  104. package/dist/core/edits/marker-parser.js +12 -12
  105. package/dist/core/edits/security-gate.js +27 -27
  106. package/dist/core/edits/verify-hook.js +273 -0
  107. package/dist/core/edits/worktree.js +29 -29
  108. package/dist/core/engine/anvil-client.js +214 -26
  109. package/dist/core/engine/auto-compact.js +179 -0
  110. package/dist/core/engine/budgets.js +186 -0
  111. package/dist/core/engine/context-prefix.js +155 -0
  112. package/dist/core/engine/index.js +1 -1
  113. package/dist/core/engine/intensity.js +158 -0
  114. package/dist/core/engine/intent.js +260 -0
  115. package/dist/core/engine/native-pugi.js +1295 -227
  116. package/dist/core/engine/prompts.js +129 -19
  117. package/dist/core/engine/strip-internal-fields.js +124 -0
  118. package/dist/core/engine/tool-bridge.js +1792 -59
  119. package/dist/core/evaluation/golden-dataset.js +293 -0
  120. package/dist/core/feedback/queue.js +177 -0
  121. package/dist/core/feedback/submitter.js +145 -0
  122. package/dist/core/file-cache.js +113 -1
  123. package/dist/core/flatten/flatten-repo.js +439 -0
  124. package/dist/core/format/osc8-link.js +28 -0
  125. package/dist/core/hook-chains.js +392 -0
  126. package/dist/core/hooks/citation-verify-hook.js +138 -0
  127. package/dist/core/hooks/citation-verify.js +112 -0
  128. package/dist/core/hooks/events.js +46 -0
  129. package/dist/core/hooks/index.js +15 -0
  130. package/dist/core/hooks/registry.js +216 -0
  131. package/dist/core/hooks/runner.js +236 -0
  132. package/dist/core/hooks/v2/event-emitter.js +115 -0
  133. package/dist/core/hooks/v2/executor.js +282 -0
  134. package/dist/core/hooks/v2/index.js +25 -0
  135. package/dist/core/hooks/v2/lifecycle.js +104 -0
  136. package/dist/core/hooks/v2/loader.js +216 -0
  137. package/dist/core/hooks/v2/matcher.js +125 -0
  138. package/dist/core/hooks/v2/trust.js +143 -0
  139. package/dist/core/hooks/v2/types.js +86 -0
  140. package/dist/core/hooks/worktree-events.js +158 -0
  141. package/dist/core/image/renderer.js +71 -0
  142. package/dist/core/init/detector.js +582 -0
  143. package/dist/core/init/template-renderer.js +242 -0
  144. package/dist/core/jobs/registry.js +18 -18
  145. package/dist/core/ledger/results-tsv.js +142 -0
  146. package/dist/core/log-discipline/stdout-redirect.js +51 -0
  147. package/dist/core/lsp/cache.js +105 -0
  148. package/dist/core/lsp/client.js +551 -41
  149. package/dist/core/lsp/language-detect.js +66 -0
  150. package/dist/core/lsp/post-edit-diagnostics.js +171 -0
  151. package/dist/core/lsp/server-detect.js +173 -0
  152. package/dist/core/lsp/symbol-cache.js +162 -0
  153. package/dist/core/lsp/symbol-tools.js +664 -0
  154. package/dist/core/mcp/client.js +97 -28
  155. package/dist/core/mcp/http-server.js +553 -0
  156. package/dist/core/mcp/orchestrator-tools.js +662 -0
  157. package/dist/core/mcp/permission.js +190 -0
  158. package/dist/core/mcp/registry.js +39 -17
  159. package/dist/core/mcp/server-tools.js +219 -0
  160. package/dist/core/mcp/server.js +397 -0
  161. package/dist/core/mcp/trust.js +10 -10
  162. package/dist/core/memory/dual-write.js +416 -0
  163. package/dist/core/memory/passive-extract.js +130 -0
  164. package/dist/core/memory/phase1-kinds.js +20 -0
  165. package/dist/core/memory/secret-scanner.js +304 -0
  166. package/dist/core/memory-sync/queue.js +170 -0
  167. package/dist/core/metrics/extract.js +113 -0
  168. package/dist/core/modes/roo-modes.js +68 -0
  169. package/dist/core/onboarding/ensure-initialized.js +133 -0
  170. package/dist/core/onboarding/marker.js +111 -0
  171. package/dist/core/onboarding/telemetry-state.js +108 -0
  172. package/dist/core/output-style/presets.js +176 -0
  173. package/dist/core/output-style/state.js +185 -0
  174. package/dist/core/path-security.js +287 -5
  175. package/dist/core/permission.js +82 -22
  176. package/dist/core/permissions/auto-classifier.js +124 -0
  177. package/dist/core/permissions/bash-parser.js +371 -0
  178. package/dist/core/permissions/circuit-breaker.js +83 -0
  179. package/dist/core/permissions/constrained-edit.js +91 -0
  180. package/dist/core/permissions/gate.js +278 -0
  181. package/dist/core/permissions/index.js +20 -0
  182. package/dist/core/permissions/mode.js +174 -0
  183. package/dist/core/permissions/network-egress.js +137 -0
  184. package/dist/core/permissions/state.js +241 -0
  185. package/dist/core/permissions/tool-class.js +93 -0
  186. package/dist/core/plan-mode/ui-state.js +51 -0
  187. package/dist/core/plans/plan-artifact.js +721 -0
  188. package/dist/core/policy-limits/etag-store.js +122 -0
  189. package/dist/core/prd-check/parser.js +215 -0
  190. package/dist/core/prd-check/reporter.js +127 -0
  191. package/dist/core/prd-check/session-review.js +557 -0
  192. package/dist/core/prd-check/verifiers.js +223 -0
  193. package/dist/core/prompt-cache/client-cache.js +99 -0
  194. package/dist/core/prompts/assembly.js +29 -0
  195. package/dist/core/prompts/registry.js +364 -0
  196. package/dist/core/pugi-md/cc-compat-rules.js +735 -0
  197. package/dist/core/pugi-md/context-injector.js +76 -0
  198. package/dist/core/pugi-md/walk-up.js +207 -0
  199. package/dist/core/python/uv-installer.js +270 -0
  200. package/dist/core/python/uv-resolver.js +83 -0
  201. package/dist/core/rate-limit/narrator.js +146 -0
  202. package/dist/core/recipes/cli-types.js +20 -0
  203. package/dist/core/recipes/loader.js +103 -0
  204. package/dist/core/recipes/runner.js +345 -0
  205. package/dist/core/recipes/schema.js +587 -0
  206. package/dist/core/release-notes/parser.js +241 -0
  207. package/dist/core/release-notes/state.js +116 -0
  208. package/dist/core/repl/ask.js +37 -37
  209. package/dist/core/repl/cancellation.js +26 -26
  210. package/dist/core/repl/cap-warning.js +4 -4
  211. package/dist/core/repl/clipboard-read.js +11 -11
  212. package/dist/core/repl/dispatch-fsm.js +12 -12
  213. package/dist/core/repl/history-search.js +15 -15
  214. package/dist/core/repl/history.js +28 -18
  215. package/dist/core/repl/kill-ring.js +5 -5
  216. package/dist/core/repl/model-pricing.js +135 -0
  217. package/dist/core/repl/privacy-banner.js +22 -22
  218. package/dist/core/repl/session.js +2148 -217
  219. package/dist/core/repl/slash-commands.js +501 -41
  220. package/dist/core/repl/store/index.js +1 -1
  221. package/dist/core/repl/store/jsonl-log.js +22 -22
  222. package/dist/core/repl/store/lockfile.js +10 -10
  223. package/dist/core/repl/store/session-store.js +136 -107
  224. package/dist/core/repl/store/types.js +15 -15
  225. package/dist/core/repl/store/uuid-v7.js +12 -12
  226. package/dist/core/repl/workspace-context.js +43 -21
  227. package/dist/core/repo-map/build.js +125 -0
  228. package/dist/core/repo-map/cache.js +185 -0
  229. package/dist/core/repo-map/extractor.js +254 -0
  230. package/dist/core/repo-map/formatter.js +145 -0
  231. package/dist/core/repo-map/page-rank.js +105 -0
  232. package/dist/core/repo-map/scanner.js +211 -0
  233. package/dist/core/retry-budget/budget.js +284 -0
  234. package/dist/core/retry-budget/index.js +5 -0
  235. package/dist/core/retry-budget/retry-cap.js +74 -0
  236. package/dist/core/routing/lead-worker.js +43 -0
  237. package/dist/core/routing/pre-flight-estimator.js +108 -0
  238. package/dist/core/runs/run-tree.js +103 -0
  239. package/dist/core/security/injection-scanner.js +367 -0
  240. package/dist/core/security/output-filter.js +418 -0
  241. package/dist/core/session/env-file.js +105 -0
  242. package/dist/core/session/section-budgets.js +140 -0
  243. package/dist/core/session.js +92 -0
  244. package/dist/core/settings.js +324 -5
  245. package/dist/core/share/formatter.js +271 -0
  246. package/dist/core/share/redactor.js +221 -0
  247. package/dist/core/share/uploader.js +267 -0
  248. package/dist/core/skills/defaults.js +30 -30
  249. package/dist/core/skills/loader.js +22 -22
  250. package/dist/core/skills/sources.js +27 -27
  251. package/dist/core/smoke/headless-driver.js +174 -0
  252. package/dist/core/smoke/orchestrator.js +194 -0
  253. package/dist/core/smoke/runner.js +238 -0
  254. package/dist/core/smoke/scenario-parser.js +316 -0
  255. package/dist/core/statusline.js +99 -0
  256. package/dist/core/subagents/dispatcher-real.js +600 -0
  257. package/dist/core/subagents/dispatcher.js +132 -43
  258. package/dist/core/subagents/index.js +19 -6
  259. package/dist/core/subagents/isolation-matrix.js +213 -0
  260. package/dist/core/subagents/spawn.js +19 -4
  261. package/dist/core/telemetry/emitter.js +229 -0
  262. package/dist/core/telemetry/queue.js +251 -0
  263. package/dist/core/theme/context.js +91 -0
  264. package/dist/core/theme/presets.js +228 -0
  265. package/dist/core/theme/state.js +181 -0
  266. package/dist/core/todos/invariant.js +10 -0
  267. package/dist/core/todos/state.js +177 -0
  268. package/dist/core/tool-schema/compressor.js +89 -0
  269. package/dist/core/transport/version-interceptor.js +166 -0
  270. package/dist/core/trust.js +2 -2
  271. package/dist/core/tui/thinking-block.js +64 -0
  272. package/dist/core/vim/keymap.js +288 -0
  273. package/dist/core/vim/state.js +92 -0
  274. package/dist/core/watch-markers/marker-watcher.js +133 -0
  275. package/dist/core/worktree/include-parser.js +249 -0
  276. package/dist/core/worktree-manager/cleanup.js +123 -0
  277. package/dist/core/worktree-manager/manager.js +303 -0
  278. package/dist/index.js +36 -0
  279. package/dist/runtime/bootstrap.js +190 -0
  280. package/dist/runtime/cli.js +4185 -549
  281. package/dist/runtime/commands/agents.js +31 -31
  282. package/dist/runtime/commands/budget.js +5 -5
  283. package/dist/runtime/commands/cancel.js +231 -0
  284. package/dist/runtime/commands/chain.js +489 -0
  285. package/dist/runtime/commands/codegraph-status.js +227 -0
  286. package/dist/runtime/commands/compact.js +297 -0
  287. package/dist/runtime/commands/config.js +73 -39
  288. package/dist/runtime/commands/cost.js +199 -0
  289. package/dist/runtime/commands/delegate.js +27 -4
  290. package/dist/runtime/commands/dispatch.js +126 -0
  291. package/dist/runtime/commands/doctor.js +579 -0
  292. package/dist/runtime/commands/feedback.js +184 -0
  293. package/dist/runtime/commands/hooks.js +187 -0
  294. package/dist/runtime/commands/init.js +254 -0
  295. package/dist/runtime/commands/lsp.js +200 -38
  296. package/dist/runtime/commands/mcp.js +879 -0
  297. package/dist/runtime/commands/memory.js +582 -0
  298. package/dist/runtime/commands/model.js +237 -0
  299. package/dist/runtime/commands/onboarding.js +275 -0
  300. package/dist/runtime/commands/patch.js +12 -12
  301. package/dist/runtime/commands/permissions.js +112 -0
  302. package/dist/runtime/commands/plan.js +143 -0
  303. package/dist/runtime/commands/prd-check.js +285 -0
  304. package/dist/runtime/commands/privacy.js +17 -17
  305. package/dist/runtime/commands/recipe.js +325 -0
  306. package/dist/runtime/commands/redo-blob-store.js +92 -0
  307. package/dist/runtime/commands/redo.js +361 -0
  308. package/dist/runtime/commands/release-notes.js +229 -0
  309. package/dist/runtime/commands/repo-map.js +95 -0
  310. package/dist/runtime/commands/report.js +299 -0
  311. package/dist/runtime/commands/resume.js +118 -0
  312. package/dist/runtime/commands/review-consensus.js +68 -53
  313. package/dist/runtime/commands/rewind.js +333 -0
  314. package/dist/runtime/commands/roster.js +14 -14
  315. package/dist/runtime/commands/sessions.js +163 -0
  316. package/dist/runtime/commands/share.js +316 -0
  317. package/dist/runtime/commands/skills.js +31 -31
  318. package/dist/runtime/commands/status.js +186 -0
  319. package/dist/runtime/commands/stickers.js +82 -0
  320. package/dist/runtime/commands/style.js +194 -0
  321. package/dist/runtime/commands/theme.js +196 -0
  322. package/dist/runtime/commands/undo.js +54 -22
  323. package/dist/runtime/commands/update.js +289 -0
  324. package/dist/runtime/commands/vim.js +140 -0
  325. package/dist/runtime/commands/worktree.js +8 -8
  326. package/dist/runtime/commands/worktrees.js +155 -0
  327. package/dist/runtime/headless-repl.js +195 -0
  328. package/dist/runtime/headless.js +543 -0
  329. package/dist/runtime/load-hooks-or-exit.js +71 -0
  330. package/dist/runtime/plan-decompose.js +22 -22
  331. package/dist/runtime/sigint-guard.js +272 -0
  332. package/dist/runtime/update-check.js +28 -28
  333. package/dist/runtime/version.js +65 -0
  334. package/dist/runtime/worktree-bootstrap.js +579 -0
  335. package/dist/skills/bundled/batch.js +617 -0
  336. package/dist/skills/bundled/index.js +45 -0
  337. package/dist/skills/bundled/loop.js +358 -0
  338. package/dist/skills/bundled/remember.js +383 -0
  339. package/dist/skills/bundled/simplify.js +289 -0
  340. package/dist/skills/bundled/skillify.js +373 -0
  341. package/dist/skills/bundled/stuck.js +558 -0
  342. package/dist/skills/bundled/verify.js +439 -0
  343. package/dist/testing/vcr.js +486 -0
  344. package/dist/tools/agent-tool.js +229 -0
  345. package/dist/tools/apply-patch.js +89 -28
  346. package/dist/tools/ask-user-question.js +337 -0
  347. package/dist/tools/ask-user.js +115 -0
  348. package/dist/tools/bash.js +624 -46
  349. package/dist/tools/brief.js +224 -0
  350. package/dist/tools/cron.js +433 -0
  351. package/dist/tools/enter-worktree.js +250 -0
  352. package/dist/tools/exit-worktree.js +147 -0
  353. package/dist/tools/file-tools.js +161 -44
  354. package/dist/tools/lsp-tools.js +377 -1
  355. package/dist/tools/mcp-tool.js +260 -0
  356. package/dist/tools/multi-edit.js +361 -0
  357. package/dist/tools/powershell.js +268 -0
  358. package/dist/tools/registry.js +99 -4
  359. package/dist/tools/skill-tool.js +96 -0
  360. package/dist/tools/sleep.js +99 -0
  361. package/dist/tools/synthetic-output.js +133 -0
  362. package/dist/tools/tasks.js +208 -0
  363. package/dist/tools/todo-write.js +184 -0
  364. package/dist/tools/verify-plan-execution.js +295 -0
  365. package/dist/tools/web-fetch-injection-scanner.js +207 -0
  366. package/dist/tools/web-fetch.js +195 -10
  367. package/dist/tools/web-search.js +458 -0
  368. package/dist/tui/agent-progress-card.js +111 -0
  369. package/dist/tui/agent-tree.js +11 -1
  370. package/dist/tui/ask-modal.js +14 -14
  371. package/dist/tui/ask-user-question-chips.js +315 -0
  372. package/dist/tui/ask-user-question-prompt.js +203 -0
  373. package/dist/tui/compact-banner.js +81 -0
  374. package/dist/tui/conversation-pane.js +85 -11
  375. package/dist/tui/cost-table.js +111 -0
  376. package/dist/tui/device-flow.js +2 -2
  377. package/dist/tui/doctor-table.js +46 -0
  378. package/dist/tui/feedback-prompt.js +156 -0
  379. package/dist/tui/input-box.js +247 -32
  380. package/dist/tui/login-picker.js +3 -3
  381. package/dist/tui/markdown-render.js +6 -6
  382. package/dist/tui/multi-file-diff-approval.js +375 -0
  383. package/dist/tui/onboarding-wizard.js +240 -0
  384. package/dist/tui/permissions-picker.js +86 -0
  385. package/dist/tui/render.js +36 -1
  386. package/dist/tui/repl-render.js +176 -25
  387. package/dist/tui/repl-splash-art.js +16 -16
  388. package/dist/tui/repl-splash-mascot.js +48 -24
  389. package/dist/tui/repl-splash.js +22 -22
  390. package/dist/tui/repl.js +125 -45
  391. package/dist/tui/slash-palette.js +6 -6
  392. package/dist/tui/splash.js +2 -2
  393. package/dist/tui/status-bar.js +109 -31
  394. package/dist/tui/status-table.js +7 -0
  395. package/dist/tui/stickers-art.js +136 -0
  396. package/dist/tui/style-table.js +28 -0
  397. package/dist/tui/theme-table.js +29 -0
  398. package/dist/tui/thinking-spinner.js +123 -0
  399. package/dist/tui/tool-stream-pane.js +53 -4
  400. package/dist/tui/update-banner.js +27 -2
  401. package/dist/tui/vim-input.js +267 -0
  402. package/dist/tui/welcome-banner.js +107 -0
  403. package/dist/tui/welcome-data.js +293 -0
  404. package/dist/tui/workspace-context.js +2 -2
  405. package/package.json +31 -16
  406. package/test/scenarios/codegen-create-file.scenario.txt +13 -0
  407. package/test/scenarios/compact-force.scenario.txt +12 -0
  408. package/test/scenarios/identity.scenario.txt +12 -0
  409. package/test/scenarios/persona-handoff.scenario.txt +12 -0
  410. package/test/scenarios/walkback.scenario.txt +12 -0
  411. package/dist/core/engine/compaction-hook.js +0 -154
@@ -1,27 +1,27 @@
1
1
  import { jsx as _jsx, jsxs as _jsxs } from "react/jsx-runtime";
2
2
  /**
3
- * REPL input box - Sprint α6.14 (REPL UX P0 wave 1).
3
+ * REPL input box - Sprint (REPL UX P0 wave 1).
4
4
  *
5
- * Bordered, cursor-aware input box matching Claude Code / Codex CLI
6
- * aesthetics. Layered upgrade over α5.7:
5
+ * Bordered, cursor-aware input box matching the upstream tool / peer CLI
6
+ * aesthetics. Layered upgrade over :
7
7
  *
8
- * - Top divider (full-width cyan rule) anchors the input below the
9
- * main pane and gives the operator a clear visual seam.
10
- * - Rounded cyan border wraps the prompt + line + cursor.
11
- * - Cursor follows the caret position (left/right arrows + Home/End
12
- * reposition without losing the trailing text).
13
- * - Single-arrow `›` prompt in brand cyan; dim continuation prompt
14
- * `┊` when the input wraps past the available width so the operator
15
- * sees that they are still inside one logical line.
16
- * - History navigation (↑/↓), slash palette inline suggestion, Esc
17
- * cancel, Ctrl+C ×2 exit remain wired identically to α5.7.
8
+ * - Top divider (full-width cyan rule) anchors the input below the
9
+ * main pane and gives the operator a clear visual seam.
10
+ * - Rounded cyan border wraps the prompt + line + cursor.
11
+ * - Cursor follows the caret position (left/right arrows + Home/End
12
+ * reposition without losing the trailing text).
13
+ * - Single-arrow `›` prompt in brand cyan; dim continuation prompt
14
+ * `┊` when the input wraps past the available width so the operator
15
+ * sees that they are still inside one logical line.
16
+ * - History navigation (↑/↓), slash palette inline suggestion, Esc
17
+ * cancel, Ctrl+C ×2 exit remain wired identically to .
18
18
  *
19
19
  * State that belongs in this component:
20
- * - `line` (string) - current buffer
21
- * - `cursor` (number) - caret offset into `line`
22
- * - `history` (string[]) - session-local; persistence lands in
23
- * commit 2 (per-workspace JSONL).
24
- * - `historyIndex` (number) - -1 when not navigating
20
+ * - `line` (string) - current buffer
21
+ * - `cursor` (number) - caret offset into `line`
22
+ * - `history` (string[]) - session-local; persistence lands in
23
+ * commit 2 (per-workspace JSONL).
24
+ * - `historyIndex` (number) - -1 when not navigating
25
25
  *
26
26
  * Brand voice gate: no forbidden words. ASCII-only glyphs.
27
27
  */
@@ -33,6 +33,14 @@ import { SlashPalette, completePalette, filterPalette, } from './slash-palette.j
33
33
  import { EMPTY_KILL_RING, killToLineEnd, killToLineStart, killWordBackward, yankAtCursor, } from '../core/repl/kill-ring.js';
34
34
  import { readClipboard } from '../core/repl/clipboard-read.js';
35
35
  const CTRL_C_DOUBLE_TAP_MS = 1_000;
36
+ /**
37
+ * BT 8 (the upstream tool parity): Esc-Esc walks the conversation back
38
+ * one turn. 500ms is tight enough that an operator clearing the buffer +
39
+ * later changing their mind does NOT accidentally pop a turn, while
40
+ * still feeling like one motion. Matches the upstream tool's documented
41
+ * double-Esc window.
42
+ */
43
+ const ESCAPE_DOUBLE_TAP_MS = 500;
36
44
  /** Width subtracted from the terminal width so the border + padding fit. */
37
45
  const FRAME_OVERHEAD_COLUMNS = 4;
38
46
  /** Fallback width when ink cannot read stdout (e.g. test harness). */
@@ -75,6 +83,18 @@ export function InputBox(props) {
75
83
  const [history, setHistory] = useState(seededHistory);
76
84
  const [historyIndex, setHistoryIndex] = useState(-1);
77
85
  const [lastCtrlCAt, setLastCtrlCAt] = useState(undefined);
86
+ // CEO P0 #2 : the upstream tool parity — surface а visible
87
+ // "Press Ctrl+C again to exit" toast on the first Ctrl+C press so
88
+ // the operator knows the second press will terminate the REPL.
89
+ // Auto-clears after CTRL_C_DOUBLE_TAP_MS so it never lingers past
90
+ // the double-tap window.
91
+ const [ctrlCToast, setCtrlCToast] = useState(null);
92
+ const ctrlCToastTimerRef = useRef(null);
93
+ // BT 8: Esc-Esc walkback double-tap window. Tracks the epoch
94
+ // ms of the most recent Esc press so the next Esc within
95
+ // ESCAPE_DOUBLE_TAP_MS triggers the walkback handler instead of
96
+ // re-clearing the buffer.
97
+ const [lastEscapeAt, setLastEscapeAt] = useState(undefined);
78
98
  const [cursorVisible, setCursorVisible] = useState(true);
79
99
  // Ctrl+R / Ctrl+S reverse-search mode. Undefined when idle, a
80
100
  // HistorySearchState while the operator is searching.
@@ -94,6 +114,11 @@ export function InputBox(props) {
94
114
  // panes when Ctrl+L wipes the terminal (the parent React tree is
95
115
  // otherwise stable and would not redraw on a stdout.write alone).
96
116
  const [, setRedrawTick] = useState(0);
117
+ // Shift+Tab toast — flashed for 2s after a mode cycle so the
118
+ // operator sees `Mode → acceptEdits` под the input divider. Cleared
119
+ // by a setTimeout so a quick second Shift+Tab refreshes the toast.
120
+ const [modeCycleToast, setModeCycleToast] = useState(null);
121
+ const modeCycleTimerRef = useRef(null);
97
122
  const now = props.now ?? Date.now;
98
123
  const { stdout } = useStdout();
99
124
  const columns = stdout?.columns ?? FALLBACK_COLUMNS;
@@ -131,7 +156,7 @@ export function InputBox(props) {
131
156
  useInput((input, key) => {
132
157
  if (key.ctrl && input === 'c') {
133
158
  const t = now();
134
- // α6.9: Claude Code-style double-press semantics. First Ctrl+C
159
+ // : the upstream tool-style double-press semantics. First Ctrl+C
135
160
  // ALWAYS attempts to cancel an in-flight dispatch (when the
136
161
  // session reports non-idle); second Ctrl+C within 1s exits the
137
162
  // process. If onCancel is omitted (legacy callers, tests), the
@@ -140,7 +165,7 @@ export function InputBox(props) {
140
165
  const withinDoubleTapWindow = typeof lastCtrlCAt === 'number' && t - lastCtrlCAt <= CTRL_C_DOUBLE_TAP_MS;
141
166
  if (withinDoubleTapWindow) {
142
167
  // Second press inside the window — always exit. This matches
143
- // Claude Code: even mid-dispatch, the second Ctrl+C wins so
168
+ // the upstream tool: even mid-dispatch, the second Ctrl+C wins so
144
169
  // the operator can always escape a stuck REPL.
145
170
  props.onExit();
146
171
  return;
@@ -152,13 +177,13 @@ export function InputBox(props) {
152
177
  // tool is running).
153
178
  //
154
179
  // Three-valued onCancel return (see prop docstring):
155
- // - true → dispatch cancelled, keep buffer, arm exit timer
156
- // - false → idle, clear buffer (legacy), arm exit timer
157
- // - undefined → handler bypassed (modal owns input); NO state
158
- // change at all. Buffer stays, exit timer NOT
159
- // armed (otherwise the modal would silently
160
- // promote a Ctrl+C to "press again to exit",
161
- // which is wrong context for a modal cancel).
180
+ // - true → dispatch cancelled, keep buffer, arm exit timer
181
+ // - false → idle, clear buffer (legacy), arm exit timer
182
+ // - undefined → handler bypassed (modal owns input); NO state
183
+ // change at all. Buffer stays, exit timer NOT
184
+ // armed (otherwise the modal would silently
185
+ // promote a Ctrl+C to "press again to exit",
186
+ // which is wrong context for a modal cancel).
162
187
  let cancelResult;
163
188
  if (props.onCancel) {
164
189
  cancelResult = props.onCancel();
@@ -173,6 +198,28 @@ export function InputBox(props) {
173
198
  return;
174
199
  }
175
200
  setLastCtrlCAt(t);
201
+ // CEO P0 #2 : surface the "Press Ctrl+C again to
202
+ // exit" toast on the first press so the operator sees the
203
+ // double-tap semantics in the UI, not just в the bottom hint
204
+ // line. Mirrors the standard tool's exit affordance verbatim. The
205
+ // toast string varies by which branch fired (cancel vs idle
206
+ // clear) so the operator learns what the press just did:
207
+ //
208
+ // - cancelResult === true → "Aborted. Press Ctrl+C again to exit."
209
+ // - cancelResult === false → "Press Ctrl+C again to exit."
210
+ //
211
+ // (The undefined branch already returned above — а modal owns
212
+ // input и the toast is suppressed.)
213
+ const toastCopy = cancelResult === true
214
+ ? 'Aborted. Press Ctrl+C again to exit.'
215
+ : 'Press Ctrl+C again to exit.';
216
+ setCtrlCToast(toastCopy);
217
+ if (ctrlCToastTimerRef.current)
218
+ clearTimeout(ctrlCToastTimerRef.current);
219
+ ctrlCToastTimerRef.current = setTimeout(() => {
220
+ setCtrlCToast(null);
221
+ ctrlCToastTimerRef.current = null;
222
+ }, CTRL_C_DOUBLE_TAP_MS);
176
223
  // Legacy behaviour: on idle (or no onCancel wired), clear the
177
224
  // buffer + reset search so the operator's screen is calm before
178
225
  // they confirm exit. When we DID cancel a live dispatch, keep
@@ -184,6 +231,24 @@ export function InputBox(props) {
184
231
  }
185
232
  return;
186
233
  }
234
+ // — the upstream tool parity: Shift+Tab cycles permission mode.
235
+ // The host owns the cycle logic + persistence; we just intercept
236
+ // the chord and surface a one-line toast on success. Place this
237
+ // BEFORE the search-mode and palette branches so a Shift+Tab fires
238
+ // even while reverse-search is active (operator habit-driven).
239
+ if (key.shift && key.tab && props.onCyclePermissionMode) {
240
+ const nextMode = props.onCyclePermissionMode();
241
+ if (nextMode) {
242
+ setModeCycleToast(`Mode → ${nextMode}`);
243
+ if (modeCycleTimerRef.current)
244
+ clearTimeout(modeCycleTimerRef.current);
245
+ modeCycleTimerRef.current = setTimeout(() => {
246
+ setModeCycleToast(null);
247
+ modeCycleTimerRef.current = null;
248
+ }, 2_000);
249
+ }
250
+ return;
251
+ }
187
252
  // Search-mode key handling. Ctrl+R / Ctrl+S cycle, Enter accepts,
188
253
  // Esc cancels (restoring the pre-search draft), backspace shortens
189
254
  // the query, typed characters extend it.
@@ -202,7 +267,9 @@ export function InputBox(props) {
202
267
  setCursor(draftBeforeSearch.length);
203
268
  return;
204
269
  }
205
- if (key.return) {
270
+ // Bare LF accepts the focused match, same as CR (`key.return`).
271
+ // See the post-search block below for the rationale.
272
+ if (key.return || (input === '\n' && !key.meta && !key.ctrl && !key.shift)) {
206
273
  const picked = currentBrief(search);
207
274
  setSearch(undefined);
208
275
  if (picked !== null) {
@@ -221,6 +288,11 @@ export function InputBox(props) {
221
288
  return;
222
289
  }
223
290
  if (input && !key.meta && !key.ctrl) {
291
+ // Drop a bare LF from the search query — the Enter-accept
292
+ // branch above already handled it; falling through here would
293
+ // splice a newline into the search string.
294
+ if (input === '\n')
295
+ return;
224
296
  const nextQuery = search.query + input;
225
297
  setSearch(applyQuery(search, nextQuery, history));
226
298
  return;
@@ -243,6 +315,118 @@ export function InputBox(props) {
243
315
  setSearch(initialSearchState(history));
244
316
  return;
245
317
  }
318
+ // P0 fix (CEO dogfood, second iteration): bare LF (`\n`)
319
+ // MUST submit the brief, same as bare CR (`\r`). Ink's parseKeypress
320
+ // maps `\r` to `key.return` and `\n` to `key.name === 'enter'`
321
+ // WITHOUT setting `key.return`. Most real terminals deliver CR for
322
+ // Enter (ICRNL on by default), so the `key.return` branch below
323
+ // catches them. But when stdin is a PTY whose parent writes raw
324
+ // `\n` (Python's `pty.fork` + `os.write(fd, b"\n")`, automation
325
+ // harnesses, certain SSH multiplexers), the LF arrives as a
326
+ // printable char.
327
+ //
328
+ // PR (beta.45) fixed the case where `input === '\n'` exactly.
329
+ // CEO PTY smoke surfaced the REAL shape: when the parent
330
+ // writes the brief AND the Enter as separate `os.write` calls (or
331
+ // even when it doesn't), Node's stdin buffer COALESCES them into
332
+ // ONE chunk before Ink delivers the `useInput` event. The repro
333
+ // confirmed via stderr instrumentation: typing `hi\n` arrives in
334
+ // input-box as `bytes=[68 69 0a] len=3 flags=-` — a SINGLE 3-char
335
+ // chunk "hi\n" with no key flags. The PR branch (`input ===
336
+ // '\n'`) does not match, so `hi\n` falls through to the printable-
337
+ // char branch and the literal newline lands in the buffer as
338
+ // `› hi\n █` (multi-line composer, brief never dispatches, status
339
+ // stays `idle` forever).
340
+ //
341
+ // Fix: detect a TRAILING `\n` in a printable chunk with no
342
+ // modifiers — type the prefix into the buffer, then submit. The
343
+ // discriminator that keeps multi-line paste working: the chunk
344
+ // must contain EXACTLY ONE `\n` (the trailing one) and no other
345
+ // newlines. Multi-line pastes have ≥2 `\n` characters (or arrive
346
+ // wrapped in bracketed-paste markers handled below), so they
347
+ // still preserve interior newlines via the printable-char branch.
348
+ //
349
+ // Detection contract:
350
+ // - `input` ends with `\n`
351
+ // - no Ctrl / Meta / Shift modifiers
352
+ // - exactly ONE `\n` in the chunk (the trailing one)
353
+ // - chunk is not bracketed-paste wrapped (markers stripped below)
354
+ //
355
+ // Edge cases covered by `test/input-box-lf-submit.spec.tsx`:
356
+ // - bare `\n` → submit empty (no-op on empty buf)
357
+ // - `hi\n` → splice `hi` + submit
358
+ // - `hi\nthere\n` (multi-line) → printable branch, preserves \n
359
+ // - `\r` (CR) → key.return branch unchanged
360
+ // - `hi\r\n` (CRLF) → key.return branch (CR wins first)
361
+ const endsWithLf = input.length > 0 && input.charCodeAt(input.length - 1) === 0x0a;
362
+ const newlineCount = (input.match(/\n/g) || []).length;
363
+ if (endsWithLf
364
+ && newlineCount === 1
365
+ && !key.meta
366
+ && !key.ctrl
367
+ && !key.shift) {
368
+ // Splice the prefix (everything before the trailing `\n`) into
369
+ // the buffer at the cursor, then run the canonical submit path.
370
+ // Refs (cursorRef / lineRef) hold the latest committed values so
371
+ // the splice runs against the operator's most recent edits even
372
+ // if a previous async paste / setState is still mid-flight.
373
+ const prefix = input.slice(0, -1);
374
+ let mergedLine = lineRef.current;
375
+ let mergedCursor = cursorRef.current;
376
+ if (prefix.length > 0) {
377
+ // Same sanitisation as the printable-char branch below — strip
378
+ // bracketed-paste markers so a stray escape sequence never
379
+ // lands in the submitted brief.
380
+ const stripped = prefix
381
+ .replace(/\x1b\[200~/g, '')
382
+ .replace(/\x1b\[201~/g, '')
383
+ .replace(/\[200~/g, '')
384
+ .replace(/\[201~/g, '');
385
+ if (stripped.length > 0) {
386
+ mergedLine =
387
+ mergedLine.slice(0, mergedCursor) + stripped + mergedLine.slice(mergedCursor);
388
+ mergedCursor = mergedCursor + stripped.length;
389
+ }
390
+ }
391
+ // Synthesise the same payload-shape the `key.return` branch
392
+ // below uses so palette completion + history dedup + onSubmit
393
+ // dispatch all run identically.
394
+ const paletteHere = !paletteSuppressed
395
+ ? filterPalette(mergedLine)
396
+ : { rows: [], totalBeforeLimit: 0 };
397
+ const paletteOpenHere = paletteHere.rows.length > 0;
398
+ const paletteFocusedIndexHere = paletteHere.rows.length === 0
399
+ ? 0
400
+ : Math.min(paletteIndex, paletteHere.rows.length - 1);
401
+ let payload = mergedLine;
402
+ if (paletteOpenHere) {
403
+ const completed = completePalette(mergedLine, paletteHere.rows, paletteFocusedIndexHere);
404
+ if (completed !== null)
405
+ payload = completed;
406
+ }
407
+ const trimmed = payload.trim();
408
+ if (trimmed.length > 0) {
409
+ setHistory((prev) => {
410
+ if (prev[prev.length - 1] === trimmed)
411
+ return prev;
412
+ return [...prev, trimmed];
413
+ });
414
+ setHistoryIndex(-1);
415
+ if (props.workspaceSlug) {
416
+ appendHistory({
417
+ home: props.historyHome,
418
+ workspaceSlug: props.workspaceSlug,
419
+ brief: trimmed,
420
+ });
421
+ }
422
+ props.onSubmit(trimmed);
423
+ }
424
+ setLine('');
425
+ setCursor(0);
426
+ setPaletteSuppressed(false);
427
+ setPaletteIndex(0);
428
+ return;
429
+ }
246
430
  // Readline-style kill ring shortcuts. All four kills push the
247
431
  // removed slice onto the ring; Ctrl+Y yanks the most recent.
248
432
  if (key.ctrl && input === 'u') {
@@ -375,10 +559,41 @@ export function InputBox(props) {
375
559
  if (key.escape) {
376
560
  if (paletteOpen) {
377
561
  // Close the palette without clearing the buffer so the operator
378
- // can still send `/help` as plain text if they want.
562
+ // can still send `/help` as plain text if they want. Palette
563
+ // takes precedence over walkback because the operator's mental
564
+ // model is "Esc closes the visible overlay first".
379
565
  setPaletteSuppressed(true);
566
+ setLastEscapeAt(undefined);
567
+ return;
568
+ }
569
+ // BT 8: Esc-Esc walkback. Two presses within
570
+ // ESCAPE_DOUBLE_TAP_MS step the conversation back by one turn.
571
+ // First press still clears the buffer (legacy behaviour for the
572
+ // single-Esc cancel UX); the second press calls the host's
573
+ // walkback handler. Buffer-clear on the first press is what makes
574
+ // the double-tap feel "free" - the operator did not have to
575
+ // memorise a new chord; they just have to keep pressing.
576
+ const tEsc = now();
577
+ const withinEscapeWindow = typeof lastEscapeAt === 'number'
578
+ && tEsc - lastEscapeAt <= ESCAPE_DOUBLE_TAP_MS;
579
+ if (withinEscapeWindow && props.onWalkback) {
580
+ // Second tap inside the window. Buffer was already cleared on
581
+ // the first press, so the host sees a clean input box AND the
582
+ // walkback result. We clear the window so a third tap restarts
583
+ // the cycle (no run-on walkbacks from a stuck Esc key).
584
+ const verdict = props.onWalkback();
585
+ setLastEscapeAt(undefined);
586
+ if (verdict !== 'walked-back') {
587
+ // Host refused (dispatch in flight, no turns to pop). The
588
+ // host owns the refusal copy via its own writeOutput path;
589
+ // we do not double-message here.
590
+ return;
591
+ }
380
592
  return;
381
593
  }
594
+ // First Esc (or no walkback wired). Arm the window + clear the
595
+ // buffer per the long-standing single-Esc cancel contract.
596
+ setLastEscapeAt(tEsc);
382
597
  setLine('');
383
598
  setCursor(0);
384
599
  setHistoryIndex(-1);
@@ -442,7 +657,7 @@ export function InputBox(props) {
442
657
  // Read cursor via ref inside the updater so the slice indices come
443
658
  // from the latest committed value, not the closure-captured one.
444
659
  // Same React-18 strict-mode race that bit the Ctrl+V paste path
445
- // (Claude P1 on PR #335 wave 1): updaters run twice under strict
660
+ // (Claude P1 on PR wave 1): updaters run twice under strict
446
661
  // mode, and a stale closure `cursor` produces a double-edit on the
447
662
  // second invocation. cursorRef is the canonical fix — do NOT
448
663
  // re-introduce closure `cursor` inside setLine updaters.
@@ -479,7 +694,7 @@ export function InputBox(props) {
479
694
  // Read cursor via ref inside the updater so the splice indices come
480
695
  // from the latest committed value, not the closure-captured one.
481
696
  // Same React-18 strict-mode race that bit the Ctrl+V paste path
482
- // (Claude P1 on PR #335 wave 1): updaters run twice under strict
697
+ // (Claude P1 on PR wave 1): updaters run twice under strict
483
698
  // mode, and a stale closure `cursor` produces a duplicated insert
484
699
  // on the second invocation. cursorRef is the canonical fix — do
485
700
  // NOT re-introduce closure `cursor` inside setLine updaters.
@@ -499,7 +714,7 @@ export function InputBox(props) {
499
714
  : Math.min(paletteIndex, paletteView.rows.length - 1);
500
715
  const divider = '─'.repeat(innerWidth);
501
716
  const focusedMatch = search ? search.matches[search.focusedIndex] : undefined;
502
- return (_jsxs(Box, { flexDirection: "column", children: [_jsx(Text, { color: "cyan", dimColor: true, children: divider }), _jsx(Box, { paddingX: 1, flexDirection: "column", children: search ? (_jsxs(Box, { flexDirection: "column", children: [_jsxs(Box, { children: [_jsx(Text, { color: "cyan", children: '(reverse-i-search) ' }), _jsx(Text, { children: `\`${search.query}\`: ` }), _jsx(Text, { color: "yellow", children: focusedMatch ? focusedMatch.brief : '(no match)' })] }), _jsx(Box, { children: _jsx(Text, { dimColor: true, children: `Ctrl+R next · Ctrl+S prev · Enter accept · Esc cancel · ${search.matches.length} match${search.matches.length === 1 ? '' : 'es'}` }) })] })) : (_jsxs(Box, { children: [_jsx(Text, { color: "cyan", children: '› ' }), _jsx(Text, { children: renderLineWithCursor(line, cursor, cursorVisible) })] })) }), _jsx(Text, { color: "cyan", dimColor: true, children: divider }), line.length > innerWidth - 4 ? (_jsxs(Box, { children: [_jsx(Text, { color: "gray", children: '┊ ' }), _jsx(Text, { dimColor: true, children: 'line wraps - Enter still submits' })] })) : null, _jsx(SlashPalette, { rows: paletteView.rows, focusedIndex: clampedPaletteIndex, totalBeforeLimit: paletteView.totalBeforeLimit }), _jsx(Box, { children: _jsx(Text, { dimColor: true, children: '↑/↓ history · Ctrl+R search · / commands · Enter brief · Esc cancel · Ctrl+C abort / ×2 exit' }) })] }));
717
+ return (_jsxs(Box, { flexDirection: "column", children: [_jsx(Text, { color: "#3da9fc", dimColor: true, children: divider }), _jsx(Box, { paddingX: 1, flexDirection: "column", children: search ? (_jsxs(Box, { flexDirection: "column", children: [_jsxs(Box, { children: [_jsx(Text, { color: "#3da9fc", children: '(reverse-i-search) ' }), _jsx(Text, { children: `\`${search.query}\`: ` }), _jsx(Text, { color: "yellow", children: focusedMatch ? focusedMatch.brief : '(no match)' })] }), _jsx(Box, { children: _jsx(Text, { dimColor: true, children: `Ctrl+R next · Ctrl+S prev · Enter accept · Esc cancel · ${search.matches.length} match${search.matches.length === 1 ? '' : 'es'}` }) })] })) : (_jsxs(Box, { children: [_jsx(Text, { color: "#3da9fc", children: '› ' }), _jsx(Text, { children: renderLineWithCursor(line, cursor, cursorVisible) })] })) }), _jsx(Text, { color: "#3da9fc", dimColor: true, children: divider }), modeCycleToast ? (_jsx(Box, { children: _jsx(Text, { color: "#3da9fc", bold: true, children: ` ${modeCycleToast}` }) })) : null, ctrlCToast ? (_jsx(Box, { children: _jsx(Text, { color: "yellow", bold: true, children: ` ${ctrlCToast}` }) })) : null, line.length > innerWidth - 4 ? (_jsxs(Box, { children: [_jsx(Text, { color: "gray", children: '┊ ' }), _jsx(Text, { dimColor: true, children: 'line wraps - Enter still submits' })] })) : null, _jsx(SlashPalette, { rows: paletteView.rows, focusedIndex: clampedPaletteIndex, totalBeforeLimit: paletteView.totalBeforeLimit }), _jsx(Box, { children: _jsx(Text, { dimColor: true, children: '↑/↓ history · Ctrl+R search · / commands · Shift+Tab mode · Enter brief · Esc cancel · Ctrl+C abort / ×2 exit' }) })] }));
503
718
  }
504
719
  /**
505
720
  * Render the line with the cursor glyph inserted at `cursor`. The cursor
@@ -54,15 +54,15 @@ export function LoginPicker(props) {
54
54
  if (input === '3')
55
55
  props.onSelect('env');
56
56
  });
57
- return (_jsxs(Box, { flexDirection: "column", paddingX: 2, paddingY: 1, children: [_jsxs(Box, { children: [_jsx(Text, { bold: true, children: "Sign in to Pugi" }), _jsx(Text, { dimColor: true, children: ` (endpoint: ${props.apiUrl})` })] }), _jsx(Box, { marginTop: 1, flexDirection: "column", children: ITEMS.map((item, itemIndex) => {
57
+ return (_jsxs(Box, { flexDirection: "column", paddingX: 2, paddingY: 1, children: [_jsxs(Box, { children: [_jsx(Text, { bold: true, children: "Sign in to Pugi" }), _jsx(Text, { dimColor: true, children: ` (endpoint: ${props.apiUrl})` })] }), _jsx(Box, { marginTop: 1, flexDirection: "column", children: ITEMS.map((item, itemIndex) => {
58
58
  const isSelected = itemIndex === index;
59
59
  return (_jsx(PickerRow, { isSelected: isSelected, title: item.title, hint: item.hint }, item.provider));
60
- }) }), _jsx(Box, { marginTop: 1, children: _jsx(Text, { dimColor: true, children: '↑/↓ select Enter confirm Esc cancel' }) })] }));
60
+ }) }), _jsx(Box, { marginTop: 1, children: _jsx(Text, { dimColor: true, children: '↑/↓ select Enter confirm Esc cancel' }) })] }));
61
61
  }
62
62
  function PickerRow({ isSelected, title, hint, }) {
63
63
  // Arrow glyph + padded title so highlighted and dim rows share
64
64
  // column alignment.
65
- const indicator = isSelected ? '▸ ' : ' ';
65
+ const indicator = isSelected ? '▸ ' : ' ';
66
66
  const padded = title.padEnd(22, ' ');
67
67
  return (_jsxs(Text, { children: [_jsxs(Text, { color: isSelected ? 'cyan' : undefined, bold: isSelected, children: [indicator, padded] }), _jsx(Text, { dimColor: true, children: hint })] }));
68
68
  }
@@ -95,7 +95,7 @@ function parseBlocks(source) {
95
95
  return blocks;
96
96
  }
97
97
  /* ------------------------------------------------------------------ */
98
- /* Block renderers */
98
+ /* Block renderers */
99
99
  /* ------------------------------------------------------------------ */
100
100
  function renderBlock(block, key) {
101
101
  switch (block.kind) {
@@ -107,9 +107,9 @@ function renderBlock(block, key) {
107
107
  case 'paragraph':
108
108
  return (_jsx(Text, { children: renderInline(block.text) }, key));
109
109
  case 'bullet':
110
- return (_jsxs(Box, { children: [_jsx(Text, { color: "cyan", children: '• ' }), _jsx(Text, { children: renderInline(block.text) })] }, key));
110
+ return (_jsxs(Box, { children: [_jsx(Text, { color: "#3da9fc", children: '• ' }), _jsx(Text, { children: renderInline(block.text) })] }, key));
111
111
  case 'ordered':
112
- return (_jsxs(Box, { children: [_jsx(Text, { color: "cyan", children: `${block.index}. ` }), _jsx(Text, { children: renderInline(block.text) })] }, key));
112
+ return (_jsxs(Box, { children: [_jsx(Text, { color: "#3da9fc", children: `${block.index}. ` }), _jsx(Text, { children: renderInline(block.text) })] }, key));
113
113
  case 'code':
114
114
  return renderCodeBlock(block.lang, block.body, key);
115
115
  case 'blank':
@@ -148,7 +148,7 @@ function renderCodeLine(line, keywords) {
148
148
  spans.push(_jsx(Text, { color: "green", children: tok }, key));
149
149
  }
150
150
  else if (keywords.includes(tok)) {
151
- spans.push(_jsx(Text, { color: "cyan", bold: true, children: tok }, key));
151
+ spans.push(_jsx(Text, { color: "#3da9fc", bold: true, children: tok }, key));
152
152
  }
153
153
  else {
154
154
  spans.push(_jsx(Text, { children: tok }, key));
@@ -184,7 +184,7 @@ function findCommentStart(line) {
184
184
  return -1;
185
185
  }
186
186
  /* ------------------------------------------------------------------ */
187
- /* Inline tokeniser */
187
+ /* Inline tokeniser */
188
188
  /* ------------------------------------------------------------------ */
189
189
  /**
190
190
  * Parse one paragraph line into a list of inline spans, then render
@@ -260,7 +260,7 @@ function renderSpan(span, key) {
260
260
  case 'code':
261
261
  return _jsx(Text, { color: "green", children: span.text }, key);
262
262
  case 'link':
263
- return (_jsxs(Text, { children: [_jsx(Text, { color: "cyan", underline: true, children: span.text }), _jsx(Text, { dimColor: true, children: ` (${span.url})` })] }, key));
263
+ return (_jsxs(Text, { children: [_jsx(Text, { color: "#3da9fc", underline: true, children: span.text }), _jsx(Text, { dimColor: true, children: ` (${span.url})` })] }, key));
264
264
  }
265
265
  }
266
266
  //# sourceMappingURL=markdown-render.js.map