suzi-cli 0.1.13 → 0.1.14

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (60) hide show
  1. package/dist/commands/accounts.d.ts.map +1 -1
  2. package/dist/commands/accounts.js +27 -7
  3. package/dist/commands/accounts.js.map +1 -1
  4. package/dist/commands/agent.d.ts +45 -0
  5. package/dist/commands/agent.d.ts.map +1 -0
  6. package/dist/commands/agent.js +991 -0
  7. package/dist/commands/agent.js.map +1 -0
  8. package/dist/commands/debug.d.ts.map +1 -1
  9. package/dist/commands/debug.js +124 -41
  10. package/dist/commands/debug.js.map +1 -1
  11. package/dist/commands/list-actions.d.ts.map +1 -1
  12. package/dist/commands/list-actions.js +35 -4
  13. package/dist/commands/list-actions.js.map +1 -1
  14. package/dist/commands/list-triggers.d.ts.map +1 -1
  15. package/dist/commands/list-triggers.js +38 -10
  16. package/dist/commands/list-triggers.js.map +1 -1
  17. package/dist/commands/portfolio.d.ts.map +1 -1
  18. package/dist/commands/portfolio.js +113 -14
  19. package/dist/commands/portfolio.js.map +1 -1
  20. package/dist/commands/preferences.d.ts.map +1 -1
  21. package/dist/commands/preferences.js +119 -26
  22. package/dist/commands/preferences.js.map +1 -1
  23. package/dist/commands/run.d.ts +4 -0
  24. package/dist/commands/run.d.ts.map +1 -1
  25. package/dist/commands/run.js +8 -305
  26. package/dist/commands/run.js.map +1 -1
  27. package/dist/commands/transactions.d.ts.map +1 -1
  28. package/dist/commands/transactions.js +18 -4
  29. package/dist/commands/transactions.js.map +1 -1
  30. package/dist/index.js +29 -26
  31. package/dist/index.js.map +1 -1
  32. package/dist/utils/agent-picker.d.ts +16 -0
  33. package/dist/utils/agent-picker.d.ts.map +1 -0
  34. package/dist/utils/agent-picker.js +83 -0
  35. package/dist/utils/agent-picker.js.map +1 -0
  36. package/dist/utils/resolver.d.ts +35 -0
  37. package/dist/utils/resolver.d.ts.map +1 -0
  38. package/dist/utils/resolver.js +157 -0
  39. package/dist/utils/resolver.js.map +1 -0
  40. package/dist/utils/tty.d.ts +26 -0
  41. package/dist/utils/tty.d.ts.map +1 -0
  42. package/dist/utils/tty.js +50 -0
  43. package/dist/utils/tty.js.map +1 -0
  44. package/dist/utils/ui.d.ts +4 -0
  45. package/dist/utils/ui.d.ts.map +1 -1
  46. package/dist/utils/ui.js +9 -0
  47. package/dist/utils/ui.js.map +1 -1
  48. package/package.json +1 -1
  49. package/dist/commands/agents.d.ts +0 -3
  50. package/dist/commands/agents.d.ts.map +0 -1
  51. package/dist/commands/agents.js +0 -309
  52. package/dist/commands/agents.js.map +0 -1
  53. package/dist/commands/deploy.d.ts +0 -3
  54. package/dist/commands/deploy.d.ts.map +0 -1
  55. package/dist/commands/deploy.js +0 -174
  56. package/dist/commands/deploy.js.map +0 -1
  57. package/dist/commands/validate.d.ts +0 -3
  58. package/dist/commands/validate.d.ts.map +0 -1
  59. package/dist/commands/validate.js +0 -165
  60. package/dist/commands/validate.js.map +0 -1
