vibe-weaver 1.0.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/README.md +229 -0
- package/bin/vibe-weaver.js +8 -0
- package/dist/bin/vibe-weaver.js +8 -0
- package/dist/index.d.ts +2 -0
- package/dist/index.js +2018 -0
- package/dist/index.js.map +1 -0
- package/package.json +66 -0
- package/src/agent/deploy.ts +171 -0
- package/src/agent/swarm.ts +167 -0
- package/src/agent/tasks.ts +205 -0
- package/src/auth/index.ts +273 -0
- package/src/config/index.ts +86 -0
- package/src/index.ts +797 -0
- package/src/lib/code-parser.ts +150 -0
- package/src/lib/vibe-api.ts +197 -0
- package/src/mcp/index.ts +273 -0
- package/src/tools/files.ts +279 -0
- package/src/tools/git.ts +498 -0
- package/src/tools/shell.ts +248 -0
- package/tsconfig.json +25 -0
- package/tsup.config.ts +34 -0
- package/vibe-weaver-1.0.0.tgz +0 -0
package/src/tools/git.ts
ADDED
|
@@ -0,0 +1,498 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Git tools for Vibe-Weaver CLI
|
|
3
|
+
* Handles local git operations and GitHub integration
|
|
4
|
+
*/
|
|
5
|
+
|
|
6
|
+
import simpleGit, { SimpleGit, LogResult, StatusResult } from 'simple-git';
|
|
7
|
+
import chalk from 'chalk';
|
|
8
|
+
import { getGithubToken } from '../auth/index.js';
|
|
9
|
+
import { getSupabaseUrl } from '../config/index.js';
|
|
10
|
+
|
|
11
|
+
export interface GitStatus {
|
|
12
|
+
current: string | null;
|
|
13
|
+
tracking: string | null;
|
|
14
|
+
ahead: number;
|
|
15
|
+
behind: number;
|
|
16
|
+
staged: string[];
|
|
17
|
+
modified: string[];
|
|
18
|
+
untracked: string[];
|
|
19
|
+
conflicted: string[];
|
|
20
|
+
}
|
|
21
|
+
|
|
22
|
+
export interface GitCommitResult {
|
|
23
|
+
success: boolean;
|
|
24
|
+
commitSha?: string;
|
|
25
|
+
message?: string;
|
|
26
|
+
files?: string[];
|
|
27
|
+
error?: string;
|
|
28
|
+
}
|
|
29
|
+
|
|
30
|
+
export interface GitLogEntry {
|
|
31
|
+
hash: string;
|
|
32
|
+
date: string;
|
|
33
|
+
message: string;
|
|
34
|
+
author_name: string;
|
|
35
|
+
author_email: string;
|
|
36
|
+
}
|
|
37
|
+
|
|
38
|
+
/**
|
|
39
|
+
* Get a git instance for a directory
|
|
40
|
+
*/
|
|
41
|
+
export function getGit(cwd: string = process.cwd()): SimpleGit {
|
|
42
|
+
return simpleGit(cwd);
|
|
43
|
+
}
|
|
44
|
+
|
|
45
|
+
/**
|
|
46
|
+
* Get the current git status
|
|
47
|
+
*/
|
|
48
|
+
export async function getStatus(cwd: string = process.cwd()): Promise<GitStatus> {
|
|
49
|
+
const git = getGit(cwd);
|
|
50
|
+
const status = await git.status();
|
|
51
|
+
|
|
52
|
+
return {
|
|
53
|
+
current: status.current,
|
|
54
|
+
tracking: status.tracking,
|
|
55
|
+
ahead: status.ahead,
|
|
56
|
+
behind: status.behind,
|
|
57
|
+
staged: status.staged,
|
|
58
|
+
modified: status.modified,
|
|
59
|
+
untracked: status.not_added,
|
|
60
|
+
conflicted: status.conflicted
|
|
61
|
+
};
|
|
62
|
+
}
|
|
63
|
+
|
|
64
|
+
/**
|
|
65
|
+
* Get the current branch name
|
|
66
|
+
*/
|
|
67
|
+
export async function getBranch(cwd: string = process.cwd()): Promise<string> {
|
|
68
|
+
const git = getGit(cwd);
|
|
69
|
+
const branchSummary = await git.branch();
|
|
70
|
+
return branchSummary.current;
|
|
71
|
+
}
|
|
72
|
+
|
|
73
|
+
/**
|
|
74
|
+
* Get recent commit history
|
|
75
|
+
*/
|
|
76
|
+
export async function getLog(cwd: string = process.cwd(), maxCount: number = 10): Promise<GitLogEntry[]> {
|
|
77
|
+
const git = getGit(cwd);
|
|
78
|
+
const log = await git.log({ maxCount });
|
|
79
|
+
|
|
80
|
+
return log.all.map(entry => ({
|
|
81
|
+
hash: entry.hash,
|
|
82
|
+
date: entry.date,
|
|
83
|
+
message: entry.message,
|
|
84
|
+
author_name: entry.author_name,
|
|
85
|
+
author_email: entry.author_email
|
|
86
|
+
}));
|
|
87
|
+
}
|
|
88
|
+
|
|
89
|
+
/**
|
|
90
|
+
* Stage files for commit
|
|
91
|
+
*/
|
|
92
|
+
export async function stage(files: string | string[], cwd: string = process.cwd()): Promise<void> {
|
|
93
|
+
const git = getGit(cwd);
|
|
94
|
+
await git.add(files);
|
|
95
|
+
}
|
|
96
|
+
|
|
97
|
+
/**
|
|
98
|
+
* Stage all changes
|
|
99
|
+
*/
|
|
100
|
+
export async function stageAll(cwd: string = process.cwd()): Promise<void> {
|
|
101
|
+
const git = getGit(cwd);
|
|
102
|
+
await git.add('.');
|
|
103
|
+
}
|
|
104
|
+
|
|
105
|
+
/**
|
|
106
|
+
* Commit changes with a message
|
|
107
|
+
*/
|
|
108
|
+
export async function commit(message: string, cwd: string = process.cwd()): Promise<GitCommitResult> {
|
|
109
|
+
const git = getGit(cwd);
|
|
110
|
+
|
|
111
|
+
try {
|
|
112
|
+
const result = await git.commit(message);
|
|
113
|
+
|
|
114
|
+
return {
|
|
115
|
+
success: true,
|
|
116
|
+
commitSha: result.commit,
|
|
117
|
+
message: result.summary.changes + ' file(s) changed'
|
|
118
|
+
};
|
|
119
|
+
} catch (error) {
|
|
120
|
+
return {
|
|
121
|
+
success: false,
|
|
122
|
+
error: error instanceof Error ? error.message : String(error)
|
|
123
|
+
};
|
|
124
|
+
}
|
|
125
|
+
}
|
|
126
|
+
|
|
127
|
+
/**
|
|
128
|
+
* Commit all changes with a conventional commit message
|
|
129
|
+
*/
|
|
130
|
+
export async function commitAll(message: string, cwd: string = process.cwd()): Promise<GitCommitResult> {
|
|
131
|
+
await stageAll(cwd);
|
|
132
|
+
return commit(message, cwd);
|
|
133
|
+
}
|
|
134
|
+
|
|
135
|
+
/**
|
|
136
|
+
* Push changes to remote
|
|
137
|
+
*/
|
|
138
|
+
export async function push(options: { remote?: string; branch?: string; force?: boolean } = {}, cwd: string = process.cwd()): Promise<GitCommitResult> {
|
|
139
|
+
const git = getGit(cwd);
|
|
140
|
+
|
|
141
|
+
try {
|
|
142
|
+
const result = await git.push(options.remote || 'origin', options.branch || 'HEAD', {
|
|
143
|
+
'--force': options.force || false
|
|
144
|
+
});
|
|
145
|
+
|
|
146
|
+
return {
|
|
147
|
+
success: true,
|
|
148
|
+
commitSha: result.pushed[0]?.hash,
|
|
149
|
+
message: 'Push successful'
|
|
150
|
+
};
|
|
151
|
+
} catch (error) {
|
|
152
|
+
return {
|
|
153
|
+
success: false,
|
|
154
|
+
error: error instanceof Error ? error.message : String(error)
|
|
155
|
+
};
|
|
156
|
+
}
|
|
157
|
+
}
|
|
158
|
+
|
|
159
|
+
/**
|
|
160
|
+
* Pull changes from remote
|
|
161
|
+
*/
|
|
162
|
+
export async function pull(options: { remote?: string; branch?: string } = {}, cwd: string = process.cwd()): Promise<GitCommitResult> {
|
|
163
|
+
const git = getGit(cwd);
|
|
164
|
+
|
|
165
|
+
try {
|
|
166
|
+
const result = await git.pull(options.remote || 'origin', options.branch || 'HEAD');
|
|
167
|
+
|
|
168
|
+
return {
|
|
169
|
+
success: true,
|
|
170
|
+
message: 'Pull successful'
|
|
171
|
+
};
|
|
172
|
+
} catch (error) {
|
|
173
|
+
return {
|
|
174
|
+
success: false,
|
|
175
|
+
error: error instanceof Error ? error.message : String(error)
|
|
176
|
+
};
|
|
177
|
+
}
|
|
178
|
+
}
|
|
179
|
+
|
|
180
|
+
/**
|
|
181
|
+
* Create a new branch
|
|
182
|
+
*/
|
|
183
|
+
export async function createBranch(branchName: string, options: { checkout?: boolean } = {}, cwd: string = process.cwd()): Promise<GitCommitResult> {
|
|
184
|
+
const git = getGit(cwd);
|
|
185
|
+
|
|
186
|
+
try {
|
|
187
|
+
if (options.checkout) {
|
|
188
|
+
await git.checkoutLocalBranch(branchName);
|
|
189
|
+
} else {
|
|
190
|
+
await git.branch([branchName]);
|
|
191
|
+
}
|
|
192
|
+
|
|
193
|
+
return {
|
|
194
|
+
success: true,
|
|
195
|
+
message: `Branch ${branchName} created`
|
|
196
|
+
};
|
|
197
|
+
} catch (error) {
|
|
198
|
+
return {
|
|
199
|
+
success: false,
|
|
200
|
+
error: error instanceof Error ? error.message : String(error)
|
|
201
|
+
};
|
|
202
|
+
}
|
|
203
|
+
}
|
|
204
|
+
|
|
205
|
+
/**
|
|
206
|
+
* Checkout a branch
|
|
207
|
+
*/
|
|
208
|
+
export async function checkout(branchName: string, cwd: string = process.cwd()): Promise<GitCommitResult> {
|
|
209
|
+
const git = getGit(cwd);
|
|
210
|
+
|
|
211
|
+
try {
|
|
212
|
+
await git.checkout(branchName);
|
|
213
|
+
|
|
214
|
+
return {
|
|
215
|
+
success: true,
|
|
216
|
+
message: `Switched to branch ${branchName}`
|
|
217
|
+
};
|
|
218
|
+
} catch (error) {
|
|
219
|
+
return {
|
|
220
|
+
success: false,
|
|
221
|
+
error: error instanceof Error ? error.message : String(error)
|
|
222
|
+
};
|
|
223
|
+
}
|
|
224
|
+
}
|
|
225
|
+
|
|
226
|
+
/**
|
|
227
|
+
* Get the diff between commits, branches, or working tree
|
|
228
|
+
*/
|
|
229
|
+
export async function getDiff(options: { staged?: boolean; from?: string; to?: string } = {}, cwd: string = process.cwd()): Promise<string> {
|
|
230
|
+
const git = getGit(cwd);
|
|
231
|
+
|
|
232
|
+
if (options.staged) {
|
|
233
|
+
return git.diff(['--staged']);
|
|
234
|
+
}
|
|
235
|
+
|
|
236
|
+
if (options.from && options.to) {
|
|
237
|
+
return git.diff([options.from, options.to]);
|
|
238
|
+
}
|
|
239
|
+
|
|
240
|
+
return git.diff();
|
|
241
|
+
}
|
|
242
|
+
|
|
243
|
+
/**
|
|
244
|
+
* Check if a directory is a git repository
|
|
245
|
+
*/
|
|
246
|
+
export async function isRepo(cwd: string = process.cwd()): Promise<boolean> {
|
|
247
|
+
const git = getGit(cwd);
|
|
248
|
+
return git.checkIsRepo();
|
|
249
|
+
}
|
|
250
|
+
|
|
251
|
+
/**
|
|
252
|
+
* Initialize a new git repository
|
|
253
|
+
*/
|
|
254
|
+
export async function init(cwd: string = process.cwd()): Promise<GitCommitResult> {
|
|
255
|
+
const git = getGit(cwd);
|
|
256
|
+
|
|
257
|
+
try {
|
|
258
|
+
await git.init();
|
|
259
|
+
|
|
260
|
+
return {
|
|
261
|
+
success: true,
|
|
262
|
+
message: 'Git repository initialized'
|
|
263
|
+
};
|
|
264
|
+
} catch (error) {
|
|
265
|
+
return {
|
|
266
|
+
success: false,
|
|
267
|
+
error: error instanceof Error ? error.message : String(error)
|
|
268
|
+
};
|
|
269
|
+
}
|
|
270
|
+
}
|
|
271
|
+
|
|
272
|
+
/**
|
|
273
|
+
* Get the remote URL
|
|
274
|
+
*/
|
|
275
|
+
export async function getRemote(cwd: string = process.cwd()): Promise<string | null> {
|
|
276
|
+
const git = getGit(cwd);
|
|
277
|
+
const remotes = await git.getRemotes(true);
|
|
278
|
+
|
|
279
|
+
const origin = remotes.find(r => r.name === 'origin');
|
|
280
|
+
return origin?.refs.fetch || null;
|
|
281
|
+
}
|
|
282
|
+
|
|
283
|
+
// GitHub-specific operations via the platform's edge function
|
|
284
|
+
|
|
285
|
+
/**
|
|
286
|
+
* Call the github-ai-sync edge function
|
|
287
|
+
*/
|
|
288
|
+
async function callGithubSync(action: string, params: Record<string, any>): Promise<any> {
|
|
289
|
+
const apiKey = await getGithubToken();
|
|
290
|
+
if (!apiKey) {
|
|
291
|
+
throw new Error('GitHub token not configured. Run "vibe-weaver login --github" first.');
|
|
292
|
+
}
|
|
293
|
+
|
|
294
|
+
const supabaseUrl = getSupabaseUrl();
|
|
295
|
+
const endpoint = `${supabaseUrl}/functions/v1/github-ai-sync`;
|
|
296
|
+
|
|
297
|
+
const response = await fetch(endpoint, {
|
|
298
|
+
method: 'POST',
|
|
299
|
+
headers: {
|
|
300
|
+
'Content-Type': 'application/json',
|
|
301
|
+
'Authorization': `Bearer ${apiKey}`
|
|
302
|
+
},
|
|
303
|
+
body: JSON.stringify({
|
|
304
|
+
action,
|
|
305
|
+
token: apiKey,
|
|
306
|
+
...params
|
|
307
|
+
})
|
|
308
|
+
});
|
|
309
|
+
|
|
310
|
+
if (!response.ok) {
|
|
311
|
+
const error = await response.json().catch(() => ({ error: 'Unknown error' }));
|
|
312
|
+
throw new Error(`GitHub API error: ${error.error || error.message}`);
|
|
313
|
+
}
|
|
314
|
+
|
|
315
|
+
return response.json();
|
|
316
|
+
}
|
|
317
|
+
|
|
318
|
+
/**
|
|
319
|
+
* Commit files via GitHub API
|
|
320
|
+
*/
|
|
321
|
+
export async function commitFilesToGithub(options: {
|
|
322
|
+
owner: string;
|
|
323
|
+
repo: string;
|
|
324
|
+
branch: string;
|
|
325
|
+
files: { path: string; content: string; message: string }[];
|
|
326
|
+
commitMessage: string;
|
|
327
|
+
}): Promise<GitCommitResult> {
|
|
328
|
+
try {
|
|
329
|
+
const result = await callGithubSync('commit_files', options);
|
|
330
|
+
|
|
331
|
+
return {
|
|
332
|
+
success: true,
|
|
333
|
+
commitSha: result.commitSha,
|
|
334
|
+
message: `Committed ${result.files?.length || 0} file(s) to ${options.branch}`,
|
|
335
|
+
files: result.files
|
|
336
|
+
};
|
|
337
|
+
} catch (error) {
|
|
338
|
+
return {
|
|
339
|
+
success: false,
|
|
340
|
+
error: error instanceof Error ? error.message : String(error)
|
|
341
|
+
};
|
|
342
|
+
}
|
|
343
|
+
}
|
|
344
|
+
|
|
345
|
+
/**
|
|
346
|
+
* Create a branch via GitHub API
|
|
347
|
+
*/
|
|
348
|
+
export async function createBranchOnGithub(options: {
|
|
349
|
+
owner: string;
|
|
350
|
+
repo: string;
|
|
351
|
+
newBranch: string;
|
|
352
|
+
fromBranch: string;
|
|
353
|
+
}): Promise<GitCommitResult> {
|
|
354
|
+
try {
|
|
355
|
+
const result = await callGithubSync('create_branch', options);
|
|
356
|
+
|
|
357
|
+
return {
|
|
358
|
+
success: true,
|
|
359
|
+
commitSha: result.sha,
|
|
360
|
+
message: `Created branch ${options.newBranch} from ${options.fromBranch}`
|
|
361
|
+
};
|
|
362
|
+
} catch (error) {
|
|
363
|
+
return {
|
|
364
|
+
success: false,
|
|
365
|
+
error: error instanceof Error ? error.message : String(error)
|
|
366
|
+
};
|
|
367
|
+
}
|
|
368
|
+
}
|
|
369
|
+
|
|
370
|
+
/**
|
|
371
|
+
* Create a pull request via GitHub API
|
|
372
|
+
*/
|
|
373
|
+
export async function createPullRequestOnGithub(options: {
|
|
374
|
+
owner: string;
|
|
375
|
+
repo: string;
|
|
376
|
+
title: string;
|
|
377
|
+
body: string;
|
|
378
|
+
head: string;
|
|
379
|
+
base: string;
|
|
380
|
+
}): Promise<{ success: boolean; prNumber?: number; prUrl?: string; error?: string }> {
|
|
381
|
+
try {
|
|
382
|
+
const result = await callGithubSync('create_pr', options);
|
|
383
|
+
|
|
384
|
+
return {
|
|
385
|
+
success: true,
|
|
386
|
+
prNumber: result.prNumber,
|
|
387
|
+
prUrl: result.prUrl
|
|
388
|
+
};
|
|
389
|
+
} catch (error) {
|
|
390
|
+
return {
|
|
391
|
+
success: false,
|
|
392
|
+
error: error instanceof Error ? error.message : String(error)
|
|
393
|
+
};
|
|
394
|
+
}
|
|
395
|
+
}
|
|
396
|
+
|
|
397
|
+
/**
|
|
398
|
+
* Full PR workflow: create branch, commit changes, open PR
|
|
399
|
+
*/
|
|
400
|
+
export async function fullPRWorkflow(options: {
|
|
401
|
+
owner: string;
|
|
402
|
+
repo: string;
|
|
403
|
+
branchName: string;
|
|
404
|
+
baseBranch: string;
|
|
405
|
+
files: { path: string; content: string; message: string }[];
|
|
406
|
+
commitMessage: string;
|
|
407
|
+
prTitle: string;
|
|
408
|
+
prBody: string;
|
|
409
|
+
}): Promise<{
|
|
410
|
+
success: boolean;
|
|
411
|
+
branch?: string;
|
|
412
|
+
commitSha?: string;
|
|
413
|
+
prUrl?: string;
|
|
414
|
+
prNumber?: number;
|
|
415
|
+
error?: string;
|
|
416
|
+
}> {
|
|
417
|
+
console.log(chalk.blue('\n=== GitHub PR Workflow ==='));
|
|
418
|
+
|
|
419
|
+
// Step 1: Create branch
|
|
420
|
+
console.log(chalk.gray('1. Creating branch...'));
|
|
421
|
+
const branchResult = await createBranchOnGithub({
|
|
422
|
+
owner: options.owner,
|
|
423
|
+
repo: options.repo,
|
|
424
|
+
newBranch: options.branchName,
|
|
425
|
+
fromBranch: options.baseBranch
|
|
426
|
+
});
|
|
427
|
+
|
|
428
|
+
if (!branchResult.success) {
|
|
429
|
+
return { success: false, error: `Failed to create branch: ${branchResult.error}` };
|
|
430
|
+
}
|
|
431
|
+
|
|
432
|
+
console.log(chalk.green(` ✓ Branch ${options.branchName} created`));
|
|
433
|
+
|
|
434
|
+
// Step 2: Commit files
|
|
435
|
+
console.log(chalk.gray('2. Committing files...'));
|
|
436
|
+
const commitResult = await commitFilesToGithub({
|
|
437
|
+
owner: options.owner,
|
|
438
|
+
repo: options.repo,
|
|
439
|
+
branch: options.branchName,
|
|
440
|
+
files: options.files,
|
|
441
|
+
commitMessage: options.commitMessage
|
|
442
|
+
});
|
|
443
|
+
|
|
444
|
+
if (!commitResult.success) {
|
|
445
|
+
return { success: false, error: `Failed to commit: ${commitResult.error}` };
|
|
446
|
+
}
|
|
447
|
+
|
|
448
|
+
console.log(chalk.green(` ✓ Committed ${commitResult.files?.length || 0} file(s)`));
|
|
449
|
+
|
|
450
|
+
// Step 3: Create PR
|
|
451
|
+
console.log(chalk.gray('3. Creating pull request...'));
|
|
452
|
+
const prResult = await createPullRequestOnGithub({
|
|
453
|
+
owner: options.owner,
|
|
454
|
+
repo: options.repo,
|
|
455
|
+
title: options.prTitle,
|
|
456
|
+
body: options.prBody,
|
|
457
|
+
head: options.branchName,
|
|
458
|
+
base: options.baseBranch
|
|
459
|
+
});
|
|
460
|
+
|
|
461
|
+
if (!prResult.success) {
|
|
462
|
+
return { success: false, error: `Failed to create PR: ${prResult.error}` };
|
|
463
|
+
}
|
|
464
|
+
|
|
465
|
+
console.log(chalk.green(` ✓ PR created: ${prResult.prUrl}`));
|
|
466
|
+
console.log(chalk.blue('===========================\n'));
|
|
467
|
+
|
|
468
|
+
return {
|
|
469
|
+
success: true,
|
|
470
|
+
branch: options.branchName,
|
|
471
|
+
commitSha: commitResult.commitSha,
|
|
472
|
+
prUrl: prResult.prUrl,
|
|
473
|
+
prNumber: prResult.prNumber
|
|
474
|
+
};
|
|
475
|
+
}
|
|
476
|
+
|
|
477
|
+
export default {
|
|
478
|
+
getGit,
|
|
479
|
+
getStatus,
|
|
480
|
+
getBranch,
|
|
481
|
+
getLog,
|
|
482
|
+
stage,
|
|
483
|
+
stageAll,
|
|
484
|
+
commit,
|
|
485
|
+
commitAll,
|
|
486
|
+
push,
|
|
487
|
+
pull,
|
|
488
|
+
createBranch,
|
|
489
|
+
checkout,
|
|
490
|
+
getDiff,
|
|
491
|
+
isRepo,
|
|
492
|
+
init,
|
|
493
|
+
getRemote,
|
|
494
|
+
commitFilesToGithub,
|
|
495
|
+
createBranchOnGithub,
|
|
496
|
+
createPullRequestOnGithub,
|
|
497
|
+
fullPRWorkflow
|
|
498
|
+
};
|