vibetree 1.2.0 → 1.3.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/.vibetree/worktrees/{d9baadc6-9864-472d-afa8-ee208877e85f → 3020aa56-a7a7-46c4-a452-b558cf6eadfd}/bin/vibetree.js +17 -54
- package/.vibetree/worktrees/{d9baadc6-9864-472d-afa8-ee208877e85f → 3020aa56-a7a7-46c4-a452-b558cf6eadfd}/client/package.json +2 -2
- package/.vibetree/worktrees/{d9baadc6-9864-472d-afa8-ee208877e85f → 3020aa56-a7a7-46c4-a452-b558cf6eadfd}/package.json +2 -2
- package/.vibetree/worktrees/{d9baadc6-9864-472d-afa8-ee208877e85f → 3020aa56-a7a7-46c4-a452-b558cf6eadfd}/server/package.json +2 -2
- package/.vibetree/worktrees/3020aa56-a7a7-46c4-a452-b558cf6eadfd/server/router.ts +274 -0
- package/.vibetree/worktrees/32fa1562-8457-4084-b833-db88c38d249e/client/dist/assets/{index-ZqVhjef4.js → index-LGdAMmu9.js} +39 -39
- package/.vibetree/worktrees/32fa1562-8457-4084-b833-db88c38d249e/client/dist/assets/index-O9kV9afk.css +32 -0
- package/.vibetree/worktrees/32fa1562-8457-4084-b833-db88c38d249e/client/dist/index.html +2 -2
- package/.vibetree/worktrees/32fa1562-8457-4084-b833-db88c38d249e/client/src/App.tsx +0 -27
- package/.vibetree/worktrees/46276a4e-dc74-4ca3-acd1-96feb2ecf3ad/.github/workflows/lint.yml +26 -0
- package/.vibetree/worktrees/46276a4e-dc74-4ca3-acd1-96feb2ecf3ad/.github/workflows/test.yml +29 -0
- package/.vibetree/worktrees/46276a4e-dc74-4ca3-acd1-96feb2ecf3ad/.node-version +1 -0
- package/.vibetree/worktrees/46276a4e-dc74-4ca3-acd1-96feb2ecf3ad/bin/vibetree.js +84 -0
- package/.vibetree/worktrees/46276a4e-dc74-4ca3-acd1-96feb2ecf3ad/client/.eslintrc.cjs +21 -0
- package/.vibetree/worktrees/46276a4e-dc74-4ca3-acd1-96feb2ecf3ad/client/index.html +16 -0
- package/.vibetree/worktrees/46276a4e-dc74-4ca3-acd1-96feb2ecf3ad/client/package.json +40 -0
- package/.vibetree/worktrees/46276a4e-dc74-4ca3-acd1-96feb2ecf3ad/client/postcss.config.js +6 -0
- package/.vibetree/worktrees/46276a4e-dc74-4ca3-acd1-96feb2ecf3ad/client/public/favicon.svg +28 -0
- package/.vibetree/worktrees/46276a4e-dc74-4ca3-acd1-96feb2ecf3ad/client/src/App.tsx +161 -0
- package/.vibetree/worktrees/46276a4e-dc74-4ca3-acd1-96feb2ecf3ad/client/src/components/ConfirmationModal.tsx +33 -0
- package/.vibetree/worktrees/46276a4e-dc74-4ca3-acd1-96feb2ecf3ad/client/src/components/CreateTaskModal.tsx +62 -0
- package/.vibetree/worktrees/46276a4e-dc74-4ca3-acd1-96feb2ecf3ad/client/src/components/KanbanBoard.tsx +111 -0
- package/.vibetree/worktrees/46276a4e-dc74-4ca3-acd1-96feb2ecf3ad/client/src/components/LanguageSelector.tsx +67 -0
- package/.vibetree/worktrees/46276a4e-dc74-4ca3-acd1-96feb2ecf3ad/client/src/components/RepoModal.tsx +155 -0
- package/.vibetree/worktrees/46276a4e-dc74-4ca3-acd1-96feb2ecf3ad/client/src/components/TaskDetail.tsx +165 -0
- package/.vibetree/worktrees/46276a4e-dc74-4ca3-acd1-96feb2ecf3ad/client/src/context/TaskContext.tsx +91 -0
- package/.vibetree/worktrees/46276a4e-dc74-4ca3-acd1-96feb2ecf3ad/client/src/context/TerminalContext.tsx +89 -0
- package/.vibetree/worktrees/46276a4e-dc74-4ca3-acd1-96feb2ecf3ad/client/src/i18n/config.ts +36 -0
- package/.vibetree/worktrees/46276a4e-dc74-4ca3-acd1-96feb2ecf3ad/client/src/i18n/locales/en.json +64 -0
- package/.vibetree/worktrees/46276a4e-dc74-4ca3-acd1-96feb2ecf3ad/client/src/i18n/locales/ja.json +64 -0
- package/.vibetree/worktrees/46276a4e-dc74-4ca3-acd1-96feb2ecf3ad/client/src/i18n/locales/ko.json +64 -0
- package/.vibetree/worktrees/46276a4e-dc74-4ca3-acd1-96feb2ecf3ad/client/src/i18n/locales/zh.json +64 -0
- package/.vibetree/worktrees/46276a4e-dc74-4ca3-acd1-96feb2ecf3ad/client/src/index.css +31 -0
- package/.vibetree/worktrees/46276a4e-dc74-4ca3-acd1-96feb2ecf3ad/client/src/main.tsx +11 -0
- package/.vibetree/worktrees/46276a4e-dc74-4ca3-acd1-96feb2ecf3ad/client/src/trpc.ts +4 -0
- package/.vibetree/worktrees/46276a4e-dc74-4ca3-acd1-96feb2ecf3ad/client/src/types.ts +39 -0
- package/.vibetree/worktrees/46276a4e-dc74-4ca3-acd1-96feb2ecf3ad/client/tailwind.config.js +22 -0
- package/.vibetree/worktrees/46276a4e-dc74-4ca3-acd1-96feb2ecf3ad/client/tsconfig.json +25 -0
- package/.vibetree/worktrees/46276a4e-dc74-4ca3-acd1-96feb2ecf3ad/client/tsconfig.node.json +11 -0
- package/.vibetree/worktrees/46276a4e-dc74-4ca3-acd1-96feb2ecf3ad/client/vite.config.ts +29 -0
- package/.vibetree/worktrees/46276a4e-dc74-4ca3-acd1-96feb2ecf3ad/package.json +69 -0
- package/.vibetree/worktrees/46276a4e-dc74-4ca3-acd1-96feb2ecf3ad/server/README_TESTS.md +118 -0
- package/.vibetree/worktrees/46276a4e-dc74-4ca3-acd1-96feb2ecf3ad/server/dist/config.js +45 -0
- package/.vibetree/worktrees/46276a4e-dc74-4ca3-acd1-96feb2ecf3ad/server/dist/db.js +208 -0
- package/.vibetree/worktrees/46276a4e-dc74-4ca3-acd1-96feb2ecf3ad/server/dist/git.js +100 -0
- package/.vibetree/worktrees/46276a4e-dc74-4ca3-acd1-96feb2ecf3ad/server/dist/index.js +121 -0
- package/.vibetree/worktrees/46276a4e-dc74-4ca3-acd1-96feb2ecf3ad/server/dist/router.js +278 -0
- package/.vibetree/worktrees/46276a4e-dc74-4ca3-acd1-96feb2ecf3ad/server/dist/tasks.js +7 -0
- package/.vibetree/worktrees/46276a4e-dc74-4ca3-acd1-96feb2ecf3ad/server/dist/terminal.js +203 -0
- package/.vibetree/worktrees/46276a4e-dc74-4ca3-acd1-96feb2ecf3ad/server/dist/trpc.js +7 -0
- package/.vibetree/worktrees/46276a4e-dc74-4ca3-acd1-96feb2ecf3ad/server/dist/types.js +2 -0
- package/.vibetree/worktrees/46276a4e-dc74-4ca3-acd1-96feb2ecf3ad/server/dist/vitest.config.js +19 -0
- package/.vibetree/worktrees/46276a4e-dc74-4ca3-acd1-96feb2ecf3ad/server/package.json +44 -0
- package/.vibetree/worktrees/46276a4e-dc74-4ca3-acd1-96feb2ecf3ad/server/tsconfig.json +20 -0
- package/.vibetree/worktrees/46276a4e-dc74-4ca3-acd1-96feb2ecf3ad/server/vitest.config.ts +18 -0
- package/bin/vibetree.js +17 -54
- package/client/package.json +2 -2
- package/client/src/App.tsx +1 -0
- package/client/src/trpc.ts +1 -1
- package/client/vite.config.ts +10 -0
- package/package.json +2 -2
- package/server/dist/api/router.js +278 -0
- package/server/dist/api/trpc.js +7 -0
- package/server/dist/config/index.js +45 -0
- package/server/dist/db.js +3 -2
- package/server/dist/index.js +6 -6
- package/server/dist/services/db.js +209 -0
- package/server/dist/services/git.js +100 -0
- package/server/dist/services/tasks.js +7 -0
- package/server/dist/services/terminal.js +203 -0
- package/server/dist/src/api/router.js +278 -0
- package/server/dist/src/api/trpc.js +7 -0
- package/server/dist/src/config/index.js +45 -0
- package/server/dist/src/index.js +121 -0
- package/server/dist/src/services/db.js +209 -0
- package/server/dist/src/services/git.js +100 -0
- package/server/dist/src/services/tasks.js +7 -0
- package/server/dist/src/services/terminal.js +203 -0
- package/server/dist/src/types/index.js +2 -0
- package/server/dist/types/index.js +2 -0
- package/server/package.json +2 -2
- package/server/{router.ts → src/api/router.ts} +5 -5
- package/server/src/api/trpc.ts +16 -0
- package/server/src/config/index.ts +43 -0
- package/server/src/index.ts +112 -0
- package/server/src/services/db.ts +217 -0
- package/server/src/services/git.ts +108 -0
- package/server/src/services/tasks.ts +8 -0
- package/server/src/services/terminal.ts +181 -0
- package/server/src/types/index.ts +33 -0
- package/server/tsconfig.json +3 -3
- package/.vibetree/worktrees/32fa1562-8457-4084-b833-db88c38d249e/client/dist/assets/index-CID86LBU.css +0 -32
- /package/.vibetree/worktrees/{d9baadc6-9864-472d-afa8-ee208877e85f → 3020aa56-a7a7-46c4-a452-b558cf6eadfd}/.github/workflows/lint.yml +0 -0
- /package/.vibetree/worktrees/{d9baadc6-9864-472d-afa8-ee208877e85f → 3020aa56-a7a7-46c4-a452-b558cf6eadfd}/.github/workflows/test.yml +0 -0
- /package/.vibetree/worktrees/{d9baadc6-9864-472d-afa8-ee208877e85f → 3020aa56-a7a7-46c4-a452-b558cf6eadfd}/.node-version +0 -0
- /package/.vibetree/worktrees/{d9baadc6-9864-472d-afa8-ee208877e85f → 3020aa56-a7a7-46c4-a452-b558cf6eadfd}/client/.eslintrc.cjs +0 -0
- /package/.vibetree/worktrees/{d9baadc6-9864-472d-afa8-ee208877e85f → 3020aa56-a7a7-46c4-a452-b558cf6eadfd}/client/index.html +0 -0
- /package/.vibetree/worktrees/{d9baadc6-9864-472d-afa8-ee208877e85f → 3020aa56-a7a7-46c4-a452-b558cf6eadfd}/client/postcss.config.js +0 -0
- /package/.vibetree/worktrees/{d9baadc6-9864-472d-afa8-ee208877e85f → 3020aa56-a7a7-46c4-a452-b558cf6eadfd}/client/public/favicon.svg +0 -0
- /package/.vibetree/worktrees/{d9baadc6-9864-472d-afa8-ee208877e85f → 3020aa56-a7a7-46c4-a452-b558cf6eadfd}/client/src/App.tsx +0 -0
- /package/.vibetree/worktrees/{32fa1562-8457-4084-b833-db88c38d249e → 3020aa56-a7a7-46c4-a452-b558cf6eadfd}/client/src/assets/react.svg +0 -0
- /package/.vibetree/worktrees/{d9baadc6-9864-472d-afa8-ee208877e85f → 3020aa56-a7a7-46c4-a452-b558cf6eadfd}/client/src/components/ConfirmationModal.tsx +0 -0
- /package/.vibetree/worktrees/{d9baadc6-9864-472d-afa8-ee208877e85f → 3020aa56-a7a7-46c4-a452-b558cf6eadfd}/client/src/components/CreateTaskModal.tsx +0 -0
- /package/.vibetree/worktrees/{d9baadc6-9864-472d-afa8-ee208877e85f → 3020aa56-a7a7-46c4-a452-b558cf6eadfd}/client/src/components/KanbanBoard.tsx +0 -0
- /package/.vibetree/worktrees/{d9baadc6-9864-472d-afa8-ee208877e85f → 3020aa56-a7a7-46c4-a452-b558cf6eadfd}/client/src/components/LanguageSelector.tsx +0 -0
- /package/.vibetree/worktrees/{d9baadc6-9864-472d-afa8-ee208877e85f → 3020aa56-a7a7-46c4-a452-b558cf6eadfd}/client/src/components/RepoModal.tsx +0 -0
- /package/.vibetree/worktrees/{32fa1562-8457-4084-b833-db88c38d249e → 3020aa56-a7a7-46c4-a452-b558cf6eadfd}/client/src/components/Tabs.tsx +0 -0
- /package/.vibetree/worktrees/{d9baadc6-9864-472d-afa8-ee208877e85f → 3020aa56-a7a7-46c4-a452-b558cf6eadfd}/client/src/components/TaskDetail.tsx +0 -0
- /package/.vibetree/worktrees/{32fa1562-8457-4084-b833-db88c38d249e → 3020aa56-a7a7-46c4-a452-b558cf6eadfd}/client/src/components/TerminalView.tsx +0 -0
- /package/.vibetree/worktrees/{d9baadc6-9864-472d-afa8-ee208877e85f → 3020aa56-a7a7-46c4-a452-b558cf6eadfd}/client/src/context/TaskContext.tsx +0 -0
- /package/.vibetree/worktrees/{d9baadc6-9864-472d-afa8-ee208877e85f → 3020aa56-a7a7-46c4-a452-b558cf6eadfd}/client/src/context/TerminalContext.tsx +0 -0
- /package/.vibetree/worktrees/{d9baadc6-9864-472d-afa8-ee208877e85f → 3020aa56-a7a7-46c4-a452-b558cf6eadfd}/client/src/i18n/config.ts +0 -0
- /package/.vibetree/worktrees/{d9baadc6-9864-472d-afa8-ee208877e85f → 3020aa56-a7a7-46c4-a452-b558cf6eadfd}/client/src/i18n/locales/en.json +0 -0
- /package/.vibetree/worktrees/{d9baadc6-9864-472d-afa8-ee208877e85f → 3020aa56-a7a7-46c4-a452-b558cf6eadfd}/client/src/i18n/locales/ja.json +0 -0
- /package/.vibetree/worktrees/{d9baadc6-9864-472d-afa8-ee208877e85f → 3020aa56-a7a7-46c4-a452-b558cf6eadfd}/client/src/i18n/locales/ko.json +0 -0
- /package/.vibetree/worktrees/{d9baadc6-9864-472d-afa8-ee208877e85f → 3020aa56-a7a7-46c4-a452-b558cf6eadfd}/client/src/i18n/locales/zh.json +0 -0
- /package/.vibetree/worktrees/{d9baadc6-9864-472d-afa8-ee208877e85f → 3020aa56-a7a7-46c4-a452-b558cf6eadfd}/client/src/index.css +0 -0
- /package/.vibetree/worktrees/{d9baadc6-9864-472d-afa8-ee208877e85f → 3020aa56-a7a7-46c4-a452-b558cf6eadfd}/client/src/main.tsx +0 -0
- /package/.vibetree/worktrees/{d9baadc6-9864-472d-afa8-ee208877e85f → 3020aa56-a7a7-46c4-a452-b558cf6eadfd}/client/src/trpc.ts +0 -0
- /package/.vibetree/worktrees/{d9baadc6-9864-472d-afa8-ee208877e85f → 3020aa56-a7a7-46c4-a452-b558cf6eadfd}/client/src/types.ts +0 -0
- /package/.vibetree/worktrees/{d9baadc6-9864-472d-afa8-ee208877e85f → 3020aa56-a7a7-46c4-a452-b558cf6eadfd}/client/tailwind.config.js +0 -0
- /package/.vibetree/worktrees/{d9baadc6-9864-472d-afa8-ee208877e85f → 3020aa56-a7a7-46c4-a452-b558cf6eadfd}/client/tsconfig.json +0 -0
- /package/.vibetree/worktrees/{d9baadc6-9864-472d-afa8-ee208877e85f → 3020aa56-a7a7-46c4-a452-b558cf6eadfd}/client/tsconfig.node.json +0 -0
- /package/.vibetree/worktrees/{d9baadc6-9864-472d-afa8-ee208877e85f → 3020aa56-a7a7-46c4-a452-b558cf6eadfd}/client/vite.config.ts +0 -0
- /package/.vibetree/worktrees/{d9baadc6-9864-472d-afa8-ee208877e85f → 3020aa56-a7a7-46c4-a452-b558cf6eadfd}/server/README_TESTS.md +0 -0
- /package/.vibetree/worktrees/{d9baadc6-9864-472d-afa8-ee208877e85f → 3020aa56-a7a7-46c4-a452-b558cf6eadfd}/server/config.test.ts +0 -0
- /package/.vibetree/worktrees/{d9baadc6-9864-472d-afa8-ee208877e85f → 3020aa56-a7a7-46c4-a452-b558cf6eadfd}/server/config.ts +0 -0
- /package/.vibetree/worktrees/{d9baadc6-9864-472d-afa8-ee208877e85f → 3020aa56-a7a7-46c4-a452-b558cf6eadfd}/server/db.test.ts +0 -0
- /package/.vibetree/worktrees/{d9baadc6-9864-472d-afa8-ee208877e85f → 3020aa56-a7a7-46c4-a452-b558cf6eadfd}/server/db.ts +0 -0
- /package/.vibetree/worktrees/{d9baadc6-9864-472d-afa8-ee208877e85f → 3020aa56-a7a7-46c4-a452-b558cf6eadfd}/server/git.test.ts +0 -0
- /package/.vibetree/worktrees/{d9baadc6-9864-472d-afa8-ee208877e85f → 3020aa56-a7a7-46c4-a452-b558cf6eadfd}/server/git.ts +0 -0
- /package/.vibetree/worktrees/{d9baadc6-9864-472d-afa8-ee208877e85f → 3020aa56-a7a7-46c4-a452-b558cf6eadfd}/server/index.ts +0 -0
- /package/.vibetree/worktrees/{d9baadc6-9864-472d-afa8-ee208877e85f → 3020aa56-a7a7-46c4-a452-b558cf6eadfd}/server/router.test.ts +0 -0
- /package/.vibetree/worktrees/{d9baadc6-9864-472d-afa8-ee208877e85f → 3020aa56-a7a7-46c4-a452-b558cf6eadfd}/server/tasks.test.ts +0 -0
- /package/.vibetree/worktrees/{d9baadc6-9864-472d-afa8-ee208877e85f → 3020aa56-a7a7-46c4-a452-b558cf6eadfd}/server/tasks.ts +0 -0
- /package/.vibetree/worktrees/{d9baadc6-9864-472d-afa8-ee208877e85f → 3020aa56-a7a7-46c4-a452-b558cf6eadfd}/server/terminal.ts +0 -0
- /package/.vibetree/worktrees/{d9baadc6-9864-472d-afa8-ee208877e85f → 3020aa56-a7a7-46c4-a452-b558cf6eadfd}/server/trpc.ts +0 -0
- /package/.vibetree/worktrees/{d9baadc6-9864-472d-afa8-ee208877e85f → 3020aa56-a7a7-46c4-a452-b558cf6eadfd}/server/tsconfig.json +0 -0
- /package/.vibetree/worktrees/{d9baadc6-9864-472d-afa8-ee208877e85f → 3020aa56-a7a7-46c4-a452-b558cf6eadfd}/server/types.ts +0 -0
- /package/.vibetree/worktrees/{d9baadc6-9864-472d-afa8-ee208877e85f → 3020aa56-a7a7-46c4-a452-b558cf6eadfd}/server/vitest.config.ts +0 -0
- /package/.vibetree/worktrees/{d9baadc6-9864-472d-afa8-ee208877e85f → 46276a4e-dc74-4ca3-acd1-96feb2ecf3ad}/client/src/assets/react.svg +0 -0
- /package/.vibetree/worktrees/{d9baadc6-9864-472d-afa8-ee208877e85f → 46276a4e-dc74-4ca3-acd1-96feb2ecf3ad}/client/src/components/Tabs.tsx +0 -0
- /package/.vibetree/worktrees/{d9baadc6-9864-472d-afa8-ee208877e85f → 46276a4e-dc74-4ca3-acd1-96feb2ecf3ad}/client/src/components/TerminalView.tsx +0 -0
- /package/{server → .vibetree/worktrees/46276a4e-dc74-4ca3-acd1-96feb2ecf3ad/server}/config.test.ts +0 -0
- /package/{server → .vibetree/worktrees/46276a4e-dc74-4ca3-acd1-96feb2ecf3ad/server}/config.ts +0 -0
- /package/{server → .vibetree/worktrees/46276a4e-dc74-4ca3-acd1-96feb2ecf3ad/server}/db.test.ts +0 -0
- /package/{server → .vibetree/worktrees/46276a4e-dc74-4ca3-acd1-96feb2ecf3ad/server}/db.ts +0 -0
- /package/{server → .vibetree/worktrees/46276a4e-dc74-4ca3-acd1-96feb2ecf3ad/server}/git.test.ts +0 -0
- /package/{server → .vibetree/worktrees/46276a4e-dc74-4ca3-acd1-96feb2ecf3ad/server}/git.ts +0 -0
- /package/{server → .vibetree/worktrees/46276a4e-dc74-4ca3-acd1-96feb2ecf3ad/server}/index.ts +0 -0
- /package/{server → .vibetree/worktrees/46276a4e-dc74-4ca3-acd1-96feb2ecf3ad/server}/router.test.ts +0 -0
- /package/.vibetree/worktrees/{d9baadc6-9864-472d-afa8-ee208877e85f → 46276a4e-dc74-4ca3-acd1-96feb2ecf3ad}/server/router.ts +0 -0
- /package/{server → .vibetree/worktrees/46276a4e-dc74-4ca3-acd1-96feb2ecf3ad/server}/tasks.test.ts +0 -0
- /package/{server → .vibetree/worktrees/46276a4e-dc74-4ca3-acd1-96feb2ecf3ad/server}/tasks.ts +0 -0
- /package/{server → .vibetree/worktrees/46276a4e-dc74-4ca3-acd1-96feb2ecf3ad/server}/terminal.ts +0 -0
- /package/{server → .vibetree/worktrees/46276a4e-dc74-4ca3-acd1-96feb2ecf3ad/server}/trpc.ts +0 -0
- /package/{server → .vibetree/worktrees/46276a4e-dc74-4ca3-acd1-96feb2ecf3ad/server}/types.ts +0 -0
|
@@ -4,77 +4,40 @@ const path = require('path');
|
|
|
4
4
|
const { spawn, spawnSync } = require('child_process');
|
|
5
5
|
const yargs = require('yargs/yargs');
|
|
6
6
|
const { hideBin } = require('yargs/helpers');
|
|
7
|
-
const prompts = require('prompts');
|
|
8
7
|
// const open = require('open'); // Moved to dynamic import
|
|
9
8
|
|
|
10
|
-
const argv = yargs(hideBin(process.argv))
|
|
11
|
-
.option('repo', {
|
|
12
|
-
alias: 'r',
|
|
13
|
-
type: 'string',
|
|
14
|
-
description: 'Path to target repository',
|
|
15
|
-
})
|
|
16
|
-
.option('ai', {
|
|
17
|
-
alias: 'a',
|
|
18
|
-
type: 'string',
|
|
19
|
-
choices: ['claude', 'codex', 'gemini'],
|
|
20
|
-
description: 'AI tool to use',
|
|
21
|
-
})
|
|
22
|
-
.argv;
|
|
9
|
+
const argv = yargs(hideBin(process.argv)).argv;
|
|
23
10
|
|
|
24
|
-
|
|
25
|
-
|
|
26
|
-
|
|
27
|
-
|
|
28
|
-
|
|
29
|
-
|
|
30
|
-
|
|
31
|
-
|
|
32
|
-
|
|
33
|
-
}
|
|
34
|
-
|
|
35
|
-
// 2. Resolve AI Tool
|
|
36
|
-
const configPath = path.join(repoPath, '.vibetree', 'config.json');
|
|
37
|
-
let config = {};
|
|
38
|
-
if (fs.existsSync(configPath)) {
|
|
39
|
-
try {
|
|
40
|
-
config = JSON.parse(fs.readFileSync(configPath, 'utf8'));
|
|
41
|
-
} catch (e) { }
|
|
11
|
+
async function verifyNativeModules(pkgRoot) {
|
|
12
|
+
try {
|
|
13
|
+
require(require.resolve('node-pty', { paths: [path.join(pkgRoot, 'node_modules'), pkgRoot] }));
|
|
14
|
+
require(require.resolve('better-sqlite3', { paths: [path.join(pkgRoot, 'node_modules'), pkgRoot] }));
|
|
15
|
+
} catch (e) {
|
|
16
|
+
if (e.code === 'ERR_DLOPEN_FAILED' || (e.message && e.message.includes('Node.js version'))) {
|
|
17
|
+
console.log('\x1b[33m%s\x1b[0m', 'Binary mismatch detected. Rebuilding native modules for your Node.js version...');
|
|
18
|
+
spawnSync('npm', ['rebuild', 'node-pty', 'better-sqlite3'], { cwd: pkgRoot, stdio: 'inherit', shell: true });
|
|
19
|
+
}
|
|
42
20
|
}
|
|
21
|
+
}
|
|
43
22
|
|
|
44
|
-
|
|
23
|
+
(async () => {
|
|
24
|
+
const pkgRoot = path.join(__dirname, '..');
|
|
45
25
|
|
|
46
|
-
|
|
47
|
-
|
|
48
|
-
type: 'select',
|
|
49
|
-
name: 'aiTool',
|
|
50
|
-
message: 'Select AI tool to use:',
|
|
51
|
-
choices: [
|
|
52
|
-
{ title: 'Claude', value: 'claude' },
|
|
53
|
-
{ title: 'Codex (OpenAI)', value: 'codex' },
|
|
54
|
-
{ title: 'Gemini', value: 'gemini' },
|
|
55
|
-
],
|
|
56
|
-
});
|
|
57
|
-
aiTool = response.aiTool;
|
|
26
|
+
// Verify native modules before proceeding
|
|
27
|
+
await verifyNativeModules(pkgRoot);
|
|
58
28
|
|
|
59
|
-
|
|
60
|
-
|
|
61
|
-
if (!fs.existsSync(vibeDir)) fs.mkdirSync(vibeDir, { recursive: true });
|
|
62
|
-
fs.writeFileSync(path.join(vibeDir, 'config.json'), JSON.stringify({ aiTool }, null, 2));
|
|
63
|
-
}
|
|
29
|
+
const PORT = process.env.VIBETREE_PORT || 5179;
|
|
30
|
+
const repoPath = process.cwd();
|
|
64
31
|
|
|
65
32
|
console.log(`Starting VibeTree...`);
|
|
66
|
-
console.log(`Repository: ${repoPath}`);
|
|
67
|
-
console.log(`AI Tool: ${aiTool}`);
|
|
68
33
|
console.log(`Port: ${PORT}`);
|
|
69
34
|
|
|
70
35
|
// 3. Start Server
|
|
71
|
-
const pkgRoot = path.join(__dirname, '..');
|
|
72
36
|
const serverPath = path.join(pkgRoot, 'server', 'dist', 'index.js');
|
|
73
37
|
const clientPath = path.join(pkgRoot, 'client', 'dist');
|
|
74
38
|
const env = {
|
|
75
39
|
...process.env,
|
|
76
40
|
REPO_PATH: repoPath,
|
|
77
|
-
AI_TOOL: aiTool,
|
|
78
41
|
VIBETREE_PORT: PORT,
|
|
79
42
|
};
|
|
80
43
|
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "vibetree",
|
|
3
|
-
"version": "1.2.
|
|
3
|
+
"version": "1.2.1",
|
|
4
4
|
"description": "Local task management with Git worktrees and AI integration",
|
|
5
5
|
"main": "bin/vibetree.js",
|
|
6
6
|
"bin": {
|
|
@@ -66,4 +66,4 @@
|
|
|
66
66
|
"tailwindcss": "^3.4.19",
|
|
67
67
|
"vite": "^5.1.0"
|
|
68
68
|
}
|
|
69
|
-
}
|
|
69
|
+
}
|
|
@@ -0,0 +1,274 @@
|
|
|
1
|
+
import { z } from 'zod';
|
|
2
|
+
import { router, publicProcedure } from './trpc';
|
|
3
|
+
import { v4 as uuidv4 } from 'uuid';
|
|
4
|
+
import { Task } from './types';
|
|
5
|
+
import { createWorktree, runGit } from './git';
|
|
6
|
+
import { exec } from 'child_process';
|
|
7
|
+
import util from 'util';
|
|
8
|
+
import os from 'os';
|
|
9
|
+
import path from 'path';
|
|
10
|
+
import fs from 'fs';
|
|
11
|
+
import { saveConfig } from './config';
|
|
12
|
+
import {
|
|
13
|
+
getRepositories,
|
|
14
|
+
getRepositoryByPath,
|
|
15
|
+
addRepository,
|
|
16
|
+
getTasks,
|
|
17
|
+
getTaskById,
|
|
18
|
+
createTask,
|
|
19
|
+
updateTask,
|
|
20
|
+
deleteTask,
|
|
21
|
+
normalizePath
|
|
22
|
+
} from './db';
|
|
23
|
+
|
|
24
|
+
const execAsync = util.promisify(exec);
|
|
25
|
+
|
|
26
|
+
function slugify(text: string): string {
|
|
27
|
+
return text
|
|
28
|
+
.toString()
|
|
29
|
+
.normalize('NFD')
|
|
30
|
+
.replace(/[\u0300-\u036f]/g, '')
|
|
31
|
+
.toLowerCase()
|
|
32
|
+
.trim()
|
|
33
|
+
.replace(/\s+/g, '-')
|
|
34
|
+
.replace(/[^\w-]+/g, '')
|
|
35
|
+
.replace(/--+/g, '-');
|
|
36
|
+
}
|
|
37
|
+
|
|
38
|
+
export const appRouter = router({
|
|
39
|
+
// Config Procedures
|
|
40
|
+
getConfig: publicProcedure.query(({ ctx }) => {
|
|
41
|
+
return ctx.getState();
|
|
42
|
+
}),
|
|
43
|
+
updateConfig: publicProcedure
|
|
44
|
+
.input(z.object({
|
|
45
|
+
repoPath: z.string().optional(),
|
|
46
|
+
aiTool: z.string().optional(),
|
|
47
|
+
copyFiles: z.string().optional(),
|
|
48
|
+
}))
|
|
49
|
+
.mutation(async ({ input, ctx }) => {
|
|
50
|
+
const state = ctx.getState();
|
|
51
|
+
if (input.repoPath !== undefined) {
|
|
52
|
+
if (input.repoPath && !fs.existsSync(input.repoPath)) {
|
|
53
|
+
throw new Error('Path does not exist');
|
|
54
|
+
}
|
|
55
|
+
const normalized = normalizePath(input.repoPath || '');
|
|
56
|
+
state.repoPath = normalized;
|
|
57
|
+
if (normalized) {
|
|
58
|
+
addRepository(normalized, input.copyFiles);
|
|
59
|
+
}
|
|
60
|
+
}
|
|
61
|
+
if (input.aiTool !== undefined) state.aiTool = input.aiTool;
|
|
62
|
+
if (input.copyFiles !== undefined) {
|
|
63
|
+
state.copyFiles = input.copyFiles;
|
|
64
|
+
// Update copyFiles for active repo if it exists
|
|
65
|
+
const repo = getRepositoryByPath(state.repoPath);
|
|
66
|
+
if (repo) {
|
|
67
|
+
const { updateRepository } = await import('./db');
|
|
68
|
+
updateRepository(repo.id, { copyFiles: input.copyFiles });
|
|
69
|
+
}
|
|
70
|
+
}
|
|
71
|
+
|
|
72
|
+
await saveConfig(state);
|
|
73
|
+
return state;
|
|
74
|
+
}),
|
|
75
|
+
|
|
76
|
+
getRepositories: publicProcedure.query(async () => {
|
|
77
|
+
return getRepositories();
|
|
78
|
+
}),
|
|
79
|
+
|
|
80
|
+
addRepository: publicProcedure
|
|
81
|
+
.input(z.object({ path: z.string(), copyFiles: z.string().optional() }))
|
|
82
|
+
.mutation(async ({ input }) => {
|
|
83
|
+
return addRepository(input.path, input.copyFiles);
|
|
84
|
+
}),
|
|
85
|
+
|
|
86
|
+
// Task Procedures
|
|
87
|
+
getTasks: publicProcedure
|
|
88
|
+
.input(z.object({ repoPath: z.string() }))
|
|
89
|
+
.query(async ({ input }) => {
|
|
90
|
+
const repo = getRepositoryByPath(input.repoPath);
|
|
91
|
+
if (!repo) return [];
|
|
92
|
+
return getTasks(repo.id);
|
|
93
|
+
}),
|
|
94
|
+
createTask: publicProcedure
|
|
95
|
+
.input(z.object({
|
|
96
|
+
repoPath: z.string(),
|
|
97
|
+
title: z.string(),
|
|
98
|
+
description: z.string().optional(),
|
|
99
|
+
}))
|
|
100
|
+
.mutation(async ({ input, ctx }) => {
|
|
101
|
+
let repo = getRepositoryByPath(input.repoPath);
|
|
102
|
+
if (!repo) {
|
|
103
|
+
repo = addRepository(input.repoPath);
|
|
104
|
+
}
|
|
105
|
+
|
|
106
|
+
const slug = slugify(input.title);
|
|
107
|
+
const shortHash = uuidv4().split('-')[0];
|
|
108
|
+
const branchName = `feature/task-${slug.substring(0, 50)}-${shortHash}`;
|
|
109
|
+
|
|
110
|
+
const newTask = createTask(repo.id, {
|
|
111
|
+
title: input.title,
|
|
112
|
+
description: input.description || '',
|
|
113
|
+
branchName: branchName
|
|
114
|
+
});
|
|
115
|
+
|
|
116
|
+
// Handle side effects (worktree, terminal, AI)
|
|
117
|
+
if (input.repoPath && ctx.createWorktree && ctx.ensureTerminalForTask && ctx.runAiForTask) {
|
|
118
|
+
try {
|
|
119
|
+
console.log(`[tRPC] Creating worktree for task ${newTask.id} in ${input.repoPath}`);
|
|
120
|
+
await ctx.createWorktree(input.repoPath, newTask.id, newTask.branchName || '');
|
|
121
|
+
|
|
122
|
+
console.log(`[tRPC] Ensuring terminal for task ${newTask.id}`);
|
|
123
|
+
await ctx.ensureTerminalForTask(newTask.id, input.repoPath);
|
|
124
|
+
|
|
125
|
+
console.log(`[tRPC] Running AI for task ${newTask.id}`);
|
|
126
|
+
ctx.runAiForTask(newTask.id, input.repoPath).catch(e => console.error(`[tRPC] runAiForTask error:`, e));
|
|
127
|
+
} catch (e) {
|
|
128
|
+
console.error(`[tRPC] Side effects failed for task ${newTask.id}:`, e);
|
|
129
|
+
}
|
|
130
|
+
}
|
|
131
|
+
|
|
132
|
+
return newTask;
|
|
133
|
+
}),
|
|
134
|
+
updateTask: publicProcedure
|
|
135
|
+
.input(z.object({
|
|
136
|
+
repoPath: z.string(),
|
|
137
|
+
id: z.string(),
|
|
138
|
+
updates: z.object({
|
|
139
|
+
title: z.string().optional(),
|
|
140
|
+
description: z.string().optional(),
|
|
141
|
+
}),
|
|
142
|
+
}))
|
|
143
|
+
.mutation(async ({ input }) => {
|
|
144
|
+
const task = getTaskById(input.id);
|
|
145
|
+
if (!task) throw new Error('Task not found');
|
|
146
|
+
return updateTask(input.id, input.updates);
|
|
147
|
+
}),
|
|
148
|
+
deleteTask: publicProcedure
|
|
149
|
+
.input(z.object({ repoPath: z.string(), taskId: z.string() }))
|
|
150
|
+
.mutation(async ({ input, ctx }) => {
|
|
151
|
+
const task = getTaskById(input.taskId);
|
|
152
|
+
if (!task) throw new Error('Task not found');
|
|
153
|
+
|
|
154
|
+
// Cleanup side effects
|
|
155
|
+
if (ctx.shutdownTerminalForTask) {
|
|
156
|
+
console.log(`[tRPC] Shutting down terminal for task ${input.taskId}`);
|
|
157
|
+
await ctx.shutdownTerminalForTask(input.taskId);
|
|
158
|
+
}
|
|
159
|
+
if (input.repoPath && ctx.removeWorktree) {
|
|
160
|
+
console.log(`[tRPC] Removing worktree and branch for task ${input.taskId} (${task.branchName})`);
|
|
161
|
+
try {
|
|
162
|
+
await ctx.removeWorktree(input.repoPath, input.taskId, task.branchName);
|
|
163
|
+
} catch (e) {
|
|
164
|
+
console.error(`[tRPC] Failed to remove worktree/branch:`, e);
|
|
165
|
+
}
|
|
166
|
+
}
|
|
167
|
+
|
|
168
|
+
deleteTask(input.taskId);
|
|
169
|
+
return { success: true };
|
|
170
|
+
}),
|
|
171
|
+
|
|
172
|
+
// Git Procedures
|
|
173
|
+
getGitStatus: publicProcedure
|
|
174
|
+
.input(z.object({ repoPath: z.string(), taskId: z.string().optional() }))
|
|
175
|
+
.query(async ({ input }) => {
|
|
176
|
+
const cwd = input.taskId ? path.join(input.repoPath, '.vibetree', 'worktrees', input.taskId) : input.repoPath;
|
|
177
|
+
const branch = await runGit('git branch --show-current', cwd, input.repoPath);
|
|
178
|
+
const status = await runGit('git status --short', cwd, input.repoPath);
|
|
179
|
+
return { branch, status };
|
|
180
|
+
}),
|
|
181
|
+
getGitDiff: publicProcedure
|
|
182
|
+
.input(z.object({ repoPath: z.string(), taskId: z.string().optional() }))
|
|
183
|
+
.query(async ({ input }) => {
|
|
184
|
+
const cwd = input.taskId ? path.join(input.repoPath, '.vibetree', 'worktrees', input.taskId) : input.repoPath;
|
|
185
|
+
const diff = await runGit('git diff', cwd, input.repoPath);
|
|
186
|
+
return { diff };
|
|
187
|
+
}),
|
|
188
|
+
createCommit: publicProcedure
|
|
189
|
+
.input(z.object({
|
|
190
|
+
repoPath: z.string(),
|
|
191
|
+
taskId: z.string().optional(),
|
|
192
|
+
message: z.string(),
|
|
193
|
+
}))
|
|
194
|
+
.mutation(async ({ input }) => {
|
|
195
|
+
const cwd = input.taskId ? path.join(input.repoPath, '.vibetree', 'worktrees', input.taskId) : input.repoPath;
|
|
196
|
+
await runGit('git add .', cwd, input.repoPath);
|
|
197
|
+
await runGit(`git commit -m "${input.message}"`, cwd, input.repoPath);
|
|
198
|
+
return { success: true };
|
|
199
|
+
}),
|
|
200
|
+
getWorktreePath: publicProcedure
|
|
201
|
+
.input(z.object({ repoPath: z.string(), taskId: z.string() }))
|
|
202
|
+
.query(({ input }) => {
|
|
203
|
+
const worktreePath = path.join(input.repoPath, '.vibetree', 'worktrees', input.taskId);
|
|
204
|
+
return { path: worktreePath };
|
|
205
|
+
}),
|
|
206
|
+
|
|
207
|
+
// System Procedures
|
|
208
|
+
openDirectory: publicProcedure
|
|
209
|
+
.input(z.object({ path: z.string() }))
|
|
210
|
+
.mutation(async ({ input }) => {
|
|
211
|
+
let command: string;
|
|
212
|
+
switch (os.platform()) {
|
|
213
|
+
case 'darwin':
|
|
214
|
+
command = `open "${input.path}"`;
|
|
215
|
+
break;
|
|
216
|
+
case 'win32':
|
|
217
|
+
command = `start "" "${input.path}"`;
|
|
218
|
+
break;
|
|
219
|
+
default:
|
|
220
|
+
command = `xdg-open "${input.path}"`;
|
|
221
|
+
break;
|
|
222
|
+
}
|
|
223
|
+
await execAsync(command);
|
|
224
|
+
return { success: true };
|
|
225
|
+
}),
|
|
226
|
+
pickFolder: publicProcedure.mutation(async () => {
|
|
227
|
+
let command: string | undefined;
|
|
228
|
+
if (os.platform() === 'darwin') {
|
|
229
|
+
command = `osascript -e 'POSIX path of (choose folder with prompt "Select a Git Repository")'`;
|
|
230
|
+
} else if (os.platform() === 'win32') {
|
|
231
|
+
command = `powershell -Command "Add-Type -AssemblyName System.Windows.Forms; $f = New-Object System.Windows.Forms.FolderBrowserDialog; $f.ShowDialog() | Out-Null; $f.SelectedPath"`;
|
|
232
|
+
} else {
|
|
233
|
+
throw new Error('Directory picker not supported on this platform');
|
|
234
|
+
}
|
|
235
|
+
|
|
236
|
+
const { stdout } = await execAsync(command);
|
|
237
|
+
const resultPath = stdout.trim();
|
|
238
|
+
return resultPath ? { path: resultPath } : { canceled: true };
|
|
239
|
+
}),
|
|
240
|
+
getAiTools: publicProcedure.query(async () => {
|
|
241
|
+
const tools = ['claude', 'codex', 'gemini'];
|
|
242
|
+
const results: Record<string, boolean> = {};
|
|
243
|
+
const commonPaths = [
|
|
244
|
+
'/opt/homebrew/bin',
|
|
245
|
+
'/usr/local/bin',
|
|
246
|
+
'/usr/bin',
|
|
247
|
+
'/bin',
|
|
248
|
+
(process.env.HOME || '') + '/.local/bin',
|
|
249
|
+
(process.env.HOME || '') + '/bin',
|
|
250
|
+
];
|
|
251
|
+
const envPath = process.env.PATH || '';
|
|
252
|
+
const extendedPath = commonPaths.join(path.delimiter) + path.delimiter + envPath;
|
|
253
|
+
|
|
254
|
+
for (const tool of tools) {
|
|
255
|
+
let found = false;
|
|
256
|
+
try {
|
|
257
|
+
const cmd = os.platform() === 'win32' ? `where ${tool}` : `which ${tool}`;
|
|
258
|
+
const { stdout } = await execAsync(cmd, { env: { ...process.env, PATH: extendedPath } });
|
|
259
|
+
if (stdout.trim()) found = true;
|
|
260
|
+
} catch { }
|
|
261
|
+
|
|
262
|
+
if (!found) {
|
|
263
|
+
for (const p of commonPaths) {
|
|
264
|
+
const binaryPath = path.join(p, tool + (os.platform() === 'win32' ? '.exe' : ''));
|
|
265
|
+
if (fs.existsSync(binaryPath)) { found = true; break; }
|
|
266
|
+
}
|
|
267
|
+
}
|
|
268
|
+
results[tool] = found;
|
|
269
|
+
}
|
|
270
|
+
return results;
|
|
271
|
+
}),
|
|
272
|
+
});
|
|
273
|
+
|
|
274
|
+
export type AppRouter = typeof appRouter;
|