@@ -0,0 +1,991 @@
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
+ var __importStar = (this && this.__importStar) || (function () {
19
+ var ownKeys = function(o) {
20
+ ownKeys = Object.getOwnPropertyNames || function (o) {
21
+ var ar = [];
22
+ for (var k in o) if (Object.prototype.hasOwnProperty.call(o, k)) ar[ar.length] = k;
23
+ return ar;
24
+ };
25
+ return ownKeys(o);
26
+ };
27
+ return function (mod) {
28
+ if (mod && mod.__esModule) return mod;
29
+ var result = {};
30
+ if (mod != null) for (var k = ownKeys(mod), i = 0; i < k.length; i++) if (k[i] !== "default") __createBinding(result, mod, k[i]);
31
+ __setModuleDefault(result, mod);
32
+ return result;
33
+ };
34
+ })();
35
+ var __importDefault = (this && this.__importDefault) || function (mod) {
36
+ return (mod && mod.__esModule) ? mod : { "default": mod };
37
+ };
38
+ Object.defineProperty(exports, "__esModule", { value: true });
39
+ exports.registerAgentCommand = registerAgentCommand;
40
+ exports.listAgentsCommand = listAgentsCommand;
41
+ exports.viewAgentCommand = viewAgentCommand;
42
+ exports.deployAgentCommand = deployAgentCommand;
43
+ exports.validateAgentCommand = validateAgentCommand;
44
+ exports.activateAgentCommand = activateAgentCommand;
45
+ exports.deactivateAgentCommand = deactivateAgentCommand;
46
+ exports.executeAgentCommand = executeAgentCommand;
47
+ exports.logsAgentCommand = logsAgentCommand;
48
+ exports.codeAgentCommand = codeAgentCommand;
49
+ exports.deleteAgentCommand = deleteAgentCommand;
50
+ const commander_1 = require("commander");
51
+ const chalk_1 = __importDefault(require("chalk"));
52
+ const cli_table3_1 = __importDefault(require("cli-table3"));
53
+ const inquirer_1 = __importDefault(require("inquirer"));
54
+ const fs_1 = __importDefault(require("fs"));
55
+ const path_1 = __importDefault(require("path"));
56
+ const api_1 = require("../lib/api");
57
+ const ui_1 = require("../utils/ui");
58
+ const memory_1 = require("../lib/memory");
59
+ const tty_1 = require("../utils/tty");
60
+ const agent_picker_1 = require("../utils/agent-picker");
61
+ function registerAgentCommand(program) {
62
+ const agent = program
63
+ .command('agents')
64
+ .description('Manage agents (list, view, deploy, activate, execute, logs, etc.)');
65
+ // suzi agents (default: list)
66
+ agent
67
+ .action(async (opts) => {
68
+ // Default action is list
69
+ await listAgentsCommand(opts);
70
+ });
71
+ // suzi agents list
72
+ agent
73
+ .command('list')
74
+ .description('List all agents')
75
+ .option('--json', 'Output as JSON')
76
+ .action(async (opts) => {
77
+ await listAgentsCommand(opts);
78
+ });
79
+ // suzi agents view [id]
80
+ agent
81
+ .command('view [id]')
82
+ .description('View agent details')
83
+ .option('--json', 'Output as JSON')
84
+ .action(async (id, opts) => {
85
+ await viewAgentCommand(id, opts);
86
+ });
87
+ // suzi agents deploy [file]
88
+ agent
89
+ .command('deploy [file]')
90
+ .description('Deploy an agent from a TypeScript file')
91
+ .option('-t, --title <title>', 'Agent title')
92
+ .option('-d, --description <desc>', 'Agent description')
93
+ .option('--update <agentId>', 'Update an existing agent instead of creating new')
94
+ .option('--activate', 'Activate the agent after deploying')
95
+ .option('--json', 'Output as JSON')
96
+ .action(async (file, opts) => {
97
+ await deployAgentCommand(file, opts);
98
+ });
99
+ // suzi agents validate [file]
100
+ agent
101
+ .command('validate [file]')
102
+ .description('Validate an agent TypeScript file without deploying')
103
+ .option('--json', 'Output as JSON')
104
+ .action(async (file, opts) => {
105
+ await validateAgentCommand(file, opts);
106
+ });
107
+ // suzi agents run <action>
108
+ agent
109
+ .command('run <action>')
110
+ .description('Execute an action directly (e.g. suzi agents run polymarket.get_market_price --tokenID 0x123)')
111
+ .allowUnknownOption()
112
+ .allowExcessArguments(true)
113
+ .option('--json-params <params>', 'Pass all parameters as a JSON string')
114
+ .option('--output <format>', 'Output format: pretty (default) or json', 'pretty')
115
+ .option('--dry-run', 'Preview the request payload without executing')
116
+ .action(async (action, opts) => {
117
+ // Delegate to existing run command logic
118
+ const { registerRunCommand } = await Promise.resolve().then(() => __importStar(require('./run')));
119
+ const tempProgram = new commander_1.Command();
120
+ registerRunCommand(tempProgram);
121
+ // Re-parse args for run command
122
+ const runArgs = ['node', 'suzi', 'run', action, ...process.argv.slice(process.argv.indexOf(action) + 1)];
123
+ await tempProgram.parseAsync(runArgs);
124
+ });
125
+ // suzi agents activate [id]
126
+ agent
127
+ .command('activate [id]')
128
+ .description('Activate an agent')
129
+ .option('--json', 'Output as JSON')
130
+ .action(async (id, opts) => {
131
+ await activateAgentCommand(id, opts);
132
+ });
133
+ // suzi agents deactivate [id]
134
+ agent
135
+ .command('deactivate [id]')
136
+ .description('Deactivate an agent (stops execution)')
137
+ .option('-f, --force', 'Skip confirmation')
138
+ .option('--json', 'Output as JSON')
139
+ .action(async (id, opts) => {
140
+ await deactivateAgentCommand(id, opts);
141
+ });
142
+ // suzi agents execute [id]
143
+ agent
144
+ .command('execute [id] [trigger]')
145
+ .description('Manually execute an agent trigger')
146
+ .option('--json', 'Output as JSON')
147
+ .action(async (id, trigger, opts) => {
148
+ await executeAgentCommand(id, trigger, opts);
149
+ });
150
+ // suzi agents logs [id]
151
+ agent
152
+ .command('logs [id]')
153
+ .description('View agent logs')
154
+ .option('-n, --limit <n>', 'Number of log entries', '20')
155
+ .option('--level <level>', 'Filter by level (info|warn|error|debug)')
156
+ .option('--json', 'Output as JSON')
157
+ .action(async (id, opts) => {
158
+ await logsAgentCommand(id, opts);
159
+ });
160
+ // suzi agents code [id]
161
+ agent
162
+ .command('code [id]')
163
+ .description('View agent source code')
164
+ .option('--json', 'Output as JSON')
165
+ .action(async (id, opts) => {
166
+ await codeAgentCommand(id, opts);
167
+ });
168
+ // suzi agents delete [id]
169
+ agent
170
+ .command('delete [id]')
171
+ .description('Delete an agent')
172
+ .option('-f, --force', 'Skip confirmation')
173
+ .option('--json', 'Output as JSON')
174
+ .action(async (id, opts) => {
175
+ await deleteAgentCommand(id, opts);
176
+ });
177
+ }
178
+ // ============================================================================
179
+ // Command Implementations
180
+ // ============================================================================
181
+ async function listAgentsCommand(opts) {
182
+ if (!(0, ui_1.requireAuth)())
183
+ return;
184
+ const jsonMode = opts?.json || false;
185
+ const spinner = (0, tty_1.createSpinner)('Loading agents...', jsonMode);
186
+ spinner?.start();
187
+ const resp = await (0, api_1.get)('/api/agent?limit=50');
188
+ if (!resp.ok) {
189
+ spinner?.fail();
190
+ const msg = `Failed to load agents: ${resp.data?.error || 'Unknown error'}`;
191
+ if (jsonMode) {
192
+ (0, tty_1.outputJson)({ success: false, error: msg });
193
+ }
194
+ else {
195
+ (0, ui_1.error)(msg);
196
+ }
197
+ return;
198
+ }
199
+ spinner?.stop();
200
+ const agentList = resp.data.agents || [];
201
+ if (jsonMode) {
202
+ (0, tty_1.outputJson)({ success: true, data: { agents: agentList, count: agentList.length } });
203
+ return;
204
+ }
205
+ if (agentList.length === 0) {
206
+ (0, ui_1.header)('Agents');
207
+ console.log();
208
+ (0, ui_1.info)('No agents found. Create one with `suzi agents deploy <file>`.');
209
+ return;
210
+ }
211
+ (0, ui_1.header)(`Agents (${agentList.length})`);
212
+ console.log();
213
+ const table = new cli_table3_1.default({
214
+ head: [
215
+ chalk_1.default.gray('#'),
216
+ chalk_1.default.gray('Name'),
217
+ chalk_1.default.gray('Status'),
218
+ chalk_1.default.gray('ID'),
219
+ chalk_1.default.gray('Created'),
220
+ ],
221
+ style: { head: [], border: ['gray'] },
222
+ });
223
+ for (let i = 0; i < agentList.length; i++) {
224
+ const agent = agentList[i];
225
+ table.push([
226
+ ui_1.colors.muted(String(i + 1)),
227
+ chalk_1.default.bold(agent.title || 'Untitled'),
228
+ (0, ui_1.statusBadge)(agent.status),
229
+ agent.id,
230
+ ui_1.colors.muted(new Date(agent.createdAt).toLocaleDateString()),
231
+ ]);
232
+ }
233
+ console.log(table.toString());
234
+ }
235
+ async function viewAgentCommand(idOrName, opts) {
236
+ if (!(0, ui_1.requireAuth)())
237
+ return;
238
+ const jsonMode = opts?.json || false;
239
+ const agent = await (0, agent_picker_1.fetchAndPickAgent)(idOrName, jsonMode);
240
+ if (!agent)
241
+ return;
242
+ // Fetch full details
243
+ const spinner = (0, tty_1.createSpinner)('Loading agent details...', jsonMode);
244
+ spinner?.start();
245
+ const resp = await (0, api_1.get)(`/api/agent/${agent.id}`);
246
+ if (!resp.ok) {
247
+ spinner?.fail();
248
+ const msg = `Failed to load agent: ${resp.data?.error || 'Unknown error'}`;
249
+ if (jsonMode) {
250
+ (0, tty_1.outputJson)({ success: false, error: msg });
251
+ }
252
+ else {
253
+ (0, ui_1.error)(msg);
254
+ }
255
+ return;
256
+ }
257
+ spinner?.stop();
258
+ const fullAgent = resp.data;
259
+ // Fetch resources
260
+ const resResp = await (0, api_1.get)(`/api/agent/${agent.id}/resources`);
261
+ const resources = resResp.ok ? resResp.data?.resources || [] : [];
262
+ if (jsonMode) {
263
+ (0, tty_1.outputJson)({ success: true, data: { agent: fullAgent, resources } });
264
+ return;
265
+ }
266
+ // Pretty output
267
+ (0, ui_1.header)(fullAgent.title || 'Untitled Agent');
268
+ console.log();
269
+ (0, ui_1.label)('ID', fullAgent.id);
270
+ (0, ui_1.label)('Status', (0, ui_1.statusBadge)(fullAgent.status));
271
+ (0, ui_1.label)('Description', fullAgent.description || ui_1.colors.muted('None'));
272
+ (0, ui_1.label)('Created', new Date(fullAgent.createdAt).toLocaleString());
273
+ (0, ui_1.label)('Updated', new Date(fullAgent.updatedAt).toLocaleString());
274
+ // Show spec info
275
+ if (fullAgent.spec) {
276
+ const spec = (0, ui_1.safeParseJSON)(fullAgent.spec);
277
+ console.log();
278
+ console.log(ui_1.colors.muted(' Agent Spec:'));
279
+ if (spec.meta) {
280
+ (0, ui_1.label)(' Version', spec.meta.version || 'N/A');
281
+ }
282
+ if (spec.triggers) {
283
+ const triggerNames = Object.keys(spec.triggers);
284
+ (0, ui_1.label)(' Triggers', triggerNames.join(', ') || 'None');
285
+ }
286
+ if (spec.resources) {
287
+ const resourceTypes = Object.entries(spec.resources)
288
+ .map(([key, val]) => {
289
+ const type = typeof val === 'string' ? val : (val?.type || 'unknown');
290
+ return `${key}(${type})`;
291
+ })
292
+ .join(', ');
293
+ (0, ui_1.label)(' Resources', resourceTypes || 'None');
294
+ }
295
+ }
296
+ // Show resources
297
+ if (resources.length > 0) {
298
+ console.log();
299
+ console.log(ui_1.colors.muted(' Wallet Resources:'));
300
+ for (const res of resources) {
301
+ (0, ui_1.label)(` ${res.walletType.toUpperCase()}`, res.address || 'N/A');
302
+ }
303
+ }
304
+ console.log();
305
+ (0, ui_1.divider)();
306
+ }
307
+ async function deployAgentCommand(file, opts) {
308
+ if (!(0, ui_1.requireAuth)())
309
+ return;
310
+ const jsonMode = opts?.json || false;
311
+ // Find the agent file
312
+ let filePath = file;
313
+ if (!filePath) {
314
+ // Look for common agent file patterns in current directory
315
+ const candidates = [
316
+ 'agent.ts',
317
+ 'src/agent.ts',
318
+ 'index.ts',
319
+ 'src/index.ts',
320
+ ];
321
+ for (const candidate of candidates) {
322
+ const resolved = path_1.default.resolve(process.cwd(), candidate);
323
+ if (fs_1.default.existsSync(resolved)) {
324
+ filePath = resolved;
325
+ break;
326
+ }
327
+ }
328
+ if (!filePath) {
329
+ const msg = 'No agent file found. Specify a file path.';
330
+ if (jsonMode) {
331
+ (0, tty_1.outputJson)({ success: false, error: msg });
332
+ }
333
+ else {
334
+ (0, ui_1.error)(msg);
335
+ (0, ui_1.info)('Looked for: ' + candidates.join(', '));
336
+ }
337
+ return;
338
+ }
339
+ }
340
+ const resolvedPath = path_1.default.resolve(process.cwd(), filePath);
341
+ if (!fs_1.default.existsSync(resolvedPath)) {
342
+ const msg = `File not found: ${resolvedPath}`;
343
+ if (jsonMode) {
344
+ (0, tty_1.outputJson)({ success: false, error: msg });
345
+ }
346
+ else {
347
+ (0, ui_1.error)(msg);
348
+ }
349
+ return;
350
+ }
351
+ const source = fs_1.default.readFileSync(resolvedPath, 'utf-8');
352
+ if (!source.includes('defineAgent')) {
353
+ const msg = 'File does not appear to be a Suzi agent (missing defineAgent).';
354
+ if (jsonMode) {
355
+ (0, tty_1.outputJson)({ success: false, error: msg });
356
+ }
357
+ else {
358
+ (0, ui_1.error)(msg);
359
+ (0, ui_1.info)('Agent files must export `defineAgent({...})`.');
360
+ }
361
+ return;
362
+ }
363
+ if (!jsonMode) {
364
+ (0, ui_1.header)('Deploy Agent');
365
+ console.log();
366
+ (0, ui_1.label)('File', path_1.default.relative(process.cwd(), resolvedPath));
367
+ (0, ui_1.label)('Size', `${source.length} bytes`);
368
+ console.log();
369
+ }
370
+ // Determine title
371
+ let title = opts?.title;
372
+ if (!title && !opts?.update && !jsonMode && (0, tty_1.shouldUseInteractive)()) {
373
+ // Try to extract from source
374
+ const metaMatch = source.match(/name:\s*['"]([^'"]+)['"]/);
375
+ if (metaMatch) {
376
+ title = metaMatch[1];
377
+ }
378
+ else {
379
+ const answers = await inquirer_1.default.prompt([
380
+ {
381
+ type: 'input',
382
+ name: 'title',
383
+ message: 'Agent title:',
384
+ default: path_1.default.basename(resolvedPath, path_1.default.extname(resolvedPath)),
385
+ },
386
+ ]);
387
+ title = answers.title;
388
+ }
389
+ }
390
+ const spinner = (0, tty_1.createSpinner)('Deploying agent...', jsonMode);
391
+ spinner?.start();
392
+ try {
393
+ let resp;
394
+ if (opts?.update) {
395
+ // Update existing agent
396
+ if (spinner)
397
+ spinner.text = 'Updating agent...';
398
+ resp = await (0, api_1.put)(`/api/agent/${opts.update}`, {
399
+ code: source,
400
+ ...(title ? { title } : {}),
401
+ ...(opts?.description ? { description: opts.description } : {}),
402
+ });
403
+ }
404
+ else {
405
+ // Create new agent
406
+ if (spinner)
407
+ spinner.text = 'Creating agent...';
408
+ resp = await (0, api_1.post)('/api/agent', {
409
+ code: source,
410
+ title: title || 'CLI Agent',
411
+ ...(opts?.description ? { description: opts.description } : {}),
412
+ });
413
+ }
414
+ if (!resp.ok) {
415
+ spinner?.fail();
416
+ const errorMsg = resp.data?.error || resp.data?.message || 'Unknown error';
417
+ const details = resp.data?.details;
418
+ if (jsonMode) {
419
+ (0, tty_1.outputJson)({ success: false, error: errorMsg, data: { details } });
420
+ }
421
+ else {
422
+ (0, ui_1.error)(`Deploy failed: ${errorMsg}`);
423
+ if (details) {
424
+ console.log(ui_1.colors.muted(` ${details}`));
425
+ }
426
+ }
427
+ (0, memory_1.appendLearning)({ category: 'error', message: `Deploy failed: ${errorMsg}`, command: 'agent deploy' });
428
+ return;
429
+ }
430
+ const agentData = resp.data;
431
+ // Activate if requested
432
+ if (opts?.activate) {
433
+ if (spinner)
434
+ spinner.text = 'Activating agent...';
435
+ const activateResp = await (0, api_1.post)(`/api/agent/${agentData.id}/activate`);
436
+ if (activateResp.ok) {
437
+ agentData.status = 'active';
438
+ }
439
+ else {
440
+ const activateError = activateResp.data?.error || activateResp.data?.message || 'Unknown error';
441
+ if (jsonMode) {
442
+ (0, tty_1.outputJson)({ success: true, data: { agent: agentData, activationError: activateError } });
443
+ }
444
+ else {
445
+ spinner?.warn(`Agent deployed but activation failed: ${activateError}`);
446
+ }
447
+ (0, memory_1.appendLearning)({ category: 'error', message: `Post-deploy activation failed: ${activateError}`, command: 'agent deploy --activate', agentId: agentData.id });
448
+ return;
449
+ }
450
+ }
451
+ spinner?.succeed(opts?.update ? 'Agent updated!' : 'Agent created!');
452
+ if (jsonMode) {
453
+ (0, tty_1.outputJson)({ success: true, data: { agent: agentData } });
454
+ return;
455
+ }
456
+ console.log();
457
+ (0, ui_1.label)('Agent ID', agentData.id);
458
+ (0, ui_1.label)('Title', agentData.title || 'Untitled');
459
+ (0, ui_1.label)('Status', (0, ui_1.statusBadge)(agentData.status));
460
+ if (agentData.spec) {
461
+ const spec = (0, ui_1.safeParseJSON)(agentData.spec);
462
+ if (spec.triggers) {
463
+ (0, ui_1.label)('Triggers', Object.keys(spec.triggers).join(', '));
464
+ }
465
+ }
466
+ // Show action validation warnings
467
+ if (agentData.actionValidation?.issues?.length > 0) {
468
+ console.log();
469
+ (0, ui_1.warn)('Action validation issues:');
470
+ for (const issue of agentData.actionValidation.issues) {
471
+ if (issue.type === 'unknown_protocol') {
472
+ console.log(` ${ui_1.colors.warning('⚠')} Unknown protocol: ${chalk_1.default.bold(issue.protocol)} ${ui_1.colors.muted(`(line ${issue.line})`)}`);
473
+ }
474
+ else if (issue.type === 'unknown_action') {
475
+ console.log(` ${ui_1.colors.warning('⚠')} Unknown action: ${chalk_1.default.bold(issue.protocol + '.' + issue.action)} ${ui_1.colors.muted(`(line ${issue.line})`)}`);
476
+ }
477
+ if (issue.suggestions && issue.suggestions.length > 0) {
478
+ console.log(` ${ui_1.colors.muted('Did you mean:')} ${issue.suggestions.join(', ')}`);
479
+ }
480
+ }
481
+ console.log();
482
+ (0, ui_1.info)('Run `suzi agents validate` for detailed validation.');
483
+ }
484
+ console.log();
485
+ (0, ui_1.divider)();
486
+ if (agentData.status === 'draft') {
487
+ (0, ui_1.info)('Activate with: `suzi agents activate ' + agentData.id + '`');
488
+ }
489
+ }
490
+ catch (err) {
491
+ spinner?.fail();
492
+ const msg = `Deploy error: ${err.message}`;
493
+ if (jsonMode) {
494
+ (0, tty_1.outputJson)({ success: false, error: msg });
495
+ }
496
+ else {
497
+ (0, ui_1.error)(msg);
498
+ }
499
+ (0, memory_1.appendLearning)({ category: 'error', message: msg, command: 'agent deploy' });
500
+ }
501
+ }
502
+ async function validateAgentCommand(file, opts) {
503
+ if (!(0, ui_1.requireAuth)())
504
+ return;
505
+ const jsonMode = opts?.json || false;
506
+ // Resolve file path
507
+ let filePath = file;
508
+ if (!filePath && !jsonMode && (0, tty_1.shouldUseInteractive)()) {
509
+ const cwd = process.cwd();
510
+ const scanDirs = [cwd, path_1.default.join(cwd, 'src')];
511
+ const agentFiles = [];
512
+ for (const dir of scanDirs) {
513
+ if (!fs_1.default.existsSync(dir))
514
+ continue;
515
+ for (const entry of fs_1.default.readdirSync(dir)) {
516
+ if (!entry.endsWith('.ts'))
517
+ continue;
518
+ const full = path_1.default.join(dir, entry);
519
+ try {
520
+ const content = fs_1.default.readFileSync(full, 'utf-8');
521
+ if (content.includes('defineAgent')) {
522
+ agentFiles.push(full);
523
+ }
524
+ }
525
+ catch {
526
+ // skip unreadable files
527
+ }
528
+ }
529
+ }
530
+ if (agentFiles.length === 0) {
531
+ (0, ui_1.error)('No agent files found in current directory.');
532
+ (0, ui_1.info)('Create a .ts file with `defineAgent({...})` or specify a path.');
533
+ return;
534
+ }
535
+ if (agentFiles.length === 1) {
536
+ filePath = agentFiles[0];
537
+ }
538
+ else {
539
+ const { selected } = await inquirer_1.default.prompt([
540
+ {
541
+ type: 'list',
542
+ name: 'selected',
543
+ message: 'Select an agent file to validate:',
544
+ choices: agentFiles.map(f => ({
545
+ name: path_1.default.relative(cwd, f),
546
+ value: f,
547
+ })),
548
+ },
549
+ ]);
550
+ filePath = selected;
551
+ }
552
+ }
553
+ if (!filePath) {
554
+ const msg = 'File path required in non-interactive mode.';
555
+ if (jsonMode) {
556
+ (0, tty_1.outputJson)({ success: false, error: msg });
557
+ }
558
+ else {
559
+ (0, ui_1.error)(msg);
560
+ }
561
+ return;
562
+ }
563
+ const resolvedPath = path_1.default.resolve(process.cwd(), filePath);
564
+ if (!fs_1.default.existsSync(resolvedPath)) {
565
+ const msg = `File not found: ${resolvedPath}`;
566
+ if (jsonMode) {
567
+ (0, tty_1.outputJson)({ success: false, error: msg });
568
+ }
569
+ else {
570
+ (0, ui_1.error)(msg);
571
+ }
572
+ return;
573
+ }
574
+ const source = fs_1.default.readFileSync(resolvedPath, 'utf-8');
575
+ if (!source.includes('defineAgent')) {
576
+ const msg = 'File does not appear to be a Suzi agent (missing defineAgent).';
577
+ if (jsonMode) {
578
+ (0, tty_1.outputJson)({ success: false, error: msg });
579
+ }
580
+ else {
581
+ (0, ui_1.error)(msg);
582
+ (0, ui_1.info)('Agent files must export `defineAgent({...})`.');
583
+ }
584
+ return;
585
+ }
586
+ if (!jsonMode) {
587
+ (0, ui_1.header)('Validate Agent');
588
+ console.log();
589
+ (0, ui_1.label)('File', path_1.default.relative(process.cwd(), resolvedPath));
590
+ (0, ui_1.label)('Size', `${Buffer.byteLength(source, 'utf8')} bytes`);
591
+ console.log();
592
+ }
593
+ const spinner = (0, tty_1.createSpinner)('Validating agent...', jsonMode);
594
+ spinner?.start();
595
+ try {
596
+ const resp = await (0, api_1.post)('/api/agent/validate', { code: source });
597
+ if (!resp.ok) {
598
+ spinner?.fail();
599
+ const errorData = resp.data;
600
+ const msg = errorData?.message || 'Compilation error';
601
+ const details = errorData?.details;
602
+ if (jsonMode) {
603
+ (0, tty_1.outputJson)({ success: false, error: msg, data: { details } });
604
+ }
605
+ else {
606
+ (0, ui_1.error)(msg);
607
+ if (details) {
608
+ console.log(ui_1.colors.muted(` ${details}`));
609
+ }
610
+ }
611
+ return;
612
+ }
613
+ const data = resp.data;
614
+ if (jsonMode) {
615
+ (0, tty_1.outputJson)({ success: true, data });
616
+ return;
617
+ }
618
+ if (data.valid) {
619
+ spinner?.succeed('Agent is valid!');
620
+ }
621
+ else {
622
+ spinner?.fail('Validation issues found');
623
+ process.exitCode = 1;
624
+ }
625
+ console.log();
626
+ // Show spec summary
627
+ if (data.spec) {
628
+ if (data.spec.meta?.name) {
629
+ (0, ui_1.label)('Name', data.spec.meta.name);
630
+ }
631
+ (0, ui_1.label)('Triggers', Object.keys(data.spec.triggers || {}).join(', ') || 'none');
632
+ if (data.spec.resources) {
633
+ (0, ui_1.label)('Resources', Object.keys(data.spec.resources).join(', '));
634
+ }
635
+ }
636
+ // Show valid action references
637
+ const refs = data.actions?.references || [];
638
+ const issues = data.actions?.issues || [];
639
+ const issueKeys = new Set(issues.flatMap((i) => {
640
+ const keys = [`${i.protocol}.${i.action || ''}`];
641
+ if (i.type === 'unknown_protocol') {
642
+ keys.push(i.protocol);
643
+ }
644
+ return keys;
645
+ }));
646
+ if (refs.length > 0) {
647
+ console.log();
648
+ console.log(ui_1.colors.highlight(' Actions used:'));
649
+ for (const ref of refs) {
650
+ const key = `${ref.protocol}.${ref.action}`;
651
+ if (!issueKeys.has(key) && !issueKeys.has(ref.protocol)) {
652
+ console.log(` ${ui_1.colors.success('✓')} ${key} ${ui_1.colors.muted(`(line ${ref.line})`)}`);
653
+ }
654
+ }
655
+ }
656
+ // Show issues
657
+ if (issues.length > 0) {
658
+ console.log();
659
+ console.log(ui_1.colors.error(' Issues:'));
660
+ for (const issue of issues) {
661
+ if (issue.type === 'unknown_protocol') {
662
+ console.log(` ${ui_1.colors.error('✕')} Unknown protocol: ${ui_1.colors.highlight(issue.protocol)} ${ui_1.colors.muted(`(line ${issue.line})`)}`);
663
+ }
664
+ else if (issue.type === 'unknown_action') {
665
+ console.log(` ${ui_1.colors.error('✕')} Unknown action: ${ui_1.colors.highlight(issue.protocol + '.' + issue.action)} ${ui_1.colors.muted(`(line ${issue.line})`)}`);
666
+ }
667
+ if (issue.suggestions && issue.suggestions.length > 0) {
668
+ console.log(` ${ui_1.colors.muted('Did you mean:')} ${issue.suggestions.join(', ')}`);
669
+ }
670
+ }
671
+ }
672
+ console.log();
673
+ (0, ui_1.divider)();
674
+ if (data.valid) {
675
+ (0, ui_1.info)('Ready to deploy: `suzi agents deploy ' + path_1.default.relative(process.cwd(), resolvedPath) + '`');
676
+ }
677
+ else {
678
+ (0, ui_1.warn)('Fix the issues above before deploying.');
679
+ }
680
+ }
681
+ catch (err) {
682
+ spinner?.fail();
683
+ const msg = `Validation error: ${err.message}`;
684
+ if (jsonMode) {
685
+ (0, tty_1.outputJson)({ success: false, error: msg });
686
+ }
687
+ else {
688
+ (0, ui_1.error)(msg);
689
+ }
690
+ }
691
+ }
692
+ async function activateAgentCommand(idOrName, opts) {
693
+ if (!(0, ui_1.requireAuth)())
694
+ return;
695
+ const jsonMode = opts?.json || false;
696
+ const agent = await (0, agent_picker_1.fetchAndPickAgent)(idOrName, jsonMode);
697
+ if (!agent)
698
+ return;
699
+ const spinner = (0, tty_1.createSpinner)('Activating agent...', jsonMode);
700
+ spinner?.start();
701
+ const resp = await (0, api_1.post)(`/api/agent/${agent.id}/activate`);
702
+ if (!resp.ok) {
703
+ spinner?.fail();
704
+ const errorMsg = resp.data?.error || resp.data?.message || 'Unknown error';
705
+ if (jsonMode) {
706
+ (0, tty_1.outputJson)({ success: false, error: errorMsg });
707
+ }
708
+ else {
709
+ (0, ui_1.error)(`Failed to activate: ${errorMsg}`);
710
+ }
711
+ (0, memory_1.appendLearning)({ category: 'error', message: `Activate failed: ${errorMsg}`, command: 'agent activate', agentId: agent.id });
712
+ return;
713
+ }
714
+ spinner?.succeed();
715
+ if (jsonMode) {
716
+ (0, tty_1.outputJson)({ success: true, data: { agentId: agent.id, status: 'active' } });
717
+ }
718
+ else {
719
+ (0, ui_1.success)(`Agent ${agent.id.slice(0, 8)}... activated.`);
720
+ }
721
+ }
722
+ async function deactivateAgentCommand(idOrName, opts) {
723
+ if (!(0, ui_1.requireAuth)())
724
+ return;
725
+ const jsonMode = opts?.json || false;
726
+ const agent = await (0, agent_picker_1.fetchAndPickAgent)(idOrName, jsonMode);
727
+ if (!agent)
728
+ return;
729
+ // Confirmation prompt for destructive action
730
+ if (!opts?.force && !jsonMode && (0, tty_1.shouldUseInteractive)()) {
731
+ const answers = await inquirer_1.default.prompt([
732
+ {
733
+ type: 'confirm',
734
+ name: 'confirm',
735
+ message: `Deactivate "${agent.title || 'Untitled'}"? This will stop all triggers and scheduled executions.`,
736
+ default: false,
737
+ },
738
+ ]);
739
+ if (!answers.confirm) {
740
+ (0, ui_1.info)('Cancelled.');
741
+ return;
742
+ }
743
+ }
744
+ const spinner = (0, tty_1.createSpinner)('Deactivating agent...', jsonMode);
745
+ spinner?.start();
746
+ const resp = await (0, api_1.post)(`/api/agent/${agent.id}/deactivate`);
747
+ if (!resp.ok) {
748
+ spinner?.fail();
749
+ const errorMsg = resp.data?.error || resp.data?.message || 'Unknown error';
750
+ if (jsonMode) {
751
+ (0, tty_1.outputJson)({ success: false, error: errorMsg });
752
+ }
753
+ else {
754
+ (0, ui_1.error)(`Failed to deactivate: ${errorMsg}`);
755
+ }
756
+ (0, memory_1.appendLearning)({ category: 'error', message: `Deactivate failed: ${errorMsg}`, command: 'agent deactivate', agentId: agent.id });
757
+ return;
758
+ }
759
+ spinner?.succeed();
760
+ if (jsonMode) {
761
+ (0, tty_1.outputJson)({ success: true, data: { agentId: agent.id, status: 'inactive' } });
762
+ }
763
+ else {
764
+ (0, ui_1.success)(`Agent ${agent.id.slice(0, 8)}... deactivated.`);
765
+ }
766
+ }
767
+ async function executeAgentCommand(idOrName, trigger, opts) {
768
+ if (!(0, ui_1.requireAuth)())
769
+ return;
770
+ const jsonMode = opts?.json || false;
771
+ const agent = await (0, agent_picker_1.fetchAndPickAgent)(idOrName, jsonMode);
772
+ if (!agent)
773
+ return;
774
+ // If no trigger specified, fetch agent to find manual triggers
775
+ let triggerName = trigger;
776
+ if (!triggerName) {
777
+ const agentResp = await (0, api_1.get)(`/api/agent/${agent.id}`);
778
+ if (agentResp.ok && agentResp.data?.spec) {
779
+ const spec = (0, ui_1.safeParseJSON)(agentResp.data.spec);
780
+ const triggers = Object.keys(spec.triggers || {});
781
+ if (triggers.length === 0) {
782
+ const msg = 'No triggers found on this agent.';
783
+ if (jsonMode) {
784
+ (0, tty_1.outputJson)({ success: false, error: msg });
785
+ }
786
+ else {
787
+ (0, ui_1.error)(msg);
788
+ }
789
+ return;
790
+ }
791
+ if (triggers.length === 1) {
792
+ triggerName = triggers[0];
793
+ }
794
+ else if (!jsonMode && (0, tty_1.shouldUseInteractive)()) {
795
+ const answers = await inquirer_1.default.prompt([
796
+ {
797
+ type: 'list',
798
+ name: 'trigger',
799
+ message: 'Select a trigger to execute:',
800
+ choices: triggers,
801
+ },
802
+ ]);
803
+ triggerName = answers.trigger;
804
+ }
805
+ else {
806
+ const msg = 'Multiple triggers available. Specify trigger name.';
807
+ if (jsonMode) {
808
+ (0, tty_1.outputJson)({ success: false, error: msg, data: { triggers } });
809
+ }
810
+ else {
811
+ (0, ui_1.error)(msg);
812
+ (0, ui_1.info)('Available triggers: ' + triggers.join(', '));
813
+ }
814
+ return;
815
+ }
816
+ }
817
+ else {
818
+ const msg = 'Could not fetch agent spec.';
819
+ if (jsonMode) {
820
+ (0, tty_1.outputJson)({ success: false, error: msg });
821
+ }
822
+ else {
823
+ (0, ui_1.error)(msg + ' Specify trigger name explicitly.');
824
+ }
825
+ return;
826
+ }
827
+ }
828
+ const spinner = (0, tty_1.createSpinner)(`Executing trigger "${triggerName}"...`, jsonMode);
829
+ spinner?.start();
830
+ const resp = await (0, api_1.post)(`/api/agent/${agent.id}/execute`, {
831
+ triggerName: triggerName,
832
+ });
833
+ if (!resp.ok) {
834
+ spinner?.fail();
835
+ const errorMsg = resp.data?.error || resp.data?.message || 'Unknown error';
836
+ if (jsonMode) {
837
+ (0, tty_1.outputJson)({ success: false, error: errorMsg });
838
+ }
839
+ else {
840
+ (0, ui_1.error)(`Execution failed: ${errorMsg}`);
841
+ }
842
+ (0, memory_1.appendLearning)({ category: 'error', message: `Execution failed: ${errorMsg}`, command: 'agent execute', agentId: agent.id });
843
+ return;
844
+ }
845
+ spinner?.succeed();
846
+ if (jsonMode) {
847
+ (0, tty_1.outputJson)({ success: true, data: { executionId: resp.data.executionId } });
848
+ }
849
+ else {
850
+ (0, ui_1.success)(`Execution started. Run ID: ${resp.data.executionId || 'N/A'}`);
851
+ }
852
+ }
853
+ async function logsAgentCommand(idOrName, opts) {
854
+ if (!(0, ui_1.requireAuth)())
855
+ return;
856
+ const jsonMode = opts?.json || false;
857
+ const agent = await (0, agent_picker_1.fetchAndPickAgent)(idOrName, jsonMode);
858
+ if (!agent)
859
+ return;
860
+ const spinner = (0, tty_1.createSpinner)('Loading logs...', jsonMode);
861
+ spinner?.start();
862
+ let path = `/api/agent/${agent.id}/logs?limit=${opts?.limit || 20}`;
863
+ if (opts?.level)
864
+ path += `&level=${opts.level}`;
865
+ const resp = await (0, api_1.get)(path);
866
+ if (!resp.ok) {
867
+ spinner?.fail();
868
+ const msg = `Failed to load logs: ${resp.data?.error || 'Unknown error'}`;
869
+ if (jsonMode) {
870
+ (0, tty_1.outputJson)({ success: false, error: msg });
871
+ }
872
+ else {
873
+ (0, ui_1.error)(msg);
874
+ }
875
+ return;
876
+ }
877
+ spinner?.stop();
878
+ const logs = resp.data.logs || [];
879
+ if (jsonMode) {
880
+ (0, tty_1.outputJson)({ success: true, data: { logs, count: logs.length } });
881
+ return;
882
+ }
883
+ if (logs.length === 0) {
884
+ (0, ui_1.info)('No logs found.');
885
+ return;
886
+ }
887
+ (0, ui_1.header)(`Agent Logs (${logs.length})`);
888
+ console.log();
889
+ for (const log of logs) {
890
+ const levelColor = log.level === 'error'
891
+ ? chalk_1.default.red
892
+ : log.level === 'warn'
893
+ ? chalk_1.default.yellow
894
+ : log.level === 'debug'
895
+ ? chalk_1.default.gray
896
+ : chalk_1.default.white;
897
+ const ts = new Date(log.createdAt).toLocaleTimeString();
898
+ console.log(` ${ui_1.colors.muted(ts)} ${levelColor(`[${log.level}]`)} ${log.log}`);
899
+ }
900
+ }
901
+ async function codeAgentCommand(idOrName, opts) {
902
+ if (!(0, ui_1.requireAuth)())
903
+ return;
904
+ const jsonMode = opts?.json || false;
905
+ const agent = await (0, agent_picker_1.fetchAndPickAgent)(idOrName, jsonMode);
906
+ if (!agent)
907
+ return;
908
+ const spinner = (0, tty_1.createSpinner)('Loading agent code...', jsonMode);
909
+ spinner?.start();
910
+ const resp = await (0, api_1.get)(`/api/agent/${agent.id}`);
911
+ if (!resp.ok) {
912
+ spinner?.fail();
913
+ const msg = `Agent not found: ${resp.data?.error || resp.data?.message || 'Unknown error'}`;
914
+ if (jsonMode) {
915
+ (0, tty_1.outputJson)({ success: false, error: msg });
916
+ }
917
+ else {
918
+ (0, ui_1.error)(msg);
919
+ }
920
+ return;
921
+ }
922
+ spinner?.stop();
923
+ const agentData = resp.data;
924
+ if (!agentData.source) {
925
+ const msg = 'No source code found for this agent.';
926
+ if (jsonMode) {
927
+ (0, tty_1.outputJson)({ success: false, error: msg });
928
+ }
929
+ else {
930
+ (0, ui_1.info)(msg);
931
+ }
932
+ return;
933
+ }
934
+ if (jsonMode) {
935
+ (0, tty_1.outputJson)({ success: true, data: { source: agentData.source, title: agentData.title } });
936
+ return;
937
+ }
938
+ (0, ui_1.header)(agentData.title || 'Untitled Agent');
939
+ console.log();
940
+ const lines = agentData.source.split('\n');
941
+ for (let i = 0; i < lines.length; i++) {
942
+ const lineNum = ui_1.colors.muted(String(i + 1).padStart(4));
943
+ console.log(`${lineNum} ${lines[i]}`);
944
+ }
945
+ console.log();
946
+ console.log(ui_1.colors.muted(` ${lines.length} lines`));
947
+ }
948
+ async function deleteAgentCommand(idOrName, opts) {
949
+ if (!(0, ui_1.requireAuth)())
950
+ return;
951
+ const jsonMode = opts?.json || false;
952
+ const agent = await (0, agent_picker_1.fetchAndPickAgent)(idOrName, jsonMode);
953
+ if (!agent)
954
+ return;
955
+ if (!opts?.force && !jsonMode && (0, tty_1.shouldUseInteractive)()) {
956
+ const answers = await inquirer_1.default.prompt([
957
+ {
958
+ type: 'confirm',
959
+ name: 'confirm',
960
+ message: `Are you sure you want to delete agent ${agent.id.slice(0, 8)}...?`,
961
+ default: false,
962
+ },
963
+ ]);
964
+ if (!answers.confirm) {
965
+ (0, ui_1.info)('Cancelled.');
966
+ return;
967
+ }
968
+ }
969
+ const spinner = (0, tty_1.createSpinner)('Deleting agent...', jsonMode);
970
+ spinner?.start();
971
+ const resp = await (0, api_1.del)(`/api/agent/${agent.id}`);
972
+ if (!resp.ok) {
973
+ spinner?.fail();
974
+ const msg = `Failed to delete: ${resp.data?.error || 'Unknown error'}`;
975
+ if (jsonMode) {
976
+ (0, tty_1.outputJson)({ success: false, error: msg });
977
+ }
978
+ else {
979
+ (0, ui_1.error)(msg);
980
+ }
981
+ return;
982
+ }
983
+ spinner?.succeed();
984
+ if (jsonMode) {
985
+ (0, tty_1.outputJson)({ success: true, data: { agentId: agent.id, deleted: true } });
986
+ }
987
+ else {
988
+ (0, ui_1.success)(`Agent ${agent.id.slice(0, 8)}... deleted.`);
989
+ }
990
+ }
991
+ //# sourceMappingURL=agent.js.map