nastech-tui 0.0.1

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (424) hide show
  1. package/.prettierrc +11 -0
  2. package/README.md +346 -0
  3. package/eslint.config.mjs +111 -0
  4. package/package.json +51 -0
  5. package/packages/nastech-ink/ambient.d.ts +83 -0
  6. package/packages/nastech-ink/index.d.ts +40 -0
  7. package/packages/nastech-ink/index.js +1 -0
  8. package/packages/nastech-ink/nastech-ink/ambient.d.ts +83 -0
  9. package/packages/nastech-ink/nastech-ink/index.d.ts +40 -0
  10. package/packages/nastech-ink/nastech-ink/index.js +1 -0
  11. package/packages/nastech-ink/nastech-ink/package.json +54 -0
  12. package/packages/nastech-ink/nastech-ink/src/bootstrap/state.ts +9 -0
  13. package/packages/nastech-ink/nastech-ink/src/entry-exports.ts +32 -0
  14. package/packages/nastech-ink/nastech-ink/src/hooks/use-stderr.ts +15 -0
  15. package/packages/nastech-ink/nastech-ink/src/hooks/use-stdout.ts +15 -0
  16. package/packages/nastech-ink/nastech-ink/src/ink/Ansi.tsx +435 -0
  17. package/packages/nastech-ink/nastech-ink/src/ink/app-mouse.test.ts +123 -0
  18. package/packages/nastech-ink/nastech-ink/src/ink/bidi.ts +145 -0
  19. package/packages/nastech-ink/nastech-ink/src/ink/cache-eviction.ts +45 -0
  20. package/packages/nastech-ink/nastech-ink/src/ink/clearTerminal.ts +68 -0
  21. package/packages/nastech-ink/nastech-ink/src/ink/colorize.test.ts +60 -0
  22. package/packages/nastech-ink/nastech-ink/src/ink/colorize.ts +277 -0
  23. package/packages/nastech-ink/nastech-ink/src/ink/components/AlternateScreen.tsx +133 -0
  24. package/packages/nastech-ink/nastech-ink/src/ink/components/App.tsx +830 -0
  25. package/packages/nastech-ink/nastech-ink/src/ink/components/AppContext.ts +20 -0
  26. package/packages/nastech-ink/nastech-ink/src/ink/components/Box.tsx +294 -0
  27. package/packages/nastech-ink/nastech-ink/src/ink/components/Button.tsx +236 -0
  28. package/packages/nastech-ink/nastech-ink/src/ink/components/ClockContext.tsx +133 -0
  29. package/packages/nastech-ink/nastech-ink/src/ink/components/CursorAdvanceContext.ts +35 -0
  30. package/packages/nastech-ink/nastech-ink/src/ink/components/CursorDeclarationContext.ts +28 -0
  31. package/packages/nastech-ink/nastech-ink/src/ink/components/ErrorOverview.tsx +130 -0
  32. package/packages/nastech-ink/nastech-ink/src/ink/components/Link.tsx +38 -0
  33. package/packages/nastech-ink/nastech-ink/src/ink/components/Newline.tsx +43 -0
  34. package/packages/nastech-ink/nastech-ink/src/ink/components/NoSelect.tsx +73 -0
  35. package/packages/nastech-ink/nastech-ink/src/ink/components/RawAnsi.tsx +61 -0
  36. package/packages/nastech-ink/nastech-ink/src/ink/components/ScrollBox.tsx +290 -0
  37. package/packages/nastech-ink/nastech-ink/src/ink/components/Spacer.tsx +23 -0
  38. package/packages/nastech-ink/nastech-ink/src/ink/components/StdinContext.ts +25 -0
  39. package/packages/nastech-ink/nastech-ink/src/ink/components/TerminalFocusContext.tsx +63 -0
  40. package/packages/nastech-ink/nastech-ink/src/ink/components/TerminalSizeContext.tsx +7 -0
  41. package/packages/nastech-ink/nastech-ink/src/ink/components/Text.test.ts +38 -0
  42. package/packages/nastech-ink/nastech-ink/src/ink/components/Text.tsx +336 -0
  43. package/packages/nastech-ink/nastech-ink/src/ink/constants.ts +6 -0
  44. package/packages/nastech-ink/nastech-ink/src/ink/cursor.ts +5 -0
  45. package/packages/nastech-ink/nastech-ink/src/ink/devtools.ts +2 -0
  46. package/packages/nastech-ink/nastech-ink/src/ink/dom.ts +495 -0
  47. package/packages/nastech-ink/nastech-ink/src/ink/events/click-event.ts +38 -0
  48. package/packages/nastech-ink/nastech-ink/src/ink/events/cmd-shortcuts.test.ts +65 -0
  49. package/packages/nastech-ink/nastech-ink/src/ink/events/dispatcher.ts +242 -0
  50. package/packages/nastech-ink/nastech-ink/src/ink/events/emitter.ts +40 -0
  51. package/packages/nastech-ink/nastech-ink/src/ink/events/event-handlers.ts +84 -0
  52. package/packages/nastech-ink/nastech-ink/src/ink/events/event.ts +11 -0
  53. package/packages/nastech-ink/nastech-ink/src/ink/events/focus-event.ts +18 -0
  54. package/packages/nastech-ink/nastech-ink/src/ink/events/input-event.ts +176 -0
  55. package/packages/nastech-ink/nastech-ink/src/ink/events/keyboard-event.ts +57 -0
  56. package/packages/nastech-ink/nastech-ink/src/ink/events/mouse-event.ts +18 -0
  57. package/packages/nastech-ink/nastech-ink/src/ink/events/paste-event.ts +10 -0
  58. package/packages/nastech-ink/nastech-ink/src/ink/events/resize-event.ts +12 -0
  59. package/packages/nastech-ink/nastech-ink/src/ink/events/terminal-event.ts +107 -0
  60. package/packages/nastech-ink/nastech-ink/src/ink/events/terminal-focus-event.ts +19 -0
  61. package/packages/nastech-ink/nastech-ink/src/ink/focus.ts +219 -0
  62. package/packages/nastech-ink/nastech-ink/src/ink/frame.ts +124 -0
  63. package/packages/nastech-ink/nastech-ink/src/ink/get-max-width.ts +27 -0
  64. package/packages/nastech-ink/nastech-ink/src/ink/global.d.ts +1 -0
  65. package/packages/nastech-ink/nastech-ink/src/ink/hit-test.test.ts +38 -0
  66. package/packages/nastech-ink/nastech-ink/src/ink/hit-test.ts +224 -0
  67. package/packages/nastech-ink/nastech-ink/src/ink/hooks/use-animation-frame.ts +62 -0
  68. package/packages/nastech-ink/nastech-ink/src/ink/hooks/use-app.ts +9 -0
  69. package/packages/nastech-ink/nastech-ink/src/ink/hooks/use-cursor-advance.ts +33 -0
  70. package/packages/nastech-ink/nastech-ink/src/ink/hooks/use-declared-cursor.ts +75 -0
  71. package/packages/nastech-ink/nastech-ink/src/ink/hooks/use-external-process.ts +27 -0
  72. package/packages/nastech-ink/nastech-ink/src/ink/hooks/use-input.ts +95 -0
  73. package/packages/nastech-ink/nastech-ink/src/ink/hooks/use-interval.ts +71 -0
  74. package/packages/nastech-ink/package.json +57 -0
  75. package/packages/nastech-ink/src/bootstrap/state.ts +9 -0
  76. package/packages/nastech-ink/src/entry-exports.ts +32 -0
  77. package/packages/nastech-ink/src/hooks/use-stderr.ts +15 -0
  78. package/packages/nastech-ink/src/hooks/use-stdout.ts +15 -0
  79. package/packages/nastech-ink/src/ink/Ansi.tsx +435 -0
  80. package/packages/nastech-ink/src/ink/app-mouse.test.ts +123 -0
  81. package/packages/nastech-ink/src/ink/app-rawmode-mouse.test.ts +91 -0
  82. package/packages/nastech-ink/src/ink/bidi.ts +145 -0
  83. package/packages/nastech-ink/src/ink/cache-eviction.ts +45 -0
  84. package/packages/nastech-ink/src/ink/clearTerminal.ts +68 -0
  85. package/packages/nastech-ink/src/ink/colorize.test.ts +60 -0
  86. package/packages/nastech-ink/src/ink/colorize.ts +277 -0
  87. package/packages/nastech-ink/src/ink/components/AlternateScreen.tsx +133 -0
  88. package/packages/nastech-ink/src/ink/components/App.tsx +855 -0
  89. package/packages/nastech-ink/src/ink/components/AppContext.ts +20 -0
  90. package/packages/nastech-ink/src/ink/components/Box.tsx +294 -0
  91. package/packages/nastech-ink/src/ink/components/Button.tsx +236 -0
  92. package/packages/nastech-ink/src/ink/components/ClockContext.tsx +133 -0
  93. package/packages/nastech-ink/src/ink/components/CursorAdvanceContext.ts +35 -0
  94. package/packages/nastech-ink/src/ink/components/CursorDeclarationContext.ts +28 -0
  95. package/packages/nastech-ink/src/ink/components/ErrorOverview.tsx +130 -0
  96. package/packages/nastech-ink/src/ink/components/Link.tsx +38 -0
  97. package/packages/nastech-ink/src/ink/components/Newline.tsx +43 -0
  98. package/packages/nastech-ink/src/ink/components/NoSelect.tsx +73 -0
  99. package/packages/nastech-ink/src/ink/components/RawAnsi.tsx +61 -0
  100. package/packages/nastech-ink/src/ink/components/ScrollBox.tsx +290 -0
  101. package/packages/nastech-ink/src/ink/components/Spacer.tsx +23 -0
  102. package/packages/nastech-ink/src/ink/components/StdinContext.ts +25 -0
  103. package/packages/nastech-ink/src/ink/components/TerminalFocusContext.tsx +63 -0
  104. package/packages/nastech-ink/src/ink/components/TerminalSizeContext.tsx +7 -0
  105. package/packages/nastech-ink/src/ink/components/Text.test.ts +38 -0
  106. package/packages/nastech-ink/src/ink/components/Text.tsx +336 -0
  107. package/packages/nastech-ink/src/ink/constants.ts +6 -0
  108. package/packages/nastech-ink/src/ink/cursor.ts +5 -0
  109. package/packages/nastech-ink/src/ink/devtools.ts +2 -0
  110. package/packages/nastech-ink/src/ink/dom.ts +495 -0
  111. package/packages/nastech-ink/src/ink/events/click-event.ts +38 -0
  112. package/packages/nastech-ink/src/ink/events/cmd-shortcuts.test.ts +65 -0
  113. package/packages/nastech-ink/src/ink/events/dispatcher.ts +242 -0
  114. package/packages/nastech-ink/src/ink/events/emitter.ts +40 -0
  115. package/packages/nastech-ink/src/ink/events/event-handlers.ts +84 -0
  116. package/packages/nastech-ink/src/ink/events/event.ts +11 -0
  117. package/packages/nastech-ink/src/ink/events/focus-event.ts +18 -0
  118. package/packages/nastech-ink/src/ink/events/input-event.ts +176 -0
  119. package/packages/nastech-ink/src/ink/events/keyboard-event.ts +57 -0
  120. package/packages/nastech-ink/src/ink/events/mouse-event.ts +18 -0
  121. package/packages/nastech-ink/src/ink/events/paste-event.ts +10 -0
  122. package/packages/nastech-ink/src/ink/events/resize-event.ts +12 -0
  123. package/packages/nastech-ink/src/ink/events/terminal-event.ts +107 -0
  124. package/packages/nastech-ink/src/ink/events/terminal-focus-event.ts +19 -0
  125. package/packages/nastech-ink/src/ink/focus.ts +219 -0
  126. package/packages/nastech-ink/src/ink/frame.ts +124 -0
  127. package/packages/nastech-ink/src/ink/get-max-width.ts +27 -0
  128. package/packages/nastech-ink/src/ink/global.d.ts +1 -0
  129. package/packages/nastech-ink/src/ink/hit-test.test.ts +38 -0
  130. package/packages/nastech-ink/src/ink/hit-test.ts +224 -0
  131. package/packages/nastech-ink/src/ink/hooks/use-animation-frame.ts +62 -0
  132. package/packages/nastech-ink/src/ink/hooks/use-app.ts +9 -0
  133. package/packages/nastech-ink/src/ink/hooks/use-cursor-advance.ts +33 -0
  134. package/packages/nastech-ink/src/ink/hooks/use-declared-cursor.ts +75 -0
  135. package/packages/nastech-ink/src/ink/hooks/use-external-process.ts +27 -0
  136. package/packages/nastech-ink/src/ink/hooks/use-input.ts +95 -0
  137. package/packages/nastech-ink/src/ink/hooks/use-interval.ts +71 -0
  138. package/packages/nastech-ink/src/ink/hooks/use-search-highlight.ts +56 -0
  139. package/packages/nastech-ink/src/ink/hooks/use-selection.ts +101 -0
  140. package/packages/nastech-ink/src/ink/hooks/use-stdin.ts +9 -0
  141. package/packages/nastech-ink/src/ink/hooks/use-tab-status.ts +71 -0
  142. package/packages/nastech-ink/src/ink/hooks/use-terminal-focus.ts +18 -0
  143. package/packages/nastech-ink/src/ink/hooks/use-terminal-title.ts +34 -0
  144. package/packages/nastech-ink/src/ink/hooks/use-terminal-viewport.ts +100 -0
  145. package/packages/nastech-ink/src/ink/hyperlinkHover.ts +52 -0
  146. package/packages/nastech-ink/src/ink/ink-cursor-advance.test.ts +234 -0
  147. package/packages/nastech-ink/src/ink/ink-resize.test.ts +50 -0
  148. package/packages/nastech-ink/src/ink/ink.tsx +2705 -0
  149. package/packages/nastech-ink/src/ink/instances.ts +10 -0
  150. package/packages/nastech-ink/src/ink/layout/engine.ts +6 -0
  151. package/packages/nastech-ink/src/ink/layout/geometry.ts +98 -0
  152. package/packages/nastech-ink/src/ink/layout/node.ts +145 -0
  153. package/packages/nastech-ink/src/ink/layout/yoga.ts +313 -0
  154. package/packages/nastech-ink/src/ink/line-width-cache.ts +38 -0
  155. package/packages/nastech-ink/src/ink/log-update.test.ts +223 -0
  156. package/packages/nastech-ink/src/ink/log-update.ts +752 -0
  157. package/packages/nastech-ink/src/ink/lru.ts +14 -0
  158. package/packages/nastech-ink/src/ink/measure-element.ts +23 -0
  159. package/packages/nastech-ink/src/ink/measure-text.ts +50 -0
  160. package/packages/nastech-ink/src/ink/node-cache.ts +53 -0
  161. package/packages/nastech-ink/src/ink/optimizer.ts +99 -0
  162. package/packages/nastech-ink/src/ink/output.ts +845 -0
  163. package/packages/nastech-ink/src/ink/parse-keypress.test.ts +133 -0
  164. package/packages/nastech-ink/src/ink/parse-keypress.ts +848 -0
  165. package/packages/nastech-ink/src/ink/reconciler.ts +382 -0
  166. package/packages/nastech-ink/src/ink/render-border.ts +206 -0
  167. package/packages/nastech-ink/src/ink/render-node-to-output.ts +1582 -0
  168. package/packages/nastech-ink/src/ink/render-to-screen.ts +236 -0
  169. package/packages/nastech-ink/src/ink/renderer.ts +169 -0
  170. package/packages/nastech-ink/src/ink/root.ts +204 -0
  171. package/packages/nastech-ink/src/ink/screen.ts +1590 -0
  172. package/packages/nastech-ink/src/ink/searchHighlight.ts +91 -0
  173. package/packages/nastech-ink/src/ink/selection.test.ts +82 -0
  174. package/packages/nastech-ink/src/ink/selection.ts +1143 -0
  175. package/packages/nastech-ink/src/ink/squash-text-nodes.ts +74 -0
  176. package/packages/nastech-ink/src/ink/stringWidth.ts +341 -0
  177. package/packages/nastech-ink/src/ink/styles.ts +750 -0
  178. package/packages/nastech-ink/src/ink/supports-hyperlinks.ts +51 -0
  179. package/packages/nastech-ink/src/ink/tabstops.ts +44 -0
  180. package/packages/nastech-ink/src/ink/terminal-focus-state.ts +52 -0
  181. package/packages/nastech-ink/src/ink/terminal-querier.ts +222 -0
  182. package/packages/nastech-ink/src/ink/terminal.test.ts +15 -0
  183. package/packages/nastech-ink/src/ink/terminal.ts +299 -0
  184. package/packages/nastech-ink/src/ink/termio/ansi.ts +75 -0
  185. package/packages/nastech-ink/src/ink/termio/csi.ts +334 -0
  186. package/packages/nastech-ink/src/ink/termio/dec.ts +99 -0
  187. package/packages/nastech-ink/src/ink/termio/esc.ts +69 -0
  188. package/packages/nastech-ink/src/ink/termio/osc.test.ts +191 -0
  189. package/packages/nastech-ink/src/ink/termio/osc.ts +724 -0
  190. package/packages/nastech-ink/src/ink/termio/parser.ts +467 -0
  191. package/packages/nastech-ink/src/ink/termio/sgr.ts +362 -0
  192. package/packages/nastech-ink/src/ink/termio/tokenize.test.ts +185 -0
  193. package/packages/nastech-ink/src/ink/termio/tokenize.ts +350 -0
  194. package/packages/nastech-ink/src/ink/termio/types.ts +230 -0
  195. package/packages/nastech-ink/src/ink/termio.ts +42 -0
  196. package/packages/nastech-ink/src/ink/useTerminalNotification.ts +110 -0
  197. package/packages/nastech-ink/src/ink/warn.ts +15 -0
  198. package/packages/nastech-ink/src/ink/widest-line.ts +22 -0
  199. package/packages/nastech-ink/src/ink/wrap-text.test.ts +17 -0
  200. package/packages/nastech-ink/src/ink/wrap-text.ts +144 -0
  201. package/packages/nastech-ink/src/ink/wrapAnsi.ts +13 -0
  202. package/packages/nastech-ink/src/native-ts/yoga-layout/enums.ts +112 -0
  203. package/packages/nastech-ink/src/native-ts/yoga-layout/index.ts +2326 -0
  204. package/packages/nastech-ink/src/utils/debug.ts +6 -0
  205. package/packages/nastech-ink/src/utils/earlyInput.ts +131 -0
  206. package/packages/nastech-ink/src/utils/env.ts +66 -0
  207. package/packages/nastech-ink/src/utils/envUtils.ts +13 -0
  208. package/packages/nastech-ink/src/utils/execFileNoThrow.test.ts +146 -0
  209. package/packages/nastech-ink/src/utils/execFileNoThrow.ts +115 -0
  210. package/packages/nastech-ink/src/utils/fullscreen.ts +3 -0
  211. package/packages/nastech-ink/src/utils/intl.ts +87 -0
  212. package/packages/nastech-ink/src/utils/log.ts +7 -0
  213. package/packages/nastech-ink/src/utils/semver.ts +57 -0
  214. package/packages/nastech-ink/src/utils/sliceAnsi.ts +106 -0
  215. package/packages/nastech-ink/text-input.d.ts +2 -0
  216. package/packages/nastech-ink/text-input.js +1 -0
  217. package/scripts/build.mjs +61 -0
  218. package/scripts/profile-tui.mjs +121 -0
  219. package/src/__tests__/activeSessionSwitcher.test.ts +157 -0
  220. package/src/__tests__/appChromeStatusRule.test.tsx +84 -0
  221. package/src/__tests__/appChromeStatusRuleDevCredits.test.tsx +73 -0
  222. package/src/__tests__/approvalAction.test.ts +50 -0
  223. package/src/__tests__/asCommandDispatch.test.ts +27 -0
  224. package/src/__tests__/blockLayout.test.ts +122 -0
  225. package/src/__tests__/clipboard.test.ts +369 -0
  226. package/src/__tests__/constants.test.ts +53 -0
  227. package/src/__tests__/createGatewayEventHandler.test.ts +1091 -0
  228. package/src/__tests__/createSlashHandler.test.ts +822 -0
  229. package/src/__tests__/creditsCommand.test.ts +144 -0
  230. package/src/__tests__/cursorDriftRegression.test.ts +114 -0
  231. package/src/__tests__/details.test.ts +115 -0
  232. package/src/__tests__/emoji.test.ts +64 -0
  233. package/src/__tests__/externalLink.test.ts +144 -0
  234. package/src/__tests__/forceTruecolor.test.ts +191 -0
  235. package/src/__tests__/gatewayClient.test.ts +394 -0
  236. package/src/__tests__/gatewayRecovery.test.ts +47 -0
  237. package/src/__tests__/markdown.test.ts +331 -0
  238. package/src/__tests__/mathUnicode.test.ts +293 -0
  239. package/src/__tests__/memoryMonitor.test.ts +102 -0
  240. package/src/__tests__/messageLine.test.ts +19 -0
  241. package/src/__tests__/messages.test.ts +92 -0
  242. package/src/__tests__/orchestratorPromptSession.test.ts +64 -0
  243. package/src/__tests__/osc52.test.ts +67 -0
  244. package/src/__tests__/parentLog.test.ts +75 -0
  245. package/src/__tests__/paths.test.ts +70 -0
  246. package/src/__tests__/platform.test.ts +556 -0
  247. package/src/__tests__/precisionWheel.test.ts +44 -0
  248. package/src/__tests__/prompt.test.ts +31 -0
  249. package/src/__tests__/providers.test.ts +65 -0
  250. package/src/__tests__/reasoning.test.ts +76 -0
  251. package/src/__tests__/rpc.test.ts +27 -0
  252. package/src/__tests__/scroll.test.ts +99 -0
  253. package/src/__tests__/slashParity.test.ts +123 -0
  254. package/src/__tests__/spawnHistoryStore.test.ts +46 -0
  255. package/src/__tests__/stateIsolation.test.ts +46 -0
  256. package/src/__tests__/statusBarTicker.test.ts +18 -0
  257. package/src/__tests__/statusRule.test.ts +32 -0
  258. package/src/__tests__/streamingMarkdown.test.ts +121 -0
  259. package/src/__tests__/subagentTree.test.ts +407 -0
  260. package/src/__tests__/syntax.test.ts +45 -0
  261. package/src/__tests__/terminalModes.test.ts +39 -0
  262. package/src/__tests__/terminalParity.test.ts +77 -0
  263. package/src/__tests__/terminalSetup.test.ts +386 -0
  264. package/src/__tests__/termux.test.ts +35 -0
  265. package/src/__tests__/termuxComposerLayout.test.ts +40 -0
  266. package/src/__tests__/text.test.ts +233 -0
  267. package/src/__tests__/textInputBurstInput.test.ts +40 -0
  268. package/src/__tests__/textInputCursorSourceOfTruth.test.ts +50 -0
  269. package/src/__tests__/textInputFastEcho.test.ts +200 -0
  270. package/src/__tests__/textInputLineNav.test.ts +55 -0
  271. package/src/__tests__/textInputPassThrough.test.ts +59 -0
  272. package/src/__tests__/textInputRightClick.test.ts +48 -0
  273. package/src/__tests__/textInputWrap.test.ts +151 -0
  274. package/src/__tests__/theme.test.ts +311 -0
  275. package/src/__tests__/turnControllerNotice.test.ts +43 -0
  276. package/src/__tests__/turnStore.test.ts +66 -0
  277. package/src/__tests__/useCompletion.test.ts +35 -0
  278. package/src/__tests__/useComposerState.test.ts +59 -0
  279. package/src/__tests__/useConfigSync.test.ts +460 -0
  280. package/src/__tests__/useInputHandlers.test.ts +77 -0
  281. package/src/__tests__/useQueue.test.ts +28 -0
  282. package/src/__tests__/useSessionLifecycle.test.ts +60 -0
  283. package/src/__tests__/useVirtualHistoryHeights.test.ts +39 -0
  284. package/src/__tests__/viewport.test.ts +58 -0
  285. package/src/__tests__/viewportStore.test.ts +85 -0
  286. package/src/__tests__/virtualHeights.test.ts +96 -0
  287. package/src/__tests__/virtualHistoryClamp.test.ts +19 -0
  288. package/src/__tests__/virtualHistoryOffsetCache.test.ts +282 -0
  289. package/src/__tests__/wheelAccel.test.ts +138 -0
  290. package/src/app/createGatewayEventHandler.ts +833 -0
  291. package/src/app/createSlashHandler.ts +130 -0
  292. package/src/app/delegationStore.ts +77 -0
  293. package/src/app/gatewayContext.tsx +19 -0
  294. package/src/app/gatewayRecovery.ts +35 -0
  295. package/src/app/inputSelectionStore.ts +15 -0
  296. package/src/app/interfaces.ts +394 -0
  297. package/src/app/overlayStore.ts +53 -0
  298. package/src/app/scroll.ts +71 -0
  299. package/src/app/setupHandoff.ts +54 -0
  300. package/src/app/slash/commands/core.ts +648 -0
  301. package/src/app/slash/commands/credits.ts +57 -0
  302. package/src/app/slash/commands/debug.ts +48 -0
  303. package/src/app/slash/commands/ops.ts +717 -0
  304. package/src/app/slash/commands/session.ts +554 -0
  305. package/src/app/slash/commands/setup.ts +20 -0
  306. package/src/app/slash/registry.ts +20 -0
  307. package/src/app/slash/types.ts +21 -0
  308. package/src/app/spawnHistoryStore.ts +159 -0
  309. package/src/app/turnController.ts +866 -0
  310. package/src/app/turnStore.ts +85 -0
  311. package/src/app/uiStore.ts +44 -0
  312. package/src/app/useComposerState.ts +367 -0
  313. package/src/app/useConfigSync.ts +288 -0
  314. package/src/app/useInputHandlers.ts +576 -0
  315. package/src/app/useLongRunToolCharms.ts +69 -0
  316. package/src/app/useMainApp.ts +1039 -0
  317. package/src/app/useSessionLifecycle.ts +366 -0
  318. package/src/app/useSubmission.ts +429 -0
  319. package/src/app.tsx +25 -0
  320. package/src/banner.ts +93 -0
  321. package/src/components/activeSessionSwitcher.tsx +635 -0
  322. package/src/components/agentsOverlay.tsx +1073 -0
  323. package/src/components/appChrome.tsx +554 -0
  324. package/src/components/appLayout.tsx +444 -0
  325. package/src/components/appOverlays.tsx +254 -0
  326. package/src/components/branding.tsx +466 -0
  327. package/src/components/fpsOverlay.tsx +30 -0
  328. package/src/components/helpHint.tsx +73 -0
  329. package/src/components/markdown.tsx +1119 -0
  330. package/src/components/maskedPrompt.tsx +34 -0
  331. package/src/components/messageLine.tsx +237 -0
  332. package/src/components/modelPicker.tsx +527 -0
  333. package/src/components/overlayControls.tsx +50 -0
  334. package/src/components/pluginsHub.tsx +238 -0
  335. package/src/components/prompts.tsx +276 -0
  336. package/src/components/queuedMessages.tsx +64 -0
  337. package/src/components/sessionPicker.tsx +227 -0
  338. package/src/components/skillsHub.tsx +308 -0
  339. package/src/components/streamingAssistant.tsx +110 -0
  340. package/src/components/streamingMarkdown.tsx +174 -0
  341. package/src/components/textInput.tsx +1340 -0
  342. package/src/components/themed.tsx +30 -0
  343. package/src/components/thinking.tsx +1224 -0
  344. package/src/components/todoPanel.tsx +93 -0
  345. package/src/config/env.ts +64 -0
  346. package/src/config/limits.ts +13 -0
  347. package/src/config/timing.ts +6 -0
  348. package/src/content/charms.ts +1 -0
  349. package/src/content/faces.ts +17 -0
  350. package/src/content/fortunes.ts +30 -0
  351. package/src/content/hotkeys.ts +37 -0
  352. package/src/content/placeholders.ts +13 -0
  353. package/src/content/setup.ts +17 -0
  354. package/src/content/verbs.ts +38 -0
  355. package/src/domain/blockLayout.ts +146 -0
  356. package/src/domain/details.ts +76 -0
  357. package/src/domain/messages.ts +91 -0
  358. package/src/domain/paths.ts +16 -0
  359. package/src/domain/providers.ts +11 -0
  360. package/src/domain/roles.ts +9 -0
  361. package/src/domain/slash.ts +10 -0
  362. package/src/domain/usage.ts +3 -0
  363. package/src/domain/viewport.ts +51 -0
  364. package/src/entry.tsx +104 -0
  365. package/src/gatewayClient.ts +730 -0
  366. package/src/gatewayTypes.ts +568 -0
  367. package/src/hooks/useCompletion.ts +112 -0
  368. package/src/hooks/useGitBranch.ts +72 -0
  369. package/src/hooks/useInputHistory.ts +11 -0
  370. package/src/hooks/useQueue.ts +76 -0
  371. package/src/hooks/useVirtualHistory.ts +554 -0
  372. package/src/lib/circularBuffer.ts +48 -0
  373. package/src/lib/clipboard.ts +182 -0
  374. package/src/lib/editor.test.ts +74 -0
  375. package/src/lib/editor.ts +47 -0
  376. package/src/lib/emoji.ts +55 -0
  377. package/src/lib/externalCli.ts +16 -0
  378. package/src/lib/externalLink.ts +435 -0
  379. package/src/lib/forceTruecolor.ts +60 -0
  380. package/src/lib/fpsStore.ts +51 -0
  381. package/src/lib/fuzzy.test.ts +109 -0
  382. package/src/lib/fuzzy.ts +177 -0
  383. package/src/lib/gracefulExit.ts +47 -0
  384. package/src/lib/history.ts +82 -0
  385. package/src/lib/inputMetrics.ts +203 -0
  386. package/src/lib/liveProgress.test.ts +116 -0
  387. package/src/lib/liveProgress.ts +79 -0
  388. package/src/lib/mathUnicode.ts +770 -0
  389. package/src/lib/memory.test.ts +155 -0
  390. package/src/lib/memory.ts +188 -0
  391. package/src/lib/memoryMonitor.ts +109 -0
  392. package/src/lib/messages.test.ts +29 -0
  393. package/src/lib/messages.ts +8 -0
  394. package/src/lib/openExternalUrl.test.ts +217 -0
  395. package/src/lib/openExternalUrl.ts +158 -0
  396. package/src/lib/osc52.ts +73 -0
  397. package/src/lib/parentLog.ts +57 -0
  398. package/src/lib/perfPane.tsx +107 -0
  399. package/src/lib/platform.ts +409 -0
  400. package/src/lib/precisionWheel.ts +48 -0
  401. package/src/lib/prompt.ts +35 -0
  402. package/src/lib/reasoning.ts +55 -0
  403. package/src/lib/rpc.ts +41 -0
  404. package/src/lib/subagentTree.ts +355 -0
  405. package/src/lib/syntax.ts +117 -0
  406. package/src/lib/terminalModes.ts +51 -0
  407. package/src/lib/terminalParity.ts +78 -0
  408. package/src/lib/terminalSetup.ts +444 -0
  409. package/src/lib/termux.ts +29 -0
  410. package/src/lib/text.test.ts +18 -0
  411. package/src/lib/text.ts +339 -0
  412. package/src/lib/todo.test.ts +21 -0
  413. package/src/lib/todo.ts +9 -0
  414. package/src/lib/viewportStore.ts +124 -0
  415. package/src/lib/virtualHeights.ts +145 -0
  416. package/src/lib/wheelAccel.ts +190 -0
  417. package/src/protocol/interpolation.ts +3 -0
  418. package/src/protocol/paste.ts +1 -0
  419. package/src/theme.ts +589 -0
  420. package/src/types/nastech-ink.d.ts +176 -0
  421. package/src/types.ts +212 -0
  422. package/tsconfig.build.json +9 -0
  423. package/tsconfig.json +19 -0
  424. package/vitest.config.ts +7 -0
