claude-code-tools 0.2.0__py3-none-any.whl → 1.4.1__py3-none-any.whl

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 (1805) hide show
  1. claude_code_tools/__init__.py +1 -1
  2. claude_code_tools/action_rpc.py +407 -0
  3. claude_code_tools/aichat.py +2460 -0
  4. claude_code_tools/claude_continue.py +299 -0
  5. claude_code_tools/codex_continue.py +309 -0
  6. claude_code_tools/config.py +93 -0
  7. claude_code_tools/delete_session.py +194 -0
  8. claude_code_tools/export_all.py +342 -0
  9. claude_code_tools/export_claude_session.py +481 -0
  10. claude_code_tools/export_codex_session.py +466 -0
  11. claude_code_tools/export_session.py +577 -0
  12. claude_code_tools/find_claude_session.py +1280 -118
  13. claude_code_tools/find_codex_session.py +946 -79
  14. claude_code_tools/find_original_session.py +134 -0
  15. claude_code_tools/find_session.py +1088 -0
  16. claude_code_tools/find_trimmed_sessions.py +259 -0
  17. claude_code_tools/gdoc2md.py +220 -0
  18. claude_code_tools/md2gdoc.py +549 -0
  19. claude_code_tools/node_menu_ui.py +406 -0
  20. claude_code_tools/search_index.py +1321 -0
  21. claude_code_tools/session_lineage.py +260 -0
  22. claude_code_tools/session_menu.py +187 -0
  23. claude_code_tools/session_menu_cli.py +448 -0
  24. claude_code_tools/session_utils.py +1313 -0
  25. claude_code_tools/smart_trim.py +424 -0
  26. claude_code_tools/smart_trim_core.py +616 -0
  27. claude_code_tools/tmux_cli_controller.py +55 -36
  28. claude_code_tools/trim_session.py +817 -0
  29. claude_code_tools/trim_session_claude.py +319 -0
  30. claude_code_tools/trim_session_codex.py +344 -0
  31. claude_code_tools-1.4.1.dist-info/METADATA +1113 -0
  32. claude_code_tools-1.4.1.dist-info/RECORD +1813 -0
  33. {claude_code_tools-0.2.0.dist-info → claude_code_tools-1.4.1.dist-info}/WHEEL +1 -1
  34. {claude_code_tools-0.2.0.dist-info → claude_code_tools-1.4.1.dist-info}/entry_points.txt +3 -2
  35. docs/lmsh.md +27 -5
  36. docs/local-llm-setup.md +286 -0
  37. docs/reddit-aichat-resume-v2.md +80 -0
  38. docs/reddit-aichat-resume.md +29 -0
  39. docs/reddit-aichat.md +79 -0
  40. docs/rollover-details.md +67 -0
  41. node_ui/action_config.js +72 -0
  42. node_ui/menu.js +2321 -0
  43. node_ui/node_modules/.bin/is-in-ci +5 -0
  44. node_ui/node_modules/.bin/loose-envify +16 -0
  45. node_ui/node_modules/.package-lock.json +714 -0
  46. node_ui/node_modules/@alcalzone/ansi-tokenize/README.md +248 -0
  47. node_ui/node_modules/@alcalzone/ansi-tokenize/build/ansiCodes.d.ts +11 -0
  48. node_ui/node_modules/@alcalzone/ansi-tokenize/build/ansiCodes.js +41 -0
  49. node_ui/node_modules/@alcalzone/ansi-tokenize/build/ansiCodes.js.map +1 -0
  50. node_ui/node_modules/@alcalzone/ansi-tokenize/build/diff.d.ts +6 -0
  51. node_ui/node_modules/@alcalzone/ansi-tokenize/build/diff.js +17 -0
  52. node_ui/node_modules/@alcalzone/ansi-tokenize/build/diff.js.map +1 -0
  53. node_ui/node_modules/@alcalzone/ansi-tokenize/build/index.d.ts +6 -0
  54. node_ui/node_modules/@alcalzone/ansi-tokenize/build/index.js +7 -0
  55. node_ui/node_modules/@alcalzone/ansi-tokenize/build/index.js.map +1 -0
  56. node_ui/node_modules/@alcalzone/ansi-tokenize/build/reduce.d.ts +5 -0
  57. node_ui/node_modules/@alcalzone/ansi-tokenize/build/reduce.js +27 -0
  58. node_ui/node_modules/@alcalzone/ansi-tokenize/build/reduce.js.map +1 -0
  59. node_ui/node_modules/@alcalzone/ansi-tokenize/build/styledChars.d.ts +6 -0
  60. node_ui/node_modules/@alcalzone/ansi-tokenize/build/styledChars.js +38 -0
  61. node_ui/node_modules/@alcalzone/ansi-tokenize/build/styledChars.js.map +1 -0
  62. node_ui/node_modules/@alcalzone/ansi-tokenize/build/tokenize.d.ts +12 -0
  63. node_ui/node_modules/@alcalzone/ansi-tokenize/build/tokenize.js +70 -0
  64. node_ui/node_modules/@alcalzone/ansi-tokenize/build/tokenize.js.map +1 -0
  65. node_ui/node_modules/@alcalzone/ansi-tokenize/build/undo.d.ts +3 -0
  66. node_ui/node_modules/@alcalzone/ansi-tokenize/build/undo.js +11 -0
  67. node_ui/node_modules/@alcalzone/ansi-tokenize/build/undo.js.map +1 -0
  68. node_ui/node_modules/@alcalzone/ansi-tokenize/package.json +63 -0
  69. node_ui/node_modules/ansi-escapes/base.d.ts +292 -0
  70. node_ui/node_modules/ansi-escapes/base.js +198 -0
  71. node_ui/node_modules/ansi-escapes/index.d.ts +2 -0
  72. node_ui/node_modules/ansi-escapes/index.js +2 -0
  73. node_ui/node_modules/ansi-escapes/license +9 -0
  74. node_ui/node_modules/ansi-escapes/package.json +70 -0
  75. node_ui/node_modules/ansi-escapes/readme.md +284 -0
  76. node_ui/node_modules/ansi-regex/index.d.ts +33 -0
  77. node_ui/node_modules/ansi-regex/index.js +14 -0
  78. node_ui/node_modules/ansi-regex/license +9 -0
  79. node_ui/node_modules/ansi-regex/package.json +61 -0
  80. node_ui/node_modules/ansi-regex/readme.md +66 -0
  81. node_ui/node_modules/ansi-styles/index.d.ts +236 -0
  82. node_ui/node_modules/ansi-styles/index.js +223 -0
  83. node_ui/node_modules/ansi-styles/license +9 -0
  84. node_ui/node_modules/ansi-styles/package.json +54 -0
  85. node_ui/node_modules/ansi-styles/readme.md +173 -0
  86. node_ui/node_modules/auto-bind/index.d.ts +50 -0
  87. node_ui/node_modules/auto-bind/index.js +41 -0
  88. node_ui/node_modules/auto-bind/license +9 -0
  89. node_ui/node_modules/auto-bind/package.json +51 -0
  90. node_ui/node_modules/auto-bind/react.d.ts +26 -0
  91. node_ui/node_modules/auto-bind/react.js +28 -0
  92. node_ui/node_modules/auto-bind/readme.md +92 -0
  93. node_ui/node_modules/chalk/license +9 -0
  94. node_ui/node_modules/chalk/package.json +83 -0
  95. node_ui/node_modules/chalk/readme.md +325 -0
  96. node_ui/node_modules/chalk/source/index.d.ts +320 -0
  97. node_ui/node_modules/chalk/source/index.js +225 -0
  98. node_ui/node_modules/chalk/source/utilities.js +33 -0
  99. node_ui/node_modules/chalk/source/vendor/ansi-styles/index.d.ts +236 -0
  100. node_ui/node_modules/chalk/source/vendor/ansi-styles/index.js +223 -0
  101. node_ui/node_modules/chalk/source/vendor/supports-color/browser.d.ts +1 -0
  102. node_ui/node_modules/chalk/source/vendor/supports-color/browser.js +30 -0
  103. node_ui/node_modules/chalk/source/vendor/supports-color/index.d.ts +55 -0
  104. node_ui/node_modules/chalk/source/vendor/supports-color/index.js +182 -0
  105. node_ui/node_modules/cli-boxes/boxes.json +82 -0
  106. node_ui/node_modules/cli-boxes/index.d.ts +127 -0
  107. node_ui/node_modules/cli-boxes/index.js +6 -0
  108. node_ui/node_modules/cli-boxes/license +9 -0
  109. node_ui/node_modules/cli-boxes/package.json +42 -0
  110. node_ui/node_modules/cli-boxes/readme.md +115 -0
  111. node_ui/node_modules/cli-cursor/index.d.ts +47 -0
  112. node_ui/node_modules/cli-cursor/index.js +39 -0
  113. node_ui/node_modules/cli-cursor/license +9 -0
  114. node_ui/node_modules/cli-cursor/package.json +49 -0
  115. node_ui/node_modules/cli-cursor/readme.md +51 -0
  116. node_ui/node_modules/cli-truncate/index.d.ts +116 -0
  117. node_ui/node_modules/cli-truncate/index.js +99 -0
  118. node_ui/node_modules/cli-truncate/license +9 -0
  119. node_ui/node_modules/cli-truncate/node_modules/slice-ansi/index.js +105 -0
  120. node_ui/node_modules/cli-truncate/node_modules/slice-ansi/license +10 -0
  121. node_ui/node_modules/cli-truncate/node_modules/slice-ansi/package.json +53 -0
  122. node_ui/node_modules/cli-truncate/node_modules/slice-ansi/readme.md +66 -0
  123. node_ui/node_modules/cli-truncate/package.json +51 -0
  124. node_ui/node_modules/cli-truncate/readme.md +150 -0
  125. node_ui/node_modules/code-excerpt/dist/index.d.ts +9 -0
  126. node_ui/node_modules/code-excerpt/dist/index.js +27 -0
  127. node_ui/node_modules/code-excerpt/license +21 -0
  128. node_ui/node_modules/code-excerpt/package.json +43 -0
  129. node_ui/node_modules/code-excerpt/readme.md +65 -0
  130. node_ui/node_modules/convert-to-spaces/dist/index.d.ts +2 -0
  131. node_ui/node_modules/convert-to-spaces/dist/index.js +4 -0
  132. node_ui/node_modules/convert-to-spaces/license +21 -0
  133. node_ui/node_modules/convert-to-spaces/package.json +40 -0
  134. node_ui/node_modules/convert-to-spaces/readme.md +39 -0
  135. node_ui/node_modules/emoji-regex/LICENSE-MIT.txt +20 -0
  136. node_ui/node_modules/emoji-regex/README.md +107 -0
  137. node_ui/node_modules/emoji-regex/index.d.ts +3 -0
  138. node_ui/node_modules/emoji-regex/index.js +4 -0
  139. node_ui/node_modules/emoji-regex/index.mjs +4 -0
  140. node_ui/node_modules/emoji-regex/package.json +45 -0
  141. node_ui/node_modules/environment/index.d.ts +74 -0
  142. node_ui/node_modules/environment/index.js +47 -0
  143. node_ui/node_modules/environment/license +9 -0
  144. node_ui/node_modules/environment/package.json +74 -0
  145. node_ui/node_modules/environment/readme.md +94 -0
  146. node_ui/node_modules/escape-string-regexp/index.d.ts +16 -0
  147. node_ui/node_modules/escape-string-regexp/index.js +11 -0
  148. node_ui/node_modules/escape-string-regexp/license +9 -0
  149. node_ui/node_modules/escape-string-regexp/package.json +40 -0
  150. node_ui/node_modules/escape-string-regexp/readme.md +34 -0
  151. node_ui/node_modules/figures/index.d.ts +269 -0
  152. node_ui/node_modules/figures/index.js +322 -0
  153. node_ui/node_modules/figures/license +9 -0
  154. node_ui/node_modules/figures/package.json +46 -0
  155. node_ui/node_modules/figures/readme.md +328 -0
  156. node_ui/node_modules/get-east-asian-width/index.d.ts +60 -0
  157. node_ui/node_modules/get-east-asian-width/index.js +30 -0
  158. node_ui/node_modules/get-east-asian-width/license +9 -0
  159. node_ui/node_modules/get-east-asian-width/lookup.js +403 -0
  160. node_ui/node_modules/get-east-asian-width/package.json +70 -0
  161. node_ui/node_modules/get-east-asian-width/readme.md +65 -0
  162. node_ui/node_modules/indent-string/index.d.ts +38 -0
  163. node_ui/node_modules/indent-string/index.js +38 -0
  164. node_ui/node_modules/indent-string/license +9 -0
  165. node_ui/node_modules/indent-string/package.json +40 -0
  166. node_ui/node_modules/indent-string/readme.md +73 -0
  167. node_ui/node_modules/ink/build/apply-styles.js +175 -0
  168. node_ui/node_modules/ink/build/build-layout.js +77 -0
  169. node_ui/node_modules/ink/build/calculate-wrapped-text.js +53 -0
  170. node_ui/node_modules/ink/build/colorize.d.ts +3 -0
  171. node_ui/node_modules/ink/build/colorize.js +48 -0
  172. node_ui/node_modules/ink/build/colorize.js.map +1 -0
  173. node_ui/node_modules/ink/build/components/App.d.ts +61 -0
  174. node_ui/node_modules/ink/build/components/App.js +286 -0
  175. node_ui/node_modules/ink/build/components/App.js.map +1 -0
  176. node_ui/node_modules/ink/build/components/AppContext.d.ts +12 -0
  177. node_ui/node_modules/ink/build/components/AppContext.js +11 -0
  178. node_ui/node_modules/ink/build/components/AppContext.js.map +1 -0
  179. node_ui/node_modules/ink/build/components/Box.d.ts +62 -0
  180. node_ui/node_modules/ink/build/components/Box.js +20 -0
  181. node_ui/node_modules/ink/build/components/Box.js.map +1 -0
  182. node_ui/node_modules/ink/build/components/Color.js +62 -0
  183. node_ui/node_modules/ink/build/components/ErrorOverview.d.ts +6 -0
  184. node_ui/node_modules/ink/build/components/ErrorOverview.js +79 -0
  185. node_ui/node_modules/ink/build/components/ErrorOverview.js.map +1 -0
  186. node_ui/node_modules/ink/build/components/FocusContext.d.ts +17 -0
  187. node_ui/node_modules/ink/build/components/FocusContext.js +17 -0
  188. node_ui/node_modules/ink/build/components/FocusContext.js.map +1 -0
  189. node_ui/node_modules/ink/build/components/Newline.d.ts +13 -0
  190. node_ui/node_modules/ink/build/components/Newline.js +8 -0
  191. node_ui/node_modules/ink/build/components/Newline.js.map +1 -0
  192. node_ui/node_modules/ink/build/components/Spacer.d.ts +6 -0
  193. node_ui/node_modules/ink/build/components/Spacer.js +10 -0
  194. node_ui/node_modules/ink/build/components/Spacer.js.map +1 -0
  195. node_ui/node_modules/ink/build/components/Static.d.ts +31 -0
  196. node_ui/node_modules/ink/build/components/Static.js +33 -0
  197. node_ui/node_modules/ink/build/components/Static.js.map +1 -0
  198. node_ui/node_modules/ink/build/components/StderrContext.d.ts +19 -0
  199. node_ui/node_modules/ink/build/components/StderrContext.js +13 -0
  200. node_ui/node_modules/ink/build/components/StderrContext.js.map +1 -0
  201. node_ui/node_modules/ink/build/components/StdinContext.d.ts +26 -0
  202. node_ui/node_modules/ink/build/components/StdinContext.js +19 -0
  203. node_ui/node_modules/ink/build/components/StdinContext.js.map +1 -0
  204. node_ui/node_modules/ink/build/components/StdoutContext.d.ts +19 -0
  205. node_ui/node_modules/ink/build/components/StdoutContext.js +13 -0
  206. node_ui/node_modules/ink/build/components/StdoutContext.js.map +1 -0
  207. node_ui/node_modules/ink/build/components/Text.d.ts +49 -0
  208. node_ui/node_modules/ink/build/components/Text.js +40 -0
  209. node_ui/node_modules/ink/build/components/Text.js.map +1 -0
  210. node_ui/node_modules/ink/build/components/Transform.d.ts +15 -0
  211. node_ui/node_modules/ink/build/components/Transform.js +14 -0
  212. node_ui/node_modules/ink/build/components/Transform.js.map +1 -0
  213. node_ui/node_modules/ink/build/devtools-window-polyfill.d.ts +1 -0
  214. node_ui/node_modules/ink/build/devtools-window-polyfill.js +64 -0
  215. node_ui/node_modules/ink/build/devtools-window-polyfill.js.map +1 -0
  216. node_ui/node_modules/ink/build/devtools.d.ts +1 -0
  217. node_ui/node_modules/ink/build/devtools.js +9 -0
  218. node_ui/node_modules/ink/build/devtools.js.map +1 -0
  219. node_ui/node_modules/ink/build/dom.d.ts +42 -0
  220. node_ui/node_modules/ink/build/dom.js +117 -0
  221. node_ui/node_modules/ink/build/dom.js.map +1 -0
  222. node_ui/node_modules/ink/build/experimental/apply-style.js +140 -0
  223. node_ui/node_modules/ink/build/experimental/dom.js +123 -0
  224. node_ui/node_modules/ink/build/experimental/output.js +91 -0
  225. node_ui/node_modules/ink/build/experimental/reconciler.js +141 -0
  226. node_ui/node_modules/ink/build/experimental/renderer.js +81 -0
  227. node_ui/node_modules/ink/build/get-max-width.d.ts +3 -0
  228. node_ui/node_modules/ink/build/get-max-width.js +10 -0
  229. node_ui/node_modules/ink/build/get-max-width.js.map +1 -0
  230. node_ui/node_modules/ink/build/hooks/use-app.d.ts +5 -0
  231. node_ui/node_modules/ink/build/hooks/use-app.js +8 -0
  232. node_ui/node_modules/ink/build/hooks/use-app.js.map +1 -0
  233. node_ui/node_modules/ink/build/hooks/use-focus-manager.d.ts +34 -0
  234. node_ui/node_modules/ink/build/hooks/use-focus-manager.js +18 -0
  235. node_ui/node_modules/ink/build/hooks/use-focus-manager.js.map +1 -0
  236. node_ui/node_modules/ink/build/hooks/use-focus.d.ts +34 -0
  237. node_ui/node_modules/ink/build/hooks/use-focus.js +47 -0
  238. node_ui/node_modules/ink/build/hooks/use-focus.js.map +1 -0
  239. node_ui/node_modules/ink/build/hooks/use-input.d.ts +97 -0
  240. node_ui/node_modules/ink/build/hooks/use-input.js +96 -0
  241. node_ui/node_modules/ink/build/hooks/use-input.js.map +1 -0
  242. node_ui/node_modules/ink/build/hooks/use-stderr.d.ts +5 -0
  243. node_ui/node_modules/ink/build/hooks/use-stderr.js +8 -0
  244. node_ui/node_modules/ink/build/hooks/use-stderr.js.map +1 -0
  245. node_ui/node_modules/ink/build/hooks/use-stdin.d.ts +5 -0
  246. node_ui/node_modules/ink/build/hooks/use-stdin.js +8 -0
  247. node_ui/node_modules/ink/build/hooks/use-stdin.js.map +1 -0
  248. node_ui/node_modules/ink/build/hooks/use-stdout.d.ts +5 -0
  249. node_ui/node_modules/ink/build/hooks/use-stdout.js +8 -0
  250. node_ui/node_modules/ink/build/hooks/use-stdout.js.map +1 -0
  251. node_ui/node_modules/ink/build/hooks/useInput.js +38 -0
  252. node_ui/node_modules/ink/build/index.d.ts +27 -0
  253. node_ui/node_modules/ink/build/index.js +16 -0
  254. node_ui/node_modules/ink/build/index.js.map +1 -0
  255. node_ui/node_modules/ink/build/ink.d.ts +38 -0
  256. node_ui/node_modules/ink/build/ink.js +235 -0
  257. node_ui/node_modules/ink/build/ink.js.map +1 -0
  258. node_ui/node_modules/ink/build/instance.js +205 -0
  259. node_ui/node_modules/ink/build/instances.d.ts +4 -0
  260. node_ui/node_modules/ink/build/instances.js +8 -0
  261. node_ui/node_modules/ink/build/instances.js.map +1 -0
  262. node_ui/node_modules/ink/build/log-update.d.ts +13 -0
  263. node_ui/node_modules/ink/build/log-update.js +37 -0
  264. node_ui/node_modules/ink/build/log-update.js.map +1 -0
  265. node_ui/node_modules/ink/build/measure-element.d.ts +16 -0
  266. node_ui/node_modules/ink/build/measure-element.js +9 -0
  267. node_ui/node_modules/ink/build/measure-element.js.map +1 -0
  268. node_ui/node_modules/ink/build/measure-text.d.ts +6 -0
  269. node_ui/node_modules/ink/build/measure-text.js +20 -0
  270. node_ui/node_modules/ink/build/measure-text.js.map +1 -0
  271. node_ui/node_modules/ink/build/output.d.ts +35 -0
  272. node_ui/node_modules/ink/build/output.js +148 -0
  273. node_ui/node_modules/ink/build/output.js.map +1 -0
  274. node_ui/node_modules/ink/build/parse-keypress.d.ts +15 -0
  275. node_ui/node_modules/ink/build/parse-keypress.js +225 -0
  276. node_ui/node_modules/ink/build/parse-keypress.js.map +1 -0
  277. node_ui/node_modules/ink/build/reconciler.d.ts +4 -0
  278. node_ui/node_modules/ink/build/reconciler.js +219 -0
  279. node_ui/node_modules/ink/build/reconciler.js.map +1 -0
  280. node_ui/node_modules/ink/build/render-border.d.ts +4 -0
  281. node_ui/node_modules/ink/build/render-border.js +73 -0
  282. node_ui/node_modules/ink/build/render-border.js.map +1 -0
  283. node_ui/node_modules/ink/build/render-node-to-output.d.ts +10 -0
  284. node_ui/node_modules/ink/build/render-node-to-output.js +99 -0
  285. node_ui/node_modules/ink/build/render-node-to-output.js.map +1 -0
  286. node_ui/node_modules/ink/build/render.d.ts +68 -0
  287. node_ui/node_modules/ink/build/render.js +48 -0
  288. node_ui/node_modules/ink/build/render.js.map +1 -0
  289. node_ui/node_modules/ink/build/renderer.d.ts +8 -0
  290. node_ui/node_modules/ink/build/renderer.js +36 -0
  291. node_ui/node_modules/ink/build/renderer.js.map +1 -0
  292. node_ui/node_modules/ink/build/squash-text-nodes.d.ts +3 -0
  293. node_ui/node_modules/ink/build/squash-text-nodes.js +35 -0
  294. node_ui/node_modules/ink/build/squash-text-nodes.js.map +1 -0
  295. node_ui/node_modules/ink/build/styles.d.ts +243 -0
  296. node_ui/node_modules/ink/build/styles.js +229 -0
  297. node_ui/node_modules/ink/build/styles.js.map +1 -0
  298. node_ui/node_modules/ink/build/wrap-text.d.ts +3 -0
  299. node_ui/node_modules/ink/build/wrap-text.js +31 -0
  300. node_ui/node_modules/ink/build/wrap-text.js.map +1 -0
  301. node_ui/node_modules/ink/license +9 -0
  302. node_ui/node_modules/ink/package.json +197 -0
  303. node_ui/node_modules/ink/readme.md +2153 -0
  304. node_ui/node_modules/ink-select-input/build/Indicator.d.ts +6 -0
  305. node_ui/node_modules/ink-select-input/build/Indicator.js +8 -0
  306. node_ui/node_modules/ink-select-input/build/Indicator.js.map +1 -0
  307. node_ui/node_modules/ink-select-input/build/Item.d.ts +7 -0
  308. node_ui/node_modules/ink-select-input/build/Item.js +7 -0
  309. node_ui/node_modules/ink-select-input/build/Item.js.map +1 -0
  310. node_ui/node_modules/ink-select-input/build/SelectInput.d.ts +49 -0
  311. node_ui/node_modules/ink-select-input/build/SelectInput.js +83 -0
  312. node_ui/node_modules/ink-select-input/build/SelectInput.js.map +1 -0
  313. node_ui/node_modules/ink-select-input/build/index.d.ts +3 -0
  314. node_ui/node_modules/ink-select-input/build/index.js +4 -0
  315. node_ui/node_modules/ink-select-input/build/index.js.map +1 -0
  316. node_ui/node_modules/ink-select-input/license +9 -0
  317. node_ui/node_modules/ink-select-input/node_modules/figures/index.d.ts +279 -0
  318. node_ui/node_modules/ink-select-input/node_modules/figures/index.js +292 -0
  319. node_ui/node_modules/ink-select-input/node_modules/figures/license +9 -0
  320. node_ui/node_modules/ink-select-input/node_modules/figures/package.json +49 -0
  321. node_ui/node_modules/ink-select-input/node_modules/figures/readme.md +337 -0
  322. node_ui/node_modules/ink-select-input/node_modules/is-unicode-supported/index.d.ts +12 -0
  323. node_ui/node_modules/ink-select-input/node_modules/is-unicode-supported/index.js +21 -0
  324. node_ui/node_modules/ink-select-input/node_modules/is-unicode-supported/license +9 -0
  325. node_ui/node_modules/ink-select-input/node_modules/is-unicode-supported/package.json +47 -0
  326. node_ui/node_modules/ink-select-input/node_modules/is-unicode-supported/readme.md +35 -0
  327. node_ui/node_modules/ink-select-input/package.json +83 -0
  328. node_ui/node_modules/ink-select-input/readme.md +98 -0
  329. node_ui/node_modules/is-fullwidth-code-point/index.d.ts +17 -0
  330. node_ui/node_modules/is-fullwidth-code-point/index.js +40 -0
  331. node_ui/node_modules/is-fullwidth-code-point/license +9 -0
  332. node_ui/node_modules/is-fullwidth-code-point/package.json +45 -0
  333. node_ui/node_modules/is-fullwidth-code-point/readme.md +43 -0
  334. node_ui/node_modules/is-in-ci/cli.js +5 -0
  335. node_ui/node_modules/is-in-ci/index.d.ts +15 -0
  336. node_ui/node_modules/is-in-ci/index.js +11 -0
  337. node_ui/node_modules/is-in-ci/license +9 -0
  338. node_ui/node_modules/is-in-ci/package.json +48 -0
  339. node_ui/node_modules/is-in-ci/readme.md +43 -0
  340. node_ui/node_modules/is-unicode-supported/index.d.ts +12 -0
  341. node_ui/node_modules/is-unicode-supported/index.js +17 -0
  342. node_ui/node_modules/is-unicode-supported/license +9 -0
  343. node_ui/node_modules/is-unicode-supported/package.json +43 -0
  344. node_ui/node_modules/is-unicode-supported/readme.md +35 -0
  345. node_ui/node_modules/js-tokens/CHANGELOG.md +151 -0
  346. node_ui/node_modules/js-tokens/LICENSE +21 -0
  347. node_ui/node_modules/js-tokens/README.md +240 -0
  348. node_ui/node_modules/js-tokens/index.js +23 -0
  349. node_ui/node_modules/js-tokens/package.json +30 -0
  350. node_ui/node_modules/lodash/LICENSE +47 -0
  351. node_ui/node_modules/lodash/README.md +39 -0
  352. node_ui/node_modules/lodash/_DataView.js +7 -0
  353. node_ui/node_modules/lodash/_Hash.js +32 -0
  354. node_ui/node_modules/lodash/_LazyWrapper.js +28 -0
  355. node_ui/node_modules/lodash/_ListCache.js +32 -0
  356. node_ui/node_modules/lodash/_LodashWrapper.js +22 -0
  357. node_ui/node_modules/lodash/_Map.js +7 -0
  358. node_ui/node_modules/lodash/_MapCache.js +32 -0
  359. node_ui/node_modules/lodash/_Promise.js +7 -0
  360. node_ui/node_modules/lodash/_Set.js +7 -0
  361. node_ui/node_modules/lodash/_SetCache.js +27 -0
  362. node_ui/node_modules/lodash/_Stack.js +27 -0
  363. node_ui/node_modules/lodash/_Symbol.js +6 -0
  364. node_ui/node_modules/lodash/_Uint8Array.js +6 -0
  365. node_ui/node_modules/lodash/_WeakMap.js +7 -0
  366. node_ui/node_modules/lodash/_apply.js +21 -0
  367. node_ui/node_modules/lodash/_arrayAggregator.js +22 -0
  368. node_ui/node_modules/lodash/_arrayEach.js +22 -0
  369. node_ui/node_modules/lodash/_arrayEachRight.js +21 -0
  370. node_ui/node_modules/lodash/_arrayEvery.js +23 -0
  371. node_ui/node_modules/lodash/_arrayFilter.js +25 -0
  372. node_ui/node_modules/lodash/_arrayIncludes.js +17 -0
  373. node_ui/node_modules/lodash/_arrayIncludesWith.js +22 -0
  374. node_ui/node_modules/lodash/_arrayLikeKeys.js +49 -0
  375. node_ui/node_modules/lodash/_arrayMap.js +21 -0
  376. node_ui/node_modules/lodash/_arrayPush.js +20 -0
  377. node_ui/node_modules/lodash/_arrayReduce.js +26 -0
  378. node_ui/node_modules/lodash/_arrayReduceRight.js +24 -0
  379. node_ui/node_modules/lodash/_arraySample.js +15 -0
  380. node_ui/node_modules/lodash/_arraySampleSize.js +17 -0
  381. node_ui/node_modules/lodash/_arrayShuffle.js +15 -0
  382. node_ui/node_modules/lodash/_arraySome.js +23 -0
  383. node_ui/node_modules/lodash/_asciiSize.js +12 -0
  384. node_ui/node_modules/lodash/_asciiToArray.js +12 -0
  385. node_ui/node_modules/lodash/_asciiWords.js +15 -0
  386. node_ui/node_modules/lodash/_assignMergeValue.js +20 -0
  387. node_ui/node_modules/lodash/_assignValue.js +28 -0
  388. node_ui/node_modules/lodash/_assocIndexOf.js +21 -0
  389. node_ui/node_modules/lodash/_baseAggregator.js +21 -0
  390. node_ui/node_modules/lodash/_baseAssign.js +17 -0
  391. node_ui/node_modules/lodash/_baseAssignIn.js +17 -0
  392. node_ui/node_modules/lodash/_baseAssignValue.js +25 -0
  393. node_ui/node_modules/lodash/_baseAt.js +23 -0
  394. node_ui/node_modules/lodash/_baseClamp.js +22 -0
  395. node_ui/node_modules/lodash/_baseClone.js +166 -0
  396. node_ui/node_modules/lodash/_baseConforms.js +18 -0
  397. node_ui/node_modules/lodash/_baseConformsTo.js +27 -0
  398. node_ui/node_modules/lodash/_baseCreate.js +30 -0
  399. node_ui/node_modules/lodash/_baseDelay.js +21 -0
  400. node_ui/node_modules/lodash/_baseDifference.js +67 -0
  401. node_ui/node_modules/lodash/_baseEach.js +14 -0
  402. node_ui/node_modules/lodash/_baseEachRight.js +14 -0
  403. node_ui/node_modules/lodash/_baseEvery.js +21 -0
  404. node_ui/node_modules/lodash/_baseExtremum.js +32 -0
  405. node_ui/node_modules/lodash/_baseFill.js +32 -0
  406. node_ui/node_modules/lodash/_baseFilter.js +21 -0
  407. node_ui/node_modules/lodash/_baseFindIndex.js +24 -0
  408. node_ui/node_modules/lodash/_baseFindKey.js +23 -0
  409. node_ui/node_modules/lodash/_baseFlatten.js +38 -0
  410. node_ui/node_modules/lodash/_baseFor.js +16 -0
  411. node_ui/node_modules/lodash/_baseForOwn.js +16 -0
  412. node_ui/node_modules/lodash/_baseForOwnRight.js +16 -0
  413. node_ui/node_modules/lodash/_baseForRight.js +15 -0
  414. node_ui/node_modules/lodash/_baseFunctions.js +19 -0
  415. node_ui/node_modules/lodash/_baseGet.js +24 -0
  416. node_ui/node_modules/lodash/_baseGetAllKeys.js +20 -0
  417. node_ui/node_modules/lodash/_baseGetTag.js +28 -0
  418. node_ui/node_modules/lodash/_baseGt.js +14 -0
  419. node_ui/node_modules/lodash/_baseHas.js +19 -0
  420. node_ui/node_modules/lodash/_baseHasIn.js +13 -0
  421. node_ui/node_modules/lodash/_baseInRange.js +18 -0
  422. node_ui/node_modules/lodash/_baseIndexOf.js +20 -0
  423. node_ui/node_modules/lodash/_baseIndexOfWith.js +23 -0
  424. node_ui/node_modules/lodash/_baseIntersection.js +74 -0
  425. node_ui/node_modules/lodash/_baseInverter.js +21 -0
  426. node_ui/node_modules/lodash/_baseInvoke.js +24 -0
  427. node_ui/node_modules/lodash/_baseIsArguments.js +18 -0
  428. node_ui/node_modules/lodash/_baseIsArrayBuffer.js +17 -0
  429. node_ui/node_modules/lodash/_baseIsDate.js +18 -0
  430. node_ui/node_modules/lodash/_baseIsEqual.js +28 -0
  431. node_ui/node_modules/lodash/_baseIsEqualDeep.js +83 -0
  432. node_ui/node_modules/lodash/_baseIsMap.js +18 -0
  433. node_ui/node_modules/lodash/_baseIsMatch.js +62 -0
  434. node_ui/node_modules/lodash/_baseIsNaN.js +12 -0
  435. node_ui/node_modules/lodash/_baseIsNative.js +47 -0
  436. node_ui/node_modules/lodash/_baseIsRegExp.js +18 -0
  437. node_ui/node_modules/lodash/_baseIsSet.js +18 -0
  438. node_ui/node_modules/lodash/_baseIsTypedArray.js +60 -0
  439. node_ui/node_modules/lodash/_baseIteratee.js +31 -0
  440. node_ui/node_modules/lodash/_baseKeys.js +30 -0
  441. node_ui/node_modules/lodash/_baseKeysIn.js +33 -0
  442. node_ui/node_modules/lodash/_baseLodash.js +10 -0
  443. node_ui/node_modules/lodash/_baseLt.js +14 -0
  444. node_ui/node_modules/lodash/_baseMap.js +22 -0
  445. node_ui/node_modules/lodash/_baseMatches.js +22 -0
  446. node_ui/node_modules/lodash/_baseMatchesProperty.js +33 -0
  447. node_ui/node_modules/lodash/_baseMean.js +20 -0
  448. node_ui/node_modules/lodash/_baseMerge.js +42 -0
  449. node_ui/node_modules/lodash/_baseMergeDeep.js +94 -0
  450. node_ui/node_modules/lodash/_baseNth.js +20 -0
  451. node_ui/node_modules/lodash/_baseOrderBy.js +49 -0
  452. node_ui/node_modules/lodash/_basePick.js +19 -0
  453. node_ui/node_modules/lodash/_basePickBy.js +30 -0
  454. node_ui/node_modules/lodash/_baseProperty.js +14 -0
  455. node_ui/node_modules/lodash/_basePropertyDeep.js +16 -0
  456. node_ui/node_modules/lodash/_basePropertyOf.js +14 -0
  457. node_ui/node_modules/lodash/_basePullAll.js +51 -0
  458. node_ui/node_modules/lodash/_basePullAt.js +37 -0
  459. node_ui/node_modules/lodash/_baseRandom.js +18 -0
  460. node_ui/node_modules/lodash/_baseRange.js +28 -0
  461. node_ui/node_modules/lodash/_baseReduce.js +23 -0
  462. node_ui/node_modules/lodash/_baseRepeat.js +35 -0
  463. node_ui/node_modules/lodash/_baseRest.js +17 -0
  464. node_ui/node_modules/lodash/_baseSample.js +15 -0
  465. node_ui/node_modules/lodash/_baseSampleSize.js +18 -0
  466. node_ui/node_modules/lodash/_baseSet.js +51 -0
  467. node_ui/node_modules/lodash/_baseSetData.js +17 -0
  468. node_ui/node_modules/lodash/_baseSetToString.js +22 -0
  469. node_ui/node_modules/lodash/_baseShuffle.js +15 -0
  470. node_ui/node_modules/lodash/_baseSlice.js +31 -0
  471. node_ui/node_modules/lodash/_baseSome.js +22 -0
  472. node_ui/node_modules/lodash/_baseSortBy.js +21 -0
  473. node_ui/node_modules/lodash/_baseSortedIndex.js +42 -0
  474. node_ui/node_modules/lodash/_baseSortedIndexBy.js +67 -0
  475. node_ui/node_modules/lodash/_baseSortedUniq.js +30 -0
  476. node_ui/node_modules/lodash/_baseSum.js +24 -0
  477. node_ui/node_modules/lodash/_baseTimes.js +20 -0
  478. node_ui/node_modules/lodash/_baseToNumber.js +24 -0
  479. node_ui/node_modules/lodash/_baseToPairs.js +18 -0
  480. node_ui/node_modules/lodash/_baseToString.js +37 -0
  481. node_ui/node_modules/lodash/_baseTrim.js +19 -0
  482. node_ui/node_modules/lodash/_baseUnary.js +14 -0
  483. node_ui/node_modules/lodash/_baseUniq.js +72 -0
  484. node_ui/node_modules/lodash/_baseUnset.js +20 -0
  485. node_ui/node_modules/lodash/_baseUpdate.js +18 -0
  486. node_ui/node_modules/lodash/_baseValues.js +19 -0
  487. node_ui/node_modules/lodash/_baseWhile.js +26 -0
  488. node_ui/node_modules/lodash/_baseWrapperValue.js +25 -0
  489. node_ui/node_modules/lodash/_baseXor.js +36 -0
  490. node_ui/node_modules/lodash/_baseZipObject.js +23 -0
  491. node_ui/node_modules/lodash/_cacheHas.js +13 -0
  492. node_ui/node_modules/lodash/_castArrayLikeObject.js +14 -0
  493. node_ui/node_modules/lodash/_castFunction.js +14 -0
  494. node_ui/node_modules/lodash/_castPath.js +21 -0
  495. node_ui/node_modules/lodash/_castRest.js +14 -0
  496. node_ui/node_modules/lodash/_castSlice.js +18 -0
  497. node_ui/node_modules/lodash/_charsEndIndex.js +19 -0
  498. node_ui/node_modules/lodash/_charsStartIndex.js +20 -0
  499. node_ui/node_modules/lodash/_cloneArrayBuffer.js +16 -0
  500. node_ui/node_modules/lodash/_cloneBuffer.js +35 -0
  501. node_ui/node_modules/lodash/_cloneDataView.js +16 -0
  502. node_ui/node_modules/lodash/_cloneRegExp.js +17 -0
  503. node_ui/node_modules/lodash/_cloneSymbol.js +18 -0
  504. node_ui/node_modules/lodash/_cloneTypedArray.js +16 -0
  505. node_ui/node_modules/lodash/_compareAscending.js +41 -0
  506. node_ui/node_modules/lodash/_compareMultiple.js +44 -0
  507. node_ui/node_modules/lodash/_composeArgs.js +39 -0
  508. node_ui/node_modules/lodash/_composeArgsRight.js +41 -0
  509. node_ui/node_modules/lodash/_copyArray.js +20 -0
  510. node_ui/node_modules/lodash/_copyObject.js +40 -0
  511. node_ui/node_modules/lodash/_copySymbols.js +16 -0
  512. node_ui/node_modules/lodash/_copySymbolsIn.js +16 -0
  513. node_ui/node_modules/lodash/_coreJsData.js +6 -0
  514. node_ui/node_modules/lodash/_countHolders.js +21 -0
  515. node_ui/node_modules/lodash/_createAggregator.js +23 -0
  516. node_ui/node_modules/lodash/_createAssigner.js +37 -0
  517. node_ui/node_modules/lodash/_createBaseEach.js +32 -0
  518. node_ui/node_modules/lodash/_createBaseFor.js +25 -0
  519. node_ui/node_modules/lodash/_createBind.js +28 -0
  520. node_ui/node_modules/lodash/_createCaseFirst.js +33 -0
  521. node_ui/node_modules/lodash/_createCompounder.js +24 -0
  522. node_ui/node_modules/lodash/_createCtor.js +37 -0
  523. node_ui/node_modules/lodash/_createCurry.js +46 -0
  524. node_ui/node_modules/lodash/_createFind.js +25 -0
  525. node_ui/node_modules/lodash/_createFlow.js +78 -0
  526. node_ui/node_modules/lodash/_createHybrid.js +92 -0
  527. node_ui/node_modules/lodash/_createInverter.js +17 -0
  528. node_ui/node_modules/lodash/_createMathOperation.js +38 -0
  529. node_ui/node_modules/lodash/_createOver.js +27 -0
  530. node_ui/node_modules/lodash/_createPadding.js +33 -0
  531. node_ui/node_modules/lodash/_createPartial.js +43 -0
  532. node_ui/node_modules/lodash/_createRange.js +30 -0
  533. node_ui/node_modules/lodash/_createRecurry.js +56 -0
  534. node_ui/node_modules/lodash/_createRelationalOperation.js +20 -0
  535. node_ui/node_modules/lodash/_createRound.js +35 -0
  536. node_ui/node_modules/lodash/_createSet.js +19 -0
  537. node_ui/node_modules/lodash/_createToPairs.js +30 -0
  538. node_ui/node_modules/lodash/_createWrap.js +106 -0
  539. node_ui/node_modules/lodash/_customDefaultsAssignIn.js +29 -0
  540. node_ui/node_modules/lodash/_customDefaultsMerge.js +28 -0
  541. node_ui/node_modules/lodash/_customOmitClone.js +16 -0
  542. node_ui/node_modules/lodash/_deburrLetter.js +71 -0
  543. node_ui/node_modules/lodash/_defineProperty.js +11 -0
  544. node_ui/node_modules/lodash/_equalArrays.js +84 -0
  545. node_ui/node_modules/lodash/_equalByTag.js +112 -0
  546. node_ui/node_modules/lodash/_equalObjects.js +90 -0
  547. node_ui/node_modules/lodash/_escapeHtmlChar.js +21 -0
  548. node_ui/node_modules/lodash/_escapeStringChar.js +22 -0
  549. node_ui/node_modules/lodash/_flatRest.js +16 -0
  550. node_ui/node_modules/lodash/_freeGlobal.js +4 -0
  551. node_ui/node_modules/lodash/_getAllKeys.js +16 -0
  552. node_ui/node_modules/lodash/_getAllKeysIn.js +17 -0
  553. node_ui/node_modules/lodash/_getData.js +15 -0
  554. node_ui/node_modules/lodash/_getFuncName.js +31 -0
  555. node_ui/node_modules/lodash/_getHolder.js +13 -0
  556. node_ui/node_modules/lodash/_getMapData.js +18 -0
  557. node_ui/node_modules/lodash/_getMatchData.js +24 -0
  558. node_ui/node_modules/lodash/_getNative.js +17 -0
  559. node_ui/node_modules/lodash/_getPrototype.js +6 -0
  560. node_ui/node_modules/lodash/_getRawTag.js +46 -0
  561. node_ui/node_modules/lodash/_getSymbols.js +30 -0
  562. node_ui/node_modules/lodash/_getSymbolsIn.js +25 -0
  563. node_ui/node_modules/lodash/_getTag.js +58 -0
  564. node_ui/node_modules/lodash/_getValue.js +13 -0
  565. node_ui/node_modules/lodash/_getView.js +33 -0
  566. node_ui/node_modules/lodash/_getWrapDetails.js +17 -0
  567. node_ui/node_modules/lodash/_hasPath.js +39 -0
  568. node_ui/node_modules/lodash/_hasUnicode.js +26 -0
  569. node_ui/node_modules/lodash/_hasUnicodeWord.js +15 -0
  570. node_ui/node_modules/lodash/_hashClear.js +15 -0
  571. node_ui/node_modules/lodash/_hashDelete.js +17 -0
  572. node_ui/node_modules/lodash/_hashGet.js +30 -0
  573. node_ui/node_modules/lodash/_hashHas.js +23 -0
  574. node_ui/node_modules/lodash/_hashSet.js +23 -0
  575. node_ui/node_modules/lodash/_initCloneArray.js +26 -0
  576. node_ui/node_modules/lodash/_initCloneByTag.js +77 -0
  577. node_ui/node_modules/lodash/_initCloneObject.js +18 -0
  578. node_ui/node_modules/lodash/_insertWrapDetails.js +23 -0
  579. node_ui/node_modules/lodash/_isFlattenable.js +20 -0
  580. node_ui/node_modules/lodash/_isIndex.js +25 -0
  581. node_ui/node_modules/lodash/_isIterateeCall.js +30 -0
  582. node_ui/node_modules/lodash/_isKey.js +29 -0
  583. node_ui/node_modules/lodash/_isKeyable.js +15 -0
  584. node_ui/node_modules/lodash/_isLaziable.js +28 -0
  585. node_ui/node_modules/lodash/_isMaskable.js +14 -0
  586. node_ui/node_modules/lodash/_isMasked.js +20 -0
  587. node_ui/node_modules/lodash/_isPrototype.js +18 -0
  588. node_ui/node_modules/lodash/_isStrictComparable.js +15 -0
  589. node_ui/node_modules/lodash/_iteratorToArray.js +18 -0
  590. node_ui/node_modules/lodash/_lazyClone.js +23 -0
  591. node_ui/node_modules/lodash/_lazyReverse.js +23 -0
  592. node_ui/node_modules/lodash/_lazyValue.js +69 -0
  593. node_ui/node_modules/lodash/_listCacheClear.js +13 -0
  594. node_ui/node_modules/lodash/_listCacheDelete.js +35 -0
  595. node_ui/node_modules/lodash/_listCacheGet.js +19 -0
  596. node_ui/node_modules/lodash/_listCacheHas.js +16 -0
  597. node_ui/node_modules/lodash/_listCacheSet.js +26 -0
  598. node_ui/node_modules/lodash/_mapCacheClear.js +21 -0
  599. node_ui/node_modules/lodash/_mapCacheDelete.js +18 -0
  600. node_ui/node_modules/lodash/_mapCacheGet.js +16 -0
  601. node_ui/node_modules/lodash/_mapCacheHas.js +16 -0
  602. node_ui/node_modules/lodash/_mapCacheSet.js +22 -0
  603. node_ui/node_modules/lodash/_mapToArray.js +18 -0
  604. node_ui/node_modules/lodash/_matchesStrictComparable.js +20 -0
  605. node_ui/node_modules/lodash/_memoizeCapped.js +26 -0
  606. node_ui/node_modules/lodash/_mergeData.js +90 -0
  607. node_ui/node_modules/lodash/_metaMap.js +6 -0
  608. node_ui/node_modules/lodash/_nativeCreate.js +6 -0
  609. node_ui/node_modules/lodash/_nativeKeys.js +6 -0
  610. node_ui/node_modules/lodash/_nativeKeysIn.js +20 -0
  611. node_ui/node_modules/lodash/_nodeUtil.js +30 -0
  612. node_ui/node_modules/lodash/_objectToString.js +22 -0
  613. node_ui/node_modules/lodash/_overArg.js +15 -0
  614. node_ui/node_modules/lodash/_overRest.js +36 -0
  615. node_ui/node_modules/lodash/_parent.js +16 -0
  616. node_ui/node_modules/lodash/_reEscape.js +4 -0
  617. node_ui/node_modules/lodash/_reEvaluate.js +4 -0
  618. node_ui/node_modules/lodash/_reInterpolate.js +4 -0
  619. node_ui/node_modules/lodash/_realNames.js +4 -0
  620. node_ui/node_modules/lodash/_reorder.js +29 -0
  621. node_ui/node_modules/lodash/_replaceHolders.js +29 -0
  622. node_ui/node_modules/lodash/_root.js +9 -0
  623. node_ui/node_modules/lodash/_safeGet.js +21 -0
  624. node_ui/node_modules/lodash/_setCacheAdd.js +19 -0
  625. node_ui/node_modules/lodash/_setCacheHas.js +14 -0
  626. node_ui/node_modules/lodash/_setData.js +20 -0
  627. node_ui/node_modules/lodash/_setToArray.js +18 -0
  628. node_ui/node_modules/lodash/_setToPairs.js +18 -0
  629. node_ui/node_modules/lodash/_setToString.js +14 -0
  630. node_ui/node_modules/lodash/_setWrapToString.js +21 -0
  631. node_ui/node_modules/lodash/_shortOut.js +37 -0
  632. node_ui/node_modules/lodash/_shuffleSelf.js +28 -0
  633. node_ui/node_modules/lodash/_stackClear.js +15 -0
  634. node_ui/node_modules/lodash/_stackDelete.js +18 -0
  635. node_ui/node_modules/lodash/_stackGet.js +14 -0
  636. node_ui/node_modules/lodash/_stackHas.js +14 -0
  637. node_ui/node_modules/lodash/_stackSet.js +34 -0
  638. node_ui/node_modules/lodash/_strictIndexOf.js +23 -0
  639. node_ui/node_modules/lodash/_strictLastIndexOf.js +21 -0
  640. node_ui/node_modules/lodash/_stringSize.js +18 -0
  641. node_ui/node_modules/lodash/_stringToArray.js +18 -0
  642. node_ui/node_modules/lodash/_stringToPath.js +27 -0
  643. node_ui/node_modules/lodash/_toKey.js +21 -0
  644. node_ui/node_modules/lodash/_toSource.js +26 -0
  645. node_ui/node_modules/lodash/_trimmedEndIndex.js +19 -0
  646. node_ui/node_modules/lodash/_unescapeHtmlChar.js +21 -0
  647. node_ui/node_modules/lodash/_unicodeSize.js +44 -0
  648. node_ui/node_modules/lodash/_unicodeToArray.js +40 -0
  649. node_ui/node_modules/lodash/_unicodeWords.js +69 -0
  650. node_ui/node_modules/lodash/_updateWrapDetails.js +46 -0
  651. node_ui/node_modules/lodash/_wrapperClone.js +23 -0
  652. node_ui/node_modules/lodash/add.js +22 -0
  653. node_ui/node_modules/lodash/after.js +42 -0
  654. node_ui/node_modules/lodash/array.js +67 -0
  655. node_ui/node_modules/lodash/ary.js +29 -0
  656. node_ui/node_modules/lodash/assign.js +58 -0
  657. node_ui/node_modules/lodash/assignIn.js +40 -0
  658. node_ui/node_modules/lodash/assignInWith.js +38 -0
  659. node_ui/node_modules/lodash/assignWith.js +37 -0
  660. node_ui/node_modules/lodash/at.js +23 -0
  661. node_ui/node_modules/lodash/attempt.js +35 -0
  662. node_ui/node_modules/lodash/before.js +40 -0
  663. node_ui/node_modules/lodash/bind.js +57 -0
  664. node_ui/node_modules/lodash/bindAll.js +41 -0
  665. node_ui/node_modules/lodash/bindKey.js +68 -0
  666. node_ui/node_modules/lodash/camelCase.js +29 -0
  667. node_ui/node_modules/lodash/capitalize.js +23 -0
  668. node_ui/node_modules/lodash/castArray.js +44 -0
  669. node_ui/node_modules/lodash/ceil.js +26 -0
  670. node_ui/node_modules/lodash/chain.js +38 -0
  671. node_ui/node_modules/lodash/chunk.js +50 -0
  672. node_ui/node_modules/lodash/clamp.js +39 -0
  673. node_ui/node_modules/lodash/clone.js +36 -0
  674. node_ui/node_modules/lodash/cloneDeep.js +29 -0
  675. node_ui/node_modules/lodash/cloneDeepWith.js +40 -0
  676. node_ui/node_modules/lodash/cloneWith.js +42 -0
  677. node_ui/node_modules/lodash/collection.js +30 -0
  678. node_ui/node_modules/lodash/commit.js +33 -0
  679. node_ui/node_modules/lodash/compact.js +31 -0
  680. node_ui/node_modules/lodash/concat.js +43 -0
  681. node_ui/node_modules/lodash/cond.js +60 -0
  682. node_ui/node_modules/lodash/conforms.js +35 -0
  683. node_ui/node_modules/lodash/conformsTo.js +32 -0
  684. node_ui/node_modules/lodash/constant.js +26 -0
  685. node_ui/node_modules/lodash/core.js +3877 -0
  686. node_ui/node_modules/lodash/core.min.js +29 -0
  687. node_ui/node_modules/lodash/countBy.js +40 -0
  688. node_ui/node_modules/lodash/create.js +43 -0
  689. node_ui/node_modules/lodash/curry.js +57 -0
  690. node_ui/node_modules/lodash/curryRight.js +54 -0
  691. node_ui/node_modules/lodash/date.js +3 -0
  692. node_ui/node_modules/lodash/debounce.js +191 -0
  693. node_ui/node_modules/lodash/deburr.js +45 -0
  694. node_ui/node_modules/lodash/defaultTo.js +25 -0
  695. node_ui/node_modules/lodash/defaults.js +64 -0
  696. node_ui/node_modules/lodash/defaultsDeep.js +30 -0
  697. node_ui/node_modules/lodash/defer.js +26 -0
  698. node_ui/node_modules/lodash/delay.js +28 -0
  699. node_ui/node_modules/lodash/difference.js +33 -0
  700. node_ui/node_modules/lodash/differenceBy.js +44 -0
  701. node_ui/node_modules/lodash/differenceWith.js +40 -0
  702. node_ui/node_modules/lodash/divide.js +22 -0
  703. node_ui/node_modules/lodash/drop.js +38 -0
  704. node_ui/node_modules/lodash/dropRight.js +39 -0
  705. node_ui/node_modules/lodash/dropRightWhile.js +45 -0
  706. node_ui/node_modules/lodash/dropWhile.js +45 -0
  707. node_ui/node_modules/lodash/each.js +1 -0
  708. node_ui/node_modules/lodash/eachRight.js +1 -0
  709. node_ui/node_modules/lodash/endsWith.js +43 -0
  710. node_ui/node_modules/lodash/entries.js +1 -0
  711. node_ui/node_modules/lodash/entriesIn.js +1 -0
  712. node_ui/node_modules/lodash/eq.js +37 -0
  713. node_ui/node_modules/lodash/escape.js +43 -0
  714. node_ui/node_modules/lodash/escapeRegExp.js +32 -0
  715. node_ui/node_modules/lodash/every.js +56 -0
  716. node_ui/node_modules/lodash/extend.js +1 -0
  717. node_ui/node_modules/lodash/extendWith.js +1 -0
  718. node_ui/node_modules/lodash/fill.js +45 -0
  719. node_ui/node_modules/lodash/filter.js +52 -0
  720. node_ui/node_modules/lodash/find.js +42 -0
  721. node_ui/node_modules/lodash/findIndex.js +55 -0
  722. node_ui/node_modules/lodash/findKey.js +44 -0
  723. node_ui/node_modules/lodash/findLast.js +25 -0
  724. node_ui/node_modules/lodash/findLastIndex.js +59 -0
  725. node_ui/node_modules/lodash/findLastKey.js +44 -0
  726. node_ui/node_modules/lodash/first.js +1 -0
  727. node_ui/node_modules/lodash/flake.lock +40 -0
  728. node_ui/node_modules/lodash/flake.nix +20 -0
  729. node_ui/node_modules/lodash/flatMap.js +29 -0
  730. node_ui/node_modules/lodash/flatMapDeep.js +31 -0
  731. node_ui/node_modules/lodash/flatMapDepth.js +31 -0
  732. node_ui/node_modules/lodash/flatten.js +22 -0
  733. node_ui/node_modules/lodash/flattenDeep.js +25 -0
  734. node_ui/node_modules/lodash/flattenDepth.js +33 -0
  735. node_ui/node_modules/lodash/flip.js +28 -0
  736. node_ui/node_modules/lodash/floor.js +26 -0
  737. node_ui/node_modules/lodash/flow.js +27 -0
  738. node_ui/node_modules/lodash/flowRight.js +26 -0
  739. node_ui/node_modules/lodash/forEach.js +41 -0
  740. node_ui/node_modules/lodash/forEachRight.js +31 -0
  741. node_ui/node_modules/lodash/forIn.js +39 -0
  742. node_ui/node_modules/lodash/forInRight.js +37 -0
  743. node_ui/node_modules/lodash/forOwn.js +36 -0
  744. node_ui/node_modules/lodash/forOwnRight.js +34 -0
  745. node_ui/node_modules/lodash/fp/F.js +1 -0
  746. node_ui/node_modules/lodash/fp/T.js +1 -0
  747. node_ui/node_modules/lodash/fp/__.js +1 -0
  748. node_ui/node_modules/lodash/fp/_baseConvert.js +569 -0
  749. node_ui/node_modules/lodash/fp/_convertBrowser.js +18 -0
  750. node_ui/node_modules/lodash/fp/_falseOptions.js +7 -0
  751. node_ui/node_modules/lodash/fp/_mapping.js +358 -0
  752. node_ui/node_modules/lodash/fp/_util.js +16 -0
  753. node_ui/node_modules/lodash/fp/add.js +5 -0
  754. node_ui/node_modules/lodash/fp/after.js +5 -0
  755. node_ui/node_modules/lodash/fp/all.js +1 -0
  756. node_ui/node_modules/lodash/fp/allPass.js +1 -0
  757. node_ui/node_modules/lodash/fp/always.js +1 -0
  758. node_ui/node_modules/lodash/fp/any.js +1 -0
  759. node_ui/node_modules/lodash/fp/anyPass.js +1 -0
  760. node_ui/node_modules/lodash/fp/apply.js +1 -0
  761. node_ui/node_modules/lodash/fp/array.js +2 -0
  762. node_ui/node_modules/lodash/fp/ary.js +5 -0
  763. node_ui/node_modules/lodash/fp/assign.js +5 -0
  764. node_ui/node_modules/lodash/fp/assignAll.js +5 -0
  765. node_ui/node_modules/lodash/fp/assignAllWith.js +5 -0
  766. node_ui/node_modules/lodash/fp/assignIn.js +5 -0
  767. node_ui/node_modules/lodash/fp/assignInAll.js +5 -0
  768. node_ui/node_modules/lodash/fp/assignInAllWith.js +5 -0
  769. node_ui/node_modules/lodash/fp/assignInWith.js +5 -0
  770. node_ui/node_modules/lodash/fp/assignWith.js +5 -0
  771. node_ui/node_modules/lodash/fp/assoc.js +1 -0
  772. node_ui/node_modules/lodash/fp/assocPath.js +1 -0
  773. node_ui/node_modules/lodash/fp/at.js +5 -0
  774. node_ui/node_modules/lodash/fp/attempt.js +5 -0
  775. node_ui/node_modules/lodash/fp/before.js +5 -0
  776. node_ui/node_modules/lodash/fp/bind.js +5 -0
  777. node_ui/node_modules/lodash/fp/bindAll.js +5 -0
  778. node_ui/node_modules/lodash/fp/bindKey.js +5 -0
  779. node_ui/node_modules/lodash/fp/camelCase.js +5 -0
  780. node_ui/node_modules/lodash/fp/capitalize.js +5 -0
  781. node_ui/node_modules/lodash/fp/castArray.js +5 -0
  782. node_ui/node_modules/lodash/fp/ceil.js +5 -0
  783. node_ui/node_modules/lodash/fp/chain.js +5 -0
  784. node_ui/node_modules/lodash/fp/chunk.js +5 -0
  785. node_ui/node_modules/lodash/fp/clamp.js +5 -0
  786. node_ui/node_modules/lodash/fp/clone.js +5 -0
  787. node_ui/node_modules/lodash/fp/cloneDeep.js +5 -0
  788. node_ui/node_modules/lodash/fp/cloneDeepWith.js +5 -0
  789. node_ui/node_modules/lodash/fp/cloneWith.js +5 -0
  790. node_ui/node_modules/lodash/fp/collection.js +2 -0
  791. node_ui/node_modules/lodash/fp/commit.js +5 -0
  792. node_ui/node_modules/lodash/fp/compact.js +5 -0
  793. node_ui/node_modules/lodash/fp/complement.js +1 -0
  794. node_ui/node_modules/lodash/fp/compose.js +1 -0
  795. node_ui/node_modules/lodash/fp/concat.js +5 -0
  796. node_ui/node_modules/lodash/fp/cond.js +5 -0
  797. node_ui/node_modules/lodash/fp/conforms.js +1 -0
  798. node_ui/node_modules/lodash/fp/conformsTo.js +5 -0
  799. node_ui/node_modules/lodash/fp/constant.js +5 -0
  800. node_ui/node_modules/lodash/fp/contains.js +1 -0
  801. node_ui/node_modules/lodash/fp/convert.js +18 -0
  802. node_ui/node_modules/lodash/fp/countBy.js +5 -0
  803. node_ui/node_modules/lodash/fp/create.js +5 -0
  804. node_ui/node_modules/lodash/fp/curry.js +5 -0
  805. node_ui/node_modules/lodash/fp/curryN.js +5 -0
  806. node_ui/node_modules/lodash/fp/curryRight.js +5 -0
  807. node_ui/node_modules/lodash/fp/curryRightN.js +5 -0
  808. node_ui/node_modules/lodash/fp/date.js +2 -0
  809. node_ui/node_modules/lodash/fp/debounce.js +5 -0
  810. node_ui/node_modules/lodash/fp/deburr.js +5 -0
  811. node_ui/node_modules/lodash/fp/defaultTo.js +5 -0
  812. node_ui/node_modules/lodash/fp/defaults.js +5 -0
  813. node_ui/node_modules/lodash/fp/defaultsAll.js +5 -0
  814. node_ui/node_modules/lodash/fp/defaultsDeep.js +5 -0
  815. node_ui/node_modules/lodash/fp/defaultsDeepAll.js +5 -0
  816. node_ui/node_modules/lodash/fp/defer.js +5 -0
  817. node_ui/node_modules/lodash/fp/delay.js +5 -0
  818. node_ui/node_modules/lodash/fp/difference.js +5 -0
  819. node_ui/node_modules/lodash/fp/differenceBy.js +5 -0
  820. node_ui/node_modules/lodash/fp/differenceWith.js +5 -0
  821. node_ui/node_modules/lodash/fp/dissoc.js +1 -0
  822. node_ui/node_modules/lodash/fp/dissocPath.js +1 -0
  823. node_ui/node_modules/lodash/fp/divide.js +5 -0
  824. node_ui/node_modules/lodash/fp/drop.js +5 -0
  825. node_ui/node_modules/lodash/fp/dropLast.js +1 -0
  826. node_ui/node_modules/lodash/fp/dropLastWhile.js +1 -0
  827. node_ui/node_modules/lodash/fp/dropRight.js +5 -0
  828. node_ui/node_modules/lodash/fp/dropRightWhile.js +5 -0
  829. node_ui/node_modules/lodash/fp/dropWhile.js +5 -0
  830. node_ui/node_modules/lodash/fp/each.js +1 -0
  831. node_ui/node_modules/lodash/fp/eachRight.js +1 -0
  832. node_ui/node_modules/lodash/fp/endsWith.js +5 -0
  833. node_ui/node_modules/lodash/fp/entries.js +1 -0
  834. node_ui/node_modules/lodash/fp/entriesIn.js +1 -0
  835. node_ui/node_modules/lodash/fp/eq.js +5 -0
  836. node_ui/node_modules/lodash/fp/equals.js +1 -0
  837. node_ui/node_modules/lodash/fp/escape.js +5 -0
  838. node_ui/node_modules/lodash/fp/escapeRegExp.js +5 -0
  839. node_ui/node_modules/lodash/fp/every.js +5 -0
  840. node_ui/node_modules/lodash/fp/extend.js +1 -0
  841. node_ui/node_modules/lodash/fp/extendAll.js +1 -0
  842. node_ui/node_modules/lodash/fp/extendAllWith.js +1 -0
  843. node_ui/node_modules/lodash/fp/extendWith.js +1 -0
  844. node_ui/node_modules/lodash/fp/fill.js +5 -0
  845. node_ui/node_modules/lodash/fp/filter.js +5 -0
  846. node_ui/node_modules/lodash/fp/find.js +5 -0
  847. node_ui/node_modules/lodash/fp/findFrom.js +5 -0
  848. node_ui/node_modules/lodash/fp/findIndex.js +5 -0
  849. node_ui/node_modules/lodash/fp/findIndexFrom.js +5 -0
  850. node_ui/node_modules/lodash/fp/findKey.js +5 -0
  851. node_ui/node_modules/lodash/fp/findLast.js +5 -0
  852. node_ui/node_modules/lodash/fp/findLastFrom.js +5 -0
  853. node_ui/node_modules/lodash/fp/findLastIndex.js +5 -0
  854. node_ui/node_modules/lodash/fp/findLastIndexFrom.js +5 -0
  855. node_ui/node_modules/lodash/fp/findLastKey.js +5 -0
  856. node_ui/node_modules/lodash/fp/first.js +1 -0
  857. node_ui/node_modules/lodash/fp/flatMap.js +5 -0
  858. node_ui/node_modules/lodash/fp/flatMapDeep.js +5 -0
  859. node_ui/node_modules/lodash/fp/flatMapDepth.js +5 -0
  860. node_ui/node_modules/lodash/fp/flatten.js +5 -0
  861. node_ui/node_modules/lodash/fp/flattenDeep.js +5 -0
  862. node_ui/node_modules/lodash/fp/flattenDepth.js +5 -0
  863. node_ui/node_modules/lodash/fp/flip.js +5 -0
  864. node_ui/node_modules/lodash/fp/floor.js +5 -0
  865. node_ui/node_modules/lodash/fp/flow.js +5 -0
  866. node_ui/node_modules/lodash/fp/flowRight.js +5 -0
  867. node_ui/node_modules/lodash/fp/forEach.js +5 -0
  868. node_ui/node_modules/lodash/fp/forEachRight.js +5 -0
  869. node_ui/node_modules/lodash/fp/forIn.js +5 -0
  870. node_ui/node_modules/lodash/fp/forInRight.js +5 -0
  871. node_ui/node_modules/lodash/fp/forOwn.js +5 -0
  872. node_ui/node_modules/lodash/fp/forOwnRight.js +5 -0
  873. node_ui/node_modules/lodash/fp/fromPairs.js +5 -0
  874. node_ui/node_modules/lodash/fp/function.js +2 -0
  875. node_ui/node_modules/lodash/fp/functions.js +5 -0
  876. node_ui/node_modules/lodash/fp/functionsIn.js +5 -0
  877. node_ui/node_modules/lodash/fp/get.js +5 -0
  878. node_ui/node_modules/lodash/fp/getOr.js +5 -0
  879. node_ui/node_modules/lodash/fp/groupBy.js +5 -0
  880. node_ui/node_modules/lodash/fp/gt.js +5 -0
  881. node_ui/node_modules/lodash/fp/gte.js +5 -0
  882. node_ui/node_modules/lodash/fp/has.js +5 -0
  883. node_ui/node_modules/lodash/fp/hasIn.js +5 -0
  884. node_ui/node_modules/lodash/fp/head.js +5 -0
  885. node_ui/node_modules/lodash/fp/identical.js +1 -0
  886. node_ui/node_modules/lodash/fp/identity.js +5 -0
  887. node_ui/node_modules/lodash/fp/inRange.js +5 -0
  888. node_ui/node_modules/lodash/fp/includes.js +5 -0
  889. node_ui/node_modules/lodash/fp/includesFrom.js +5 -0
  890. node_ui/node_modules/lodash/fp/indexBy.js +1 -0
  891. node_ui/node_modules/lodash/fp/indexOf.js +5 -0
  892. node_ui/node_modules/lodash/fp/indexOfFrom.js +5 -0
  893. node_ui/node_modules/lodash/fp/init.js +1 -0
  894. node_ui/node_modules/lodash/fp/initial.js +5 -0
  895. node_ui/node_modules/lodash/fp/intersection.js +5 -0
  896. node_ui/node_modules/lodash/fp/intersectionBy.js +5 -0
  897. node_ui/node_modules/lodash/fp/intersectionWith.js +5 -0
  898. node_ui/node_modules/lodash/fp/invert.js +5 -0
  899. node_ui/node_modules/lodash/fp/invertBy.js +5 -0
  900. node_ui/node_modules/lodash/fp/invertObj.js +1 -0
  901. node_ui/node_modules/lodash/fp/invoke.js +5 -0
  902. node_ui/node_modules/lodash/fp/invokeArgs.js +5 -0
  903. node_ui/node_modules/lodash/fp/invokeArgsMap.js +5 -0
  904. node_ui/node_modules/lodash/fp/invokeMap.js +5 -0
  905. node_ui/node_modules/lodash/fp/isArguments.js +5 -0
  906. node_ui/node_modules/lodash/fp/isArray.js +5 -0
  907. node_ui/node_modules/lodash/fp/isArrayBuffer.js +5 -0
  908. node_ui/node_modules/lodash/fp/isArrayLike.js +5 -0
  909. node_ui/node_modules/lodash/fp/isArrayLikeObject.js +5 -0
  910. node_ui/node_modules/lodash/fp/isBoolean.js +5 -0
  911. node_ui/node_modules/lodash/fp/isBuffer.js +5 -0
  912. node_ui/node_modules/lodash/fp/isDate.js +5 -0
  913. node_ui/node_modules/lodash/fp/isElement.js +5 -0
  914. node_ui/node_modules/lodash/fp/isEmpty.js +5 -0
  915. node_ui/node_modules/lodash/fp/isEqual.js +5 -0
  916. node_ui/node_modules/lodash/fp/isEqualWith.js +5 -0
  917. node_ui/node_modules/lodash/fp/isError.js +5 -0
  918. node_ui/node_modules/lodash/fp/isFinite.js +5 -0
  919. node_ui/node_modules/lodash/fp/isFunction.js +5 -0
  920. node_ui/node_modules/lodash/fp/isInteger.js +5 -0
  921. node_ui/node_modules/lodash/fp/isLength.js +5 -0
  922. node_ui/node_modules/lodash/fp/isMap.js +5 -0
  923. node_ui/node_modules/lodash/fp/isMatch.js +5 -0
  924. node_ui/node_modules/lodash/fp/isMatchWith.js +5 -0
  925. node_ui/node_modules/lodash/fp/isNaN.js +5 -0
  926. node_ui/node_modules/lodash/fp/isNative.js +5 -0
  927. node_ui/node_modules/lodash/fp/isNil.js +5 -0
  928. node_ui/node_modules/lodash/fp/isNull.js +5 -0
  929. node_ui/node_modules/lodash/fp/isNumber.js +5 -0
  930. node_ui/node_modules/lodash/fp/isObject.js +5 -0
  931. node_ui/node_modules/lodash/fp/isObjectLike.js +5 -0
  932. node_ui/node_modules/lodash/fp/isPlainObject.js +5 -0
  933. node_ui/node_modules/lodash/fp/isRegExp.js +5 -0
  934. node_ui/node_modules/lodash/fp/isSafeInteger.js +5 -0
  935. node_ui/node_modules/lodash/fp/isSet.js +5 -0
  936. node_ui/node_modules/lodash/fp/isString.js +5 -0
  937. node_ui/node_modules/lodash/fp/isSymbol.js +5 -0
  938. node_ui/node_modules/lodash/fp/isTypedArray.js +5 -0
  939. node_ui/node_modules/lodash/fp/isUndefined.js +5 -0
  940. node_ui/node_modules/lodash/fp/isWeakMap.js +5 -0
  941. node_ui/node_modules/lodash/fp/isWeakSet.js +5 -0
  942. node_ui/node_modules/lodash/fp/iteratee.js +5 -0
  943. node_ui/node_modules/lodash/fp/join.js +5 -0
  944. node_ui/node_modules/lodash/fp/juxt.js +1 -0
  945. node_ui/node_modules/lodash/fp/kebabCase.js +5 -0
  946. node_ui/node_modules/lodash/fp/keyBy.js +5 -0
  947. node_ui/node_modules/lodash/fp/keys.js +5 -0
  948. node_ui/node_modules/lodash/fp/keysIn.js +5 -0
  949. node_ui/node_modules/lodash/fp/lang.js +2 -0
  950. node_ui/node_modules/lodash/fp/last.js +5 -0
  951. node_ui/node_modules/lodash/fp/lastIndexOf.js +5 -0
  952. node_ui/node_modules/lodash/fp/lastIndexOfFrom.js +5 -0
  953. node_ui/node_modules/lodash/fp/lowerCase.js +5 -0
  954. node_ui/node_modules/lodash/fp/lowerFirst.js +5 -0
  955. node_ui/node_modules/lodash/fp/lt.js +5 -0
  956. node_ui/node_modules/lodash/fp/lte.js +5 -0
  957. node_ui/node_modules/lodash/fp/map.js +5 -0
  958. node_ui/node_modules/lodash/fp/mapKeys.js +5 -0
  959. node_ui/node_modules/lodash/fp/mapValues.js +5 -0
  960. node_ui/node_modules/lodash/fp/matches.js +1 -0
  961. node_ui/node_modules/lodash/fp/matchesProperty.js +5 -0
  962. node_ui/node_modules/lodash/fp/math.js +2 -0
  963. node_ui/node_modules/lodash/fp/max.js +5 -0
  964. node_ui/node_modules/lodash/fp/maxBy.js +5 -0
  965. node_ui/node_modules/lodash/fp/mean.js +5 -0
  966. node_ui/node_modules/lodash/fp/meanBy.js +5 -0
  967. node_ui/node_modules/lodash/fp/memoize.js +5 -0
  968. node_ui/node_modules/lodash/fp/merge.js +5 -0
  969. node_ui/node_modules/lodash/fp/mergeAll.js +5 -0
  970. node_ui/node_modules/lodash/fp/mergeAllWith.js +5 -0
  971. node_ui/node_modules/lodash/fp/mergeWith.js +5 -0
  972. node_ui/node_modules/lodash/fp/method.js +5 -0
  973. node_ui/node_modules/lodash/fp/methodOf.js +5 -0
  974. node_ui/node_modules/lodash/fp/min.js +5 -0
  975. node_ui/node_modules/lodash/fp/minBy.js +5 -0
  976. node_ui/node_modules/lodash/fp/mixin.js +5 -0
  977. node_ui/node_modules/lodash/fp/multiply.js +5 -0
  978. node_ui/node_modules/lodash/fp/nAry.js +1 -0
  979. node_ui/node_modules/lodash/fp/negate.js +5 -0
  980. node_ui/node_modules/lodash/fp/next.js +5 -0
  981. node_ui/node_modules/lodash/fp/noop.js +5 -0
  982. node_ui/node_modules/lodash/fp/now.js +5 -0
  983. node_ui/node_modules/lodash/fp/nth.js +5 -0
  984. node_ui/node_modules/lodash/fp/nthArg.js +5 -0
  985. node_ui/node_modules/lodash/fp/number.js +2 -0
  986. node_ui/node_modules/lodash/fp/object.js +2 -0
  987. node_ui/node_modules/lodash/fp/omit.js +5 -0
  988. node_ui/node_modules/lodash/fp/omitAll.js +1 -0
  989. node_ui/node_modules/lodash/fp/omitBy.js +5 -0
  990. node_ui/node_modules/lodash/fp/once.js +5 -0
  991. node_ui/node_modules/lodash/fp/orderBy.js +5 -0
  992. node_ui/node_modules/lodash/fp/over.js +5 -0
  993. node_ui/node_modules/lodash/fp/overArgs.js +5 -0
  994. node_ui/node_modules/lodash/fp/overEvery.js +5 -0
  995. node_ui/node_modules/lodash/fp/overSome.js +5 -0
  996. node_ui/node_modules/lodash/fp/pad.js +5 -0
  997. node_ui/node_modules/lodash/fp/padChars.js +5 -0
  998. node_ui/node_modules/lodash/fp/padCharsEnd.js +5 -0
  999. node_ui/node_modules/lodash/fp/padCharsStart.js +5 -0
  1000. node_ui/node_modules/lodash/fp/padEnd.js +5 -0
  1001. node_ui/node_modules/lodash/fp/padStart.js +5 -0
  1002. node_ui/node_modules/lodash/fp/parseInt.js +5 -0
  1003. node_ui/node_modules/lodash/fp/partial.js +5 -0
  1004. node_ui/node_modules/lodash/fp/partialRight.js +5 -0
  1005. node_ui/node_modules/lodash/fp/partition.js +5 -0
  1006. node_ui/node_modules/lodash/fp/path.js +1 -0
  1007. node_ui/node_modules/lodash/fp/pathEq.js +1 -0
  1008. node_ui/node_modules/lodash/fp/pathOr.js +1 -0
  1009. node_ui/node_modules/lodash/fp/paths.js +1 -0
  1010. node_ui/node_modules/lodash/fp/pick.js +5 -0
  1011. node_ui/node_modules/lodash/fp/pickAll.js +1 -0
  1012. node_ui/node_modules/lodash/fp/pickBy.js +5 -0
  1013. node_ui/node_modules/lodash/fp/pipe.js +1 -0
  1014. node_ui/node_modules/lodash/fp/placeholder.js +6 -0
  1015. node_ui/node_modules/lodash/fp/plant.js +5 -0
  1016. node_ui/node_modules/lodash/fp/pluck.js +1 -0
  1017. node_ui/node_modules/lodash/fp/prop.js +1 -0
  1018. node_ui/node_modules/lodash/fp/propEq.js +1 -0
  1019. node_ui/node_modules/lodash/fp/propOr.js +1 -0
  1020. node_ui/node_modules/lodash/fp/property.js +1 -0
  1021. node_ui/node_modules/lodash/fp/propertyOf.js +5 -0
  1022. node_ui/node_modules/lodash/fp/props.js +1 -0
  1023. node_ui/node_modules/lodash/fp/pull.js +5 -0
  1024. node_ui/node_modules/lodash/fp/pullAll.js +5 -0
  1025. node_ui/node_modules/lodash/fp/pullAllBy.js +5 -0
  1026. node_ui/node_modules/lodash/fp/pullAllWith.js +5 -0
  1027. node_ui/node_modules/lodash/fp/pullAt.js +5 -0
  1028. node_ui/node_modules/lodash/fp/random.js +5 -0
  1029. node_ui/node_modules/lodash/fp/range.js +5 -0
  1030. node_ui/node_modules/lodash/fp/rangeRight.js +5 -0
  1031. node_ui/node_modules/lodash/fp/rangeStep.js +5 -0
  1032. node_ui/node_modules/lodash/fp/rangeStepRight.js +5 -0
  1033. node_ui/node_modules/lodash/fp/rearg.js +5 -0
  1034. node_ui/node_modules/lodash/fp/reduce.js +5 -0
  1035. node_ui/node_modules/lodash/fp/reduceRight.js +5 -0
  1036. node_ui/node_modules/lodash/fp/reject.js +5 -0
  1037. node_ui/node_modules/lodash/fp/remove.js +5 -0
  1038. node_ui/node_modules/lodash/fp/repeat.js +5 -0
  1039. node_ui/node_modules/lodash/fp/replace.js +5 -0
  1040. node_ui/node_modules/lodash/fp/rest.js +5 -0
  1041. node_ui/node_modules/lodash/fp/restFrom.js +5 -0
  1042. node_ui/node_modules/lodash/fp/result.js +5 -0
  1043. node_ui/node_modules/lodash/fp/reverse.js +5 -0
  1044. node_ui/node_modules/lodash/fp/round.js +5 -0
  1045. node_ui/node_modules/lodash/fp/sample.js +5 -0
  1046. node_ui/node_modules/lodash/fp/sampleSize.js +5 -0
  1047. node_ui/node_modules/lodash/fp/seq.js +2 -0
  1048. node_ui/node_modules/lodash/fp/set.js +5 -0
  1049. node_ui/node_modules/lodash/fp/setWith.js +5 -0
  1050. node_ui/node_modules/lodash/fp/shuffle.js +5 -0
  1051. node_ui/node_modules/lodash/fp/size.js +5 -0
  1052. node_ui/node_modules/lodash/fp/slice.js +5 -0
  1053. node_ui/node_modules/lodash/fp/snakeCase.js +5 -0
  1054. node_ui/node_modules/lodash/fp/some.js +5 -0
  1055. node_ui/node_modules/lodash/fp/sortBy.js +5 -0
  1056. node_ui/node_modules/lodash/fp/sortedIndex.js +5 -0
  1057. node_ui/node_modules/lodash/fp/sortedIndexBy.js +5 -0
  1058. node_ui/node_modules/lodash/fp/sortedIndexOf.js +5 -0
  1059. node_ui/node_modules/lodash/fp/sortedLastIndex.js +5 -0
  1060. node_ui/node_modules/lodash/fp/sortedLastIndexBy.js +5 -0
  1061. node_ui/node_modules/lodash/fp/sortedLastIndexOf.js +5 -0
  1062. node_ui/node_modules/lodash/fp/sortedUniq.js +5 -0
  1063. node_ui/node_modules/lodash/fp/sortedUniqBy.js +5 -0
  1064. node_ui/node_modules/lodash/fp/split.js +5 -0
  1065. node_ui/node_modules/lodash/fp/spread.js +5 -0
  1066. node_ui/node_modules/lodash/fp/spreadFrom.js +5 -0
  1067. node_ui/node_modules/lodash/fp/startCase.js +5 -0
  1068. node_ui/node_modules/lodash/fp/startsWith.js +5 -0
  1069. node_ui/node_modules/lodash/fp/string.js +2 -0
  1070. node_ui/node_modules/lodash/fp/stubArray.js +5 -0
  1071. node_ui/node_modules/lodash/fp/stubFalse.js +5 -0
  1072. node_ui/node_modules/lodash/fp/stubObject.js +5 -0
  1073. node_ui/node_modules/lodash/fp/stubString.js +5 -0
  1074. node_ui/node_modules/lodash/fp/stubTrue.js +5 -0
  1075. node_ui/node_modules/lodash/fp/subtract.js +5 -0
  1076. node_ui/node_modules/lodash/fp/sum.js +5 -0
  1077. node_ui/node_modules/lodash/fp/sumBy.js +5 -0
  1078. node_ui/node_modules/lodash/fp/symmetricDifference.js +1 -0
  1079. node_ui/node_modules/lodash/fp/symmetricDifferenceBy.js +1 -0
  1080. node_ui/node_modules/lodash/fp/symmetricDifferenceWith.js +1 -0
  1081. node_ui/node_modules/lodash/fp/tail.js +5 -0
  1082. node_ui/node_modules/lodash/fp/take.js +5 -0
  1083. node_ui/node_modules/lodash/fp/takeLast.js +1 -0
  1084. node_ui/node_modules/lodash/fp/takeLastWhile.js +1 -0
  1085. node_ui/node_modules/lodash/fp/takeRight.js +5 -0
  1086. node_ui/node_modules/lodash/fp/takeRightWhile.js +5 -0
  1087. node_ui/node_modules/lodash/fp/takeWhile.js +5 -0
  1088. node_ui/node_modules/lodash/fp/tap.js +5 -0
  1089. node_ui/node_modules/lodash/fp/template.js +5 -0
  1090. node_ui/node_modules/lodash/fp/templateSettings.js +5 -0
  1091. node_ui/node_modules/lodash/fp/throttle.js +5 -0
  1092. node_ui/node_modules/lodash/fp/thru.js +5 -0
  1093. node_ui/node_modules/lodash/fp/times.js +5 -0
  1094. node_ui/node_modules/lodash/fp/toArray.js +5 -0
  1095. node_ui/node_modules/lodash/fp/toFinite.js +5 -0
  1096. node_ui/node_modules/lodash/fp/toInteger.js +5 -0
  1097. node_ui/node_modules/lodash/fp/toIterator.js +5 -0
  1098. node_ui/node_modules/lodash/fp/toJSON.js +5 -0
  1099. node_ui/node_modules/lodash/fp/toLength.js +5 -0
  1100. node_ui/node_modules/lodash/fp/toLower.js +5 -0
  1101. node_ui/node_modules/lodash/fp/toNumber.js +5 -0
  1102. node_ui/node_modules/lodash/fp/toPairs.js +5 -0
  1103. node_ui/node_modules/lodash/fp/toPairsIn.js +5 -0
  1104. node_ui/node_modules/lodash/fp/toPath.js +5 -0
  1105. node_ui/node_modules/lodash/fp/toPlainObject.js +5 -0
  1106. node_ui/node_modules/lodash/fp/toSafeInteger.js +5 -0
  1107. node_ui/node_modules/lodash/fp/toString.js +5 -0
  1108. node_ui/node_modules/lodash/fp/toUpper.js +5 -0
  1109. node_ui/node_modules/lodash/fp/transform.js +5 -0
  1110. node_ui/node_modules/lodash/fp/trim.js +5 -0
  1111. node_ui/node_modules/lodash/fp/trimChars.js +5 -0
  1112. node_ui/node_modules/lodash/fp/trimCharsEnd.js +5 -0
  1113. node_ui/node_modules/lodash/fp/trimCharsStart.js +5 -0
  1114. node_ui/node_modules/lodash/fp/trimEnd.js +5 -0
  1115. node_ui/node_modules/lodash/fp/trimStart.js +5 -0
  1116. node_ui/node_modules/lodash/fp/truncate.js +5 -0
  1117. node_ui/node_modules/lodash/fp/unapply.js +1 -0
  1118. node_ui/node_modules/lodash/fp/unary.js +5 -0
  1119. node_ui/node_modules/lodash/fp/unescape.js +5 -0
  1120. node_ui/node_modules/lodash/fp/union.js +5 -0
  1121. node_ui/node_modules/lodash/fp/unionBy.js +5 -0
  1122. node_ui/node_modules/lodash/fp/unionWith.js +5 -0
  1123. node_ui/node_modules/lodash/fp/uniq.js +5 -0
  1124. node_ui/node_modules/lodash/fp/uniqBy.js +5 -0
  1125. node_ui/node_modules/lodash/fp/uniqWith.js +5 -0
  1126. node_ui/node_modules/lodash/fp/uniqueId.js +5 -0
  1127. node_ui/node_modules/lodash/fp/unnest.js +1 -0
  1128. node_ui/node_modules/lodash/fp/unset.js +5 -0
  1129. node_ui/node_modules/lodash/fp/unzip.js +5 -0
  1130. node_ui/node_modules/lodash/fp/unzipWith.js +5 -0
  1131. node_ui/node_modules/lodash/fp/update.js +5 -0
  1132. node_ui/node_modules/lodash/fp/updateWith.js +5 -0
  1133. node_ui/node_modules/lodash/fp/upperCase.js +5 -0
  1134. node_ui/node_modules/lodash/fp/upperFirst.js +5 -0
  1135. node_ui/node_modules/lodash/fp/useWith.js +1 -0
  1136. node_ui/node_modules/lodash/fp/util.js +2 -0
  1137. node_ui/node_modules/lodash/fp/value.js +5 -0
  1138. node_ui/node_modules/lodash/fp/valueOf.js +5 -0
  1139. node_ui/node_modules/lodash/fp/values.js +5 -0
  1140. node_ui/node_modules/lodash/fp/valuesIn.js +5 -0
  1141. node_ui/node_modules/lodash/fp/where.js +1 -0
  1142. node_ui/node_modules/lodash/fp/whereEq.js +1 -0
  1143. node_ui/node_modules/lodash/fp/without.js +5 -0
  1144. node_ui/node_modules/lodash/fp/words.js +5 -0
  1145. node_ui/node_modules/lodash/fp/wrap.js +5 -0
  1146. node_ui/node_modules/lodash/fp/wrapperAt.js +5 -0
  1147. node_ui/node_modules/lodash/fp/wrapperChain.js +5 -0
  1148. node_ui/node_modules/lodash/fp/wrapperLodash.js +5 -0
  1149. node_ui/node_modules/lodash/fp/wrapperReverse.js +5 -0
  1150. node_ui/node_modules/lodash/fp/wrapperValue.js +5 -0
  1151. node_ui/node_modules/lodash/fp/xor.js +5 -0
  1152. node_ui/node_modules/lodash/fp/xorBy.js +5 -0
  1153. node_ui/node_modules/lodash/fp/xorWith.js +5 -0
  1154. node_ui/node_modules/lodash/fp/zip.js +5 -0
  1155. node_ui/node_modules/lodash/fp/zipAll.js +5 -0
  1156. node_ui/node_modules/lodash/fp/zipObj.js +1 -0
  1157. node_ui/node_modules/lodash/fp/zipObject.js +5 -0
  1158. node_ui/node_modules/lodash/fp/zipObjectDeep.js +5 -0
  1159. node_ui/node_modules/lodash/fp/zipWith.js +5 -0
  1160. node_ui/node_modules/lodash/fp.js +2 -0
  1161. node_ui/node_modules/lodash/fromPairs.js +28 -0
  1162. node_ui/node_modules/lodash/function.js +25 -0
  1163. node_ui/node_modules/lodash/functions.js +31 -0
  1164. node_ui/node_modules/lodash/functionsIn.js +31 -0
  1165. node_ui/node_modules/lodash/get.js +33 -0
  1166. node_ui/node_modules/lodash/groupBy.js +41 -0
  1167. node_ui/node_modules/lodash/gt.js +29 -0
  1168. node_ui/node_modules/lodash/gte.js +30 -0
  1169. node_ui/node_modules/lodash/has.js +35 -0
  1170. node_ui/node_modules/lodash/hasIn.js +34 -0
  1171. node_ui/node_modules/lodash/head.js +23 -0
  1172. node_ui/node_modules/lodash/identity.js +21 -0
  1173. node_ui/node_modules/lodash/inRange.js +55 -0
  1174. node_ui/node_modules/lodash/includes.js +53 -0
  1175. node_ui/node_modules/lodash/index.js +1 -0
  1176. node_ui/node_modules/lodash/indexOf.js +42 -0
  1177. node_ui/node_modules/lodash/initial.js +22 -0
  1178. node_ui/node_modules/lodash/intersection.js +30 -0
  1179. node_ui/node_modules/lodash/intersectionBy.js +45 -0
  1180. node_ui/node_modules/lodash/intersectionWith.js +41 -0
  1181. node_ui/node_modules/lodash/invert.js +42 -0
  1182. node_ui/node_modules/lodash/invertBy.js +56 -0
  1183. node_ui/node_modules/lodash/invoke.js +24 -0
  1184. node_ui/node_modules/lodash/invokeMap.js +41 -0
  1185. node_ui/node_modules/lodash/isArguments.js +36 -0
  1186. node_ui/node_modules/lodash/isArray.js +26 -0
  1187. node_ui/node_modules/lodash/isArrayBuffer.js +27 -0
  1188. node_ui/node_modules/lodash/isArrayLike.js +33 -0
  1189. node_ui/node_modules/lodash/isArrayLikeObject.js +33 -0
  1190. node_ui/node_modules/lodash/isBoolean.js +29 -0
  1191. node_ui/node_modules/lodash/isBuffer.js +38 -0
  1192. node_ui/node_modules/lodash/isDate.js +27 -0
  1193. node_ui/node_modules/lodash/isElement.js +25 -0
  1194. node_ui/node_modules/lodash/isEmpty.js +77 -0
  1195. node_ui/node_modules/lodash/isEqual.js +35 -0
  1196. node_ui/node_modules/lodash/isEqualWith.js +41 -0
  1197. node_ui/node_modules/lodash/isError.js +36 -0
  1198. node_ui/node_modules/lodash/isFinite.js +36 -0
  1199. node_ui/node_modules/lodash/isFunction.js +37 -0
  1200. node_ui/node_modules/lodash/isInteger.js +33 -0
  1201. node_ui/node_modules/lodash/isLength.js +35 -0
  1202. node_ui/node_modules/lodash/isMap.js +27 -0
  1203. node_ui/node_modules/lodash/isMatch.js +36 -0
  1204. node_ui/node_modules/lodash/isMatchWith.js +41 -0
  1205. node_ui/node_modules/lodash/isNaN.js +38 -0
  1206. node_ui/node_modules/lodash/isNative.js +40 -0
  1207. node_ui/node_modules/lodash/isNil.js +25 -0
  1208. node_ui/node_modules/lodash/isNull.js +22 -0
  1209. node_ui/node_modules/lodash/isNumber.js +38 -0
  1210. node_ui/node_modules/lodash/isObject.js +31 -0
  1211. node_ui/node_modules/lodash/isObjectLike.js +29 -0
  1212. node_ui/node_modules/lodash/isPlainObject.js +62 -0
  1213. node_ui/node_modules/lodash/isRegExp.js +27 -0
  1214. node_ui/node_modules/lodash/isSafeInteger.js +37 -0
  1215. node_ui/node_modules/lodash/isSet.js +27 -0
  1216. node_ui/node_modules/lodash/isString.js +30 -0
  1217. node_ui/node_modules/lodash/isSymbol.js +29 -0
  1218. node_ui/node_modules/lodash/isTypedArray.js +27 -0
  1219. node_ui/node_modules/lodash/isUndefined.js +22 -0
  1220. node_ui/node_modules/lodash/isWeakMap.js +28 -0
  1221. node_ui/node_modules/lodash/isWeakSet.js +28 -0
  1222. node_ui/node_modules/lodash/iteratee.js +53 -0
  1223. node_ui/node_modules/lodash/join.js +26 -0
  1224. node_ui/node_modules/lodash/kebabCase.js +28 -0
  1225. node_ui/node_modules/lodash/keyBy.js +36 -0
  1226. node_ui/node_modules/lodash/keys.js +37 -0
  1227. node_ui/node_modules/lodash/keysIn.js +32 -0
  1228. node_ui/node_modules/lodash/lang.js +58 -0
  1229. node_ui/node_modules/lodash/last.js +20 -0
  1230. node_ui/node_modules/lodash/lastIndexOf.js +46 -0
  1231. node_ui/node_modules/lodash/lodash.js +17209 -0
  1232. node_ui/node_modules/lodash/lodash.min.js +140 -0
  1233. node_ui/node_modules/lodash/lowerCase.js +27 -0
  1234. node_ui/node_modules/lodash/lowerFirst.js +22 -0
  1235. node_ui/node_modules/lodash/lt.js +29 -0
  1236. node_ui/node_modules/lodash/lte.js +30 -0
  1237. node_ui/node_modules/lodash/map.js +53 -0
  1238. node_ui/node_modules/lodash/mapKeys.js +36 -0
  1239. node_ui/node_modules/lodash/mapValues.js +43 -0
  1240. node_ui/node_modules/lodash/matches.js +46 -0
  1241. node_ui/node_modules/lodash/matchesProperty.js +44 -0
  1242. node_ui/node_modules/lodash/math.js +17 -0
  1243. node_ui/node_modules/lodash/max.js +29 -0
  1244. node_ui/node_modules/lodash/maxBy.js +34 -0
  1245. node_ui/node_modules/lodash/mean.js +22 -0
  1246. node_ui/node_modules/lodash/meanBy.js +31 -0
  1247. node_ui/node_modules/lodash/memoize.js +73 -0
  1248. node_ui/node_modules/lodash/merge.js +39 -0
  1249. node_ui/node_modules/lodash/mergeWith.js +39 -0
  1250. node_ui/node_modules/lodash/method.js +34 -0
  1251. node_ui/node_modules/lodash/methodOf.js +33 -0
  1252. node_ui/node_modules/lodash/min.js +29 -0
  1253. node_ui/node_modules/lodash/minBy.js +34 -0
  1254. node_ui/node_modules/lodash/mixin.js +74 -0
  1255. node_ui/node_modules/lodash/multiply.js +22 -0
  1256. node_ui/node_modules/lodash/negate.js +40 -0
  1257. node_ui/node_modules/lodash/next.js +35 -0
  1258. node_ui/node_modules/lodash/noop.js +17 -0
  1259. node_ui/node_modules/lodash/now.js +23 -0
  1260. node_ui/node_modules/lodash/nth.js +29 -0
  1261. node_ui/node_modules/lodash/nthArg.js +32 -0
  1262. node_ui/node_modules/lodash/number.js +5 -0
  1263. node_ui/node_modules/lodash/object.js +49 -0
  1264. node_ui/node_modules/lodash/omit.js +57 -0
  1265. node_ui/node_modules/lodash/omitBy.js +29 -0
  1266. node_ui/node_modules/lodash/once.js +25 -0
  1267. node_ui/node_modules/lodash/orderBy.js +47 -0
  1268. node_ui/node_modules/lodash/over.js +24 -0
  1269. node_ui/node_modules/lodash/overArgs.js +61 -0
  1270. node_ui/node_modules/lodash/overEvery.js +34 -0
  1271. node_ui/node_modules/lodash/overSome.js +37 -0
  1272. node_ui/node_modules/lodash/package.json +17 -0
  1273. node_ui/node_modules/lodash/pad.js +49 -0
  1274. node_ui/node_modules/lodash/padEnd.js +39 -0
  1275. node_ui/node_modules/lodash/padStart.js +39 -0
  1276. node_ui/node_modules/lodash/parseInt.js +43 -0
  1277. node_ui/node_modules/lodash/partial.js +50 -0
  1278. node_ui/node_modules/lodash/partialRight.js +49 -0
  1279. node_ui/node_modules/lodash/partition.js +43 -0
  1280. node_ui/node_modules/lodash/pick.js +25 -0
  1281. node_ui/node_modules/lodash/pickBy.js +37 -0
  1282. node_ui/node_modules/lodash/plant.js +48 -0
  1283. node_ui/node_modules/lodash/property.js +32 -0
  1284. node_ui/node_modules/lodash/propertyOf.js +30 -0
  1285. node_ui/node_modules/lodash/pull.js +29 -0
  1286. node_ui/node_modules/lodash/pullAll.js +29 -0
  1287. node_ui/node_modules/lodash/pullAllBy.js +33 -0
  1288. node_ui/node_modules/lodash/pullAllWith.js +32 -0
  1289. node_ui/node_modules/lodash/pullAt.js +43 -0
  1290. node_ui/node_modules/lodash/random.js +82 -0
  1291. node_ui/node_modules/lodash/range.js +46 -0
  1292. node_ui/node_modules/lodash/rangeRight.js +41 -0
  1293. node_ui/node_modules/lodash/rearg.js +33 -0
  1294. node_ui/node_modules/lodash/reduce.js +51 -0
  1295. node_ui/node_modules/lodash/reduceRight.js +36 -0
  1296. node_ui/node_modules/lodash/reject.js +46 -0
  1297. node_ui/node_modules/lodash/release.md +48 -0
  1298. node_ui/node_modules/lodash/remove.js +53 -0
  1299. node_ui/node_modules/lodash/repeat.js +37 -0
  1300. node_ui/node_modules/lodash/replace.js +29 -0
  1301. node_ui/node_modules/lodash/rest.js +40 -0
  1302. node_ui/node_modules/lodash/result.js +56 -0
  1303. node_ui/node_modules/lodash/reverse.js +34 -0
  1304. node_ui/node_modules/lodash/round.js +26 -0
  1305. node_ui/node_modules/lodash/sample.js +24 -0
  1306. node_ui/node_modules/lodash/sampleSize.js +37 -0
  1307. node_ui/node_modules/lodash/seq.js +16 -0
  1308. node_ui/node_modules/lodash/set.js +35 -0
  1309. node_ui/node_modules/lodash/setWith.js +32 -0
  1310. node_ui/node_modules/lodash/shuffle.js +25 -0
  1311. node_ui/node_modules/lodash/size.js +46 -0
  1312. node_ui/node_modules/lodash/slice.js +37 -0
  1313. node_ui/node_modules/lodash/snakeCase.js +28 -0
  1314. node_ui/node_modules/lodash/some.js +51 -0
  1315. node_ui/node_modules/lodash/sortBy.js +48 -0
  1316. node_ui/node_modules/lodash/sortedIndex.js +24 -0
  1317. node_ui/node_modules/lodash/sortedIndexBy.js +33 -0
  1318. node_ui/node_modules/lodash/sortedIndexOf.js +31 -0
  1319. node_ui/node_modules/lodash/sortedLastIndex.js +25 -0
  1320. node_ui/node_modules/lodash/sortedLastIndexBy.js +33 -0
  1321. node_ui/node_modules/lodash/sortedLastIndexOf.js +31 -0
  1322. node_ui/node_modules/lodash/sortedUniq.js +24 -0
  1323. node_ui/node_modules/lodash/sortedUniqBy.js +26 -0
  1324. node_ui/node_modules/lodash/split.js +52 -0
  1325. node_ui/node_modules/lodash/spread.js +63 -0
  1326. node_ui/node_modules/lodash/startCase.js +29 -0
  1327. node_ui/node_modules/lodash/startsWith.js +39 -0
  1328. node_ui/node_modules/lodash/string.js +33 -0
  1329. node_ui/node_modules/lodash/stubArray.js +23 -0
  1330. node_ui/node_modules/lodash/stubFalse.js +18 -0
  1331. node_ui/node_modules/lodash/stubObject.js +23 -0
  1332. node_ui/node_modules/lodash/stubString.js +18 -0
  1333. node_ui/node_modules/lodash/stubTrue.js +18 -0
  1334. node_ui/node_modules/lodash/subtract.js +22 -0
  1335. node_ui/node_modules/lodash/sum.js +24 -0
  1336. node_ui/node_modules/lodash/sumBy.js +33 -0
  1337. node_ui/node_modules/lodash/tail.js +22 -0
  1338. node_ui/node_modules/lodash/take.js +37 -0
  1339. node_ui/node_modules/lodash/takeRight.js +39 -0
  1340. node_ui/node_modules/lodash/takeRightWhile.js +45 -0
  1341. node_ui/node_modules/lodash/takeWhile.js +45 -0
  1342. node_ui/node_modules/lodash/tap.js +29 -0
  1343. node_ui/node_modules/lodash/template.js +272 -0
  1344. node_ui/node_modules/lodash/templateSettings.js +67 -0
  1345. node_ui/node_modules/lodash/throttle.js +69 -0
  1346. node_ui/node_modules/lodash/thru.js +28 -0
  1347. node_ui/node_modules/lodash/times.js +51 -0
  1348. node_ui/node_modules/lodash/toArray.js +58 -0
  1349. node_ui/node_modules/lodash/toFinite.js +42 -0
  1350. node_ui/node_modules/lodash/toInteger.js +36 -0
  1351. node_ui/node_modules/lodash/toIterator.js +23 -0
  1352. node_ui/node_modules/lodash/toJSON.js +1 -0
  1353. node_ui/node_modules/lodash/toLength.js +38 -0
  1354. node_ui/node_modules/lodash/toLower.js +28 -0
  1355. node_ui/node_modules/lodash/toNumber.js +64 -0
  1356. node_ui/node_modules/lodash/toPairs.js +30 -0
  1357. node_ui/node_modules/lodash/toPairsIn.js +30 -0
  1358. node_ui/node_modules/lodash/toPath.js +33 -0
  1359. node_ui/node_modules/lodash/toPlainObject.js +32 -0
  1360. node_ui/node_modules/lodash/toSafeInteger.js +37 -0
  1361. node_ui/node_modules/lodash/toString.js +28 -0
  1362. node_ui/node_modules/lodash/toUpper.js +28 -0
  1363. node_ui/node_modules/lodash/transform.js +65 -0
  1364. node_ui/node_modules/lodash/trim.js +47 -0
  1365. node_ui/node_modules/lodash/trimEnd.js +41 -0
  1366. node_ui/node_modules/lodash/trimStart.js +43 -0
  1367. node_ui/node_modules/lodash/truncate.js +111 -0
  1368. node_ui/node_modules/lodash/unary.js +22 -0
  1369. node_ui/node_modules/lodash/unescape.js +34 -0
  1370. node_ui/node_modules/lodash/union.js +26 -0
  1371. node_ui/node_modules/lodash/unionBy.js +39 -0
  1372. node_ui/node_modules/lodash/unionWith.js +34 -0
  1373. node_ui/node_modules/lodash/uniq.js +25 -0
  1374. node_ui/node_modules/lodash/uniqBy.js +31 -0
  1375. node_ui/node_modules/lodash/uniqWith.js +28 -0
  1376. node_ui/node_modules/lodash/uniqueId.js +28 -0
  1377. node_ui/node_modules/lodash/unset.js +34 -0
  1378. node_ui/node_modules/lodash/unzip.js +45 -0
  1379. node_ui/node_modules/lodash/unzipWith.js +39 -0
  1380. node_ui/node_modules/lodash/update.js +35 -0
  1381. node_ui/node_modules/lodash/updateWith.js +33 -0
  1382. node_ui/node_modules/lodash/upperCase.js +27 -0
  1383. node_ui/node_modules/lodash/upperFirst.js +22 -0
  1384. node_ui/node_modules/lodash/util.js +34 -0
  1385. node_ui/node_modules/lodash/value.js +1 -0
  1386. node_ui/node_modules/lodash/valueOf.js +1 -0
  1387. node_ui/node_modules/lodash/values.js +34 -0
  1388. node_ui/node_modules/lodash/valuesIn.js +32 -0
  1389. node_ui/node_modules/lodash/without.js +31 -0
  1390. node_ui/node_modules/lodash/words.js +35 -0
  1391. node_ui/node_modules/lodash/wrap.js +30 -0
  1392. node_ui/node_modules/lodash/wrapperAt.js +48 -0
  1393. node_ui/node_modules/lodash/wrapperChain.js +34 -0
  1394. node_ui/node_modules/lodash/wrapperLodash.js +147 -0
  1395. node_ui/node_modules/lodash/wrapperReverse.js +44 -0
  1396. node_ui/node_modules/lodash/wrapperValue.js +21 -0
  1397. node_ui/node_modules/lodash/xor.js +28 -0
  1398. node_ui/node_modules/lodash/xorBy.js +39 -0
  1399. node_ui/node_modules/lodash/xorWith.js +34 -0
  1400. node_ui/node_modules/lodash/zip.js +22 -0
  1401. node_ui/node_modules/lodash/zipObject.js +24 -0
  1402. node_ui/node_modules/lodash/zipObjectDeep.js +23 -0
  1403. node_ui/node_modules/lodash/zipWith.js +32 -0
  1404. node_ui/node_modules/lodash.isequal/LICENSE +47 -0
  1405. node_ui/node_modules/lodash.isequal/README.md +18 -0
  1406. node_ui/node_modules/lodash.isequal/index.js +1848 -0
  1407. node_ui/node_modules/lodash.isequal/package.json +16 -0
  1408. node_ui/node_modules/loose-envify/LICENSE +21 -0
  1409. node_ui/node_modules/loose-envify/README.md +45 -0
  1410. node_ui/node_modules/loose-envify/cli.js +16 -0
  1411. node_ui/node_modules/loose-envify/custom.js +4 -0
  1412. node_ui/node_modules/loose-envify/index.js +3 -0
  1413. node_ui/node_modules/loose-envify/loose-envify.js +36 -0
  1414. node_ui/node_modules/loose-envify/package.json +36 -0
  1415. node_ui/node_modules/loose-envify/replace.js +65 -0
  1416. node_ui/node_modules/meow/build/dependencies.js +8828 -0
  1417. node_ui/node_modules/meow/build/index.d.ts +1425 -0
  1418. node_ui/node_modules/meow/build/index.js +95 -0
  1419. node_ui/node_modules/meow/build/licenses.md +1620 -0
  1420. node_ui/node_modules/meow/build/options.js +92 -0
  1421. node_ui/node_modules/meow/build/parser.js +84 -0
  1422. node_ui/node_modules/meow/build/utils.js +7 -0
  1423. node_ui/node_modules/meow/build/validate.js +122 -0
  1424. node_ui/node_modules/meow/license +9 -0
  1425. node_ui/node_modules/meow/package.json +105 -0
  1426. node_ui/node_modules/meow/readme.md +314 -0
  1427. node_ui/node_modules/mimic-fn/index.d.ts +54 -0
  1428. node_ui/node_modules/mimic-fn/index.js +13 -0
  1429. node_ui/node_modules/mimic-fn/license +9 -0
  1430. node_ui/node_modules/mimic-fn/package.json +42 -0
  1431. node_ui/node_modules/mimic-fn/readme.md +69 -0
  1432. node_ui/node_modules/onetime/index.d.ts +64 -0
  1433. node_ui/node_modules/onetime/index.js +44 -0
  1434. node_ui/node_modules/onetime/license +9 -0
  1435. node_ui/node_modules/onetime/package.json +43 -0
  1436. node_ui/node_modules/onetime/readme.md +94 -0
  1437. node_ui/node_modules/patch-console/dist/index.d.ts +4 -0
  1438. node_ui/node_modules/patch-console/dist/index.js +45 -0
  1439. node_ui/node_modules/patch-console/dist/index.js.map +1 -0
  1440. node_ui/node_modules/patch-console/license +9 -0
  1441. node_ui/node_modules/patch-console/package.json +53 -0
  1442. node_ui/node_modules/patch-console/readme.md +62 -0
  1443. node_ui/node_modules/react/LICENSE +21 -0
  1444. node_ui/node_modules/react/README.md +37 -0
  1445. node_ui/node_modules/react/cjs/react-jsx-dev-runtime.development.js +1315 -0
  1446. node_ui/node_modules/react/cjs/react-jsx-dev-runtime.production.min.js +10 -0
  1447. node_ui/node_modules/react/cjs/react-jsx-dev-runtime.profiling.min.js +10 -0
  1448. node_ui/node_modules/react/cjs/react-jsx-runtime.development.js +1333 -0
  1449. node_ui/node_modules/react/cjs/react-jsx-runtime.production.min.js +11 -0
  1450. node_ui/node_modules/react/cjs/react-jsx-runtime.profiling.min.js +11 -0
  1451. node_ui/node_modules/react/cjs/react.development.js +2740 -0
  1452. node_ui/node_modules/react/cjs/react.production.min.js +26 -0
  1453. node_ui/node_modules/react/cjs/react.shared-subset.development.js +20 -0
  1454. node_ui/node_modules/react/cjs/react.shared-subset.production.min.js +10 -0
  1455. node_ui/node_modules/react/index.js +7 -0
  1456. node_ui/node_modules/react/jsx-dev-runtime.js +7 -0
  1457. node_ui/node_modules/react/jsx-runtime.js +7 -0
  1458. node_ui/node_modules/react/package.json +47 -0
  1459. node_ui/node_modules/react/react.shared-subset.js +7 -0
  1460. node_ui/node_modules/react/umd/react.development.js +3343 -0
  1461. node_ui/node_modules/react/umd/react.production.min.js +31 -0
  1462. node_ui/node_modules/react/umd/react.profiling.min.js +31 -0
  1463. node_ui/node_modules/react-devtools-core/README.md +131 -0
  1464. node_ui/node_modules/react-devtools-core/backend.js +1 -0
  1465. node_ui/node_modules/react-devtools-core/dist/backend.js +16888 -0
  1466. node_ui/node_modules/react-devtools-core/dist/backend.js.map +1 -0
  1467. node_ui/node_modules/react-devtools-core/dist/importFile.worker.worker.js +2 -0
  1468. node_ui/node_modules/react-devtools-core/dist/importFile.worker.worker.js.map +1 -0
  1469. node_ui/node_modules/react-devtools-core/dist/parseHookNames.chunk.js +2 -0
  1470. node_ui/node_modules/react-devtools-core/dist/parseHookNames.chunk.js.map +1 -0
  1471. node_ui/node_modules/react-devtools-core/dist/parseSourceAndMetadata.worker.worker.js +2 -0
  1472. node_ui/node_modules/react-devtools-core/dist/parseSourceAndMetadata.worker.worker.js.map +1 -0
  1473. node_ui/node_modules/react-devtools-core/dist/standalone.js +3 -0
  1474. node_ui/node_modules/react-devtools-core/dist/standalone.js.LICENSE.txt +41 -0
  1475. node_ui/node_modules/react-devtools-core/dist/standalone.js.map +1 -0
  1476. node_ui/node_modules/react-devtools-core/node_modules/ws/LICENSE +21 -0
  1477. node_ui/node_modules/react-devtools-core/node_modules/ws/README.md +495 -0
  1478. node_ui/node_modules/react-devtools-core/node_modules/ws/browser.js +8 -0
  1479. node_ui/node_modules/react-devtools-core/node_modules/ws/index.js +10 -0
  1480. node_ui/node_modules/react-devtools-core/node_modules/ws/lib/buffer-util.js +129 -0
  1481. node_ui/node_modules/react-devtools-core/node_modules/ws/lib/constants.js +10 -0
  1482. node_ui/node_modules/react-devtools-core/node_modules/ws/lib/event-target.js +184 -0
  1483. node_ui/node_modules/react-devtools-core/node_modules/ws/lib/extension.js +223 -0
  1484. node_ui/node_modules/react-devtools-core/node_modules/ws/lib/limiter.js +55 -0
  1485. node_ui/node_modules/react-devtools-core/node_modules/ws/lib/permessage-deflate.js +518 -0
  1486. node_ui/node_modules/react-devtools-core/node_modules/ws/lib/receiver.js +607 -0
  1487. node_ui/node_modules/react-devtools-core/node_modules/ws/lib/sender.js +409 -0
  1488. node_ui/node_modules/react-devtools-core/node_modules/ws/lib/stream.js +180 -0
  1489. node_ui/node_modules/react-devtools-core/node_modules/ws/lib/validation.js +104 -0
  1490. node_ui/node_modules/react-devtools-core/node_modules/ws/lib/websocket-server.js +449 -0
  1491. node_ui/node_modules/react-devtools-core/node_modules/ws/lib/websocket.js +1197 -0
  1492. node_ui/node_modules/react-devtools-core/node_modules/ws/package.json +56 -0
  1493. node_ui/node_modules/react-devtools-core/package.json +38 -0
  1494. node_ui/node_modules/react-devtools-core/standalone.js +1 -0
  1495. node_ui/node_modules/react-reconciler/LICENSE +21 -0
  1496. node_ui/node_modules/react-reconciler/README.md +337 -0
  1497. node_ui/node_modules/react-reconciler/cjs/react-reconciler-constants.development.js +45 -0
  1498. node_ui/node_modules/react-reconciler/cjs/react-reconciler-constants.production.min.js +10 -0
  1499. node_ui/node_modules/react-reconciler/cjs/react-reconciler-reflection.development.js +660 -0
  1500. node_ui/node_modules/react-reconciler/cjs/react-reconciler-reflection.production.min.js +15 -0
  1501. node_ui/node_modules/react-reconciler/cjs/react-reconciler.development.js +21531 -0
  1502. node_ui/node_modules/react-reconciler/cjs/react-reconciler.production.min.js +234 -0
  1503. node_ui/node_modules/react-reconciler/cjs/react-reconciler.profiling.min.js +255 -0
  1504. node_ui/node_modules/react-reconciler/constants.js +7 -0
  1505. node_ui/node_modules/react-reconciler/index.js +7 -0
  1506. node_ui/node_modules/react-reconciler/package.json +40 -0
  1507. node_ui/node_modules/react-reconciler/reflection.js +7 -0
  1508. node_ui/node_modules/restore-cursor/index.d.ts +11 -0
  1509. node_ui/node_modules/restore-cursor/index.js +11 -0
  1510. node_ui/node_modules/restore-cursor/license +9 -0
  1511. node_ui/node_modules/restore-cursor/package.json +55 -0
  1512. node_ui/node_modules/restore-cursor/readme.md +31 -0
  1513. node_ui/node_modules/scheduler/LICENSE +21 -0
  1514. node_ui/node_modules/scheduler/README.md +9 -0
  1515. node_ui/node_modules/scheduler/cjs/scheduler-unstable_mock.development.js +700 -0
  1516. node_ui/node_modules/scheduler/cjs/scheduler-unstable_mock.production.min.js +20 -0
  1517. node_ui/node_modules/scheduler/cjs/scheduler-unstable_post_task.development.js +207 -0
  1518. node_ui/node_modules/scheduler/cjs/scheduler-unstable_post_task.production.min.js +14 -0
  1519. node_ui/node_modules/scheduler/cjs/scheduler.development.js +634 -0
  1520. node_ui/node_modules/scheduler/cjs/scheduler.production.min.js +19 -0
  1521. node_ui/node_modules/scheduler/index.js +7 -0
  1522. node_ui/node_modules/scheduler/package.json +36 -0
  1523. node_ui/node_modules/scheduler/umd/scheduler-unstable_mock.development.js +699 -0
  1524. node_ui/node_modules/scheduler/umd/scheduler-unstable_mock.production.min.js +19 -0
  1525. node_ui/node_modules/scheduler/umd/scheduler.development.js +152 -0
  1526. node_ui/node_modules/scheduler/umd/scheduler.production.min.js +146 -0
  1527. node_ui/node_modules/scheduler/umd/scheduler.profiling.min.js +146 -0
  1528. node_ui/node_modules/scheduler/unstable_mock.js +7 -0
  1529. node_ui/node_modules/scheduler/unstable_post_task.js +7 -0
  1530. node_ui/node_modules/shell-quote/.eslintrc +30 -0
  1531. node_ui/node_modules/shell-quote/.github/FUNDING.yml +12 -0
  1532. node_ui/node_modules/shell-quote/.nycrc +14 -0
  1533. node_ui/node_modules/shell-quote/LICENSE +24 -0
  1534. node_ui/node_modules/shell-quote/README.md +161 -0
  1535. node_ui/node_modules/shell-quote/index.js +4 -0
  1536. node_ui/node_modules/shell-quote/package.json +72 -0
  1537. node_ui/node_modules/shell-quote/parse.js +226 -0
  1538. node_ui/node_modules/shell-quote/print.py +3 -0
  1539. node_ui/node_modules/shell-quote/quote.js +19 -0
  1540. node_ui/node_modules/shell-quote/security.md +11 -0
  1541. node_ui/node_modules/shell-quote/test/comment.js +16 -0
  1542. node_ui/node_modules/shell-quote/test/env.js +52 -0
  1543. node_ui/node_modules/shell-quote/test/env_fn.js +21 -0
  1544. node_ui/node_modules/shell-quote/test/op.js +102 -0
  1545. node_ui/node_modules/shell-quote/test/parse.js +44 -0
  1546. node_ui/node_modules/shell-quote/test/quote.js +60 -0
  1547. node_ui/node_modules/shell-quote/test/set.js +31 -0
  1548. node_ui/node_modules/signal-exit/LICENSE.txt +16 -0
  1549. node_ui/node_modules/signal-exit/README.md +39 -0
  1550. node_ui/node_modules/signal-exit/index.js +202 -0
  1551. node_ui/node_modules/signal-exit/package.json +38 -0
  1552. node_ui/node_modules/signal-exit/signals.js +53 -0
  1553. node_ui/node_modules/slice-ansi/index.d.ts +19 -0
  1554. node_ui/node_modules/slice-ansi/index.js +169 -0
  1555. node_ui/node_modules/slice-ansi/license +10 -0
  1556. node_ui/node_modules/slice-ansi/node_modules/is-fullwidth-code-point/index.d.ts +17 -0
  1557. node_ui/node_modules/slice-ansi/node_modules/is-fullwidth-code-point/index.js +12 -0
  1558. node_ui/node_modules/slice-ansi/node_modules/is-fullwidth-code-point/license +9 -0
  1559. node_ui/node_modules/slice-ansi/node_modules/is-fullwidth-code-point/package.json +53 -0
  1560. node_ui/node_modules/slice-ansi/node_modules/is-fullwidth-code-point/readme.md +31 -0
  1561. node_ui/node_modules/slice-ansi/package.json +58 -0
  1562. node_ui/node_modules/slice-ansi/readme.md +54 -0
  1563. node_ui/node_modules/stack-utils/LICENSE.md +21 -0
  1564. node_ui/node_modules/stack-utils/index.js +344 -0
  1565. node_ui/node_modules/stack-utils/node_modules/escape-string-regexp/index.d.ts +18 -0
  1566. node_ui/node_modules/stack-utils/node_modules/escape-string-regexp/index.js +11 -0
  1567. node_ui/node_modules/stack-utils/node_modules/escape-string-regexp/license +9 -0
  1568. node_ui/node_modules/stack-utils/node_modules/escape-string-regexp/package.json +43 -0
  1569. node_ui/node_modules/stack-utils/node_modules/escape-string-regexp/readme.md +29 -0
  1570. node_ui/node_modules/stack-utils/package.json +39 -0
  1571. node_ui/node_modules/stack-utils/readme.md +143 -0
  1572. node_ui/node_modules/string-width/index.d.ts +39 -0
  1573. node_ui/node_modules/string-width/index.js +82 -0
  1574. node_ui/node_modules/string-width/license +9 -0
  1575. node_ui/node_modules/string-width/package.json +64 -0
  1576. node_ui/node_modules/string-width/readme.md +66 -0
  1577. node_ui/node_modules/strip-ansi/index.d.ts +15 -0
  1578. node_ui/node_modules/strip-ansi/index.js +14 -0
  1579. node_ui/node_modules/strip-ansi/license +9 -0
  1580. node_ui/node_modules/strip-ansi/package.json +59 -0
  1581. node_ui/node_modules/strip-ansi/readme.md +37 -0
  1582. node_ui/node_modules/to-rotated/index.d.ts +18 -0
  1583. node_ui/node_modules/to-rotated/index.js +24 -0
  1584. node_ui/node_modules/to-rotated/license +9 -0
  1585. node_ui/node_modules/to-rotated/package.json +46 -0
  1586. node_ui/node_modules/to-rotated/readme.md +29 -0
  1587. node_ui/node_modules/type-fest/index.d.ts +178 -0
  1588. node_ui/node_modules/type-fest/license-cc0 +121 -0
  1589. node_ui/node_modules/type-fest/license-mit +9 -0
  1590. node_ui/node_modules/type-fest/package.json +91 -0
  1591. node_ui/node_modules/type-fest/readme.md +1060 -0
  1592. node_ui/node_modules/type-fest/source/all-union-fields.d.ts +88 -0
  1593. node_ui/node_modules/type-fest/source/and.d.ts +25 -0
  1594. node_ui/node_modules/type-fest/source/array-indices.d.ts +23 -0
  1595. node_ui/node_modules/type-fest/source/array-slice.d.ts +109 -0
  1596. node_ui/node_modules/type-fest/source/array-splice.d.ts +99 -0
  1597. node_ui/node_modules/type-fest/source/array-tail.d.ts +76 -0
  1598. node_ui/node_modules/type-fest/source/array-values.d.ts +22 -0
  1599. node_ui/node_modules/type-fest/source/arrayable.d.ts +29 -0
  1600. node_ui/node_modules/type-fest/source/async-return-type.d.ts +23 -0
  1601. node_ui/node_modules/type-fest/source/asyncify.d.ts +32 -0
  1602. node_ui/node_modules/type-fest/source/basic.d.ts +68 -0
  1603. node_ui/node_modules/type-fest/source/camel-case.d.ts +89 -0
  1604. node_ui/node_modules/type-fest/source/camel-cased-properties-deep.d.ts +97 -0
  1605. node_ui/node_modules/type-fest/source/camel-cased-properties.d.ts +43 -0
  1606. node_ui/node_modules/type-fest/source/conditional-except.d.ts +45 -0
  1607. node_ui/node_modules/type-fest/source/conditional-keys.d.ts +47 -0
  1608. node_ui/node_modules/type-fest/source/conditional-pick-deep.d.ts +118 -0
  1609. node_ui/node_modules/type-fest/source/conditional-pick.d.ts +44 -0
  1610. node_ui/node_modules/type-fest/source/conditional-simplify.d.ts +32 -0
  1611. node_ui/node_modules/type-fest/source/delimiter-case.d.ts +78 -0
  1612. node_ui/node_modules/type-fest/source/delimiter-cased-properties-deep.d.ts +106 -0
  1613. node_ui/node_modules/type-fest/source/delimiter-cased-properties.d.ts +46 -0
  1614. node_ui/node_modules/type-fest/source/distributed-omit.d.ts +89 -0
  1615. node_ui/node_modules/type-fest/source/distributed-pick.d.ts +85 -0
  1616. node_ui/node_modules/type-fest/source/empty-object.d.ts +46 -0
  1617. node_ui/node_modules/type-fest/source/enforce-optional.d.ts +47 -0
  1618. node_ui/node_modules/type-fest/source/entries.d.ts +62 -0
  1619. node_ui/node_modules/type-fest/source/entry.d.ts +65 -0
  1620. node_ui/node_modules/type-fest/source/exact.d.ts +68 -0
  1621. node_ui/node_modules/type-fest/source/except.d.ts +108 -0
  1622. node_ui/node_modules/type-fest/source/find-global-type.d.ts +64 -0
  1623. node_ui/node_modules/type-fest/source/fixed-length-array.d.ts +43 -0
  1624. node_ui/node_modules/type-fest/source/get.d.ts +219 -0
  1625. node_ui/node_modules/type-fest/source/global-this.d.ts +21 -0
  1626. node_ui/node_modules/type-fest/source/greater-than-or-equal.d.ts +22 -0
  1627. node_ui/node_modules/type-fest/source/greater-than.d.ts +56 -0
  1628. node_ui/node_modules/type-fest/source/has-optional-keys.d.ts +21 -0
  1629. node_ui/node_modules/type-fest/source/has-readonly-keys.d.ts +21 -0
  1630. node_ui/node_modules/type-fest/source/has-required-keys.d.ts +59 -0
  1631. node_ui/node_modules/type-fest/source/has-writable-keys.d.ts +21 -0
  1632. node_ui/node_modules/type-fest/source/if-any.d.ts +24 -0
  1633. node_ui/node_modules/type-fest/source/if-empty-object.d.ts +26 -0
  1634. node_ui/node_modules/type-fest/source/if-never.d.ts +24 -0
  1635. node_ui/node_modules/type-fest/source/if-null.d.ts +24 -0
  1636. node_ui/node_modules/type-fest/source/if-unknown.d.ts +24 -0
  1637. node_ui/node_modules/type-fest/source/includes.d.ts +22 -0
  1638. node_ui/node_modules/type-fest/source/int-closed-range.d.ts +35 -0
  1639. node_ui/node_modules/type-fest/source/int-range.d.ts +55 -0
  1640. node_ui/node_modules/type-fest/source/internal/array.d.ts +126 -0
  1641. node_ui/node_modules/type-fest/source/internal/characters.d.ts +67 -0
  1642. node_ui/node_modules/type-fest/source/internal/index.d.ts +8 -0
  1643. node_ui/node_modules/type-fest/source/internal/keys.d.ts +97 -0
  1644. node_ui/node_modules/type-fest/source/internal/numeric.d.ts +118 -0
  1645. node_ui/node_modules/type-fest/source/internal/object.d.ts +236 -0
  1646. node_ui/node_modules/type-fest/source/internal/string.d.ts +210 -0
  1647. node_ui/node_modules/type-fest/source/internal/tuple.d.ts +90 -0
  1648. node_ui/node_modules/type-fest/source/internal/type.d.ts +139 -0
  1649. node_ui/node_modules/type-fest/source/invariant-of.d.ts +76 -0
  1650. node_ui/node_modules/type-fest/source/is-any.d.ts +33 -0
  1651. node_ui/node_modules/type-fest/source/is-equal.d.ts +31 -0
  1652. node_ui/node_modules/type-fest/source/is-float.d.ts +41 -0
  1653. node_ui/node_modules/type-fest/source/is-integer.d.ts +58 -0
  1654. node_ui/node_modules/type-fest/source/is-literal.d.ts +296 -0
  1655. node_ui/node_modules/type-fest/source/is-never.d.ts +42 -0
  1656. node_ui/node_modules/type-fest/source/is-null.d.ts +20 -0
  1657. node_ui/node_modules/type-fest/source/is-tuple.d.ts +89 -0
  1658. node_ui/node_modules/type-fest/source/is-unknown.d.ts +52 -0
  1659. node_ui/node_modules/type-fest/source/iterable-element.d.ts +64 -0
  1660. node_ui/node_modules/type-fest/source/join.d.ts +68 -0
  1661. node_ui/node_modules/type-fest/source/jsonifiable.d.ts +37 -0
  1662. node_ui/node_modules/type-fest/source/jsonify.d.ts +122 -0
  1663. node_ui/node_modules/type-fest/source/kebab-case.d.ts +44 -0
  1664. node_ui/node_modules/type-fest/source/kebab-cased-properties-deep.d.ts +63 -0
  1665. node_ui/node_modules/type-fest/source/kebab-cased-properties.d.ts +40 -0
  1666. node_ui/node_modules/type-fest/source/keys-of-union.d.ts +42 -0
  1667. node_ui/node_modules/type-fest/source/last-array-element.d.ts +38 -0
  1668. node_ui/node_modules/type-fest/source/less-than-or-equal.d.ts +22 -0
  1669. node_ui/node_modules/type-fest/source/less-than.d.ts +26 -0
  1670. node_ui/node_modules/type-fest/source/literal-to-primitive-deep.d.ts +36 -0
  1671. node_ui/node_modules/type-fest/source/literal-to-primitive.d.ts +36 -0
  1672. node_ui/node_modules/type-fest/source/literal-union.d.ts +37 -0
  1673. node_ui/node_modules/type-fest/source/merge-deep.d.ts +486 -0
  1674. node_ui/node_modules/type-fest/source/merge-exclusive.d.ts +41 -0
  1675. node_ui/node_modules/type-fest/source/merge.d.ts +48 -0
  1676. node_ui/node_modules/type-fest/source/multidimensional-array.d.ts +44 -0
  1677. node_ui/node_modules/type-fest/source/multidimensional-readonly-array.d.ts +48 -0
  1678. node_ui/node_modules/type-fest/source/non-empty-object.d.ts +35 -0
  1679. node_ui/node_modules/type-fest/source/non-empty-string.d.ts +28 -0
  1680. node_ui/node_modules/type-fest/source/non-empty-tuple.d.ts +21 -0
  1681. node_ui/node_modules/type-fest/source/numeric.d.ts +222 -0
  1682. node_ui/node_modules/type-fest/source/observable-like.d.ts +63 -0
  1683. node_ui/node_modules/type-fest/source/omit-deep.d.ts +167 -0
  1684. node_ui/node_modules/type-fest/source/omit-index-signature.d.ts +95 -0
  1685. node_ui/node_modules/type-fest/source/opaque.d.ts +1 -0
  1686. node_ui/node_modules/type-fest/source/optional-keys-of.d.ts +39 -0
  1687. node_ui/node_modules/type-fest/source/or.d.ts +25 -0
  1688. node_ui/node_modules/type-fest/source/override-properties.d.ts +36 -0
  1689. node_ui/node_modules/type-fest/source/package-json.d.ts +676 -0
  1690. node_ui/node_modules/type-fest/source/partial-deep.d.ts +151 -0
  1691. node_ui/node_modules/type-fest/source/partial-on-undefined-deep.d.ts +78 -0
  1692. node_ui/node_modules/type-fest/source/pascal-case.d.ts +42 -0
  1693. node_ui/node_modules/type-fest/source/pascal-cased-properties-deep.d.ts +62 -0
  1694. node_ui/node_modules/type-fest/source/pascal-cased-properties.d.ts +36 -0
  1695. node_ui/node_modules/type-fest/source/paths.d.ts +262 -0
  1696. node_ui/node_modules/type-fest/source/pick-deep.d.ts +149 -0
  1697. node_ui/node_modules/type-fest/source/pick-index-signature.d.ts +50 -0
  1698. node_ui/node_modules/type-fest/source/primitive.d.ts +13 -0
  1699. node_ui/node_modules/type-fest/source/promisable.d.ts +25 -0
  1700. node_ui/node_modules/type-fest/source/readonly-deep.d.ts +81 -0
  1701. node_ui/node_modules/type-fest/source/readonly-keys-of.d.ts +30 -0
  1702. node_ui/node_modules/type-fest/source/readonly-tuple.d.ts +41 -0
  1703. node_ui/node_modules/type-fest/source/replace.d.ts +85 -0
  1704. node_ui/node_modules/type-fest/source/require-all-or-none.d.ts +51 -0
  1705. node_ui/node_modules/type-fest/source/require-at-least-one.d.ts +47 -0
  1706. node_ui/node_modules/type-fest/source/require-exactly-one.d.ts +45 -0
  1707. node_ui/node_modules/type-fest/source/require-one-or-none.d.ts +46 -0
  1708. node_ui/node_modules/type-fest/source/required-deep.d.ts +78 -0
  1709. node_ui/node_modules/type-fest/source/required-keys-of.d.ts +30 -0
  1710. node_ui/node_modules/type-fest/source/schema.d.ts +114 -0
  1711. node_ui/node_modules/type-fest/source/screaming-snake-case.d.ts +28 -0
  1712. node_ui/node_modules/type-fest/source/set-field-type.d.ts +65 -0
  1713. node_ui/node_modules/type-fest/source/set-non-nullable-deep.d.ts +83 -0
  1714. node_ui/node_modules/type-fest/source/set-non-nullable.d.ts +39 -0
  1715. node_ui/node_modules/type-fest/source/set-optional.d.ts +38 -0
  1716. node_ui/node_modules/type-fest/source/set-parameter-type.d.ts +117 -0
  1717. node_ui/node_modules/type-fest/source/set-readonly.d.ts +39 -0
  1718. node_ui/node_modules/type-fest/source/set-required-deep.d.ts +68 -0
  1719. node_ui/node_modules/type-fest/source/set-required.d.ts +70 -0
  1720. node_ui/node_modules/type-fest/source/set-return-type.d.ts +29 -0
  1721. node_ui/node_modules/type-fest/source/shared-union-fields-deep.d.ts +178 -0
  1722. node_ui/node_modules/type-fest/source/shared-union-fields.d.ts +76 -0
  1723. node_ui/node_modules/type-fest/source/simplify-deep.d.ts +115 -0
  1724. node_ui/node_modules/type-fest/source/simplify.d.ts +58 -0
  1725. node_ui/node_modules/type-fest/source/single-key-object.d.ts +29 -0
  1726. node_ui/node_modules/type-fest/source/snake-case.d.ts +45 -0
  1727. node_ui/node_modules/type-fest/source/snake-cased-properties-deep.d.ts +63 -0
  1728. node_ui/node_modules/type-fest/source/snake-cased-properties.d.ts +40 -0
  1729. node_ui/node_modules/type-fest/source/split.d.ts +88 -0
  1730. node_ui/node_modules/type-fest/source/spread.d.ts +84 -0
  1731. node_ui/node_modules/type-fest/source/string-key-of.d.ts +25 -0
  1732. node_ui/node_modules/type-fest/source/string-repeat.d.ts +47 -0
  1733. node_ui/node_modules/type-fest/source/string-slice.d.ts +37 -0
  1734. node_ui/node_modules/type-fest/source/stringified.d.ts +23 -0
  1735. node_ui/node_modules/type-fest/source/structured-cloneable.d.ts +92 -0
  1736. node_ui/node_modules/type-fest/source/subtract.d.ts +83 -0
  1737. node_ui/node_modules/type-fest/source/sum.d.ts +78 -0
  1738. node_ui/node_modules/type-fest/source/tagged-union.d.ts +51 -0
  1739. node_ui/node_modules/type-fest/source/tagged.d.ts +256 -0
  1740. node_ui/node_modules/type-fest/source/trim.d.ts +27 -0
  1741. node_ui/node_modules/type-fest/source/tsconfig-json.d.ts +1294 -0
  1742. node_ui/node_modules/type-fest/source/tuple-to-object.d.ts +42 -0
  1743. node_ui/node_modules/type-fest/source/tuple-to-union.d.ts +51 -0
  1744. node_ui/node_modules/type-fest/source/typed-array.d.ts +17 -0
  1745. node_ui/node_modules/type-fest/source/undefined-on-partial-deep.d.ts +80 -0
  1746. node_ui/node_modules/type-fest/source/union-to-intersection.d.ts +61 -0
  1747. node_ui/node_modules/type-fest/source/union-to-tuple.d.ts +56 -0
  1748. node_ui/node_modules/type-fest/source/unknown-array.d.ts +25 -0
  1749. node_ui/node_modules/type-fest/source/unknown-map.d.ts +24 -0
  1750. node_ui/node_modules/type-fest/source/unknown-record.d.ts +31 -0
  1751. node_ui/node_modules/type-fest/source/unknown-set.d.ts +24 -0
  1752. node_ui/node_modules/type-fest/source/value-of.d.ts +42 -0
  1753. node_ui/node_modules/type-fest/source/words.d.ts +118 -0
  1754. node_ui/node_modules/type-fest/source/writable-deep.d.ts +83 -0
  1755. node_ui/node_modules/type-fest/source/writable-keys-of.d.ts +33 -0
  1756. node_ui/node_modules/type-fest/source/writable.d.ts +68 -0
  1757. node_ui/node_modules/widest-line/index.d.ts +12 -0
  1758. node_ui/node_modules/widest-line/index.js +11 -0
  1759. node_ui/node_modules/widest-line/license +9 -0
  1760. node_ui/node_modules/widest-line/package.json +60 -0
  1761. node_ui/node_modules/widest-line/readme.md +26 -0
  1762. node_ui/node_modules/wrap-ansi/index.d.ts +41 -0
  1763. node_ui/node_modules/wrap-ansi/index.js +222 -0
  1764. node_ui/node_modules/wrap-ansi/license +9 -0
  1765. node_ui/node_modules/wrap-ansi/package.json +69 -0
  1766. node_ui/node_modules/wrap-ansi/readme.md +75 -0
  1767. node_ui/node_modules/ws/LICENSE +20 -0
  1768. node_ui/node_modules/ws/README.md +548 -0
  1769. node_ui/node_modules/ws/browser.js +8 -0
  1770. node_ui/node_modules/ws/index.js +13 -0
  1771. node_ui/node_modules/ws/lib/buffer-util.js +131 -0
  1772. node_ui/node_modules/ws/lib/constants.js +18 -0
  1773. node_ui/node_modules/ws/lib/event-target.js +292 -0
  1774. node_ui/node_modules/ws/lib/extension.js +203 -0
  1775. node_ui/node_modules/ws/lib/limiter.js +55 -0
  1776. node_ui/node_modules/ws/lib/permessage-deflate.js +528 -0
  1777. node_ui/node_modules/ws/lib/receiver.js +706 -0
  1778. node_ui/node_modules/ws/lib/sender.js +602 -0
  1779. node_ui/node_modules/ws/lib/stream.js +161 -0
  1780. node_ui/node_modules/ws/lib/subprotocol.js +62 -0
  1781. node_ui/node_modules/ws/lib/validation.js +152 -0
  1782. node_ui/node_modules/ws/lib/websocket-server.js +550 -0
  1783. node_ui/node_modules/ws/lib/websocket.js +1388 -0
  1784. node_ui/node_modules/ws/package.json +69 -0
  1785. node_ui/node_modules/ws/wrapper.mjs +8 -0
  1786. node_ui/node_modules/yoga-wasm-web/LICENSE +21 -0
  1787. node_ui/node_modules/yoga-wasm-web/README.md +70 -0
  1788. node_ui/node_modules/yoga-wasm-web/dist/asm.d.ts +6 -0
  1789. node_ui/node_modules/yoga-wasm-web/dist/asm.js +1 -0
  1790. node_ui/node_modules/yoga-wasm-web/dist/auto.d.ts +7 -0
  1791. node_ui/node_modules/yoga-wasm-web/dist/browser.js +1 -0
  1792. node_ui/node_modules/yoga-wasm-web/dist/generated/YGEnums.d.ts +328 -0
  1793. node_ui/node_modules/yoga-wasm-web/dist/index.d.ts +7 -0
  1794. node_ui/node_modules/yoga-wasm-web/dist/index.js +1 -0
  1795. node_ui/node_modules/yoga-wasm-web/dist/node.js +1 -0
  1796. node_ui/node_modules/yoga-wasm-web/dist/wrapAsm-57389177.js +1 -0
  1797. node_ui/node_modules/yoga-wasm-web/dist/wrapAsm-f766f97f.js +1 -0
  1798. node_ui/node_modules/yoga-wasm-web/dist/wrapAsm.d.ts +176 -0
  1799. node_ui/node_modules/yoga-wasm-web/dist/yoga.wasm +0 -0
  1800. node_ui/node_modules/yoga-wasm-web/package.json +56 -0
  1801. node_ui/package.json +21 -0
  1802. claude_code_tools/codex_bridge_mcp.py +0 -333
  1803. claude_code_tools-0.2.0.dist-info/METADATA +0 -495
  1804. claude_code_tools-0.2.0.dist-info/RECORD +0 -22
  1805. {claude_code_tools-0.2.0.dist-info → claude_code_tools-1.4.1.dist-info}/licenses/LICENSE +0 -0
