@runflow-ai/cli 0.2.8 → 0.2.10
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/dist/commands/agents/agents.command.d.ts +1 -8
- package/dist/commands/agents/agents.command.js +36 -602
- package/dist/commands/agents/agents.command.js.map +1 -1
- package/dist/commands/agents/agents.service.d.ts +6 -0
- package/dist/commands/agents/agents.service.js +288 -0
- package/dist/commands/agents/agents.service.js.map +1 -0
- package/dist/commands/agents/file.service.d.ts +12 -0
- package/dist/commands/agents/file.service.js +166 -0
- package/dist/commands/agents/file.service.js.map +1 -0
- package/dist/commands/agents/git.service.d.ts +11 -0
- package/dist/commands/agents/git.service.js +135 -0
- package/dist/commands/agents/git.service.js.map +1 -0
- package/dist/commands/agents/types.d.ts +31 -0
- package/dist/commands/agents/types.js +8 -0
- package/dist/commands/agents/types.js.map +1 -0
- package/dist/common/api-client.js +6 -6
- package/dist/common/api-client.js.map +1 -1
- package/dist/common/validator.js +59 -59
- package/dist/common/validator.js.map +1 -1
- package/package.json +1 -1
- package/scenarios/webhook-hubspot-contact.json +2 -2
- package/scenarios/webhook-meta-messenger.json +1 -1
- package/scenarios/webhook-stripe.json +1 -1
- package/scenarios/webhook-zendesk-ticket.json +1 -1
|
@@ -1,43 +1,10 @@
|
|
|
1
1
|
"use strict";
|
|
2
|
-
var __createBinding = (this && this.__createBinding) || (Object.create ? (function(o, m, k, k2) {
|
|
3
|
-
if (k2 === undefined) k2 = k;
|
|
4
|
-
var desc = Object.getOwnPropertyDescriptor(m, k);
|
|
5
|
-
if (!desc || ("get" in desc ? !m.__esModule : desc.writable || desc.configurable)) {
|
|
6
|
-
desc = { enumerable: true, get: function() { return m[k]; } };
|
|
7
|
-
}
|
|
8
|
-
Object.defineProperty(o, k2, desc);
|
|
9
|
-
}) : (function(o, m, k, k2) {
|
|
10
|
-
if (k2 === undefined) k2 = k;
|
|
11
|
-
o[k2] = m[k];
|
|
12
|
-
}));
|
|
13
|
-
var __setModuleDefault = (this && this.__setModuleDefault) || (Object.create ? (function(o, v) {
|
|
14
|
-
Object.defineProperty(o, "default", { enumerable: true, value: v });
|
|
15
|
-
}) : function(o, v) {
|
|
16
|
-
o["default"] = v;
|
|
17
|
-
});
|
|
18
2
|
var __decorate = (this && this.__decorate) || function (decorators, target, key, desc) {
|
|
19
3
|
var c = arguments.length, r = c < 3 ? target : desc === null ? desc = Object.getOwnPropertyDescriptor(target, key) : desc, d;
|
|
20
4
|
if (typeof Reflect === "object" && typeof Reflect.decorate === "function") r = Reflect.decorate(decorators, target, key, desc);
|
|
21
5
|
else for (var i = decorators.length - 1; i >= 0; i--) if (d = decorators[i]) r = (c < 3 ? d(r) : c > 3 ? d(target, key, r) : d(target, key)) || r;
|
|
22
6
|
return c > 3 && r && Object.defineProperty(target, key, r), r;
|
|
23
7
|
};
|
|
24
|
-
var __importStar = (this && this.__importStar) || (function () {
|
|
25
|
-
var ownKeys = function(o) {
|
|
26
|
-
ownKeys = Object.getOwnPropertyNames || function (o) {
|
|
27
|
-
var ar = [];
|
|
28
|
-
for (var k in o) if (Object.prototype.hasOwnProperty.call(o, k)) ar[ar.length] = k;
|
|
29
|
-
return ar;
|
|
30
|
-
};
|
|
31
|
-
return ownKeys(o);
|
|
32
|
-
};
|
|
33
|
-
return function (mod) {
|
|
34
|
-
if (mod && mod.__esModule) return mod;
|
|
35
|
-
var result = {};
|
|
36
|
-
if (mod != null) for (var k = ownKeys(mod), i = 0; i < k.length; i++) if (k[i] !== "default") __createBinding(result, mod, k[i]);
|
|
37
|
-
__setModuleDefault(result, mod);
|
|
38
|
-
return result;
|
|
39
|
-
};
|
|
40
|
-
})();
|
|
41
8
|
var __metadata = (this && this.__metadata) || function (k, v) {
|
|
42
9
|
if (typeof Reflect === "object" && typeof Reflect.metadata === "function") return Reflect.metadata(k, v);
|
|
43
10
|
};
|
|
@@ -47,447 +14,38 @@ var __importDefault = (this && this.__importDefault) || function (mod) {
|
|
|
47
14
|
Object.defineProperty(exports, "__esModule", { value: true });
|
|
48
15
|
exports.AgentsCommand = void 0;
|
|
49
16
|
const nest_commander_1 = require("nest-commander");
|
|
50
|
-
const
|
|
51
|
-
const
|
|
52
|
-
const child_process_1 = require("child_process");
|
|
17
|
+
const chalk_1 = __importDefault(require("chalk"));
|
|
18
|
+
const inquirer = require("inquirer");
|
|
53
19
|
const config_1 = require("../../common/config");
|
|
54
20
|
const ui_1 = require("../../common/ui");
|
|
55
|
-
const inquirer = require("inquirer");
|
|
56
21
|
const logger_1 = require("../../common/logger");
|
|
57
22
|
const api_client_1 = require("../../common/api-client");
|
|
58
|
-
const
|
|
59
|
-
const
|
|
60
|
-
const SENSITIVE_FILES = ['.env'];
|
|
61
|
-
const IGNORE_DIRS = ['node_modules', 'dist', '.git', '.runflow'];
|
|
62
|
-
const IGNORE_FILES = ['.DS_Store', 'package-lock.json'];
|
|
63
|
-
const IGNORE_PATTERNS = [/\.log$/, /\.lock$/, /\.tmp$/];
|
|
64
|
-
async function showAgentActionMenu(agent) {
|
|
65
|
-
const actions = [
|
|
66
|
-
{ name: 'Clone repository (download)', value: 'clone' },
|
|
67
|
-
{ name: 'Pull latest changes', value: 'pull' },
|
|
68
|
-
{ name: 'Duplicate agent on server', value: 'duplicate' },
|
|
69
|
-
{ name: 'Deploy agent', value: 'deploy' },
|
|
70
|
-
{ name: 'Delete agent', value: 'delete' },
|
|
71
|
-
{ name: 'Cancel', value: 'cancel' }
|
|
72
|
-
];
|
|
73
|
-
const { action } = await inquirer.prompt([
|
|
74
|
-
{
|
|
75
|
-
type: 'list',
|
|
76
|
-
name: 'action',
|
|
77
|
-
message: `What would you like to do with "${agent.name}"?`,
|
|
78
|
-
choices: actions
|
|
79
|
-
}
|
|
80
|
-
]);
|
|
81
|
-
return action === 'cancel' ? null : action;
|
|
82
|
-
}
|
|
83
|
-
function sanitizeFileName(name) {
|
|
84
|
-
const sanitized = name
|
|
85
|
-
.replace(/[<>:"/\\|?*]/g, '-')
|
|
86
|
-
.replace(/\s+/g, '-')
|
|
87
|
-
.replace(/-+/g, '-')
|
|
88
|
-
.replace(/^-|-$/g, '')
|
|
89
|
-
.toLowerCase();
|
|
90
|
-
return sanitized || 'agent';
|
|
91
|
-
}
|
|
92
|
-
async function detectAgentFromCurrentDirectory() {
|
|
93
|
-
try {
|
|
94
|
-
const currentDir = process.cwd();
|
|
95
|
-
(0, logger_1.logVerbose)(`Checking for .runflow/rf.json in: ${currentDir}`);
|
|
96
|
-
const runflowDir = path.join(currentDir, '.runflow');
|
|
97
|
-
const runflowFile = path.join(runflowDir, 'rf.json');
|
|
98
|
-
if (fs.existsSync(runflowFile)) {
|
|
99
|
-
(0, logger_1.logVerbose)(`Found .runflow/rf.json at: ${runflowFile}`);
|
|
100
|
-
const content = fs.readFileSync(runflowFile, 'utf8');
|
|
101
|
-
(0, logger_1.logVerbose)(`Raw rf.json content: ${content}`);
|
|
102
|
-
const config = JSON.parse(content);
|
|
103
|
-
(0, logger_1.logVerbose)(`Parsed rf.json config: ${JSON.stringify(config)}`);
|
|
104
|
-
const agentId = config.agentId || null;
|
|
105
|
-
if (agentId) {
|
|
106
|
-
(0, logger_1.logVerbose)(`Detected agent ${agentId} from .runflow/rf.json`);
|
|
107
|
-
}
|
|
108
|
-
else {
|
|
109
|
-
(0, logger_1.logVerbose)(`No agentId found in .runflow/rf.json`);
|
|
110
|
-
}
|
|
111
|
-
return agentId;
|
|
112
|
-
}
|
|
113
|
-
const oldRunflowFile = path.join(currentDir, '.runflow');
|
|
114
|
-
if (fs.existsSync(oldRunflowFile) && fs.statSync(oldRunflowFile).isFile()) {
|
|
115
|
-
(0, logger_1.logVerbose)(`Found legacy .runflow file at: ${oldRunflowFile}`);
|
|
116
|
-
const content = fs.readFileSync(oldRunflowFile, 'utf8');
|
|
117
|
-
const config = JSON.parse(content);
|
|
118
|
-
const agentId = config.agentId || null;
|
|
119
|
-
if (agentId) {
|
|
120
|
-
(0, logger_1.logVerbose)(`Detected agent ${agentId} from legacy .runflow file`);
|
|
121
|
-
}
|
|
122
|
-
return agentId;
|
|
123
|
-
}
|
|
124
|
-
(0, logger_1.logVerbose)(`No .runflow/rf.json found in current directory: ${currentDir}`);
|
|
125
|
-
return null;
|
|
126
|
-
}
|
|
127
|
-
catch (error) {
|
|
128
|
-
(0, logger_1.logVerbose)(`Error reading .runflow/rf.json: ${error}`);
|
|
129
|
-
return null;
|
|
130
|
-
}
|
|
131
|
-
}
|
|
132
|
-
function dirToTree(dir, base = dir) {
|
|
133
|
-
(0, logger_1.logVerbose)(`📁 Scanning directory: ${dir}`);
|
|
134
|
-
const result = fs.readdirSync(dir, { withFileTypes: true }).reduce((acc, entry) => {
|
|
135
|
-
const fullPath = path.join(dir, entry.name);
|
|
136
|
-
const relPath = path.relative(base, fullPath).replace(/\\/g, '/');
|
|
137
|
-
if (IGNORE_DIRS.includes(entry.name) ||
|
|
138
|
-
SENSITIVE_FILES.includes(entry.name) ||
|
|
139
|
-
IGNORE_FILES.includes(entry.name) ||
|
|
140
|
-
IGNORE_PATTERNS.some(pattern => pattern.test(entry.name))) {
|
|
141
|
-
return acc;
|
|
142
|
-
}
|
|
143
|
-
if (entry.name === '.runflow') {
|
|
144
|
-
return acc;
|
|
145
|
-
}
|
|
146
|
-
if (entry.isDirectory()) {
|
|
147
|
-
acc.push(...dirToTree(fullPath, base));
|
|
148
|
-
}
|
|
149
|
-
else if (entry.isFile()) {
|
|
150
|
-
const relPath = path.relative(base, fullPath).replace(/\\/g, '/');
|
|
151
|
-
try {
|
|
152
|
-
const content = fs.readFileSync(fullPath, 'utf8');
|
|
153
|
-
acc.push({ path: relPath, mode: '100644', type: 'blob', content });
|
|
154
|
-
}
|
|
155
|
-
catch (error) {
|
|
156
|
-
(0, logger_1.logVerbose)(`❌ Error reading file ${relPath}: ${error}`);
|
|
157
|
-
}
|
|
158
|
-
}
|
|
159
|
-
return acc;
|
|
160
|
-
}, []);
|
|
161
|
-
(0, logger_1.logVerbose)(`📊 Directory ${dir} contributed ${result.length} items`);
|
|
162
|
-
return result;
|
|
163
|
-
}
|
|
23
|
+
const file_service_1 = require("./file.service");
|
|
24
|
+
const agents_service_1 = require("./agents.service");
|
|
164
25
|
let AgentsCommand = class AgentsCommand extends nest_commander_1.CommandRunner {
|
|
165
|
-
async performDeploy(targetAgentId, apiClient, data) {
|
|
166
|
-
const validation = (0, validator_1.validateForDeploy)();
|
|
167
|
-
if (!validation.isValid) {
|
|
168
|
-
console.error(chalk_1.default.red('\n❌ Deploy validation failed!'));
|
|
169
|
-
validation.errors.forEach(error => {
|
|
170
|
-
console.error(chalk_1.default.red(` • ${error}`));
|
|
171
|
-
});
|
|
172
|
-
console.error(chalk_1.default.gray('\n📚 Documentation: https://docs.runflow.ai\n'));
|
|
173
|
-
return;
|
|
174
|
-
}
|
|
175
|
-
(0, logger_1.logVerbose)(`Deploying agent ${targetAgentId} with local changes...`);
|
|
176
|
-
(0, logger_1.logVerbose)(`Current directory: ${process.cwd()}`);
|
|
177
|
-
const baseRepo = path.basename(process.cwd());
|
|
178
|
-
const { config } = (0, config_1.getValidatedConfig)();
|
|
179
|
-
const repo = `${config.tenantId}-${baseRepo}`;
|
|
180
|
-
const tree = dirToTree(process.cwd()).filter((item) => Boolean(item.path));
|
|
181
|
-
const deletedFilesFromGit = this.getDeletedFiles();
|
|
182
|
-
const fullTree = [...tree, ...deletedFilesFromGit];
|
|
183
|
-
const defaultPayload = {
|
|
184
|
-
repo,
|
|
185
|
-
message: 'deploy with local changes',
|
|
186
|
-
tree: fullTree,
|
|
187
|
-
branch: 'main',
|
|
188
|
-
};
|
|
189
|
-
const payload = data
|
|
190
|
-
? JSON.parse(data)
|
|
191
|
-
: defaultPayload;
|
|
192
|
-
const normalFiles = payload.tree.filter(item => !item.deleted);
|
|
193
|
-
const deletedFiles = payload.tree.filter(item => item.deleted);
|
|
194
|
-
console.log(chalk_1.default.cyan.bold('\n📦 Deploy Preview:'));
|
|
195
|
-
console.log(chalk_1.default.gray(`Repository: ${payload.repo}`));
|
|
196
|
-
console.log(chalk_1.default.gray(`Files: ${normalFiles.length} to deploy, ${deletedFiles.length} to delete`));
|
|
197
|
-
if (normalFiles.length > 0) {
|
|
198
|
-
console.log(chalk_1.default.green('\n📄 Files to deploy:'));
|
|
199
|
-
normalFiles.slice(0, 10).forEach((item, index) => {
|
|
200
|
-
const size = item.content?.length || 0;
|
|
201
|
-
const sizeStr = size > 1024 ? `${Math.round(size / 1024)}KB` : `${size}B`;
|
|
202
|
-
console.log(chalk_1.default.gray(` ${index + 1}.`), chalk_1.default.white(item.path), chalk_1.default.gray(`(${sizeStr})`));
|
|
203
|
-
});
|
|
204
|
-
if (normalFiles.length > 10) {
|
|
205
|
-
console.log(chalk_1.default.gray(` ... and ${normalFiles.length - 10} more files`));
|
|
206
|
-
}
|
|
207
|
-
}
|
|
208
|
-
if (deletedFiles.length > 0) {
|
|
209
|
-
console.log(chalk_1.default.red('\n🗑️ Files to delete:'));
|
|
210
|
-
deletedFiles.forEach((item, index) => {
|
|
211
|
-
console.log(chalk_1.default.gray(` ${index + 1}.`), chalk_1.default.white(item.path));
|
|
212
|
-
});
|
|
213
|
-
}
|
|
214
|
-
if (payload.tree.length === 0) {
|
|
215
|
-
console.log(chalk_1.default.yellow('\n⚠️ No files to deploy!'));
|
|
216
|
-
return;
|
|
217
|
-
}
|
|
218
|
-
const { confirm } = await inquirer.prompt([
|
|
219
|
-
{
|
|
220
|
-
type: 'confirm',
|
|
221
|
-
name: 'confirm',
|
|
222
|
-
message: `Deploy ${normalFiles.length} files to agent ${targetAgentId}?`,
|
|
223
|
-
default: true
|
|
224
|
-
}
|
|
225
|
-
]);
|
|
226
|
-
if (!confirm) {
|
|
227
|
-
console.log(chalk_1.default.yellow('Deploy cancelled'));
|
|
228
|
-
return;
|
|
229
|
-
}
|
|
230
|
-
console.log(chalk_1.default.blue('\n🚀 Deploying...'));
|
|
231
|
-
const res = await apiClient.patch(`/agents/${targetAgentId}/deploy`, payload);
|
|
232
|
-
console.log(chalk_1.default.green.bold('\n✅ Deploy Successful!'));
|
|
233
|
-
console.log(chalk_1.default.gray(`📦 ${normalFiles.length} files deployed`));
|
|
234
|
-
console.log(chalk_1.default.gray(`🕐 ${new Date().toLocaleTimeString()}`));
|
|
235
|
-
try {
|
|
236
|
-
(0, logger_1.logVerbose)(`Creating commit for deployed changes...`);
|
|
237
|
-
const currentDir = process.cwd();
|
|
238
|
-
(0, child_process_1.execSync)('git add .', { cwd: currentDir, stdio: 'pipe' });
|
|
239
|
-
const timestamp = new Date().toISOString().replace('T', ' ').split('.')[0];
|
|
240
|
-
const commitMessage = `Deploy: ${timestamp}`;
|
|
241
|
-
(0, child_process_1.execSync)(`git commit -m "${commitMessage}"`, { cwd: currentDir, stdio: 'pipe' });
|
|
242
|
-
(0, logger_1.logVerbose)(`✅ Auto-commit created: ${commitMessage}`);
|
|
243
|
-
}
|
|
244
|
-
catch (commitError) {
|
|
245
|
-
(0, logger_1.logVerbose)(`⚠️ Could not create auto-commit: ${commitError}`);
|
|
246
|
-
}
|
|
247
|
-
}
|
|
248
|
-
async checkForLocalChanges() {
|
|
249
|
-
try {
|
|
250
|
-
const status = (0, child_process_1.execSync)('git status --porcelain', { cwd: process.cwd(), stdio: 'pipe' }).toString().trim();
|
|
251
|
-
return status.length > 0;
|
|
252
|
-
}
|
|
253
|
-
catch (error) {
|
|
254
|
-
(0, logger_1.logVerbose)(`Could not check git status: ${error}`);
|
|
255
|
-
return true;
|
|
256
|
-
}
|
|
257
|
-
}
|
|
258
|
-
getDeletedFiles() {
|
|
259
|
-
try {
|
|
260
|
-
const status = (0, child_process_1.execSync)('git status --porcelain', { cwd: process.cwd(), stdio: 'pipe' }).toString();
|
|
261
|
-
const deletedFiles = [];
|
|
262
|
-
const lines = status.split('\n').filter(line => line.trim());
|
|
263
|
-
for (const line of lines) {
|
|
264
|
-
const statusCode = line.substring(0, 2);
|
|
265
|
-
const filePath = line.substring(3);
|
|
266
|
-
if (statusCode.includes('D')) {
|
|
267
|
-
(0, logger_1.logVerbose)(`🗑️ Detected deleted file: ${filePath}`);
|
|
268
|
-
deletedFiles.push({
|
|
269
|
-
path: filePath,
|
|
270
|
-
mode: '100644',
|
|
271
|
-
type: 'blob',
|
|
272
|
-
content: '',
|
|
273
|
-
deleted: true
|
|
274
|
-
});
|
|
275
|
-
}
|
|
276
|
-
}
|
|
277
|
-
(0, logger_1.logVerbose)(`Found ${deletedFiles.length} deleted files`);
|
|
278
|
-
return deletedFiles;
|
|
279
|
-
}
|
|
280
|
-
catch (error) {
|
|
281
|
-
(0, logger_1.logVerbose)(`Could not get deleted files: ${error}`);
|
|
282
|
-
return [];
|
|
283
|
-
}
|
|
284
|
-
}
|
|
285
26
|
async executeAction(action, agent, apiClient) {
|
|
286
27
|
const agentId = agent.id;
|
|
287
|
-
const agentName = sanitizeFileName(agent.name || agent.id);
|
|
28
|
+
const agentName = file_service_1.FileService.sanitizeFileName(agent.name || agent.id);
|
|
288
29
|
switch (action) {
|
|
289
30
|
case 'clone': {
|
|
290
|
-
|
|
291
|
-
(0, child_process_1.execSync)('git --version', { stdio: 'pipe', timeout: 3000 });
|
|
292
|
-
}
|
|
293
|
-
catch (error) {
|
|
294
|
-
console.log(chalk_1.default.red('Git is required for cloning agents'));
|
|
295
|
-
console.log(chalk_1.default.gray('Install Git: https://git-scm.com\n'));
|
|
296
|
-
return;
|
|
297
|
-
}
|
|
298
|
-
console.log(chalk_1.default.blue('Cloning agent repository...'));
|
|
299
|
-
const res = await apiClient.get(`/agents/${agentId}/clone`);
|
|
300
|
-
const tree = res.data;
|
|
301
|
-
(0, logger_1.logVerbose)(`Received ${tree.length} items from API`);
|
|
302
|
-
const gitFiles = tree.filter(item => item.path.startsWith('.git'));
|
|
303
|
-
(0, logger_1.logVerbose)(`Found ${gitFiles.length} .git files: ${gitFiles.map(f => f.path).join(', ')}`);
|
|
304
|
-
let dir = agentName;
|
|
305
|
-
if (fs.existsSync(dir)) {
|
|
306
|
-
console.log(chalk_1.default.yellow(`\n⚠ Directory "${dir}" already exists`));
|
|
307
|
-
const { action } = await inquirer.prompt([
|
|
308
|
-
{
|
|
309
|
-
type: 'list',
|
|
310
|
-
name: 'action',
|
|
311
|
-
message: 'What would you like to do?',
|
|
312
|
-
choices: [
|
|
313
|
-
{ name: 'Overwrite existing directory', value: 'overwrite' },
|
|
314
|
-
{ name: 'Clone with different name', value: 'rename' },
|
|
315
|
-
{ name: 'Cancel', value: 'cancel' }
|
|
316
|
-
]
|
|
317
|
-
}
|
|
318
|
-
]);
|
|
319
|
-
if (action === 'cancel') {
|
|
320
|
-
console.log(chalk_1.default.gray('Clone cancelled'));
|
|
321
|
-
return;
|
|
322
|
-
}
|
|
323
|
-
if (action === 'rename') {
|
|
324
|
-
const { newName } = await inquirer.prompt([
|
|
325
|
-
{
|
|
326
|
-
type: 'input',
|
|
327
|
-
name: 'newName',
|
|
328
|
-
message: 'Enter new directory name:',
|
|
329
|
-
default: `${agentName}-copy`,
|
|
330
|
-
validate: (input) => {
|
|
331
|
-
if (!input.trim())
|
|
332
|
-
return 'Directory name cannot be empty';
|
|
333
|
-
if (fs.existsSync(input.trim()))
|
|
334
|
-
return `Directory "${input.trim()}" already exists`;
|
|
335
|
-
return true;
|
|
336
|
-
}
|
|
337
|
-
}
|
|
338
|
-
]);
|
|
339
|
-
dir = newName.trim();
|
|
340
|
-
console.log(chalk_1.default.blue(`Using directory name: ${dir}`));
|
|
341
|
-
}
|
|
342
|
-
else if (action === 'overwrite') {
|
|
343
|
-
fs.rmSync(dir, { recursive: true, force: true });
|
|
344
|
-
console.log(chalk_1.default.blue('Removed existing directory'));
|
|
345
|
-
}
|
|
346
|
-
}
|
|
347
|
-
fs.mkdirSync(dir, { recursive: true });
|
|
348
|
-
const gitRefFiles = {};
|
|
349
|
-
const regularFiles = tree.filter(item => {
|
|
350
|
-
if (item.path === '.git/config' || item.path === '.git/HEAD') {
|
|
351
|
-
if (item.content) {
|
|
352
|
-
gitRefFiles[item.path] = item.content;
|
|
353
|
-
}
|
|
354
|
-
return false;
|
|
355
|
-
}
|
|
356
|
-
return true;
|
|
357
|
-
});
|
|
358
|
-
for (const item of regularFiles) {
|
|
359
|
-
if (SENSITIVE_FILES.includes(item.path)) {
|
|
360
|
-
(0, logger_1.logVerbose)(`Skipping sensitive file: ${item.path}`);
|
|
361
|
-
continue;
|
|
362
|
-
}
|
|
363
|
-
(0, logger_1.logVerbose)(`Processing: ${item.path} (type: ${item.type})`);
|
|
364
|
-
const filePath = path.join(dir, item.path);
|
|
365
|
-
if (item.type === 'blob') {
|
|
366
|
-
const dirPath = path.dirname(filePath);
|
|
367
|
-
(0, logger_1.logVerbose)(`Creating directory: ${dirPath}`);
|
|
368
|
-
fs.mkdirSync(dirPath, { recursive: true });
|
|
369
|
-
(0, logger_1.logVerbose)(`Writing file: ${filePath}`);
|
|
370
|
-
fs.writeFileSync(filePath, item.content ?? '', 'utf8');
|
|
371
|
-
}
|
|
372
|
-
else if (item.type === 'tree') {
|
|
373
|
-
(0, logger_1.logVerbose)(`Creating tree directory: ${filePath}`);
|
|
374
|
-
fs.mkdirSync(filePath, { recursive: true });
|
|
375
|
-
}
|
|
376
|
-
}
|
|
377
|
-
(0, logger_1.logVerbose)(`Initializing git repository in ${dir}/`);
|
|
378
|
-
try {
|
|
379
|
-
const resolvedDir = path.resolve(dir);
|
|
380
|
-
(0, child_process_1.execSync)('git init', { cwd: resolvedDir, stdio: 'pipe' });
|
|
381
|
-
(0, logger_1.logVerbose)(`✅ Git repository initialized`);
|
|
382
|
-
for (const [gitPath, content] of Object.entries(gitRefFiles)) {
|
|
383
|
-
const fullPath = path.join(dir, gitPath);
|
|
384
|
-
(0, logger_1.logVerbose)(`Applying git reference file: ${gitPath}`);
|
|
385
|
-
fs.mkdirSync(path.dirname(fullPath), { recursive: true });
|
|
386
|
-
fs.writeFileSync(fullPath, content, 'utf8');
|
|
387
|
-
}
|
|
388
|
-
(0, logger_1.logVerbose)(`✅ Applied ${Object.keys(gitRefFiles).length} git reference files`);
|
|
389
|
-
(0, child_process_1.execSync)('git config user.name "Runflow CLI"', { cwd: resolvedDir, stdio: 'pipe' });
|
|
390
|
-
(0, child_process_1.execSync)('git config user.email "noreply@runflow.ai"', { cwd: resolvedDir, stdio: 'pipe' });
|
|
391
|
-
(0, child_process_1.execSync)('git add .', { cwd: resolvedDir, stdio: 'pipe' });
|
|
392
|
-
await new Promise(resolve => setTimeout(resolve, 100));
|
|
393
|
-
(0, child_process_1.execSync)('git commit -m "Initial commit"', { cwd: resolvedDir, stdio: 'pipe' });
|
|
394
|
-
(0, logger_1.logVerbose)(`✅ Initial commit created`);
|
|
395
|
-
}
|
|
396
|
-
catch (error) {
|
|
397
|
-
(0, logger_1.logVerbose)(`❌ Error initializing git: ${error}`);
|
|
398
|
-
}
|
|
399
|
-
const runflowPath = path.join(dir, '.runflow', 'rf.json');
|
|
400
|
-
if (fs.existsSync(runflowPath)) {
|
|
401
|
-
(0, logger_1.logVerbose)(`✅ .runflow/rf.json provided by API for deploy operations`);
|
|
402
|
-
}
|
|
403
|
-
else {
|
|
404
|
-
(0, logger_1.logVerbose)(`⚠️ No .runflow/rf.json found - deploy may not work`);
|
|
405
|
-
}
|
|
406
|
-
console.log(chalk_1.default.green.bold(`\n✓ Repository cloned to ${dir}/`));
|
|
407
|
-
console.log(chalk_1.default.cyan.bold('\nNext Steps:'));
|
|
408
|
-
console.log(chalk_1.default.gray('1.'), chalk_1.default.white(`cd ${dir}`));
|
|
409
|
-
console.log(chalk_1.default.gray('2.'), chalk_1.default.white('npm install'));
|
|
410
|
-
console.log(chalk_1.default.gray('3.'), chalk_1.default.white('rf test'), chalk_1.default.gray('# Start test interface'));
|
|
411
|
-
console.log(chalk_1.default.gray('4.'), chalk_1.default.white('rf deploy'), chalk_1.default.gray('# Deploy changes back'));
|
|
412
|
-
console.log(chalk_1.default.cyan.bold('\nQuick Start:'));
|
|
413
|
-
console.log(chalk_1.default.white(`cd ${dir} && npm install && rf test`));
|
|
31
|
+
await agents_service_1.AgentsService.cloneAgent(agentId, agentName, apiClient);
|
|
414
32
|
break;
|
|
415
33
|
}
|
|
416
34
|
case 'pull': {
|
|
417
|
-
const
|
|
418
|
-
if (!
|
|
35
|
+
const detectedAgent = await file_service_1.FileService.detectAgentFromCurrentDirectory();
|
|
36
|
+
if (!detectedAgent) {
|
|
419
37
|
(0, logger_1.logError)('❌ Pull requires being in a cloned agent directory with .runflow/rf.json.');
|
|
420
38
|
(0, logger_1.logError)('💡 Either:');
|
|
421
39
|
(0, logger_1.logError)(' 1. Navigate to a cloned agent directory and try again');
|
|
422
40
|
(0, logger_1.logError)(' 2. Use "Clone repository" first to download the agent');
|
|
423
41
|
return;
|
|
424
42
|
}
|
|
425
|
-
if (
|
|
426
|
-
(0, logger_1.logError)(`❌ Directory mismatch: Current directory has agent ${
|
|
43
|
+
if (detectedAgent.agentId !== agentId) {
|
|
44
|
+
(0, logger_1.logError)(`❌ Directory mismatch: Current directory has agent ${detectedAgent.agentId}${detectedAgent.agentName ? ` (${detectedAgent.agentName})` : ''}, but menu selected agent ${agentId}`);
|
|
427
45
|
(0, logger_1.logError)('💡 Navigate to the correct agent directory or select the matching agent in the menu.');
|
|
428
46
|
return;
|
|
429
47
|
}
|
|
430
|
-
|
|
431
|
-
if (hasChanges) {
|
|
432
|
-
(0, logger_1.logVerbose)('Local changes detected in repository');
|
|
433
|
-
const { confirm } = await inquirer.prompt([
|
|
434
|
-
{
|
|
435
|
-
type: 'confirm',
|
|
436
|
-
name: 'confirm',
|
|
437
|
-
message: '⚠️ You have local changes. Pull will overwrite them. Continue?',
|
|
438
|
-
default: false
|
|
439
|
-
}
|
|
440
|
-
]);
|
|
441
|
-
if (!confirm) {
|
|
442
|
-
(0, logger_1.logSuccess)('Pull cancelled');
|
|
443
|
-
return;
|
|
444
|
-
}
|
|
445
|
-
}
|
|
446
|
-
(0, logger_1.logVerbose)(`Pulling latest changes for agent ${agentId}...`);
|
|
447
|
-
const res = await apiClient.get(`/agents/${agentId}/clone`);
|
|
448
|
-
const tree = res.data;
|
|
449
|
-
(0, logger_1.logVerbose)(`Received ${tree.length} items from API`);
|
|
450
|
-
const currentFiles = fs.readdirSync(process.cwd(), { withFileTypes: true });
|
|
451
|
-
for (const file of currentFiles) {
|
|
452
|
-
if (file.name === '.git' || file.name === '.runflow') {
|
|
453
|
-
continue;
|
|
454
|
-
}
|
|
455
|
-
const filePath = path.join(process.cwd(), file.name);
|
|
456
|
-
if (file.isDirectory()) {
|
|
457
|
-
fs.rmSync(filePath, { recursive: true, force: true });
|
|
458
|
-
}
|
|
459
|
-
else {
|
|
460
|
-
fs.unlinkSync(filePath);
|
|
461
|
-
}
|
|
462
|
-
}
|
|
463
|
-
for (const item of tree) {
|
|
464
|
-
if (SENSITIVE_FILES.includes(item.path) || item.path.startsWith('.git/')) {
|
|
465
|
-
(0, logger_1.logVerbose)(`Skipping: ${item.path}`);
|
|
466
|
-
continue;
|
|
467
|
-
}
|
|
468
|
-
(0, logger_1.logVerbose)(`Writing: ${item.path} (type: ${item.type})`);
|
|
469
|
-
const filePath = path.join(process.cwd(), item.path);
|
|
470
|
-
if (item.type === 'blob') {
|
|
471
|
-
const dirPath = path.dirname(filePath);
|
|
472
|
-
fs.mkdirSync(dirPath, { recursive: true });
|
|
473
|
-
fs.writeFileSync(filePath, item.content ?? '', 'utf8');
|
|
474
|
-
}
|
|
475
|
-
else if (item.type === 'tree') {
|
|
476
|
-
fs.mkdirSync(filePath, { recursive: true });
|
|
477
|
-
}
|
|
478
|
-
}
|
|
479
|
-
try {
|
|
480
|
-
(0, logger_1.logVerbose)(`Creating commit for pulled changes...`);
|
|
481
|
-
(0, child_process_1.execSync)('git add .', { cwd: process.cwd(), stdio: 'pipe' });
|
|
482
|
-
const timestamp = new Date().toISOString().replace('T', ' ').split('.')[0];
|
|
483
|
-
const commitMessage = `Pull: ${timestamp}`;
|
|
484
|
-
(0, child_process_1.execSync)(`git commit -m "${commitMessage}"`, { cwd: process.cwd(), stdio: 'pipe' });
|
|
485
|
-
(0, logger_1.logVerbose)(`✅ Auto-commit created: ${commitMessage}`);
|
|
486
|
-
}
|
|
487
|
-
catch (commitError) {
|
|
488
|
-
(0, logger_1.logVerbose)(`⚠️ Could not create auto-commit: ${commitError}`);
|
|
489
|
-
}
|
|
490
|
-
(0, logger_1.logSuccess)('Latest changes pulled successfully');
|
|
48
|
+
await agents_service_1.AgentsService.pullAgent(agentId, detectedAgent.agentName, apiClient);
|
|
491
49
|
break;
|
|
492
50
|
}
|
|
493
51
|
case 'duplicate': {
|
|
@@ -497,20 +55,20 @@ let AgentsCommand = class AgentsCommand extends nest_commander_1.CommandRunner {
|
|
|
497
55
|
break;
|
|
498
56
|
}
|
|
499
57
|
case 'deploy': {
|
|
500
|
-
const
|
|
501
|
-
if (!
|
|
58
|
+
const detectedAgent = await file_service_1.FileService.detectAgentFromCurrentDirectory();
|
|
59
|
+
if (!detectedAgent) {
|
|
502
60
|
(0, logger_1.logError)('❌ Deploy from menu requires being in a cloned agent directory with .runflow/rf.json.');
|
|
503
61
|
(0, logger_1.logError)('💡 Either:');
|
|
504
62
|
(0, logger_1.logError)(' 1. Navigate to a cloned agent directory and try again');
|
|
505
63
|
(0, logger_1.logError)(' 2. Use "Clone repository" first to download the agent');
|
|
506
64
|
return;
|
|
507
65
|
}
|
|
508
|
-
if (
|
|
509
|
-
(0, logger_1.logError)(`❌ Directory mismatch: Current directory has agent ${
|
|
66
|
+
if (detectedAgent.agentId !== agentId) {
|
|
67
|
+
(0, logger_1.logError)(`❌ Directory mismatch: Current directory has agent ${detectedAgent.agentId}${detectedAgent.agentName ? ` (${detectedAgent.agentName})` : ''}, but menu selected agent ${agentId}`);
|
|
510
68
|
(0, logger_1.logError)('💡 Navigate to the correct agent directory or select the matching agent in the menu.');
|
|
511
69
|
return;
|
|
512
70
|
}
|
|
513
|
-
await
|
|
71
|
+
await agents_service_1.AgentsService.performDeploy(detectedAgent.agentId, apiClient, undefined, detectedAgent.agentName);
|
|
514
72
|
break;
|
|
515
73
|
}
|
|
516
74
|
case 'delete': {
|
|
@@ -581,7 +139,7 @@ let AgentsCommand = class AgentsCommand extends nest_commander_1.CommandRunner {
|
|
|
581
139
|
const selected = await (0, ui_1.selectItem)(agents, 'Select an agent:');
|
|
582
140
|
(0, config_1.saveConfig)({ agentId: selected.id });
|
|
583
141
|
console.log(chalk_1.default.green(`\n✓ Selected: ${selected.name}`));
|
|
584
|
-
const selectedAction = await showAgentActionMenu(selected);
|
|
142
|
+
const selectedAction = await agents_service_1.AgentsService.showAgentActionMenu(selected);
|
|
585
143
|
if (!selectedAction) {
|
|
586
144
|
console.log(chalk_1.default.gray('Operation cancelled'));
|
|
587
145
|
return;
|
|
@@ -590,13 +148,15 @@ let AgentsCommand = class AgentsCommand extends nest_commander_1.CommandRunner {
|
|
|
590
148
|
break;
|
|
591
149
|
}
|
|
592
150
|
case 'get': {
|
|
593
|
-
|
|
151
|
+
const detectedAgent = await file_service_1.FileService.detectAgentFromCurrentDirectory();
|
|
152
|
+
if (!agentId && !detectedAgent) {
|
|
594
153
|
console.log(chalk_1.default.red('No agent selected'));
|
|
595
154
|
console.log(chalk_1.default.gray('Run: rf agents list'));
|
|
596
155
|
return;
|
|
597
156
|
}
|
|
157
|
+
const targetAgentId = detectedAgent?.agentId || agentId;
|
|
598
158
|
console.log(chalk_1.default.blue(`Fetching agent details...`));
|
|
599
|
-
const res = await apiClient.get(`/agents/${
|
|
159
|
+
const res = await apiClient.get(`/agents/${targetAgentId}`);
|
|
600
160
|
console.log(chalk_1.default.cyan.bold('\nAgent Details:'));
|
|
601
161
|
console.log(chalk_1.default.gray(`Name: ${res.data.name}`));
|
|
602
162
|
console.log(chalk_1.default.gray(`ID: ${res.data.id}`));
|
|
@@ -604,6 +164,13 @@ let AgentsCommand = class AgentsCommand extends nest_commander_1.CommandRunner {
|
|
|
604
164
|
if (res.data.updatedAt) {
|
|
605
165
|
console.log(chalk_1.default.gray(`Updated: ${new Date(res.data.updatedAt).toLocaleString()}`));
|
|
606
166
|
}
|
|
167
|
+
if (detectedAgent && detectedAgent.agentName) {
|
|
168
|
+
console.log(chalk_1.default.cyan.bold('\nLocal Info:'));
|
|
169
|
+
console.log(chalk_1.default.gray(`Agent Name: ${detectedAgent.agentName}`));
|
|
170
|
+
if (detectedAgent.tenantId) {
|
|
171
|
+
console.log(chalk_1.default.gray(`Tenant ID: ${detectedAgent.tenantId}`));
|
|
172
|
+
}
|
|
173
|
+
}
|
|
607
174
|
break;
|
|
608
175
|
}
|
|
609
176
|
case 'create': {
|
|
@@ -645,155 +212,22 @@ let AgentsCommand = class AgentsCommand extends nest_commander_1.CommandRunner {
|
|
|
645
212
|
(0, logger_1.logError)(config_1.ERROR_MESSAGES.AGENT_NOT_SELECTED);
|
|
646
213
|
return;
|
|
647
214
|
}
|
|
648
|
-
(0, logger_1.logVerbose)(`Cloning agent ${agentId} repository...`);
|
|
649
215
|
const agentRes = await apiClient.get(`/agents/${agentId}`);
|
|
650
216
|
const originalName = agentRes.data.name || agentId;
|
|
651
|
-
const agentName = sanitizeFileName(originalName);
|
|
217
|
+
const agentName = file_service_1.FileService.sanitizeFileName(originalName);
|
|
652
218
|
if (originalName !== agentName) {
|
|
653
219
|
console.log(chalk_1.default.gray(`Directory name: "${originalName}" → "${agentName}"`));
|
|
654
220
|
}
|
|
655
|
-
|
|
656
|
-
const tree = res.data;
|
|
657
|
-
(0, logger_1.logVerbose)(`Received ${tree.length} items from API`);
|
|
658
|
-
const gitFiles = tree.filter(item => item.path.startsWith('.git'));
|
|
659
|
-
(0, logger_1.logVerbose)(`Found ${gitFiles.length} .git files: ${gitFiles.map(f => f.path).join(', ')}`);
|
|
660
|
-
const dir = agentName;
|
|
661
|
-
fs.mkdirSync(dir, { recursive: true });
|
|
662
|
-
const gitRefFiles = {};
|
|
663
|
-
const regularFiles = tree.filter(item => {
|
|
664
|
-
if (item.path === '.git/config' || item.path === '.git/HEAD') {
|
|
665
|
-
if (item.content) {
|
|
666
|
-
gitRefFiles[item.path] = item.content;
|
|
667
|
-
}
|
|
668
|
-
return false;
|
|
669
|
-
}
|
|
670
|
-
return true;
|
|
671
|
-
});
|
|
672
|
-
for (const item of regularFiles) {
|
|
673
|
-
if (SENSITIVE_FILES.includes(item.path)) {
|
|
674
|
-
(0, logger_1.logVerbose)(`Skipping sensitive file: ${item.path}`);
|
|
675
|
-
continue;
|
|
676
|
-
}
|
|
677
|
-
(0, logger_1.logVerbose)(`Processing: ${item.path} (type: ${item.type})`);
|
|
678
|
-
const filePath = path.join(dir, item.path);
|
|
679
|
-
if (item.type === 'blob') {
|
|
680
|
-
const dirPath = path.dirname(filePath);
|
|
681
|
-
(0, logger_1.logVerbose)(`Creating directory: ${dirPath}`);
|
|
682
|
-
fs.mkdirSync(dirPath, { recursive: true });
|
|
683
|
-
(0, logger_1.logVerbose)(`Writing file: ${filePath}`);
|
|
684
|
-
fs.writeFileSync(filePath, item.content ?? '', 'utf8');
|
|
685
|
-
}
|
|
686
|
-
else if (item.type === 'tree') {
|
|
687
|
-
(0, logger_1.logVerbose)(`Creating tree directory: ${filePath}`);
|
|
688
|
-
fs.mkdirSync(filePath, { recursive: true });
|
|
689
|
-
}
|
|
690
|
-
}
|
|
691
|
-
(0, logger_1.logVerbose)(`Initializing git repository in ${dir}/`);
|
|
692
|
-
try {
|
|
693
|
-
const resolvedDir = path.resolve(dir);
|
|
694
|
-
(0, child_process_1.execSync)('git init', { cwd: resolvedDir, stdio: 'pipe' });
|
|
695
|
-
(0, logger_1.logVerbose)(`✅ Git repository initialized`);
|
|
696
|
-
for (const [gitPath, content] of Object.entries(gitRefFiles)) {
|
|
697
|
-
const fullPath = path.join(dir, gitPath);
|
|
698
|
-
(0, logger_1.logVerbose)(`Applying git reference file: ${gitPath}`);
|
|
699
|
-
fs.mkdirSync(path.dirname(fullPath), { recursive: true });
|
|
700
|
-
fs.writeFileSync(fullPath, content, 'utf8');
|
|
701
|
-
}
|
|
702
|
-
(0, logger_1.logVerbose)(`✅ Applied ${Object.keys(gitRefFiles).length} git reference files`);
|
|
703
|
-
(0, child_process_1.execSync)('git config user.name "Runflow CLI"', { cwd: resolvedDir, stdio: 'pipe' });
|
|
704
|
-
(0, child_process_1.execSync)('git config user.email "noreply@runflow.ai"', { cwd: resolvedDir, stdio: 'pipe' });
|
|
705
|
-
(0, child_process_1.execSync)('git add .', { cwd: resolvedDir, stdio: 'pipe' });
|
|
706
|
-
await new Promise(resolve => setTimeout(resolve, 100));
|
|
707
|
-
(0, child_process_1.execSync)('git commit -m "Initial commit"', { cwd: resolvedDir, stdio: 'pipe' });
|
|
708
|
-
(0, logger_1.logVerbose)(`✅ Initial commit created`);
|
|
709
|
-
}
|
|
710
|
-
catch (error) {
|
|
711
|
-
(0, logger_1.logVerbose)(`❌ Error initializing git: ${error}`);
|
|
712
|
-
}
|
|
713
|
-
const runflowPath = path.join(dir, '.runflow');
|
|
714
|
-
if (fs.existsSync(runflowPath)) {
|
|
715
|
-
(0, logger_1.logVerbose)(`✅ .runflow file provided by API for deploy operations`);
|
|
716
|
-
}
|
|
717
|
-
else {
|
|
718
|
-
(0, logger_1.logVerbose)(`⚠️ No .runflow file found - deploy may not work`);
|
|
719
|
-
}
|
|
720
|
-
(0, logger_1.logSuccess)(`Repository cloned to ${dir}/`);
|
|
721
|
-
console.log(chalk_1.default.cyan.bold('\n🚀 Next Steps:'));
|
|
722
|
-
console.log(chalk_1.default.gray('1.'), chalk_1.default.white(`cd ${dir}`));
|
|
723
|
-
console.log(chalk_1.default.gray('2.'), chalk_1.default.white('npm install'));
|
|
724
|
-
console.log(chalk_1.default.gray('3.'), chalk_1.default.white('rf test'), chalk_1.default.gray('# Start test interface'));
|
|
725
|
-
console.log(chalk_1.default.gray('4.'), chalk_1.default.white('rf deploy'), chalk_1.default.gray('# Deploy changes back'));
|
|
726
|
-
console.log(chalk_1.default.cyan.bold('\n💡 Quick Start:'));
|
|
727
|
-
console.log(chalk_1.default.gray(`cd ${dir} && npm install && rf test`));
|
|
221
|
+
await agents_service_1.AgentsService.cloneAgent(agentId, agentName, apiClient);
|
|
728
222
|
break;
|
|
729
223
|
}
|
|
730
224
|
case 'pull': {
|
|
731
|
-
const
|
|
732
|
-
if (!
|
|
225
|
+
const detectedAgent = await file_service_1.FileService.detectAgentFromCurrentDirectory();
|
|
226
|
+
if (!detectedAgent) {
|
|
733
227
|
(0, logger_1.logError)(config_1.ERROR_MESSAGES.AGENT_NOT_DETECTED);
|
|
734
228
|
return;
|
|
735
229
|
}
|
|
736
|
-
|
|
737
|
-
if (hasChanges) {
|
|
738
|
-
(0, logger_1.logVerbose)('Local changes detected in repository');
|
|
739
|
-
const { confirm } = await inquirer.prompt([
|
|
740
|
-
{
|
|
741
|
-
type: 'confirm',
|
|
742
|
-
name: 'confirm',
|
|
743
|
-
message: '⚠️ You have local changes. Pull will overwrite them. Continue?',
|
|
744
|
-
default: false
|
|
745
|
-
}
|
|
746
|
-
]);
|
|
747
|
-
if (!confirm) {
|
|
748
|
-
(0, logger_1.logSuccess)('Pull cancelled');
|
|
749
|
-
return;
|
|
750
|
-
}
|
|
751
|
-
}
|
|
752
|
-
(0, logger_1.logVerbose)(`Pulling latest changes for agent ${detectedAgentId}...`);
|
|
753
|
-
const res = await apiClient.get(`/agents/${detectedAgentId}/clone`);
|
|
754
|
-
const tree = res.data;
|
|
755
|
-
(0, logger_1.logVerbose)(`Received ${tree.length} items from API`);
|
|
756
|
-
const currentFiles = fs.readdirSync(process.cwd(), { withFileTypes: true });
|
|
757
|
-
for (const file of currentFiles) {
|
|
758
|
-
if (file.name === '.git' || file.name === '.runflow') {
|
|
759
|
-
continue;
|
|
760
|
-
}
|
|
761
|
-
const filePath = path.join(process.cwd(), file.name);
|
|
762
|
-
if (file.isDirectory()) {
|
|
763
|
-
fs.rmSync(filePath, { recursive: true, force: true });
|
|
764
|
-
}
|
|
765
|
-
else {
|
|
766
|
-
fs.unlinkSync(filePath);
|
|
767
|
-
}
|
|
768
|
-
}
|
|
769
|
-
for (const item of tree) {
|
|
770
|
-
if (SENSITIVE_FILES.includes(item.path) || item.path.startsWith('.git/')) {
|
|
771
|
-
(0, logger_1.logVerbose)(`Skipping: ${item.path}`);
|
|
772
|
-
continue;
|
|
773
|
-
}
|
|
774
|
-
(0, logger_1.logVerbose)(`Writing: ${item.path} (type: ${item.type})`);
|
|
775
|
-
const filePath = path.join(process.cwd(), item.path);
|
|
776
|
-
if (item.type === 'blob') {
|
|
777
|
-
const dirPath = path.dirname(filePath);
|
|
778
|
-
fs.mkdirSync(dirPath, { recursive: true });
|
|
779
|
-
fs.writeFileSync(filePath, item.content ?? '', 'utf8');
|
|
780
|
-
}
|
|
781
|
-
else if (item.type === 'tree') {
|
|
782
|
-
fs.mkdirSync(filePath, { recursive: true });
|
|
783
|
-
}
|
|
784
|
-
}
|
|
785
|
-
try {
|
|
786
|
-
(0, logger_1.logVerbose)(`Creating commit for pulled changes...`);
|
|
787
|
-
(0, child_process_1.execSync)('git add .', { cwd: process.cwd(), stdio: 'pipe' });
|
|
788
|
-
const timestamp = new Date().toISOString().replace('T', ' ').split('.')[0];
|
|
789
|
-
const commitMessage = `Pull: ${timestamp}`;
|
|
790
|
-
(0, child_process_1.execSync)(`git commit -m "${commitMessage}"`, { cwd: process.cwd(), stdio: 'pipe' });
|
|
791
|
-
(0, logger_1.logVerbose)(`✅ Auto-commit created: ${commitMessage}`);
|
|
792
|
-
}
|
|
793
|
-
catch (commitError) {
|
|
794
|
-
(0, logger_1.logVerbose)(`⚠️ Could not create auto-commit: ${commitError}`);
|
|
795
|
-
}
|
|
796
|
-
(0, logger_1.logSuccess)('Latest changes pulled successfully');
|
|
230
|
+
await agents_service_1.AgentsService.pullAgent(detectedAgent.agentId, detectedAgent.agentName, apiClient);
|
|
797
231
|
break;
|
|
798
232
|
}
|
|
799
233
|
case 'duplicate': {
|
|
@@ -807,12 +241,12 @@ let AgentsCommand = class AgentsCommand extends nest_commander_1.CommandRunner {
|
|
|
807
241
|
break;
|
|
808
242
|
}
|
|
809
243
|
case 'deploy': {
|
|
810
|
-
const
|
|
811
|
-
if (!
|
|
244
|
+
const detectedAgent = await file_service_1.FileService.detectAgentFromCurrentDirectory();
|
|
245
|
+
if (!detectedAgent) {
|
|
812
246
|
(0, logger_1.logError)(config_1.ERROR_MESSAGES.AGENT_NOT_DETECTED);
|
|
813
247
|
return;
|
|
814
248
|
}
|
|
815
|
-
await
|
|
249
|
+
await agents_service_1.AgentsService.performDeploy(detectedAgent.agentId, apiClient, data, detectedAgent.agentName);
|
|
816
250
|
break;
|
|
817
251
|
}
|
|
818
252
|
}
|