package/.prettierrc ADDED
@@ -0,0 +1,11 @@
1
+ {
2
+ "arrowParens": "avoid",
3
+ "bracketSpacing": true,
4
+ "endOfLine": "auto",
5
+ "printWidth": 120,
6
+ "semi": false,
7
+ "singleQuote": true,
8
+ "tabWidth": 2,
9
+ "trailingComma": "none",
10
+ "useTabs": false
11
+ }
package/README.md ADDED
@@ -0,0 +1,346 @@
1
+ # NasTech TUI
2
+
3
+ React + Ink terminal UI for NasTech. TypeScript owns the screen. Python owns sessions, tools, model calls, and most command logic.
4
+
5
+ ```bash
6
+ nastech --tui
7
+ ```
8
+
9
+ ## What runs
10
+
11
+ The client entrypoint is `src/entry.tsx`. It exits early if `stdin` is not a TTY, starts `GatewayClient`, then renders `App`.
12
+
13
+ `GatewayClient` spawns:
14
+
15
+ ```text
16
+ python -m tui_gateway.entry
17
+ ```
18
+
19
+ Interpreter resolution order is: `NASTECH_PYTHON` → `PYTHON` → `$VIRTUAL_ENV/bin/python` → `./.venv/bin/python` → `./venv/bin/python` → `python3` (or `python` on Windows).
20
+
21
+ The transport is newline-delimited JSON-RPC over stdio:
22
+
23
+ ```text
24
+ ui-tui/src tui_gateway/
25
+ ----------- -------------
26
+ entry.tsx entry.py
27
+ -> GatewayClient -> request loop
28
+ -> App -> server.py RPC handlers
29
+
30
+ stdin/stdout: JSON-RPC requests, responses, events
31
+ stderr: captured into an in-memory log ring
32
+ ```
33
+
34
+ Malformed stdout lines are treated as protocol noise and surfaced as `gateway.protocol_error`. Stderr lines become `gateway.stderr`. Neither writes directly into the terminal.
35
+
36
+ ## Running it
37
+
38
+ From the repo root, the normal path is:
39
+
40
+ ```bash
41
+ nastech --tui
42
+ ```
43
+
44
+ The CLI expects `ui-tui/dist/entry.js` to exist, or the whole source code available in which to run `npm install` and `npm run dev`.
45
+
46
+ ```bash
47
+ cd ui-tui
48
+ npm install
49
+ ```
50
+
51
+ Local package commands:
52
+
53
+ ```bash
54
+ npm run dev
55
+ npm start
56
+ npm run build
57
+ npm run lint
58
+ npm run fmt
59
+ npm run fix
60
+ ```
61
+
62
+ Tests use vitest:
63
+
64
+ ```bash
65
+ npm test # single run
66
+ npm run test:watch
67
+ ```
68
+
69
+ ## App model
70
+
71
+ `src/app.tsx` is the center of the UI. Heavy logic is split into `src/app/`:
72
+
73
+ - `createGatewayEventHandler.ts` — maps gateway events to state updates
74
+ - `createSlashHandler.ts` — local slash command dispatch
75
+ - `useComposerState.ts` — draft, multiline buffer, queue editing
76
+ - `useInputHandlers.ts` — keypress routing
77
+ - `useTurnState.ts` — agent turn lifecycle
78
+ - `overlayStore.ts` / `uiStore.ts` — nanostores for overlay and UI state
79
+ - `gatewayContext.tsx` — React context for the gateway client
80
+ - `constants.ts`, `helpers.ts`, `interfaces.ts`
81
+
82
+ The top-level `app.tsx` composes these into the Ink tree with `Static` transcript output, a live streaming assistant row, prompt overlays, queue preview, status rule, input line, and completion list.
83
+
84
+ State managed at the top level includes:
85
+
86
+ - transcript and streaming state
87
+ - queued messages and input history
88
+ - session lifecycle
89
+ - tool progress and reasoning text
90
+ - prompt flows for approval, clarify, sudo, and secret input
91
+ - slash command routing
92
+ - tab completion and path completion
93
+ - theme state from gateway skin data
94
+
95
+ The UI renders as a normal Ink tree with `Static` transcript output, a live streaming assistant row, prompt overlays, queue preview, status rule, input line, and completion list.
96
+
97
+ The intro panel is driven by `session.info` and rendered through `branding.tsx`.
98
+
99
+ ## Hotkeys and interactions
100
+
101
+ Current input behavior is split across `app.tsx`, `components/textInput.tsx`, and the prompt/picker components.
102
+
103
+ ### Main chat input
104
+
105
+ | Key | Behavior |
106
+ | ------------------------------- | ------------------------------------------------------------------------------------------------------------------------------------------------------- |
107
+ | `Enter` | Submit the current draft |
108
+ | empty `Enter` twice | If queued messages exist and the agent is busy, interrupt the current run. If queued messages exist and the agent is idle, send the next queued message |
109
+ | `Shift+Enter` / `Alt+Enter` | Insert a newline in the current draft |
110
+ | `\` + `Enter` | Append the line to the multiline buffer (fallback for terminals without modifier support) |
111
+ | `Ctrl+C` | Interrupt active run, or clear the current draft, or exit if nothing is pending |
112
+ | `Ctrl+D` | Exit |
113
+ | `Cmd/Ctrl+G` / `Alt+G` | Open `$EDITOR` with the current draft (use `Alt+G` in VSCode/Cursor — they bind the primary keystroke to Find Next) |
114
+ | `Ctrl+L` | New session (same as `/clear`) |
115
+ | `Ctrl+V` / `Alt+V` | Paste text first, then fall back to image/path attachment when applicable |
116
+ | `Tab` | Apply the active completion |
117
+ | `Up/Down` | Cycle completions if the completion list is open; otherwise edit queued messages first, then walk input history |
118
+ | `Left/Right` | Move the cursor |
119
+ | modified `Left/Right` | Move by word when the terminal sends `Ctrl` or `Meta` with the arrow key |
120
+ | `Home` / `Ctrl+A` | Start of line |
121
+ | `End` / `Ctrl+E` | End of line |
122
+ | `Backspace` | Delete the character to the left of the cursor |
123
+ | `Delete` | Delete the character to the right of the cursor |
124
+ | modified `Backspace` | Delete the previous word |
125
+ | modified `Delete` | Delete the next word |
126
+ | `Ctrl+W` | Delete the previous word |
127
+ | `Ctrl+U` | Delete from the cursor back to the start of the line |
128
+ | `Ctrl+K` | Delete from the cursor to the end of the line |
129
+ | `Meta+B` / `Meta+F` | Move by word |
130
+ | `!cmd` | Run a shell command through the gateway |
131
+ | `{!cmd}` | Inline shell interpolation before send; queued drafts keep the raw text until they are sent |
132
+
133
+ Notes:
134
+
135
+ - `Tab` only applies completions when completions are present and you are not in multiline mode.
136
+ - Queue/history navigation only applies when you are not in multiline mode.
137
+ - `PgUp` / `PgDn` are left to the terminal emulator; the TUI does not handle them.
138
+
139
+ ### Prompt and picker modes
140
+
141
+ | Context | Keys | Behavior |
142
+ | --------------------------- | ------------------- | ------------------------------------------------- |
143
+ | approval prompt | `Up/Down`, `Enter` | Move and confirm the selected approval choice |
144
+ | approval prompt | `o`, `s`, `a`, `d` | Quick-pick `once`, `session`, `always`, `deny` |
145
+ | approval prompt | `Esc`, `Ctrl+C` | Deny |
146
+ | clarify prompt with choices | `Up/Down`, `Enter` | Move and confirm the selected choice |
147
+ | clarify prompt with choices | single-digit number | Quick-pick the matching numbered choice |
148
+ | clarify prompt with choices | `Enter` on "Other" | Switch into free-text entry |
149
+ | clarify free-text mode | `Enter` | Submit typed answer |
150
+ | sudo / secret prompt | `Enter` | Submit typed value |
151
+ | sudo / secret prompt | `Ctrl+C` | Cancel by sending an empty response |
152
+ | resume picker | `Up/Down`, `Enter` | Move and resume the selected session |
153
+ | resume picker | `1-9` | Quick-pick one of the first nine visible sessions |
154
+ | resume picker | `Esc`, `Ctrl+C` | Close the picker |
155
+
156
+ Notes:
157
+
158
+ - Clarify free-text mode and masked prompts use `ink-text-input`, so text editing there follows the library's default bindings rather than `components/textInput.tsx`.
159
+ - When a blocking prompt is open, the main chat input hotkeys are suspended.
160
+ - Clarify mode has no dedicated cancel shortcut in the current client. Sudo and secret prompts only expose `Ctrl+C` cancellation from the app-level blocked handler.
161
+
162
+ ### Interaction rules
163
+
164
+ - Plain text entered while the agent is busy is queued instead of sent immediately.
165
+ - Slash commands and `!cmd` do not queue; they execute immediately even while a run is active.
166
+ - Queue auto-drains after each assistant response, unless a queued item is currently being edited.
167
+ - `Up/Down` prioritizes queued-message editing over history. History only activates when there is no queue to edit.
168
+ - Queued drafts keep their original `!cmd` and `{!cmd}` text while you edit them. Shell commands and interpolation run when the queued item is actually sent.
169
+ - If you load a queued item into the input and resubmit plain text, that queue item is replaced, removed from the queue preview, and promoted to send next. If the agent is still busy, the edited item is moved to the front of the queue and sent after the current run completes.
170
+ - Completion requests are debounced by 60 ms. Input starting with `/` uses `complete.slash`. A trailing token that starts with `./`, `../`, `~/`, `/`, or `@` uses `complete.path`.
171
+ - Text pastes are inserted inline directly into the draft. Nothing is newline-flattened.
172
+ - `Cmd/Ctrl+G` (or `Alt+G` in VSCode/Cursor, which intercept the primary keystroke for Find Next) writes the current draft, including any multiline buffer, to a temp file, suspends Ink, launches `$EDITOR`, then restores the TUI and submits the saved text if the editor exits cleanly.
173
+ - Input history is stored in `~/.nastech/.nastech_history` or under `NASTECH_HOME`.
174
+
175
+ ## Rendering
176
+
177
+ Assistant output is rendered in one of two ways:
178
+
179
+ - if the payload already contains ANSI, `messageLine.tsx` prints it directly
180
+ - otherwise `components/markdown.tsx` renders a small Markdown subset into Ink components
181
+
182
+ The Markdown renderer handles headings, lists, block quotes, tables, fenced code blocks, diff coloring, inline code, emphasis, links, and plain URLs.
183
+
184
+ Tool/status activity is shown in a live activity lane. Transcript rows stay focused on user/assistant turns.
185
+
186
+ ## Prompt flows
187
+
188
+ The Python gateway can pause the main loop and request structured input:
189
+
190
+ - `approval.request`: allow once, allow for session, allow always, or deny
191
+ - `clarify.request`: pick from choices or type a custom answer
192
+ - `sudo.request`: masked password entry
193
+ - `secret.request`: masked value entry for a named env var
194
+ - `session.list`: used by `SessionPicker` for `/resume`
195
+
196
+ These are stateful UI branches in `app.tsx`, not separate screens.
197
+
198
+ ## Commands
199
+
200
+ The local slash handler covers the built-ins that need direct client behavior:
201
+
202
+ - `/help`
203
+ - `/quit`, `/exit`, `/q`
204
+ - `/clear`
205
+ - `/new`
206
+ - `/compact`
207
+ - `/resume`
208
+ - `/copy`
209
+ - `/paste`
210
+ - `/details`
211
+ - `/logs`
212
+ - `/statusbar`, `/sb`
213
+ - `/queue`
214
+ - `/undo`
215
+ - `/retry`
216
+
217
+ Notes:
218
+
219
+ - `/copy` sends the selected assistant response through OSC 52.
220
+ - `/paste` with no args asks the gateway to attach a clipboard image.
221
+ - Text paste remains inline-only; `Cmd+V` / `Ctrl+V` handle layered text/OSC52/image fallback before `/paste` is needed.
222
+ - `/details [hidden|collapsed|expanded|cycle]` controls thinking/tool-detail visibility.
223
+ - `/statusbar` toggles the status rule on/off.
224
+
225
+ Anything else falls through to:
226
+
227
+ 1. `slash.exec`
228
+ 2. `command.dispatch`
229
+
230
+ That lets Python own aliases, plugins, skills, and registry-backed commands without duplicating the logic in the TUI.
231
+
232
+ ## Event surface
233
+
234
+ Primary event types the client handles today:
235
+
236
+ | Event | Payload |
237
+ | ------------------------ | ----------------------------------------------- |
238
+ | `gateway.ready` | `{ skin? }` |
239
+ | `session.info` | session metadata for banner + tool/skill panels |
240
+ | `message.start` | start assistant streaming |
241
+ | `message.delta` | `{ text, rendered? }` |
242
+ | `message.complete` | `{ text, rendered?, usage, status }` |
243
+ | `thinking.delta` | `{ text }` |
244
+ | `reasoning.delta` | `{ text }` |
245
+ | `reasoning.available` | `{ text }` |
246
+ | `status.update` | `{ kind, text }` |
247
+ | `tool.start` | `{ tool_id, name, context? }` |
248
+ | `tool.progress` | `{ name, preview }` |
249
+ | `tool.complete` | `{ tool_id, name }` |
250
+ | `clarify.request` | `{ question, choices?, request_id }` |
251
+ | `approval.request` | `{ command, description }` |
252
+ | `sudo.request` | `{ request_id }` |
253
+ | `secret.request` | `{ prompt, env_var, request_id }` |
254
+ | `background.complete` | `{ task_id, text }` |
255
+ | `error` | `{ message }` |
256
+ | `gateway.stderr` | synthesized from child stderr |
257
+ | `gateway.protocol_error` | synthesized from malformed stdout |
258
+
259
+ ## Theme model
260
+
261
+ The client starts with `DEFAULT_THEME` from `theme.ts`, then merges in gateway skin data from `gateway.ready`.
262
+
263
+ Current branding overrides:
264
+
265
+ - agent name
266
+ - prompt symbol
267
+ - welcome text
268
+ - goodbye text
269
+
270
+ Current color overrides:
271
+
272
+ - banner title, accent, border, body, dim
273
+ - label, ok, error, warn
274
+
275
+ `branding.tsx` uses those values for the logo, session panel, and update notice.
276
+
277
+ ## File map
278
+
279
+ ```text
280
+ ui-tui/
281
+ packages/nastech-ink/ forked Ink renderer (local dep)
282
+ src/
283
+ entry.tsx TTY gate + render()
284
+ app.tsx top-level Ink tree, composes src/app/*
285
+ gatewayClient.ts child process + JSON-RPC bridge
286
+ theme.ts default palette + skin merge
287
+ constants.ts display constants, hotkeys, tool labels
288
+ types.ts shared client-side types
289
+ banner.ts ASCII art data
290
+
291
+ app/
292
+ createGatewayEventHandler.ts event → state mapping
293
+ createSlashHandler.ts local slash dispatch
294
+ useComposerState.ts draft + multiline + queue editing
295
+ useInputHandlers.ts keypress routing
296
+ useTurnState.ts agent turn lifecycle
297
+ overlayStore.ts nanostores for overlays
298
+ uiStore.ts nanostores for UI flags
299
+ gatewayContext.tsx React context for gateway client
300
+ constants.ts app-level constants
301
+ helpers.ts pure helpers
302
+ interfaces.ts internal interfaces
303
+
304
+ components/
305
+ appChrome.tsx status bar, input row, completions
306
+ appLayout.tsx top-level layout composition
307
+ appOverlays.tsx overlay routing (pickers, prompts)
308
+ branding.tsx banner + session summary
309
+ markdown.tsx Markdown-to-Ink renderer
310
+ maskedPrompt.tsx masked input for sudo / secrets
311
+ messageLine.tsx transcript rows
312
+ modelPicker.tsx model switch picker
313
+ prompts.tsx approval + clarify flows
314
+ queuedMessages.tsx queued input preview
315
+ sessionPicker.tsx session resume picker
316
+ textInput.tsx custom line editor
317
+ thinking.tsx spinner, reasoning, tool activity
318
+
319
+ hooks/
320
+ useCompletion.ts tab completion (slash + path)
321
+ useInputHistory.ts persistent history navigation
322
+ useQueue.ts queued message management
323
+ useVirtualHistory.ts in-memory history for pickers
324
+
325
+ lib/
326
+ history.ts persistent input history
327
+ messages.ts message formatting helpers
328
+ osc52.ts OSC 52 clipboard copy
329
+ rpc.ts JSON-RPC type helpers
330
+ text.ts text helpers, ANSI detection, previews
331
+
332
+ types/
333
+ nastech-ink.d.ts type declarations for @nastech/ink
334
+
335
+ __tests__/ vitest suite
336
+ ```
337
+
338
+ Related Python side:
339
+
340
+ ```text
341
+ tui_gateway/
342
+ entry.py stdio entrypoint
343
+ server.py RPC handlers and session logic
344
+ render.py optional rich/ANSI bridge
345
+ slash_worker.py persistent NasTechCLI subprocess for slash commands
346
+ ```
@@ -0,0 +1,111 @@
1
+ import js from '@eslint/js'
2
+ import typescriptEslint from '@typescript-eslint/eslint-plugin'
3
+ import typescriptParser from '@typescript-eslint/parser'
4
+ import perfectionist from 'eslint-plugin-perfectionist'
5
+ import reactPlugin from 'eslint-plugin-react'
6
+ import reactCompiler from 'eslint-plugin-react-compiler'
7
+ import hooksPlugin from 'eslint-plugin-react-hooks'
8
+ import unusedImports from 'eslint-plugin-unused-imports'
9
+ import globals from 'globals'
10
+
11
+ const noopRule = {
12
+ meta: { schema: [], type: 'problem' },
13
+ create: () => ({})
14
+ }
15
+
16
+ const customRules = {
17
+ rules: {
18
+ 'no-process-cwd': noopRule,
19
+ 'no-process-env-top-level': noopRule,
20
+ 'no-sync-fs': noopRule,
21
+ 'no-top-level-dynamic-import': noopRule,
22
+ 'no-top-level-side-effects': noopRule
23
+ }
24
+ }
25
+
26
+ export default [
27
+ {
28
+ ignores: ['**/node_modules/**', '**/dist/**', 'src/**/*.js']
29
+ },
30
+ js.configs.recommended,
31
+ {
32
+ files: ['**/*.{ts,tsx}'],
33
+ languageOptions: {
34
+ globals: { ...globals.node },
35
+ parser: typescriptParser,
36
+ parserOptions: {
37
+ ecmaFeatures: { jsx: true },
38
+ ecmaVersion: 'latest',
39
+ sourceType: 'module'
40
+ }
41
+ },
42
+ plugins: {
43
+ '@typescript-eslint': typescriptEslint,
44
+ 'custom-rules': customRules,
45
+ perfectionist,
46
+ react: reactPlugin,
47
+ 'react-compiler': reactCompiler,
48
+ 'react-hooks': hooksPlugin,
49
+ 'unused-imports': unusedImports
50
+ },
51
+ rules: {
52
+ 'no-fallthrough': ['error', { allowEmptyCase: true }],
53
+ curly: ['error', 'all'],
54
+ '@typescript-eslint/consistent-type-imports': ['error', { prefer: 'type-imports' }],
55
+ '@typescript-eslint/no-unused-vars': 'off',
56
+ 'no-undef': 'off',
57
+ 'no-unused-vars': 'off',
58
+ 'react-compiler/react-compiler': 'warn',
59
+ 'padding-line-between-statements': [
60
+ 1,
61
+ { blankLine: 'always', next: ['block-like', 'block', 'return', 'if', 'class', 'continue', 'debugger', 'break', 'multiline-const', 'multiline-let'], prev: '*' },
62
+ { blankLine: 'always', next: '*', prev: ['case', 'default', 'multiline-const', 'multiline-let', 'multiline-block-like'] },
63
+ { blankLine: 'never', next: ['block', 'block-like'], prev: ['case', 'default'] },
64
+ { blankLine: 'always', next: ['block', 'block-like'], prev: ['block', 'block-like'] },
65
+ { blankLine: 'always', next: ['empty'], prev: 'export' },
66
+ { blankLine: 'never', next: 'iife', prev: ['block', 'block-like', 'empty'] }
67
+ ],
68
+ 'perfectionist/sort-exports': ['error', { order: 'asc', type: 'natural' }],
69
+ 'perfectionist/sort-imports': [
70
+ 'error',
71
+ {
72
+ groups: ['side-effect', 'builtin', 'external', 'internal', 'parent', 'sibling', 'index'],
73
+ order: 'asc',
74
+ type: 'natural'
75
+ }
76
+ ],
77
+ 'perfectionist/sort-jsx-props': ['error', { order: 'asc', type: 'natural' }],
78
+ 'perfectionist/sort-named-exports': ['error', { order: 'asc', type: 'natural' }],
79
+ 'perfectionist/sort-named-imports': ['error', { order: 'asc', type: 'natural' }],
80
+ 'react-hooks/exhaustive-deps': 'warn',
81
+ 'react-hooks/rules-of-hooks': 'error',
82
+ 'unused-imports/no-unused-imports': 'error'
83
+ },
84
+ settings: {
85
+ react: { version: 'detect' }
86
+ }
87
+ },
88
+ {
89
+ files: ['packages/nastech-ink/**/*.{ts,tsx}'],
90
+ rules: {
91
+ '@typescript-eslint/consistent-type-imports': 'off',
92
+ 'no-constant-condition': 'off',
93
+ 'no-empty': 'off',
94
+ 'no-redeclare': 'off',
95
+ 'react-compiler/react-compiler': 'off',
96
+ 'react-hooks/exhaustive-deps': 'off'
97
+ }
98
+ },
99
+ {
100
+ files: ['**/*.js'],
101
+ ignores: ['**/node_modules/**', '**/dist/**'],
102
+ languageOptions: {
103
+ globals: { ...globals.node },
104
+ ecmaVersion: 'latest',
105
+ sourceType: 'module'
106
+ }
107
+ },
108
+ {
109
+ ignores: ['*.config.*']
110
+ }
111
+ ]
package/package.json ADDED
@@ -0,0 +1,51 @@
1
+ {
2
+ "name": "nastech-tui",
3
+ "version": "0.0.1",
4
+ "type": "module",
5
+ "scripts": {
6
+ "dev": "npm run build --prefix packages/nastech-ink && tsx --watch src/entry.tsx",
7
+ "start": "tsx src/entry.tsx",
8
+ "build": "node scripts/build.mjs",
9
+ "type-check": "tsc --noEmit -p tsconfig.json",
10
+ "typecheck": "tsc --noEmit -p tsconfig.json",
11
+ "lint": "eslint src/ packages/",
12
+ "lint:fix": "eslint src/ packages/ --fix",
13
+ "fmt": "prettier --write 'src/**/*.{ts,tsx}' 'packages/**/*.{ts,tsx}'",
14
+ "fix": "npm run lint:fix && npm run fmt",
15
+ "test": "vitest run",
16
+ "test:watch": "vitest"
17
+ },
18
+ "dependencies": {
19
+ "@nanostores/react": "^1.1.0",
20
+ "@nastechai/ink": "file:./packages/nastech-ink",
21
+ "undici": ">=7.24.0",
22
+ "ink": "^6.8.0",
23
+ "ink-text-input": "^6.0.0",
24
+ "nanostores": "^1.2.0",
25
+ "react": "^19.2.4",
26
+ "unicode-animations": "^1.0.3"
27
+ },
28
+ "devDependencies": {
29
+ "@eslint/js": "^9",
30
+ "@types/node": "^25.5.0",
31
+ "@types/react": "^19.2.14",
32
+ "@typescript-eslint/eslint-plugin": "^8",
33
+ "@typescript-eslint/parser": "^8",
34
+ "esbuild": "^0.28.1",
35
+ "eslint": "^9",
36
+ "eslint-plugin-perfectionist": "^5",
37
+ "eslint-plugin-react": "^7",
38
+ "eslint-plugin-react-compiler": "^19.1.0-rc.2",
39
+ "eslint-plugin-react-hooks": "^7",
40
+ "eslint-plugin-unused-imports": "^4",
41
+ "globals": "^16",
42
+ "prettier": "^3",
43
+ "tsx": "^4.19.0",
44
+ "typescript": "^5.7.0",
45
+ "vitest": "^4.1.3"
46
+ },
47
+ "publishConfig": {
48
+ "access": "public",
49
+ "registry": "https://registry.npmjs.org/"
50
+ }
51
+ }
@@ -0,0 +1,83 @@
1
+ /// <reference types="react" />
2
+
3
+ declare module 'react/compiler-runtime' {
4
+ export function c(size: number): any[]
5
+ }
6
+
7
+ declare module 'bidi-js' {
8
+ const bidiFactory: () => Record<string, any>
9
+ export default bidiFactory
10
+ }
11
+
12
+ declare module 'stack-utils' {
13
+ class StackUtils {
14
+ static nodeInternals(): RegExp[]
15
+ constructor(opts?: { cwd?: string; internals?: RegExp[] })
16
+ clean(stack: string | undefined): string | undefined
17
+ parseLine(line: string): { file?: string; line?: number; column?: number; function?: string } | undefined
18
+ }
19
+ export default StackUtils
20
+ }
21
+
22
+ declare module 'react-reconciler' {
23
+ export type FiberRoot = unknown
24
+ const createReconciler: any
25
+ export default createReconciler
26
+ }
27
+
28
+ declare module 'react-reconciler/constants.js' {
29
+ export const ConcurrentRoot: number
30
+ export const LegacyRoot: number
31
+ export const DiscreteEventPriority: symbol | number
32
+ export const ContinuousEventPriority: symbol | number
33
+ export const DefaultEventPriority: symbol | number
34
+ export const NoEventPriority: symbol | number
35
+ }
36
+
37
+ declare module 'lodash-es/noop.js' {
38
+ const noop: (...args: unknown[]) => void
39
+ export default noop
40
+ }
41
+
42
+ declare module 'lodash-es/throttle.js' {
43
+ function throttle<T extends (...args: unknown[]) => unknown>(
44
+ fn: T,
45
+ wait?: number,
46
+ opts?: { leading?: boolean; trailing?: boolean }
47
+ ): T & { cancel(): void; flush(): void }
48
+ export default throttle
49
+ }
50
+
51
+ declare module 'semver' {
52
+ export function coerce(version: string | number | null | undefined): { version: string } | null
53
+ export function gt(a: string, b: string, opts?: { loose?: boolean }): boolean
54
+ export function gte(a: string, b: string, opts?: { loose?: boolean }): boolean
55
+ export function lt(a: string, b: string, opts?: { loose?: boolean }): boolean
56
+ export function lte(a: string, b: string, opts?: { loose?: boolean }): boolean
57
+ export function satisfies(version: string, range: string, opts?: { loose?: boolean }): boolean
58
+ export function compare(a: string, b: string, opts?: { loose?: boolean }): number
59
+ }
60
+
61
+ interface BunSemver {
62
+ order(a: string, b: string): -1 | 0 | 1
63
+ satisfies(version: string, range: string): boolean
64
+ }
65
+
66
+ interface BunRuntime {
67
+ stringWidth(s: string, opts?: { ambiguousIsNarrow?: boolean }): number
68
+ semver: BunSemver
69
+ wrapAnsi?(input: string, columns: number, options?: { hard?: boolean; wordWrap?: boolean; trim?: boolean }): string
70
+ }
71
+
72
+ declare var Bun: BunRuntime | undefined
73
+
74
+ declare namespace React {
75
+ namespace JSX {
76
+ interface IntrinsicElements {
77
+ 'ink-box': Record<string, unknown>
78
+ 'ink-text': Record<string, unknown>
79
+ 'ink-link': Record<string, unknown>
80
+ 'ink-raw-ansi': Record<string, unknown>
81
+ }
82
+ }
83
+ }
@@ -0,0 +1,40 @@
1
+ /// <reference path="./ambient.d.ts" />
2
+ export { default as useStderr } from './src/hooks/use-stderr.ts'
3
+ export type { StderrHandle } from './src/hooks/use-stderr.ts'
4
+ export { default as useStdout } from './src/hooks/use-stdout.ts'
5
+ export type { StdoutHandle } from './src/hooks/use-stdout.ts'
6
+ export { Ansi } from './src/ink/Ansi.tsx'
7
+ export { evictInkCaches } from './src/ink/cache-eviction.ts'
8
+ export type { EvictLevel, InkCacheSizes } from './src/ink/cache-eviction.ts'
9
+ export { AlternateScreen } from './src/ink/components/AlternateScreen.tsx'
10
+ export type { MouseTrackingMode } from './src/ink/termio/dec.ts'
11
+ export { default as Box } from './src/ink/components/Box.tsx'
12
+ export type { Props as BoxProps } from './src/ink/components/Box.tsx'
13
+ export { default as Link } from './src/ink/components/Link.tsx'
14
+ export { default as Newline } from './src/ink/components/Newline.tsx'
15
+ export { NoSelect } from './src/ink/components/NoSelect.tsx'
16
+ export { RawAnsi } from './src/ink/components/RawAnsi.tsx'
17
+ export { default as ScrollBox } from './src/ink/components/ScrollBox.tsx'
18
+ export type { ScrollBoxHandle, ScrollBoxProps } from './src/ink/components/ScrollBox.tsx'
19
+ export { default as Spacer } from './src/ink/components/Spacer.tsx'
20
+ export type { Props as StdinProps } from './src/ink/components/StdinContext.ts'
21
+ export { default as Text } from './src/ink/components/Text.tsx'
22
+ export type { Props as TextProps } from './src/ink/components/Text.tsx'
23
+ export type { Key } from './src/ink/events/input-event.ts'
24
+ export { default as useApp } from './src/ink/hooks/use-app.ts'
25
+ export { useCursorAdvance } from './src/ink/hooks/use-cursor-advance.ts'
26
+ export { useDeclaredCursor } from './src/ink/hooks/use-declared-cursor.ts'
27
+ export { default as useInput } from './src/ink/hooks/use-input.ts'
28
+ export { useHasSelection, useSelection } from './src/ink/hooks/use-selection.ts'
29
+ export { default as useStdin } from './src/ink/hooks/use-stdin.ts'
30
+ export { useTabStatus } from './src/ink/hooks/use-tab-status.ts'
31
+ export { useTerminalFocus } from './src/ink/hooks/use-terminal-focus.ts'
32
+ export { useTerminalTitle } from './src/ink/hooks/use-terminal-title.ts'
33
+ export { useTerminalViewport } from './src/ink/hooks/use-terminal-viewport.ts'
34
+ export { default as measureElement } from './src/ink/measure-element.ts'
35
+ export { createRoot, forceRedraw, default as render, renderSync } from './src/ink/root.ts'
36
+ export type { Instance, RenderOptions, Root } from './src/ink/root.ts'
37
+ export { stringWidth } from './src/ink/stringWidth.ts'
38
+ export { wrapAnsi } from './src/ink/wrapAnsi.ts'
39
+ export { default as TextInput, UncontrolledTextInput } from 'ink-text-input'
40
+ export type { Props as TextInputProps } from 'ink-text-input'
@@ -0,0 +1 @@
1
+ export * from './dist/entry-exports.js'