|
| 1 | +import chalk from 'chalk'; |
| 2 | +import { getConnection } from '../config.js'; |
| 3 | + |
| 4 | +function getAccountsAuth(): { baseUrl: string; token: string } { |
| 5 | + const connection = getConnection(); |
| 6 | + if (!connection) { |
| 7 | + console.error(chalk.red('Not logged in.')); |
| 8 | + console.error(`Run: ${chalk.cyan('npx atxp login')}`); |
| 9 | + process.exit(1); |
| 10 | + } |
| 11 | + const url = new URL(connection); |
| 12 | + const token = url.searchParams.get('connection_token'); |
| 13 | + if (!token) { |
| 14 | + console.error(chalk.red('Invalid connection string: missing connection_token')); |
| 15 | + process.exit(1); |
| 16 | + } |
| 17 | + return { baseUrl: `${url.protocol}//${url.host}`, token }; |
| 18 | +} |
| 19 | + |
| 20 | +function showAgentHelp(): void { |
| 21 | + console.log(chalk.bold('Agent Commands:')); |
| 22 | + console.log(); |
| 23 | + console.log(' ' + chalk.cyan('npx atxp agent create') + ' ' + 'Create a new agent account'); |
| 24 | + console.log(' ' + chalk.cyan('npx atxp agent list') + ' ' + 'List your agents'); |
| 25 | + console.log(); |
| 26 | + console.log(chalk.bold('Details:')); |
| 27 | + console.log(' Each agent gets:'); |
| 28 | + console.log(' - A unique email address ({agentId}@atxp.email)'); |
| 29 | + console.log(' - An Ethereum wallet'); |
| 30 | + console.log(' - 10 IOU tokens to start'); |
| 31 | + console.log(' - A connection token for SDK/CLI access'); |
| 32 | + console.log(); |
| 33 | + console.log(chalk.bold('Examples:')); |
| 34 | + console.log(' npx atxp agent create'); |
| 35 | + console.log(' npx atxp agent list'); |
| 36 | + console.log(' CONNECTION_TOKEN=<agent_token> npx atxp email inbox'); |
| 37 | +} |
| 38 | + |
| 39 | +export async function agentCommand(subCommand: string): Promise<void> { |
| 40 | + if (!subCommand || subCommand === 'help' || subCommand === '--help' || subCommand === '-h') { |
| 41 | + showAgentHelp(); |
| 42 | + return; |
| 43 | + } |
| 44 | + |
| 45 | + switch (subCommand) { |
| 46 | + case 'create': |
| 47 | + await createAgent(); |
| 48 | + break; |
| 49 | + |
| 50 | + case 'list': |
| 51 | + await listAgents(); |
| 52 | + break; |
| 53 | + |
| 54 | + default: |
| 55 | + console.error(chalk.red(`Unknown agent command: ${subCommand}`)); |
| 56 | + console.log(); |
| 57 | + showAgentHelp(); |
| 58 | + process.exit(1); |
| 59 | + } |
| 60 | +} |
| 61 | + |
| 62 | +async function createAgent(): Promise<void> { |
| 63 | + const { baseUrl, token } = getAccountsAuth(); |
| 64 | + |
| 65 | + console.log(chalk.gray('Creating agent...')); |
| 66 | + |
| 67 | + const res = await fetch(`${baseUrl}/agents`, { |
| 68 | + method: 'POST', |
| 69 | + headers: { |
| 70 | + 'Authorization': `Bearer ${token}`, |
| 71 | + 'Content-Type': 'application/json', |
| 72 | + }, |
| 73 | + }); |
| 74 | + |
| 75 | + if (!res.ok) { |
| 76 | + const body = await res.json().catch(() => ({})); |
| 77 | + console.error(chalk.red(`Error: ${(body as Record<string, string>).error || res.statusText}`)); |
| 78 | + process.exit(1); |
| 79 | + } |
| 80 | + |
| 81 | + const data = await res.json() as { |
| 82 | + agentId: string; |
| 83 | + email: string; |
| 84 | + atxpAccountId: string; |
| 85 | + connectionToken: string; |
| 86 | + connectionString: string; |
| 87 | + walletAddress: string; |
| 88 | + fundedAmount: string; |
| 89 | + }; |
| 90 | + |
| 91 | + console.log(); |
| 92 | + console.log(chalk.green.bold('Agent created successfully!')); |
| 93 | + console.log(); |
| 94 | + console.log(' ' + chalk.bold('Agent ID:') + ' ' + data.agentId); |
| 95 | + console.log(' ' + chalk.bold('Email:') + ' ' + chalk.cyan(data.email)); |
| 96 | + console.log(' ' + chalk.bold('Account ID:') + ' ' + data.atxpAccountId); |
| 97 | + console.log(' ' + chalk.bold('Connection Token:') + ' ' + data.connectionToken); |
| 98 | + console.log(' ' + chalk.bold('Wallet:') + ' ' + data.walletAddress); |
| 99 | + console.log(' ' + chalk.bold('Funded:') + ' ' + data.fundedAmount + ' IOU'); |
| 100 | + console.log(); |
| 101 | + console.log(chalk.bold('Connection String:')); |
| 102 | + console.log(' ' + chalk.cyan(data.connectionString)); |
| 103 | + console.log(); |
| 104 | + console.log(chalk.bold('Use this to authenticate as the agent:')); |
| 105 | + console.log(' ' + chalk.yellow(`CONNECTION_TOKEN=${data.connectionToken} npx atxp email inbox`)); |
| 106 | +} |
| 107 | + |
| 108 | +async function listAgents(): Promise<void> { |
| 109 | + const { baseUrl, token } = getAccountsAuth(); |
| 110 | + |
| 111 | + const res = await fetch(`${baseUrl}/agents`, { |
| 112 | + headers: { |
| 113 | + 'Authorization': `Bearer ${token}`, |
| 114 | + }, |
| 115 | + }); |
| 116 | + |
| 117 | + if (!res.ok) { |
| 118 | + const body = await res.json().catch(() => ({})); |
| 119 | + console.error(chalk.red(`Error: ${(body as Record<string, string>).error || res.statusText}`)); |
| 120 | + process.exit(1); |
| 121 | + } |
| 122 | + |
| 123 | + const data = await res.json() as { |
| 124 | + agents: Array<{ |
| 125 | + connectionToken: string; |
| 126 | + atxpAccountId: string; |
| 127 | + email: string | null; |
| 128 | + walletAddress: string | null; |
| 129 | + balance: { totalUsdc: string; totalIou: string } | null; |
| 130 | + createdAt: string | null; |
| 131 | + }>; |
| 132 | + }; |
| 133 | + |
| 134 | + if (data.agents.length === 0) { |
| 135 | + console.log(chalk.gray('No agents created yet.')); |
| 136 | + console.log(); |
| 137 | + console.log('Create one with: ' + chalk.cyan('npx atxp agent create')); |
| 138 | + return; |
| 139 | + } |
| 140 | + |
| 141 | + console.log(chalk.bold(`Your Agents (${data.agents.length})`)); |
| 142 | + console.log(); |
| 143 | + |
| 144 | + for (const agent of data.agents) { |
| 145 | + console.log(chalk.gray('─'.repeat(50))); |
| 146 | + console.log(' ' + chalk.bold('Email:') + ' ' + chalk.cyan(agent.email || 'Unknown')); |
| 147 | + console.log(' ' + chalk.bold('Account ID:') + ' ' + agent.atxpAccountId); |
| 148 | + console.log(' ' + chalk.bold('Connection Token:') + ' ' + agent.connectionToken); |
| 149 | + if (agent.walletAddress) { |
| 150 | + console.log(' ' + chalk.bold('Wallet:') + ' ' + agent.walletAddress); |
| 151 | + } |
| 152 | + if (agent.balance) { |
| 153 | + console.log(' ' + chalk.bold('Balance:') + ' ' + `$${agent.balance.totalUsdc} USDC / $${agent.balance.totalIou} IOU`); |
| 154 | + } |
| 155 | + if (agent.createdAt) { |
| 156 | + const date = new Date(agent.createdAt).toLocaleDateString('en-US', { |
| 157 | + month: 'short', |
| 158 | + day: 'numeric', |
| 159 | + year: 'numeric', |
| 160 | + hour: '2-digit', |
| 161 | + minute: '2-digit', |
| 162 | + }); |
| 163 | + console.log(' ' + chalk.bold('Created:') + ' ' + chalk.gray(date)); |
| 164 | + } |
| 165 | + } |
| 166 | + console.log(chalk.gray('─'.repeat(50))); |
| 167 | +} |
0 commit comments