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.
@@ -0,0 +1,171 @@
1
+ /**
2
+ * Deploy functionality for Vibe-Weaver CLI
3
+ * Deploy projects and verify against live URL
4
+ */
5
+
6
+ import chalk from 'chalk';
7
+ import { getApiKey } from '../auth/index.js';
8
+ import { getSupabaseUrl } from '../config/index.js';
9
+ import { runShell } from '../tools/shell.js';
10
+
11
+ export interface DeployOptions {
12
+ projectId?: string;
13
+ platform?: string;
14
+ siteUrl?: string;
15
+ }
16
+
17
+ export interface DeployResult {
18
+ success: boolean;
19
+ url?: string;
20
+ projectId?: string;
21
+ error?: string;
22
+ }
23
+
24
+ /**
25
+ * Submit deployment
26
+ */
27
+ export async function submitDeploy(options: DeployOptions): Promise<DeployResult> {
28
+ const apiKey = await getApiKey();
29
+ if (!apiKey) {
30
+ throw new Error('Not logged in. Run "vibe-weaver login" first.');
31
+ }
32
+
33
+ const supabaseUrl = getSupabaseUrl();
34
+
35
+ console.log(chalk.cyan('\nšŸš€ Submitting deployment...'));
36
+
37
+ const response = await fetch(`${supabaseUrl}/functions/v1/deploy-bridge`, {
38
+ method: 'POST',
39
+ headers: {
40
+ 'Content-Type': 'application/json',
41
+ 'Authorization': `Bearer ${apiKey}`
42
+ },
43
+ body: JSON.stringify({
44
+ projectId: options.projectId,
45
+ platform: options.platform || 'web'
46
+ })
47
+ });
48
+
49
+ if (!response.ok) {
50
+ const error = await response.json().catch(() => ({ error: 'Unknown error' }));
51
+ return {
52
+ success: false,
53
+ error: error.error || error.message
54
+ };
55
+ }
56
+
57
+ const result = await response.json();
58
+
59
+ console.log(chalk.green(`āœ“ Deployment submitted`));
60
+ console.log(chalk.gray(` URL: ${result.url}`));
61
+
62
+ return {
63
+ success: true,
64
+ url: result.url,
65
+ projectId: result.projectId
66
+ };
67
+ }
68
+
69
+ /**
70
+ * Verify deployment by checking the URL
71
+ */
72
+ export async function verifyDeploy(url: string, options: {
73
+ timeout?: number;
74
+ expectedStatus?: number;
75
+ } = {}): Promise<{ success: boolean; status?: number; error?: string }> {
76
+ const timeout = options.timeout || 60000;
77
+ const expectedStatus = options.expectedStatus || 200;
78
+
79
+ console.log(chalk.gray(`\nVerifying deployment at ${url}...`));
80
+
81
+ const startTime = Date.now();
82
+
83
+ while (Date.now() - startTime < timeout) {
84
+ try {
85
+ const response = await fetch(url, { method: 'HEAD' });
86
+
87
+ if (response.status === expectedStatus) {
88
+ console.log(chalk.green(`āœ“ Deployment verified (${response.status})`));
89
+ return { success: true, status: response.status };
90
+ }
91
+
92
+ // If we get 404, the site might still be deploying
93
+ if (response.status === 404) {
94
+ console.log(chalk.yellow(` Still deploying... (${response.status})`));
95
+ } else {
96
+ console.log(chalk.yellow(` Unexpected status: ${response.status}`));
97
+ }
98
+ } catch (error) {
99
+ console.log(chalk.yellow(` Waiting for deployment...`));
100
+ }
101
+
102
+ await new Promise(resolve => setTimeout(resolve, 5000));
103
+ }
104
+
105
+ console.log(chalk.red(`āœ— Deployment verification timed out`));
106
+ return {
107
+ success: false,
108
+ error: 'Deployment verification timed out'
109
+ };
110
+ }
111
+
112
+ /**
113
+ * Full deploy and verify workflow
114
+ */
115
+ export async function deploy(options: {
116
+ projectId?: string;
117
+ platform?: string;
118
+ verify?: boolean;
119
+ cwd?: string;
120
+ } = {}): Promise<DeployResult> {
121
+ const verify = options.verify !== false;
122
+
123
+ console.log(chalk.cyan('\nšŸš€ Vibe-Weaver Deploy'));
124
+
125
+ // First build locally
126
+ if (options.cwd) {
127
+ console.log(chalk.gray('\nBuilding project locally...'));
128
+ const buildResult = await runShell('npm run build', { cwd: options.cwd });
129
+
130
+ if (!buildResult.success) {
131
+ return {
132
+ success: false,
133
+ error: `Build failed: ${buildResult.stderr}`
134
+ };
135
+ }
136
+
137
+ console.log(chalk.green('āœ“ Build successful'));
138
+ }
139
+
140
+ // Submit deployment
141
+ console.log(chalk.gray('\nSubmitting to Vibe-Weaver...'));
142
+ const deployResult = await submitDeploy({
143
+ projectId: options.projectId,
144
+ platform: options.platform
145
+ });
146
+
147
+ if (!deployResult.success) {
148
+ return deployResult;
149
+ }
150
+
151
+ // Verify if requested
152
+ if (verify && deployResult.url) {
153
+ const verifyResult = await verifyDeploy(deployResult.url);
154
+
155
+ if (!verifyResult.success) {
156
+ return {
157
+ success: false,
158
+ url: deployResult.url,
159
+ error: verifyResult.error
160
+ };
161
+ }
162
+ }
163
+
164
+ return deployResult;
165
+ }
166
+
167
+ export default {
168
+ submitDeploy,
169
+ verifyDeploy,
170
+ deploy
171
+ };
@@ -0,0 +1,167 @@
1
+ /**
2
+ * Sub-agent Swarm for Vibe-Weaver CLI
3
+ * Runs multiple agents in parallel for complex tasks
4
+ */
5
+
6
+ import chalk from 'chalk';
7
+ import { generateCode } from '../lib/vibe-api.js';
8
+ import { writeCodeBlocks } from '../lib/code-parser.js';
9
+ import { runShell } from '../tools/shell.js';
10
+ import path from 'path';
11
+
12
+ export interface AgentTask {
13
+ id: string;
14
+ name: string;
15
+ goal: string;
16
+ status: 'pending' | 'running' | 'completed' | 'failed';
17
+ result?: string;
18
+ error?: string;
19
+ }
20
+
21
+ export interface SwarmResult {
22
+ success: boolean;
23
+ completed: number;
24
+ failed: number;
25
+ results: AgentTask[];
26
+ }
27
+
28
+ /**
29
+ * Split a complex goal into sub-tasks for parallel execution
30
+ */
31
+ export async function planSubTasks(goal: string): Promise<string[]> {
32
+ const result = await generateCode({
33
+ goal: `Break down this complex goal into 3-5 independent subtasks that can run in parallel. List only the subtask descriptions, one per line:\n\n${goal}`,
34
+ modelId: 'balanced'
35
+ });
36
+
37
+ // Parse subtasks from result
38
+ const lines = result.explanation.split('\n').filter(line => line.trim().length > 0);
39
+ return lines.slice(0, 5); // Limit to 5 subtasks
40
+ }
41
+
42
+ /**
43
+ * Execute a single subtask
44
+ */
45
+ async function executeSubTask(task: AgentTask, baseDir: string): Promise<AgentTask> {
46
+ task.status = 'running';
47
+
48
+ try {
49
+ console.log(chalk.gray(`[${task.id}] Starting: ${task.name}`));
50
+
51
+ const result = await generateCode({
52
+ goal: task.goal,
53
+ modelId: 'balanced'
54
+ });
55
+
56
+ // Write generated files
57
+ if (result.parsed.blocks.length > 0) {
58
+ const writeResult = await writeCodeBlocks(result.parsed.blocks, baseDir);
59
+
60
+ if (writeResult.failed.length > 0) {
61
+ task.status = 'failed';
62
+ task.error = `Failed to write files: ${writeResult.failed.map(f => f.path).join(', ')}`;
63
+ } else {
64
+ task.status = 'completed';
65
+ task.result = `Generated ${writeResult.success.length} files: ${writeResult.success.join(', ')}`;
66
+ }
67
+ } else {
68
+ task.status = 'completed';
69
+ task.result = result.explanation;
70
+ }
71
+
72
+ console.log(chalk.green(`[${task.id}] Completed: ${task.name}`));
73
+ } catch (error) {
74
+ task.status = 'failed';
75
+ task.error = error instanceof Error ? error.message : String(error);
76
+ console.log(chalk.red(`[${task.id}] Failed: ${task.name} - ${task.error}`));
77
+ }
78
+
79
+ return task;
80
+ }
81
+
82
+ /**
83
+ * Run multiple agents in parallel (swarm)
84
+ */
85
+ export async function runSwarm(goal: string, options: {
86
+ maxParallel?: number;
87
+ baseDir?: string;
88
+ } = {}): Promise<SwarmResult> {
89
+ const maxParallel = options.maxParallel || 3;
90
+ const baseDir = options.baseDir || process.cwd();
91
+
92
+ console.log(chalk.cyan('\nšŸŽÆ Vibe-Weaver Agent Swarm'));
93
+ console.log(chalk.gray(`Planning subtasks for: ${goal.substring(0, 50)}...\n`));
94
+
95
+ // Plan subtasks
96
+ const subtaskGoals = await planSubTasks(goal);
97
+
98
+ if (subtaskGoals.length === 0) {
99
+ console.log(chalk.yellow('Could not generate subtasks. Running as single task.'));
100
+ subtaskGoals.push(goal);
101
+ }
102
+
103
+ console.log(chalk.gray(`Found ${subtaskGoals.length} subtasks:\n`));
104
+ for (let i = 0; i < subtaskGoals.length; i++) {
105
+ console.log(chalk.gray(` ${i + 1}. ${subtaskGoals[i].substring(0, 60)}...`));
106
+ }
107
+ console.log();
108
+
109
+ // Create tasks
110
+ const tasks: AgentTask[] = subtaskGoals.map((subGoal, i) => ({
111
+ id: `agent-${i + 1}`,
112
+ name: `Agent ${i + 1}`,
113
+ goal: subGoal,
114
+ status: 'pending' as const
115
+ }));
116
+
117
+ // Run tasks in batches
118
+ const results: AgentTask[] = [];
119
+
120
+ for (let i = 0; i < tasks.length; i += maxParallel) {
121
+ const batch = tasks.slice(i, i + maxParallel);
122
+
123
+ console.log(chalk.cyan(`\n--- Running batch ${Math.floor(i / maxParallel) + 1} (${batch.length} agents) ---\n`));
124
+
125
+ // Execute batch in parallel
126
+ const batchResults = await Promise.all(
127
+ batch.map(task => executeSubTask(task, baseDir))
128
+ );
129
+
130
+ results.push(...batchResults);
131
+
132
+ // Show progress
133
+ const completed = results.filter(t => t.status === 'completed').length;
134
+ const failed = results.filter(t => t.status === 'failed').length;
135
+ console.log(chalk.gray(`\nProgress: ${completed} completed, ${failed} failed\n`));
136
+ }
137
+
138
+ // Summary
139
+ const completed = results.filter(t => t.status === 'completed').length;
140
+ const failed = results.filter(t => t.status === 'failed').length;
141
+
142
+ console.log(chalk.cyan('\n=== Swarm Results ==='));
143
+ console.log(chalk.green(`Completed: ${completed}`));
144
+ if (failed > 0) {
145
+ console.log(chalk.red(`Failed: ${failed}`));
146
+ }
147
+
148
+ for (const task of results) {
149
+ if (task.status === 'completed') {
150
+ console.log(chalk.green(` āœ“ ${task.name}: ${task.result?.substring(0, 50)}...`));
151
+ } else if (task.status === 'failed') {
152
+ console.log(chalk.red(` āœ— ${task.name}: ${task.error}`));
153
+ }
154
+ }
155
+
156
+ return {
157
+ success: failed === 0,
158
+ completed,
159
+ failed,
160
+ results
161
+ };
162
+ }
163
+
164
+ export default {
165
+ runSwarm,
166
+ planSubTasks
167
+ };
@@ -0,0 +1,205 @@
1
+ /**
2
+ * Background Tasks for Vibe-Weaver CLI
3
+ * Submit server-side runs and check status
4
+ */
5
+
6
+ import chalk from 'chalk';
7
+ import { getApiKey } from '../auth/index.js';
8
+ import { getSupabaseUrl } from '../config/index.js';
9
+
10
+ export interface TaskSubmission {
11
+ id?: string;
12
+ goal: string;
13
+ platform?: string;
14
+ language?: string;
15
+ modelId?: string;
16
+ }
17
+
18
+ export interface TaskStatus {
19
+ id: string;
20
+ status: 'pending' | 'running' | 'completed' | 'failed';
21
+ progress?: number;
22
+ result?: string;
23
+ error?: string;
24
+ createdAt: string;
25
+ updatedAt: string;
26
+ }
27
+
28
+ /**
29
+ * Submit a background task to the server
30
+ */
31
+ export async function submitTask(options: TaskSubmission): Promise<{ id: string; status: string }> {
32
+ const apiKey = await getApiKey();
33
+ if (!apiKey) {
34
+ throw new Error('Not logged in. Run "vibe-weaver login" first.');
35
+ }
36
+
37
+ const supabaseUrl = getSupabaseUrl();
38
+
39
+ console.log(chalk.gray(`\nSubmitting background task: ${options.goal.substring(0, 50)}...`));
40
+
41
+ const response = await fetch(`${supabaseUrl}/functions/v1/automation-executor`, {
42
+ method: 'POST',
43
+ headers: {
44
+ 'Content-Type': 'application/json',
45
+ 'Authorization': `Bearer ${apiKey}`
46
+ },
47
+ body: JSON.stringify({
48
+ goal: options.goal,
49
+ platform: options.platform || 'web',
50
+ language: options.language || 'typescript',
51
+ modelId: options.modelId || 'balanced'
52
+ })
53
+ });
54
+
55
+ if (!response.ok) {
56
+ const error = await response.json().catch(() => ({ error: 'Unknown error' }));
57
+ throw new Error(`Failed to submit task: ${error.error || error.message}`);
58
+ }
59
+
60
+ const result = await response.json();
61
+
62
+ console.log(chalk.green(`āœ“ Task submitted: ${result.id}`));
63
+ console.log(chalk.gray(` Use "vibe-weaver task status ${result.id}" to check progress\n`));
64
+
65
+ return {
66
+ id: result.id,
67
+ status: result.status || 'pending'
68
+ };
69
+ }
70
+
71
+ /**
72
+ * Get task status
73
+ */
74
+ export async function getTaskStatus(taskId: string): Promise<TaskStatus> {
75
+ const apiKey = await getApiKey();
76
+ if (!apiKey) {
77
+ throw new Error('Not logged in. Run "vibe-weaver login" first.');
78
+ }
79
+
80
+ const supabaseUrl = getSupabaseUrl();
81
+
82
+ const response = await fetch(`${supabaseUrl}/functions/v1/automation-executor?id=${taskId}`, {
83
+ method: 'GET',
84
+ headers: {
85
+ 'Authorization': `Bearer ${apiKey}`
86
+ }
87
+ });
88
+
89
+ if (!response.ok) {
90
+ const error = await response.json().catch(() => ({ error: 'Unknown error' }));
91
+ throw new Error(`Failed to get task status: ${error.error || error.message}`);
92
+ }
93
+
94
+ return response.json();
95
+ }
96
+
97
+ /**
98
+ * Stream task logs
99
+ */
100
+ export async function* streamTaskLogs(taskId: string): AsyncGenerator<string> {
101
+ const apiKey = await getApiKey();
102
+ if (!apiKey) {
103
+ throw new Error('Not logged in. Run "vibe-weaver login" first.');
104
+ }
105
+
106
+ const supabaseUrl = getSupabaseUrl();
107
+
108
+ const response = await fetch(`${supabaseUrl}/functions/v1/automation-executor/logs?id=${taskId}`, {
109
+ method: 'GET',
110
+ headers: {
111
+ 'Authorization': `Bearer ${apiKey}`
112
+ }
113
+ });
114
+
115
+ if (!response.ok) {
116
+ throw new Error(`Failed to get task logs: ${response.status}`);
117
+ }
118
+
119
+ const reader = response.body?.getReader();
120
+ const decoder = new TextDecoder();
121
+
122
+ if (!reader) {
123
+ throw new Error('Could not read response body');
124
+ }
125
+
126
+ try {
127
+ while (true) {
128
+ const { done, value } = await reader.read();
129
+
130
+ if (done) break;
131
+
132
+ yield decoder.decode(value);
133
+ }
134
+ } finally {
135
+ reader.releaseLock();
136
+ }
137
+ }
138
+
139
+ /**
140
+ * Poll task status until completion
141
+ */
142
+ export async function waitForTask(taskId: string, options: {
143
+ pollInterval?: number;
144
+ onProgress?: (status: TaskStatus) => void;
145
+ } = {}): Promise<TaskStatus> {
146
+ const pollInterval = options.pollInterval || 5000;
147
+
148
+ while (true) {
149
+ const status = await getTaskStatus(taskId);
150
+
151
+ if (options.onProgress) {
152
+ options.onProgress(status);
153
+ }
154
+
155
+ if (status.status === 'completed') {
156
+ return status;
157
+ }
158
+
159
+ if (status.status === 'failed') {
160
+ throw new Error(`Task failed: ${status.error}`);
161
+ }
162
+
163
+ // Wait before next poll
164
+ await new Promise(resolve => setTimeout(resolve, pollInterval));
165
+ }
166
+ }
167
+
168
+ /**
169
+ * Display task status nicely
170
+ */
171
+ export function displayTaskStatus(status: TaskStatus): void {
172
+ const statusColor: Record<string, (s: string) => string> = {
173
+ pending: chalk.yellow,
174
+ running: chalk.blue,
175
+ completed: chalk.green,
176
+ failed: chalk.red
177
+ };
178
+
179
+ console.log(chalk.bold(`\nTask: ${status.id}`));
180
+ console.log(chalk.gray(`Status: ${statusColor[status.status] ? statusColor[status.status](status.status) : chalk.gray(status.status)}`));
181
+
182
+ if (status.progress !== undefined) {
183
+ console.log(chalk.gray(`Progress: ${status.progress}%`));
184
+ }
185
+
186
+ if (status.result) {
187
+ console.log(chalk.gray(`\nResult:`));
188
+ console.log(status.result);
189
+ }
190
+
191
+ if (status.error) {
192
+ console.log(chalk.red(`\nError: ${status.error}`));
193
+ }
194
+
195
+ console.log(chalk.gray(`\nCreated: ${new Date(status.createdAt).toLocaleString()}`));
196
+ console.log(chalk.gray(`Updated: ${new Date(status.updatedAt).toLocaleString()}`));
197
+ }
198
+
199
+ export default {
200
+ submitTask,
201
+ getTaskStatus,
202
+ streamTaskLogs,
203
+ waitForTask,
204
+ displayTaskStatus
205
+ };