vibeman 0.0.5 → 0.0.7

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (239) hide show
  1. package/dist/api.js +43 -0
  2. package/dist/index.js +227 -104
  3. package/dist/ui/assets/index-C_kQPI1m.js +9 -0
  4. package/dist/ui/index.html +12 -0
  5. package/package.json +13 -46
  6. package/README.md +0 -12
  7. package/dist/runtime/api/.tsbuildinfo +0 -1
  8. package/dist/runtime/api/agent/agent-service.d.ts +0 -229
  9. package/dist/runtime/api/agent/agent-service.js +0 -963
  10. package/dist/runtime/api/agent/ai-providers/amp-cli-provider.d.ts +0 -38
  11. package/dist/runtime/api/agent/ai-providers/amp-cli-provider.js +0 -268
  12. package/dist/runtime/api/agent/ai-providers/claude-code-adapter.d.ts +0 -61
  13. package/dist/runtime/api/agent/ai-providers/claude-code-adapter.js +0 -362
  14. package/dist/runtime/api/agent/ai-providers/codex-cli-provider.d.ts +0 -36
  15. package/dist/runtime/api/agent/ai-providers/codex-cli-provider.js +0 -375
  16. package/dist/runtime/api/agent/ai-providers/gemini-cli-provider.d.ts +0 -24
  17. package/dist/runtime/api/agent/ai-providers/gemini-cli-provider.js +0 -291
  18. package/dist/runtime/api/agent/ai-providers/index.d.ts +0 -9
  19. package/dist/runtime/api/agent/ai-providers/index.js +0 -9
  20. package/dist/runtime/api/agent/ai-providers/types.d.ts +0 -185
  21. package/dist/runtime/api/agent/ai-providers/types.js +0 -5
  22. package/dist/runtime/api/agent/amp-cli-provider.test.d.ts +0 -1
  23. package/dist/runtime/api/agent/amp-cli-provider.test.js +0 -99
  24. package/dist/runtime/api/agent/codex-cli-provider.test.d.ts +0 -1
  25. package/dist/runtime/api/agent/codex-cli-provider.test.js +0 -172
  26. package/dist/runtime/api/agent/core-agent-service.d.ts +0 -119
  27. package/dist/runtime/api/agent/core-agent-service.js +0 -267
  28. package/dist/runtime/api/agent/parsers.d.ts +0 -16
  29. package/dist/runtime/api/agent/parsers.js +0 -308
  30. package/dist/runtime/api/agent/prompt-service.d.ts +0 -30
  31. package/dist/runtime/api/agent/prompt-service.js +0 -452
  32. package/dist/runtime/api/agent/prompt-service.test.d.ts +0 -1
  33. package/dist/runtime/api/agent/prompt-service.test.js +0 -265
  34. package/dist/runtime/api/agent/routing-policy.d.ts +0 -171
  35. package/dist/runtime/api/agent/routing-policy.js +0 -196
  36. package/dist/runtime/api/agent/routing-policy.test.d.ts +0 -1
  37. package/dist/runtime/api/agent/routing-policy.test.js +0 -63
  38. package/dist/runtime/api/api/router-helpers.d.ts +0 -32
  39. package/dist/runtime/api/api/router-helpers.js +0 -31
  40. package/dist/runtime/api/api/routers/ai.d.ts +0 -200
  41. package/dist/runtime/api/api/routers/ai.js +0 -396
  42. package/dist/runtime/api/api/routers/executions.d.ts +0 -93
  43. package/dist/runtime/api/api/routers/executions.js +0 -94
  44. package/dist/runtime/api/api/routers/git.d.ts +0 -45
  45. package/dist/runtime/api/api/routers/git.js +0 -35
  46. package/dist/runtime/api/api/routers/provider-config.d.ts +0 -199
  47. package/dist/runtime/api/api/routers/provider-config.js +0 -252
  48. package/dist/runtime/api/api/routers/settings.d.ts +0 -158
  49. package/dist/runtime/api/api/routers/settings.js +0 -129
  50. package/dist/runtime/api/api/routers/tasks.d.ts +0 -141
  51. package/dist/runtime/api/api/routers/tasks.js +0 -238
  52. package/dist/runtime/api/api/routers/workflows.d.ts +0 -275
  53. package/dist/runtime/api/api/routers/workflows.js +0 -311
  54. package/dist/runtime/api/api/routers/worktrees.d.ts +0 -101
  55. package/dist/runtime/api/api/routers/worktrees.js +0 -80
  56. package/dist/runtime/api/api/trpc.d.ts +0 -118
  57. package/dist/runtime/api/api/trpc.js +0 -34
  58. package/dist/runtime/api/index.d.ts +0 -9
  59. package/dist/runtime/api/index.js +0 -117
  60. package/dist/runtime/api/lib/id-generator.d.ts +0 -70
  61. package/dist/runtime/api/lib/id-generator.js +0 -123
  62. package/dist/runtime/api/lib/local-config.d.ts +0 -335
  63. package/dist/runtime/api/lib/local-config.js +0 -304
  64. package/dist/runtime/api/lib/logger.d.ts +0 -11
  65. package/dist/runtime/api/lib/logger.js +0 -188
  66. package/dist/runtime/api/lib/provider-detection.d.ts +0 -61
  67. package/dist/runtime/api/lib/provider-detection.js +0 -326
  68. package/dist/runtime/api/lib/server/agent-service-singleton.d.ts +0 -6
  69. package/dist/runtime/api/lib/server/agent-service-singleton.js +0 -27
  70. package/dist/runtime/api/lib/server/bootstrap.d.ts +0 -38
  71. package/dist/runtime/api/lib/server/bootstrap.js +0 -197
  72. package/dist/runtime/api/lib/server/git-service-singleton.d.ts +0 -6
  73. package/dist/runtime/api/lib/server/git-service-singleton.js +0 -47
  74. package/dist/runtime/api/lib/server/project-root.d.ts +0 -2
  75. package/dist/runtime/api/lib/server/project-root.js +0 -61
  76. package/dist/runtime/api/lib/server/task-service-singleton.d.ts +0 -7
  77. package/dist/runtime/api/lib/server/task-service-singleton.js +0 -58
  78. package/dist/runtime/api/lib/server/vibeman-info.d.ts +0 -5
  79. package/dist/runtime/api/lib/server/vibeman-info.js +0 -85
  80. package/dist/runtime/api/lib/server/vibing-orchestrator-singleton.d.ts +0 -7
  81. package/dist/runtime/api/lib/server/vibing-orchestrator-singleton.js +0 -57
  82. package/dist/runtime/api/lib/trpc/server.d.ts +0 -965
  83. package/dist/runtime/api/lib/trpc/server.js +0 -11
  84. package/dist/runtime/api/lib/trpc/ws-server.d.ts +0 -8
  85. package/dist/runtime/api/lib/trpc/ws-server.js +0 -33
  86. package/dist/runtime/api/persistence/database-service.d.ts +0 -14
  87. package/dist/runtime/api/persistence/database-service.js +0 -74
  88. package/dist/runtime/api/persistence/execution-log-persistence.d.ts +0 -90
  89. package/dist/runtime/api/persistence/execution-log-persistence.js +0 -426
  90. package/dist/runtime/api/persistence/execution-log-persistence.test.d.ts +0 -1
  91. package/dist/runtime/api/persistence/execution-log-persistence.test.js +0 -170
  92. package/dist/runtime/api/router.d.ts +0 -968
  93. package/dist/runtime/api/router.js +0 -34
  94. package/dist/runtime/api/settings-service.d.ts +0 -110
  95. package/dist/runtime/api/settings-service.js +0 -678
  96. package/dist/runtime/api/tasks/file-watcher.d.ts +0 -23
  97. package/dist/runtime/api/tasks/file-watcher.js +0 -88
  98. package/dist/runtime/api/tasks/task-file-parser.d.ts +0 -14
  99. package/dist/runtime/api/tasks/task-file-parser.js +0 -180
  100. package/dist/runtime/api/tasks/task-service.d.ts +0 -36
  101. package/dist/runtime/api/tasks/task-service.js +0 -173
  102. package/dist/runtime/api/tasks/task-updater.d.ts +0 -62
  103. package/dist/runtime/api/tasks/task-updater.js +0 -260
  104. package/dist/runtime/api/tasks/task-updater.test.d.ts +0 -1
  105. package/dist/runtime/api/tasks/task-updater.test.js +0 -303
  106. package/dist/runtime/api/types/index.d.ts +0 -186
  107. package/dist/runtime/api/types/index.js +0 -1
  108. package/dist/runtime/api/types/settings.d.ts +0 -105
  109. package/dist/runtime/api/types/settings.js +0 -2
  110. package/dist/runtime/api/types.d.ts +0 -2
  111. package/dist/runtime/api/types.js +0 -1
  112. package/dist/runtime/api/utils/env.d.ts +0 -6
  113. package/dist/runtime/api/utils/env.js +0 -12
  114. package/dist/runtime/api/utils/stripNextEnv.d.ts +0 -7
  115. package/dist/runtime/api/utils/stripNextEnv.js +0 -22
  116. package/dist/runtime/api/utils/title-slug.d.ts +0 -6
  117. package/dist/runtime/api/utils/title-slug.js +0 -77
  118. package/dist/runtime/api/utils/url.d.ts +0 -2
  119. package/dist/runtime/api/utils/url.js +0 -19
  120. package/dist/runtime/api/vcs/git-history-service.d.ts +0 -57
  121. package/dist/runtime/api/vcs/git-history-service.js +0 -228
  122. package/dist/runtime/api/vcs/git-service.d.ts +0 -136
  123. package/dist/runtime/api/vcs/git-service.js +0 -307
  124. package/dist/runtime/api/vcs/worktree-service.d.ts +0 -93
  125. package/dist/runtime/api/vcs/worktree-service.js +0 -518
  126. package/dist/runtime/api/vcs/worktree-service.test.d.ts +0 -1
  127. package/dist/runtime/api/vcs/worktree-service.test.js +0 -20
  128. package/dist/runtime/api/workflows/quality-pipeline.d.ts +0 -58
  129. package/dist/runtime/api/workflows/quality-pipeline.js +0 -401
  130. package/dist/runtime/api/workflows/vibing-orchestrator.d.ts +0 -406
  131. package/dist/runtime/api/workflows/vibing-orchestrator.js +0 -2462
  132. package/dist/runtime/api/workflows/workflow-effects.d.ts +0 -45
  133. package/dist/runtime/api/workflows/workflow-effects.js +0 -49
  134. package/dist/runtime/api/workflows/workflow-reconciler.d.ts +0 -65
  135. package/dist/runtime/api/workflows/workflow-reconciler.js +0 -226
  136. package/dist/runtime/api/workflows/workflow-reducer.d.ts +0 -26
  137. package/dist/runtime/api/workflows/workflow-reducer.js +0 -288
  138. package/dist/runtime/api/workflows/workflow-reducer.test.d.ts +0 -1
  139. package/dist/runtime/api/workflows/workflow-reducer.test.js +0 -247
  140. package/dist/runtime/api/workflows/workflow-schema.d.ts +0 -546
  141. package/dist/runtime/api/workflows/workflow-schema.js +0 -256
  142. package/dist/runtime/web/.next/BUILD_ID +0 -1
  143. package/dist/runtime/web/.next/app-build-manifest.json +0 -66
  144. package/dist/runtime/web/.next/app-path-routes-manifest.json +0 -8
  145. package/dist/runtime/web/.next/build-manifest.json +0 -33
  146. package/dist/runtime/web/.next/package.json +0 -1
  147. package/dist/runtime/web/.next/prerender-manifest.json +0 -61
  148. package/dist/runtime/web/.next/react-loadable-manifest.json +0 -8
  149. package/dist/runtime/web/.next/required-server-files.json +0 -334
  150. package/dist/runtime/web/.next/routes-manifest.json +0 -70
  151. package/dist/runtime/web/.next/server/app/.vibeman/assets/images/[...path]/route.js +0 -1
  152. package/dist/runtime/web/.next/server/app/.vibeman/assets/images/[...path]/route.js.nft.json +0 -1
  153. package/dist/runtime/web/.next/server/app/.vibeman/assets/images/[...path]/route_client-reference-manifest.js +0 -1
  154. package/dist/runtime/web/.next/server/app/_not-found/page.js +0 -2
  155. package/dist/runtime/web/.next/server/app/_not-found/page.js.nft.json +0 -1
  156. package/dist/runtime/web/.next/server/app/_not-found/page_client-reference-manifest.js +0 -1
  157. package/dist/runtime/web/.next/server/app/_not-found.html +0 -7
  158. package/dist/runtime/web/.next/server/app/_not-found.meta +0 -8
  159. package/dist/runtime/web/.next/server/app/_not-found.rsc +0 -22
  160. package/dist/runtime/web/.next/server/app/api/health/route.js +0 -1
  161. package/dist/runtime/web/.next/server/app/api/health/route.js.nft.json +0 -1
  162. package/dist/runtime/web/.next/server/app/api/health/route_client-reference-manifest.js +0 -1
  163. package/dist/runtime/web/.next/server/app/api/images/[...path]/route.js +0 -1
  164. package/dist/runtime/web/.next/server/app/api/images/[...path]/route.js.nft.json +0 -1
  165. package/dist/runtime/web/.next/server/app/api/images/[...path]/route_client-reference-manifest.js +0 -1
  166. package/dist/runtime/web/.next/server/app/api/upload/route.js +0 -1
  167. package/dist/runtime/web/.next/server/app/api/upload/route.js.nft.json +0 -1
  168. package/dist/runtime/web/.next/server/app/api/upload/route_client-reference-manifest.js +0 -1
  169. package/dist/runtime/web/.next/server/app/index.html +0 -7
  170. package/dist/runtime/web/.next/server/app/index.meta +0 -7
  171. package/dist/runtime/web/.next/server/app/index.rsc +0 -27
  172. package/dist/runtime/web/.next/server/app/page.js +0 -112
  173. package/dist/runtime/web/.next/server/app/page.js.nft.json +0 -1
  174. package/dist/runtime/web/.next/server/app/page_client-reference-manifest.js +0 -1
  175. package/dist/runtime/web/.next/server/app-paths-manifest.json +0 -8
  176. package/dist/runtime/web/.next/server/chunks/210.js +0 -1
  177. package/dist/runtime/web/.next/server/chunks/291.js +0 -18
  178. package/dist/runtime/web/.next/server/chunks/552.js +0 -22
  179. package/dist/runtime/web/.next/server/chunks/780.js +0 -1
  180. package/dist/runtime/web/.next/server/chunks/905.js +0 -6
  181. package/dist/runtime/web/.next/server/chunks/98.js +0 -1
  182. package/dist/runtime/web/.next/server/functions-config-manifest.json +0 -4
  183. package/dist/runtime/web/.next/server/middleware-build-manifest.js +0 -1
  184. package/dist/runtime/web/.next/server/middleware-manifest.json +0 -6
  185. package/dist/runtime/web/.next/server/middleware-react-loadable-manifest.js +0 -1
  186. package/dist/runtime/web/.next/server/next-font-manifest.js +0 -1
  187. package/dist/runtime/web/.next/server/next-font-manifest.json +0 -1
  188. package/dist/runtime/web/.next/server/pages/404.html +0 -7
  189. package/dist/runtime/web/.next/server/pages/500.html +0 -1
  190. package/dist/runtime/web/.next/server/pages/_app.js +0 -1
  191. package/dist/runtime/web/.next/server/pages/_app.js.nft.json +0 -1
  192. package/dist/runtime/web/.next/server/pages/_document.js +0 -1
  193. package/dist/runtime/web/.next/server/pages/_document.js.nft.json +0 -1
  194. package/dist/runtime/web/.next/server/pages/_error.js +0 -19
  195. package/dist/runtime/web/.next/server/pages/_error.js.nft.json +0 -1
  196. package/dist/runtime/web/.next/server/pages-manifest.json +0 -6
  197. package/dist/runtime/web/.next/server/server-reference-manifest.js +0 -1
  198. package/dist/runtime/web/.next/server/server-reference-manifest.json +0 -1
  199. package/dist/runtime/web/.next/server/webpack-runtime.js +0 -1
  200. package/dist/runtime/web/.next/static/LJFZk_8tvKFN_Ee4HqUuM/_buildManifest.js +0 -1
  201. package/dist/runtime/web/.next/static/LJFZk_8tvKFN_Ee4HqUuM/_ssgManifest.js +0 -1
  202. package/dist/runtime/web/.next/static/chunks/05c91ade-7d09b2b280adffd1.js +0 -1
  203. package/dist/runtime/web/.next/static/chunks/201-51bef3fa8c832e2e.js +0 -1
  204. package/dist/runtime/web/.next/static/chunks/524-89747ed9b0294f8a.js +0 -1
  205. package/dist/runtime/web/.next/static/chunks/554-8bec6e9cca6acc67.js +0 -1
  206. package/dist/runtime/web/.next/static/chunks/764.86e9503a69d45a85.js +0 -1
  207. package/dist/runtime/web/.next/static/chunks/7ab4dc20-239138e0ae7af24a.js +0 -1
  208. package/dist/runtime/web/.next/static/chunks/905-342391e3d3a3678f.js +0 -20
  209. package/dist/runtime/web/.next/static/chunks/a8a5ce16-4edea7df2d9b544a.js +0 -79
  210. package/dist/runtime/web/.next/static/chunks/ad74d572-4c1b162e2c15acaa.js +0 -1
  211. package/dist/runtime/web/.next/static/chunks/app/.vibeman/assets/images/[...path]/route-7b752a8641f96c1f.js +0 -1
  212. package/dist/runtime/web/.next/static/chunks/app/_not-found/page-34e66b251c2b5044.js +0 -1
  213. package/dist/runtime/web/.next/static/chunks/app/api/health/route-7b752a8641f96c1f.js +0 -1
  214. package/dist/runtime/web/.next/static/chunks/app/api/images/[...path]/route-7b752a8641f96c1f.js +0 -1
  215. package/dist/runtime/web/.next/static/chunks/app/api/upload/route-7b752a8641f96c1f.js +0 -1
  216. package/dist/runtime/web/.next/static/chunks/app/layout-df9ac93cb02b2385.js +0 -1
  217. package/dist/runtime/web/.next/static/chunks/app/page-6610743f7de5f92a.js +0 -1
  218. package/dist/runtime/web/.next/static/chunks/c25e0690-e9b798b8de667da1.js +0 -1
  219. package/dist/runtime/web/.next/static/chunks/framework-57157ec4d37f64aa.js +0 -1
  220. package/dist/runtime/web/.next/static/chunks/main-app-156cc0c60371bd78.js +0 -1
  221. package/dist/runtime/web/.next/static/chunks/main-df25d367c47b1fec.js +0 -1
  222. package/dist/runtime/web/.next/static/chunks/pages/_app-9f629a5e1131d19f.js +0 -1
  223. package/dist/runtime/web/.next/static/chunks/pages/_error-9238238274c7efcd.js +0 -1
  224. package/dist/runtime/web/.next/static/chunks/polyfills-42372ed130431b0a.js +0 -1
  225. package/dist/runtime/web/.next/static/chunks/webpack-cd50e39b423d1808.js +0 -1
  226. package/dist/runtime/web/.next/static/css/2728291c68f99cb1.css +0 -3
  227. package/dist/runtime/web/.next/static/css/4fbf378a264bd4ea.css +0 -1
  228. package/dist/runtime/web/.next/static/css/521bd69cc298cd1a.css +0 -1
  229. package/dist/runtime/web/.next/static/css/537e22821e101b87.css +0 -1
  230. package/dist/runtime/web/.next/static/media/19cfc7226ec3afaa-s.woff2 +0 -0
  231. package/dist/runtime/web/.next/static/media/21350d82a1f187e9-s.woff2 +0 -0
  232. package/dist/runtime/web/.next/static/media/8e9860b6e62d6359-s.woff2 +0 -0
  233. package/dist/runtime/web/.next/static/media/ba9851c3c22cd980-s.woff2 +0 -0
  234. package/dist/runtime/web/.next/static/media/c5fe6dc8356a8c31-s.woff2 +0 -0
  235. package/dist/runtime/web/.next/static/media/df0a9ae256c0569c-s.woff2 +0 -0
  236. package/dist/runtime/web/.next/static/media/e4af272ccee01ff0-s.p.woff2 +0 -0
  237. package/dist/runtime/web/package.json +0 -65
  238. package/dist/runtime/web/server.js +0 -44
  239. package/dist/tsconfig.tsbuildinfo +0 -1