@@ -0,0 +1,2460 @@
1
+ #!/usr/bin/env python3
2
+ """
3
+ aichat - Unified CLI for AI chat session management tools.
4
+
5
+ This provides a grouped command interface for managing Claude Code and
6
+ Codex sessions, following the pattern of tools like git, docker, etc.
7
+
8
+ All session-related tools are accessible as subcommands:
9
+ aichat search - Full-text search across all sessions
10
+ aichat resume - Resume a session (latest or by ID)
11
+ aichat menu - Interactive session menu
12
+ aichat trim - Trim session content
13
+ ... and more
14
+
15
+ For backward compatibility, all flat commands (find-claude-session,
16
+ etc.) are still available.
17
+ """
18
+
19
+ import click
20
+
21
+
22
+ class SessionIDGroup(click.Group):
23
+ """Custom group that treats unknown commands as session IDs for menu."""
24
+
25
+ def parse_args(self, ctx, args):
26
+ # If the first arg looks like a session ID (not a known command), route to menu
27
+ if args and args[0] not in self.commands and not args[0].startswith('-'):
28
+ # Treat as session ID - prepend 'menu' to make it a menu command
29
+ args = ['menu'] + args
30
+ return super().parse_args(ctx, args)
31
+
32
+
33
+ @click.group(cls=SessionIDGroup, invoke_without_command=True)
34
+ @click.version_option()
35
+ @click.option(
36
+ '--claude-home',
37
+ type=click.Path(exists=True, file_okay=False, dir_okay=True),
38
+ help='Claude home directory (default: ~/.claude or CLAUDE_CONFIG_DIR)',
39
+ )
40
+ @click.option(
41
+ '--codex-home',
42
+ type=click.Path(exists=True, file_okay=False, dir_okay=True),
43
+ help='Codex home directory (default: ~/.codex or CODEX_HOME)',
44
+ )
45
+ @click.pass_context
46
+ def main(ctx, claude_home, codex_home):
47
+ """
48
+ Session management tools for Claude Code and Codex.
49
+
50
+ This is the recommended interface for managing AI chat sessions.
51
+ Each subcommand provides specialized functionality for finding,
52
+ managing, and manipulating session files.
53
+
54
+ For help on any subcommand, use:
55
+
56
+ \b
57
+ aichat COMMAND --help
58
+
59
+ Examples:
60
+
61
+ \b
62
+ aichat # Action menu for latest session(s)
63
+ aichat abc123-def456 # Shortcut for: aichat menu abc123-def456
64
+ aichat search "langroid" # Full-text search
65
+ aichat resume # Resume latest session
66
+ aichat resume abc123-def456 # Resume specific session
67
+ aichat menu abc123-def456
68
+ aichat trim session-id.jsonl
69
+
70
+ \b
71
+ Environment variables:
72
+ CLAUDE_CONFIG_DIR - Default Claude home (overridden by --claude-home)
73
+ CODEX_HOME - Default Codex home (overridden by --codex-home)
74
+ """
75
+ # Store home dirs in context for subcommands to access
76
+ ctx.ensure_object(dict)
77
+ ctx.obj['claude_home'] = claude_home
78
+ ctx.obj['codex_home'] = codex_home
79
+
80
+ # Auto-index sessions on every aichat command (incremental, fast if up-to-date)
81
+ # Skip for build-index/clear-index to avoid double-indexing or state conflicts
82
+ # In JSON mode (-j/--json), suppress all output for clean parsing
83
+ import sys
84
+ skip_auto_index_cmds = ['build-index', 'clear-index', 'index-stats']
85
+ should_skip = any(cmd in sys.argv for cmd in skip_auto_index_cmds)
86
+ json_mode = any(arg in sys.argv for arg in ['-j', '--json'])
87
+ if not should_skip:
88
+ try:
89
+ from claude_code_tools.search_index import auto_index
90
+ from claude_code_tools.session_utils import get_claude_home, get_codex_home
91
+ # Respect CLI args, then env vars, then defaults
92
+ auto_index(
93
+ claude_home=get_claude_home(cli_arg=claude_home),
94
+ codex_home=get_codex_home(cli_arg=codex_home),
95
+ verbose=False,
96
+ silent=json_mode,
97
+ )
98
+ except ImportError:
99
+ pass # tantivy not installed
100
+ except Exception:
101
+ pass # Index errors shouldn't block commands
102
+
103
+ if ctx.invoked_subcommand is None:
104
+ # No subcommand - find latest sessions and show action menu
105
+ _find_and_run_session_ui(
106
+ session_id=None,
107
+ agent_constraint='both',
108
+ start_screen='action',
109
+ select_target='action',
110
+ results_title=' Select a session ',
111
+ )
112
+
113
+
114
+ # Shared help text for find commands
115
+ _FIND_OPTIONS_COMMON = """
116
+ Options:
117
+ KEYWORDS Comma-separated keywords to search (AND logic)
118
+ -g, --global Search across all projects
119
+ -n, --num-matches N Number of matches to display (default: 10)
120
+ --original Show only original sessions
121
+ --no-sub Exclude sub-agent sessions
122
+ --no-trim Exclude trimmed sessions
123
+ --no-roll Exclude rollover sessions
124
+ --min-lines N Only sessions with at least N lines
125
+ --before TIMESTAMP Sessions modified before (inclusive)
126
+ --after TIMESTAMP Sessions modified after (inclusive)
127
+ --no-ui Skip options menu, run search with CLI args directly
128
+ --simple-ui Use Rich table UI instead of Node UI"""
129
+
130
+ _FIND_OPTIONS_CODEX = _FIND_OPTIONS_COMMON.replace(
131
+ " --no-sub Exclude sub-agent sessions\n", ""
132
+ )
133
+
134
+ _FIND_TIMESTAMP_HELP = """
135
+ Timestamp formats: YYYYMMDD, YYYY-MM-DD, MM/DD/YY, MM/DD/YYYY
136
+ Optional time: T16:45:23, T16:45, T16"""
137
+
138
+ _FIND_CTX_SETTINGS = {
139
+ "ignore_unknown_options": True,
140
+ "allow_extra_args": True,
141
+ "allow_interspersed_args": False,
142
+ }
143
+
144
+
145
+ def _find_and_run_session_ui(
146
+ session_id: str | None,
147
+ agent_constraint: str, # 'claude', 'codex', or 'both'
148
+ start_screen: str,
149
+ select_target: str | None = None,
150
+ results_title: str | None = None,
151
+ direct_action: str | None = None,
152
+ action_kwargs: dict | None = None,
153
+ ) -> None:
154
+ """
155
+ Find session(s) and run Node UI for the specified action.
156
+
157
+ If session_id is provided, routes to session_menu_cli.
158
+ Otherwise, finds latest sessions for current project/branch and shows UI.
159
+
160
+ Args:
161
+ session_id: Optional explicit session ID or path
162
+ agent_constraint: 'claude', 'codex', or 'both'
163
+ start_screen: Screen to show when single session found
164
+ select_target: Screen to go to after selection (multiple sessions)
165
+ results_title: Title for selection screen
166
+ direct_action: If set, execute this action directly instead of showing UI
167
+ action_kwargs: Optional kwargs to pass to action
168
+ """
169
+ import os
170
+ import subprocess
171
+ import sys
172
+ from pathlib import Path
173
+
174
+ from claude_code_tools.node_menu_ui import run_node_menu_ui
175
+ from claude_code_tools.search_index import SessionIndex
176
+ from claude_code_tools.session_menu_cli import execute_action
177
+ from claude_code_tools.session_utils import default_export_path
178
+
179
+ if session_id:
180
+ if direct_action:
181
+ # Direct action mode: bypass session_menu_cli for proper context
182
+ # This allows direct_action to be passed to Node UI for correct
183
+ # escape behavior (exit to shell vs. go to resume menu)
184
+ from claude_code_tools.session_utils import (
185
+ find_session_file,
186
+ default_export_path,
187
+ detect_agent_from_path,
188
+ )
189
+
190
+ # Find session file
191
+ input_path = Path(session_id).expanduser()
192
+ if input_path.exists() and input_path.is_file():
193
+ session_file = input_path
194
+ agent = detect_agent_from_path(session_file)
195
+ project_path = str(session_file.parent)
196
+ git_branch = None
197
+ else:
198
+ result = find_session_file(session_id)
199
+ if not result:
200
+ print(f"Error: Session not found: {session_id}", file=sys.stderr)
201
+ sys.exit(1)
202
+ agent, session_file, project_path, git_branch = result
203
+
204
+ # Build session dict for Node UI
205
+ session_dict = {
206
+ "agent": agent,
207
+ "agent_display": "Claude" if agent == "claude" else "Codex",
208
+ "session_id": session_file.stem,
209
+ "mod_time": session_file.stat().st_mtime,
210
+ "create_time": session_file.stat().st_ctime,
211
+ "lines": 0, # Not needed for direct action
212
+ "project": Path(project_path).name,
213
+ "preview": "",
214
+ "cwd": project_path,
215
+ "branch": git_branch or "",
216
+ "file_path": str(session_file),
217
+ "default_export_path": str(default_export_path(session_file, agent)),
218
+ "is_trimmed": False,
219
+ "derivation_type": None,
220
+ "is_sidechain": False,
221
+ }
222
+
223
+ # Handler for actions
224
+ def handler(sess, action, kwargs=None):
225
+ merged_kwargs = {**(action_kwargs or {}), **(kwargs or {})}
226
+ return execute_action(
227
+ action,
228
+ sess["agent"],
229
+ Path(sess["file_path"]),
230
+ sess["cwd"],
231
+ action_kwargs=merged_kwargs if merged_kwargs else None,
232
+ session_id=sess.get("session_id"),
233
+ )
234
+
235
+ rpc_path = str(Path(__file__).parent / "action_rpc.py")
236
+
237
+ # Run Node UI directly with direct_action for proper escape behavior
238
+ run_node_menu_ui(
239
+ [session_dict],
240
+ [],
241
+ handler,
242
+ start_screen=start_screen,
243
+ rpc_path=rpc_path,
244
+ direct_action=direct_action,
245
+ )
246
+ return
247
+
248
+ # Normal mode (no direct_action): route through session_menu_cli
249
+ sys.argv = [
250
+ sys.argv[0].replace('aichat', 'session-menu'),
251
+ '--start-screen', start_screen,
252
+ session_id,
253
+ ]
254
+ from claude_code_tools.session_menu_cli import main as menu_main
255
+ menu_main()
256
+ return
257
+
258
+ # No session provided - find latest sessions for current project and branch
259
+ current_cwd = os.getcwd()
260
+ current_branch = None
261
+ try:
262
+ result = subprocess.run(
263
+ ["git", "rev-parse", "--abbrev-ref", "HEAD"],
264
+ capture_output=True, text=True, check=True
265
+ )
266
+ current_branch = result.stdout.strip()
267
+ except (subprocess.CalledProcessError, FileNotFoundError):
268
+ pass
269
+
270
+ # Use the Tantivy index for fast session lookup
271
+ index_path = Path.home() / ".cctools" / "search-index"
272
+ if not index_path.exists():
273
+ print(
274
+ "Session index not found. Run 'aichat search' first to build the index.",
275
+ file=sys.stderr
276
+ )
277
+ sys.exit(1)
278
+
279
+ try:
280
+ idx = SessionIndex(index_path)
281
+ except Exception as e:
282
+ print(f"Failed to open session index: {e}", file=sys.stderr)
283
+ sys.exit(1)
284
+
285
+ candidates = []
286
+ used_fallback = False # Track if any agent fell back to any-branch
287
+
288
+ def _get_latest_session(agent: str) -> tuple[dict | None, bool]:
289
+ """Get latest session for agent, with fallback to any branch.
290
+
291
+ Returns (session_dict, used_fallback).
292
+ """
293
+ # First try with branch filter
294
+ if current_branch:
295
+ session = idx.get_latest_session(
296
+ cwd=current_cwd, branch=current_branch, agent=agent
297
+ )
298
+ if session:
299
+ return session, False
300
+
301
+ # Fallback: try without branch filter
302
+ session = idx.get_latest_session(cwd=current_cwd, agent=agent)
303
+ return session, bool(session) # used_fallback=True only if we found one
304
+
305
+ def _session_to_candidate(s: dict) -> dict:
306
+ """Convert index session dict to UI candidate format."""
307
+ export_path = s.get("export_path", "")
308
+ session_file = Path(export_path) if export_path else None
309
+ agent = s.get("agent", "claude")
310
+
311
+ # Parse timestamps - index stores as ISO strings
312
+ mod_time = 0
313
+ create_time = 0
314
+ if s.get("modified"):
315
+ try:
316
+ from datetime import datetime
317
+ mod_time = datetime.fromisoformat(
318
+ s["modified"].replace("Z", "+00:00")
319
+ ).timestamp()
320
+ except (ValueError, TypeError):
321
+ pass
322
+ if s.get("created"):
323
+ try:
324
+ from datetime import datetime
325
+ create_time = datetime.fromisoformat(
326
+ s["created"].replace("Z", "+00:00")
327
+ ).timestamp()
328
+ except (ValueError, TypeError):
329
+ pass
330
+
331
+ # Build preview from last message content (convention: show most recent)
332
+ preview = ""
333
+ if s.get("last_msg_content"):
334
+ role = s.get("last_msg_role", "assistant")
335
+ preview = f"[{role}] {s['last_msg_content'][:200]}"
336
+
337
+ return {
338
+ "agent": agent,
339
+ "agent_display": "Claude" if agent == "claude" else "Codex",
340
+ "session_id": s.get("session_id", ""),
341
+ "mod_time": mod_time,
342
+ "create_time": create_time,
343
+ "lines": s.get("lines", 0),
344
+ "project": s.get("project", ""),
345
+ "preview": preview,
346
+ "cwd": s.get("cwd", ""),
347
+ "branch": s.get("branch", ""),
348
+ "file_path": export_path,
349
+ "default_export_path": str(
350
+ default_export_path(session_file, agent)
351
+ ) if session_file and session_file.exists() else "",
352
+ "is_trimmed": s.get("derivation_type") == "trimmed",
353
+ "derivation_type": s.get("derivation_type"),
354
+ "is_sidechain": s.get("is_sidechain") == "true",
355
+ }
356
+
357
+ # Find Claude sessions if applicable
358
+ if agent_constraint in ('claude', 'both'):
359
+ session, fallback = _get_latest_session("claude")
360
+ if session:
361
+ candidates.append(_session_to_candidate(session))
362
+ if fallback:
363
+ used_fallback = True
364
+
365
+ # Find Codex sessions if applicable
366
+ if agent_constraint in ('codex', 'both'):
367
+ session, fallback = _get_latest_session("codex")
368
+ if session:
369
+ candidates.append(_session_to_candidate(session))
370
+ if fallback:
371
+ used_fallback = True
372
+
373
+ # Build the unified scope message
374
+ project_name = Path(current_cwd).name
375
+ agent_desc = {
376
+ 'claude': 'Claude',
377
+ 'codex': 'Codex',
378
+ 'both': 'Claude/Codex',
379
+ }.get(agent_constraint, 'Claude/Codex')
380
+ branch_part = f" on branch '{current_branch}'" if current_branch else ""
381
+ fallback_note = " (fallback to any branch if none found)" if current_branch else ""
382
+ scope_text = (
383
+ f"Latest {agent_desc} sessions for '{project_name}'{branch_part}{fallback_note}"
384
+ )
385
+
386
+ if not candidates:
387
+ print(
388
+ f"No {agent_desc} sessions found for '{project_name}'"
389
+ f"{branch_part} (even with fallback to any branch).",
390
+ file=sys.stderr
391
+ )
392
+ sys.exit(1)
393
+
394
+ # Handler for when user selects and acts - returns 'back' if user wants to
395
+ # go back to menu
396
+ def handler(sess, action, kwargs=None):
397
+ session_file = Path(sess["file_path"])
398
+ merged_kwargs = {**(action_kwargs or {}), **(kwargs or {})}
399
+ return execute_action(
400
+ action,
401
+ sess["agent"],
402
+ session_file,
403
+ sess["cwd"],
404
+ action_kwargs=merged_kwargs if merged_kwargs else None,
405
+ session_id=sess.get("session_id"),
406
+ )
407
+
408
+ rpc_path = str(Path(__file__).parent / "action_rpc.py")
409
+
410
+ # If direct_action specified, execute it immediately for single session
411
+ if direct_action and len(candidates) == 1:
412
+ handler(candidates[0], direct_action, action_kwargs)
413
+ return
414
+
415
+ # Create handler that may execute direct_action after selection
416
+ def selection_handler(sess, action, kwargs=None):
417
+ if direct_action:
418
+ # Execute direct_action instead of whatever came from UI
419
+ return handler(sess, direct_action, action_kwargs)
420
+ else:
421
+ return handler(sess, action, kwargs)
422
+
423
+ if len(candidates) == 1:
424
+ # Single session - go directly to start_screen
425
+ run_node_menu_ui(
426
+ candidates,
427
+ [],
428
+ selection_handler,
429
+ start_screen=start_screen,
430
+ scope_line=scope_text,
431
+ rpc_path=rpc_path,
432
+ direct_action=direct_action,
433
+ )
434
+ else:
435
+ # Multiple sessions - show selection first
436
+ run_node_menu_ui(
437
+ candidates,
438
+ [],
439
+ selection_handler,
440
+ start_screen="results",
441
+ select_target=select_target or start_screen,
442
+ results_title=results_title or f" Select session for {start_screen} ",
443
+ start_zoomed=True,
444
+ scope_line=scope_text,
445
+ rpc_path=rpc_path,
446
+ direct_action=direct_action,
447
+ )
448
+
449
+
450
+ @main.command("find", context_settings=_FIND_CTX_SETTINGS, add_help_option=False, hidden=True)
451
+ @click.pass_context
452
+ def find(ctx):
453
+ """Find sessions across all agents (Claude Code, Codex, etc.)."""
454
+ import sys
455
+ sys.argv = [sys.argv[0].replace('aichat', 'find-session')] + ctx.args
456
+ from claude_code_tools.find_session import main as find_main
457
+ find_main()
458
+
459
+
460
+ find.__doc__ = f"""Find sessions across all agents (Claude Code, Codex, etc.).
461
+ {_FIND_OPTIONS_COMMON}
462
+ --agents AGENT [...] Limit to one or more agents (e.g., --agents claude,
463
+ --agents claude codex). Default: all.
464
+ {_FIND_TIMESTAMP_HELP}
465
+
466
+ Examples:
467
+ aichat find "langroid,MCP"
468
+ aichat find -g --min-lines 50 --agents claude
469
+ aichat find --after 11/20/25 --before 11/25/25
470
+ """
471
+
472
+
473
+ @main.command("find-claude", context_settings=_FIND_CTX_SETTINGS, add_help_option=False, hidden=True)
474
+ @click.pass_context
475
+ def find_claude(ctx):
476
+ """Find Claude Code sessions by keywords."""
477
+ import sys
478
+ sys.argv = [sys.argv[0].replace('aichat', 'find-claude-session')] + ctx.args
479
+ from claude_code_tools.find_claude_session import main as find_claude_main
480
+ find_claude_main()
481
+
482
+
483
+ find_claude.__doc__ = f"""Find Claude Code sessions by keywords.
484
+ {_FIND_OPTIONS_COMMON}
485
+ {_FIND_TIMESTAMP_HELP}
486
+
487
+ Examples:
488
+ aichat find-claude "bug fix"
489
+ aichat find-claude -g --min-lines 100
490
+ aichat find-claude --after 2025-11-01
491
+ """
492
+
493
+
494
+ @main.command("find-codex", context_settings=_FIND_CTX_SETTINGS, add_help_option=False, hidden=True)
495
+ @click.pass_context
496
+ def find_codex(ctx):
497
+ """Find Codex sessions by keywords."""
498
+ import sys
499
+ sys.argv = [sys.argv[0].replace('aichat', 'find-codex-session')] + ctx.args
500
+ from claude_code_tools.find_codex_session import main as find_codex_main
501
+ find_codex_main()
502
+
503
+
504
+ find_codex.__doc__ = f"""Find Codex sessions by keywords.
505
+ {_FIND_OPTIONS_CODEX}
506
+ {_FIND_TIMESTAMP_HELP}
507
+
508
+ Examples:
509
+ aichat find-codex "error"
510
+ aichat find-codex -g --after 11/15/25
511
+ """
512
+
513
+
514
+ @main.command("find-original", context_settings={"ignore_unknown_options": True, "allow_extra_args": True, "allow_interspersed_args": False})
515
+ @click.pass_context
516
+ def find_original(ctx):
517
+ """Find the original session from a trimmed/continued session."""
518
+ import sys
519
+ sys.argv = [sys.argv[0].replace('aichat', 'find-original-session')] + ctx.args
520
+ from claude_code_tools.find_original_session import (
521
+ main as find_original_main,
522
+ )
523
+ find_original_main()
524
+
525
+
526
+ @main.command("find-derived", context_settings={"ignore_unknown_options": True, "allow_extra_args": True, "allow_interspersed_args": False})
527
+ @click.pass_context
528
+ def find_derived(ctx):
529
+ """Find derived sessions (trimmed/continued) from an original."""
530
+ import sys
531
+ sys.argv = [sys.argv[0].replace('aichat', 'find-trimmed-sessions')] + ctx.args
532
+ from claude_code_tools.find_trimmed_sessions import (
533
+ main as find_derived_main,
534
+ )
535
+ find_derived_main()
536
+
537
+
538
+ @main.command("menu", context_settings={"ignore_unknown_options": True, "allow_extra_args": True, "allow_interspersed_args": False})
539
+ @click.pass_context
540
+ def menu(ctx):
541
+ """Interactive menu for a specific session (by ID or path)."""
542
+ import sys
543
+ sys.argv = [sys.argv[0].replace('aichat', 'session-menu')] + ctx.args
544
+ from claude_code_tools.session_menu_cli import main as menu_main
545
+ menu_main()
546
+
547
+
548
+ @main.command("trim")
549
+ @click.argument("session", required=False)
550
+ @click.option("--tools", "-t",
551
+ help="Comma-separated tools to trim (e.g., 'bash,read,edit'). "
552
+ "Default: all tools.")
553
+ @click.option("--len", "-l", "threshold", type=int, default=500,
554
+ help="Minimum length threshold in chars for trimming (default: 500)")
555
+ @click.option("--trim-assistant", "-a", "trim_assistant", type=int,
556
+ help="Trim assistant messages: positive N trims first N over threshold, "
557
+ "negative N trims all except last |N| over threshold")
558
+ @click.option("--output-dir", "-o",
559
+ help="Output directory (default: same as input file)")
560
+ @click.option("--agent", type=click.Choice(["claude", "codex"], case_sensitive=False),
561
+ help="Force agent type (auto-detected if not specified)")
562
+ @click.option("--claude-home", help="Path to Claude home directory")
563
+ @click.option("--simple-ui", is_flag=True,
564
+ help="Use simple CLI trim instead of Node UI (requires session ID)")
565
+ def trim(session, tools, threshold, trim_assistant, output_dir, agent, claude_home, simple_ui):
566
+ """Trim session to reduce size by truncating large tool outputs.
567
+
568
+ Trims tool call results and optionally assistant messages that exceed
569
+ the length threshold. Creates a new trimmed session file with lineage
570
+ metadata linking back to the original.
571
+
572
+ If no session ID provided, finds latest session for current project/branch
573
+ and opens the interactive trim menu.
574
+
575
+ \b
576
+ Examples:
577
+ aichat trim # Interactive menu for latest session
578
+ aichat trim abc123 # Interactive menu for specific session
579
+ aichat trim abc123 --simple-ui # Direct CLI trim with defaults
580
+ aichat trim abc123 -t bash,read -l 1000 # Trim specific tools, custom threshold
581
+ aichat trim abc123 -a 5 # Also trim first 5 long assistant msgs
582
+
583
+ \b
584
+ Options:
585
+ --tools, -t Which tool outputs to trim (default: all)
586
+ --len, -l Character threshold for trimming (default: 500)
587
+ --trim-assistant, -a Trim assistant messages too
588
+ --output-dir, -o Where to write trimmed file
589
+ """
590
+ import sys
591
+
592
+ if simple_ui or tools or trim_assistant or output_dir:
593
+ # Direct CLI mode - need a session
594
+ if not session:
595
+ print("Error: Direct trim options require a session ID", file=sys.stderr)
596
+ print("Use 'aichat trim' without options for interactive mode", file=sys.stderr)
597
+ sys.exit(1)
598
+
599
+ # Build args for trim-session CLI
600
+ args = [session]
601
+ if tools:
602
+ args.extend(["--tools", tools])
603
+ if threshold != 500:
604
+ args.extend(["--len", str(threshold)])
605
+ if trim_assistant is not None:
606
+ args.extend(["--trim-assistant-messages", str(trim_assistant)])
607
+ if output_dir:
608
+ args.extend(["--output-dir", output_dir])
609
+ if agent:
610
+ args.extend(["--agent", agent])
611
+ if claude_home:
612
+ args.extend(["--claude-home", claude_home])
613
+
614
+ sys.argv = [sys.argv[0].replace('aichat', 'trim-session')] + args
615
+ from claude_code_tools.trim_session import main as trim_main
616
+ trim_main()
617
+ return
618
+
619
+ _find_and_run_session_ui(
620
+ session_id=session,
621
+ agent_constraint='both',
622
+ start_screen='trim_menu',
623
+ select_target='trim_menu',
624
+ results_title=' Which session to trim? ',
625
+ )
626
+
627
+
628
+ @main.command("smart-trim")
629
+ @click.argument("session", required=False)
630
+ @click.option("--instructions", "-i",
631
+ help="Custom instructions for what to prioritize when trimming")
632
+ @click.option("--exclude-types", "-e",
633
+ help="Comma-separated message types to never trim (default: user)")
634
+ @click.option("--preserve-recent", "-p", type=int, default=10,
635
+ help="Always preserve last N messages (default: 10)")
636
+ @click.option("--len", "-l", "content_threshold", type=int, default=200,
637
+ help="Minimum chars for content extraction (default: 200)")
638
+ @click.option("--output-dir", "-o",
639
+ help="Output directory (default: same as input)")
640
+ @click.option("--dry-run", "-n", is_flag=True,
641
+ help="Show what would be trimmed without doing it")
642
+ @click.option("--claude-home", help="Path to Claude home directory")
643
+ def smart_trim(session, instructions, exclude_types, preserve_recent, content_threshold,
644
+ output_dir, dry_run, claude_home):
645
+ """Smart trim using Claude SDK agents (EXPERIMENTAL).
646
+
647
+ Uses an LLM to intelligently analyze the session and decide what can
648
+ be safely trimmed while preserving important context. Creates a new
649
+ trimmed session with lineage metadata.
650
+
651
+ If no session ID provided, finds latest session for current project/branch.
652
+
653
+ \b
654
+ Examples:
655
+ aichat smart-trim # Interactive for latest session
656
+ aichat smart-trim abc123 # Smart trim specific session
657
+ aichat smart-trim abc123 --dry-run # Preview what would be trimmed
658
+ aichat smart-trim abc123 -p 20 # Preserve last 20 messages
659
+ aichat smart-trim abc123 -e user,system # Never trim user or system msgs
660
+ aichat smart-trim abc123 -i "preserve auth-related messages"
661
+
662
+ \b
663
+ Options:
664
+ --instructions, -i Custom instructions for what to prioritize
665
+ --exclude-types, -e Message types to EXCLUDE from trimming
666
+ --preserve-recent, -p Keep last N messages untouched (default: 10)
667
+ --len, -l Min chars for content extraction (default: 200)
668
+ --dry-run, -n Preview only, don't actually trim
669
+ """
670
+ import sys
671
+ from pathlib import Path
672
+
673
+ from claude_code_tools.session_utils import find_session_file, detect_agent_from_path
674
+
675
+ # If --instructions provided, use the handler function (same as TUI)
676
+ if instructions and session:
677
+ input_path = Path(session).expanduser()
678
+ if input_path.exists() and input_path.is_file():
679
+ session_file = input_path
680
+ detected_agent = detect_agent_from_path(session_file)
681
+ session_id = session_file.stem
682
+ project_path = str(session_file.parent)
683
+ else:
684
+ result = find_session_file(session)
685
+ if not result:
686
+ print(f"Error: Session not found: {session}", file=sys.stderr)
687
+ sys.exit(1)
688
+ detected_agent, session_file, project_path, _ = result
689
+ session_id = session_file.stem
690
+
691
+ # Use the handler function which supports custom_instructions
692
+ if detected_agent == "claude":
693
+ from claude_code_tools.find_claude_session import handle_smart_trim_resume_claude
694
+ handle_smart_trim_resume_claude(
695
+ session_id, project_path, claude_home,
696
+ custom_instructions=instructions,
697
+ )
698
+ else:
699
+ from claude_code_tools.find_codex_session import handle_smart_trim_resume_codex
700
+ from claude_code_tools.session_utils import get_codex_home
701
+ handle_smart_trim_resume_codex(
702
+ {"file_path": str(session_file), "cwd": project_path, "session_id": session_id},
703
+ Path(get_codex_home(cli_arg=None)),
704
+ custom_instructions=instructions,
705
+ )
706
+ return
707
+
708
+ # If any direct CLI options specified (but not instructions), use smart_trim.py
709
+ if exclude_types or preserve_recent != 10 or content_threshold != 200 or output_dir or dry_run:
710
+ if not session:
711
+ print("Error: Direct smart-trim options require a session ID", file=sys.stderr)
712
+ print("Use 'aichat smart-trim' without options for interactive mode", file=sys.stderr)
713
+ sys.exit(1)
714
+
715
+ # Build args for smart-trim CLI
716
+ args = [session]
717
+ if exclude_types:
718
+ args.extend(["--exclude-types", exclude_types])
719
+ if preserve_recent != 10:
720
+ args.extend(["--preserve-recent", str(preserve_recent)])
721
+ if content_threshold != 200:
722
+ args.extend(["--content-threshold", str(content_threshold)])
723
+ if output_dir:
724
+ args.extend(["--output-dir", output_dir])
725
+ if dry_run:
726
+ args.append("--dry-run")
727
+ if claude_home:
728
+ args.extend(["--claude-home", claude_home])
729
+
730
+ sys.argv = [sys.argv[0].replace('aichat', 'smart-trim')] + args
731
+ from claude_code_tools.smart_trim import main as smart_trim_main
732
+ smart_trim_main()
733
+ return
734
+
735
+ # Show interactive UI for entering instructions
736
+ # (whether session provided or not - find latest if not)
737
+ _find_and_run_session_ui(
738
+ session_id=session,
739
+ agent_constraint='both',
740
+ start_screen='smart_trim_form',
741
+ select_target='smart_trim_form',
742
+ results_title=' Which session to smart-trim? ',
743
+ )
744
+
745
+
746
+ @main.command("export", context_settings={"ignore_unknown_options": True, "allow_extra_args": True, "allow_interspersed_args": False})
747
+ @click.option("--agent", type=click.Choice(["claude", "codex"], case_sensitive=False), help="Force export with specific agent")
748
+ @click.argument("session", required=False)
749
+ @click.pass_context
750
+ def export_session(ctx, agent, session):
751
+ """Export session to text/markdown format.
752
+
753
+ If no session ID provided, finds latest session for current project/branch.
754
+ Auto-detects session type and uses matching export command.
755
+ Use --agent to override and force export with a specific agent.
756
+ """
757
+ import sys
758
+ from pathlib import Path
759
+ from claude_code_tools.session_utils import detect_agent_from_path, find_session_file
760
+
761
+ if not session:
762
+ # No session provided - find latest and export directly
763
+ _find_and_run_session_ui(
764
+ session_id=None,
765
+ agent_constraint='both',
766
+ start_screen='action',
767
+ results_title=' Which session to export? ',
768
+ direct_action='export',
769
+ )
770
+ return
771
+
772
+ # Session provided - existing behavior
773
+ # Try to detect session type
774
+ detected_agent = None
775
+ session_file = None
776
+
777
+ # First check if it's a file path
778
+ input_path = Path(session).expanduser()
779
+ if input_path.exists() and input_path.is_file():
780
+ session_file = input_path
781
+ detected_agent = detect_agent_from_path(session_file)
782
+ else:
783
+ # Try to find by session ID
784
+ result = find_session_file(session)
785
+ if result:
786
+ detected_agent, session_file, _, _ = result
787
+
788
+ # Determine which agent to use
789
+ if agent:
790
+ # User explicitly specified agent
791
+ export_agent = agent.lower()
792
+ if detected_agent and detected_agent != export_agent:
793
+ print(f"\nDetected {detected_agent.upper()} session")
794
+ print(f"Exporting with {export_agent.upper()} (user specified)")
795
+ else:
796
+ print(f"\nExporting with {export_agent.upper()} (user specified)")
797
+ elif detected_agent:
798
+ # Use detected agent
799
+ export_agent = detected_agent
800
+ print(f"\nDetected {detected_agent.upper()} session")
801
+ print(f"Exporting with {export_agent.upper()}")
802
+ else:
803
+ # Default to Claude if cannot detect
804
+ export_agent = "claude"
805
+ print(f"\nCould not detect session type, defaulting to CLAUDE")
806
+
807
+ print()
808
+
809
+ # Route to appropriate export command
810
+ if export_agent == "claude":
811
+ sys.argv = [sys.argv[0].replace('aichat', 'export-claude-session'), session] + ctx.args
812
+ from claude_code_tools.export_claude_session import main as export_main
813
+ export_main()
814
+ else:
815
+ sys.argv = [sys.argv[0].replace('aichat', 'export-codex-session'), session] + ctx.args
816
+ from claude_code_tools.export_codex_session import main as export_main
817
+ export_main()
818
+
819
+
820
+ @main.command("export-claude", context_settings={"ignore_unknown_options": True, "allow_extra_args": True, "allow_interspersed_args": False})
821
+ @click.pass_context
822
+ def export_claude(ctx):
823
+ """Export Claude Code session to text/markdown format.
824
+
825
+ If no session ID provided, finds latest Claude session for current
826
+ project/branch.
827
+ """
828
+ import sys
829
+ args = ctx.args
830
+ session_id = args[0] if args and not args[0].startswith('-') else None
831
+
832
+ if session_id:
833
+ # Pass to existing export CLI
834
+ sys.argv = [sys.argv[0].replace('aichat', 'export-claude-session')] + args
835
+ from claude_code_tools.export_claude_session import (
836
+ main as export_claude_main,
837
+ )
838
+ export_claude_main()
839
+ else:
840
+ # Find latest Claude session and export directly
841
+ _find_and_run_session_ui(
842
+ session_id=None,
843
+ agent_constraint='claude',
844
+ start_screen='action',
845
+ results_title=' Which Claude session to export? ',
846
+ direct_action='export',
847
+ )
848
+
849
+
850
+ @main.command("export-codex", context_settings={"ignore_unknown_options": True, "allow_extra_args": True, "allow_interspersed_args": False})
851
+ @click.pass_context
852
+ def export_codex(ctx):
853
+ """Export Codex session to text/markdown format.
854
+
855
+ If no session ID provided, finds latest Codex session for current
856
+ project/branch.
857
+ """
858
+ import sys
859
+ args = ctx.args
860
+ session_id = args[0] if args and not args[0].startswith('-') else None
861
+
862
+ if session_id:
863
+ # Pass to existing export CLI
864
+ sys.argv = [sys.argv[0].replace('aichat', 'export-codex-session')] + args
865
+ from claude_code_tools.export_codex_session import (
866
+ main as export_codex_main,
867
+ )
868
+ export_codex_main()
869
+ else:
870
+ # Find latest Codex session and export directly
871
+ _find_and_run_session_ui(
872
+ session_id=None,
873
+ agent_constraint='codex',
874
+ start_screen='action',
875
+ results_title=' Which Codex session to export? ',
876
+ direct_action='export',
877
+ )
878
+
879
+
880
+ @main.command("delete", context_settings={"ignore_unknown_options": True, "allow_extra_args": True, "allow_interspersed_args": False})
881
+ @click.pass_context
882
+ def delete(ctx):
883
+ """Delete a session file with safety confirmation."""
884
+ import sys
885
+ sys.argv = [sys.argv[0].replace('aichat', 'delete-session')] + ctx.args
886
+ from claude_code_tools.delete_session import main as delete_main
887
+ delete_main()
888
+
889
+
890
+ @main.command("info")
891
+ @click.argument("session", required=False)
892
+ @click.option("--agent", type=click.Choice(["claude", "codex"], case_sensitive=False),
893
+ help="Force agent type (auto-detected if not specified)")
894
+ @click.option("--json", "json_output", is_flag=True, help="Output as JSON")
895
+ def info(session, agent, json_output):
896
+ """Show information about a session.
897
+
898
+ Displays session metadata including file path, agent type, project,
899
+ branch, timestamps, message counts, and lineage (parent sessions).
900
+
901
+ If no session ID provided, shows info for latest session in current
902
+ project/branch.
903
+
904
+ \b
905
+ Examples:
906
+ aichat info # Info for latest session
907
+ aichat info abc123-def456 # Info for specific session
908
+ aichat info --json abc123 # Output as JSON
909
+ """
910
+ import json as json_lib
911
+ import sys
912
+ from pathlib import Path
913
+ from datetime import datetime
914
+
915
+ from claude_code_tools.session_utils import (
916
+ find_session_file,
917
+ detect_agent_from_path,
918
+ extract_cwd_from_session,
919
+ count_user_messages,
920
+ default_export_path,
921
+ )
922
+ from claude_code_tools.session_lineage import get_continuation_lineage
923
+
924
+ # Find session file
925
+ if session:
926
+ input_path = Path(session).expanduser()
927
+ if input_path.exists() and input_path.is_file():
928
+ session_file = input_path
929
+ detected_agent = agent or detect_agent_from_path(session_file)
930
+ else:
931
+ result = find_session_file(session)
932
+ if not result:
933
+ print(f"Error: Session not found: {session}", file=sys.stderr)
934
+ sys.exit(1)
935
+ detected_agent, session_file, _, _ = result
936
+ if agent:
937
+ detected_agent = agent
938
+ else:
939
+ # No session provided - find latest
940
+ _find_and_run_session_ui(
941
+ session_id=None,
942
+ agent_constraint='both',
943
+ start_screen='action',
944
+ direct_action='path', # Just show path for now
945
+ )
946
+ return
947
+
948
+ # Gather session info
949
+ session_id = session_file.stem
950
+ mod_time = datetime.fromtimestamp(session_file.stat().st_mtime)
951
+ create_time = datetime.fromtimestamp(session_file.stat().st_ctime)
952
+ file_size = session_file.stat().st_size
953
+ line_count = sum(1 for _ in open(session_file))
954
+
955
+ # Extract metadata from session
956
+ from claude_code_tools.export_session import extract_session_metadata
957
+ metadata = extract_session_metadata(session_file, detected_agent)
958
+ cwd = metadata.get("cwd") or extract_cwd_from_session(session_file)
959
+ project = Path(cwd).name if cwd else "unknown"
960
+ custom_title = metadata.get("customTitle", "")
961
+ user_msg_count = count_user_messages(session_file, detected_agent)
962
+
963
+ # Get lineage
964
+ lineage = get_continuation_lineage(session_file, export_missing=False)
965
+ lineage_info = []
966
+ for node in lineage:
967
+ lineage_info.append({
968
+ "file": str(node.session_file),
969
+ "type": node.derivation_type or "original",
970
+ })
971
+
972
+ info_data = {
973
+ "session_id": session_id,
974
+ "agent": detected_agent,
975
+ "custom_title": custom_title,
976
+ "file_path": str(session_file),
977
+ "project": project,
978
+ "cwd": cwd,
979
+ "created": create_time.isoformat(),
980
+ "modified": mod_time.isoformat(),
981
+ "file_size_bytes": file_size,
982
+ "line_count": line_count,
983
+ "user_message_count": user_msg_count,
984
+ "export_path": str(default_export_path(session_file, detected_agent)),
985
+ "lineage": lineage_info,
986
+ }
987
+
988
+ if json_output:
989
+ print(json_lib.dumps(info_data, indent=2))
990
+ else:
991
+ print(f"\n{'='*60}")
992
+ print(f"Session: {session_id}")
993
+ if custom_title:
994
+ print(f"Title: {custom_title}")
995
+ print(f"{'='*60}")
996
+ print(f"Agent: {detected_agent}")
997
+ print(f"Project: {project}")
998
+ print(f"CWD: {cwd}")
999
+ print(f"File: {session_file}")
1000
+ print(f"Created: {create_time.strftime('%Y-%m-%d %H:%M:%S')}")
1001
+ print(f"Modified: {mod_time.strftime('%Y-%m-%d %H:%M:%S')}")
1002
+ print(f"Size: {file_size:,} bytes")
1003
+ print(f"Lines: {line_count:,}")
1004
+ print(f"User msgs: {user_msg_count}")
1005
+ if lineage_info:
1006
+ print(f"\nLineage ({len(lineage_info)} sessions):")
1007
+ for i, node in enumerate(lineage_info):
1008
+ prefix = " └─" if i == len(lineage_info) - 1 else " ├─"
1009
+ fname = Path(node["file"]).name
1010
+ print(f"{prefix} {fname} ({node['type']})")
1011
+
1012
+
1013
+ @main.command("copy")
1014
+ @click.argument("session", required=False)
1015
+ @click.option("--dest", "-d", help="Destination path (default: prompted)")
1016
+ @click.option("--agent", type=click.Choice(["claude", "codex"], case_sensitive=False),
1017
+ help="Force agent type (auto-detected if not specified)")
1018
+ def copy_session(session, dest, agent):
1019
+ """Copy a session file to a new location.
1020
+
1021
+ If no session ID provided, finds latest session for current project/branch.
1022
+
1023
+ \b
1024
+ Examples:
1025
+ aichat copy abc123-def456 # Copy with prompted destination
1026
+ aichat copy abc123 -d ~/backups/ # Copy to specific directory
1027
+ aichat copy abc123 -d ./my-session.jsonl # Copy with specific filename
1028
+ """
1029
+ import sys
1030
+ from pathlib import Path
1031
+
1032
+ from claude_code_tools.session_utils import find_session_file, detect_agent_from_path
1033
+
1034
+ if not session:
1035
+ _find_and_run_session_ui(
1036
+ session_id=None,
1037
+ agent_constraint='both',
1038
+ start_screen='action',
1039
+ direct_action='copy',
1040
+ )
1041
+ return
1042
+
1043
+ # Find session file
1044
+ input_path = Path(session).expanduser()
1045
+ if input_path.exists() and input_path.is_file():
1046
+ session_file = input_path
1047
+ detected_agent = agent or detect_agent_from_path(session_file)
1048
+ else:
1049
+ result = find_session_file(session)
1050
+ if not result:
1051
+ print(f"Error: Session not found: {session}", file=sys.stderr)
1052
+ sys.exit(1)
1053
+ detected_agent, session_file, _, _ = result
1054
+ if agent:
1055
+ detected_agent = agent
1056
+
1057
+ # Import agent-specific copy function
1058
+ if detected_agent == "claude":
1059
+ from claude_code_tools.find_claude_session import copy_session_file
1060
+ else:
1061
+ from claude_code_tools.find_codex_session import copy_session_file
1062
+
1063
+ copy_session_file(str(session_file), dest)
1064
+
1065
+
1066
+ @main.command("query")
1067
+ @click.argument("session", required=False)
1068
+ @click.argument("question", required=False)
1069
+ @click.option("--agent", type=click.Choice(["claude", "codex"], case_sensitive=False),
1070
+ help="Force agent type (auto-detected if not specified)")
1071
+ def query_session(session, question, agent):
1072
+ """Query a session with a question using an AI agent.
1073
+
1074
+ Exports the session and uses Claude to answer questions about its content.
1075
+ If no question provided, opens interactive query mode.
1076
+
1077
+ \b
1078
+ Examples:
1079
+ aichat query abc123 "What was the main bug fixed?"
1080
+ aichat query abc123 "Summarize the changes made"
1081
+ aichat query # Interactive mode for latest session
1082
+ """
1083
+ import sys
1084
+ from pathlib import Path
1085
+
1086
+ from claude_code_tools.session_utils import find_session_file, detect_agent_from_path
1087
+
1088
+ if not session:
1089
+ _find_and_run_session_ui(
1090
+ session_id=None,
1091
+ agent_constraint='both',
1092
+ start_screen='query',
1093
+ direct_action='query',
1094
+ )
1095
+ return
1096
+
1097
+ # Find session file
1098
+ input_path = Path(session).expanduser()
1099
+ if input_path.exists() and input_path.is_file():
1100
+ session_file = input_path
1101
+ detected_agent = agent or detect_agent_from_path(session_file)
1102
+ else:
1103
+ result = find_session_file(session)
1104
+ if not result:
1105
+ print(f"Error: Session not found: {session}", file=sys.stderr)
1106
+ sys.exit(1)
1107
+ detected_agent, session_file, cwd, _ = result
1108
+ if agent:
1109
+ detected_agent = agent
1110
+
1111
+ # If no question, show interactive query UI
1112
+ if not question:
1113
+ from claude_code_tools.node_menu_ui import run_node_menu_ui
1114
+ from claude_code_tools.session_menu_cli import execute_action
1115
+
1116
+ rpc_path = str(Path(__file__).parent / "action_rpc.py")
1117
+ session_data = {
1118
+ "session_id": session_file.stem,
1119
+ "agent": detected_agent,
1120
+ "file_path": str(session_file),
1121
+ "cwd": str(session_file.parent),
1122
+ }
1123
+
1124
+ def handler(sess, action, kwargs=None):
1125
+ return execute_action(
1126
+ action, sess["agent"], Path(sess["file_path"]),
1127
+ sess["cwd"], action_kwargs=kwargs
1128
+ )
1129
+
1130
+ run_node_menu_ui(
1131
+ [session_data], [], handler,
1132
+ start_screen="query",
1133
+ rpc_path=rpc_path,
1134
+ )
1135
+ return
1136
+
1137
+ # Direct query with provided question
1138
+ from claude_code_tools.session_utils import default_export_path
1139
+
1140
+ # Export session first
1141
+ if detected_agent == "claude":
1142
+ from claude_code_tools.find_claude_session import handle_export_session
1143
+ else:
1144
+ from claude_code_tools.find_codex_session import handle_export_session
1145
+
1146
+ export_path = default_export_path(session_file, detected_agent)
1147
+ handle_export_session(str(session_file))
1148
+
1149
+ # Query using Claude
1150
+ import subprocess
1151
+ prompt = f"Read the session transcript at {export_path} and answer: {question}"
1152
+ subprocess.run(["claude", "-p", prompt])
1153
+
1154
+
1155
+ @main.command("clone")
1156
+ @click.argument("session", required=False)
1157
+ @click.option("--agent", type=click.Choice(["claude", "codex"], case_sensitive=False),
1158
+ help="Force agent type (auto-detected if not specified)")
1159
+ def clone_session_cmd(session, agent):
1160
+ """Clone a session and resume the clone.
1161
+
1162
+ Creates a copy of the session with a new ID and resumes it,
1163
+ leaving the original session untouched.
1164
+
1165
+ If no session ID provided, finds latest session for current project/branch.
1166
+
1167
+ \b
1168
+ Examples:
1169
+ aichat clone abc123-def456 # Clone specific session
1170
+ aichat clone # Clone latest session
1171
+ """
1172
+ import sys
1173
+ from pathlib import Path
1174
+
1175
+ from claude_code_tools.session_utils import find_session_file, detect_agent_from_path
1176
+
1177
+ if not session:
1178
+ _find_and_run_session_ui(
1179
+ session_id=None,
1180
+ agent_constraint='both',
1181
+ start_screen='resume',
1182
+ direct_action='clone',
1183
+ )
1184
+ return
1185
+
1186
+ # Find session file
1187
+ input_path = Path(session).expanduser()
1188
+ if input_path.exists() and input_path.is_file():
1189
+ session_file = input_path
1190
+ detected_agent = agent or detect_agent_from_path(session_file)
1191
+ cwd = str(session_file.parent)
1192
+ else:
1193
+ result = find_session_file(session)
1194
+ if not result:
1195
+ print(f"Error: Session not found: {session}", file=sys.stderr)
1196
+ sys.exit(1)
1197
+ detected_agent, session_file, cwd, _ = result
1198
+ if agent:
1199
+ detected_agent = agent
1200
+
1201
+ session_id = session_file.stem
1202
+
1203
+ # Execute clone
1204
+ if detected_agent == "claude":
1205
+ from claude_code_tools.find_claude_session import clone_session
1206
+ clone_session(session_id, cwd, shell_mode=False)
1207
+ else:
1208
+ from claude_code_tools.find_codex_session import clone_session
1209
+ clone_session(str(session_file), session_id, cwd, shell_mode=False)
1210
+
1211
+
1212
+ @main.command("rollover")
1213
+ @click.argument("session", required=False)
1214
+ @click.option("--quick", is_flag=True,
1215
+ help="Quick rollover without context extraction (just preserve lineage)")
1216
+ @click.option("--prompt", "-p", help="Custom prompt for context extraction")
1217
+ @click.option("--agent", type=click.Choice(["claude", "codex"], case_sensitive=False),
1218
+ help="Force agent type (auto-detected if not specified)")
1219
+ def rollover(session, quick, prompt, agent):
1220
+ """Rollover: hand off work to a fresh session with preserved lineage.
1221
+
1222
+ Creates a new session with a summary of the current work and links back
1223
+ to the parent session. The new session starts with full context available
1224
+ while the parent session is preserved intact.
1225
+
1226
+ \b
1227
+ Options:
1228
+ --quick Skip context extraction, just preserve lineage pointers
1229
+ --prompt Custom instructions for what context to extract
1230
+
1231
+ \b
1232
+ Examples:
1233
+ aichat rollover abc123 # Rollover with context extraction
1234
+ aichat rollover abc123 --quick # Quick rollover (lineage only)
1235
+ aichat rollover abc123 -p "Focus on the auth changes"
1236
+ aichat rollover # Rollover latest session
1237
+ """
1238
+ import sys
1239
+ from pathlib import Path
1240
+
1241
+ from claude_code_tools.session_utils import (
1242
+ find_session_file,
1243
+ detect_agent_from_path,
1244
+ continue_with_options,
1245
+ )
1246
+
1247
+ # If CLI options provided, use direct handler (backward compatible)
1248
+ if quick or prompt or agent:
1249
+ if not session:
1250
+ print("Error: --quick, --prompt, or --agent require a session ID",
1251
+ file=sys.stderr)
1252
+ print("Use 'aichat rollover' without options for interactive mode",
1253
+ file=sys.stderr)
1254
+ sys.exit(1)
1255
+
1256
+ # Find session file
1257
+ input_path = Path(session).expanduser()
1258
+ if input_path.exists() and input_path.is_file():
1259
+ session_file = input_path
1260
+ detected_agent = agent or detect_agent_from_path(session_file)
1261
+ else:
1262
+ result = find_session_file(session)
1263
+ if not result:
1264
+ print(f"Error: Session not found: {session}", file=sys.stderr)
1265
+ sys.exit(1)
1266
+ detected_agent, session_file, _, _ = result
1267
+ if agent:
1268
+ detected_agent = agent
1269
+
1270
+ # Execute rollover directly
1271
+ rollover_type = "quick" if quick else "context"
1272
+ continue_with_options(
1273
+ str(session_file),
1274
+ detected_agent,
1275
+ preset_prompt=prompt,
1276
+ rollover_type=rollover_type,
1277
+ )
1278
+ return
1279
+
1280
+ # Show interactive Node UI for rollover options
1281
+ # (whether session provided or not - find latest if not)
1282
+ # Start at lineage screen, with direct_action for proper escape behavior
1283
+ _find_and_run_session_ui(
1284
+ session_id=session,
1285
+ agent_constraint='both',
1286
+ start_screen='lineage',
1287
+ select_target='lineage',
1288
+ results_title=' Which session to rollover? ',
1289
+ direct_action='continue',
1290
+ )
1291
+
1292
+
1293
+ @main.command("lineage")
1294
+ @click.argument("session", required=False)
1295
+ @click.option("--agent", type=click.Choice(["claude", "codex"], case_sensitive=False),
1296
+ help="Force agent type (auto-detected if not specified)")
1297
+ @click.option("--json", "json_output", is_flag=True, help="Output as JSON")
1298
+ def lineage(session, agent, json_output):
1299
+ """Show the parent lineage chain of a session.
1300
+
1301
+ Traces back through continue_metadata and trim_metadata to find
1302
+ all ancestor sessions, from the current session back to the original.
1303
+
1304
+ \b
1305
+ Examples:
1306
+ aichat lineage abc123-def456 # Show lineage for specific session
1307
+ aichat lineage # Show lineage for latest session
1308
+ aichat lineage abc123 --json # Output as JSON
1309
+ """
1310
+ import json as json_lib
1311
+ import sys
1312
+ from pathlib import Path
1313
+ from datetime import datetime
1314
+
1315
+ from claude_code_tools.session_utils import find_session_file, detect_agent_from_path
1316
+ from claude_code_tools.session_lineage import get_full_lineage_chain
1317
+
1318
+ if not session:
1319
+ _find_and_run_session_ui(
1320
+ session_id=None,
1321
+ agent_constraint='both',
1322
+ start_screen='lineage',
1323
+ )
1324
+ return
1325
+
1326
+ # Find session file
1327
+ input_path = Path(session).expanduser()
1328
+ if input_path.exists() and input_path.is_file():
1329
+ session_file = input_path
1330
+ detected_agent = agent or detect_agent_from_path(session_file)
1331
+ else:
1332
+ result = find_session_file(session)
1333
+ if not result:
1334
+ print(f"Error: Session not found: {session}", file=sys.stderr)
1335
+ sys.exit(1)
1336
+ detected_agent, session_file, _, _ = result
1337
+ if agent:
1338
+ detected_agent = agent
1339
+
1340
+ # Get lineage (returns newest-first, ending with original)
1341
+ lineage_chain = get_full_lineage_chain(session_file)
1342
+
1343
+ # Check if this is an original session (only one item with type "original")
1344
+ if len(lineage_chain) == 1 and lineage_chain[0][1] == "original":
1345
+ print("No lineage found (this is an original session).")
1346
+ return
1347
+
1348
+ lineage_data = []
1349
+ for path, derivation_type in lineage_chain:
1350
+ mod_time = datetime.fromtimestamp(path.stat().st_mtime)
1351
+ lineage_data.append({
1352
+ "session_id": path.stem,
1353
+ "file_path": str(path),
1354
+ "derivation_type": derivation_type,
1355
+ "modified": mod_time.isoformat(),
1356
+ })
1357
+
1358
+ if json_output:
1359
+ print(json_lib.dumps(lineage_data, indent=2))
1360
+ else:
1361
+ print(f"\nLineage for: {session_file.stem}")
1362
+ print(f"{'='*60}")
1363
+ print(f"Chain has {len(lineage_data)} session(s):\n")
1364
+
1365
+ for i, node in enumerate(lineage_data):
1366
+ # Current session or ancestor
1367
+ if i == 0:
1368
+ marker = "► "
1369
+ else:
1370
+ marker = " "
1371
+
1372
+ dtype = node["derivation_type"]
1373
+ fname = Path(node["file_path"]).name
1374
+ mod = node["modified"][:10]
1375
+
1376
+ if i == len(lineage_data) - 1:
1377
+ prefix = f"{marker}└─"
1378
+ else:
1379
+ prefix = f"{marker}├─"
1380
+
1381
+ print(f"{prefix} [{dtype:10}] {fname} ({mod})")
1382
+
1383
+
1384
+ @main.command("resume", context_settings={"ignore_unknown_options": True, "allow_extra_args": True, "allow_interspersed_args": False})
1385
+ @click.option(
1386
+ '--claude-home',
1387
+ type=click.Path(exists=True, file_okay=False, dir_okay=True),
1388
+ help='Claude home directory (default: ~/.claude or CLAUDE_CONFIG_DIR)',
1389
+ )
1390
+ @click.option(
1391
+ '--codex-home',
1392
+ type=click.Path(exists=True, file_okay=False, dir_okay=True),
1393
+ help='Codex home directory (default: ~/.codex or CODEX_HOME)',
1394
+ )
1395
+ @click.pass_context
1396
+ def resume_session(ctx, claude_home, codex_home):
1397
+ """Resume a session with various options (resume, clone, trim, continue).
1398
+
1399
+ If no session ID provided, finds latest session for current project/branch.
1400
+ Shows resume menu with options: resume as-is, clone, trim+resume,
1401
+ smart-trim, or continue with context.
1402
+
1403
+ \b
1404
+ Environment variables:
1405
+ CLAUDE_CONFIG_DIR - Default Claude home (overridden by --claude-home)
1406
+ CODEX_HOME - Default Codex home (overridden by --codex-home)
1407
+ """
1408
+ # Merge with parent context options (CLI arg takes precedence)
1409
+ claude_home = claude_home or (ctx.obj or {}).get('claude_home')
1410
+ codex_home = codex_home or (ctx.obj or {}).get('codex_home')
1411
+
1412
+ args = ctx.args
1413
+ session_id = args[0] if args and not args[0].startswith('-') else None
1414
+ _find_and_run_session_ui(
1415
+ session_id=session_id,
1416
+ agent_constraint='both',
1417
+ start_screen='resume',
1418
+ select_target='resume',
1419
+ results_title=' Which session to resume? ',
1420
+ )
1421
+
1422
+
1423
+ # =============================================================================
1424
+ # Search Infrastructure Commands
1425
+ # =============================================================================
1426
+
1427
+
1428
+ @main.command("clear-index")
1429
+ @click.option(
1430
+ "--index", "-i",
1431
+ type=click.Path(),
1432
+ default="~/.cctools/search-index",
1433
+ help="Index directory (default: ~/.cctools/search-index/)",
1434
+ )
1435
+ @click.option("--dry-run", "-n", is_flag=True, help="Show what would be deleted")
1436
+ def clear_index(index, dry_run):
1437
+ """Clear the Tantivy search index.
1438
+
1439
+ Deletes the entire index directory to allow a fresh rebuild.
1440
+ """
1441
+ import shutil
1442
+ from pathlib import Path
1443
+
1444
+ index_path = Path(index).expanduser()
1445
+
1446
+ if not index_path.exists():
1447
+ print(f"Index directory does not exist: {index_path}")
1448
+ return
1449
+
1450
+ # Count files for info
1451
+ file_count = sum(1 for _ in index_path.rglob("*") if _.is_file())
1452
+
1453
+ if dry_run:
1454
+ print(f"Dry run: would delete index at {index_path}")
1455
+ print(f" {file_count} files would be removed")
1456
+ else:
1457
+ shutil.rmtree(index_path)
1458
+ print(f"✅ Cleared index at {index_path}")
1459
+ print(f" {file_count} files removed")
1460
+
1461
+
1462
+ @main.command("clear-exports", hidden=True)
1463
+ @click.option("--verbose", "-v", is_flag=True, help="Show what's being deleted")
1464
+ @click.option("--dry-run", "-n", is_flag=True, help="Show what would be deleted")
1465
+ def clear_exports(verbose, dry_run):
1466
+ """Clear all exported session files from project directories.
1467
+
1468
+ Finds export files in per-project directories:
1469
+ {project}/exported-sessions/{agent}/*.txt
1470
+
1471
+ Use this before re-exporting to ensure a clean slate.
1472
+ """
1473
+ from claude_code_tools.export_all import (
1474
+ collect_sessions_to_export,
1475
+ extract_export_dir_from_session,
1476
+ )
1477
+
1478
+ print("Scanning for export files to delete...")
1479
+ sessions = collect_sessions_to_export()
1480
+ print(f"Found {len(sessions)} sessions to check")
1481
+
1482
+ deleted_count = 0
1483
+ dirs_cleaned = set()
1484
+
1485
+ with click.progressbar(
1486
+ sessions,
1487
+ label="Scanning",
1488
+ show_pos=True,
1489
+ item_show_func=lambda x: x[0].name if x else "",
1490
+ ) as bar:
1491
+ for session_file, agent in bar:
1492
+ export_dir = extract_export_dir_from_session(session_file, agent=agent)
1493
+ if export_dir and export_dir.exists():
1494
+ export_file = export_dir / f"{session_file.stem}.txt"
1495
+ if export_file.exists():
1496
+ if dry_run:
1497
+ if verbose:
1498
+ print(f"\nWould delete: {export_file}")
1499
+ else:
1500
+ if verbose:
1501
+ print(f"\nDeleting: {export_file}")
1502
+ export_file.unlink()
1503
+ deleted_count += 1
1504
+ dirs_cleaned.add(export_dir)
1505
+
1506
+ if dry_run:
1507
+ print(f"\nDry run: would delete {deleted_count} files "
1508
+ f"from {len(dirs_cleaned)} directories")
1509
+ else:
1510
+ print(f"\n✅ Cleared {deleted_count} export files "
1511
+ f"from {len(dirs_cleaned)} directories")
1512
+
1513
+
1514
+ @main.command("export-all", hidden=True)
1515
+ @click.option("--force", "-f", is_flag=True, help="Re-export all (ignore mtime)")
1516
+ @click.option("--verbose", "-v", is_flag=True, help="Show detailed progress and failures")
1517
+ def export_all(force, verbose):
1518
+ """Export all sessions with YAML front matter for indexing.
1519
+
1520
+ Each session is exported to its own project directory:
1521
+ {project}/exported-sessions/{agent}/{session_id}.txt
1522
+
1523
+ Skips sessions that haven't changed since last export (unless --force).
1524
+ """
1525
+ from claude_code_tools.export_all import (
1526
+ collect_sessions_to_export,
1527
+ export_single_session,
1528
+ )
1529
+
1530
+ print("Collecting sessions...")
1531
+ sessions = collect_sessions_to_export()
1532
+ print(f"Found {len(sessions)} sessions to process")
1533
+
1534
+ stats: dict = {
1535
+ "exported": 0,
1536
+ "skipped": 0,
1537
+ "failed": 0,
1538
+ "exported_files": [],
1539
+ "failures": [],
1540
+ }
1541
+
1542
+ with click.progressbar(
1543
+ sessions,
1544
+ label="Exporting",
1545
+ show_pos=True,
1546
+ item_show_func=lambda x: x[0].name if x else "",
1547
+ ) as bar:
1548
+ for session_file, agent in bar:
1549
+ result = export_single_session(session_file, agent, force)
1550
+
1551
+ if result["status"] == "exported":
1552
+ stats["exported"] += 1
1553
+ stats["exported_files"].append(result["export_file"])
1554
+ elif result["status"] == "skipped":
1555
+ stats["skipped"] += 1
1556
+ if result["export_file"]:
1557
+ stats["exported_files"].append(result["export_file"])
1558
+ else: # failed
1559
+ stats["failed"] += 1
1560
+ stats["failures"].append({
1561
+ "session": str(session_file),
1562
+ "agent": agent,
1563
+ "error": result["error"],
1564
+ })
1565
+
1566
+ print(f"\n✅ Export complete:")
1567
+ print(f" Exported: {stats['exported']}")
1568
+ print(f" Skipped: {stats['skipped']} (up-to-date)")
1569
+ print(f" Failed: {stats['failed']}")
1570
+ print(f" Total export files: {len(stats['exported_files'])}")
1571
+
1572
+ if stats["failures"] and verbose:
1573
+ print(f"\n⚠️ Failures ({len(stats['failures'])}):")
1574
+ for failure in stats["failures"]:
1575
+ print(f" {failure['session']}")
1576
+ print(f" Error: {failure['error']}")
1577
+
1578
+
1579
+ @main.command("build-index")
1580
+ @click.option(
1581
+ "--claude-home",
1582
+ type=click.Path(),
1583
+ default=None,
1584
+ help="Claude home directory (default: ~/.claude or CLAUDE_CONFIG_DIR)",
1585
+ )
1586
+ @click.option(
1587
+ "--codex-home",
1588
+ type=click.Path(),
1589
+ default=None,
1590
+ help="Codex home directory (default: ~/.codex or CODEX_HOME)",
1591
+ )
1592
+ def build_index(claude_home, codex_home):
1593
+ """Build/update the Tantivy search index from JSONL session files.
1594
+
1595
+ Indexes sessions directly from JSONL files (no export step needed).
1596
+ Incremental by default - only indexes new/modified sessions.
1597
+
1598
+ Use 'aichat clear-index' first if you want a full rebuild.
1599
+ """
1600
+ from claude_code_tools.search_index import auto_index
1601
+ from claude_code_tools.session_utils import get_claude_home, get_codex_home
1602
+
1603
+ claude_home_path = get_claude_home(cli_arg=claude_home)
1604
+ codex_home_path = get_codex_home(cli_arg=codex_home)
1605
+
1606
+ print("Building search index...")
1607
+ stats = auto_index(
1608
+ claude_home=claude_home_path,
1609
+ codex_home=codex_home_path,
1610
+ verbose=True,
1611
+ silent=False, # Show tqdm progress bar
1612
+ )
1613
+
1614
+ print(f"\n✅ Index build complete:")
1615
+ print(f" Indexed: {stats['indexed']}")
1616
+ print(f" Skipped: {stats['skipped']} (unchanged)")
1617
+ failed = stats['failed']
1618
+ if failed > 0:
1619
+ empty = stats.get('empty', 0)
1620
+ parse_err = stats.get('parse_error', 0)
1621
+ index_err = stats.get('index_error', 0)
1622
+ print(f" Failed: {failed} (empty: {empty}, parse: {parse_err}, "
1623
+ f"index: {index_err})")
1624
+ else:
1625
+ print(f" Failed: 0")
1626
+ print(f" Total: {stats['total_files']} "
1627
+ f"(Claude: {stats.get('claude_files', '?')}, "
1628
+ f"Codex: {stats.get('codex_files', '?')})")
1629
+
1630
+
1631
+ def _scan_session_files(
1632
+ claude_home: "Path",
1633
+ codex_home: "Path",
1634
+ ) -> dict:
1635
+ """
1636
+ Scan filesystem for all JSONL session files and read their metadata.
1637
+
1638
+ Returns dict with:
1639
+ - files: dict mapping file_path (str) -> {path, is_subagent, agent, ...}
1640
+ - counts: {claude_resumable, claude_subagent, codex_resumable, codex_subagent}
1641
+ - errors: list of files that couldn't be parsed
1642
+ """
1643
+ import json
1644
+ from claude_code_tools.session_utils import is_valid_session
1645
+
1646
+ files = {}
1647
+ counts = {
1648
+ "claude_resumable": 0,
1649
+ "claude_subagent": 0,
1650
+ "codex_resumable": 0,
1651
+ "codex_subagent": 0,
1652
+ "claude_invalid": 0,
1653
+ "codex_invalid": 0,
1654
+ }
1655
+ errors = []
1656
+
1657
+ # Scan Claude sessions
1658
+ claude_projects = claude_home / "projects"
1659
+ if claude_projects.exists():
1660
+ for jsonl_path in claude_projects.glob("**/*.jsonl"):
1661
+ is_subagent = jsonl_path.name.startswith("agent-")
1662
+ try:
1663
+ with open(jsonl_path) as f:
1664
+ first_line = f.readline().strip()
1665
+ if first_line:
1666
+ data = json.loads(first_line)
1667
+
1668
+ # Skip sessions run from inside claude_home or codex_home
1669
+ cwd = data.get("cwd", "")
1670
+ claude_home_str = str(claude_home)
1671
+ codex_home_str = str(codex_home)
1672
+ if cwd and (
1673
+ cwd.startswith(claude_home_str)
1674
+ or cwd.startswith(codex_home_str)
1675
+ ):
1676
+ continue
1677
+ # Use file path as key (unique per file)
1678
+ file_key = str(jsonl_path)
1679
+
1680
+ # Check if actually resumable (has user/assistant messages)
1681
+ if is_subagent:
1682
+ is_resumable = True # Subagents are always valid
1683
+ else:
1684
+ is_resumable = is_valid_session(jsonl_path)
1685
+
1686
+ if not is_resumable:
1687
+ counts["claude_invalid"] += 1
1688
+ continue # Skip non-resumable files
1689
+
1690
+ files[file_key] = {
1691
+ "path": jsonl_path,
1692
+ "is_subagent": is_subagent,
1693
+ "agent": "claude",
1694
+ "session_id": data.get("sessionId", ""),
1695
+ }
1696
+ if is_subagent:
1697
+ counts["claude_subagent"] += 1
1698
+ else:
1699
+ counts["claude_resumable"] += 1
1700
+ except Exception as e:
1701
+ errors.append({"path": jsonl_path, "error": str(e)})
1702
+
1703
+ # Scan Codex sessions
1704
+ if codex_home.exists():
1705
+ for jsonl_path in codex_home.glob("**/*.jsonl"):
1706
+ is_subagent = jsonl_path.name.startswith("agent-")
1707
+ try:
1708
+ with open(jsonl_path) as f:
1709
+ first_line = f.readline().strip()
1710
+ if first_line:
1711
+ data = json.loads(first_line)
1712
+
1713
+ # Skip sessions run from inside claude_home or codex_home
1714
+ cwd = data.get("cwd", "")
1715
+ claude_home_str = str(claude_home)
1716
+ codex_home_str = str(codex_home)
1717
+ if cwd and (
1718
+ cwd.startswith(claude_home_str)
1719
+ or cwd.startswith(codex_home_str)
1720
+ ):
1721
+ continue
1722
+ # Use file path as key (unique per file)
1723
+ file_key = str(jsonl_path)
1724
+
1725
+ # Check if actually resumable (has user/assistant messages)
1726
+ if is_subagent:
1727
+ is_resumable = True # Subagents are always valid
1728
+ else:
1729
+ is_resumable = is_valid_session(jsonl_path)
1730
+
1731
+ if not is_resumable:
1732
+ counts["codex_invalid"] += 1
1733
+ continue # Skip non-resumable files
1734
+
1735
+ files[file_key] = {
1736
+ "path": jsonl_path,
1737
+ "is_subagent": is_subagent,
1738
+ "agent": "codex",
1739
+ "session_id": data.get("sessionId", "") or data.get("id", ""),
1740
+ }
1741
+ if is_subagent:
1742
+ counts["codex_subagent"] += 1
1743
+ else:
1744
+ counts["codex_resumable"] += 1
1745
+ except Exception as e:
1746
+ errors.append({"path": jsonl_path, "error": str(e)})
1747
+
1748
+ return {"files": files, "counts": counts, "errors": errors}
1749
+
1750
+
1751
+ @main.command("index-stats")
1752
+ @click.option(
1753
+ "--index", "-i",
1754
+ type=click.Path(),
1755
+ default="~/.cctools/search-index",
1756
+ help="Index directory",
1757
+ )
1758
+ @click.option("--cwd", "-c", help="Filter to specific cwd path")
1759
+ @click.option(
1760
+ "--claude-home",
1761
+ type=click.Path(),
1762
+ default=None,
1763
+ help="Claude home directory (default: ~/.claude or CLAUDE_CONFIG_DIR)",
1764
+ )
1765
+ @click.option(
1766
+ "--codex-home",
1767
+ type=click.Path(),
1768
+ default=None,
1769
+ help="Codex home directory (default: ~/.codex or CODEX_HOME)",
1770
+ )
1771
+ def index_stats(index, cwd, claude_home, codex_home):
1772
+ """Show statistics about the Tantivy search index with reconciliation.
1773
+
1774
+ Compares index contents against actual session files on disk to identify
1775
+ missing or orphaned sessions.
1776
+ """
1777
+ from collections import Counter
1778
+ from pathlib import Path
1779
+
1780
+ try:
1781
+ from claude_code_tools.search_index import SessionIndex
1782
+ except ImportError:
1783
+ print("Error: tantivy not installed")
1784
+ return
1785
+
1786
+ from claude_code_tools.session_utils import get_claude_home, get_codex_home
1787
+
1788
+ index_path = Path(index).expanduser()
1789
+ claude_home_path = get_claude_home(cli_arg=claude_home)
1790
+ codex_home_path = get_codex_home(cli_arg=codex_home)
1791
+
1792
+ if not index_path.exists():
1793
+ print(f"Index not found at {index_path}")
1794
+ return
1795
+
1796
+ # === Filesystem scan ===
1797
+ print("Scanning filesystem...")
1798
+ fs_data = _scan_session_files(claude_home_path, codex_home_path)
1799
+ fs_files = fs_data["files"]
1800
+ fs_counts = fs_data["counts"]
1801
+ fs_errors = fs_data["errors"]
1802
+
1803
+ print("\n=== Filesystem ===")
1804
+ print(f"Claude resumable: {fs_counts['claude_resumable']}")
1805
+ print(f"Claude subagent: {fs_counts['claude_subagent']}")
1806
+ print(f"Codex resumable: {fs_counts['codex_resumable']}")
1807
+ print(f"Codex subagent: {fs_counts['codex_subagent']}")
1808
+ total_valid = (
1809
+ fs_counts['claude_resumable'] + fs_counts['claude_subagent'] +
1810
+ fs_counts['codex_resumable'] + fs_counts['codex_subagent']
1811
+ )
1812
+ total_invalid = fs_counts['claude_invalid'] + fs_counts['codex_invalid']
1813
+ print(f"Total valid: {total_valid}")
1814
+ if total_invalid > 0:
1815
+ print(f"Skipped invalid: {total_invalid} (no resumable messages)")
1816
+
1817
+ if fs_errors:
1818
+ print(f"Parse errors: {len(fs_errors)}")
1819
+
1820
+ # === Index stats ===
1821
+ idx = SessionIndex(index_path)
1822
+ results = idx.get_recent(limit=100000)
1823
+
1824
+ print("\n=== Index ===")
1825
+ print(f"Total documents: {len(results)}")
1826
+
1827
+ # Build index lookup by export_path (unique key for each indexed file)
1828
+ # Filter to only entries matching the specified claude_home/codex_home
1829
+ indexed_by_path = {}
1830
+ claude_home_str = str(claude_home_path)
1831
+ codex_home_str = str(codex_home_path)
1832
+
1833
+ for r in results:
1834
+ fpath = r.get("export_path", "")
1835
+ stored_home = r.get("claude_home", "")
1836
+ # Only include if home matches (claude or codex)
1837
+ if fpath and (stored_home == claude_home_str or stored_home == codex_home_str):
1838
+ indexed_by_path[fpath] = {
1839
+ "agent": r.get("agent", ""),
1840
+ "session_id": r.get("session_id", ""),
1841
+ "is_subagent": "agent-" in fpath,
1842
+ }
1843
+
1844
+ # Also count unique session IDs for display (filtered)
1845
+ unique_session_ids = set(
1846
+ r.get("session_id", "") for r in results
1847
+ if r.get("session_id") and r.get("claude_home") in (claude_home_str, codex_home_str)
1848
+ )
1849
+ print(f"Unique session IDs: {len(unique_session_ids)} (for specified homes)")
1850
+ print(f"Total file paths: {len(indexed_by_path)}")
1851
+
1852
+ # === Reconciliation ===
1853
+ print("\n=== Reconciliation (by file path) ===")
1854
+
1855
+ fs_paths = set(fs_files.keys())
1856
+ idx_paths = set(indexed_by_path.keys())
1857
+
1858
+ missing_from_index = fs_paths - idx_paths
1859
+ orphaned_in_index = idx_paths - fs_paths
1860
+ in_sync = fs_paths & idx_paths
1861
+
1862
+ print(f"Files on disk: {len(fs_paths)}")
1863
+ print(f"Files indexed: {len(idx_paths)}")
1864
+ print(f"In sync: {len(in_sync)}")
1865
+
1866
+ if not missing_from_index and not orphaned_in_index:
1867
+ print("✅ Index is fully in sync with filesystem")
1868
+ else:
1869
+ if missing_from_index:
1870
+ print(f"❌ Missing from index: {len(missing_from_index)}")
1871
+ # Count by type
1872
+ missing_subagent = sum(
1873
+ 1 for p in missing_from_index if fs_files[p]["is_subagent"]
1874
+ )
1875
+ missing_resumable = len(missing_from_index) - missing_subagent
1876
+ print(f" ({missing_resumable} resumable, {missing_subagent} subagent)")
1877
+ # Show a few examples
1878
+ for fpath in list(missing_from_index)[:3]:
1879
+ info = fs_files[fpath]
1880
+ stype = "subagent" if info["is_subagent"] else "resumable"
1881
+ fname = info["path"].name
1882
+ print(f" - {fname} ({info['agent']}, {stype})")
1883
+ if len(missing_from_index) > 3:
1884
+ print(f" ... and {len(missing_from_index) - 3} more")
1885
+
1886
+ if orphaned_in_index:
1887
+ print(f"⚠️ Orphaned in index (file gone): {len(orphaned_in_index)}")
1888
+ # Count by type
1889
+ orphan_subagent = sum(
1890
+ 1 for p in orphaned_in_index if indexed_by_path[p]["is_subagent"]
1891
+ )
1892
+ orphan_resumable = len(orphaned_in_index) - orphan_subagent
1893
+ print(f" ({orphan_resumable} resumable, {orphan_subagent} subagent)")
1894
+ for fpath in list(orphaned_in_index)[:3]:
1895
+ info = indexed_by_path[fpath]
1896
+ fname = fpath.split("/")[-1]
1897
+ print(f" - {fname} ({info['agent']})")
1898
+ if len(orphaned_in_index) > 3:
1899
+ print(f" ... and {len(orphaned_in_index) - 3} more")
1900
+
1901
+ # Count by cwd if filter specified
1902
+ if cwd:
1903
+ matching = [r for r in results if r.get("cwd") == cwd]
1904
+ matching_unique = set(r.get("session_id") for r in matching)
1905
+ print(f"\nWith cwd '{cwd}':")
1906
+ print(f" Documents: {len(matching)}")
1907
+ print(f" Unique sessions: {len(matching_unique)}")
1908
+
1909
+ # Top cwds
1910
+ cwd_counts = Counter(r.get("cwd", "unknown") for r in results)
1911
+ print("\nTop 5 cwds:")
1912
+ for path, count in cwd_counts.most_common(5):
1913
+ short = path[-50:] if len(path) > 50 else path
1914
+ print(f" {count:4d} | ...{short}" if len(path) > 50 else f" {count:4d} | {short}")
1915
+
1916
+ # Claude home stats
1917
+ claude_home_counts = Counter(r.get("claude_home", "") for r in results)
1918
+ print("\nClaude homes:")
1919
+ for home, count in claude_home_counts.most_common(10):
1920
+ home_display = home if home else "(empty)"
1921
+ print(f" {count:4d} | {home_display}")
1922
+
1923
+
1924
+ @main.command("search")
1925
+ @click.option(
1926
+ '--claude-home',
1927
+ 'claude_home_arg',
1928
+ type=click.Path(exists=True, file_okay=False, dir_okay=True),
1929
+ help='Path to Claude home directory (overrides CLAUDE_CONFIG_DIR env var)',
1930
+ )
1931
+ @click.option(
1932
+ '--codex-home',
1933
+ 'codex_home_arg',
1934
+ type=click.Path(exists=True, file_okay=False, dir_okay=True),
1935
+ help='Path to Codex home directory (overrides CODEX_HOME env var)',
1936
+ )
1937
+ @click.option('-g', '--global', 'global_search', is_flag=True,
1938
+ help='Search across all projects (not just current)')
1939
+ @click.option('--dir', 'filter_dir',
1940
+ help='Filter to directory[:branch] (overrides -g)')
1941
+ @click.option('--branch', 'filter_branch',
1942
+ help='Filter to specific git branch (only effective when not global)')
1943
+ @click.option('-n', '--num-results', type=int, default=None,
1944
+ help='Limit number of results displayed')
1945
+ @click.option('--no-original', is_flag=True, help='Exclude original sessions')
1946
+ @click.option('--sub-agent', is_flag=True, help='Include sub-agent sessions (additive)')
1947
+ @click.option('--no-trimmed', is_flag=True, help='Exclude trimmed sessions')
1948
+ @click.option('--no-rollover', is_flag=True, help='Exclude rollover sessions')
1949
+ @click.option('--min-lines', type=int, default=None,
1950
+ help='Only show sessions with at least N lines')
1951
+ @click.option('--after', metavar='DATE',
1952
+ help='Sessions modified after date (YYYYMMDD, MM/DD/YY)')
1953
+ @click.option('--before', metavar='DATE',
1954
+ help='Sessions modified before date (YYYYMMDD, MM/DD/YY)')
1955
+ @click.option('--agent', type=click.Choice(['claude', 'codex', 'all']),
1956
+ default='all', help='Filter by agent type')
1957
+ @click.option('--json', 'json_output', is_flag=True,
1958
+ help='Output as JSONL for AI agents. Fields per line: session_id, '
1959
+ 'agent, project, branch, cwd, lines, created, modified, '
1960
+ 'first_msg, last_msg, file_path, derivation_type, '
1961
+ 'is_sidechain, snippet')
1962
+ @click.option('--by-time', 'by_time', is_flag=True,
1963
+ help='Sort results by last-modified time (default: sort by relevance)')
1964
+ @click.argument('query', required=False)
1965
+ def search(
1966
+ claude_home_arg, codex_home_arg, global_search, filter_dir, filter_branch,
1967
+ num_results, no_original, sub_agent, no_trimmed, no_rollover, min_lines,
1968
+ after, before, agent, json_output, by_time, query
1969
+ ):
1970
+ """Launch interactive TUI for full-text session search.
1971
+
1972
+ Provides fast Tantivy-based search across all Claude and Codex sessions
1973
+ with auto-indexing, keyword highlighting, and session actions.
1974
+
1975
+ \b
1976
+ Examples:
1977
+ aichat search # Interactive TUI
1978
+ aichat search "langroid agent" # Pre-fill search query
1979
+ aichat search -g --after 11/20/25 # Global, recent sessions
1980
+ aichat search --dir ~/Git/myproj # Filter to specific directory
1981
+ aichat search --json "MCP" # JSON output (sorted by relevance)
1982
+ aichat search --json --by-time # JSON output sorted by time
1983
+
1984
+ \b
1985
+ Notes:
1986
+ --dir overrides -g (global) when both are specified.
1987
+ --by-time sorts by last-modified time; default is relevance.
1988
+
1989
+ \b
1990
+ Environment variables:
1991
+ CLAUDE_CONFIG_DIR - Default Claude home (overridden by --claude-home)
1992
+ CODEX_HOME - Default Codex home (overridden by --codex-home)
1993
+ """
1994
+ import json as json_lib
1995
+ import os
1996
+ import subprocess
1997
+ import sys
1998
+ import tempfile
1999
+ from pathlib import Path
2000
+
2001
+ # Find Rust binary - check PATH first (cargo install), then local dev build
2002
+ import shutil
2003
+ rust_binary_name = "aichat-search"
2004
+ rust_binary = shutil.which(rust_binary_name)
2005
+ if rust_binary:
2006
+ rust_binary = Path(rust_binary)
2007
+ else:
2008
+ # Fall back to local development build
2009
+ rust_binary = (
2010
+ Path(__file__).parent.parent
2011
+ / "rust-search-ui"
2012
+ / "target"
2013
+ / "release"
2014
+ / rust_binary_name
2015
+ )
2016
+ if not rust_binary.exists():
2017
+ print(f"Error: {rust_binary_name} not found.", file=sys.stderr)
2018
+ print("Install with: cargo install aichat-search", file=sys.stderr)
2019
+ print("Or build locally: cd rust-search-ui && cargo build --release",
2020
+ file=sys.stderr)
2021
+ return
2022
+
2023
+ # Resolve home directories (CLI arg > env var > default)
2024
+ from claude_code_tools.session_utils import get_claude_home, get_codex_home
2025
+ claude_home = get_claude_home(cli_arg=claude_home_arg)
2026
+ codex_home = get_codex_home(cli_arg=codex_home_arg)
2027
+
2028
+ # Build CLI args for Rust binary
2029
+ rust_args = [str(rust_binary)]
2030
+
2031
+ # Home directories
2032
+ rust_args.extend(["--claude-home", str(claude_home)])
2033
+ rust_args.extend(["--codex-home", str(codex_home)])
2034
+
2035
+ # Filter options
2036
+ if filter_dir:
2037
+ # --dir overrides -g
2038
+ # Support dir:branch format - extract branch if present before resolving path
2039
+ if ':' in filter_dir and not filter_dir.startswith('/') or (
2040
+ ':' in filter_dir and filter_dir.count(':') == 1 and
2041
+ '/' not in filter_dir.split(':')[-1]
2042
+ ):
2043
+ # Has branch suffix (dir:branch format)
2044
+ parts = filter_dir.rsplit(':', 1)
2045
+ dir_part = parts[0]
2046
+ branch_part = parts[1] if len(parts) > 1 else None
2047
+ resolved_dir = str(Path(dir_part).resolve())
2048
+ if branch_part:
2049
+ rust_args.extend(["--dir", f"{resolved_dir}:{branch_part}"])
2050
+ else:
2051
+ rust_args.extend(["--dir", resolved_dir])
2052
+ else:
2053
+ rust_args.extend(["--dir", str(Path(filter_dir).resolve())])
2054
+ elif global_search:
2055
+ rust_args.append("--global")
2056
+ if filter_branch:
2057
+ rust_args.extend(["--branch", filter_branch])
2058
+ if num_results:
2059
+ rust_args.extend(["--num-results", str(num_results)])
2060
+ if no_original:
2061
+ rust_args.append("--no-original")
2062
+ if sub_agent:
2063
+ rust_args.append("--sub-agent")
2064
+ if no_trimmed:
2065
+ rust_args.append("--no-trimmed")
2066
+ if no_rollover:
2067
+ rust_args.append("--no-rollover")
2068
+ if min_lines:
2069
+ rust_args.extend(["--min-lines", str(min_lines)])
2070
+ if after:
2071
+ rust_args.extend(["--after", after])
2072
+ if before:
2073
+ rust_args.extend(["--before", before])
2074
+ if agent and agent != "all":
2075
+ rust_args.extend(["--agent", agent])
2076
+ if query:
2077
+ rust_args.extend(["--query", query])
2078
+ if by_time:
2079
+ rust_args.append("--by-time")
2080
+
2081
+ # JSON output mode - run Rust with --json, output to stdout, exit
2082
+ if json_output:
2083
+ rust_args.append("--json")
2084
+ try:
2085
+ result = subprocess.run(rust_args, capture_output=True, text=True)
2086
+ # Output JSON to stdout (errors to stderr)
2087
+ # Use end='' to avoid double newline (Rust already adds one)
2088
+ if result.stdout:
2089
+ print(result.stdout, end='')
2090
+ if result.returncode != 0 and result.stderr:
2091
+ print(result.stderr, file=sys.stderr)
2092
+ sys.exit(result.returncode)
2093
+ except Exception as e:
2094
+ print(f"Error running search: {e}", file=sys.stderr)
2095
+ sys.exit(1)
2096
+
2097
+ # Import for interactive TUI mode
2098
+ from claude_code_tools.node_menu_ui import run_node_menu_ui, run_dir_confirm_ui
2099
+ from claude_code_tools.session_menu_cli import execute_action
2100
+
2101
+ # RPC path for action execution
2102
+ rpc_path = str(Path(__file__).parent / "action_rpc.py")
2103
+
2104
+ def action_handler(sess, action, kwargs):
2105
+ """Handle action from Node menu."""
2106
+ agent_type = sess.get("agent", "claude")
2107
+ file_path = sess.get("file_path")
2108
+ cwd = sess.get("cwd") or "."
2109
+
2110
+ if not file_path:
2111
+ print(f"Error: No file_path for session {sess.get('session_id')}")
2112
+ return
2113
+
2114
+ return execute_action(
2115
+ action=action,
2116
+ agent=agent_type,
2117
+ session_file=Path(file_path),
2118
+ project_path=cwd,
2119
+ action_kwargs=kwargs,
2120
+ session_id=sess.get("session_id"),
2121
+ )
2122
+
2123
+ def check_directory_and_confirm(sess):
2124
+ """Check if session is from different directory and get user confirmation.
2125
+
2126
+ Returns:
2127
+ (proceed, original_dir) tuple:
2128
+ - proceed: True if user wants to proceed, False if cancelled
2129
+ - original_dir: The directory before any change (to restore on cancel),
2130
+ or None if no directory change was made
2131
+ """
2132
+ session_dir = sess.get("cwd") or "."
2133
+ current_dir = os.getcwd()
2134
+
2135
+ # If same directory, proceed (no restore needed)
2136
+ if os.path.realpath(session_dir) == os.path.realpath(current_dir):
2137
+ return (True, None)
2138
+
2139
+ # Show confirmation dialog
2140
+ choice = run_dir_confirm_ui(current_dir, session_dir)
2141
+
2142
+ if choice == "yes":
2143
+ # Change directory and proceed
2144
+ original_dir = current_dir
2145
+ try:
2146
+ os.chdir(session_dir)
2147
+ except Exception as e:
2148
+ print(f"Error changing directory: {e}")
2149
+ original_dir = None # No restore needed if change failed
2150
+ return (True, original_dir)
2151
+ elif choice == "no":
2152
+ # Proceed without changing directory (no restore needed)
2153
+ return (True, None)
2154
+ else:
2155
+ # 'cancel' or None - user wants to go back
2156
+ return (False, None)
2157
+
2158
+ # Main loop: Rust TUI → Node menu → back to Rust TUI
2159
+ while True:
2160
+ # Create temp file for IPC
2161
+ fd, out_path = tempfile.mkstemp(suffix="-rust-ui.json")
2162
+ os.close(fd)
2163
+
2164
+ # Run Rust TUI (interactive - needs TTY)
2165
+ tui_args = rust_args + [out_path]
2166
+ try:
2167
+ result = subprocess.run(tui_args)
2168
+ except Exception as e:
2169
+ print(f"Error running Rust TUI: {e}")
2170
+ try:
2171
+ os.unlink(out_path)
2172
+ except Exception:
2173
+ pass
2174
+ return
2175
+
2176
+ if result.returncode != 0:
2177
+ try:
2178
+ os.unlink(out_path)
2179
+ except Exception:
2180
+ pass
2181
+ return
2182
+
2183
+ # Read JSON from temp file
2184
+ try:
2185
+ content = Path(out_path).read_text().strip()
2186
+ except Exception:
2187
+ content = ""
2188
+ finally:
2189
+ try:
2190
+ os.unlink(out_path)
2191
+ except Exception:
2192
+ pass
2193
+
2194
+ if not content:
2195
+ # User quit without selecting - exit the loop
2196
+ return
2197
+
2198
+ try:
2199
+ result = json_lib.loads(content)
2200
+ except json_lib.JSONDecodeError as e:
2201
+ print(f"Error parsing Rust output: {e}")
2202
+ print(f"Output was: {content[:200]}")
2203
+ return
2204
+
2205
+ # New format: {"session": {...}, "action": "...", "filter_state": {...}}
2206
+ # Legacy format: just the session object
2207
+ if "session" in result and "action" in result:
2208
+ selected = result["session"]
2209
+ action = result["action"]
2210
+ else:
2211
+ # Legacy: session only, show Node menu
2212
+ selected = result
2213
+ action = "menu"
2214
+
2215
+ # Extract and apply filter state for next loop iteration
2216
+ filter_state = result.get("filter_state", {})
2217
+ if filter_state:
2218
+ # Rebuild rust_args with preserved filter state
2219
+ rust_args = [str(rust_binary)]
2220
+ rust_args.extend(["--claude-home", str(claude_home)])
2221
+ rust_args.extend(["--codex-home", str(codex_home)])
2222
+
2223
+ # Scope: --dir overrides --global
2224
+ if filter_state.get("filter_dir"):
2225
+ rust_args.extend(["--dir", filter_state["filter_dir"]])
2226
+ elif filter_state.get("scope_global"):
2227
+ rust_args.append("--global")
2228
+
2229
+ # Branch filter
2230
+ if filter_state.get("filter_branch"):
2231
+ rust_args.extend(["--branch", filter_state["filter_branch"]])
2232
+
2233
+ # Session type filters
2234
+ # Subtractive: add --no-* when type is excluded
2235
+ # Additive: add --sub-agent when sub-agents are included
2236
+ if not filter_state.get("include_original", True):
2237
+ rust_args.append("--no-original")
2238
+ if filter_state.get("include_sub"):
2239
+ rust_args.append("--sub-agent")
2240
+ if not filter_state.get("include_trimmed", True):
2241
+ rust_args.append("--no-trimmed")
2242
+ if not filter_state.get("include_continued", True):
2243
+ rust_args.append("--no-rollover")
2244
+
2245
+ # Other filters
2246
+ if filter_state.get("filter_min_lines"):
2247
+ rust_args.extend(["--min-lines", str(filter_state["filter_min_lines"])])
2248
+ if filter_state.get("filter_after_date"):
2249
+ rust_args.extend(["--after", filter_state["filter_after_date"]])
2250
+ if filter_state.get("filter_before_date"):
2251
+ rust_args.extend(["--before", filter_state["filter_before_date"]])
2252
+ if filter_state.get("filter_agent"):
2253
+ rust_args.extend(["--agent", filter_state["filter_agent"]])
2254
+ if filter_state.get("query"):
2255
+ rust_args.extend(["--query", filter_state["query"]])
2256
+ if filter_state.get("sort_by_time"):
2257
+ rust_args.append("--by-time")
2258
+
2259
+ # Restore scroll/selection state
2260
+ if filter_state.get("selected") is not None:
2261
+ rust_args.extend(["--selected", str(filter_state["selected"])])
2262
+ if filter_state.get("list_scroll") is not None:
2263
+ rust_args.extend(["--scroll", str(filter_state["list_scroll"])])
2264
+
2265
+ # Preserve num_results if originally specified
2266
+ if num_results:
2267
+ rust_args.extend(["--num-results", str(num_results)])
2268
+
2269
+ # Convert ISO date strings from Rust to Unix timestamps
2270
+ def iso_to_timestamp(iso_str: str) -> float:
2271
+ """Convert ISO date string to Unix timestamp."""
2272
+ if not iso_str:
2273
+ return 0.0
2274
+ try:
2275
+ from datetime import datetime
2276
+ # Handle both formats: with and without 'Z' suffix
2277
+ iso_str = iso_str.replace("Z", "+00:00")
2278
+ dt = datetime.fromisoformat(iso_str)
2279
+ return dt.timestamp()
2280
+ except (ValueError, TypeError):
2281
+ return 0.0
2282
+
2283
+ # Convert to session format expected by handlers
2284
+ # Rust sends 'created'/'modified' as ISO strings, Node UI expects
2285
+ # 'create_time'/'mod_time' as Unix timestamps
2286
+ session = {
2287
+ "session_id": selected.get("session_id", ""),
2288
+ "agent": selected.get("agent", "claude"),
2289
+ "agent_display": selected.get("agent", "claude").title(),
2290
+ "project": selected.get("project", ""),
2291
+ "branch": selected.get("branch", ""),
2292
+ "lines": selected.get("lines", 0),
2293
+ "file_path": selected.get("file_path", ""),
2294
+ "cwd": selected.get("cwd", ""),
2295
+ "is_sidechain": selected.get("is_sidechain", False),
2296
+ "create_time": iso_to_timestamp(selected.get("created", "")),
2297
+ "mod_time": iso_to_timestamp(selected.get("modified", "")),
2298
+ }
2299
+
2300
+ # Extract cwd from file_path metadata if needed (for older export format)
2301
+ file_path = selected.get("file_path", "")
2302
+ if file_path and file_path.endswith(".txt"):
2303
+ try:
2304
+ with open(file_path, "r") as f:
2305
+ file_content = f.read(2000)
2306
+ if file_content.startswith("---\n"):
2307
+ end_idx = file_content.find("\n---\n", 4)
2308
+ if end_idx != -1:
2309
+ import yaml
2310
+ metadata = yaml.safe_load(file_content[4:end_idx])
2311
+ if metadata:
2312
+ session["cwd"] = metadata.get("cwd") or session["cwd"]
2313
+ session["file_path"] = metadata.get("file_path", file_path)
2314
+ except Exception:
2315
+ pass
2316
+
2317
+ print(f"Selected: {session['project']} / {session['session_id'][:12]}...")
2318
+
2319
+ # Track original directory for restoration on Ctrl+C
2320
+ original_dir_for_interrupt = None
2321
+
2322
+ try:
2323
+ # Dispatch based on action
2324
+ if action == "menu":
2325
+ # Legacy: show Node action menu, loop back on Escape
2326
+ run_node_menu_ui(
2327
+ sessions=[session],
2328
+ keywords=[],
2329
+ action_handler=action_handler,
2330
+ start_action=True,
2331
+ focus_session_id=session["session_id"],
2332
+ rpc_path=rpc_path,
2333
+ )
2334
+ # Loop back to Rust TUI
2335
+ elif action == "view":
2336
+ # View is handled in Rust, shouldn't reach here
2337
+ pass
2338
+ elif action in ("path", "copy", "export"):
2339
+ # Non-launch actions: go directly to nonlaunch screen
2340
+ run_node_menu_ui(
2341
+ sessions=[session],
2342
+ keywords=[],
2343
+ action_handler=action_handler,
2344
+ start_action=False,
2345
+ focus_session_id=session["session_id"],
2346
+ rpc_path=rpc_path,
2347
+ start_screen="nonlaunch",
2348
+ direct_action=action,
2349
+ )
2350
+ # Continue loop to return to Rust TUI
2351
+ elif action == "query":
2352
+ # Query: go directly to query screen
2353
+ run_node_menu_ui(
2354
+ sessions=[session],
2355
+ keywords=[],
2356
+ action_handler=action_handler,
2357
+ start_action=False,
2358
+ focus_session_id=session["session_id"],
2359
+ rpc_path=rpc_path,
2360
+ start_screen="query",
2361
+ direct_action="query",
2362
+ )
2363
+ # Continue loop to return to Rust TUI
2364
+ elif action == "suppress_resume":
2365
+ # Trim + resume: check directory first, then show trim form
2366
+ proceed, original_dir = check_directory_and_confirm(session)
2367
+ if not proceed:
2368
+ continue # User cancelled - pop back to Rust search
2369
+ original_dir_for_interrupt = original_dir
2370
+ run_node_menu_ui(
2371
+ sessions=[session],
2372
+ keywords=[],
2373
+ action_handler=action_handler,
2374
+ start_action=False,
2375
+ focus_session_id=session["session_id"],
2376
+ rpc_path=rpc_path,
2377
+ start_screen="trim",
2378
+ direct_action="suppress_resume",
2379
+ exit_on_back=True, # Pop back to Rust search on cancel
2380
+ )
2381
+ # If we return here, user cancelled - restore directory and pop back
2382
+ if original_dir:
2383
+ os.chdir(original_dir)
2384
+ elif action == "smart_trim_resume":
2385
+ # Smart trim: check directory first, then show options form
2386
+ proceed, original_dir = check_directory_and_confirm(session)
2387
+ if not proceed:
2388
+ continue # User cancelled - pop back to Rust search
2389
+ original_dir_for_interrupt = original_dir
2390
+ run_node_menu_ui(
2391
+ sessions=[session],
2392
+ keywords=[],
2393
+ action_handler=action_handler,
2394
+ start_action=False,
2395
+ focus_session_id=session["session_id"],
2396
+ rpc_path=rpc_path,
2397
+ start_screen="smart_trim_form",
2398
+ direct_action="smart_trim_resume",
2399
+ exit_on_back=True, # Pop back to Rust search on cancel
2400
+ )
2401
+ # If we return here, user cancelled - restore directory and pop back
2402
+ if original_dir:
2403
+ os.chdir(original_dir)
2404
+ elif action == "continue":
2405
+ # Continue with context: check directory first, then show options form
2406
+ proceed, original_dir = check_directory_and_confirm(session)
2407
+ if not proceed:
2408
+ continue # User cancelled - pop back to Rust search
2409
+ original_dir_for_interrupt = original_dir
2410
+ run_node_menu_ui(
2411
+ sessions=[session],
2412
+ keywords=[],
2413
+ action_handler=action_handler,
2414
+ start_action=False,
2415
+ focus_session_id=session["session_id"],
2416
+ rpc_path=rpc_path,
2417
+ start_screen="continue_form",
2418
+ direct_action="continue",
2419
+ exit_on_back=True, # Pop back to Rust search on cancel
2420
+ )
2421
+ # If we return here, user cancelled - restore directory and pop back
2422
+ if original_dir:
2423
+ os.chdir(original_dir)
2424
+ elif action in ("resume", "clone"):
2425
+ # Resume/clone: check directory first, then execute
2426
+ proceed, original_dir = check_directory_and_confirm(session)
2427
+ if not proceed:
2428
+ continue # User cancelled - pop back to Rust search
2429
+ original_dir_for_interrupt = original_dir
2430
+ # Note: if successful, action_handler calls os.execvp and never returns
2431
+ action_handler(session, action, {})
2432
+ # If we get here, something failed - restore directory and pop back
2433
+ if original_dir:
2434
+ os.chdir(original_dir)
2435
+ elif action == "delete":
2436
+ # Delete: already confirmed in Rust UI, just execute
2437
+ action_handler(session, action, {})
2438
+ # Remove deleted session from search index
2439
+ try:
2440
+ from claude_code_tools.search_index import SessionIndex
2441
+ idx = SessionIndex(Path("~/.cctools/search-index").expanduser())
2442
+ idx.prune_deleted()
2443
+ except Exception:
2444
+ pass # Index errors shouldn't block the UI
2445
+ # Loop back to Rust TUI (session list will refresh)
2446
+ else:
2447
+ print(f"Unknown action: {action}")
2448
+ # Continue loop
2449
+ except KeyboardInterrupt:
2450
+ # Ctrl+C pressed - restore directory if changed and pop back to search
2451
+ if original_dir_for_interrupt:
2452
+ try:
2453
+ os.chdir(original_dir_for_interrupt)
2454
+ except Exception:
2455
+ pass
2456
+ # Continue loop to return to Rust TUI
2457
+
2458
+
2459
+ if __name__ == "__main__":
2460
+ main()