@drewsepsi/nextpi 0.1.0
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.
- package/.next/BUILD_ID +1 -0
- package/.next/app-path-routes-manifest.json +13 -0
- package/.next/build/chunks/33f32_323ea524._.js +6766 -0
- package/.next/build/chunks/33f32_323ea524._.js.map +47 -0
- package/.next/build/chunks/[root-of-the-server]__6ead02f9._.js +500 -0
- package/.next/build/chunks/[root-of-the-server]__6ead02f9._.js.map +11 -0
- package/.next/build/chunks/[root-of-the-server]__777e9116._.js +206 -0
- package/.next/build/chunks/[root-of-the-server]__777e9116._.js.map +8 -0
- package/.next/build/chunks/[turbopack-node]_transforms_postcss_ts_597188b4._.js +13 -0
- package/.next/build/chunks/[turbopack-node]_transforms_postcss_ts_597188b4._.js.map +5 -0
- package/.next/build/chunks/[turbopack]_runtime.js +795 -0
- package/.next/build/chunks/[turbopack]_runtime.js.map +10 -0
- package/.next/build/package.json +1 -0
- package/.next/build/postcss.js +6 -0
- package/.next/build/postcss.js.map +5 -0
- package/.next/build-manifest.json +19 -0
- package/.next/cache/.previewinfo +1 -0
- package/.next/cache/.rscinfo +1 -0
- package/.next/cache/.tsbuildinfo +1 -0
- package/.next/diagnostics/build-diagnostics.json +6 -0
- package/.next/diagnostics/framework.json +1 -0
- package/.next/export-marker.json +6 -0
- package/.next/fallback-build-manifest.json +12 -0
- package/.next/images-manifest.json +67 -0
- package/.next/next-minimal-server.js.nft.json +1 -0
- package/.next/next-server.js.nft.json +1 -0
- package/.next/package.json +1 -0
- package/.next/prerender-manifest.json +114 -0
- package/.next/required-server-files.js +324 -0
- package/.next/required-server-files.json +324 -0
- package/.next/routes-manifest.json +113 -0
- package/.next/server/app/_global-error/page/app-paths-manifest.json +3 -0
- package/.next/server/app/_global-error/page/build-manifest.json +16 -0
- package/.next/server/app/_global-error/page/next-font-manifest.json +6 -0
- package/.next/server/app/_global-error/page/react-loadable-manifest.json +1 -0
- package/.next/server/app/_global-error/page/server-reference-manifest.json +4 -0
- package/.next/server/app/_global-error/page.js +11 -0
- package/.next/server/app/_global-error/page.js.map +5 -0
- package/.next/server/app/_global-error/page.js.nft.json +1 -0
- package/.next/server/app/_global-error/page_client-reference-manifest.js +2 -0
- package/.next/server/app/_global-error.html +2 -0
- package/.next/server/app/_global-error.meta +15 -0
- package/.next/server/app/_global-error.rsc +13 -0
- package/.next/server/app/_global-error.segments/__PAGE__.segment.rsc +5 -0
- package/.next/server/app/_global-error.segments/_full.segment.rsc +13 -0
- package/.next/server/app/_global-error.segments/_head.segment.rsc +6 -0
- package/.next/server/app/_global-error.segments/_index.segment.rsc +4 -0
- package/.next/server/app/_global-error.segments/_tree.segment.rsc +1 -0
- package/.next/server/app/_not-found/page/app-paths-manifest.json +3 -0
- package/.next/server/app/_not-found/page/build-manifest.json +16 -0
- package/.next/server/app/_not-found/page/next-font-manifest.json +11 -0
- package/.next/server/app/_not-found/page/react-loadable-manifest.json +1 -0
- package/.next/server/app/_not-found/page/server-reference-manifest.json +4 -0
- package/.next/server/app/_not-found/page.js +14 -0
- package/.next/server/app/_not-found/page.js.map +5 -0
- package/.next/server/app/_not-found/page.js.nft.json +1 -0
- package/.next/server/app/_not-found/page_client-reference-manifest.js +2 -0
- package/.next/server/app/_not-found.html +1 -0
- package/.next/server/app/_not-found.meta +16 -0
- package/.next/server/app/_not-found.rsc +15 -0
- package/.next/server/app/_not-found.segments/_full.segment.rsc +15 -0
- package/.next/server/app/_not-found.segments/_head.segment.rsc +6 -0
- package/.next/server/app/_not-found.segments/_index.segment.rsc +6 -0
- package/.next/server/app/_not-found.segments/_not-found/__PAGE__.segment.rsc +5 -0
- package/.next/server/app/_not-found.segments/_not-found.segment.rsc +4 -0
- package/.next/server/app/_not-found.segments/_tree.segment.rsc +2 -0
- package/.next/server/app/api/chat/route/app-paths-manifest.json +3 -0
- package/.next/server/app/api/chat/route/build-manifest.json +11 -0
- package/.next/server/app/api/chat/route/server-reference-manifest.json +4 -0
- package/.next/server/app/api/chat/route.js +7 -0
- package/.next/server/app/api/chat/route.js.map +5 -0
- package/.next/server/app/api/chat/route.js.nft.json +1 -0
- package/.next/server/app/api/chat/route_client-reference-manifest.js +2 -0
- package/.next/server/app/api/config/route/app-paths-manifest.json +3 -0
- package/.next/server/app/api/config/route/build-manifest.json +11 -0
- package/.next/server/app/api/config/route/server-reference-manifest.json +4 -0
- package/.next/server/app/api/config/route.js +7 -0
- package/.next/server/app/api/config/route.js.map +5 -0
- package/.next/server/app/api/config/route.js.nft.json +1 -0
- package/.next/server/app/api/config/route_client-reference-manifest.js +2 -0
- package/.next/server/app/api/files/[...path]/route/app-paths-manifest.json +3 -0
- package/.next/server/app/api/files/[...path]/route/build-manifest.json +11 -0
- package/.next/server/app/api/files/[...path]/route/server-reference-manifest.json +4 -0
- package/.next/server/app/api/files/[...path]/route.js +7 -0
- package/.next/server/app/api/files/[...path]/route.js.map +5 -0
- package/.next/server/app/api/files/[...path]/route.js.nft.json +1 -0
- package/.next/server/app/api/files/[...path]/route_client-reference-manifest.js +2 -0
- package/.next/server/app/api/files/route/app-paths-manifest.json +3 -0
- package/.next/server/app/api/files/route/build-manifest.json +11 -0
- package/.next/server/app/api/files/route/server-reference-manifest.json +4 -0
- package/.next/server/app/api/files/route.js +7 -0
- package/.next/server/app/api/files/route.js.map +5 -0
- package/.next/server/app/api/files/route.js.nft.json +1 -0
- package/.next/server/app/api/files/route_client-reference-manifest.js +2 -0
- package/.next/server/app/api/messages/route/app-paths-manifest.json +3 -0
- package/.next/server/app/api/messages/route/build-manifest.json +11 -0
- package/.next/server/app/api/messages/route/server-reference-manifest.json +4 -0
- package/.next/server/app/api/messages/route.js +7 -0
- package/.next/server/app/api/messages/route.js.map +5 -0
- package/.next/server/app/api/messages/route.js.nft.json +1 -0
- package/.next/server/app/api/messages/route_client-reference-manifest.js +2 -0
- package/.next/server/app/api/session/route/app-paths-manifest.json +3 -0
- package/.next/server/app/api/session/route/build-manifest.json +11 -0
- package/.next/server/app/api/session/route/server-reference-manifest.json +4 -0
- package/.next/server/app/api/session/route.js +7 -0
- package/.next/server/app/api/session/route.js.map +5 -0
- package/.next/server/app/api/session/route.js.nft.json +1 -0
- package/.next/server/app/api/session/route_client-reference-manifest.js +2 -0
- package/.next/server/app/api/stream/route/app-paths-manifest.json +3 -0
- package/.next/server/app/api/stream/route/build-manifest.json +11 -0
- package/.next/server/app/api/stream/route/server-reference-manifest.json +4 -0
- package/.next/server/app/api/stream/route.js +6 -0
- package/.next/server/app/api/stream/route.js.map +5 -0
- package/.next/server/app/api/stream/route.js.nft.json +1 -0
- package/.next/server/app/api/stream/route_client-reference-manifest.js +2 -0
- package/.next/server/app/favicon.ico/route/app-paths-manifest.json +3 -0
- package/.next/server/app/favicon.ico/route/build-manifest.json +11 -0
- package/.next/server/app/favicon.ico/route.js +8 -0
- package/.next/server/app/favicon.ico/route.js.map +5 -0
- package/.next/server/app/favicon.ico/route.js.nft.json +1 -0
- package/.next/server/app/favicon.ico.body +0 -0
- package/.next/server/app/favicon.ico.meta +1 -0
- package/.next/server/app/index.html +1 -0
- package/.next/server/app/index.meta +14 -0
- package/.next/server/app/index.rsc +21 -0
- package/.next/server/app/index.segments/__PAGE__.segment.rsc +9 -0
- package/.next/server/app/index.segments/_full.segment.rsc +21 -0
- package/.next/server/app/index.segments/_head.segment.rsc +6 -0
- package/.next/server/app/index.segments/_index.segment.rsc +6 -0
- package/.next/server/app/index.segments/_tree.segment.rsc +4 -0
- package/.next/server/app/page/app-paths-manifest.json +3 -0
- package/.next/server/app/page/build-manifest.json +16 -0
- package/.next/server/app/page/next-font-manifest.json +11 -0
- package/.next/server/app/page/react-loadable-manifest.json +1 -0
- package/.next/server/app/page/server-reference-manifest.json +4 -0
- package/.next/server/app/page.js +16 -0
- package/.next/server/app/page.js.map +5 -0
- package/.next/server/app/page.js.nft.json +1 -0
- package/.next/server/app/page_client-reference-manifest.js +2 -0
- package/.next/server/app-paths-manifest.json +13 -0
- package/.next/server/chunks/33f32_next_b78429d5._.js +17 -0
- package/.next/server/chunks/33f32_next_b78429d5._.js.map +1 -0
- package/.next/server/chunks/33f32_next_dist_esm_build_templates_app-route_5a539e27.js +3 -0
- package/.next/server/chunks/33f32_next_dist_esm_build_templates_app-route_5a539e27.js.map +1 -0
- package/.next/server/chunks/[externals]_next_dist_b89b5a39._.js +3 -0
- package/.next/server/chunks/[externals]_next_dist_b89b5a39._.js.map +1 -0
- package/.next/server/chunks/[root-of-the-server]__2554f0b0._.js +17 -0
- package/.next/server/chunks/[root-of-the-server]__2554f0b0._.js.map +1 -0
- package/.next/server/chunks/[root-of-the-server]__5e671cad._.js +7 -0
- package/.next/server/chunks/[root-of-the-server]__5e671cad._.js.map +1 -0
- package/.next/server/chunks/[root-of-the-server]__629f5815._.js +3 -0
- package/.next/server/chunks/[root-of-the-server]__629f5815._.js.map +1 -0
- package/.next/server/chunks/[root-of-the-server]__633f9ccd._.js +3 -0
- package/.next/server/chunks/[root-of-the-server]__633f9ccd._.js.map +1 -0
- package/.next/server/chunks/[root-of-the-server]__65cdeb73._.js +17 -0
- package/.next/server/chunks/[root-of-the-server]__65cdeb73._.js.map +1 -0
- package/.next/server/chunks/[root-of-the-server]__bc57ef5b._.js +21 -0
- package/.next/server/chunks/[root-of-the-server]__bc57ef5b._.js.map +1 -0
- package/.next/server/chunks/[root-of-the-server]__be62c218._.js +17 -0
- package/.next/server/chunks/[root-of-the-server]__be62c218._.js.map +1 -0
- package/.next/server/chunks/[root-of-the-server]__e87dbf93._.js +3 -0
- package/.next/server/chunks/[root-of-the-server]__e87dbf93._.js.map +1 -0
- package/.next/server/chunks/[turbopack]_runtime.js +795 -0
- package/.next/server/chunks/[turbopack]_runtime.js.map +10 -0
- package/.next/server/chunks/c45a0_nextpi__next-internal_server_app_api_files_[___path]_route_actions_16a66e62.js +3 -0
- package/.next/server/chunks/c45a0_nextpi__next-internal_server_app_api_files_[___path]_route_actions_16a66e62.js.map +1 -0
- package/.next/server/chunks/picode_nextpi__next-internal_server_app_api_chat_route_actions_e342cdbf.js +3 -0
- package/.next/server/chunks/picode_nextpi__next-internal_server_app_api_chat_route_actions_e342cdbf.js.map +1 -0
- package/.next/server/chunks/picode_nextpi__next-internal_server_app_api_config_route_actions_04d1272c.js +3 -0
- package/.next/server/chunks/picode_nextpi__next-internal_server_app_api_config_route_actions_04d1272c.js.map +1 -0
- package/.next/server/chunks/picode_nextpi__next-internal_server_app_api_files_route_actions_a8035013.js +3 -0
- package/.next/server/chunks/picode_nextpi__next-internal_server_app_api_files_route_actions_a8035013.js.map +1 -0
- package/.next/server/chunks/picode_nextpi__next-internal_server_app_api_messages_route_actions_4f52ac4b.js +3 -0
- package/.next/server/chunks/picode_nextpi__next-internal_server_app_api_messages_route_actions_4f52ac4b.js.map +1 -0
- package/.next/server/chunks/picode_nextpi__next-internal_server_app_api_session_route_actions_ff684c69.js +3 -0
- package/.next/server/chunks/picode_nextpi__next-internal_server_app_api_session_route_actions_ff684c69.js.map +1 -0
- package/.next/server/chunks/picode_nextpi__next-internal_server_app_api_stream_route_actions_7a0f6dba.js +3 -0
- package/.next/server/chunks/picode_nextpi__next-internal_server_app_api_stream_route_actions_7a0f6dba.js.map +1 -0
- package/.next/server/chunks/picode_nextpi__next-internal_server_app_favicon_ico_route_actions_2526216f.js +3 -0
- package/.next/server/chunks/picode_nextpi__next-internal_server_app_favicon_ico_route_actions_2526216f.js.map +1 -0
- package/.next/server/chunks/ssr/33f32_next_dist_580d3573._.js +6 -0
- package/.next/server/chunks/ssr/33f32_next_dist_580d3573._.js.map +1 -0
- package/.next/server/chunks/ssr/33f32_next_dist_85b0ccc0._.js +4 -0
- package/.next/server/chunks/ssr/33f32_next_dist_85b0ccc0._.js.map +1 -0
- package/.next/server/chunks/ssr/33f32_next_dist_client_components_a8ffe8d4._.js +3 -0
- package/.next/server/chunks/ssr/33f32_next_dist_client_components_a8ffe8d4._.js.map +1 -0
- package/.next/server/chunks/ssr/33f32_next_dist_client_components_builtin_forbidden_ad97660b.js +3 -0
- package/.next/server/chunks/ssr/33f32_next_dist_client_components_builtin_forbidden_ad97660b.js.map +1 -0
- package/.next/server/chunks/ssr/33f32_next_dist_client_components_builtin_global-error_ab28468b.js +3 -0
- package/.next/server/chunks/ssr/33f32_next_dist_client_components_builtin_global-error_ab28468b.js.map +1 -0
- package/.next/server/chunks/ssr/33f32_next_dist_client_components_builtin_unauthorized_edd1fe08.js +3 -0
- package/.next/server/chunks/ssr/33f32_next_dist_client_components_builtin_unauthorized_edd1fe08.js.map +1 -0
- package/.next/server/chunks/ssr/33f32_next_dist_esm_build_templates_app-page_5ef96b51.js +4 -0
- package/.next/server/chunks/ssr/33f32_next_dist_esm_build_templates_app-page_5ef96b51.js.map +1 -0
- package/.next/server/chunks/ssr/33f32_next_dist_server_route-modules_app-page_vendored_ssr_react-dom_33aeae20.js +3 -0
- package/.next/server/chunks/ssr/33f32_next_dist_server_route-modules_app-page_vendored_ssr_react-dom_33aeae20.js.map +1 -0
- package/.next/server/chunks/ssr/[root-of-the-server]__028106ef._.js +3 -0
- package/.next/server/chunks/ssr/[root-of-the-server]__028106ef._.js.map +1 -0
- package/.next/server/chunks/ssr/[root-of-the-server]__0dc9a9e1._.js +4 -0
- package/.next/server/chunks/ssr/[root-of-the-server]__0dc9a9e1._.js.map +1 -0
- package/.next/server/chunks/ssr/[root-of-the-server]__15f57d5d._.js +3 -0
- package/.next/server/chunks/ssr/[root-of-the-server]__15f57d5d._.js.map +1 -0
- package/.next/server/chunks/ssr/[root-of-the-server]__26f2451b._.js +3 -0
- package/.next/server/chunks/ssr/[root-of-the-server]__26f2451b._.js.map +1 -0
- package/.next/server/chunks/ssr/[root-of-the-server]__42ddc417._.js +3 -0
- package/.next/server/chunks/ssr/[root-of-the-server]__42ddc417._.js.map +1 -0
- package/.next/server/chunks/ssr/[root-of-the-server]__6823e2d4._.js +3 -0
- package/.next/server/chunks/ssr/[root-of-the-server]__6823e2d4._.js.map +1 -0
- package/.next/server/chunks/ssr/[root-of-the-server]__6bf5dd5d._.js +3 -0
- package/.next/server/chunks/ssr/[root-of-the-server]__6bf5dd5d._.js.map +1 -0
- package/.next/server/chunks/ssr/[root-of-the-server]__7b7d477c._.js +10 -0
- package/.next/server/chunks/ssr/[root-of-the-server]__7b7d477c._.js.map +1 -0
- package/.next/server/chunks/ssr/[root-of-the-server]__85c46341._.js +3 -0
- package/.next/server/chunks/ssr/[root-of-the-server]__85c46341._.js.map +1 -0
- package/.next/server/chunks/ssr/[root-of-the-server]__99c61367._.js +3 -0
- package/.next/server/chunks/ssr/[root-of-the-server]__99c61367._.js.map +1 -0
- package/.next/server/chunks/ssr/[root-of-the-server]__a0bdeac8._.js +3 -0
- package/.next/server/chunks/ssr/[root-of-the-server]__a0bdeac8._.js.map +1 -0
- package/.next/server/chunks/ssr/[turbopack]_runtime.js +795 -0
- package/.next/server/chunks/ssr/[turbopack]_runtime.js.map +10 -0
- package/.next/server/chunks/ssr/_091ac666._.js +3 -0
- package/.next/server/chunks/ssr/_091ac666._.js.map +1 -0
- package/.next/server/chunks/ssr/picode_nextpi_1e69e558._.js +4 -0
- package/.next/server/chunks/ssr/picode_nextpi_1e69e558._.js.map +1 -0
- package/.next/server/chunks/ssr/picode_nextpi_4fadcd01._.js +3 -0
- package/.next/server/chunks/ssr/picode_nextpi_4fadcd01._.js.map +1 -0
- package/.next/server/chunks/ssr/picode_nextpi__next-internal_server_app__global-error_page_actions_91eb1cf1.js +3 -0
- package/.next/server/chunks/ssr/picode_nextpi__next-internal_server_app__global-error_page_actions_91eb1cf1.js.map +1 -0
- package/.next/server/chunks/ssr/picode_nextpi__next-internal_server_app__not-found_page_actions_0a31df41.js +3 -0
- package/.next/server/chunks/ssr/picode_nextpi__next-internal_server_app__not-found_page_actions_0a31df41.js.map +1 -0
- package/.next/server/chunks/ssr/picode_nextpi__next-internal_server_app_page_actions_b14d985f.js +3 -0
- package/.next/server/chunks/ssr/picode_nextpi__next-internal_server_app_page_actions_b14d985f.js.map +1 -0
- package/.next/server/chunks/ssr/picode_nextpi_app_77d1bd95._.js +3 -0
- package/.next/server/chunks/ssr/picode_nextpi_app_77d1bd95._.js.map +1 -0
- package/.next/server/chunks/ssr/picode_nextpi_app_page_tsx_cebd7814._.js +3 -0
- package/.next/server/chunks/ssr/picode_nextpi_app_page_tsx_cebd7814._.js.map +1 -0
- package/.next/server/functions-config-manifest.json +4 -0
- package/.next/server/interception-route-rewrite-manifest.js +1 -0
- package/.next/server/middleware-build-manifest.js +20 -0
- package/.next/server/middleware-manifest.json +6 -0
- package/.next/server/next-font-manifest.js +1 -0
- package/.next/server/next-font-manifest.json +15 -0
- package/.next/server/pages/404.html +1 -0
- package/.next/server/pages/500.html +2 -0
- package/.next/server/pages-manifest.json +4 -0
- package/.next/server/server-reference-manifest.js +1 -0
- package/.next/server/server-reference-manifest.json +5 -0
- package/.next/static/PdRtiPZ_ExBLCzmKGXOBT/_buildManifest.js +11 -0
- package/.next/static/PdRtiPZ_ExBLCzmKGXOBT/_clientMiddlewareManifest.json +1 -0
- package/.next/static/PdRtiPZ_ExBLCzmKGXOBT/_ssgManifest.js +1 -0
- package/.next/static/chunks/0ab43a45e07af0f9.js +1 -0
- package/.next/static/chunks/265e06106152dcbb.js +1 -0
- package/.next/static/chunks/65d5124f3edd1b84.js +1 -0
- package/.next/static/chunks/76111d9b2044b643.js +1 -0
- package/.next/static/chunks/81dfdd74986c8afe.css +3 -0
- package/.next/static/chunks/93b85e5de0842835.js +5 -0
- package/.next/static/chunks/a6dad97d9634a72d.js +1 -0
- package/.next/static/chunks/a6dad97d9634a72d.js.map +1 -0
- package/.next/static/chunks/cace1b477872431f.js +1 -0
- package/.next/static/chunks/turbopack-775e95d747b6e667.js +4 -0
- package/.next/static/media/4fa387ec64143e14-s.c1fdd6c2.woff2 +0 -0
- package/.next/static/media/7178b3e590c64307-s.b97b3418.woff2 +0 -0
- package/.next/static/media/797e433ab948586e-s.p.dbea232f.woff2 +0 -0
- package/.next/static/media/8a480f0b521d4e75-s.8e0177b5.woff2 +0 -0
- package/.next/static/media/bbc41e54d2fcbd21-s.799d8ef8.woff2 +0 -0
- package/.next/static/media/caa3a2e1cccd8315-s.p.853070df.woff2 +0 -0
- package/.next/static/media/favicon.0b3bf435.ico +0 -0
- package/.next/trace +1 -0
- package/.next/trace-build +1 -0
- package/.next/turbopack +0 -0
- package/.next/types/routes.d.ts +79 -0
- package/.next/types/validator.ts +133 -0
- package/README.md +50 -0
- package/app/api/chat/route.ts +28 -0
- package/app/api/config/route.ts +25 -0
- package/app/api/files/[...path]/route.ts +55 -0
- package/app/api/files/route.ts +62 -0
- package/app/api/messages/route.ts +26 -0
- package/app/api/session/route.ts +55 -0
- package/app/api/stream/route.ts +76 -0
- package/app/favicon.ico +0 -0
- package/app/globals.css +1143 -0
- package/app/layout.tsx +46 -0
- package/app/page.tsx +1643 -0
- package/bin/cli.js +85 -0
- package/components/.gitkeep +0 -0
- package/components/theme-provider.tsx +71 -0
- package/components/ui/button.tsx +67 -0
- package/components/ui/file-tree.tsx +560 -0
- package/lib/.gitkeep +0 -0
- package/lib/agent.ts +105 -0
- package/lib/config.ts +50 -0
- package/lib/root-path.ts +15 -0
- package/lib/session-singleton.ts +48 -0
- package/lib/utils.ts +6 -0
- package/package.json +72 -0
- package/public/.gitkeep +0 -0
- package/src/agent.ts +82 -0
- package/src/cli.ts +107 -0
- package/src/tools.ts +71 -0
- package/src/tui.ts +238 -0
- package/src/web-server.ts +280 -0
- package/tsconfig.json +34 -0
package/lib/root-path.ts
ADDED
|
@@ -0,0 +1,15 @@
|
|
|
1
|
+
import path from 'path';
|
|
2
|
+
|
|
3
|
+
export function getProjectRoot() {
|
|
4
|
+
// PI_ROOT can be set via environment variable to override the root directory
|
|
5
|
+
const envRoot = process.env.PI_ROOT;
|
|
6
|
+
|
|
7
|
+
if (envRoot) {
|
|
8
|
+
// Resolve the path to handle relative paths from where the process was started
|
|
9
|
+
return path.resolve(envRoot);
|
|
10
|
+
}
|
|
11
|
+
|
|
12
|
+
// If no PI_ROOT is set, fallback to process.cwd()
|
|
13
|
+
// Note: in a Next.js environment during dev/build, process.cwd() is the project root.
|
|
14
|
+
return process.cwd();
|
|
15
|
+
}
|
|
@@ -0,0 +1,48 @@
|
|
|
1
|
+
import { createResearchAgent } from '@/lib/agent';
|
|
2
|
+
|
|
3
|
+
type AgentSession = Awaited<ReturnType<typeof createResearchAgent>>;
|
|
4
|
+
|
|
5
|
+
/**
|
|
6
|
+
* In Next.js development mode, modules are frequently re-evaluated due to HMR.
|
|
7
|
+
* Attaching the session to `globalThis` ensures that all API routes (which may
|
|
8
|
+
* be running in different contexts or re-evaluated modules) share exactly
|
|
9
|
+
* the same AgentSession instance.
|
|
10
|
+
*/
|
|
11
|
+
const globalForAgent = globalThis as unknown as {
|
|
12
|
+
_sharedSession?: AgentSession;
|
|
13
|
+
_sharedSessionPromise?: Promise<AgentSession>;
|
|
14
|
+
};
|
|
15
|
+
|
|
16
|
+
let currentModelId: string | undefined = undefined;
|
|
17
|
+
|
|
18
|
+
export async function getSharedSession(): Promise<AgentSession> {
|
|
19
|
+
// Return the existing session if already initialized
|
|
20
|
+
if (globalForAgent._sharedSession) {
|
|
21
|
+
return globalForAgent._sharedSession;
|
|
22
|
+
}
|
|
23
|
+
|
|
24
|
+
// If a session is being created, wait for it
|
|
25
|
+
if (globalForAgent._sharedSessionPromise) {
|
|
26
|
+
return globalForAgent._sharedSessionPromise;
|
|
27
|
+
}
|
|
28
|
+
|
|
29
|
+
// Otherwise, create a new session and store the promise globally
|
|
30
|
+
console.log(`[Agent] Initializing new shared session singleton (Model: ${currentModelId || 'default'})...`);
|
|
31
|
+
globalForAgent._sharedSessionPromise = createResearchAgent({ modelId: currentModelId }).then((session) => {
|
|
32
|
+
globalForAgent._sharedSession = session;
|
|
33
|
+
console.log('[Agent] Shared session initialized');
|
|
34
|
+
return session;
|
|
35
|
+
});
|
|
36
|
+
|
|
37
|
+
return globalForAgent._sharedSessionPromise;
|
|
38
|
+
}
|
|
39
|
+
|
|
40
|
+
export function resetSharedSession(modelId?: string): void {
|
|
41
|
+
console.log(`[Agent] Resetting shared session${modelId ? ` to model ${modelId}` : ''}...`);
|
|
42
|
+
if (modelId) {
|
|
43
|
+
currentModelId = modelId;
|
|
44
|
+
}
|
|
45
|
+
globalForAgent._sharedSession = undefined;
|
|
46
|
+
globalForAgent._sharedSessionPromise = undefined;
|
|
47
|
+
}
|
|
48
|
+
|
package/lib/utils.ts
ADDED
package/package.json
ADDED
|
@@ -0,0 +1,72 @@
|
|
|
1
|
+
{
|
|
2
|
+
"name": "@drewsepsi/nextpi",
|
|
3
|
+
"version": "0.1.0",
|
|
4
|
+
"description": "The Agentic IDE - An AI-powered research and coding assistant workspace.",
|
|
5
|
+
"type": "module",
|
|
6
|
+
"bin": {
|
|
7
|
+
"nextpi": "./bin/cli.js"
|
|
8
|
+
},
|
|
9
|
+
"files": [
|
|
10
|
+
"bin",
|
|
11
|
+
"app",
|
|
12
|
+
"components",
|
|
13
|
+
"lib",
|
|
14
|
+
"public",
|
|
15
|
+
"src",
|
|
16
|
+
"styles",
|
|
17
|
+
".next",
|
|
18
|
+
"next.config.js",
|
|
19
|
+
"package.json",
|
|
20
|
+
"tsconfig.json",
|
|
21
|
+
"README.md"
|
|
22
|
+
],
|
|
23
|
+
"keywords": [
|
|
24
|
+
"ai",
|
|
25
|
+
"agent",
|
|
26
|
+
"ide",
|
|
27
|
+
"coding",
|
|
28
|
+
"research",
|
|
29
|
+
"nextjs",
|
|
30
|
+
"nextpi"
|
|
31
|
+
],
|
|
32
|
+
"author": "Drew Sepeczi",
|
|
33
|
+
"license": "MIT",
|
|
34
|
+
"scripts": {
|
|
35
|
+
"dev": "next dev --turbopack",
|
|
36
|
+
"build": "next build",
|
|
37
|
+
"start": "next start",
|
|
38
|
+
"lint": "eslint",
|
|
39
|
+
"format": "prettier --write \"**/*.{ts,tsx}\"",
|
|
40
|
+
"typecheck": "tsc --noEmit"
|
|
41
|
+
},
|
|
42
|
+
"dependencies": {
|
|
43
|
+
"@mariozechner/pi-ai": "^0.66.1",
|
|
44
|
+
"@mariozechner/pi-coding-agent": "^0.66.1",
|
|
45
|
+
"@radix-ui/react-accordion": "^1.2.12",
|
|
46
|
+
"class-variance-authority": "^0.7.1",
|
|
47
|
+
"clsx": "^2.1.1",
|
|
48
|
+
"lucide-react": "^1.8.0",
|
|
49
|
+
"next": "16.1.7",
|
|
50
|
+
"next-themes": "^0.4.6",
|
|
51
|
+
"radix-ui": "^1.4.3",
|
|
52
|
+
"react": "^19.2.4",
|
|
53
|
+
"react-dom": "^19.2.4",
|
|
54
|
+
"shadcn": "^4.2.0",
|
|
55
|
+
"tailwind-merge": "^3.5.0",
|
|
56
|
+
"tw-animate-css": "^1.4.0"
|
|
57
|
+
},
|
|
58
|
+
"devDependencies": {
|
|
59
|
+
"@eslint/eslintrc": "^3",
|
|
60
|
+
"@tailwindcss/postcss": "^4.2.1",
|
|
61
|
+
"@types/node": "^25.5.0",
|
|
62
|
+
"@types/react": "^19.2.14",
|
|
63
|
+
"@types/react-dom": "^19.2.3",
|
|
64
|
+
"eslint": "^9.39.4",
|
|
65
|
+
"eslint-config-next": "16.1.7",
|
|
66
|
+
"prettier": "^3.8.1",
|
|
67
|
+
"prettier-plugin-tailwindcss": "^0.7.2",
|
|
68
|
+
"postcss": "^8",
|
|
69
|
+
"tailwindcss": "^4.2.1",
|
|
70
|
+
"typescript": "^5.9.3"
|
|
71
|
+
}
|
|
72
|
+
}
|
package/public/.gitkeep
ADDED
|
File without changes
|
package/src/agent.ts
ADDED
|
@@ -0,0 +1,82 @@
|
|
|
1
|
+
import {
|
|
2
|
+
createAgentSession,
|
|
3
|
+
SessionManager,
|
|
4
|
+
type AgentSession
|
|
5
|
+
} from "@mariozechner/pi-coding-agent";
|
|
6
|
+
import { getModel, streamSimple } from "@mariozechner/pi-ai";
|
|
7
|
+
import { researchTools } from "./tools.js";
|
|
8
|
+
import * as path from "path";
|
|
9
|
+
import * as fs from "fs";
|
|
10
|
+
import { getProjectRoot } from "../lib/root-path";
|
|
11
|
+
|
|
12
|
+
export interface ResearchAgentConfig {
|
|
13
|
+
sessionDir?: string;
|
|
14
|
+
sessionFile?: string;
|
|
15
|
+
modelId?: string & {};
|
|
16
|
+
thinkingLevel?: "off" | "minimal" | "low" | "medium" | "high" | "xhigh";
|
|
17
|
+
}
|
|
18
|
+
|
|
19
|
+
// Default OpenRouter model - Free tier
|
|
20
|
+
const DEFAULT_MODEL = "openrouter/free";
|
|
21
|
+
|
|
22
|
+
export async function createResearchAgent(
|
|
23
|
+
config: ResearchAgentConfig = {}
|
|
24
|
+
): Promise<AgentSession> {
|
|
25
|
+
const {
|
|
26
|
+
sessionDir = path.join(getProjectRoot(), ".sessions"),
|
|
27
|
+
sessionFile = path.join(sessionDir, "research-agent.jsonl"),
|
|
28
|
+
modelId = DEFAULT_MODEL,
|
|
29
|
+
thinkingLevel = "off",
|
|
30
|
+
} = config;
|
|
31
|
+
|
|
32
|
+
// Ensure session directory exists
|
|
33
|
+
fs.mkdirSync(sessionDir, { recursive: true });
|
|
34
|
+
|
|
35
|
+
// Use OpenRouter model
|
|
36
|
+
const model = getModel("openrouter", modelId as "openrouter/free");
|
|
37
|
+
|
|
38
|
+
// Create session with research tools
|
|
39
|
+
const { session } = await createAgentSession({
|
|
40
|
+
model,
|
|
41
|
+
thinkingLevel,
|
|
42
|
+
sessionManager: SessionManager.open(sessionFile),
|
|
43
|
+
customTools: researchTools,
|
|
44
|
+
});
|
|
45
|
+
|
|
46
|
+
// Wrap stream function with OpenRouter headers
|
|
47
|
+
const originalStreamFn = session.agent.streamFn;
|
|
48
|
+
session.agent.streamFn = (model, context, options) => {
|
|
49
|
+
return streamSimple(model, context, {
|
|
50
|
+
...options,
|
|
51
|
+
headers: {
|
|
52
|
+
...options?.headers,
|
|
53
|
+
"X-Title": "NextPi Agent",
|
|
54
|
+
"HTTP-Referer": "https://github.com/drewsepsi/nextpi",
|
|
55
|
+
},
|
|
56
|
+
});
|
|
57
|
+
};
|
|
58
|
+
|
|
59
|
+
return session;
|
|
60
|
+
}
|
|
61
|
+
|
|
62
|
+
// System prompt for research and coding
|
|
63
|
+
export const RESEARCH_SYSTEM_PROMPT = `You are NextPi, a research and coding assistant with access to web search and code editing tools.
|
|
64
|
+
|
|
65
|
+
Your capabilities:
|
|
66
|
+
1. **Web Search**: Search the web for documentation, error messages, news, or general information
|
|
67
|
+
2. **Web Fetch**: Extract content from specific URLs for deeper reading
|
|
68
|
+
3. **File Operations**: Read, write, and edit files in the workspace
|
|
69
|
+
4. **Shell Commands**: Execute bash commands for testing, building, or exploring
|
|
70
|
+
|
|
71
|
+
When researching:
|
|
72
|
+
- Start with web_search to find relevant information
|
|
73
|
+
- Use web_fetch to read specific documentation pages
|
|
74
|
+
- Summarize findings concisely with citations
|
|
75
|
+
|
|
76
|
+
When coding:
|
|
77
|
+
- Read existing files before making changes
|
|
78
|
+
- Make surgical edits using the edit tool
|
|
79
|
+
- Test changes with bash commands when appropriate
|
|
80
|
+
- Explain your reasoning for significant changes
|
|
81
|
+
|
|
82
|
+
Always be helpful, accurate, and efficient.`;
|
package/src/cli.ts
ADDED
|
@@ -0,0 +1,107 @@
|
|
|
1
|
+
#!/usr/bin/env node
|
|
2
|
+
import { createResearchAgent, RESEARCH_SYSTEM_PROMPT } from "./agent.js";
|
|
3
|
+
import { estimateTokens } from "@mariozechner/pi-coding-agent";
|
|
4
|
+
import * as readline from "readline";
|
|
5
|
+
|
|
6
|
+
function summarizeArgs(args: any): string {
|
|
7
|
+
if (args?.path) return args.path;
|
|
8
|
+
if (args?.command) return args.command.slice(0, 60);
|
|
9
|
+
if (args?.query) return `"${args.query}"`;
|
|
10
|
+
if (args?.url) return args.url;
|
|
11
|
+
if (args?.pattern) return args.pattern;
|
|
12
|
+
return JSON.stringify(args).slice(0, 60);
|
|
13
|
+
}
|
|
14
|
+
|
|
15
|
+
async function main() {
|
|
16
|
+
// Check for OpenRouter API key
|
|
17
|
+
if (!process.env.OPENROUTER_API_KEY) {
|
|
18
|
+
console.error("Error: OPENROUTER_API_KEY environment variable is required");
|
|
19
|
+
console.error("Set it with: export OPENROUTER_API_KEY=sk-or-v1-...");
|
|
20
|
+
process.exit(1);
|
|
21
|
+
}
|
|
22
|
+
|
|
23
|
+
console.log("[NextPi] CLI Mode");
|
|
24
|
+
console.log("");
|
|
25
|
+
|
|
26
|
+
const session = await createResearchAgent();
|
|
27
|
+
|
|
28
|
+
// Attach event handlers
|
|
29
|
+
session.subscribe((event) => {
|
|
30
|
+
switch (event.type) {
|
|
31
|
+
case "message_update":
|
|
32
|
+
if (event.assistantMessageEvent.type === "text_delta") {
|
|
33
|
+
process.stdout.write(event.assistantMessageEvent.delta);
|
|
34
|
+
}
|
|
35
|
+
break;
|
|
36
|
+
|
|
37
|
+
case "tool_execution_start":
|
|
38
|
+
console.log(`\n [${event.toolName}] ${summarizeArgs(event.args)}`);
|
|
39
|
+
break;
|
|
40
|
+
|
|
41
|
+
case "tool_execution_end":
|
|
42
|
+
if (event.isError) {
|
|
43
|
+
console.log(` [Error]`);
|
|
44
|
+
} else {
|
|
45
|
+
console.log(` [Done]`);
|
|
46
|
+
}
|
|
47
|
+
break;
|
|
48
|
+
|
|
49
|
+
case "compaction_start":
|
|
50
|
+
console.log("\n [Compacting context...]");
|
|
51
|
+
break;
|
|
52
|
+
|
|
53
|
+
case "agent_end":
|
|
54
|
+
console.log("\n");
|
|
55
|
+
break;
|
|
56
|
+
}
|
|
57
|
+
});
|
|
58
|
+
|
|
59
|
+
// Display session info
|
|
60
|
+
const tokenCount = session.messages.reduce((sum, msg) => sum + estimateTokens(msg), 0);
|
|
61
|
+
console.log(`Model: ${session.model?.id}`);
|
|
62
|
+
console.log(`History: ${session.messages.length} messages, ~${tokenCount} tokens`);
|
|
63
|
+
console.log(`Tools: ${session.getActiveToolNames().join(", ")}`);
|
|
64
|
+
console.log(`Commands: "exit" to quit, "new" to reset session\n`);
|
|
65
|
+
|
|
66
|
+
// REPL
|
|
67
|
+
const rl = readline.createInterface({ input: process.stdin, output: process.stdout });
|
|
68
|
+
|
|
69
|
+
const ask = () => {
|
|
70
|
+
rl.question("You: ", async (input) => {
|
|
71
|
+
const trimmed = input.trim();
|
|
72
|
+
|
|
73
|
+
if (trimmed === "exit" || trimmed === "quit") {
|
|
74
|
+
session.dispose();
|
|
75
|
+
rl.close();
|
|
76
|
+
return;
|
|
77
|
+
}
|
|
78
|
+
|
|
79
|
+
if (trimmed === "new") {
|
|
80
|
+
session.sessionManager.newSession();
|
|
81
|
+
console.log("Session reset.\n");
|
|
82
|
+
ask();
|
|
83
|
+
return;
|
|
84
|
+
}
|
|
85
|
+
|
|
86
|
+
if (!trimmed) {
|
|
87
|
+
ask();
|
|
88
|
+
return;
|
|
89
|
+
}
|
|
90
|
+
|
|
91
|
+
try {
|
|
92
|
+
await session.prompt(trimmed);
|
|
93
|
+
} catch (err: any) {
|
|
94
|
+
console.error(`\n[Error] ${err.message}`);
|
|
95
|
+
}
|
|
96
|
+
|
|
97
|
+
ask();
|
|
98
|
+
});
|
|
99
|
+
};
|
|
100
|
+
|
|
101
|
+
ask();
|
|
102
|
+
}
|
|
103
|
+
|
|
104
|
+
main().catch((err) => {
|
|
105
|
+
console.error("Fatal error:", err);
|
|
106
|
+
process.exit(1);
|
|
107
|
+
});
|
package/src/tools.ts
ADDED
|
@@ -0,0 +1,71 @@
|
|
|
1
|
+
import { Type } from "@mariozechner/pi-ai";
|
|
2
|
+
import type { AgentTool } from "@mariozechner/pi-agent-core";
|
|
3
|
+
|
|
4
|
+
// Web search parameters
|
|
5
|
+
const webSearchParams = Type.Object({
|
|
6
|
+
query: Type.String({ description: "Search query to find information on the web" }),
|
|
7
|
+
numResults: Type.Number({ description: "Number of results to return (1-10)", default: 5 }),
|
|
8
|
+
});
|
|
9
|
+
|
|
10
|
+
// Web fetch parameters
|
|
11
|
+
const webFetchParams = Type.Object({
|
|
12
|
+
url: Type.String({ description: "URL to fetch content from" }),
|
|
13
|
+
maxCharacters: Type.Number({ description: "Maximum characters to extract", default: 3000 }),
|
|
14
|
+
});
|
|
15
|
+
|
|
16
|
+
// Web search tool - uses Exa MCP
|
|
17
|
+
export const webSearchTool: AgentTool<typeof webSearchParams> = {
|
|
18
|
+
name: "web_search",
|
|
19
|
+
label: "Web Search",
|
|
20
|
+
description: "Search the web for documentation, error messages, news, or general information using Exa AI",
|
|
21
|
+
parameters: webSearchParams,
|
|
22
|
+
execute: async (_id, params) => {
|
|
23
|
+
try {
|
|
24
|
+
// Use the exa MCP tool via the tools.call mechanism
|
|
25
|
+
// The MCP server handles the actual API call
|
|
26
|
+
const { query, numResults = 5 } = params;
|
|
27
|
+
|
|
28
|
+
return {
|
|
29
|
+
content: [{
|
|
30
|
+
type: "text",
|
|
31
|
+
text: `Web search for "${query}" would return ${numResults} results.\n\nNote: This tool requires the Exa MCP server to be running. Connect via the MCP client to enable live web search.`
|
|
32
|
+
}],
|
|
33
|
+
details: { query, numResults, simulated: true },
|
|
34
|
+
};
|
|
35
|
+
} catch (err: any) {
|
|
36
|
+
return {
|
|
37
|
+
content: [{ type: "text", text: `Error searching web: ${err.message}` }],
|
|
38
|
+
details: { error: err.message },
|
|
39
|
+
};
|
|
40
|
+
}
|
|
41
|
+
},
|
|
42
|
+
};
|
|
43
|
+
|
|
44
|
+
// Web fetch tool - fetch content from specific URLs
|
|
45
|
+
export const webFetchTool: AgentTool<typeof webFetchParams> = {
|
|
46
|
+
name: "web_fetch",
|
|
47
|
+
label: "Web Fetch",
|
|
48
|
+
description: "Fetch and extract content from a specific URL for deeper reading",
|
|
49
|
+
parameters: webFetchParams,
|
|
50
|
+
execute: async (_id, params) => {
|
|
51
|
+
try {
|
|
52
|
+
const { url, maxCharacters = 3000 } = params;
|
|
53
|
+
|
|
54
|
+
return {
|
|
55
|
+
content: [{
|
|
56
|
+
type: "text",
|
|
57
|
+
text: `Content from ${url} would be extracted here (max ${maxCharacters} chars).\n\nNote: This tool requires the Exa MCP server to be running.`
|
|
58
|
+
}],
|
|
59
|
+
details: { url, maxCharacters, simulated: true },
|
|
60
|
+
};
|
|
61
|
+
} catch (err: any) {
|
|
62
|
+
return {
|
|
63
|
+
content: [{ type: "text", text: `Error fetching URL: ${err.message}` }],
|
|
64
|
+
details: { error: err.message },
|
|
65
|
+
};
|
|
66
|
+
}
|
|
67
|
+
},
|
|
68
|
+
};
|
|
69
|
+
|
|
70
|
+
// Combined research tools array
|
|
71
|
+
export const researchTools = [webSearchTool, webFetchTool];
|
package/src/tui.ts
ADDED
|
@@ -0,0 +1,238 @@
|
|
|
1
|
+
#!/usr/bin/env node
|
|
2
|
+
import { createResearchAgent } from "./agent.js";
|
|
3
|
+
import { estimateTokens } from "@mariozechner/pi-coding-agent";
|
|
4
|
+
import {
|
|
5
|
+
TUI,
|
|
6
|
+
ProcessTerminal,
|
|
7
|
+
Editor,
|
|
8
|
+
Markdown,
|
|
9
|
+
Text,
|
|
10
|
+
Loader,
|
|
11
|
+
CombinedAutocompleteProvider,
|
|
12
|
+
Box,
|
|
13
|
+
Container,
|
|
14
|
+
} from "@mariozechner/pi-tui";
|
|
15
|
+
import type { EditorTheme, MarkdownTheme } from "@mariozechner/pi-tui";
|
|
16
|
+
import chalk from "chalk";
|
|
17
|
+
|
|
18
|
+
// --- Themes ---
|
|
19
|
+
const markdownTheme: MarkdownTheme = {
|
|
20
|
+
heading: (s) => chalk.bold.cyan(s),
|
|
21
|
+
link: (s) => chalk.blue(s),
|
|
22
|
+
linkUrl: (s) => chalk.dim(s),
|
|
23
|
+
code: (s) => chalk.yellow(s),
|
|
24
|
+
codeBlock: (s) => chalk.green(s),
|
|
25
|
+
codeBlockBorder: (s) => chalk.dim(s),
|
|
26
|
+
quote: (s) => chalk.italic(s),
|
|
27
|
+
quoteBorder: (s) => chalk.dim(s),
|
|
28
|
+
hr: (s) => chalk.dim(s),
|
|
29
|
+
listBullet: (s) => chalk.cyan(s),
|
|
30
|
+
bold: (s) => chalk.bold(s),
|
|
31
|
+
italic: (s) => chalk.italic(s),
|
|
32
|
+
strikethrough: (s) => chalk.strikethrough(s),
|
|
33
|
+
underline: (s) => chalk.underline(s),
|
|
34
|
+
};
|
|
35
|
+
|
|
36
|
+
const editorTheme: EditorTheme = {
|
|
37
|
+
borderColor: (s) => chalk.dim(s),
|
|
38
|
+
selectList: {
|
|
39
|
+
selectedPrefix: (s) => chalk.blue(s),
|
|
40
|
+
selectedText: (s) => chalk.bold(s),
|
|
41
|
+
description: (s) => chalk.dim(s),
|
|
42
|
+
scrollInfo: (s) => chalk.dim(s),
|
|
43
|
+
noMatch: (s) => chalk.dim(s),
|
|
44
|
+
},
|
|
45
|
+
};
|
|
46
|
+
|
|
47
|
+
function summarizeArgs(args: any): string {
|
|
48
|
+
if (args?.path) return args.path;
|
|
49
|
+
if (args?.command) return args.command.slice(0, 60);
|
|
50
|
+
if (args?.query) return `"${args.query}"`;
|
|
51
|
+
if (args?.url) return args.url;
|
|
52
|
+
if (args?.pattern) return args.pattern;
|
|
53
|
+
return JSON.stringify(args).slice(0, 60);
|
|
54
|
+
}
|
|
55
|
+
|
|
56
|
+
async function main() {
|
|
57
|
+
// Check for OpenRouter API key
|
|
58
|
+
if (!process.env.OPENROUTER_API_KEY) {
|
|
59
|
+
console.error("Error: OPENROUTER_API_KEY environment variable is required");
|
|
60
|
+
console.error("Set it with: export OPENROUTER_API_KEY=sk-or-v1-...");
|
|
61
|
+
process.exit(1);
|
|
62
|
+
}
|
|
63
|
+
|
|
64
|
+
const session = await createResearchAgent();
|
|
65
|
+
|
|
66
|
+
// --- TUI setup ---
|
|
67
|
+
const tui = new TUI(new ProcessTerminal());
|
|
68
|
+
|
|
69
|
+
// Header
|
|
70
|
+
const header = new Text(
|
|
71
|
+
chalk.bold.cyan("[NextPi]") + chalk.dim(" Press Ctrl+C to exit\n")
|
|
72
|
+
);
|
|
73
|
+
tui.addChild(header);
|
|
74
|
+
|
|
75
|
+
// Session info
|
|
76
|
+
const tokenCount = session.messages.reduce((sum, msg) => sum + estimateTokens(msg), 0);
|
|
77
|
+
const infoText = new Text(
|
|
78
|
+
chalk.dim(`Model: ${session.model?.id}\n`) +
|
|
79
|
+
chalk.dim(`History: ${session.messages.length} messages, ~${tokenCount} tokens\n`) +
|
|
80
|
+
chalk.dim(`Tools: ${session.getActiveToolNames().join(", ")}\n`) +
|
|
81
|
+
chalk.dim(`Commands: /new to reset, /exit to quit\n`)
|
|
82
|
+
);
|
|
83
|
+
tui.addChild(infoText);
|
|
84
|
+
|
|
85
|
+
// Chat area (container for messages)
|
|
86
|
+
const chatContainer = new Container();
|
|
87
|
+
tui.addChild(chatContainer);
|
|
88
|
+
|
|
89
|
+
// Editor
|
|
90
|
+
const editor = new Editor(tui, editorTheme);
|
|
91
|
+
editor.setAutocompleteProvider(
|
|
92
|
+
new CombinedAutocompleteProvider(
|
|
93
|
+
[
|
|
94
|
+
{ name: "new", description: "Reset the session" },
|
|
95
|
+
{ name: "exit", description: "Quit the assistant" },
|
|
96
|
+
{ name: "search", description: "Search the web for information" },
|
|
97
|
+
{ name: "fetch", description: "Fetch content from a URL" },
|
|
98
|
+
],
|
|
99
|
+
process.cwd()
|
|
100
|
+
)
|
|
101
|
+
);
|
|
102
|
+
tui.addChild(editor);
|
|
103
|
+
tui.setFocus(editor);
|
|
104
|
+
|
|
105
|
+
// Streaming state
|
|
106
|
+
let streamingMarkdown: Markdown | null = null;
|
|
107
|
+
let streamingText = "";
|
|
108
|
+
let loader: Loader | null = null;
|
|
109
|
+
let isRunning = false;
|
|
110
|
+
|
|
111
|
+
// Subscribe to agent events
|
|
112
|
+
session.subscribe((event) => {
|
|
113
|
+
switch (event.type) {
|
|
114
|
+
case "agent_start":
|
|
115
|
+
isRunning = true;
|
|
116
|
+
editor.disableSubmit = true;
|
|
117
|
+
loader = new Loader(
|
|
118
|
+
tui,
|
|
119
|
+
(s) => chalk.cyan(s),
|
|
120
|
+
(s) => chalk.dim(s),
|
|
121
|
+
"Researching..."
|
|
122
|
+
);
|
|
123
|
+
chatContainer.addChild(loader);
|
|
124
|
+
tui.requestRender();
|
|
125
|
+
break;
|
|
126
|
+
|
|
127
|
+
case "message_update":
|
|
128
|
+
if (event.assistantMessageEvent.type === "text_delta") {
|
|
129
|
+
// Remove loader on first text
|
|
130
|
+
if (loader) {
|
|
131
|
+
chatContainer.removeChild(loader);
|
|
132
|
+
loader = null;
|
|
133
|
+
}
|
|
134
|
+
// Create or update the streaming markdown component
|
|
135
|
+
streamingText += event.assistantMessageEvent.delta;
|
|
136
|
+
if (!streamingMarkdown) {
|
|
137
|
+
streamingMarkdown = new Markdown(streamingText, 1, 0, markdownTheme);
|
|
138
|
+
chatContainer.addChild(streamingMarkdown);
|
|
139
|
+
} else {
|
|
140
|
+
streamingMarkdown.setText(streamingText);
|
|
141
|
+
}
|
|
142
|
+
tui.requestRender();
|
|
143
|
+
}
|
|
144
|
+
break;
|
|
145
|
+
|
|
146
|
+
case "tool_execution_start": {
|
|
147
|
+
if (loader) {
|
|
148
|
+
chatContainer.removeChild(loader);
|
|
149
|
+
loader = null;
|
|
150
|
+
}
|
|
151
|
+
const args = summarizeArgs(event.args);
|
|
152
|
+
const toolMsg = new Text(chalk.dim(` [${event.toolName}] ${args}`));
|
|
153
|
+
chatContainer.addChild(toolMsg);
|
|
154
|
+
tui.requestRender();
|
|
155
|
+
break;
|
|
156
|
+
}
|
|
157
|
+
|
|
158
|
+
case "tool_execution_end": {
|
|
159
|
+
if (event.isError) {
|
|
160
|
+
const errorMsg = new Text(chalk.red(` [Error] ${event.toolName}`));
|
|
161
|
+
chatContainer.addChild(errorMsg);
|
|
162
|
+
} else {
|
|
163
|
+
const doneMsg = new Text(chalk.green(` [Done] ${event.toolName}`));
|
|
164
|
+
chatContainer.addChild(doneMsg);
|
|
165
|
+
}
|
|
166
|
+
tui.requestRender();
|
|
167
|
+
break;
|
|
168
|
+
}
|
|
169
|
+
|
|
170
|
+
case "compaction_start": {
|
|
171
|
+
const compactMsg = new Text(chalk.yellow(" [Compacting context...]"));
|
|
172
|
+
chatContainer.addChild(compactMsg);
|
|
173
|
+
tui.requestRender();
|
|
174
|
+
break;
|
|
175
|
+
}
|
|
176
|
+
|
|
177
|
+
case "agent_end":
|
|
178
|
+
if (loader) {
|
|
179
|
+
chatContainer.removeChild(loader);
|
|
180
|
+
loader = null;
|
|
181
|
+
}
|
|
182
|
+
streamingMarkdown = null;
|
|
183
|
+
streamingText = "";
|
|
184
|
+
isRunning = false;
|
|
185
|
+
editor.disableSubmit = false;
|
|
186
|
+
tui.requestRender();
|
|
187
|
+
break;
|
|
188
|
+
}
|
|
189
|
+
});
|
|
190
|
+
|
|
191
|
+
// Handle input submission
|
|
192
|
+
editor.onSubmit = async (value: string) => {
|
|
193
|
+
if (isRunning) return;
|
|
194
|
+
const trimmed = value.trim();
|
|
195
|
+
if (!trimmed) return;
|
|
196
|
+
|
|
197
|
+
if (trimmed === "/exit") {
|
|
198
|
+
session.dispose();
|
|
199
|
+
tui.stop();
|
|
200
|
+
process.exit(0);
|
|
201
|
+
}
|
|
202
|
+
|
|
203
|
+
if (trimmed === "/new") {
|
|
204
|
+
session.sessionManager.newSession();
|
|
205
|
+
// Clear chat container
|
|
206
|
+
chatContainer.clear();
|
|
207
|
+
const resetMsg = new Text(chalk.yellow("[Session reset]\n"));
|
|
208
|
+
chatContainer.addChild(resetMsg);
|
|
209
|
+
tui.requestRender();
|
|
210
|
+
return;
|
|
211
|
+
}
|
|
212
|
+
|
|
213
|
+
// Add user message to chat
|
|
214
|
+
const userLabel = new Text(chalk.bold.cyan("You:"));
|
|
215
|
+
chatContainer.addChild(userLabel);
|
|
216
|
+
const userMsg = new Markdown(trimmed, 1, 0, markdownTheme);
|
|
217
|
+
chatContainer.addChild(userMsg);
|
|
218
|
+
chatContainer.addChild(new Text(""));
|
|
219
|
+
tui.requestRender();
|
|
220
|
+
|
|
221
|
+
// Send to agent
|
|
222
|
+
try {
|
|
223
|
+
await session.prompt(trimmed);
|
|
224
|
+
} catch (err: any) {
|
|
225
|
+
const errorMsg = new Text(chalk.red(`[Error] ${err.message}`));
|
|
226
|
+
chatContainer.addChild(errorMsg);
|
|
227
|
+
editor.disableSubmit = false;
|
|
228
|
+
tui.requestRender();
|
|
229
|
+
}
|
|
230
|
+
};
|
|
231
|
+
|
|
232
|
+
tui.start();
|
|
233
|
+
}
|
|
234
|
+
|
|
235
|
+
main().catch((err) => {
|
|
236
|
+
console.error("Fatal error:", err);
|
|
237
|
+
process.exit(1);
|
|
238
|
+
});
|