@@ -1,228 +0,0 @@
1
- import { simpleGit } from 'simple-git';
2
- import { getProjectRoot } from '../lib/server/project-root.js';
3
- import { log } from '../lib/logger.js';
4
- import path from 'path';
5
- export class GitHistoryService {
6
- constructor(projectRoot = getProjectRoot()) {
7
- this.projectRoot = projectRoot;
8
- this.git = simpleGit(projectRoot);
9
- }
10
- /**
11
- * Get the history of changes for a specific task file
12
- */
13
- async getTaskHistory(taskId, limit = 50) {
14
- try {
15
- const taskFilePath = path.join('.vibeman', 'tasks', `${taskId}.md`);
16
- // Check if the task file exists in the current working directory
17
- const taskExists = await this.git.raw(['ls-files', taskFilePath]).then((output) => output.trim().length > 0, () => false);
18
- if (!taskExists) {
19
- // File doesn't exist in Git, return empty history
20
- return [];
21
- }
22
- // Use --follow to track file through renames and --no-merges to avoid merge commits
23
- const logResult = await this.git.raw([
24
- 'log',
25
- '--follow',
26
- '--no-merges',
27
- '--pretty=format:%H|%h|%an|%ad|%s',
28
- '--date=iso',
29
- `--max-count=${limit}`,
30
- '--',
31
- taskFilePath,
32
- ]);
33
- if (!logResult.trim()) {
34
- return [];
35
- }
36
- const commits = logResult.trim().split('\n');
37
- const history = [];
38
- for (const commitLine of commits) {
39
- const [hash, shortHash, author, dateStr, ...messageParts] = commitLine.split('|');
40
- const message = messageParts.join('|'); // Rejoin in case message contains |
41
- if (!hash || !shortHash || !author || !dateStr) {
42
- continue;
43
- }
44
- try {
45
- // Get the diff stats for this specific file in this commit
46
- const stats = await this.getCommitStats(hash, taskFilePath);
47
- history.push({
48
- commitHash: hash,
49
- shortHash,
50
- author,
51
- date: new Date(dateStr),
52
- message,
53
- changes: stats,
54
- });
55
- }
56
- catch (error) {
57
- log.warn('Failed to get stats for commit', { hash, error }, 'git-history-service');
58
- // Add entry without stats
59
- history.push({
60
- commitHash: hash,
61
- shortHash,
62
- author,
63
- date: new Date(dateStr),
64
- message,
65
- changes: { additions: 0, deletions: 0 },
66
- });
67
- }
68
- }
69
- return history;
70
- }
71
- catch (error) {
72
- log.error('Failed to get task history', { taskId, error }, 'git-history-service');
73
- throw new Error(`Failed to retrieve history for task ${taskId}: ${String(error)}`);
74
- }
75
- }
76
- /**
77
- * Get the content of a task file at a specific commit
78
- */
79
- async getTaskVersionContent(taskId, commitHash) {
80
- try {
81
- const taskFilePath = path.join('.vibeman', 'tasks', `${taskId}.md`);
82
- // Get the file content at the specific commit
83
- const content = await this.git.show([`${commitHash}:${taskFilePath}`]);
84
- // Get commit information
85
- const commitInfo = await this.git.raw([
86
- 'show',
87
- '--pretty=format:%an|%ad',
88
- '--date=iso',
89
- '--no-patch',
90
- commitHash,
91
- ]);
92
- const [author, dateStr] = commitInfo.trim().split('|');
93
- return {
94
- commitHash,
95
- content,
96
- date: new Date(dateStr),
97
- author: author || 'Unknown',
98
- };
99
- }
100
- catch (error) {
101
- log.error('Failed to get task version content', { taskId, commitHash, error }, 'git-history-service');
102
- throw new Error(`Failed to retrieve content for task ${taskId} at commit ${commitHash}: ${String(error)}`);
103
- }
104
- }
105
- /**
106
- * Get the diff between two versions of a task file
107
- */
108
- async getTaskDiff(taskId, fromHash, toHash) {
109
- try {
110
- const taskFilePath = path.join('.vibeman', 'tasks', `${taskId}.md`);
111
- // Get the diff between two commits for the specific file
112
- const diff = await this.git.raw(['diff', `${fromHash}..${toHash}`, '--', taskFilePath]);
113
- // Get diff stats
114
- const stats = await this.git.raw([
115
- 'diff',
116
- '--numstat',
117
- `${fromHash}..${toHash}`,
118
- '--',
119
- taskFilePath,
120
- ]);
121
- let additions = 0;
122
- let deletions = 0;
123
- if (stats.trim()) {
124
- const [addStr, delStr] = stats.trim().split('\t');
125
- additions = parseInt(addStr, 10) || 0;
126
- deletions = parseInt(delStr, 10) || 0;
127
- }
128
- return {
129
- fromHash,
130
- toHash,
131
- diff,
132
- additions,
133
- deletions,
134
- };
135
- }
136
- catch (error) {
137
- log.error('Failed to get task diff', { taskId, fromHash, toHash, error }, 'git-history-service');
138
- throw new Error(`Failed to get diff for task ${taskId} between ${fromHash} and ${toHash}: ${String(error)}`);
139
- }
140
- }
141
- /**
142
- * Check if Git repository exists and is properly configured
143
- */
144
- async isGitRepositoryAvailable() {
145
- try {
146
- const isRepo = await this.git.checkIsRepo();
147
- return isRepo;
148
- }
149
- catch {
150
- return false;
151
- }
152
- }
153
- /**
154
- * Get commit statistics for a specific file in a commit
155
- */
156
- async getCommitStats(commitHash, filePath) {
157
- try {
158
- // Get the parent commit hash
159
- const parentHash = await this.git.raw(['rev-parse', `${commitHash}^`]).catch(() => {
160
- // This is likely the initial commit, compare against empty tree
161
- return '4b825dc642cb6eb9a060e54bf8d69288fbee4904'; // Git's empty tree hash
162
- });
163
- const stats = await this.git.raw([
164
- 'diff',
165
- '--numstat',
166
- parentHash.trim(),
167
- commitHash,
168
- '--',
169
- filePath,
170
- ]);
171
- if (!stats.trim()) {
172
- return { additions: 0, deletions: 0 };
173
- }
174
- const [addStr, delStr] = stats.trim().split('\t');
175
- return {
176
- additions: parseInt(addStr, 10) || 0,
177
- deletions: parseInt(delStr, 10) || 0,
178
- };
179
- }
180
- catch {
181
- return { additions: 0, deletions: 0 };
182
- }
183
- }
184
- /**
185
- * Check if a task file has been renamed or moved by tracking it through Git history
186
- */
187
- async getTaskFileRenames(taskId) {
188
- try {
189
- const taskFilePath = path.join('.vibeman', 'tasks', `${taskId}.md`);
190
- // Use git log --follow --name-status to track renames
191
- const logResult = await this.git.raw([
192
- 'log',
193
- '--follow',
194
- '--name-status',
195
- '--pretty=format:%H',
196
- '--',
197
- taskFilePath,
198
- ]);
199
- const renames = [];
200
- const lines = logResult.trim().split('\n');
201
- let currentCommit = '';
202
- for (const line of lines) {
203
- if (line.match(/^[a-f0-9]{40}$/)) {
204
- // This is a commit hash
205
- currentCommit = line;
206
- }
207
- else if (line.startsWith('R') && currentCommit) {
208
- // This is a rename operation (R100, R090, etc.)
209
- const parts = line.split('\t');
210
- if (parts.length >= 3) {
211
- const oldPath = parts[1];
212
- const newPath = parts[2];
213
- renames.push({
214
- oldPath,
215
- newPath,
216
- commitHash: currentCommit,
217
- });
218
- }
219
- }
220
- }
221
- return renames;
222
- }
223
- catch (error) {
224
- log.warn('Failed to get task file renames', { taskId, error }, 'git-history-service');
225
- return [];
226
- }
227
- }
228
- }
@@ -1,136 +0,0 @@
1
- import { SimpleGit, VersionResult } from 'simple-git';
2
- import { Task } from '../types/index.js';
3
- export interface GitConfig {
4
- remoteUrl?: string;
5
- defaultBranch?: string;
6
- }
7
- export interface BranchInfo {
8
- name: string;
9
- exists: boolean;
10
- isCurrentBranch: boolean;
11
- }
12
- export interface CommitInfo {
13
- hash: string;
14
- message: string;
15
- author: string;
16
- date: Date;
17
- }
18
- export interface WorktreeCreationResult {
19
- path: string;
20
- branchName: string;
21
- existed: boolean;
22
- }
23
- export declare class GitService {
24
- private git;
25
- private config;
26
- private projectRoot;
27
- constructor(projectRoot?: string, config?: GitConfig);
28
- getProjectRoot(): string;
29
- /**
30
- * Validate Git repository exists and is properly configured
31
- */
32
- initializeRepository(): Promise<void>;
33
- /**
34
- * Get current Git status
35
- */
36
- getStatus(): Promise<{
37
- current: string;
38
- staged: string[];
39
- modified: string[];
40
- untracked: string[];
41
- ahead: number;
42
- behind: number;
43
- }>;
44
- /**
45
- * Generate branch name from task
46
- */
47
- generateBranchName(task: Task): string;
48
- /**
49
- * Create a new branch for a task
50
- */
51
- createBranch(task: Task, baseBranch?: string): Promise<BranchInfo>;
52
- /**
53
- * Stage and commit changes
54
- */
55
- commitChanges(task: Task, message?: string, files?: string[]): Promise<CommitInfo>;
56
- /**
57
- * Generate standardized commit message
58
- */
59
- generateCommitMessage(task: Task): string;
60
- /**
61
- * Get commit history for current branch
62
- */
63
- getCommitHistory(maxCount?: number): Promise<CommitInfo[]>;
64
- /**
65
- * Get Git version information
66
- */
67
- getGitVersion(): Promise<VersionResult>;
68
- /**
69
- * Check whether a path is ignored by git.
70
- */
71
- isIgnored(relativePath: string): Promise<boolean>;
72
- /**
73
- * Get the current HEAD commit hash
74
- */
75
- getHeadCommitHash(short?: boolean): Promise<string>;
76
- /**
77
- * List all worktrees in the repository
78
- */
79
- listWorktrees(): Promise<{
80
- path: string;
81
- branch: string;
82
- prunable?: boolean;
83
- }[]>;
84
- /**
85
- * Parse git worktree list output
86
- */
87
- private parseWorktreeList;
88
- /**
89
- * Create a new worktree
90
- */
91
- createWorktree(worktreePath: string, branchName: string, branchExists?: boolean): Promise<void>;
92
- /**
93
- * Remove a worktree
94
- */
95
- removeWorktree(worktreePath: string, force?: boolean): Promise<void>;
96
- /**
97
- * Prune stale worktrees
98
- */
99
- pruneWorktrees(): Promise<void>;
100
- /**
101
- * Delete a local branch
102
- */
103
- deleteLocalBranch(branchName: string, force?: boolean): Promise<void>;
104
- /**
105
- * Check if branch exists locally
106
- */
107
- branchExists(branchName: string): Promise<boolean>;
108
- /**
109
- * Sync with remote repository
110
- */
111
- syncWithRemote(branchName?: string): Promise<void>;
112
- /**
113
- * Get Git instance for a specific directory
114
- */
115
- getGitInstance(directory: string): SimpleGit;
116
- /**
117
- * Check Git status for a specific directory
118
- */
119
- getGitStatus(directory: string): Promise<{
120
- modified: string[];
121
- staged: string[];
122
- not_added: string[];
123
- }>;
124
- /**
125
- * Check if directory has uncommitted changes
126
- */
127
- hasUncommittedChanges(directory?: string): Promise<boolean>;
128
- /**
129
- * Get log for a specific directory/worktree
130
- */
131
- getLog(directory: string, options: string[]): Promise<any>;
132
- /**
133
- * Push branch from specific directory
134
- */
135
- pushFromDirectory(directory: string, remote: string, branchName: string, options?: string[]): Promise<void>;
136
- }
@@ -1,307 +0,0 @@
1
- import { simpleGit } from 'simple-git';
2
- import { log } from '../lib/logger.js';
3
- import { getProjectRoot } from '../lib/server/project-root.js';
4
- export class GitService {
5
- constructor(projectRoot = getProjectRoot(), config = {}) {
6
- this.projectRoot = projectRoot;
7
- this.config = config;
8
- this.git = simpleGit(projectRoot);
9
- }
10
- getProjectRoot() {
11
- return this.projectRoot;
12
- }
13
- /**
14
- * Validate Git repository exists and is properly configured
15
- */
16
- async initializeRepository() {
17
- const isRepo = await this.git.checkIsRepo();
18
- if (!isRepo) {
19
- const error = new Error(`Directory ${this.projectRoot} is not a Git repository. Please run 'git init' first.`);
20
- log.error('Git repository not found', error, 'git-service');
21
- throw error;
22
- }
23
- // Set up basic Git configuration if not present
24
- try {
25
- await this.git.raw(['config', 'user.name']);
26
- }
27
- catch {
28
- await this.git.addConfig('user.name', 'Vibeman');
29
- await this.git.addConfig('user.email', 'vibeman@localhost');
30
- log.info('Set default Git user configuration', undefined, 'git-service');
31
- }
32
- }
33
- /**
34
- * Get current Git status
35
- */
36
- async getStatus() {
37
- const status = await this.git.status();
38
- return {
39
- current: status.current || 'main',
40
- staged: status.staged,
41
- modified: status.modified,
42
- untracked: status.not_added,
43
- ahead: status.ahead,
44
- behind: status.behind,
45
- };
46
- }
47
- /**
48
- * Generate branch name from task
49
- */
50
- generateBranchName(task) {
51
- const typePrefix = {
52
- feature: 'feat',
53
- bug: 'fix',
54
- chore: 'chore',
55
- refactor: 'refactor',
56
- test: 'test',
57
- doc: 'docs',
58
- }[task.type];
59
- // Keep branch concise and deterministic, use only the task id
60
- return `${typePrefix}/${task.id.toLowerCase()}`;
61
- }
62
- /**
63
- * Create a new branch for a task
64
- */
65
- async createBranch(task, baseBranch) {
66
- const branchName = this.generateBranchName(task);
67
- const base = baseBranch || this.config.defaultBranch || 'main';
68
- // Check if branch already exists
69
- const branches = await this.git.branchLocal();
70
- const exists = branches.all.includes(branchName);
71
- if (exists) {
72
- log.info('Branch already exists', { branchName }, 'git-service');
73
- await this.git.checkout(branchName);
74
- return {
75
- name: branchName,
76
- exists: true,
77
- isCurrentBranch: true,
78
- };
79
- }
80
- // Ensure we're on the base branch and it's up to date
81
- try {
82
- await this.git.checkout(base);
83
- await this.git.pull('origin', base);
84
- }
85
- catch (error) {
86
- log.warn('Could not update base branch', error, 'git-service');
87
- }
88
- // Create and checkout new branch
89
- await this.git.checkoutLocalBranch(branchName);
90
- log.info('Created and checked out branch', { branchName }, 'git-service');
91
- return {
92
- name: branchName,
93
- exists: false,
94
- isCurrentBranch: true,
95
- };
96
- }
97
- /**
98
- * Stage and commit changes
99
- */
100
- async commitChanges(task, message, files = ['.']) {
101
- // Stage only the specified files
102
- for (const file of files) {
103
- await this.git.add(file);
104
- }
105
- // Generate commit message if not provided
106
- const commitMessage = message || this.generateCommitMessage(task);
107
- // Commit only the specified files (avoid committing other pre-staged changes)
108
- const result = await this.git.commit(commitMessage, files);
109
- log.info('Committed changes', { commit: result.commit }, 'git-service');
110
- return {
111
- hash: result.commit,
112
- message: commitMessage,
113
- author: 'Vibeman',
114
- date: new Date(),
115
- };
116
- }
117
- /**
118
- * Generate standardized commit message
119
- */
120
- generateCommitMessage(task) {
121
- const typeMap = {
122
- feature: 'feat',
123
- bug: 'fix',
124
- chore: 'chore',
125
- refactor: 'refactor',
126
- test: 'test',
127
- doc: 'docs',
128
- };
129
- const type = typeMap[task.type];
130
- const scope = task.tags.length > 0 ? `(${task.tags[0]})` : '';
131
- return `${type}${scope}: ${task.title}\n\n${task.id}: ${task.title}\n\nImplemented via Vibeman`;
132
- }
133
- /**
134
- * Get commit history for current branch
135
- */
136
- async getCommitHistory(maxCount = 10) {
137
- const log = await this.git.log({ maxCount });
138
- return log.all.map((commit) => ({
139
- hash: commit.hash,
140
- message: commit.message,
141
- author: commit.author_name,
142
- date: new Date(commit.date),
143
- }));
144
- }
145
- /**
146
- * Get Git version information
147
- */
148
- async getGitVersion() {
149
- return await this.git.version();
150
- }
151
- /**
152
- * Check whether a path is ignored by git.
153
- */
154
- async isIgnored(relativePath) {
155
- try {
156
- await this.git.raw(['check-ignore', '-q', relativePath]);
157
- return true;
158
- }
159
- catch (error) {
160
- return false;
161
- }
162
- }
163
- /**
164
- * Get the current HEAD commit hash
165
- */
166
- async getHeadCommitHash(short = true) {
167
- const args = short ? ['--short', 'HEAD'] : ['HEAD'];
168
- const hash = await this.git.revparse(args);
169
- return hash.trim();
170
- }
171
- /**
172
- * List all worktrees in the repository
173
- */
174
- async listWorktrees() {
175
- const worktreeList = await this.git.raw(['worktree', 'list', '--porcelain']);
176
- return this.parseWorktreeList(worktreeList);
177
- }
178
- /**
179
- * Parse git worktree list output
180
- */
181
- parseWorktreeList(output) {
182
- const lines = output.trim().split('\n');
183
- const worktrees = [];
184
- let currentWorktree = {};
185
- for (const line of lines) {
186
- if (line.startsWith('worktree ')) {
187
- if (currentWorktree.path) {
188
- worktrees.push(currentWorktree);
189
- }
190
- currentWorktree = { path: line.substring(9) };
191
- }
192
- else if (line.startsWith('branch ')) {
193
- const ref = line.substring(7);
194
- // Strip refs/heads/ prefix if present for readability
195
- currentWorktree.branch = ref.startsWith('refs/heads/') ? ref.substring(11) : ref;
196
- }
197
- else if (line.startsWith('prunable')) {
198
- currentWorktree.prunable = true;
199
- }
200
- }
201
- if (currentWorktree.path) {
202
- worktrees.push(currentWorktree);
203
- }
204
- return worktrees;
205
- }
206
- /**
207
- * Create a new worktree
208
- */
209
- async createWorktree(worktreePath, branchName, branchExists) {
210
- if (branchExists) {
211
- // Create worktree attached to existing branch (no -b)
212
- await this.git.raw(['worktree', 'add', worktreePath, branchName]);
213
- }
214
- else {
215
- // Create worktree and new branch
216
- await this.git.raw(['worktree', 'add', worktreePath, '-b', branchName]);
217
- }
218
- }
219
- /**
220
- * Remove a worktree
221
- */
222
- async removeWorktree(worktreePath, force = false) {
223
- const args = ['worktree', 'remove', worktreePath];
224
- if (force)
225
- args.push('--force');
226
- await this.git.raw(args);
227
- }
228
- /**
229
- * Prune stale worktrees
230
- */
231
- async pruneWorktrees() {
232
- await this.git.raw(['worktree', 'prune']);
233
- }
234
- /**
235
- * Delete a local branch
236
- */
237
- async deleteLocalBranch(branchName, force = false) {
238
- await this.git.deleteLocalBranch(branchName, force);
239
- }
240
- /**
241
- * Check if branch exists locally
242
- */
243
- async branchExists(branchName) {
244
- const localBranches = await this.git.branchLocal();
245
- return !!localBranches.all.find((b) => b === branchName);
246
- }
247
- /**
248
- * Sync with remote repository
249
- */
250
- async syncWithRemote(branchName) {
251
- try {
252
- const status = await this.git.status();
253
- const currentBranch = branchName || status.current;
254
- if (currentBranch && currentBranch !== 'HEAD') {
255
- await this.git.fetch();
256
- log.info('Synced with remote repository', undefined, 'git-service');
257
- }
258
- }
259
- catch (error) {
260
- log.warn('Could not sync with remote', error, 'git-service');
261
- }
262
- }
263
- /**
264
- * Get Git instance for a specific directory
265
- */
266
- getGitInstance(directory) {
267
- return simpleGit(directory);
268
- }
269
- /**
270
- * Check Git status for a specific directory
271
- */
272
- async getGitStatus(directory) {
273
- const git = this.getGitInstance(directory);
274
- const status = await git.status();
275
- return {
276
- modified: status.modified,
277
- staged: status.staged,
278
- not_added: status.not_added,
279
- };
280
- }
281
- /**
282
- * Check if directory has uncommitted changes
283
- */
284
- async hasUncommittedChanges(directory = this.projectRoot) {
285
- try {
286
- const status = await this.getGitStatus(directory);
287
- return status.modified.length > 0 || status.staged.length > 0 || status.not_added.length > 0;
288
- }
289
- catch {
290
- return false;
291
- }
292
- }
293
- /**
294
- * Get log for a specific directory/worktree
295
- */
296
- async getLog(directory, options) {
297
- const git = this.getGitInstance(directory);
298
- return await git.log(options);
299
- }
300
- /**
301
- * Push branch from specific directory
302
- */
303
- async pushFromDirectory(directory, remote, branchName, options = []) {
304
- const git = this.getGitInstance(directory);
305
- await git.push(remote, branchName, options);
306
- }
307
- }