@myvillage/cli 1.3.0 → 1.5.1
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 +14 -199
- package/package.json +11 -6
- package/src/agent-runtime/context.js +99 -0
- package/src/agent-runtime/daemon-entry.js +66 -0
- package/src/agent-runtime/daemon.js +65 -0
- package/src/agent-runtime/loop.js +281 -0
- package/src/agent-runtime/mcp-client.js +93 -0
- package/src/agent-runtime/scheduler.js +53 -0
- package/src/commands/agent-local.js +624 -0
- package/src/commands/agent.js +274 -42
- package/src/commands/bizreqs.js +965 -0
- package/src/commands/comment.js +5 -4
- package/src/commands/community.js +13 -12
- package/src/commands/create-app.js +253 -0
- package/src/commands/create-game.js +9 -8
- package/src/commands/deploy.js +101 -23
- package/src/commands/feed.js +4 -3
- package/src/commands/login.js +164 -76
- package/src/commands/logout.js +45 -7
- package/src/commands/post.js +14 -13
- package/src/commands/profile.js +4 -3
- package/src/commands/search.js +3 -2
- package/src/commands/soulprint.js +1379 -0
- package/src/commands/status.js +64 -28
- package/src/commands/vote.js +46 -18
- package/src/index.js +244 -1
- package/src/utils/agent-scaffolder.js +165 -0
- package/src/utils/api.js +135 -14
- package/src/utils/app-templates.js +2983 -0
- package/src/utils/brand.js +107 -0
- package/src/utils/config.js +17 -1
- package/src/utils/formatters.js +351 -18
- package/src/utils/local-agent.js +168 -0
- package/src/utils/soulprint-api.js +136 -0
- package/src/utils/soulprint-workspace.js +158 -0
package/src/commands/agent.js
CHANGED
|
@@ -1,5 +1,6 @@
|
|
|
1
1
|
import chalk from 'chalk';
|
|
2
2
|
import ora from 'ora';
|
|
3
|
+
import { villageSpinner, brand } from '../utils/brand.js';
|
|
3
4
|
import inquirer from 'inquirer';
|
|
4
5
|
import { isAuthenticated } from '../utils/auth.js';
|
|
5
6
|
import {
|
|
@@ -9,8 +10,11 @@ import {
|
|
|
9
10
|
deleteAgent as apiDeleteAgent,
|
|
10
11
|
agentJoinCommunity as apiAgentJoinCommunity,
|
|
11
12
|
agentLeaveCommunity as apiAgentLeaveCommunity,
|
|
13
|
+
runAgent as apiRunAgent,
|
|
12
14
|
} from '../utils/api.js';
|
|
13
|
-
import { formatAgentCard, formatAgentList } from '../utils/formatters.js';
|
|
15
|
+
import { formatAgentCard, formatAgentList, formatLocalAgentList } from '../utils/formatters.js';
|
|
16
|
+
import { listLocalAgents, agentExists as localAgentExists, isDaemonRunning } from '../utils/local-agent.js';
|
|
17
|
+
import { agentCreateLocalCommand, agentEditLocalCommand, agentDeleteLocalCommand } from './agent-local.js';
|
|
14
18
|
|
|
15
19
|
// ── Handle-to-ID Resolution ──────────────────────────
|
|
16
20
|
|
|
@@ -33,18 +37,32 @@ export async function agentCommand(handle) {
|
|
|
33
37
|
return agentViewCommand(handle);
|
|
34
38
|
}
|
|
35
39
|
|
|
36
|
-
// No args: list
|
|
37
|
-
const
|
|
40
|
+
// No args: list local + remote agents
|
|
41
|
+
const localAgents = listLocalAgents();
|
|
42
|
+
if (localAgents.length > 0) {
|
|
43
|
+
formatLocalAgentList(localAgents);
|
|
44
|
+
}
|
|
45
|
+
|
|
46
|
+
const spinner = villageSpinner('Loading remote agents...').start();
|
|
38
47
|
|
|
39
48
|
try {
|
|
40
49
|
const result = await listMyAgents();
|
|
41
50
|
spinner.stop();
|
|
42
51
|
|
|
43
52
|
const agents = result.data || result;
|
|
44
|
-
|
|
53
|
+
const remoteAgents = Array.isArray(agents) ? agents : [];
|
|
54
|
+
|
|
55
|
+
if (remoteAgents.length > 0) {
|
|
56
|
+
if (localAgents.length > 0) {
|
|
57
|
+
console.log(` ${chalk.bold('Remote Agents')}\n`);
|
|
58
|
+
}
|
|
59
|
+
formatAgentList(remoteAgents);
|
|
60
|
+
} else if (localAgents.length === 0) {
|
|
61
|
+
console.log(brand.teal('\n No agents found. Create one with: myvillage agent create\n'));
|
|
62
|
+
}
|
|
45
63
|
} catch (err) {
|
|
46
64
|
const message = err.response?.data?.error || err.response?.data?.message || err.message;
|
|
47
|
-
spinner.fail(`Failed to load agents: ${message}`);
|
|
65
|
+
spinner.fail(`Failed to load remote agents: ${message}`);
|
|
48
66
|
}
|
|
49
67
|
}
|
|
50
68
|
|
|
@@ -55,6 +73,22 @@ export async function agentCreateCommand() {
|
|
|
55
73
|
}
|
|
56
74
|
|
|
57
75
|
try {
|
|
76
|
+
// Gate question: local or external?
|
|
77
|
+
const { agentType } = await inquirer.prompt([{
|
|
78
|
+
type: 'list',
|
|
79
|
+
name: 'agentType',
|
|
80
|
+
message: 'What kind of agent do you want to create?',
|
|
81
|
+
choices: [
|
|
82
|
+
{ name: 'Local Agent \u2014 Runs on your machine with AI + local tools', value: 'local' },
|
|
83
|
+
{ name: 'External Agent \u2014 Runs on n8n or a custom webhook', value: 'external' },
|
|
84
|
+
],
|
|
85
|
+
}]);
|
|
86
|
+
|
|
87
|
+
if (agentType === 'local') {
|
|
88
|
+
return agentCreateLocalCommand();
|
|
89
|
+
}
|
|
90
|
+
|
|
91
|
+
// External agent flow (existing behavior)
|
|
58
92
|
const answers = await inquirer.prompt([
|
|
59
93
|
{
|
|
60
94
|
type: 'input',
|
|
@@ -76,20 +110,73 @@ export async function agentCreateCommand() {
|
|
|
76
110
|
message: 'Display name:',
|
|
77
111
|
validate: (input) => input.trim().length > 0 || 'Display name is required',
|
|
78
112
|
},
|
|
113
|
+
{
|
|
114
|
+
type: 'list',
|
|
115
|
+
name: 'agentCategory',
|
|
116
|
+
message: 'Agent category:',
|
|
117
|
+
choices: [
|
|
118
|
+
{ name: 'Network — Social participant (posts, comments, votes)', value: 'NETWORK' },
|
|
119
|
+
{ name: 'Workflow — n8n automation (webhooks, schedules)', value: 'WORKFLOW' },
|
|
120
|
+
{ name: 'Hybrid — Both network and workflow', value: 'HYBRID' },
|
|
121
|
+
],
|
|
122
|
+
default: 'NETWORK',
|
|
123
|
+
},
|
|
124
|
+
// Network fields (NETWORK and HYBRID)
|
|
79
125
|
{
|
|
80
126
|
type: 'input',
|
|
81
127
|
name: 'bio',
|
|
82
128
|
message: 'Bio (short description):',
|
|
129
|
+
when: (a) => a.agentCategory !== 'WORKFLOW',
|
|
83
130
|
},
|
|
84
131
|
{
|
|
85
132
|
type: 'input',
|
|
86
133
|
name: 'interests',
|
|
87
134
|
message: 'Interests (comma-separated):',
|
|
135
|
+
when: (a) => a.agentCategory !== 'WORKFLOW',
|
|
88
136
|
},
|
|
89
137
|
{
|
|
90
138
|
type: 'input',
|
|
91
139
|
name: 'personality',
|
|
92
140
|
message: 'Personality (how should this agent behave?):',
|
|
141
|
+
when: (a) => a.agentCategory !== 'WORKFLOW',
|
|
142
|
+
},
|
|
143
|
+
// Workflow fields (WORKFLOW and HYBRID)
|
|
144
|
+
{
|
|
145
|
+
type: 'input',
|
|
146
|
+
name: 'endpointUrl',
|
|
147
|
+
message: 'n8n Webhook URL:',
|
|
148
|
+
when: (a) => a.agentCategory !== 'NETWORK',
|
|
149
|
+
validate: (input) => {
|
|
150
|
+
if (!input.trim()) return 'Endpoint URL is required for workflow agents';
|
|
151
|
+
if (!input.startsWith('http')) return 'Must be a valid HTTP/HTTPS URL';
|
|
152
|
+
return true;
|
|
153
|
+
},
|
|
154
|
+
},
|
|
155
|
+
{
|
|
156
|
+
type: 'list',
|
|
157
|
+
name: 'workflowType',
|
|
158
|
+
message: 'Workflow type:',
|
|
159
|
+
choices: [
|
|
160
|
+
{ name: 'Manual — Run on-demand', value: 'MANUAL' },
|
|
161
|
+
{ name: 'Triggered — Run in response to events', value: 'TRIGGERED' },
|
|
162
|
+
{ name: 'Scheduled — Run on a cron schedule', value: 'SCHEDULED' },
|
|
163
|
+
],
|
|
164
|
+
default: 'MANUAL',
|
|
165
|
+
when: (a) => a.agentCategory !== 'NETWORK',
|
|
166
|
+
},
|
|
167
|
+
{
|
|
168
|
+
type: 'input',
|
|
169
|
+
name: 'schedule',
|
|
170
|
+
message: 'Schedule (e.g., "Every Tuesday at 9am"):',
|
|
171
|
+
when: (a) => a.workflowType === 'SCHEDULED',
|
|
172
|
+
validate: (input) => input.trim().length > 0 || 'Schedule is required for scheduled agents',
|
|
173
|
+
},
|
|
174
|
+
{
|
|
175
|
+
type: 'confirm',
|
|
176
|
+
name: 'inputRequired',
|
|
177
|
+
message: 'Does this workflow require user input to run?',
|
|
178
|
+
default: false,
|
|
179
|
+
when: (a) => a.agentCategory !== 'NETWORK',
|
|
93
180
|
},
|
|
94
181
|
{
|
|
95
182
|
type: 'confirm',
|
|
@@ -100,26 +187,39 @@ export async function agentCreateCommand() {
|
|
|
100
187
|
]);
|
|
101
188
|
|
|
102
189
|
if (!answers.confirm) {
|
|
103
|
-
console.log(
|
|
190
|
+
console.log(brand.teal(' Cancelled.\n'));
|
|
104
191
|
return;
|
|
105
192
|
}
|
|
106
193
|
|
|
107
|
-
const spinner =
|
|
194
|
+
const spinner = villageSpinner('Creating agent...').start();
|
|
108
195
|
|
|
109
196
|
const data = {
|
|
110
197
|
handle: answers.handle,
|
|
111
198
|
displayName: answers.displayName.trim(),
|
|
112
|
-
|
|
113
|
-
interests: answers.interests ? answers.interests.split(',').map(t => t.trim()).filter(Boolean) : [],
|
|
114
|
-
personality: answers.personality?.trim() || '',
|
|
199
|
+
agentCategory: answers.agentCategory,
|
|
115
200
|
};
|
|
116
201
|
|
|
202
|
+
// Network fields
|
|
203
|
+
if (answers.agentCategory !== 'WORKFLOW') {
|
|
204
|
+
data.bio = answers.bio?.trim() || '';
|
|
205
|
+
data.interests = answers.interests ? answers.interests.split(',').map(t => t.trim()).filter(Boolean) : [];
|
|
206
|
+
data.personality = answers.personality?.trim() || '';
|
|
207
|
+
}
|
|
208
|
+
|
|
209
|
+
// Workflow fields
|
|
210
|
+
if (answers.agentCategory !== 'NETWORK') {
|
|
211
|
+
data.endpointUrl = answers.endpointUrl?.trim();
|
|
212
|
+
data.workflowType = answers.workflowType;
|
|
213
|
+
if (answers.schedule) data.schedule = answers.schedule.trim();
|
|
214
|
+
data.inputRequired = answers.inputRequired || false;
|
|
215
|
+
}
|
|
216
|
+
|
|
117
217
|
const result = await apiCreateAgent(data);
|
|
118
218
|
spinner.succeed('Agent created!');
|
|
119
219
|
|
|
120
220
|
const agent = result.data || result;
|
|
121
|
-
console.log(
|
|
122
|
-
console.log(
|
|
221
|
+
console.log(brand.green(` \u2713 Agent @${agent.handle || data.handle} is ready!`));
|
|
222
|
+
console.log(brand.teal(` ID: ${agent.id}\n`));
|
|
123
223
|
} catch (err) {
|
|
124
224
|
if (err.isTtyError) {
|
|
125
225
|
console.log(chalk.red(' \u2717 Prompts cannot be rendered in this environment.\n'));
|
|
@@ -136,7 +236,7 @@ export async function agentViewCommand(handle) {
|
|
|
136
236
|
return;
|
|
137
237
|
}
|
|
138
238
|
|
|
139
|
-
const spinner =
|
|
239
|
+
const spinner = villageSpinner(`Loading agent @${handle}...`).start();
|
|
140
240
|
|
|
141
241
|
try {
|
|
142
242
|
const agent = await resolveAgentHandle(handle);
|
|
@@ -160,7 +260,12 @@ export async function agentEditCommand(handle) {
|
|
|
160
260
|
return;
|
|
161
261
|
}
|
|
162
262
|
|
|
163
|
-
|
|
263
|
+
// Check if this is a local agent first
|
|
264
|
+
if (localAgentExists(handle)) {
|
|
265
|
+
return agentEditLocalCommand(handle);
|
|
266
|
+
}
|
|
267
|
+
|
|
268
|
+
const spinner = villageSpinner(`Loading agent @${handle}...`).start();
|
|
164
269
|
|
|
165
270
|
try {
|
|
166
271
|
const agent = await resolveAgentHandle(handle);
|
|
@@ -172,7 +277,13 @@ export async function agentEditCommand(handle) {
|
|
|
172
277
|
|
|
173
278
|
spinner.stop();
|
|
174
279
|
|
|
175
|
-
const
|
|
280
|
+
const category = agent.agentCategory || 'NETWORK';
|
|
281
|
+
const categoryLabel = category === 'NETWORK' ? brand.gold('[NETWORK]')
|
|
282
|
+
: category === 'WORKFLOW' ? chalk.yellow('[WORKFLOW]')
|
|
283
|
+
: chalk.magenta('[HYBRID]');
|
|
284
|
+
console.log(brand.teal(` Category: ${categoryLabel}\n`));
|
|
285
|
+
|
|
286
|
+
const prompts = [
|
|
176
287
|
{
|
|
177
288
|
type: 'input',
|
|
178
289
|
name: 'displayName',
|
|
@@ -180,35 +291,94 @@ export async function agentEditCommand(handle) {
|
|
|
180
291
|
default: agent.displayName,
|
|
181
292
|
validate: (input) => input.trim().length > 0 || 'Display name is required',
|
|
182
293
|
},
|
|
183
|
-
|
|
184
|
-
|
|
185
|
-
|
|
186
|
-
|
|
187
|
-
|
|
188
|
-
|
|
189
|
-
|
|
190
|
-
|
|
191
|
-
|
|
192
|
-
|
|
193
|
-
|
|
194
|
-
|
|
195
|
-
|
|
196
|
-
|
|
197
|
-
|
|
198
|
-
|
|
199
|
-
|
|
200
|
-
|
|
201
|
-
|
|
294
|
+
];
|
|
295
|
+
|
|
296
|
+
// Network fields (NETWORK and HYBRID)
|
|
297
|
+
if (category !== 'WORKFLOW') {
|
|
298
|
+
prompts.push(
|
|
299
|
+
{
|
|
300
|
+
type: 'input',
|
|
301
|
+
name: 'bio',
|
|
302
|
+
message: 'Bio:',
|
|
303
|
+
default: agent.bio || '',
|
|
304
|
+
},
|
|
305
|
+
{
|
|
306
|
+
type: 'input',
|
|
307
|
+
name: 'interests',
|
|
308
|
+
message: 'Interests (comma-separated):',
|
|
309
|
+
default: agent.interests?.join(', ') || '',
|
|
310
|
+
},
|
|
311
|
+
{
|
|
312
|
+
type: 'input',
|
|
313
|
+
name: 'personality',
|
|
314
|
+
message: 'Personality:',
|
|
315
|
+
default: agent.personality || '',
|
|
316
|
+
},
|
|
317
|
+
);
|
|
318
|
+
}
|
|
319
|
+
|
|
320
|
+
// Workflow fields (WORKFLOW and HYBRID)
|
|
321
|
+
if (category !== 'NETWORK') {
|
|
322
|
+
prompts.push(
|
|
323
|
+
{
|
|
324
|
+
type: 'input',
|
|
325
|
+
name: 'endpointUrl',
|
|
326
|
+
message: 'n8n Webhook URL:',
|
|
327
|
+
default: agent.endpointUrl || '',
|
|
328
|
+
validate: (input) => {
|
|
329
|
+
if (!input.trim()) return 'Endpoint URL is required for workflow agents';
|
|
330
|
+
if (!input.startsWith('http')) return 'Must be a valid HTTP/HTTPS URL';
|
|
331
|
+
return true;
|
|
332
|
+
},
|
|
333
|
+
},
|
|
334
|
+
{
|
|
335
|
+
type: 'list',
|
|
336
|
+
name: 'workflowType',
|
|
337
|
+
message: 'Workflow type:',
|
|
338
|
+
choices: [
|
|
339
|
+
{ name: 'Manual — Run on-demand', value: 'MANUAL' },
|
|
340
|
+
{ name: 'Triggered — Run in response to events', value: 'TRIGGERED' },
|
|
341
|
+
{ name: 'Scheduled — Run on a cron schedule', value: 'SCHEDULED' },
|
|
342
|
+
],
|
|
343
|
+
default: agent.workflowType || 'MANUAL',
|
|
344
|
+
},
|
|
345
|
+
{
|
|
346
|
+
type: 'input',
|
|
347
|
+
name: 'schedule',
|
|
348
|
+
message: 'Schedule (e.g., "Every Tuesday at 9am"):',
|
|
349
|
+
default: agent.schedule || '',
|
|
350
|
+
when: (a) => a.workflowType === 'SCHEDULED',
|
|
351
|
+
},
|
|
352
|
+
{
|
|
353
|
+
type: 'confirm',
|
|
354
|
+
name: 'inputRequired',
|
|
355
|
+
message: 'Requires user input to run?',
|
|
356
|
+
default: agent.inputRequired || false,
|
|
357
|
+
},
|
|
358
|
+
);
|
|
359
|
+
}
|
|
360
|
+
|
|
361
|
+
const answers = await inquirer.prompt(prompts);
|
|
202
362
|
|
|
203
|
-
const saveSpinner =
|
|
363
|
+
const saveSpinner = villageSpinner('Saving changes...').start();
|
|
204
364
|
|
|
205
365
|
const data = {
|
|
206
366
|
displayName: answers.displayName.trim(),
|
|
207
|
-
bio: answers.bio?.trim() || '',
|
|
208
|
-
interests: answers.interests ? answers.interests.split(',').map(t => t.trim()).filter(Boolean) : [],
|
|
209
|
-
personality: answers.personality?.trim() || '',
|
|
210
367
|
};
|
|
211
368
|
|
|
369
|
+
if (category !== 'WORKFLOW') {
|
|
370
|
+
data.bio = answers.bio?.trim() || '';
|
|
371
|
+
data.interests = answers.interests ? answers.interests.split(',').map(t => t.trim()).filter(Boolean) : [];
|
|
372
|
+
data.personality = answers.personality?.trim() || '';
|
|
373
|
+
}
|
|
374
|
+
|
|
375
|
+
if (category !== 'NETWORK') {
|
|
376
|
+
data.endpointUrl = answers.endpointUrl?.trim();
|
|
377
|
+
data.workflowType = answers.workflowType;
|
|
378
|
+
if (answers.schedule) data.schedule = answers.schedule.trim();
|
|
379
|
+
data.inputRequired = answers.inputRequired || false;
|
|
380
|
+
}
|
|
381
|
+
|
|
212
382
|
await apiUpdateAgent(agent.id, data);
|
|
213
383
|
saveSpinner.succeed(`Agent @${handle} updated!`);
|
|
214
384
|
} catch (err) {
|
|
@@ -227,6 +397,11 @@ export async function agentDeleteCommand(handle) {
|
|
|
227
397
|
return;
|
|
228
398
|
}
|
|
229
399
|
|
|
400
|
+
// Check if this is a local agent first
|
|
401
|
+
if (localAgentExists(handle)) {
|
|
402
|
+
return agentDeleteLocalCommand(handle);
|
|
403
|
+
}
|
|
404
|
+
|
|
230
405
|
try {
|
|
231
406
|
const agent = await resolveAgentHandle(handle);
|
|
232
407
|
|
|
@@ -245,11 +420,11 @@ export async function agentDeleteCommand(handle) {
|
|
|
245
420
|
]);
|
|
246
421
|
|
|
247
422
|
if (!confirm) {
|
|
248
|
-
console.log(
|
|
423
|
+
console.log(brand.teal(' Cancelled.\n'));
|
|
249
424
|
return;
|
|
250
425
|
}
|
|
251
426
|
|
|
252
|
-
const spinner =
|
|
427
|
+
const spinner = villageSpinner('Deactivating agent...').start();
|
|
253
428
|
|
|
254
429
|
await apiDeleteAgent(agent.id);
|
|
255
430
|
spinner.succeed(`Agent @${handle} deactivated.`);
|
|
@@ -265,7 +440,7 @@ export async function agentJoinCommand(handle, slug) {
|
|
|
265
440
|
return;
|
|
266
441
|
}
|
|
267
442
|
|
|
268
|
-
const spinner =
|
|
443
|
+
const spinner = villageSpinner(`Joining r/${slug} as @${handle}...`).start();
|
|
269
444
|
|
|
270
445
|
try {
|
|
271
446
|
const agent = await resolveAgentHandle(handle);
|
|
@@ -289,7 +464,7 @@ export async function agentLeaveCommand(handle, slug) {
|
|
|
289
464
|
return;
|
|
290
465
|
}
|
|
291
466
|
|
|
292
|
-
const spinner =
|
|
467
|
+
const spinner = villageSpinner(`Leaving r/${slug} as @${handle}...`).start();
|
|
293
468
|
|
|
294
469
|
try {
|
|
295
470
|
const agent = await resolveAgentHandle(handle);
|
|
@@ -306,3 +481,60 @@ export async function agentLeaveCommand(handle, slug) {
|
|
|
306
481
|
spinner.fail(`Failed to leave community: ${message}`);
|
|
307
482
|
}
|
|
308
483
|
}
|
|
484
|
+
|
|
485
|
+
export async function agentRunCommand(handle, options = {}) {
|
|
486
|
+
if (!isAuthenticated()) {
|
|
487
|
+
console.log(chalk.red(' \u2717 Authentication required. Run \'myvillage login\' first.'));
|
|
488
|
+
return;
|
|
489
|
+
}
|
|
490
|
+
|
|
491
|
+
try {
|
|
492
|
+
const agent = await resolveAgentHandle(handle);
|
|
493
|
+
|
|
494
|
+
if (!agent) {
|
|
495
|
+
console.log(chalk.red(` \u2717 Agent @${handle} not found. Run 'myvillage agent' to see your agents.\n`));
|
|
496
|
+
return;
|
|
497
|
+
}
|
|
498
|
+
|
|
499
|
+
if (agent.agentCategory === 'NETWORK') {
|
|
500
|
+
console.log(chalk.red(` \u2717 Agent @${handle} is a NETWORK agent and cannot be run as a workflow.`));
|
|
501
|
+
console.log(brand.teal(' Only WORKFLOW or HYBRID agents can be run.\n'));
|
|
502
|
+
return;
|
|
503
|
+
}
|
|
504
|
+
|
|
505
|
+
let input = options.input || null;
|
|
506
|
+
|
|
507
|
+
if (agent.inputRequired && !input) {
|
|
508
|
+
const answers = await inquirer.prompt([
|
|
509
|
+
{
|
|
510
|
+
type: 'input',
|
|
511
|
+
name: 'input',
|
|
512
|
+
message: 'Input for the agent:',
|
|
513
|
+
validate: (val) => val.trim().length > 0 || 'Input is required for this agent',
|
|
514
|
+
},
|
|
515
|
+
]);
|
|
516
|
+
input = answers.input.trim();
|
|
517
|
+
}
|
|
518
|
+
|
|
519
|
+
const spinner = villageSpinner(`Running agent @${handle}...`).start();
|
|
520
|
+
|
|
521
|
+
const result = await apiRunAgent(agent.id, input);
|
|
522
|
+
spinner.succeed(`Agent @${handle} executed successfully!`);
|
|
523
|
+
|
|
524
|
+
const data = result.data || result;
|
|
525
|
+
if (data.result) {
|
|
526
|
+
console.log(`\n ${brand.teal('Result:')}`);
|
|
527
|
+
console.log(` ${typeof data.result === 'string' ? data.result : JSON.stringify(data.result, null, 2)}\n`);
|
|
528
|
+
}
|
|
529
|
+
if (data.lastRunAt) {
|
|
530
|
+
console.log(brand.teal(` Last run: ${new Date(data.lastRunAt).toLocaleString()}\n`));
|
|
531
|
+
}
|
|
532
|
+
} catch (err) {
|
|
533
|
+
if (err.isTtyError) {
|
|
534
|
+
console.log(chalk.red(' \u2717 Prompts cannot be rendered in this environment.\n'));
|
|
535
|
+
return;
|
|
536
|
+
}
|
|
537
|
+
const message = err.response?.data?.error || err.response?.data?.message || err.message;
|
|
538
|
+
console.log(chalk.red(` \u2717 Failed to run agent: ${message}\n`));
|
|
539
|
+
}
|
|
540
|
+
}
|