From d24343fc8f46cca8db943545912939f4881a1cc9 Mon Sep 17 00:00:00 2001 From: Alex Yang Date: Mon, 19 May 2025 12:13:13 -0700 Subject: [PATCH 1/8] feat: use `ink` --- package.json | 5 +- pnpm-lock.yaml | 308 ++++++++++++++++++++++++++ src/plugins/cli-ui/components/App.tsx | 95 ++++++++ src/plugins/cli-ui/init.ts | 150 ++++--------- tsconfig.json | 21 +- 5 files changed, 466 insertions(+), 113 deletions(-) create mode 100644 src/plugins/cli-ui/components/App.tsx diff --git a/package.json b/package.json index c55f169..be9d051 100644 --- a/package.json +++ b/package.json @@ -7,7 +7,7 @@ "dist" ], "scripts": { - "dev": "tsx watch --include ./src src/main.ts configs/config.yaml", + "dev": "tsx src/main.ts configs/config.yaml", "start": "npm run build && npm run fast-start", "fast-start": "node dist/main.js configs/config.yaml", "build": "npm run clean && npm run fast-build", @@ -30,11 +30,13 @@ "description": "", "dependencies": { "@supabase/supabase-js": "^2.49.4", + "@types/react": "^19.1.4", "amadeus": "^11.0.0", "discord.js": "^14.18.0", "follow-redirects": "^1.15.9", "html-to-text": "^9.0.5", "image2uri": "^2.1.2", + "ink": "^5.2.1", "istextorbinary": "^9.5.0", "jsdom": "^26.1.0", "jsonrepair": "^3.12.0", @@ -43,6 +45,7 @@ "openai": "^4.95.1", "playwright": "^1.52.0", "python-shell": "^5.0.0", + "react": "18.3.1", "sqlite-vec": "0.1.7-alpha.2", "winston": "^3.17.0", "winston-transport": "^4.9.0", diff --git a/pnpm-lock.yaml b/pnpm-lock.yaml index abc67b6..c224069 100644 --- a/pnpm-lock.yaml +++ b/pnpm-lock.yaml @@ -11,6 +11,9 @@ importers: '@supabase/supabase-js': specifier: ^2.49.4 version: 2.49.4 + '@types/react': + specifier: ^19.1.4 + version: 19.1.4 amadeus: specifier: ^11.0.0 version: 11.0.0 @@ -26,6 +29,9 @@ importers: image2uri: specifier: ^2.1.2 version: 2.1.2 + ink: + specifier: ^5.2.1 + version: 5.2.1(@types/react@19.1.4)(react@18.3.1) istextorbinary: specifier: ^9.5.0 version: 9.5.0 @@ -50,6 +56,9 @@ importers: python-shell: specifier: ^5.0.0 version: 5.0.0 + react: + specifier: 18.3.1 + version: 18.3.1 sqlite-vec: specifier: 0.1.7-alpha.2 version: 0.1.7-alpha.2 @@ -105,6 +114,10 @@ importers: packages: + '@alcalzone/ansi-tokenize@0.1.3': + resolution: {integrity: sha512-3yWxPTq3UQ/FY9p1ErPxIyfT64elWaMvM9lIHnaqpyft63tkxodF5aUElYHrdisWve5cETkh1+KBw1yJuW0aRw==} + engines: {node: '>=14.13.1'} + '@asamuzakjp/css-color@3.1.3': resolution: {integrity: sha512-u25AyjuNrRFGb1O7KmWEu0ExN6iJMlUmDSlOPW/11JF8khOrIGG6oCoYpC+4mZlthNVhFUahk68lNrNI91f6Yg==} @@ -607,6 +620,9 @@ packages: '@types/phoenix@1.6.6': resolution: {integrity: sha512-PIzZZlEppgrpoT2QgbnDU+MMzuR6BbCjllj0bM70lWoejMeNJAxCchxnv7J3XFkI8MpygtRpzXrIlmWUBclP5A==} + '@types/react@19.1.4': + resolution: {integrity: sha512-EB1yiiYdvySuIITtD5lhW4yPyJ31RkJkkDw794LaQYrxCSaQV/47y5o1FMC4zF9ZyjUjzJMZwbovEnT5yHTW6g==} + '@types/request@2.48.12': resolution: {integrity: sha512-G3sY+NpsA9jnwm0ixhAFQSJ3Q9JkpLZpJbI3GMv0mIAT0y3mRabYeINzal5WOChIiaTEGQYlHOKgkaM9EisWHw==} @@ -681,6 +697,10 @@ packages: amadeus@11.0.0: resolution: {integrity: sha512-+/NOuWgESAByc/oi/QB4GNjF3ZzD7a3UIpK6RmGGQE2Amr7BP7evTivEbFQIvxKZj3RwCOf9AeSNygVQv1owyA==} + ansi-escapes@7.0.0: + resolution: {integrity: sha512-GdYO7a61mR0fOlAsvC9/rIHf7L96sBc6dEWzeOu+KAea5bZyQRPIpojrVoI4AXGJS/ycu/fBTdLrUkA4ODrvjw==} + engines: {node: '>=18'} + ansi-regex@5.0.1: resolution: {integrity: sha512-quJQXlTSUGL2LH9SUXo8VwsY4soanhgo6LNSm84E1LBcE8s3O0wpdiRzyR9z/ZZJMlMWv37qOOb9pdJlMUEKFQ==} engines: {node: '>=8'} @@ -729,6 +749,10 @@ packages: asynckit@0.4.0: resolution: {integrity: sha512-Oei9OH4tRh0YqU3GxhX79dM/mwVgvbZJaSNaRk+bshkj0S5cfHcgYakreBjrHwatXKbz+IoIdYLxrKim2MjW0Q==} + auto-bind@5.0.1: + resolution: {integrity: sha512-ooviqdwwgfIfNmDwo94wlshcdzfO64XV0Cg6oDsDYBJfITDz1EngD2z7DkbvCWn+XIMsIqW27sEVF6qcpJrRcg==} + engines: {node: ^12.20.0 || ^14.13.1 || >=16.0.0} + available-typed-arrays@1.0.7: resolution: {integrity: sha512-wvUjBtSGN7+7SjNpq/9M2Tg350UZD3q62IFZLbRAR1bSMlCo1ZaeW+BJ+D090e4hIIZLBcTDWe4Mh4jvUDajzQ==} engines: {node: '>= 0.4'} @@ -808,6 +832,26 @@ packages: caseless@0.12.0: resolution: {integrity: sha512-4tYFyifaFfGacoiObjJegolkwSU4xQNGbVgUiNYVUxbQ2x2lUsFvY4hVgVzGiIe6WLOPqycWXA40l+PWsxthUw==} + chalk@5.4.1: + resolution: {integrity: sha512-zgVZuo2WcZgfUEmsn6eO3kINexW8RAE4maiQ8QNs8CtpPCSyMiYsULR3HQYkm3w8FIA3SberyMJMSldGsW+U3w==} + engines: {node: ^12.17.0 || ^14.13 || >=16.0.0} + + cli-boxes@3.0.0: + resolution: {integrity: sha512-/lzGpEWL/8PfI0BmBOPRwp0c/wFNX1RdUML3jK/RcSBA9T8mZDdQpqYBKtCFTOfQbwPqWEOpjqW+Fnayc0969g==} + engines: {node: '>=10'} + + cli-cursor@4.0.0: + resolution: {integrity: sha512-VGtlMu3x/4DOtIUwEkRezxUZ2lBacNJCHash0N0WeZDBS+7Ux1dm3XWAgWYxLJFMMdOeXMHXorshEFhbMSGelg==} + engines: {node: ^12.20.0 || ^14.13.1 || >=16.0.0} + + cli-truncate@4.0.0: + resolution: {integrity: sha512-nPdaFdQ0h/GEigbPClz11D0v/ZJEwxmeVZGeMo3Z5StPtUTkA9o1lD6QwoirYiSDzbcwn2XcjwmCp68W1IS4TA==} + engines: {node: '>=18'} + + code-excerpt@4.0.0: + resolution: {integrity: sha512-xxodCmBen3iy2i0WtAK8FlFNrRzjUqjRsMfho58xT/wvZU1YTM3fCnRjcy1gJPMepaRlgm/0e6w8SpWHpn3/cA==} + engines: {node: ^12.20.0 || ^14.13.1 || >=16.0.0} + color-convert@1.9.3: resolution: {integrity: sha512-QfAUtd+vFdAtFQcC8CCyYt1fYWxSqAiK2cSD6zDB8N3cpsEBAvRxp9zOGg6G/SHHJYAT88/az/IuDGALsNVbGg==} @@ -846,6 +890,10 @@ packages: resolution: {integrity: sha512-FveZTNuGw04cxlAiWbzi6zTAL/lhehaWbTtgluJh4/E95DqMwTmha3KZN1aAWA8cFIhHzMZUvLevkw5Rqk+tSQ==} engines: {node: '>= 0.6'} + convert-to-spaces@2.0.1: + resolution: {integrity: sha512-rcQ1bsQO9799wq24uE5AM2tAILy4gXGIK/njFWcVQkGNZ96edlpY+A7bjwvzjYvLDyzmG1MmMLZhpcsb+klNMQ==} + engines: {node: ^12.20.0 || ^14.13.1 || >=16.0.0} + core-util-is@1.0.2: resolution: {integrity: sha512-3lqz5YjWTYnW6dlDa5TLaTCcShfar1e40rmcJVwCBJC6mWlFuj0eCHIElmG1g5kyuJ/GD+8Wn4FFCcz4gJPfaQ==} @@ -860,6 +908,9 @@ packages: resolution: {integrity: sha512-ZgW+Jgdd7i52AaLYCriF8Mxqft0gD/R9i9wi6RWBhs1pqdPEzPjym7rvRKi397WmQFf3SlyUsszhw+VVCbx79Q==} engines: {node: '>=18'} + csstype@3.1.3: + resolution: {integrity: sha512-M1uQkMl8rQK/szD0LNhtqxIPLpimGm8sOBwU7lLnCpSbTyY3yeU1Vc7l4KT5zT4s/yOxHH5O7tIuuLOCnLADRw==} + dashdash@1.14.1: resolution: {integrity: sha512-jRFi8UDGo6j+odZiEpjazZaWqEal3w/basFjQHQEwVtZJGDpxbH1MeYluwCS8Xq5wmLJooDlMgvVarmWfGM44g==} engines: {node: '>=0.10'} @@ -966,6 +1017,9 @@ packages: resolution: {integrity: sha512-ofkXJtn7z0urokN62DI3SBo/5xAtF0rR7tn+S/bSYV79Ka8pTajIIl+fFQ1q88DQEImymmo97M4azY3WX/nUdg==} engines: {node: '>=4'} + emoji-regex@10.4.0: + resolution: {integrity: sha512-EC+0oUMY1Rqm4O6LLrgjtYDvcVYTy7chDnM4Q7030tP4Kwj3u/pR6gP9ygnp2CJMK5Gq+9Q2oqmrFJAz01DXjw==} + emoji-regex@8.0.0: resolution: {integrity: sha512-MSjYzcWNOA0ewAHpz0MxpYFvwg6yjy1NG3xteoqz644VCo/RPgnr1/GGt+ic3iJTzQ8Eu3TdM14SawnVUmGE6A==} @@ -982,6 +1036,10 @@ packages: resolution: {integrity: sha512-V0hjH4dGPh9Ao5p0MoRY6BVqtwCjhz6vI5LT8AJ55H+4g9/4vbHx1I54fS0XuclLhDHArPQCiMjDxjaL8fPxhw==} engines: {node: '>=0.12'} + environment@1.1.0: + resolution: {integrity: sha512-xUtoPkMggbz0MPyPiIWr1Kp4aeWJjDZ6SMvURhimjdZgsRuDplF5/s9hcgGhyXMhs+6vpnuoiZ2kFiu3FMnS8Q==} + engines: {node: '>=18'} + es-abstract@1.23.9: resolution: {integrity: sha512-py07lI0wjxAC/DcfK1S6G7iANonniZwTISvdPzk9hzeH0IZIshbuuFxLIU96OyF89Yb9hiqWn8M/bY83KY5vzA==} engines: {node: '>= 0.4'} @@ -1010,11 +1068,18 @@ packages: resolution: {integrity: sha512-w+5mJ3GuFL+NjVtJlvydShqE1eN3h3PbI7/5LAsYJP/2qtuMXjfL2LpHSRqo4b4eSF5K/DH1JXKUAHSB2UW50g==} engines: {node: '>= 0.4'} + es-toolkit@1.38.0: + resolution: {integrity: sha512-OT3AxczYYd3W50bCj4V0hKoOAfqIy9tof0leNQYekEDxVKir3RTVTJOLij7VAe6fsCNsGhC0JqIkURpMXTCSEA==} + esbuild@0.25.2: resolution: {integrity: sha512-16854zccKPnC+toMywC+uKNeYSv+/eXkevRAfwRD/G9Cleq66m8XFIrigkbvauLLlCfDL45Q2cWegSg53gGBnQ==} engines: {node: '>=18'} hasBin: true + escape-string-regexp@2.0.0: + resolution: {integrity: sha512-UpzcLCXolUWcNu5HtVMHYdXJjArjsF9C0aNnquZYY4uW/Vu0miy5YoWvbV345HauVvcAUnpRuhMMcqTcGOY2+w==} + engines: {node: '>=8'} + event-target-shim@5.0.1: resolution: {integrity: sha512-i/2XbnSz/uxRCU6+NdVJgKWDTM427+MqYbkQzD321DuCQJUqOuJKIA0IM2+W2xtYHdKOmZ4dR6fExsd4SXL+WQ==} engines: {node: '>=6'} @@ -1158,6 +1223,10 @@ packages: functions-have-names@1.2.3: resolution: {integrity: sha512-xckBUXyTIqT97tq2x2AMb+g163b5JFysYk0x4qxNFwbfQkmNZoiRHb6sPzI9/QV33WeuvVYBUIiD4NzNIyqaRQ==} + get-east-asian-width@1.3.0: + resolution: {integrity: sha512-vpeMIQKxczTD/0s2CdEWHcb0eeJe6TFjxb+J5xgX7hScxqrGuyjmv4c1D4A/gelKfyox0gJJwIHF+fLjeaM8kQ==} + engines: {node: '>=18'} + get-intrinsic@1.3.0: resolution: {integrity: sha512-9fSjSaos/fRIVIp+xSJlE6lfwhES7LNtKaCBIamHsjr2na1BiABJPo0mOjjz8GJDURarmCPGqaiVg5mfjb98CQ==} engines: {node: '>= 0.4'} @@ -1287,9 +1356,26 @@ packages: image2uri@2.1.2: resolution: {integrity: sha512-3b2zRma8I3zulb4OCkZruRw1VsnysT9phBzOJj+x3lPkwybJtNa5Sz6Dw8jSQI6OL7Ns4H5h8Y26EJbwq4GhQQ==} + indent-string@5.0.0: + resolution: {integrity: sha512-m6FAo/spmsW2Ab2fU35JTYwtOKa2yAwXSwgjSv1TJzh4Mh7mC3lzAOVLBprb72XsTrgkEIsl7YrFNAiDiRhIGg==} + engines: {node: '>=12'} + inherits@2.0.4: resolution: {integrity: sha512-k/vGaX4/Yla3WzyMCvTQOXYeIHvqOKtnqBduzTHpzpQZzAskKMhZ2K+EnBiSM9zGSoIFeMpXKxa4dYeZIQqewQ==} + ink@5.2.1: + resolution: {integrity: sha512-BqcUyWrG9zq5HIwW6JcfFHsIYebJkWWb4fczNah1goUO0vv5vneIlfwuS85twyJ5hYR/y18FlAYUxrO9ChIWVg==} + engines: {node: '>=18'} + peerDependencies: + '@types/react': '>=18.0.0' + react: '>=18.0.0' + react-devtools-core: ^4.19.1 + peerDependenciesMeta: + '@types/react': + optional: true + react-devtools-core: + optional: true + inspect-with-kind@1.0.5: resolution: {integrity: sha512-MAQUJuIo7Xqk8EVNP+6d3CKq9c80hi4tjIbIAT6lmGW9W6WzlHiu9PS8uSuUYU+Do+j1baiFp3H25XEVxDIG2g==} @@ -1340,6 +1426,14 @@ packages: resolution: {integrity: sha512-zymm5+u+sCsSWyD9qNaejV3DFvhCKclKdizYaJUuHA83RLjb7nSuGnddCHGv0hk+KY7BMAlsWeK4Ueg6EV6XQg==} engines: {node: '>=8'} + is-fullwidth-code-point@4.0.0: + resolution: {integrity: sha512-O4L094N2/dZ7xqVdrXhh9r1KODPJpFms8B5sGdJLPy664AgvXsreZUyCQQNItZRDlYug4xStLjNp/sz3HvBowQ==} + engines: {node: '>=12'} + + is-fullwidth-code-point@5.0.0: + resolution: {integrity: sha512-OVa3u9kkBbw7b8Xw5F9P+D/T9X+Z4+JruYVNapTjPYZYUznQ5YfWeFkOj606XYYW8yugTfC8Pj0hYqvi4ryAhA==} + engines: {node: '>=18'} + is-generator-function@1.1.0: resolution: {integrity: sha512-nPUB5km40q9e8UfN/Zc24eLlzdSf9OfKByBw9CIdw4H1giPMeA0OIJvbchsCu4npfI2QcMVBsGEBHKZ7wLTWmQ==} engines: {node: '>= 0.4'} @@ -1348,6 +1442,11 @@ packages: resolution: {integrity: sha512-xelSayHH36ZgE7ZWhli7pW34hNbNl8Ojv5KVmkJD4hBdD3th8Tfk9vYasLM+mXWOZhFkgZfxhLSnrwRr4elSSg==} engines: {node: '>=0.10.0'} + is-in-ci@1.0.0: + resolution: {integrity: sha512-eUuAjybVTHMYWm/U+vBO1sY/JOCgoPCXRxzdju0K+K0BiGW0SChEL1MLC0PoCIR1OlPo5YAp8HuQoUlsWEICwg==} + engines: {node: '>=18'} + hasBin: true + is-map@2.0.3: resolution: {integrity: sha512-1Qed0/Hr2m+YqxnM09CjA2d/i6YZNfF6R2oRAOj36eUdS6qIV/huPJNSEpKbupewFs+ZsJlxsjjPbc0/afW6Lw==} engines: {node: '>= 0.4'} @@ -1434,6 +1533,9 @@ packages: resolution: {integrity: sha512-9DDdhb5j6cpeitCbvLO7n7J4IxnbM6hoF6O1g4HQ5TfhvvKN8ywDM7668ZhMHRqVmxqhps/F6syWK2KcPxYlkw==} engines: {node: 20 || >=22} + js-tokens@4.0.0: + resolution: {integrity: sha512-RdJUflcE3cUzKiMqQgsCu06FPu9UdIJO0beYbPhHN4k6apgJtifcoCtT9bcxOpYBtpD2kCM6Sbzg4CausW/PKQ==} + jsbn@0.1.1: resolution: {integrity: sha512-UVU9dibq2JcFWxQPA6KCqj5O42VOmAY3zQUfEKxU0KpTGXwNoCjkX1e13eHNvw/xPynt6pU0rZ1htjWTNTSXsg==} @@ -1489,6 +1591,10 @@ packages: resolution: {integrity: sha512-TFYA4jnP7PVbmlBIfhlSe+WKxs9dklXMTEGcBCIvLhE/Tn3H6Gk1norupVW7m5Cnd4bLcr08AytbyV/xj7f/kQ==} engines: {node: '>= 12.0.0'} + loose-envify@1.4.0: + resolution: {integrity: sha512-lyuxPGr/Wfhrlem2CL/UcnUc1zcqKAImBDzukY7Y5F/yQiNdko6+fRLevlw1HgMySw7f611UIY408EtxRSoK3Q==} + hasBin: true + lowercase-keys@3.0.0: resolution: {integrity: sha512-ozCC6gdQ+glXOQsveKD0YsDy8DSQFjDTz4zyzEHNV5+JP5D62LmfDZ6o1cycFx9ouG940M5dE8C8CTewdj2YWQ==} engines: {node: ^12.20.0 || ^14.13.1 || >=16.0.0} @@ -1653,6 +1759,10 @@ packages: parseley@0.12.1: resolution: {integrity: sha512-e6qHKe3a9HWr0oMRVDTRhKce+bRO8VGQR3NyVwcjwrbhMmFCX9KszEV35+rn4AdilFAq9VPxP/Fe1wC9Qjd2lw==} + patch-console@2.0.0: + resolution: {integrity: sha512-0YNdUceMdaQwoKce1gatDScmMo5pu/tfABfnzEqeG0gtTmd7mh/WcwgUjtAeOU7N8nFFlbQBnFK2gXW5fGvmMA==} + engines: {node: ^12.20.0 || ^14.13.1 || >=16.0.0} + path-key@3.1.1: resolution: {integrity: sha512-ojmeN0qd+y0jszEtoY48r0Peq5dwMEkIlCOu6Q5f41lfkswXuKtYrhgoTpLnyIcHm24Uhqx+5Tqm2InSwLhE6Q==} engines: {node: '>=8'} @@ -1732,6 +1842,16 @@ packages: resolution: {integrity: sha512-WuyALRjWPDGtt/wzJiadO5AXY+8hZ80hVpe6MyivgraREW751X3SbhRvG3eLKOYN+8VEvqLcf3wdnt44Z4S4SA==} engines: {node: '>=10'} + react-reconciler@0.29.2: + resolution: {integrity: sha512-zZQqIiYgDCTP/f1N/mAR10nJGrPD2ZR+jDSEsKWJHYC7Cm2wodlwbR3upZRdC3cjIjSlTLNVyO7Iu0Yy7t2AYg==} + engines: {node: '>=0.10.0'} + peerDependencies: + react: ^18.3.1 + + react@18.3.1: + resolution: {integrity: sha512-wS+hAgJShR0KhEvPJArfuPVN1+Hz1t0Y6n5jLrGQbkb4urgPE/0Rve+1kMB1v/oWgHgm4WIcV+i7F2pTVj+2iQ==} + engines: {node: '>=0.10.0'} + readable-stream@2.3.8: resolution: {integrity: sha512-8p0AUk4XODgIewSi0l8Epjs+EVnWiK7NoDIEGU0HhE7+ZyY8D1IMY7odu5lRrFXGg71L15KG8QrPmum45RTtdA==} @@ -1775,6 +1895,10 @@ packages: resolution: {integrity: sha512-40yHxbNcl2+rzXvZuVkrYohathsSJlMTXKryG5y8uciHv1+xDLHQpgjG64JUO9nrEq2jGLH6IZ8BcZyw3wrweg==} engines: {node: '>=14.16'} + restore-cursor@4.0.0: + resolution: {integrity: sha512-I9fPXU9geO9bHOt9pHHOhOkYerIMsmVaWB0rA2AI9ERh/+x/i7MV5HKBNrg+ljO5eoPVgCcnFuRjJ9uH6I/3eg==} + engines: {node: ^12.20.0 || ^14.13.1 || >=16.0.0} + reusify@1.1.0: resolution: {integrity: sha512-g6QUff04oZpHs0eG5p83rFLhHeV00ug/Yf9nZM6fLeUrPguBTkTQOdpAWWspMh55TZfVQDPaN3NQJfbVRAxdIw==} engines: {iojs: '>=1.0.0', node: '>=0.10.0'} @@ -1819,6 +1943,9 @@ packages: resolution: {integrity: sha512-xAg7SOnEhrm5zI3puOOKyy1OMcMlIJZYNJY7xLBwSze0UjhPLnWfj2GF2EpT0jmzaJKIWKHLsaSSajf35bcYnA==} engines: {node: '>=v12.22.7'} + scheduler@0.23.2: + resolution: {integrity: sha512-UOShsPwz7NrMUqhR6t0hWjFduvOzbtv7toDH1/hIrfRNIDBnnBWd0CwJTGvTpngVlmwGCdP9/Zl/tVrDqcuYzQ==} + seek-bzip@2.0.0: resolution: {integrity: sha512-SMguiTnYrhpLdk3PwfzHeotrcwi8bNV4iemL9tx9poR/yeaMYwB9VzR1w7b57DuWpuqR8n6oZboi0hj3AxZxQg==} hasBin: true @@ -1889,6 +2016,14 @@ packages: resolution: {integrity: sha512-g9Q1haeby36OSStwb4ntCGGGaKsaVSjQ68fBxoQcutl5fS1vuY18H3wSt3jFyFtrkx+Kz0V1G85A4MyAdDMi2Q==} engines: {node: '>=8'} + slice-ansi@5.0.0: + resolution: {integrity: sha512-FC+lgizVPfie0kkhqUScwRu1O/lF6NOgJmlCgK+/LYxDCTk8sGelYaHDhFcDN+Sn3Cv+3VSa4Byeo+IMCzpMgQ==} + engines: {node: '>=12'} + + slice-ansi@7.1.0: + resolution: {integrity: sha512-bSiSngZ/jWeX93BqeIAbImyTbEihizcwNjFoRUIY/T1wWQsfsm2Vw1agPKylXvQTU7iASGdHhyqRlqQzfz+Htg==} + engines: {node: '>=18'} + sort-keys-length@1.0.1: resolution: {integrity: sha512-GRbEOUqCxemTAk/b32F2xa8wDTs+Z1QHOkbhJDQTvv/6G3ZkbJ+frYWsTcc7cBB3Fu4wy4XlLCuNtJuMn7Gsvw==} engines: {node: '>=0.10.0'} @@ -1937,6 +2072,10 @@ packages: stack-trace@0.0.10: resolution: {integrity: sha512-KGzahc7puUKkzyMt+IqAep+TVNbKP+k2Lmwhub39m1AsTSkaDutx56aDCo+HLDzf/D26BIHTJWNiTG1KAJiQCg==} + stack-utils@2.0.6: + resolution: {integrity: sha512-XlkWvfIm6RmsWtNJx+uqtKLS8eqFbxUg0ZzLXqY0caEy9l7hruX8IpiDnjsLavoBgqCCR71TqWO8MaXYheJ3RQ==} + engines: {node: '>=10'} + stealthy-require@1.1.1: resolution: {integrity: sha512-ZnWpYnYugiOVEY5GkcuJK1io5V8QmNYChG62gSit9pQVGErXtrKuPC55ITaVSukmMta5qpMU7vqLt2Lnni4f/g==} engines: {node: '>=0.10.0'} @@ -1952,6 +2091,10 @@ packages: resolution: {integrity: sha512-HnLOCR3vjcY8beoNLtcjZ5/nxn2afmME6lhrDrebokqMap+XbeW8n9TXpPDOqdGK5qcI3oT0GKTW6wC7EMiVqA==} engines: {node: '>=12'} + string-width@7.2.0: + resolution: {integrity: sha512-tsaTIkKW9b4N+AEj+SVA+WhJzV7/zMhcSu78mLKWSk7cXMOSHsBKFWUs0fWwq8QyK3MgJBQRX6Gbi4kYbdvGkQ==} + engines: {node: '>=18'} + string.prototype.trim@1.2.10: resolution: {integrity: sha512-Rs66F0P/1kedk5lyYyH9uBzuiI/kNRmwJAR9quK6VOtIpZ2G+hMZd+HQbbv25MgCA6gEffoMZYxlTod4WcdrKA==} engines: {node: '>= 0.4'} @@ -2059,6 +2202,10 @@ packages: tweetnacl@0.14.5: resolution: {integrity: sha512-KXXFFdAbFXY4geFIwoyNK+f5Z1b7swfXABfL7HXCmoIWMKU3dmS26672A4EeQtDzLKy7SXmfBu51JolvEKwtGA==} + type-fest@4.41.0: + resolution: {integrity: sha512-TeTSQ6H5YHvpqVwBRcnLDCBnDOHWYu7IvGbHT6N8AOymcr9PJGjc1GTtiWZTYg0NCgYwvnYWEkVChQAr9bjfwA==} + engines: {node: '>=16'} + typed-array-buffer@1.0.3: resolution: {integrity: sha512-nAYYwfY3qnzX30IkA6AQZjVbtK6duGontcQm1WSG1MD94YLqK0515GNApXkoxKOWMusVssAHWLh9SeaoefYFGw==} engines: {node: '>= 0.4'} @@ -2175,6 +2322,10 @@ packages: engines: {node: '>= 8'} hasBin: true + widest-line@5.0.0: + resolution: {integrity: sha512-c9bZp7b5YtRj2wOe6dlj32MK+Bx/M/d+9VB2SHM1OtsUHR0aV0tdP6DWh/iMt0kWi1t5g1Iudu6hQRNd1A4PVA==} + engines: {node: '>=18'} + winston-transport@4.9.0: resolution: {integrity: sha512-8drMJ4rkgaPo1Me4zD/3WLfI/zPdA9o2IipKODunnGDcuqbHwjsbB79ylv04LCGGzU0xQ6vTznOMpQGaLhhm6A==} engines: {node: '>= 12.0.0'} @@ -2191,6 +2342,10 @@ packages: resolution: {integrity: sha512-si7QWI6zUMq56bESFvagtmzMdGOtoxfR+Sez11Mobfc7tm+VkUckk9bW2UeffTGVUbOksxmSw0AA2gs8g71NCQ==} engines: {node: '>=12'} + wrap-ansi@9.0.0: + resolution: {integrity: sha512-G8ura3S+3Z2G+mkgNRq8dqaFZAuxfsxpBB8OCTGRTCtp+l/v9nbFNmCUP1BZMts3G1142MsZfn6eeUKrr4PD1Q==} + engines: {node: '>=18'} + wrappy@1.0.2: resolution: {integrity: sha512-l4Sp/DRseor9wL6EvV2+TuQn63dMkPjZ/sp9XkghTEbV9KlPS1xUsZ3u7/IQO4wxtcFB4bgpQPRcR3QCvezPcQ==} @@ -2222,11 +2377,19 @@ packages: resolution: {integrity: sha512-Ow9nuGZE+qp1u4JIPvg+uCiUr7xGQWdff7JQSk5VGYTAZMDe2q8lxJ10ygv10qmSj031Ty/6FNJpLO4o1Sgc+w==} engines: {node: '>=12'} + yoga-layout@3.2.1: + resolution: {integrity: sha512-0LPOt3AxKqMdFBZA3HBAt/t/8vIKq7VaQYbuA8WxCgung+p9TVyKRYdpvCb80HcdTN2NkbIKbhNwKUfm3tQywQ==} + zod@3.24.2: resolution: {integrity: sha512-lY7CDW43ECgW9u1TcT3IoXHflywfVqDYze4waEz812jR/bZ8FHDsl7pFQoSZTz5N+2NqRXs8GBwnAwo3ZNxqhQ==} snapshots: + '@alcalzone/ansi-tokenize@0.1.3': + dependencies: + ansi-styles: 6.2.1 + is-fullwidth-code-point: 4.0.0 + '@asamuzakjp/css-color@3.1.3': dependencies: '@csstools/css-calc': 2.1.3(@csstools/css-parser-algorithms@3.0.4(@csstools/css-tokenizer@3.0.3))(@csstools/css-tokenizer@3.0.3) @@ -2643,6 +2806,10 @@ snapshots: '@types/phoenix@1.6.6': {} + '@types/react@19.1.4': + dependencies: + csstype: 3.1.3 + '@types/request@2.48.12': dependencies: '@types/caseless': 0.12.5 @@ -2749,6 +2916,10 @@ snapshots: dependencies: qs: 6.14.0 + ansi-escapes@7.0.0: + dependencies: + environment: 1.1.0 + ansi-regex@5.0.1: {} ansi-regex@6.1.0: {} @@ -2797,6 +2968,8 @@ snapshots: asynckit@0.4.0: {} + auto-bind@5.0.1: {} + available-typed-arrays@1.0.7: dependencies: possible-typed-array-names: 1.1.0 @@ -2886,6 +3059,23 @@ snapshots: caseless@0.12.0: {} + chalk@5.4.1: {} + + cli-boxes@3.0.0: {} + + cli-cursor@4.0.0: + dependencies: + restore-cursor: 4.0.0 + + cli-truncate@4.0.0: + dependencies: + slice-ansi: 5.0.0 + string-width: 7.2.0 + + code-excerpt@4.0.0: + dependencies: + convert-to-spaces: 2.0.1 + color-convert@1.9.3: dependencies: color-name: 1.1.3 @@ -2925,6 +3115,8 @@ snapshots: dependencies: safe-buffer: 5.2.1 + convert-to-spaces@2.0.1: {} + core-util-is@1.0.2: {} core-util-is@1.0.3: {} @@ -2940,6 +3132,8 @@ snapshots: '@asamuzakjp/css-color': 3.1.3 rrweb-cssom: 0.8.0 + csstype@3.1.3: {} + dashdash@1.14.1: dependencies: assert-plus: 1.0.0 @@ -3058,6 +3252,8 @@ snapshots: dependencies: version-range: 4.14.0 + emoji-regex@10.4.0: {} + emoji-regex@8.0.0: {} emoji-regex@9.2.2: {} @@ -3070,6 +3266,8 @@ snapshots: entities@4.5.0: {} + environment@1.1.0: {} + es-abstract@1.23.9: dependencies: array-buffer-byte-length: 1.0.2 @@ -3149,6 +3347,8 @@ snapshots: is-date-object: 1.1.0 is-symbol: 1.1.1 + es-toolkit@1.38.0: {} + esbuild@0.25.2: optionalDependencies: '@esbuild/aix-ppc64': 0.25.2 @@ -3177,6 +3377,8 @@ snapshots: '@esbuild/win32-ia32': 0.25.2 '@esbuild/win32-x64': 0.25.2 + escape-string-regexp@2.0.0: {} + event-target-shim@5.0.1: {} eventemitter3@3.1.2: {} @@ -3322,6 +3524,8 @@ snapshots: functions-have-names@1.2.3: {} + get-east-asian-width@1.3.0: {} + get-intrinsic@1.3.0: dependencies: call-bind-apply-helpers: 1.0.2 @@ -3486,8 +3690,43 @@ snapshots: dependencies: node-fetch: 3.3.2 + indent-string@5.0.0: {} + inherits@2.0.4: {} + ink@5.2.1(@types/react@19.1.4)(react@18.3.1): + dependencies: + '@alcalzone/ansi-tokenize': 0.1.3 + ansi-escapes: 7.0.0 + ansi-styles: 6.2.1 + auto-bind: 5.0.1 + chalk: 5.4.1 + cli-boxes: 3.0.0 + cli-cursor: 4.0.0 + cli-truncate: 4.0.0 + code-excerpt: 4.0.0 + es-toolkit: 1.38.0 + indent-string: 5.0.0 + is-in-ci: 1.0.0 + patch-console: 2.0.0 + react: 18.3.1 + react-reconciler: 0.29.2(react@18.3.1) + scheduler: 0.23.2 + signal-exit: 3.0.7 + slice-ansi: 7.1.0 + stack-utils: 2.0.6 + string-width: 7.2.0 + type-fest: 4.41.0 + widest-line: 5.0.0 + wrap-ansi: 9.0.0 + ws: 8.18.1 + yoga-layout: 3.2.1 + optionalDependencies: + '@types/react': 19.1.4 + transitivePeerDependencies: + - bufferutil + - utf-8-validate + inspect-with-kind@1.0.5: dependencies: kind-of: 6.0.3 @@ -3544,6 +3783,12 @@ snapshots: is-fullwidth-code-point@3.0.0: {} + is-fullwidth-code-point@4.0.0: {} + + is-fullwidth-code-point@5.0.0: + dependencies: + get-east-asian-width: 1.3.0 + is-generator-function@1.1.0: dependencies: call-bound: 1.0.4 @@ -3555,6 +3800,8 @@ snapshots: dependencies: is-extglob: 2.1.1 + is-in-ci@1.0.0: {} + is-map@2.0.3: {} is-number-object@1.1.1: @@ -3631,6 +3878,8 @@ snapshots: dependencies: '@isaacs/cliui': 8.0.2 + js-tokens@4.0.0: {} + jsbn@0.1.1: {} jsdom@26.1.0: @@ -3700,6 +3949,10 @@ snapshots: safe-stable-stringify: 2.5.0 triple-beam: 1.4.1 + loose-envify@1.4.0: + dependencies: + js-tokens: 4.0.0 + lowercase-keys@3.0.0: {} lru-cache@10.4.3: {} @@ -3848,6 +4101,8 @@ snapshots: leac: 0.6.0 peberminta: 0.9.0 + patch-console@2.0.0: {} + path-key@3.1.1: {} path-scurry@2.0.0: @@ -3906,6 +4161,16 @@ snapshots: quick-lru@5.1.1: {} + react-reconciler@0.29.2(react@18.3.1): + dependencies: + loose-envify: 1.4.0 + react: 18.3.1 + scheduler: 0.23.2 + + react@18.3.1: + dependencies: + loose-envify: 1.4.0 + readable-stream@2.3.8: dependencies: core-util-is: 1.0.3 @@ -3986,6 +4251,11 @@ snapshots: dependencies: lowercase-keys: 3.0.0 + restore-cursor@4.0.0: + dependencies: + onetime: 5.1.2 + signal-exit: 3.0.7 + reusify@1.1.0: {} rimraf@6.0.1: @@ -4030,6 +4300,10 @@ snapshots: dependencies: xmlchars: 2.2.0 + scheduler@0.23.2: + dependencies: + loose-envify: 1.4.0 + seek-bzip@2.0.0: dependencies: commander: 6.2.1 @@ -4112,6 +4386,16 @@ snapshots: slash@3.0.0: {} + slice-ansi@5.0.0: + dependencies: + ansi-styles: 6.2.1 + is-fullwidth-code-point: 4.0.0 + + slice-ansi@7.1.0: + dependencies: + ansi-styles: 6.2.1 + is-fullwidth-code-point: 5.0.0 + sort-keys-length@1.0.1: dependencies: sort-keys: 1.1.2 @@ -4159,6 +4443,10 @@ snapshots: stack-trace@0.0.10: {} + stack-utils@2.0.6: + dependencies: + escape-string-regexp: 2.0.0 + stealthy-require@1.1.1: {} streamx@2.22.0: @@ -4180,6 +4468,12 @@ snapshots: emoji-regex: 9.2.2 strip-ansi: 7.1.0 + string-width@7.2.0: + dependencies: + emoji-regex: 10.4.0 + get-east-asian-width: 1.3.0 + strip-ansi: 7.1.0 + string.prototype.trim@1.2.10: dependencies: call-bind: 1.0.8 @@ -4300,6 +4594,8 @@ snapshots: tweetnacl@0.14.5: {} + type-fest@4.41.0: {} + typed-array-buffer@1.0.3: dependencies: call-bound: 1.0.4 @@ -4444,6 +4740,10 @@ snapshots: dependencies: isexe: 2.0.0 + widest-line@5.0.0: + dependencies: + string-width: 7.2.0 + winston-transport@4.9.0: dependencies: logform: 2.7.0 @@ -4476,6 +4776,12 @@ snapshots: string-width: 5.1.2 strip-ansi: 7.1.0 + wrap-ansi@9.0.0: + dependencies: + ansi-styles: 6.2.1 + string-width: 7.2.0 + strip-ansi: 7.1.0 + wrappy@1.0.2: {} ws@8.18.1: {} @@ -4491,5 +4797,7 @@ snapshots: buffer-crc32: 0.2.13 pend: 1.2.0 + yoga-layout@3.2.1: {} + zod@3.24.2: optional: true diff --git a/src/plugins/cli-ui/components/App.tsx b/src/plugins/cli-ui/components/App.tsx new file mode 100644 index 0000000..231e186 --- /dev/null +++ b/src/plugins/cli-ui/components/App.tsx @@ -0,0 +1,95 @@ +import React, { useState } from 'react'; +import { Box, Text, useInput, useApp, Key } from 'ink'; +import { Dict } from '../../../core/athena.js'; + +interface Message { + type: 'user' | 'athena' | 'thinking' | 'tool-call' | 'tool-result' | 'event'; + content: string; + timestamp: string; +} + +interface AppProps { + onMessage: (content: string) => void; + messages: Message[]; + prompt: string; + isThinking: boolean; +} + +export const App: React.FC = ({ onMessage, messages, prompt, isThinking }) => { + const [input, setInput] = useState(''); + const [cursorPosition, setCursorPosition] = useState(0); + const { exit } = useApp(); + + useInput((char: string, key: Key) => { + // Handle Ctrl+C + if (key.ctrl && char === 'c') { + exit(); + return; + } + + // Handle Enter + if (key.return) { + if (input.trim()) { + onMessage(input); + } + setInput(''); + setCursorPosition(0); + return; + } + + // Handle Backspace + if (key.backspace || key.delete) { + if (cursorPosition > 0) { + const newInput = input.slice(0, cursorPosition - 1) + input.slice(cursorPosition); + setInput(newInput); + setCursorPosition(cursorPosition - 1); + } + return; + } + + // Handle Left Arrow + if (key.leftArrow) { + setCursorPosition(Math.max(0, cursorPosition - 1)); + return; + } + + // Handle Right Arrow + if (key.rightArrow) { + setCursorPosition(Math.min(input.length, cursorPosition + 1)); + return; + } + + // Handle regular character input + if (char && char.length === 1) { + const newInput = input.slice(0, cursorPosition) + char + input.slice(cursorPosition); + setInput(newInput); + setCursorPosition(cursorPosition + 1); + } + }); + + return ( + + {messages.map((message, index) => ( + + + {message.type === 'user' && ' '} + {message.type === 'athena' && ' '} + {message.type === 'thinking' && ' '} + {message.type === 'tool-call' && ' '} + {message.type === 'tool-result' && ' '} + {message.type === 'event' && ' '} + {message.content} + + + ))} + + {prompt} + + {input.slice(0, cursorPosition)} + + {input.slice(cursorPosition)} + + + + ); +}; \ No newline at end of file diff --git a/src/plugins/cli-ui/init.ts b/src/plugins/cli-ui/init.ts index b608c6e..6637ffd 100644 --- a/src/plugins/cli-ui/init.ts +++ b/src/plugins/cli-ui/init.ts @@ -1,19 +1,21 @@ -import readline from "readline"; - +import { render } from 'ink'; +import React from 'react'; import { Athena, Dict } from "../../core/athena.js"; import { PluginBase } from "../plugin-base.js"; +import { App } from './components/App.js'; + +interface Message { + type: 'user' | 'athena' | 'thinking' | 'tool-call' | 'tool-result' | 'event'; + content: string; + timestamp: string; +} export default class CLIUI extends PluginBase { athena!: Athena; - boundHandleStdin!: (key: any) => void; boundAthenaPrivateEventHandler!: (event: string, args: Dict) => void; - rl: readline.Interface = readline.createInterface({ - input: process.stdin, - terminal: true, - }); + messages: Message[] = []; + isThinking: boolean = false; prompt: string = " "; - currentInput: string = ""; - currentPos: number = 0; desc() { return "You can interact with the user using UI tools and events. When the user asks you to do something, think about what information and/or details you need to do that. If you need something only the user can provide, you need to ask the user for that information. Ask the users about task details if the request is vague. Be proactive and update the user on your progress, milestones, and obstacles and how you are going to overcome them."; @@ -21,9 +23,7 @@ export default class CLIUI extends PluginBase { async load(athena: Athena) { this.athena = athena; - this.boundAthenaPrivateEventHandler = - this.athenaPrivateEventHandler.bind(this); - this.boundHandleStdin = this.handleStdin.bind(this); + this.boundAthenaPrivateEventHandler = this.athenaPrivateEventHandler.bind(this); athena.on("private-event", this.boundAthenaPrivateEventHandler); @@ -43,6 +43,7 @@ export default class CLIUI extends PluginBase { }, }, }); + athena.registerTool( { name: "ui/send-message", @@ -64,24 +65,19 @@ export default class CLIUI extends PluginBase { }, { fn: async (args: Dict) => { - this.printOutput(` ${args.content}\n`); + this.addMessage('athena', args.content); return { status: "success" }; }, }, ); + athena.once("plugins-loaded", async () => { - process.stdin.setRawMode(true); - process.stdin.on("data", this.boundHandleStdin); - this.printOutput("Welcome to Athena!\n"); - this.redrawPrompt(); + this.addMessage('athena', "Welcome to Athena!"); + this.renderUI(); }); } async unload(athena: Athena) { - process.stdin.setRawMode(false); - process.stdin.off("data", this.boundHandleStdin); - this.rl.close(); - process.stdin.destroy(); athena.off("private-event", this.boundAthenaPrivateEventHandler); athena.deregisterTool("ui/send-message"); athena.deregisterEvent("ui/message-received"); @@ -89,99 +85,45 @@ export default class CLIUI extends PluginBase { athenaPrivateEventHandler(event: string, args: Dict) { if (event === "cerebrum/thinking") { - this.printOutput(` ${args.content}\n`); + this.addMessage('thinking', args.content); } else if (event === "athena/tool-call") { - this.printOutput(` ${args.summary}\n`); + this.addMessage('tool-call', args.summary); } else if (event === "athena/tool-result") { - this.printOutput(` ${args.summary}\n`); + this.addMessage('tool-result', args.summary); } else if (event === "athena/event") { - this.printOutput(` ${args.summary}\n`); + this.addMessage('event', args.summary); } else if (event === "cerebrum/busy") { - this.changePrompt(args.busy ? " " : " "); + this.isThinking = args.busy; + this.prompt = args.busy ? " " : " "; + this.renderUI(); } } - clearLine() { - readline.clearLine(process.stdout, 0); - readline.cursorTo(process.stdout, 0); - } - - redrawPrompt() { - this.clearLine(); - process.stdout.write(this.prompt); - process.stdout.write(this.currentInput); - readline.cursorTo(process.stdout, this.prompt.length + this.currentPos); - } - - printOutput(output: string) { - this.clearLine(); - console.log(output); - this.redrawPrompt(); + addMessage(type: Message['type'], content: string) { + this.messages.push({ + type, + content, + timestamp: new Date().toISOString(), + }); + this.renderUI(); } - changePrompt(prompt: string) { - this.prompt = prompt; - this.redrawPrompt(); + handleMessage(content: string) { + this.addMessage('user', content); + this.athena.emitEvent("ui/message-received", { + content, + time: new Date().toISOString(), + }); } - handleStdin(key: any) { - // Ctrl+C - if (key.toString() === "\u0003") { - process.kill(process.pid, "SIGINT"); - return; - } - - // Enter key - if (key.toString() === "\r" || key.toString() === "\n") { - this.athena.emitEvent("ui/message-received", { - content: this.currentInput, - time: new Date().toISOString(), - }); - this.currentInput = ""; - this.currentPos = 0; - console.log("\n"); - this.redrawPrompt(); - return; - } - - // Backspace - if (key.toString() === "\u0008" || key.toString() === "\u007f") { - if (this.currentPos > 0) { - this.currentInput = - this.currentInput.slice(0, this.currentPos - 1) + - this.currentInput.slice(this.currentPos); - this.currentPos--; - this.redrawPrompt(); - } - return; - } - - // Left arrow - if (key.toString() === "\u001b[D") { - if (this.currentPos > 0) { - this.currentPos--; - this.redrawPrompt(); - } - return; - } - - // Right arrow - if (key.toString() === "\u001b[C") { - if (this.currentPos < this.currentInput.length) { - this.currentPos++; - this.redrawPrompt(); - } - return; - } - - // Regular character input - if (key.toString().charCodeAt(0) >= 32 || key.toString().length > 1) { - this.currentInput = - this.currentInput.slice(0, this.currentPos) + - key.toString() + - this.currentInput.slice(this.currentPos); - this.currentPos += key.toString().length; - this.redrawPrompt(); - } + renderUI() { + render( + React.createElement(App, { + onMessage: this.handleMessage.bind(this), + messages: this.messages, + prompt: this.prompt, + isThinking: this.isThinking, + }) + ); } } diff --git a/tsconfig.json b/tsconfig.json index 4988fc1..a038689 100644 --- a/tsconfig.json +++ b/tsconfig.json @@ -1,13 +1,18 @@ { "compilerOptions": { - "target": "ESNext", - "module": "ESNext", - "moduleResolution": "Node", - "rootDir": "./src", - "outDir": "./dist", + "target": "ES2020", + "module": "NodeNext", + "moduleResolution": "NodeNext", "esModuleInterop": true, - "forceConsistentCasingInFileNames": true, "strict": true, - "skipLibCheck": true - } + "skipLibCheck": true, + "forceConsistentCasingInFileNames": true, + "outDir": "dist", + "rootDir": "src", + "jsx": "react-jsx", + "lib": ["ES2020", "DOM"], + "types": ["node"] + }, + "include": ["src/**/*"], + "exclude": ["node_modules", "dist"] } From 98904e062f61a4a882868b7aac83f8589fe30a78 Mon Sep 17 00:00:00 2001 From: Alex Yang Date: Mon, 19 May 2025 12:14:35 -0700 Subject: [PATCH 2/8] fix: tsconfig --- tsconfig.json | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/tsconfig.json b/tsconfig.json index a038689..d1ce7e0 100644 --- a/tsconfig.json +++ b/tsconfig.json @@ -10,7 +10,7 @@ "outDir": "dist", "rootDir": "src", "jsx": "react-jsx", - "lib": ["ES2020", "DOM"], + "lib": ["ESNext"], "types": ["node"] }, "include": ["src/**/*"], From 5322e0c3de88b81e685a84cf2891321814de203d Mon Sep 17 00:00:00 2001 From: Alex Yang Date: Mon, 19 May 2025 12:15:09 -0700 Subject: [PATCH 3/8] fix: lint --- package.json | 3 +- src/plugins/cli-ui/components/App.tsx | 41 ++++++++++++++++----------- src/plugins/cli-ui/init.ts | 29 ++++++++++--------- 3 files changed, 41 insertions(+), 32 deletions(-) diff --git a/package.json b/package.json index be9d051..34db952 100644 --- a/package.json +++ b/package.json @@ -65,5 +65,6 @@ "prettier": "^3.5.3", "tsx": "^4.19.3", "typescript": "^5.8.3" - } + }, + "packageManager": "pnpm@9.15.5+sha512.845196026aab1cc3f098a0474b64dfbab2afe7a1b4e91dd86895d8e4aa32a7a6d03049e2d0ad770bbe4de023a7122fb68c1a1d6e0d033c7076085f9d5d4800d4" } diff --git a/src/plugins/cli-ui/components/App.tsx b/src/plugins/cli-ui/components/App.tsx index 231e186..c5a2ede 100644 --- a/src/plugins/cli-ui/components/App.tsx +++ b/src/plugins/cli-ui/components/App.tsx @@ -1,9 +1,9 @@ -import React, { useState } from 'react'; -import { Box, Text, useInput, useApp, Key } from 'ink'; -import { Dict } from '../../../core/athena.js'; +import React, { useState } from "react"; +import { Box, Text, useInput, useApp, Key } from "ink"; +import { Dict } from "../../../core/athena.js"; interface Message { - type: 'user' | 'athena' | 'thinking' | 'tool-call' | 'tool-result' | 'event'; + type: "user" | "athena" | "thinking" | "tool-call" | "tool-result" | "event"; content: string; timestamp: string; } @@ -15,14 +15,19 @@ interface AppProps { isThinking: boolean; } -export const App: React.FC = ({ onMessage, messages, prompt, isThinking }) => { - const [input, setInput] = useState(''); +export const App: React.FC = ({ + onMessage, + messages, + prompt, + isThinking, +}) => { + const [input, setInput] = useState(""); const [cursorPosition, setCursorPosition] = useState(0); const { exit } = useApp(); useInput((char: string, key: Key) => { // Handle Ctrl+C - if (key.ctrl && char === 'c') { + if (key.ctrl && char === "c") { exit(); return; } @@ -32,7 +37,7 @@ export const App: React.FC = ({ onMessage, messages, prompt, isThinkin if (input.trim()) { onMessage(input); } - setInput(''); + setInput(""); setCursorPosition(0); return; } @@ -40,7 +45,8 @@ export const App: React.FC = ({ onMessage, messages, prompt, isThinkin // Handle Backspace if (key.backspace || key.delete) { if (cursorPosition > 0) { - const newInput = input.slice(0, cursorPosition - 1) + input.slice(cursorPosition); + const newInput = + input.slice(0, cursorPosition - 1) + input.slice(cursorPosition); setInput(newInput); setCursorPosition(cursorPosition - 1); } @@ -61,7 +67,8 @@ export const App: React.FC = ({ onMessage, messages, prompt, isThinkin // Handle regular character input if (char && char.length === 1) { - const newInput = input.slice(0, cursorPosition) + char + input.slice(cursorPosition); + const newInput = + input.slice(0, cursorPosition) + char + input.slice(cursorPosition); setInput(newInput); setCursorPosition(cursorPosition + 1); } @@ -72,12 +79,12 @@ export const App: React.FC = ({ onMessage, messages, prompt, isThinkin {messages.map((message, index) => ( - {message.type === 'user' && ' '} - {message.type === 'athena' && ' '} - {message.type === 'thinking' && ' '} - {message.type === 'tool-call' && ' '} - {message.type === 'tool-result' && ' '} - {message.type === 'event' && ' '} + {message.type === "user" && " "} + {message.type === "athena" && " "} + {message.type === "thinking" && " "} + {message.type === "tool-call" && " "} + {message.type === "tool-result" && " "} + {message.type === "event" && " "} {message.content} @@ -92,4 +99,4 @@ export const App: React.FC = ({ onMessage, messages, prompt, isThinkin ); -}; \ No newline at end of file +}; diff --git a/src/plugins/cli-ui/init.ts b/src/plugins/cli-ui/init.ts index 6637ffd..8f8ada7 100644 --- a/src/plugins/cli-ui/init.ts +++ b/src/plugins/cli-ui/init.ts @@ -1,11 +1,11 @@ -import { render } from 'ink'; -import React from 'react'; +import { render } from "ink"; +import React from "react"; import { Athena, Dict } from "../../core/athena.js"; import { PluginBase } from "../plugin-base.js"; -import { App } from './components/App.js'; +import { App } from "./components/App.js"; interface Message { - type: 'user' | 'athena' | 'thinking' | 'tool-call' | 'tool-result' | 'event'; + type: "user" | "athena" | "thinking" | "tool-call" | "tool-result" | "event"; content: string; timestamp: string; } @@ -23,7 +23,8 @@ export default class CLIUI extends PluginBase { async load(athena: Athena) { this.athena = athena; - this.boundAthenaPrivateEventHandler = this.athenaPrivateEventHandler.bind(this); + this.boundAthenaPrivateEventHandler = + this.athenaPrivateEventHandler.bind(this); athena.on("private-event", this.boundAthenaPrivateEventHandler); @@ -65,14 +66,14 @@ export default class CLIUI extends PluginBase { }, { fn: async (args: Dict) => { - this.addMessage('athena', args.content); + this.addMessage("athena", args.content); return { status: "success" }; }, }, ); athena.once("plugins-loaded", async () => { - this.addMessage('athena', "Welcome to Athena!"); + this.addMessage("athena", "Welcome to Athena!"); this.renderUI(); }); } @@ -85,13 +86,13 @@ export default class CLIUI extends PluginBase { athenaPrivateEventHandler(event: string, args: Dict) { if (event === "cerebrum/thinking") { - this.addMessage('thinking', args.content); + this.addMessage("thinking", args.content); } else if (event === "athena/tool-call") { - this.addMessage('tool-call', args.summary); + this.addMessage("tool-call", args.summary); } else if (event === "athena/tool-result") { - this.addMessage('tool-result', args.summary); + this.addMessage("tool-result", args.summary); } else if (event === "athena/event") { - this.addMessage('event', args.summary); + this.addMessage("event", args.summary); } else if (event === "cerebrum/busy") { this.isThinking = args.busy; this.prompt = args.busy ? " " : " "; @@ -99,7 +100,7 @@ export default class CLIUI extends PluginBase { } } - addMessage(type: Message['type'], content: string) { + addMessage(type: Message["type"], content: string) { this.messages.push({ type, content, @@ -109,7 +110,7 @@ export default class CLIUI extends PluginBase { } handleMessage(content: string) { - this.addMessage('user', content); + this.addMessage("user", content); this.athena.emitEvent("ui/message-received", { content, time: new Date().toISOString(), @@ -123,7 +124,7 @@ export default class CLIUI extends PluginBase { messages: this.messages, prompt: this.prompt, isThinking: this.isThinking, - }) + }), ); } } From aa0d7b0e8c02e6a462dfadc1e1a6aca8e3105463 Mon Sep 17 00:00:00 2001 From: Alex Yang Date: Mon, 19 May 2025 12:15:46 -0700 Subject: [PATCH 4/8] Update src/plugins/cli-ui/components/App.tsx Co-authored-by: Copilot <175728472+Copilot@users.noreply.github.com> --- src/plugins/cli-ui/components/App.tsx | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/plugins/cli-ui/components/App.tsx b/src/plugins/cli-ui/components/App.tsx index c5a2ede..b2b84ea 100644 --- a/src/plugins/cli-ui/components/App.tsx +++ b/src/plugins/cli-ui/components/App.tsx @@ -76,8 +76,8 @@ export const App: React.FC = ({ return ( - {messages.map((message, index) => ( - + {messages.map((message) => ( + {message.type === "user" && " "} {message.type === "athena" && " "} From da4ae1433dcdad63b023489f8a169fcb11b891d7 Mon Sep 17 00:00:00 2001 From: Alex Yang Date: Mon, 19 May 2025 12:16:31 -0700 Subject: [PATCH 5/8] fix: pkg --- package.json | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/package.json b/package.json index 34db952..be9d051 100644 --- a/package.json +++ b/package.json @@ -65,6 +65,5 @@ "prettier": "^3.5.3", "tsx": "^4.19.3", "typescript": "^5.8.3" - }, - "packageManager": "pnpm@9.15.5+sha512.845196026aab1cc3f098a0474b64dfbab2afe7a1b4e91dd86895d8e4aa32a7a6d03049e2d0ad770bbe4de023a7122fb68c1a1d6e0d033c7076085f9d5d4800d4" + } } From 5366f5cd21746762a71c79248d5431818153df72 Mon Sep 17 00:00:00 2001 From: Alex Yang Date: Mon, 19 May 2025 12:22:22 -0700 Subject: [PATCH 6/8] fix: use correct react type --- package.json | 2 +- pnpm-lock.yaml | 22 ++++++++++++++-------- 2 files changed, 15 insertions(+), 9 deletions(-) diff --git a/package.json b/package.json index be9d051..e79ff9f 100644 --- a/package.json +++ b/package.json @@ -30,7 +30,7 @@ "description": "", "dependencies": { "@supabase/supabase-js": "^2.49.4", - "@types/react": "^19.1.4", + "@types/react": "^18.3.21", "amadeus": "^11.0.0", "discord.js": "^14.18.0", "follow-redirects": "^1.15.9", diff --git a/pnpm-lock.yaml b/pnpm-lock.yaml index c224069..4bd9577 100644 --- a/pnpm-lock.yaml +++ b/pnpm-lock.yaml @@ -12,8 +12,8 @@ importers: specifier: ^2.49.4 version: 2.49.4 '@types/react': - specifier: ^19.1.4 - version: 19.1.4 + specifier: ^18.3.21 + version: 18.3.21 amadeus: specifier: ^11.0.0 version: 11.0.0 @@ -31,7 +31,7 @@ importers: version: 2.1.2 ink: specifier: ^5.2.1 - version: 5.2.1(@types/react@19.1.4)(react@18.3.1) + version: 5.2.1(@types/react@18.3.21)(react@18.3.1) istextorbinary: specifier: ^9.5.0 version: 9.5.0 @@ -620,8 +620,11 @@ packages: '@types/phoenix@1.6.6': resolution: {integrity: sha512-PIzZZlEppgrpoT2QgbnDU+MMzuR6BbCjllj0bM70lWoejMeNJAxCchxnv7J3XFkI8MpygtRpzXrIlmWUBclP5A==} - '@types/react@19.1.4': - resolution: {integrity: sha512-EB1yiiYdvySuIITtD5lhW4yPyJ31RkJkkDw794LaQYrxCSaQV/47y5o1FMC4zF9ZyjUjzJMZwbovEnT5yHTW6g==} + '@types/prop-types@15.7.14': + resolution: {integrity: sha512-gNMvNH49DJ7OJYv+KAKn0Xp45p8PLl6zo2YnvDIbTd4J6MER2BmWN49TG7n9LvkyihINxeKW8+3bfS2yDC9dzQ==} + + '@types/react@18.3.21': + resolution: {integrity: sha512-gXLBtmlcRJeT09/sI4PxVwyrku6SaNUj/6cMubjE6T6XdY1fDmBL7r0nX0jbSZPU/Xr0KuwLLZh6aOYY5d91Xw==} '@types/request@2.48.12': resolution: {integrity: sha512-G3sY+NpsA9jnwm0ixhAFQSJ3Q9JkpLZpJbI3GMv0mIAT0y3mRabYeINzal5WOChIiaTEGQYlHOKgkaM9EisWHw==} @@ -2806,8 +2809,11 @@ snapshots: '@types/phoenix@1.6.6': {} - '@types/react@19.1.4': + '@types/prop-types@15.7.14': {} + + '@types/react@18.3.21': dependencies: + '@types/prop-types': 15.7.14 csstype: 3.1.3 '@types/request@2.48.12': @@ -3694,7 +3700,7 @@ snapshots: inherits@2.0.4: {} - ink@5.2.1(@types/react@19.1.4)(react@18.3.1): + ink@5.2.1(@types/react@18.3.21)(react@18.3.1): dependencies: '@alcalzone/ansi-tokenize': 0.1.3 ansi-escapes: 7.0.0 @@ -3722,7 +3728,7 @@ snapshots: ws: 8.18.1 yoga-layout: 3.2.1 optionalDependencies: - '@types/react': 19.1.4 + '@types/react': 18.3.21 transitivePeerDependencies: - bufferutil - utf-8-validate From 33b4e0d819f2be7c47c1041273850f65348159eb Mon Sep 17 00:00:00 2001 From: Alex Yang Date: Mon, 19 May 2025 12:23:30 -0700 Subject: [PATCH 7/8] fix: type --- src/plugins/cli-ui/components/App.tsx | 2 +- src/plugins/cli-ui/init.ts | 8 +------- 2 files changed, 2 insertions(+), 8 deletions(-) diff --git a/src/plugins/cli-ui/components/App.tsx b/src/plugins/cli-ui/components/App.tsx index b2b84ea..c2c6f47 100644 --- a/src/plugins/cli-ui/components/App.tsx +++ b/src/plugins/cli-ui/components/App.tsx @@ -2,7 +2,7 @@ import React, { useState } from "react"; import { Box, Text, useInput, useApp, Key } from "ink"; import { Dict } from "../../../core/athena.js"; -interface Message { +export interface Message { type: "user" | "athena" | "thinking" | "tool-call" | "tool-result" | "event"; content: string; timestamp: string; diff --git a/src/plugins/cli-ui/init.ts b/src/plugins/cli-ui/init.ts index 8f8ada7..fcabf15 100644 --- a/src/plugins/cli-ui/init.ts +++ b/src/plugins/cli-ui/init.ts @@ -2,13 +2,7 @@ import { render } from "ink"; import React from "react"; import { Athena, Dict } from "../../core/athena.js"; import { PluginBase } from "../plugin-base.js"; -import { App } from "./components/App.js"; - -interface Message { - type: "user" | "athena" | "thinking" | "tool-call" | "tool-result" | "event"; - content: string; - timestamp: string; -} +import { App, type Message } from "./components/App.js"; export default class CLIUI extends PluginBase { athena!: Athena; From 8bb15ce83ec6d0bc83050aa1bf4d66c7eb3a4bd8 Mon Sep 17 00:00:00 2001 From: Alex Yang Date: Mon, 19 May 2025 12:24:19 -0700 Subject: [PATCH 8/8] fix: dev --- package.json | 2 +- pnpm-lock.yaml | 6 +++--- 2 files changed, 4 insertions(+), 4 deletions(-) diff --git a/package.json b/package.json index e79ff9f..a5c1e1a 100644 --- a/package.json +++ b/package.json @@ -30,7 +30,6 @@ "description": "", "dependencies": { "@supabase/supabase-js": "^2.49.4", - "@types/react": "^18.3.21", "amadeus": "^11.0.0", "discord.js": "^14.18.0", "follow-redirects": "^1.15.9", @@ -61,6 +60,7 @@ "@types/mime-types": "^2.1.4", "@types/node": "^22.14.1", "@types/node-telegram-bot-api": "^0.64.8", + "@types/react": "^18.3.21", "@types/ws": "^8.18.1", "prettier": "^3.5.3", "tsx": "^4.19.3", diff --git a/pnpm-lock.yaml b/pnpm-lock.yaml index 4bd9577..600133f 100644 --- a/pnpm-lock.yaml +++ b/pnpm-lock.yaml @@ -11,9 +11,6 @@ importers: '@supabase/supabase-js': specifier: ^2.49.4 version: 2.49.4 - '@types/react': - specifier: ^18.3.21 - version: 18.3.21 amadeus: specifier: ^11.0.0 version: 11.0.0 @@ -99,6 +96,9 @@ importers: '@types/node-telegram-bot-api': specifier: ^0.64.8 version: 0.64.8 + '@types/react': + specifier: ^18.3.21 + version: 18.3.21 '@types/ws': specifier: ^8.18.1 version: 8.18.1