@sly_ai/cli 0.1.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/package.json ADDED
@@ -0,0 +1,22 @@
1
+ {
2
+ "name": "@sly_ai/cli",
3
+ "version": "0.1.0",
4
+ "description": "Sly CLI — command-line interface for the Sly agentic economy platform",
5
+ "type": "module",
6
+ "bin": {
7
+ "sly": "./dist/index.js"
8
+ },
9
+ "scripts": {
10
+ "build": "tsup src/index.ts --format esm --dts --clean",
11
+ "dev": "tsx src/index.ts"
12
+ },
13
+ "dependencies": {
14
+ "@sly/sdk": "workspace:*",
15
+ "commander": "^12.0.0"
16
+ },
17
+ "devDependencies": {
18
+ "tsup": "^8.0.0",
19
+ "tsx": "^4.0.0",
20
+ "typescript": "^5.0.0"
21
+ }
22
+ }
@@ -0,0 +1,110 @@
1
+ import { Command } from 'commander';
2
+ import { createClient } from '../utils/auth.js';
3
+ import { output, error } from '../utils/output.js';
4
+
5
+ export function registerA2ACommands(program: Command) {
6
+ const cmd = program.command('a2a').description('A2A (Agent-to-Agent Protocol) task management');
7
+
8
+ cmd
9
+ .command('discover <agentId>')
10
+ .description('Discover an agent\'s capabilities via its Agent Card')
11
+ .action(async (agentId) => {
12
+ try {
13
+ const sly = createClient();
14
+ const result = await sly.a2a.discover(agentId);
15
+ output(result);
16
+ } catch (e: unknown) {
17
+ error((e as Error).message);
18
+ }
19
+ });
20
+
21
+ cmd
22
+ .command('send')
23
+ .description('Send a message to an A2A agent')
24
+ .requiredOption('--agent-id <agentId>', 'Local Sly agent ID')
25
+ .requiredOption('--message <message>', 'Text message to send to the agent')
26
+ .option('--context-id <contextId>', 'Context ID for multi-turn conversations')
27
+ .option('--skill-id <skillId>', 'Skill ID to target')
28
+ .action(async (opts) => {
29
+ try {
30
+ const sly = createClient();
31
+ const result = await sly.a2a.sendMessage(opts.agentId, {
32
+ message: opts.message,
33
+ contextId: opts.contextId,
34
+ skillId: opts.skillId,
35
+ });
36
+ output(result);
37
+ } catch (e: unknown) {
38
+ error((e as Error).message);
39
+ }
40
+ });
41
+
42
+ cmd
43
+ .command('get-task')
44
+ .description('Get the status and details of an A2A task')
45
+ .requiredOption('--agent-id <agentId>', 'Agent ID')
46
+ .requiredOption('--task-id <taskId>', 'Task ID')
47
+ .option('--history-length <length>', 'Number of history items to include', parseInt)
48
+ .action(async (opts) => {
49
+ try {
50
+ const sly = createClient();
51
+ const result = await sly.a2a.getTask(opts.agentId, opts.taskId, opts.historyLength);
52
+ output(result);
53
+ } catch (e: unknown) {
54
+ error((e as Error).message);
55
+ }
56
+ });
57
+
58
+ cmd
59
+ .command('tasks')
60
+ .description('List A2A tasks')
61
+ .option('--agent-id <agentId>', 'Filter by agent ID')
62
+ .option('--state <state>', 'Filter by state (submitted, working, input-required, completed, failed, canceled, rejected)')
63
+ .option('--direction <direction>', 'Filter by direction (inbound, outbound)')
64
+ .option('--limit <limit>', 'Results per page', parseInt)
65
+ .option('--page <page>', 'Page number', parseInt)
66
+ .action(async (opts) => {
67
+ try {
68
+ const sly = createClient();
69
+ const result = await sly.a2a.listTasks({
70
+ agentId: opts.agentId,
71
+ state: opts.state,
72
+ direction: opts.direction,
73
+ limit: opts.limit,
74
+ page: opts.page,
75
+ });
76
+ output(result);
77
+ } catch (e: unknown) {
78
+ error((e as Error).message);
79
+ }
80
+ });
81
+
82
+ cmd
83
+ .command('respond <taskId>')
84
+ .description('Respond to a task in input-required state')
85
+ .requiredOption('--message <message>', 'Response message')
86
+ .action(async (taskId, opts) => {
87
+ try {
88
+ const sly = createClient();
89
+ const result = await sly.a2a.respond(taskId, opts.message);
90
+ output(result);
91
+ } catch (e: unknown) {
92
+ error((e as Error).message);
93
+ }
94
+ });
95
+
96
+ cmd
97
+ .command('cancel')
98
+ .description('Cancel an A2A task')
99
+ .requiredOption('--agent-id <agentId>', 'Agent ID')
100
+ .requiredOption('--task-id <taskId>', 'Task ID')
101
+ .action(async (opts) => {
102
+ try {
103
+ const sly = createClient();
104
+ const result = await sly.a2a.cancelTask(opts.agentId, opts.taskId);
105
+ output(result);
106
+ } catch (e: unknown) {
107
+ error((e as Error).message);
108
+ }
109
+ });
110
+ }
@@ -0,0 +1,85 @@
1
+ import { Command } from 'commander';
2
+ import { createClient } from '../utils/auth.js';
3
+ import { output, error } from '../utils/output.js';
4
+
5
+ export function registerAccountsCommands(program: Command) {
6
+ const cmd = program.command('accounts').description('Manage accounts (entities in the payment ledger)');
7
+
8
+ cmd
9
+ .command('list')
10
+ .description('List accounts')
11
+ .option('--status <status>', 'Filter by status (active, inactive, suspended)')
12
+ .option('--type <type>', 'Filter by type (person, business)')
13
+ .action(async (opts) => {
14
+ try {
15
+ const sly = createClient();
16
+ const params = new URLSearchParams();
17
+ if (opts.status) params.set('status', opts.status);
18
+ if (opts.type) params.set('type', opts.type);
19
+ const qs = params.toString();
20
+ const result = await sly.request(`/v1/accounts${qs ? `?${qs}` : ''}`);
21
+ output(result);
22
+ } catch (e: unknown) {
23
+ error((e as Error).message);
24
+ }
25
+ });
26
+
27
+ cmd
28
+ .command('create')
29
+ .description('Create a new account')
30
+ .requiredOption('--name <name>', 'Account holder name')
31
+ .requiredOption('--type <type>', 'Account type (person, business)')
32
+ .option('--email <email>', 'Email address')
33
+ .option('--metadata <json>', 'Metadata as JSON string')
34
+ .action(async (opts) => {
35
+ try {
36
+ const sly = createClient();
37
+ const body: Record<string, unknown> = { name: opts.name, type: opts.type };
38
+ if (opts.email) body.email = opts.email;
39
+ if (opts.metadata) body.metadata = JSON.parse(opts.metadata);
40
+ const result = await sly.request('/v1/accounts', {
41
+ method: 'POST',
42
+ body: JSON.stringify(body),
43
+ });
44
+ output(result);
45
+ } catch (e: unknown) {
46
+ error((e as Error).message);
47
+ }
48
+ });
49
+
50
+ cmd
51
+ .command('get <id>')
52
+ .description('Get account details')
53
+ .action(async (id) => {
54
+ try {
55
+ const sly = createClient();
56
+ const result = await sly.request(`/v1/accounts/${id}`);
57
+ output(result);
58
+ } catch (e: unknown) {
59
+ error((e as Error).message);
60
+ }
61
+ });
62
+
63
+ cmd
64
+ .command('update <id>')
65
+ .description('Update an account')
66
+ .option('--name <name>', 'New name')
67
+ .option('--email <email>', 'New email')
68
+ .option('--metadata <json>', 'Metadata as JSON string')
69
+ .action(async (id, opts) => {
70
+ try {
71
+ const sly = createClient();
72
+ const body: Record<string, unknown> = {};
73
+ if (opts.name) body.name = opts.name;
74
+ if (opts.email) body.email = opts.email;
75
+ if (opts.metadata) body.metadata = JSON.parse(opts.metadata);
76
+ const result = await sly.request(`/v1/accounts/${id}`, {
77
+ method: 'PATCH',
78
+ body: JSON.stringify(body),
79
+ });
80
+ output(result);
81
+ } catch (e: unknown) {
82
+ error((e as Error).message);
83
+ }
84
+ });
85
+ }
@@ -0,0 +1,104 @@
1
+ import { Command } from 'commander';
2
+ import { createClient } from '../utils/auth.js';
3
+ import { output, error } from '../utils/output.js';
4
+
5
+ export function registerACPCommands(program: Command) {
6
+ const cmd = program.command('acp').description('ACP (Agentic Commerce Protocol) checkout-based payments');
7
+
8
+ cmd
9
+ .command('checkouts')
10
+ .description('List ACP checkouts')
11
+ .option('--status <status>', 'Filter by status (pending, completed, cancelled, expired)')
12
+ .option('--agent-id <agentId>', 'Filter by agent ID')
13
+ .option('--merchant-id <merchantId>', 'Filter by merchant ID')
14
+ .option('--limit <limit>', 'Max results', parseInt)
15
+ .action(async (opts) => {
16
+ try {
17
+ const sly = createClient();
18
+ const result = await sly.acp.listCheckouts({
19
+ status: opts.status,
20
+ agent_id: opts.agentId,
21
+ merchant_id: opts.merchantId,
22
+ limit: opts.limit,
23
+ });
24
+ output(result);
25
+ } catch (e: unknown) {
26
+ error((e as Error).message);
27
+ }
28
+ });
29
+
30
+ cmd
31
+ .command('get <checkoutId>')
32
+ .description('Get checkout details')
33
+ .action(async (checkoutId) => {
34
+ try {
35
+ const sly = createClient();
36
+ const result = await sly.acp.getCheckout(checkoutId);
37
+ output(result);
38
+ } catch (e: unknown) {
39
+ error((e as Error).message);
40
+ }
41
+ });
42
+
43
+ cmd
44
+ .command('create')
45
+ .description('Create a checkout session')
46
+ .requiredOption('--checkout-id <checkoutId>', 'Unique checkout identifier')
47
+ .requiredOption('--agent-id <agentId>', 'UUID of the agent')
48
+ .requiredOption('--merchant-id <merchantId>', 'Merchant identifier')
49
+ .requiredOption('--items <json>', 'Items as JSON array')
50
+ .option('--account-id <accountId>', 'UUID of the funding account')
51
+ .option('--tax-amount <amount>', 'Tax amount', parseFloat)
52
+ .option('--shipping-amount <amount>', 'Shipping amount', parseFloat)
53
+ .option('--payment-method <method>', 'Payment method')
54
+ .action(async (opts) => {
55
+ try {
56
+ const sly = createClient();
57
+ const body: Record<string, unknown> = {
58
+ checkout_id: opts.checkoutId,
59
+ agent_id: opts.agentId,
60
+ merchant_id: opts.merchantId,
61
+ items: JSON.parse(opts.items),
62
+ };
63
+ if (opts.accountId) body.account_id = opts.accountId;
64
+ if (opts.taxAmount !== undefined) body.tax_amount = opts.taxAmount;
65
+ if (opts.shippingAmount !== undefined) body.shipping_amount = opts.shippingAmount;
66
+ if (opts.paymentMethod) body.payment_method = opts.paymentMethod;
67
+ const result = await sly.acp.createCheckout(body as Parameters<typeof sly.acp.createCheckout>[0]);
68
+ output(result);
69
+ } catch (e: unknown) {
70
+ error((e as Error).message);
71
+ }
72
+ });
73
+
74
+ cmd
75
+ .command('complete <checkoutId>')
76
+ .description('Complete and pay for a checkout')
77
+ .option('--shared-payment-token <token>', 'Shared payment token (auto-generated in sandbox)')
78
+ .option('--payment-method <method>', 'Payment method')
79
+ .action(async (checkoutId, opts) => {
80
+ try {
81
+ const sly = createClient();
82
+ const body: Record<string, unknown> = {};
83
+ if (opts.sharedPaymentToken) body.shared_payment_token = opts.sharedPaymentToken;
84
+ if (opts.paymentMethod) body.payment_method = opts.paymentMethod;
85
+ const result = await sly.acp.completeCheckout(checkoutId, body as Parameters<typeof sly.acp.completeCheckout>[1]);
86
+ output(result);
87
+ } catch (e: unknown) {
88
+ error((e as Error).message);
89
+ }
90
+ });
91
+
92
+ cmd
93
+ .command('cancel <checkoutId>')
94
+ .description('Cancel a checkout')
95
+ .action(async (checkoutId) => {
96
+ try {
97
+ const sly = createClient();
98
+ const result = await sly.acp.cancelCheckout(checkoutId);
99
+ output(result);
100
+ } catch (e: unknown) {
101
+ error((e as Error).message);
102
+ }
103
+ });
104
+ }
@@ -0,0 +1,127 @@
1
+ import { Command } from 'commander';
2
+ import { createClient } from '../utils/auth.js';
3
+ import { output, error } from '../utils/output.js';
4
+
5
+ export function registerAgentWalletsCommands(program: Command) {
6
+ const cmd = program.command('agent-wallets').description('Agent wallet policies, exposures, and governance');
7
+
8
+ cmd
9
+ .command('get <agentId>')
10
+ .description('Get agent wallet details including balance and spending policy')
11
+ .action(async (agentId) => {
12
+ try {
13
+ const sly = createClient();
14
+ const result = await sly.agentWallets.getWallet(agentId);
15
+ output(result);
16
+ } catch (e: unknown) {
17
+ error((e as Error).message);
18
+ }
19
+ });
20
+
21
+ cmd
22
+ .command('evaluate-policy <agentId>')
23
+ .description('Evaluate contract policy for an agent payment (dry-run)')
24
+ .requiredOption('--amount <amount>', 'Payment amount to evaluate', parseFloat)
25
+ .option('--currency <currency>', 'Currency (default: USDC)')
26
+ .option('--action-type <type>', 'Action type (payment, escrow_create, escrow_release, contract_sign, negotiation_check, counterparty_check)')
27
+ .option('--contract-type <type>', 'Contract type')
28
+ .option('--counterparty-agent-id <id>', 'UUID of the counterparty agent')
29
+ .option('--counterparty-address <addr>', 'Wallet address of external counterparty')
30
+ .action(async (agentId, opts) => {
31
+ try {
32
+ const sly = createClient();
33
+ const result = await sly.agentWallets.evaluatePolicy(agentId, {
34
+ amount: opts.amount,
35
+ currency: opts.currency,
36
+ actionType: opts.actionType || 'negotiation_check',
37
+ contractType: opts.contractType,
38
+ counterpartyAgentId: opts.counterpartyAgentId,
39
+ counterpartyAddress: opts.counterpartyAddress,
40
+ });
41
+ output(result);
42
+ } catch (e: unknown) {
43
+ error((e as Error).message);
44
+ }
45
+ });
46
+
47
+ cmd
48
+ .command('exposures <agentId>')
49
+ .description('List per-counterparty exposure windows for an agent wallet')
50
+ .action(async (agentId) => {
51
+ try {
52
+ const sly = createClient();
53
+ const result = await sly.agentWallets.getExposures(agentId);
54
+ output(result);
55
+ } catch (e: unknown) {
56
+ error((e as Error).message);
57
+ }
58
+ });
59
+
60
+ cmd
61
+ .command('evaluations <agentId>')
62
+ .description('Get the policy evaluation audit log for an agent wallet')
63
+ .option('--page <page>', 'Page number', parseInt)
64
+ .option('--limit <limit>', 'Results per page', parseInt)
65
+ .action(async (agentId, opts) => {
66
+ try {
67
+ const sly = createClient();
68
+ const result = await sly.agentWallets.getEvaluations(agentId, {
69
+ page: opts.page,
70
+ limit: opts.limit,
71
+ });
72
+ output(result);
73
+ } catch (e: unknown) {
74
+ error((e as Error).message);
75
+ }
76
+ });
77
+
78
+ cmd
79
+ .command('freeze <agentId>')
80
+ .description('Freeze an agent\'s wallet (disables all payments)')
81
+ .action(async (agentId) => {
82
+ try {
83
+ const sly = createClient();
84
+ const result = await sly.agentWallets.freezeWallet(agentId);
85
+ output(result);
86
+ } catch (e: unknown) {
87
+ error((e as Error).message);
88
+ }
89
+ });
90
+
91
+ cmd
92
+ .command('unfreeze <agentId>')
93
+ .description('Unfreeze an agent\'s wallet')
94
+ .action(async (agentId) => {
95
+ try {
96
+ const sly = createClient();
97
+ const result = await sly.agentWallets.unfreezeWallet(agentId);
98
+ output(result);
99
+ } catch (e: unknown) {
100
+ error((e as Error).message);
101
+ }
102
+ });
103
+
104
+ cmd
105
+ .command('set-policy <agentId>')
106
+ .description('Set or update the spending and contract policy on an agent\'s wallet')
107
+ .option('--daily-spend-limit <amount>', 'Daily spending limit', parseFloat)
108
+ .option('--monthly-spend-limit <amount>', 'Monthly spending limit', parseFloat)
109
+ .option('--requires-approval-above <amount>', 'Amount above which human approval is required', parseFloat)
110
+ .option('--approved-vendors <json>', 'Approved vendor domains as JSON array')
111
+ .option('--contract-policy <json>', 'Contract policy rules as JSON object')
112
+ .action(async (agentId, opts) => {
113
+ try {
114
+ const sly = createClient();
115
+ const policy: Record<string, unknown> = {};
116
+ if (opts.dailySpendLimit !== undefined) policy.dailySpendLimit = opts.dailySpendLimit;
117
+ if (opts.monthlySpendLimit !== undefined) policy.monthlySpendLimit = opts.monthlySpendLimit;
118
+ if (opts.requiresApprovalAbove !== undefined) policy.requiresApprovalAbove = opts.requiresApprovalAbove;
119
+ if (opts.approvedVendors) policy.approvedVendors = JSON.parse(opts.approvedVendors);
120
+ if (opts.contractPolicy) policy.contractPolicy = JSON.parse(opts.contractPolicy);
121
+ const result = await sly.agentWallets.setContractPolicy(agentId, policy as Parameters<typeof sly.agentWallets.setContractPolicy>[1]);
122
+ output(result);
123
+ } catch (e: unknown) {
124
+ error((e as Error).message);
125
+ }
126
+ });
127
+ }
@@ -0,0 +1,110 @@
1
+ import { Command } from 'commander';
2
+ import { createClient } from '../utils/auth.js';
3
+ import { output, error } from '../utils/output.js';
4
+
5
+ export function registerAgentsCommands(program: Command) {
6
+ const cmd = program.command('agents').description('Manage AI agents');
7
+
8
+ cmd
9
+ .command('create')
10
+ .description('Register a new AI agent under a business account')
11
+ .requiredOption('--account-id <accountId>', 'UUID of the parent business account')
12
+ .requiredOption('--name <name>', 'Name for the agent')
13
+ .option('--description <description>', 'Description of what the agent does')
14
+ .action(async (opts) => {
15
+ try {
16
+ const sly = createClient();
17
+ const body: Record<string, unknown> = {
18
+ accountId: opts.accountId,
19
+ name: opts.name,
20
+ };
21
+ if (opts.description) body.description = opts.description;
22
+ const result = await sly.request('/v1/agents', {
23
+ method: 'POST',
24
+ body: JSON.stringify(body),
25
+ });
26
+ output(result);
27
+ } catch (e: unknown) {
28
+ error((e as Error).message);
29
+ }
30
+ });
31
+
32
+ cmd
33
+ .command('get <id>')
34
+ .description('Get agent details')
35
+ .action(async (id) => {
36
+ try {
37
+ const sly = createClient();
38
+ const result = await sly.request(`/v1/agents/${id}`);
39
+ output(result);
40
+ } catch (e: unknown) {
41
+ error((e as Error).message);
42
+ }
43
+ });
44
+
45
+ cmd
46
+ .command('delete <id>')
47
+ .description('Delete an agent')
48
+ .action(async (id) => {
49
+ try {
50
+ const sly = createClient();
51
+ const result = await sly.request(`/v1/agents/${id}`, { method: 'DELETE' });
52
+ output(result);
53
+ } catch (e: unknown) {
54
+ error((e as Error).message);
55
+ }
56
+ });
57
+
58
+ cmd
59
+ .command('verify <id>')
60
+ .description('Verify an agent at a KYA tier')
61
+ .requiredOption('--tier <tier>', 'KYA verification tier (1, 2, or 3)', parseInt)
62
+ .action(async (id, opts) => {
63
+ try {
64
+ const sly = createClient();
65
+ const result = await sly.request(`/v1/agents/${id}/verify`, {
66
+ method: 'POST',
67
+ body: JSON.stringify({ tier: opts.tier }),
68
+ });
69
+ output(result);
70
+ } catch (e: unknown) {
71
+ error((e as Error).message);
72
+ }
73
+ });
74
+
75
+ cmd
76
+ .command('limits <id>')
77
+ .description('Get spending limits and current usage for an agent')
78
+ .action(async (id) => {
79
+ try {
80
+ const sly = createClient();
81
+ const result = await sly.request(`/v1/agents/${id}/limits`);
82
+ output(result);
83
+ } catch (e: unknown) {
84
+ error((e as Error).message);
85
+ }
86
+ });
87
+
88
+ cmd
89
+ .command('transactions <id>')
90
+ .description('Get transaction history for an agent')
91
+ .option('--limit <limit>', 'Max results per page', parseInt)
92
+ .option('--offset <offset>', 'Offset for pagination', parseInt)
93
+ .option('--from <from>', 'Filter from date (ISO 8601)')
94
+ .option('--to <to>', 'Filter to date (ISO 8601)')
95
+ .action(async (id, opts) => {
96
+ try {
97
+ const sly = createClient();
98
+ const params = new URLSearchParams();
99
+ if (opts.limit) params.set('limit', String(opts.limit));
100
+ if (opts.offset) params.set('offset', String(opts.offset));
101
+ if (opts.from) params.set('from', opts.from);
102
+ if (opts.to) params.set('to', opts.to);
103
+ const qs = params.toString();
104
+ const result = await sly.request(`/v1/agents/${id}/transactions${qs ? `?${qs}` : ''}`);
105
+ output(result);
106
+ } catch (e: unknown) {
107
+ error((e as Error).message);
108
+ }
109
+ });
110
+ }