commandmate 0.1.5 → 0.1.6
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-build-manifest.json +72 -0
- package/.next/app-path-routes-manifest.json +1 -0
- package/.next/build-manifest.json +32 -0
- package/.next/cache/.tsbuildinfo +1 -0
- package/.next/cache/config.json +7 -0
- package/.next/cache/webpack/client-production/0.pack +0 -0
- package/.next/cache/webpack/client-production/1.pack +0 -0
- package/.next/cache/webpack/client-production/2.pack +0 -0
- package/.next/cache/webpack/client-production/index.pack +0 -0
- package/.next/cache/webpack/client-production/index.pack.old +0 -0
- package/.next/cache/webpack/edge-server-production/0.pack +0 -0
- package/.next/cache/webpack/edge-server-production/index.pack +0 -0
- package/.next/cache/webpack/server-production/0.pack +0 -0
- package/.next/cache/webpack/server-production/index.pack +0 -0
- package/.next/export-marker.json +1 -0
- package/.next/images-manifest.json +1 -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 +1 -0
- package/.next/react-loadable-manifest.json +249 -0
- package/.next/required-server-files.json +1 -0
- package/.next/routes-manifest.json +1 -0
- package/.next/server/app/_not-found/page.js +1 -0
- package/.next/server/app/_not-found/page.js.nft.json +1 -0
- package/.next/server/app/_not-found/page_client-reference-manifest.js +1 -0
- package/.next/server/app/_not-found.html +1 -0
- package/.next/server/app/_not-found.meta +6 -0
- package/.next/server/app/_not-found.rsc +10 -0
- package/.next/server/app/api/external-apps/[id]/health/route.js +45 -0
- package/.next/server/app/api/external-apps/[id]/health/route.js.nft.json +1 -0
- package/.next/server/app/api/external-apps/[id]/route.js +45 -0
- package/.next/server/app/api/external-apps/[id]/route.js.nft.json +1 -0
- package/.next/server/app/api/external-apps/route.js +45 -0
- package/.next/server/app/api/external-apps/route.js.nft.json +1 -0
- package/.next/server/app/api/hooks/claude-done/route.js +19 -0
- package/.next/server/app/api/hooks/claude-done/route.js.nft.json +1 -0
- package/.next/server/app/api/repositories/clone/[jobId]/route.js +1 -0
- package/.next/server/app/api/repositories/clone/[jobId]/route.js.nft.json +1 -0
- package/.next/server/app/api/repositories/clone/route.js +1 -0
- package/.next/server/app/api/repositories/clone/route.js.nft.json +1 -0
- package/.next/server/app/api/repositories/route.js +1 -0
- package/.next/server/app/api/repositories/route.js.nft.json +1 -0
- package/.next/server/app/api/repositories/scan/route.js +1 -0
- package/.next/server/app/api/repositories/scan/route.js.nft.json +1 -0
- package/.next/server/app/api/repositories/sync/route.js +1 -0
- package/.next/server/app/api/repositories/sync/route.js.nft.json +1 -0
- package/.next/server/app/api/slash-commands/route.js +1 -0
- package/.next/server/app/api/slash-commands/route.js.nft.json +1 -0
- package/.next/server/app/api/slash-commands.body +1 -0
- package/.next/server/app/api/slash-commands.meta +1 -0
- package/.next/server/app/api/worktrees/[id]/auto-yes/route.js +1 -0
- package/.next/server/app/api/worktrees/[id]/auto-yes/route.js.nft.json +1 -0
- package/.next/server/app/api/worktrees/[id]/capture/route.js +2 -0
- package/.next/server/app/api/worktrees/[id]/capture/route.js.nft.json +1 -0
- package/.next/server/app/api/worktrees/[id]/cli-tool/route.js +1 -0
- package/.next/server/app/api/worktrees/[id]/cli-tool/route.js.nft.json +1 -0
- package/.next/server/app/api/worktrees/[id]/current-output/route.js +1 -0
- package/.next/server/app/api/worktrees/[id]/current-output/route.js.nft.json +1 -0
- package/.next/server/app/api/worktrees/[id]/files/[...path]/route.js +1 -0
- package/.next/server/app/api/worktrees/[id]/files/[...path]/route.js.nft.json +1 -0
- package/.next/server/app/api/worktrees/[id]/interrupt/route.js +1 -0
- package/.next/server/app/api/worktrees/[id]/interrupt/route.js.nft.json +1 -0
- package/.next/server/app/api/worktrees/[id]/kill-session/route.js +1 -0
- package/.next/server/app/api/worktrees/[id]/kill-session/route.js.nft.json +1 -0
- package/.next/server/app/api/worktrees/[id]/logs/[filename]/route.js +1 -0
- package/.next/server/app/api/worktrees/[id]/logs/[filename]/route.js.nft.json +1 -0
- package/.next/server/app/api/worktrees/[id]/logs/route.js +19 -0
- package/.next/server/app/api/worktrees/[id]/logs/route.js.nft.json +1 -0
- package/.next/server/app/api/worktrees/[id]/memos/[memoId]/route.js +1 -0
- package/.next/server/app/api/worktrees/[id]/memos/[memoId]/route.js.nft.json +1 -0
- package/.next/server/app/api/worktrees/[id]/memos/route.js +1 -0
- package/.next/server/app/api/worktrees/[id]/memos/route.js.nft.json +1 -0
- package/.next/server/app/api/worktrees/[id]/messages/route.js +1 -0
- package/.next/server/app/api/worktrees/[id]/messages/route.js.nft.json +1 -0
- package/.next/server/app/api/worktrees/[id]/prompt-response/route.js +1 -0
- package/.next/server/app/api/worktrees/[id]/prompt-response/route.js.nft.json +1 -0
- package/.next/server/app/api/worktrees/[id]/respond/route.js +1 -0
- package/.next/server/app/api/worktrees/[id]/respond/route.js.nft.json +1 -0
- package/.next/server/app/api/worktrees/[id]/route.js +1 -0
- package/.next/server/app/api/worktrees/[id]/route.js.nft.json +1 -0
- package/.next/server/app/api/worktrees/[id]/search/route.js +1 -0
- package/.next/server/app/api/worktrees/[id]/search/route.js.nft.json +1 -0
- package/.next/server/app/api/worktrees/[id]/send/route.js +1 -0
- package/.next/server/app/api/worktrees/[id]/send/route.js.nft.json +1 -0
- package/.next/server/app/api/worktrees/[id]/slash-commands/route.js +1 -0
- package/.next/server/app/api/worktrees/[id]/slash-commands/route.js.nft.json +1 -0
- package/.next/server/app/api/worktrees/[id]/start-polling/route.js +1 -0
- package/.next/server/app/api/worktrees/[id]/start-polling/route.js.nft.json +1 -0
- package/.next/server/app/api/worktrees/[id]/terminal/route.js +1 -0
- package/.next/server/app/api/worktrees/[id]/terminal/route.js.nft.json +1 -0
- package/.next/server/app/api/worktrees/[id]/tree/[...path]/route.js +1 -0
- package/.next/server/app/api/worktrees/[id]/tree/[...path]/route.js.nft.json +1 -0
- package/.next/server/app/api/worktrees/[id]/tree/route.js +1 -0
- package/.next/server/app/api/worktrees/[id]/tree/route.js.nft.json +1 -0
- package/.next/server/app/api/worktrees/[id]/upload/[...path]/route.js +1 -0
- package/.next/server/app/api/worktrees/[id]/upload/[...path]/route.js.nft.json +1 -0
- package/.next/server/app/api/worktrees/[id]/viewed/route.js +1 -0
- package/.next/server/app/api/worktrees/[id]/viewed/route.js.nft.json +1 -0
- package/.next/server/app/api/worktrees/route.js +1 -0
- package/.next/server/app/api/worktrees/route.js.nft.json +1 -0
- package/.next/server/app/apple-icon.png/route.js +1 -0
- package/.next/server/app/apple-icon.png/route.js.nft.json +1 -0
- package/.next/server/app/apple-icon.png.body +0 -0
- package/.next/server/app/apple-icon.png.meta +1 -0
- package/.next/server/app/icon.png/route.js +1 -0
- package/.next/server/app/icon.png/route.js.nft.json +1 -0
- package/.next/server/app/icon.png.body +0 -0
- package/.next/server/app/icon.png.meta +1 -0
- package/.next/server/app/index.html +9 -0
- package/.next/server/app/index.meta +5 -0
- package/.next/server/app/index.rsc +8 -0
- package/.next/server/app/page.js +16 -0
- package/.next/server/app/page.js.nft.json +1 -0
- package/.next/server/app/page_client-reference-manifest.js +1 -0
- package/.next/server/app/proxy/[...path]/route.js +45 -0
- package/.next/server/app/proxy/[...path]/route.js.nft.json +1 -0
- package/.next/server/app/worktrees/[id]/files/[...path]/page.js +1 -0
- package/.next/server/app/worktrees/[id]/files/[...path]/page.js.nft.json +1 -0
- package/.next/server/app/worktrees/[id]/files/[...path]/page_client-reference-manifest.js +1 -0
- package/.next/server/app/worktrees/[id]/page.js +21 -0
- package/.next/server/app/worktrees/[id]/page.js.nft.json +1 -0
- package/.next/server/app/worktrees/[id]/page_client-reference-manifest.js +1 -0
- package/.next/server/app/worktrees/[id]/simple-terminal/page.js +4 -0
- package/.next/server/app/worktrees/[id]/simple-terminal/page.js.nft.json +1 -0
- package/.next/server/app/worktrees/[id]/simple-terminal/page_client-reference-manifest.js +1 -0
- package/.next/server/app/worktrees/[id]/terminal/page.js +6 -0
- package/.next/server/app/worktrees/[id]/terminal/page.js.nft.json +1 -0
- package/.next/server/app/worktrees/[id]/terminal/page_client-reference-manifest.js +1 -0
- package/.next/server/app-paths-manifest.json +46 -0
- package/.next/server/chunks/1318.js +29 -0
- package/.next/server/chunks/1528.js +1 -0
- package/.next/server/chunks/1682.js +6 -0
- package/.next/server/chunks/2518.js +12 -0
- package/.next/server/chunks/3053.js +1 -0
- package/.next/server/chunks/3673.js +1 -0
- package/.next/server/chunks/3853.js +1 -0
- package/.next/server/chunks/434.js +1 -0
- package/.next/server/chunks/4471.js +2 -0
- package/.next/server/chunks/4893.js +2 -0
- package/.next/server/chunks/5972.js +12 -0
- package/.next/server/chunks/6550.js +1 -0
- package/.next/server/chunks/6621.js +1 -0
- package/.next/server/chunks/7213.js +1 -0
- package/.next/server/chunks/7425.js +500 -0
- package/.next/server/chunks/8585.js +1 -0
- package/.next/server/chunks/8887.js +1 -0
- package/.next/server/chunks/8948.js +2 -0
- package/.next/server/chunks/9703.js +31 -0
- package/.next/server/chunks/9723.js +19 -0
- package/.next/server/chunks/font-manifest.json +1 -0
- package/.next/server/edge-runtime-webpack.js +2 -0
- package/.next/server/edge-runtime-webpack.js.map +1 -0
- package/.next/server/font-manifest.json +1 -0
- package/.next/server/functions-config-manifest.json +1 -0
- package/.next/server/interception-route-rewrite-manifest.js +1 -0
- package/.next/server/middleware-build-manifest.js +1 -0
- package/.next/server/middleware-manifest.json +32 -0
- package/.next/server/middleware-react-loadable-manifest.js +1 -0
- package/.next/server/next-font-manifest.js +1 -0
- package/.next/server/next-font-manifest.json +1 -0
- package/.next/server/pages/404.html +1 -0
- package/.next/server/pages/500.html +1 -0
- package/.next/server/pages/_app.js +1 -0
- package/.next/server/pages/_app.js.nft.json +1 -0
- package/.next/server/pages/_document.js +1 -0
- package/.next/server/pages/_document.js.nft.json +1 -0
- package/.next/server/pages/_error.js +1 -0
- package/.next/server/pages/_error.js.nft.json +1 -0
- package/.next/server/pages-manifest.json +1 -0
- package/.next/server/server-reference-manifest.js +1 -0
- package/.next/server/server-reference-manifest.json +1 -0
- package/.next/server/src/middleware.js +14 -0
- package/.next/server/src/middleware.js.map +1 -0
- package/.next/server/webpack-runtime.js +1 -0
- package/.next/static/chunks/0dbeb660.3e800dfbd28be3bd.js +53 -0
- package/.next/static/chunks/1015.0eaa4da7f61149bc.js +59 -0
- package/.next/static/chunks/1098.49268c9fe1b028fa.js +1 -0
- package/.next/static/chunks/13.feeafc7cc620f8c4.js +1 -0
- package/.next/static/chunks/1423.7b1e8bf760d28078.js +1 -0
- package/.next/static/chunks/1582.9f8590f71ff798ca.js +55 -0
- package/.next/static/chunks/1817.a66d96cedb761daa.js +262 -0
- package/.next/static/chunks/2117-d845c2cd62e344a6.js +2 -0
- package/.next/static/chunks/2398.0b21e4eb7006a230.js +93 -0
- package/.next/static/chunks/2526.8ac62b527c9ab703.js +43 -0
- package/.next/static/chunks/2626.2125083a1ff3b80a.js +29 -0
- package/.next/static/chunks/2689.720a4874b02d4211.js +174 -0
- package/.next/static/chunks/2853-d11a80b03c9a1640.js +1 -0
- package/.next/static/chunks/2957-327e43ef4c12808f.js +1 -0
- package/.next/static/chunks/2cdb6380.35626fc6e41bbba4.js +136 -0
- package/.next/static/chunks/30d07d85-393352a92199f695.js +3 -0
- package/.next/static/chunks/3559.f073f72c4466ce0e.js +1 -0
- package/.next/static/chunks/3574.7a94c27e6a496a56.js +63 -0
- package/.next/static/chunks/383.20683891c9a5f2c4.js +4 -0
- package/.next/static/chunks/3843.3fdda732987f7bb8.js +1 -0
- package/.next/static/chunks/3852.822389f445c9b427.js +1 -0
- package/.next/static/chunks/3991.4bc063cb5be3a86c.js +1 -0
- package/.next/static/chunks/4212.52c1bb34fc97d0d0.js +131 -0
- package/.next/static/chunks/4327.3b84aa049900fdeb.js +60 -0
- package/.next/static/chunks/4362.7bd6f0282e49d79b.js +1 -0
- package/.next/static/chunks/4721.40615a5f4f32b5fb.js +1 -0
- package/.next/static/chunks/4851-45df4d388db5623f.js +1 -0
- package/.next/static/chunks/5112.17318d1c6b28044b.js +1 -0
- package/.next/static/chunks/5126.93fa4e797d609286.js +56 -0
- package/.next/static/chunks/5387.47590ac4ef66c864.js +5 -0
- package/.next/static/chunks/5813.4483664ba482beb1.js +1 -0
- package/.next/static/chunks/6143.1450875bd03a2366.js +36 -0
- package/.next/static/chunks/6406.9653f0d41ab85059.js +1 -0
- package/.next/static/chunks/656.d72f25ce819bd77e.js +149 -0
- package/.next/static/chunks/6678.492e73ca42b2a273.js +62 -0
- package/.next/static/chunks/6725-f7607851b7d57eb1.js +1 -0
- package/.next/static/chunks/6792.3c01ac4dda4b5c6d.js +1 -0
- package/.next/static/chunks/7004.808cbf327ef5955e.js +1 -0
- package/.next/static/chunks/7290.09ef84cf94f90c4d.js +1 -0
- package/.next/static/chunks/7415.6b481c2baf363262.js +148 -0
- package/.next/static/chunks/7648-325564a6e12a3257.js +1 -0
- package/.next/static/chunks/7665.47fccad04449a8f9.js +215 -0
- package/.next/static/chunks/7753.6bdce86b7fde3d10.js +166 -0
- package/.next/static/chunks/8125.245a9df052d274fb.js +1 -0
- package/.next/static/chunks/816-7e340dad784be28c.js +1 -0
- package/.next/static/chunks/8288.4883743fa40672e2.js +24 -0
- package/.next/static/chunks/8522.1607e96011c66877.js +1 -0
- package/.next/static/chunks/8772.863c564498d88487.js +1 -0
- package/.next/static/chunks/8841.dadeb1ece8e46004.js +1 -0
- package/.next/static/chunks/8885.f8d9912b40d74811.js +1 -0
- package/.next/static/chunks/90542734.c1553d0fe7fc14fc.js +1 -0
- package/.next/static/chunks/9365-733d8c05712d2888.js +1 -0
- package/.next/static/chunks/9552.b7dfb7903ead934b.js +1 -0
- package/.next/static/chunks/9834.295b45635ce04f5e.js +24 -0
- package/.next/static/chunks/app/_not-found/page-a9d04e58c81115ec.js +1 -0
- package/.next/static/chunks/app/layout-37e55f11dcc8b1bf.js +1 -0
- package/.next/static/chunks/app/page-9cd00de9cc0abc43.js +1 -0
- package/.next/static/chunks/app/worktrees/[id]/files/[...path]/page-9e5adf57cbbbdf05.js +1 -0
- package/.next/static/chunks/app/worktrees/[id]/page-8c6676303b63fdaf.js +1 -0
- package/.next/static/chunks/app/worktrees/[id]/simple-terminal/page-16feb3e86e42f4d1.js +1 -0
- package/.next/static/chunks/app/worktrees/[id]/terminal/page-be802baffc84dbd2.js +1 -0
- package/.next/static/chunks/d3ac728e.6c9c508274d4d2d5.js +1 -0
- package/.next/static/chunks/fd9d1056-bbe86e4ae099d5cd.js +1 -0
- package/.next/static/chunks/framework-8e0e0f4a6b83a956.js +1 -0
- package/.next/static/chunks/main-a960f4a5e1a2f598.js +1 -0
- package/.next/static/chunks/main-app-420d93e43682fee5.js +1 -0
- package/.next/static/chunks/pages/_app-3c9ca398d360b709.js +1 -0
- package/.next/static/chunks/pages/_error-cf5ca766ac8f493f.js +1 -0
- package/.next/static/chunks/polyfills-42372ed130431b0a.js +1 -0
- package/.next/static/chunks/webpack-3fc79fab9bb738d7.js +1 -0
- package/.next/static/css/5eacd01f773eed7f.css +11 -0
- package/.next/static/css/85fa6dafca566008.css +1 -0
- package/.next/static/css/e174aa24f94ce607.css +3 -0
- package/.next/static/pQTquVjewvoJa7BML07ip/_buildManifest.js +1 -0
- package/.next/static/pQTquVjewvoJa7BML07ip/_ssgManifest.js +1 -0
- package/.next/trace +5 -0
- package/.next/types/app/api/external-apps/[id]/health/route.ts +343 -0
- package/.next/types/app/api/external-apps/[id]/route.ts +343 -0
- package/.next/types/app/api/external-apps/route.ts +343 -0
- package/.next/types/app/api/hooks/claude-done/route.ts +343 -0
- package/.next/types/app/api/repositories/clone/[jobId]/route.ts +343 -0
- package/.next/types/app/api/repositories/clone/route.ts +343 -0
- package/.next/types/app/api/repositories/route.ts +343 -0
- package/.next/types/app/api/repositories/scan/route.ts +343 -0
- package/.next/types/app/api/repositories/sync/route.ts +343 -0
- package/.next/types/app/api/slash-commands/route.ts +343 -0
- package/.next/types/app/api/worktrees/[id]/auto-yes/route.ts +343 -0
- package/.next/types/app/api/worktrees/[id]/capture/route.ts +343 -0
- package/.next/types/app/api/worktrees/[id]/cli-tool/route.ts +343 -0
- package/.next/types/app/api/worktrees/[id]/current-output/route.ts +343 -0
- package/.next/types/app/api/worktrees/[id]/files/[...path]/route.ts +343 -0
- package/.next/types/app/api/worktrees/[id]/interrupt/route.ts +343 -0
- package/.next/types/app/api/worktrees/[id]/kill-session/route.ts +343 -0
- package/.next/types/app/api/worktrees/[id]/logs/[filename]/route.ts +343 -0
- package/.next/types/app/api/worktrees/[id]/logs/route.ts +343 -0
- package/.next/types/app/api/worktrees/[id]/memos/[memoId]/route.ts +343 -0
- package/.next/types/app/api/worktrees/[id]/memos/route.ts +343 -0
- package/.next/types/app/api/worktrees/[id]/messages/route.ts +343 -0
- package/.next/types/app/api/worktrees/[id]/prompt-response/route.ts +343 -0
- package/.next/types/app/api/worktrees/[id]/respond/route.ts +343 -0
- package/.next/types/app/api/worktrees/[id]/route.ts +343 -0
- package/.next/types/app/api/worktrees/[id]/search/route.ts +343 -0
- package/.next/types/app/api/worktrees/[id]/send/route.ts +343 -0
- package/.next/types/app/api/worktrees/[id]/slash-commands/route.ts +343 -0
- package/.next/types/app/api/worktrees/[id]/start-polling/route.ts +343 -0
- package/.next/types/app/api/worktrees/[id]/terminal/route.ts +343 -0
- package/.next/types/app/api/worktrees/[id]/tree/[...path]/route.ts +343 -0
- package/.next/types/app/api/worktrees/[id]/tree/route.ts +343 -0
- package/.next/types/app/api/worktrees/[id]/upload/[...path]/route.ts +343 -0
- package/.next/types/app/api/worktrees/[id]/viewed/route.ts +343 -0
- package/.next/types/app/api/worktrees/route.ts +343 -0
- package/.next/types/app/page.ts +79 -0
- package/.next/types/app/proxy/[...path]/route.ts +343 -0
- package/.next/types/app/worktrees/[id]/files/[...path]/page.ts +79 -0
- package/.next/types/app/worktrees/[id]/page.ts +79 -0
- package/.next/types/app/worktrees/[id]/simple-terminal/page.ts +79 -0
- package/.next/types/app/worktrees/[id]/terminal/page.ts +79 -0
- package/.next/types/package.json +1 -0
- package/README.md +39 -8
- package/dist/server/server.js +123 -0
- package/dist/server/src/lib/claude-output.js +33 -0
- package/dist/server/src/lib/claude-session.js +312 -0
- package/dist/server/src/lib/cli-patterns.js +137 -0
- package/dist/server/src/lib/cli-session.js +73 -0
- package/dist/server/src/lib/cli-tools/base.js +51 -0
- package/dist/server/src/lib/cli-tools/claude.js +65 -0
- package/dist/server/src/lib/cli-tools/codex.js +132 -0
- package/dist/server/src/lib/cli-tools/gemini.js +122 -0
- package/dist/server/src/lib/cli-tools/index.js +22 -0
- package/dist/server/src/lib/cli-tools/manager.js +143 -0
- package/dist/server/src/lib/cli-tools/types.js +5 -0
- package/dist/server/src/lib/conversation-logger.js +25 -0
- package/dist/server/src/lib/db-instance.js +51 -0
- package/dist/server/src/lib/db-migrations.js +777 -0
- package/dist/server/src/lib/db.js +835 -0
- package/dist/server/src/lib/env.js +179 -0
- package/dist/server/src/lib/log-manager.js +234 -0
- package/dist/server/src/lib/logger.js +232 -0
- package/dist/server/src/lib/prompt-detector.js +285 -0
- package/dist/server/src/lib/response-poller.js +638 -0
- package/dist/server/src/lib/tmux.js +299 -0
- package/dist/server/src/lib/worktrees.js +231 -0
- package/dist/server/src/lib/ws-server.js +323 -0
- package/dist/server/src/types/clone.js +39 -0
- package/dist/server/src/types/conversation.js +9 -0
- package/dist/server/src/types/external-apps.js +6 -0
- package/dist/server/src/types/infinite-messages.js +65 -0
- package/dist/server/src/types/markdown-editor.js +94 -0
- package/dist/server/src/types/models.js +5 -0
- package/dist/server/src/types/sidebar.js +89 -0
- package/dist/server/src/types/slash-commands.js +47 -0
- package/dist/server/src/types/ui-actions.js +8 -0
- package/dist/server/src/types/ui-state.js +62 -0
- package/package.json +8 -4
|
@@ -0,0 +1,73 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
/**
|
|
3
|
+
* Generic CLI session management
|
|
4
|
+
* Manages CLI tool sessions (Claude, Codex, Gemini) within tmux
|
|
5
|
+
*/
|
|
6
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
7
|
+
exports.isSessionRunning = isSessionRunning;
|
|
8
|
+
exports.captureSessionOutput = captureSessionOutput;
|
|
9
|
+
exports.getSessionName = getSessionName;
|
|
10
|
+
const tmux_1 = require("./tmux");
|
|
11
|
+
const manager_1 = require("./cli-tools/manager");
|
|
12
|
+
const logger_1 = require("./logger");
|
|
13
|
+
const logger = (0, logger_1.createLogger)('cli-session');
|
|
14
|
+
/**
|
|
15
|
+
* Check if CLI tool session is running
|
|
16
|
+
*
|
|
17
|
+
* @param worktreeId - Worktree ID
|
|
18
|
+
* @param cliToolId - CLI tool ID (claude, codex, gemini)
|
|
19
|
+
* @returns True if session exists and is running
|
|
20
|
+
*/
|
|
21
|
+
async function isSessionRunning(worktreeId, cliToolId) {
|
|
22
|
+
const manager = manager_1.CLIToolManager.getInstance();
|
|
23
|
+
const cliTool = manager.getTool(cliToolId);
|
|
24
|
+
const sessionName = cliTool.getSessionName(worktreeId);
|
|
25
|
+
return await (0, tmux_1.hasSession)(sessionName);
|
|
26
|
+
}
|
|
27
|
+
/**
|
|
28
|
+
* Capture CLI session output
|
|
29
|
+
*
|
|
30
|
+
* @param worktreeId - Worktree ID
|
|
31
|
+
* @param cliToolId - CLI tool ID (claude, codex, gemini)
|
|
32
|
+
* @param lines - Number of lines to capture (default: 1000)
|
|
33
|
+
* @returns Captured output
|
|
34
|
+
*/
|
|
35
|
+
async function captureSessionOutput(worktreeId, cliToolId, lines = 1000) {
|
|
36
|
+
const log = logger.withContext({ worktreeId, cliToolId });
|
|
37
|
+
log.debug('captureSessionOutput:start', { requestedLines: lines });
|
|
38
|
+
const manager = manager_1.CLIToolManager.getInstance();
|
|
39
|
+
const cliTool = manager.getTool(cliToolId);
|
|
40
|
+
const sessionName = cliTool.getSessionName(worktreeId);
|
|
41
|
+
// Check if session exists
|
|
42
|
+
const exists = await (0, tmux_1.hasSession)(sessionName);
|
|
43
|
+
if (!exists) {
|
|
44
|
+
log.debug('captureSessionOutput:sessionNotFound', { sessionName });
|
|
45
|
+
throw new Error(`${cliTool.name} session ${sessionName} does not exist`);
|
|
46
|
+
}
|
|
47
|
+
try {
|
|
48
|
+
const output = await (0, tmux_1.capturePane)(sessionName, { startLine: -lines });
|
|
49
|
+
const actualLines = output.split('\n').length;
|
|
50
|
+
log.debug('captureSessionOutput:success', {
|
|
51
|
+
actualLines,
|
|
52
|
+
lastFewLines: output.split('\n').slice(-3).join(' | '),
|
|
53
|
+
});
|
|
54
|
+
return output;
|
|
55
|
+
}
|
|
56
|
+
catch (error) {
|
|
57
|
+
const errorMessage = error instanceof Error ? error.message : String(error);
|
|
58
|
+
log.error('captureSessionOutput:failed', { error: errorMessage });
|
|
59
|
+
throw new Error(`Failed to capture ${cliTool.name} output: ${errorMessage}`);
|
|
60
|
+
}
|
|
61
|
+
}
|
|
62
|
+
/**
|
|
63
|
+
* Get session name for a CLI tool and worktree
|
|
64
|
+
*
|
|
65
|
+
* @param worktreeId - Worktree ID
|
|
66
|
+
* @param cliToolId - CLI tool ID
|
|
67
|
+
* @returns Session name
|
|
68
|
+
*/
|
|
69
|
+
function getSessionName(worktreeId, cliToolId) {
|
|
70
|
+
const manager = manager_1.CLIToolManager.getInstance();
|
|
71
|
+
const cliTool = manager.getTool(cliToolId);
|
|
72
|
+
return cliTool.getSessionName(worktreeId);
|
|
73
|
+
}
|
|
@@ -0,0 +1,51 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
/**
|
|
3
|
+
* Base implementation for CLI tools
|
|
4
|
+
* Provides common functionality for all CLI tool implementations
|
|
5
|
+
*/
|
|
6
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
7
|
+
exports.BaseCLITool = void 0;
|
|
8
|
+
const child_process_1 = require("child_process");
|
|
9
|
+
const util_1 = require("util");
|
|
10
|
+
const tmux_1 = require("../tmux");
|
|
11
|
+
const execAsync = (0, util_1.promisify)(child_process_1.exec);
|
|
12
|
+
/**
|
|
13
|
+
* Abstract base class for CLI tools
|
|
14
|
+
* Implements common functionality and defines abstract methods for specific implementations
|
|
15
|
+
*/
|
|
16
|
+
class BaseCLITool {
|
|
17
|
+
/**
|
|
18
|
+
* Check if CLI tool is installed
|
|
19
|
+
* Uses 'which' command to check if the tool is available in PATH
|
|
20
|
+
*/
|
|
21
|
+
async isInstalled() {
|
|
22
|
+
try {
|
|
23
|
+
await execAsync(`which ${this.command}`, { timeout: 5000 });
|
|
24
|
+
return true;
|
|
25
|
+
}
|
|
26
|
+
catch {
|
|
27
|
+
return false;
|
|
28
|
+
}
|
|
29
|
+
}
|
|
30
|
+
/**
|
|
31
|
+
* Generate session name for a worktree
|
|
32
|
+
* Format: mcbd-{cli_tool_id}-{worktree_id}
|
|
33
|
+
*
|
|
34
|
+
* @param worktreeId - Worktree ID
|
|
35
|
+
* @returns Session name
|
|
36
|
+
*/
|
|
37
|
+
getSessionName(worktreeId) {
|
|
38
|
+
return `mcbd-${this.id}-${worktreeId}`;
|
|
39
|
+
}
|
|
40
|
+
/**
|
|
41
|
+
* Interrupt processing by sending Escape key
|
|
42
|
+
* Default implementation: send Escape key to tmux session
|
|
43
|
+
*
|
|
44
|
+
* @param worktreeId - Worktree ID
|
|
45
|
+
*/
|
|
46
|
+
async interrupt(worktreeId) {
|
|
47
|
+
const sessionName = this.getSessionName(worktreeId);
|
|
48
|
+
await (0, tmux_1.sendSpecialKey)(sessionName, 'Escape');
|
|
49
|
+
}
|
|
50
|
+
}
|
|
51
|
+
exports.BaseCLITool = BaseCLITool;
|
|
@@ -0,0 +1,65 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
/**
|
|
3
|
+
* Claude Code CLI tool implementation
|
|
4
|
+
* Wraps existing claude-session functionality into the ICLITool interface
|
|
5
|
+
*/
|
|
6
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
7
|
+
exports.ClaudeTool = void 0;
|
|
8
|
+
const base_1 = require("./base");
|
|
9
|
+
const claude_session_1 = require("../claude-session");
|
|
10
|
+
/**
|
|
11
|
+
* Claude Code CLI tool implementation
|
|
12
|
+
* Uses existing claude-session module for compatibility
|
|
13
|
+
*/
|
|
14
|
+
class ClaudeTool extends base_1.BaseCLITool {
|
|
15
|
+
id = 'claude';
|
|
16
|
+
name = 'Claude Code';
|
|
17
|
+
command = 'claude';
|
|
18
|
+
/**
|
|
19
|
+
* Check if Claude CLI is installed
|
|
20
|
+
* Uses existing isClaudeInstalled function for compatibility
|
|
21
|
+
*/
|
|
22
|
+
async isInstalled() {
|
|
23
|
+
return await (0, claude_session_1.isClaudeInstalled)();
|
|
24
|
+
}
|
|
25
|
+
/**
|
|
26
|
+
* Check if Claude session is running for a worktree
|
|
27
|
+
*
|
|
28
|
+
* @param worktreeId - Worktree ID
|
|
29
|
+
* @returns True if session is running
|
|
30
|
+
*/
|
|
31
|
+
async isRunning(worktreeId) {
|
|
32
|
+
return await (0, claude_session_1.isClaudeRunning)(worktreeId);
|
|
33
|
+
}
|
|
34
|
+
/**
|
|
35
|
+
* Start a new Claude session for a worktree
|
|
36
|
+
*
|
|
37
|
+
* @param worktreeId - Worktree ID
|
|
38
|
+
* @param worktreePath - Worktree path
|
|
39
|
+
*/
|
|
40
|
+
async startSession(worktreeId, worktreePath) {
|
|
41
|
+
const options = {
|
|
42
|
+
worktreeId,
|
|
43
|
+
worktreePath,
|
|
44
|
+
};
|
|
45
|
+
await (0, claude_session_1.startClaudeSession)(options);
|
|
46
|
+
}
|
|
47
|
+
/**
|
|
48
|
+
* Send a message to Claude session
|
|
49
|
+
*
|
|
50
|
+
* @param worktreeId - Worktree ID
|
|
51
|
+
* @param message - Message to send
|
|
52
|
+
*/
|
|
53
|
+
async sendMessage(worktreeId, message) {
|
|
54
|
+
await (0, claude_session_1.sendMessageToClaude)(worktreeId, message);
|
|
55
|
+
}
|
|
56
|
+
/**
|
|
57
|
+
* Kill Claude session
|
|
58
|
+
*
|
|
59
|
+
* @param worktreeId - Worktree ID
|
|
60
|
+
*/
|
|
61
|
+
async killSession(worktreeId) {
|
|
62
|
+
await (0, claude_session_1.stopClaudeSession)(worktreeId);
|
|
63
|
+
}
|
|
64
|
+
}
|
|
65
|
+
exports.ClaudeTool = ClaudeTool;
|
|
@@ -0,0 +1,132 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
/**
|
|
3
|
+
* Codex CLI tool implementation
|
|
4
|
+
* Provides integration with OpenAI's Codex CLI
|
|
5
|
+
*/
|
|
6
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
7
|
+
exports.CodexTool = void 0;
|
|
8
|
+
const base_1 = require("./base");
|
|
9
|
+
const tmux_1 = require("../tmux");
|
|
10
|
+
const child_process_1 = require("child_process");
|
|
11
|
+
const util_1 = require("util");
|
|
12
|
+
const execAsync = (0, util_1.promisify)(child_process_1.exec);
|
|
13
|
+
/**
|
|
14
|
+
* Codex CLI tool implementation
|
|
15
|
+
* Manages Codex sessions using tmux
|
|
16
|
+
*/
|
|
17
|
+
class CodexTool extends base_1.BaseCLITool {
|
|
18
|
+
id = 'codex';
|
|
19
|
+
name = 'Codex CLI';
|
|
20
|
+
command = 'codex';
|
|
21
|
+
/**
|
|
22
|
+
* Check if Codex session is running for a worktree
|
|
23
|
+
*
|
|
24
|
+
* @param worktreeId - Worktree ID
|
|
25
|
+
* @returns True if session is running
|
|
26
|
+
*/
|
|
27
|
+
async isRunning(worktreeId) {
|
|
28
|
+
const sessionName = this.getSessionName(worktreeId);
|
|
29
|
+
return await (0, tmux_1.hasSession)(sessionName);
|
|
30
|
+
}
|
|
31
|
+
/**
|
|
32
|
+
* Start a new Codex session for a worktree
|
|
33
|
+
*
|
|
34
|
+
* @param worktreeId - Worktree ID
|
|
35
|
+
* @param worktreePath - Worktree path
|
|
36
|
+
*/
|
|
37
|
+
async startSession(worktreeId, worktreePath) {
|
|
38
|
+
// Check if Codex is installed
|
|
39
|
+
const codexAvailable = await this.isInstalled();
|
|
40
|
+
if (!codexAvailable) {
|
|
41
|
+
throw new Error('Codex CLI is not installed or not in PATH');
|
|
42
|
+
}
|
|
43
|
+
const sessionName = this.getSessionName(worktreeId);
|
|
44
|
+
// Check if session already exists
|
|
45
|
+
const exists = await (0, tmux_1.hasSession)(sessionName);
|
|
46
|
+
if (exists) {
|
|
47
|
+
console.log(`Codex session ${sessionName} already exists`);
|
|
48
|
+
return;
|
|
49
|
+
}
|
|
50
|
+
try {
|
|
51
|
+
// Create tmux session with large history buffer for Codex output
|
|
52
|
+
await (0, tmux_1.createSession)({
|
|
53
|
+
sessionName,
|
|
54
|
+
workingDirectory: worktreePath,
|
|
55
|
+
historyLimit: 50000,
|
|
56
|
+
});
|
|
57
|
+
// Wait a moment for the session to be created
|
|
58
|
+
await new Promise((resolve) => setTimeout(resolve, 100));
|
|
59
|
+
// Start Codex CLI in interactive mode
|
|
60
|
+
await (0, tmux_1.sendKeys)(sessionName, 'codex', true);
|
|
61
|
+
// Wait for Codex to initialize (and potentially show update notification)
|
|
62
|
+
await new Promise((resolve) => setTimeout(resolve, 3000));
|
|
63
|
+
// Auto-skip update notification if present (select option 2: Skip)
|
|
64
|
+
await (0, tmux_1.sendKeys)(sessionName, '2', true);
|
|
65
|
+
// Wait a moment for the selection to process
|
|
66
|
+
await new Promise((resolve) => setTimeout(resolve, 500));
|
|
67
|
+
console.log(`✓ Started Codex session: ${sessionName}`);
|
|
68
|
+
}
|
|
69
|
+
catch (error) {
|
|
70
|
+
const errorMessage = error instanceof Error ? error.message : String(error);
|
|
71
|
+
throw new Error(`Failed to start Codex session: ${errorMessage}`);
|
|
72
|
+
}
|
|
73
|
+
}
|
|
74
|
+
/**
|
|
75
|
+
* Send a message to Codex session
|
|
76
|
+
*
|
|
77
|
+
* @param worktreeId - Worktree ID
|
|
78
|
+
* @param message - Message to send
|
|
79
|
+
*/
|
|
80
|
+
async sendMessage(worktreeId, message) {
|
|
81
|
+
const sessionName = this.getSessionName(worktreeId);
|
|
82
|
+
// Check if session exists
|
|
83
|
+
const exists = await (0, tmux_1.hasSession)(sessionName);
|
|
84
|
+
if (!exists) {
|
|
85
|
+
throw new Error(`Codex session ${sessionName} does not exist. Start the session first.`);
|
|
86
|
+
}
|
|
87
|
+
try {
|
|
88
|
+
// Send message to Codex (without Enter)
|
|
89
|
+
await (0, tmux_1.sendKeys)(sessionName, message, false);
|
|
90
|
+
// Wait a moment for the text to be typed
|
|
91
|
+
await new Promise((resolve) => setTimeout(resolve, 100));
|
|
92
|
+
// Send Enter key separately
|
|
93
|
+
await execAsync(`tmux send-keys -t "${sessionName}" C-m`);
|
|
94
|
+
// Wait a moment for the message to be processed
|
|
95
|
+
await new Promise((resolve) => setTimeout(resolve, 200));
|
|
96
|
+
console.log(`✓ Sent message to Codex session: ${sessionName}`);
|
|
97
|
+
}
|
|
98
|
+
catch (error) {
|
|
99
|
+
const errorMessage = error instanceof Error ? error.message : String(error);
|
|
100
|
+
throw new Error(`Failed to send message to Codex: ${errorMessage}`);
|
|
101
|
+
}
|
|
102
|
+
}
|
|
103
|
+
/**
|
|
104
|
+
* Kill Codex session
|
|
105
|
+
*
|
|
106
|
+
* @param worktreeId - Worktree ID
|
|
107
|
+
*/
|
|
108
|
+
async killSession(worktreeId) {
|
|
109
|
+
const sessionName = this.getSessionName(worktreeId);
|
|
110
|
+
try {
|
|
111
|
+
// Send Ctrl+D to exit Codex gracefully
|
|
112
|
+
const exists = await (0, tmux_1.hasSession)(sessionName);
|
|
113
|
+
if (exists) {
|
|
114
|
+
// Send Ctrl+D (ASCII 4)
|
|
115
|
+
await execAsync(`tmux send-keys -t "${sessionName}" C-d`);
|
|
116
|
+
// Wait a moment for Codex to exit
|
|
117
|
+
await new Promise((resolve) => setTimeout(resolve, 500));
|
|
118
|
+
}
|
|
119
|
+
// Kill the tmux session
|
|
120
|
+
const killed = await (0, tmux_1.killSession)(sessionName);
|
|
121
|
+
if (killed) {
|
|
122
|
+
console.log(`✓ Stopped Codex session: ${sessionName}`);
|
|
123
|
+
}
|
|
124
|
+
}
|
|
125
|
+
catch (error) {
|
|
126
|
+
const errorMessage = error instanceof Error ? error.message : String(error);
|
|
127
|
+
console.error(`Error stopping Codex session: ${errorMessage}`);
|
|
128
|
+
throw error;
|
|
129
|
+
}
|
|
130
|
+
}
|
|
131
|
+
}
|
|
132
|
+
exports.CodexTool = CodexTool;
|
|
@@ -0,0 +1,122 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
/**
|
|
3
|
+
* Gemini CLI tool implementation
|
|
4
|
+
* Provides integration with Google's Gemini CLI
|
|
5
|
+
*/
|
|
6
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
7
|
+
exports.GeminiTool = void 0;
|
|
8
|
+
const base_1 = require("./base");
|
|
9
|
+
const tmux_1 = require("../tmux");
|
|
10
|
+
const child_process_1 = require("child_process");
|
|
11
|
+
const util_1 = require("util");
|
|
12
|
+
const execAsync = (0, util_1.promisify)(child_process_1.exec);
|
|
13
|
+
/**
|
|
14
|
+
* Gemini CLI tool implementation
|
|
15
|
+
* Manages Gemini sessions using tmux
|
|
16
|
+
*/
|
|
17
|
+
class GeminiTool extends base_1.BaseCLITool {
|
|
18
|
+
id = 'gemini';
|
|
19
|
+
name = 'Gemini CLI';
|
|
20
|
+
command = 'gemini';
|
|
21
|
+
/**
|
|
22
|
+
* Check if Gemini session is running for a worktree
|
|
23
|
+
*
|
|
24
|
+
* @param worktreeId - Worktree ID
|
|
25
|
+
* @returns True if session is running
|
|
26
|
+
*/
|
|
27
|
+
async isRunning(worktreeId) {
|
|
28
|
+
const sessionName = this.getSessionName(worktreeId);
|
|
29
|
+
return await (0, tmux_1.hasSession)(sessionName);
|
|
30
|
+
}
|
|
31
|
+
/**
|
|
32
|
+
* Start a new Gemini session for a worktree
|
|
33
|
+
* Note: Gemini uses non-interactive mode, so we just create a tmux session
|
|
34
|
+
* for running one-shot commands
|
|
35
|
+
*
|
|
36
|
+
* @param worktreeId - Worktree ID
|
|
37
|
+
* @param worktreePath - Worktree path
|
|
38
|
+
*/
|
|
39
|
+
async startSession(worktreeId, worktreePath) {
|
|
40
|
+
// Check if Gemini is installed
|
|
41
|
+
const geminiAvailable = await this.isInstalled();
|
|
42
|
+
if (!geminiAvailable) {
|
|
43
|
+
throw new Error('Gemini CLI is not installed or not in PATH');
|
|
44
|
+
}
|
|
45
|
+
const sessionName = this.getSessionName(worktreeId);
|
|
46
|
+
// Check if session already exists
|
|
47
|
+
const exists = await (0, tmux_1.hasSession)(sessionName);
|
|
48
|
+
if (exists) {
|
|
49
|
+
console.log(`Gemini session ${sessionName} already exists`);
|
|
50
|
+
return;
|
|
51
|
+
}
|
|
52
|
+
try {
|
|
53
|
+
// Create tmux session for running Gemini commands
|
|
54
|
+
await (0, tmux_1.createSession)({
|
|
55
|
+
sessionName,
|
|
56
|
+
workingDirectory: worktreePath,
|
|
57
|
+
historyLimit: 50000,
|
|
58
|
+
});
|
|
59
|
+
console.log(`✓ Started Gemini session: ${sessionName}`);
|
|
60
|
+
}
|
|
61
|
+
catch (error) {
|
|
62
|
+
const errorMessage = error instanceof Error ? error.message : String(error);
|
|
63
|
+
throw new Error(`Failed to start Gemini session: ${errorMessage}`);
|
|
64
|
+
}
|
|
65
|
+
}
|
|
66
|
+
/**
|
|
67
|
+
* Send a message to Gemini session (non-interactive mode)
|
|
68
|
+
* Executes a one-shot Gemini command and captures the output
|
|
69
|
+
*
|
|
70
|
+
* @param worktreeId - Worktree ID
|
|
71
|
+
* @param message - Message to send
|
|
72
|
+
*/
|
|
73
|
+
async sendMessage(worktreeId, message) {
|
|
74
|
+
const sessionName = this.getSessionName(worktreeId);
|
|
75
|
+
// Check if session exists
|
|
76
|
+
const exists = await (0, tmux_1.hasSession)(sessionName);
|
|
77
|
+
if (!exists) {
|
|
78
|
+
throw new Error(`Gemini session ${sessionName} does not exist. Start the session first.`);
|
|
79
|
+
}
|
|
80
|
+
try {
|
|
81
|
+
// Escape the message for shell execution
|
|
82
|
+
const escapedMessage = message.replace(/'/g, "'\\''");
|
|
83
|
+
// Execute Gemini in non-interactive mode using stdin piping
|
|
84
|
+
// This approach bypasses the TUI and executes in one-shot mode
|
|
85
|
+
await (0, tmux_1.sendKeys)(sessionName, `echo '${escapedMessage}' | gemini`, true);
|
|
86
|
+
console.log(`✓ Sent message to Gemini session: ${sessionName}`);
|
|
87
|
+
}
|
|
88
|
+
catch (error) {
|
|
89
|
+
const errorMessage = error instanceof Error ? error.message : String(error);
|
|
90
|
+
throw new Error(`Failed to send message to Gemini: ${errorMessage}`);
|
|
91
|
+
}
|
|
92
|
+
}
|
|
93
|
+
/**
|
|
94
|
+
* Kill Gemini session
|
|
95
|
+
*
|
|
96
|
+
* @param worktreeId - Worktree ID
|
|
97
|
+
*/
|
|
98
|
+
async killSession(worktreeId) {
|
|
99
|
+
const sessionName = this.getSessionName(worktreeId);
|
|
100
|
+
try {
|
|
101
|
+
// Send Ctrl+D to exit Gemini gracefully
|
|
102
|
+
const exists = await (0, tmux_1.hasSession)(sessionName);
|
|
103
|
+
if (exists) {
|
|
104
|
+
// Send Ctrl+D (ASCII 4)
|
|
105
|
+
await execAsync(`tmux send-keys -t "${sessionName}" C-d`);
|
|
106
|
+
// Wait a moment for Gemini to exit
|
|
107
|
+
await new Promise((resolve) => setTimeout(resolve, 500));
|
|
108
|
+
}
|
|
109
|
+
// Kill the tmux session
|
|
110
|
+
const killed = await (0, tmux_1.killSession)(sessionName);
|
|
111
|
+
if (killed) {
|
|
112
|
+
console.log(`✓ Stopped Gemini session: ${sessionName}`);
|
|
113
|
+
}
|
|
114
|
+
}
|
|
115
|
+
catch (error) {
|
|
116
|
+
const errorMessage = error instanceof Error ? error.message : String(error);
|
|
117
|
+
console.error(`Error stopping Gemini session: ${errorMessage}`);
|
|
118
|
+
throw error;
|
|
119
|
+
}
|
|
120
|
+
}
|
|
121
|
+
}
|
|
122
|
+
exports.GeminiTool = GeminiTool;
|
|
@@ -0,0 +1,22 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
/**
|
|
3
|
+
* CLI Tools Module
|
|
4
|
+
* Provides abstraction layer for multiple SWE CLI tools (Claude, Codex, Gemini)
|
|
5
|
+
*
|
|
6
|
+
* @module cli-tools
|
|
7
|
+
*/
|
|
8
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
9
|
+
exports.CLIToolManager = exports.GeminiTool = exports.CodexTool = exports.ClaudeTool = exports.BaseCLITool = void 0;
|
|
10
|
+
// Export base class
|
|
11
|
+
var base_1 = require("./base");
|
|
12
|
+
Object.defineProperty(exports, "BaseCLITool", { enumerable: true, get: function () { return base_1.BaseCLITool; } });
|
|
13
|
+
// Export CLI tool implementations
|
|
14
|
+
var claude_1 = require("./claude");
|
|
15
|
+
Object.defineProperty(exports, "ClaudeTool", { enumerable: true, get: function () { return claude_1.ClaudeTool; } });
|
|
16
|
+
var codex_1 = require("./codex");
|
|
17
|
+
Object.defineProperty(exports, "CodexTool", { enumerable: true, get: function () { return codex_1.CodexTool; } });
|
|
18
|
+
var gemini_1 = require("./gemini");
|
|
19
|
+
Object.defineProperty(exports, "GeminiTool", { enumerable: true, get: function () { return gemini_1.GeminiTool; } });
|
|
20
|
+
// Export CLI tool manager
|
|
21
|
+
var manager_1 = require("./manager");
|
|
22
|
+
Object.defineProperty(exports, "CLIToolManager", { enumerable: true, get: function () { return manager_1.CLIToolManager; } });
|
|
@@ -0,0 +1,143 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
/**
|
|
3
|
+
* CLI Tool Manager
|
|
4
|
+
* Singleton class to manage multiple CLI tools (Claude, Codex, Gemini)
|
|
5
|
+
*/
|
|
6
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
7
|
+
exports.CLIToolManager = void 0;
|
|
8
|
+
const claude_1 = require("./claude");
|
|
9
|
+
const codex_1 = require("./codex");
|
|
10
|
+
const gemini_1 = require("./gemini");
|
|
11
|
+
/**
|
|
12
|
+
* CLI Tool Manager (Singleton)
|
|
13
|
+
* Provides centralized access to all CLI tools
|
|
14
|
+
*/
|
|
15
|
+
class CLIToolManager {
|
|
16
|
+
static instance;
|
|
17
|
+
tools;
|
|
18
|
+
/**
|
|
19
|
+
* Private constructor for Singleton pattern
|
|
20
|
+
*/
|
|
21
|
+
constructor() {
|
|
22
|
+
this.tools = new Map();
|
|
23
|
+
// Initialize all tools
|
|
24
|
+
this.tools.set('claude', new claude_1.ClaudeTool());
|
|
25
|
+
this.tools.set('codex', new codex_1.CodexTool());
|
|
26
|
+
this.tools.set('gemini', new gemini_1.GeminiTool());
|
|
27
|
+
}
|
|
28
|
+
/**
|
|
29
|
+
* Get singleton instance
|
|
30
|
+
*
|
|
31
|
+
* @returns CLIToolManager instance
|
|
32
|
+
*/
|
|
33
|
+
static getInstance() {
|
|
34
|
+
if (!CLIToolManager.instance) {
|
|
35
|
+
CLIToolManager.instance = new CLIToolManager();
|
|
36
|
+
}
|
|
37
|
+
return CLIToolManager.instance;
|
|
38
|
+
}
|
|
39
|
+
/**
|
|
40
|
+
* Get a specific CLI tool by type
|
|
41
|
+
*
|
|
42
|
+
* @param type - CLI tool type
|
|
43
|
+
* @returns CLI tool instance
|
|
44
|
+
*
|
|
45
|
+
* @example
|
|
46
|
+
* ```typescript
|
|
47
|
+
* const manager = CLIToolManager.getInstance();
|
|
48
|
+
* const claude = manager.getTool('claude');
|
|
49
|
+
* await claude.startSession('my-worktree', '/path/to/worktree');
|
|
50
|
+
* ```
|
|
51
|
+
*/
|
|
52
|
+
getTool(type) {
|
|
53
|
+
const tool = this.tools.get(type);
|
|
54
|
+
if (!tool) {
|
|
55
|
+
throw new Error(`CLI tool '${type}' not found`);
|
|
56
|
+
}
|
|
57
|
+
return tool;
|
|
58
|
+
}
|
|
59
|
+
/**
|
|
60
|
+
* Get all CLI tools
|
|
61
|
+
*
|
|
62
|
+
* @returns Array of all CLI tool instances
|
|
63
|
+
*
|
|
64
|
+
* @example
|
|
65
|
+
* ```typescript
|
|
66
|
+
* const manager = CLIToolManager.getInstance();
|
|
67
|
+
* const allTools = manager.getAllTools();
|
|
68
|
+
* console.log(allTools.map(t => t.name)); // ['Claude Code', 'Codex CLI', 'Gemini CLI']
|
|
69
|
+
* ```
|
|
70
|
+
*/
|
|
71
|
+
getAllTools() {
|
|
72
|
+
return Array.from(this.tools.values());
|
|
73
|
+
}
|
|
74
|
+
/**
|
|
75
|
+
* Get information about a specific tool including installation status
|
|
76
|
+
*
|
|
77
|
+
* @param type - CLI tool type
|
|
78
|
+
* @returns Tool information with installation status
|
|
79
|
+
*
|
|
80
|
+
* @example
|
|
81
|
+
* ```typescript
|
|
82
|
+
* const manager = CLIToolManager.getInstance();
|
|
83
|
+
* const info = await manager.getToolInfo('claude');
|
|
84
|
+
* if (info.installed) {
|
|
85
|
+
* console.log(`${info.name} is installed`);
|
|
86
|
+
* }
|
|
87
|
+
* ```
|
|
88
|
+
*/
|
|
89
|
+
async getToolInfo(type) {
|
|
90
|
+
const tool = this.getTool(type);
|
|
91
|
+
const installed = await tool.isInstalled();
|
|
92
|
+
return {
|
|
93
|
+
id: tool.id,
|
|
94
|
+
name: tool.name,
|
|
95
|
+
command: tool.command,
|
|
96
|
+
installed,
|
|
97
|
+
};
|
|
98
|
+
}
|
|
99
|
+
/**
|
|
100
|
+
* Get information about all tools including installation status
|
|
101
|
+
*
|
|
102
|
+
* @returns Array of tool information for all tools
|
|
103
|
+
*
|
|
104
|
+
* @example
|
|
105
|
+
* ```typescript
|
|
106
|
+
* const manager = CLIToolManager.getInstance();
|
|
107
|
+
* const allInfo = await manager.getAllToolsInfo();
|
|
108
|
+
* allInfo.forEach(info => {
|
|
109
|
+
* console.log(`${info.name}: ${info.installed ? 'installed' : 'not installed'}`);
|
|
110
|
+
* });
|
|
111
|
+
* ```
|
|
112
|
+
*/
|
|
113
|
+
async getAllToolsInfo() {
|
|
114
|
+
const tools = this.getAllTools();
|
|
115
|
+
const infoPromises = tools.map(async (tool) => {
|
|
116
|
+
const installed = await tool.isInstalled();
|
|
117
|
+
return {
|
|
118
|
+
id: tool.id,
|
|
119
|
+
name: tool.name,
|
|
120
|
+
command: tool.command,
|
|
121
|
+
installed,
|
|
122
|
+
};
|
|
123
|
+
});
|
|
124
|
+
return Promise.all(infoPromises);
|
|
125
|
+
}
|
|
126
|
+
/**
|
|
127
|
+
* Get only installed tools
|
|
128
|
+
*
|
|
129
|
+
* @returns Array of tool information for installed tools only
|
|
130
|
+
*
|
|
131
|
+
* @example
|
|
132
|
+
* ```typescript
|
|
133
|
+
* const manager = CLIToolManager.getInstance();
|
|
134
|
+
* const installed = await manager.getInstalledTools();
|
|
135
|
+
* console.log(`${installed.length} tools installed`);
|
|
136
|
+
* ```
|
|
137
|
+
*/
|
|
138
|
+
async getInstalledTools() {
|
|
139
|
+
const allInfo = await this.getAllToolsInfo();
|
|
140
|
+
return allInfo.filter(info => info.installed);
|
|
141
|
+
}
|
|
142
|
+
}
|
|
143
|
+
exports.CLIToolManager = CLIToolManager;
|
|
@@ -0,0 +1,25 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
/**
|
|
3
|
+
* Conversation logging helper
|
|
4
|
+
* Ensures Claude responses are paired with the latest user input before writing markdown logs
|
|
5
|
+
*/
|
|
6
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
7
|
+
exports.recordClaudeConversation = recordClaudeConversation;
|
|
8
|
+
const db_1 = require("./db");
|
|
9
|
+
const log_manager_1 = require("./log-manager");
|
|
10
|
+
/**
|
|
11
|
+
* Persist the latest Claude response alongside the most recent user prompt.
|
|
12
|
+
* Errors are swallowed so the calling API route can continue responding.
|
|
13
|
+
*/
|
|
14
|
+
async function recordClaudeConversation(db, worktreeId, claudeResponse, cliToolId = 'claude') {
|
|
15
|
+
const lastUserMessage = (0, db_1.getLastUserMessage)(db, worktreeId);
|
|
16
|
+
if (!lastUserMessage) {
|
|
17
|
+
return;
|
|
18
|
+
}
|
|
19
|
+
try {
|
|
20
|
+
await (0, log_manager_1.createLog)(worktreeId, lastUserMessage.content, claudeResponse, cliToolId);
|
|
21
|
+
}
|
|
22
|
+
catch (error) {
|
|
23
|
+
console.error('[recordClaudeConversation] Failed to create log file:', error);
|
|
24
|
+
}
|
|
25
|
+
}
|