@hightop/cli 0.1.3 → 0.1.5
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 +4 -0
- package/dist/cli.js +7 -149
- package/dist/commandMetadata.d.ts +37 -0
- package/dist/commandMetadata.js +151 -0
- package/dist/simulatableEndpointKeys.d.ts +1 -0
- package/dist/simulatableEndpointKeys.js +23 -0
- package/package.json +2 -2
package/README.md
CHANGED
|
@@ -85,6 +85,8 @@ Examples:
|
|
|
85
85
|
hightop self --pretty
|
|
86
86
|
hightop balances --pretty
|
|
87
87
|
hightop operations get <operation-id> --include-onchain --pretty
|
|
88
|
+
hightop borrow collateral-options --pretty
|
|
89
|
+
hightop borrow collateral add --asset <option-id> --amount-usd 25 --simulate --pretty
|
|
88
90
|
hightop borrow repay --asset GREEN --amount-usd 25 --simulate --pretty
|
|
89
91
|
hightop one-off-payments create --to 0x... --asset USDC --amount-usd 25 --simulate --pretty
|
|
90
92
|
hightop webhooks create --url https://example.com/hook --event-types payment.executed,webhook.test --pretty
|
|
@@ -94,6 +96,8 @@ hightop raw GET /v1/agent/openapi.json --pretty
|
|
|
94
96
|
|
|
95
97
|
The generated command layer supports all catalogued `/v1/agent/*` endpoints. CLI flags are generated from endpoint query/body field names by converting underscores to dashes, for example `amount_usd` becomes `--amount-usd`.
|
|
96
98
|
|
|
99
|
+
For collateral, fetch `hightop borrow collateral-options` first and pass the returned option `id` as `--asset` to `hightop borrow collateral add`. Vault-backed options use the vault contract address as the option id.
|
|
100
|
+
|
|
97
101
|
For complex bodies, pass a JSON object:
|
|
98
102
|
|
|
99
103
|
```sh
|
package/dist/cli.js
CHANGED
|
@@ -2,6 +2,8 @@ import { readFileSync } from 'fs';
|
|
|
2
2
|
import { dirname, join } from 'path';
|
|
3
3
|
import { fileURLToPath } from 'url';
|
|
4
4
|
import { agentApiEndpoints, buildAgentApiPath, createIdempotencyKey, HightopAgentClient, HightopAgentOperationWaitTimeoutError, HightopAgentSDKError, } from '@hightop/sdk';
|
|
5
|
+
import { buildCliEndpointCommands, commandDisplayName, endpointCanSimulate as commandEndpointCanSimulate, endpointCanWait, KNOWN_BOOLEAN_REQUEST_FIELDS, requestFieldNames, } from './commandMetadata.js';
|
|
6
|
+
import { SIMULATABLE_ENDPOINT_KEYS } from './simulatableEndpointKeys.js';
|
|
5
7
|
class CliUsageError extends Error {
|
|
6
8
|
constructor(message) {
|
|
7
9
|
super(message);
|
|
@@ -22,18 +24,6 @@ class CliWriteError extends Error {
|
|
|
22
24
|
this.response = input.response;
|
|
23
25
|
}
|
|
24
26
|
}
|
|
25
|
-
const KNOWN_BOOLEAN_REQUEST_FIELDS = [
|
|
26
|
-
'allow_conversion',
|
|
27
|
-
'allow_partial',
|
|
28
|
-
'enabled',
|
|
29
|
-
'move_all',
|
|
30
|
-
'remove_all',
|
|
31
|
-
'repay_all',
|
|
32
|
-
'to_best_available',
|
|
33
|
-
'use_available_cash_first',
|
|
34
|
-
'use_best_available',
|
|
35
|
-
'withdraw_all',
|
|
36
|
-
];
|
|
37
27
|
const BOOLEAN_REQUEST_FIELDS = new Set(KNOWN_BOOLEAN_REQUEST_FIELDS);
|
|
38
28
|
const NULLABLE_REQUEST_FIELDS = new Set(['body', 'description', 'note']);
|
|
39
29
|
const BOOLEAN_FLAGS = new Set([
|
|
@@ -48,24 +38,6 @@ const BOOLEAN_FLAGS = new Set([
|
|
|
48
38
|
]);
|
|
49
39
|
const PACKAGE_JSON_PATH = join(dirname(fileURLToPath(import.meta.url)), '..', 'package.json');
|
|
50
40
|
const PUBLIC_NO_AUTH_CLI_ENDPOINT_KEYS = new Set(['GET /v1/agent/openapi.json', 'GET /v1/agent/capabilities.json']);
|
|
51
|
-
// Mirrors SIMULATED_WRITE_ROUTES in src/backend/agentApi/simulate.ts.
|
|
52
|
-
const SIMULATABLE_ENDPOINT_KEYS = new Set([
|
|
53
|
-
'POST /v1/agent/payments',
|
|
54
|
-
'POST /v1/agent/one-off-payments',
|
|
55
|
-
'POST /v1/agent/conversions/quote',
|
|
56
|
-
'POST /v1/agent/conversions',
|
|
57
|
-
'POST /v1/agent/earn/deposit',
|
|
58
|
-
'POST /v1/agent/earn/withdraw',
|
|
59
|
-
'POST /v1/agent/earn/move',
|
|
60
|
-
'POST /v1/agent/earn/rewards/claim',
|
|
61
|
-
'POST /v1/agent/borrow',
|
|
62
|
-
'POST /v1/agent/borrow/repay',
|
|
63
|
-
'POST /v1/agent/borrow/deleverage',
|
|
64
|
-
'POST /v1/agent/borrow/collateral/add',
|
|
65
|
-
'POST /v1/agent/borrow/collateral/remove',
|
|
66
|
-
'POST /v1/agent/withdrawals/to-bank',
|
|
67
|
-
'POST /v1/agent/withdrawals/to-crypto',
|
|
68
|
-
]);
|
|
69
41
|
function readCliVersion() {
|
|
70
42
|
return JSON.parse(readFileSync(PACKAGE_JSON_PATH, 'utf8')).version;
|
|
71
43
|
}
|
|
@@ -118,125 +90,11 @@ function hasFlag(parsed, name) {
|
|
|
118
90
|
function isRecord(value) {
|
|
119
91
|
return typeof value === 'object' && value !== null && !Array.isArray(value);
|
|
120
92
|
}
|
|
121
|
-
|
|
122
|
-
|
|
123
|
-
|
|
124
|
-
.split('/')
|
|
125
|
-
.filter(Boolean);
|
|
126
|
-
}
|
|
127
|
-
function endpointPathParamsAfterCommand(endpoint) {
|
|
128
|
-
return endpoint.pathParams.filter((param) => !endpoint.queryParams.includes(param) && !endpoint.bodyParams.includes(param));
|
|
129
|
-
}
|
|
130
|
-
function endpointCanWait(endpoint) {
|
|
131
|
-
return ['AgentApiWriteResponse', 'AgentApiX402SignResponse', 'AgentApiX402PurchaseResponse'].includes(endpoint.responseType ?? '');
|
|
132
|
-
}
|
|
93
|
+
const CLI_ENDPOINT_COMMANDS = buildCliEndpointCommands(agentApiEndpoints, {
|
|
94
|
+
simulatableEndpointKeys: SIMULATABLE_ENDPOINT_KEYS,
|
|
95
|
+
});
|
|
133
96
|
function endpointCanSimulate(endpoint) {
|
|
134
|
-
return
|
|
135
|
-
}
|
|
136
|
-
function commandUsage(commandPath, endpoint, pathParamsAfterCommand) {
|
|
137
|
-
const pathSuffix = pathParamsAfterCommand.map((param) => ` <${param}>`).join('');
|
|
138
|
-
const flags = [...endpoint.queryParams, ...endpoint.bodyParams]
|
|
139
|
-
.filter((param) => !endpoint.pathParams.includes(param))
|
|
140
|
-
.map((param) => ` [--${param.replace(/_/g, '-')} <value>]`)
|
|
141
|
-
.join('');
|
|
142
|
-
const waitFlag = endpointCanWait(endpoint) ? ' [--wait]' : '';
|
|
143
|
-
const simulateFlag = endpointCanSimulate(endpoint) ? ' [--simulate]' : '';
|
|
144
|
-
const submitFlags = endpoint.idempotencyRequired ? ` [--idempotency-key <key>]${waitFlag}${simulateFlag}` : '';
|
|
145
|
-
return `hightop ${commandPath.join(' ')}${pathSuffix}${flags}${submitFlags}`;
|
|
146
|
-
}
|
|
147
|
-
function commandFromEndpoint(endpoint) {
|
|
148
|
-
const segments = endpointSegments(endpoint);
|
|
149
|
-
const pathParamsAfterCommand = endpointPathParamsAfterCommand(endpoint);
|
|
150
|
-
const staticSegments = segments.filter((segment) => !segment.startsWith('{'));
|
|
151
|
-
if (endpoint.path === '/v1/agent/capabilities.json') {
|
|
152
|
-
return { commandPath: ['capabilities', 'json'], pathParamsAfterCommand };
|
|
153
|
-
}
|
|
154
|
-
if (endpoint.method === 'GET' && endpoint.pathParams.length === 0) {
|
|
155
|
-
return { commandPath: staticSegments, pathParamsAfterCommand };
|
|
156
|
-
}
|
|
157
|
-
if (endpoint.method === 'GET' && endpoint.pathParams.length > 0) {
|
|
158
|
-
const tail = staticSegments.slice(1);
|
|
159
|
-
if (tail.length > 0) {
|
|
160
|
-
return { commandPath: [staticSegments[0], ...tail], pathParamsAfterCommand };
|
|
161
|
-
}
|
|
162
|
-
return { commandPath: [staticSegments[0], 'get'], pathParamsAfterCommand };
|
|
163
|
-
}
|
|
164
|
-
if (endpoint.method === 'POST') {
|
|
165
|
-
if (endpoint.pathParams.length > 0) {
|
|
166
|
-
return { commandPath: staticSegments, pathParamsAfterCommand };
|
|
167
|
-
}
|
|
168
|
-
if (staticSegments.length === 1) {
|
|
169
|
-
if (staticSegments[0] === 'conversions') {
|
|
170
|
-
return { commandPath: ['conversions', 'execute'], pathParamsAfterCommand };
|
|
171
|
-
}
|
|
172
|
-
return { commandPath: [staticSegments[0], 'create'], pathParamsAfterCommand };
|
|
173
|
-
}
|
|
174
|
-
return { commandPath: staticSegments, pathParamsAfterCommand };
|
|
175
|
-
}
|
|
176
|
-
if (endpoint.method === 'PATCH') {
|
|
177
|
-
return { commandPath: [staticSegments[0], 'update'], pathParamsAfterCommand };
|
|
178
|
-
}
|
|
179
|
-
if (endpoint.method === 'DELETE') {
|
|
180
|
-
return { commandPath: [staticSegments[0], 'delete'], pathParamsAfterCommand };
|
|
181
|
-
}
|
|
182
|
-
return { commandPath: staticSegments, pathParamsAfterCommand };
|
|
183
|
-
}
|
|
184
|
-
function buildCliEndpointCommands() {
|
|
185
|
-
const commands = agentApiEndpoints
|
|
186
|
-
.filter((endpoint) => endpoint.key !== 'POST /v1/agent/simulate')
|
|
187
|
-
.flatMap((endpoint) => {
|
|
188
|
-
const primary = commandFromEndpoint(endpoint);
|
|
189
|
-
const aliases = [primary];
|
|
190
|
-
if (endpoint.key === 'GET /v1/agent/self/usage') {
|
|
191
|
-
aliases.push({ commandPath: ['usage'], pathParamsAfterCommand: [] });
|
|
192
|
-
}
|
|
193
|
-
if (endpoint.method === 'GET' &&
|
|
194
|
-
endpoint.pathParams.length === 0 &&
|
|
195
|
-
endpoint.queryParams.some((param) => param === 'cursor' || param === 'limit')) {
|
|
196
|
-
aliases.push({ commandPath: [...primary.commandPath, 'list'], pathParamsAfterCommand: [] });
|
|
197
|
-
}
|
|
198
|
-
return aliases.map((alias) => ({
|
|
199
|
-
commandPath: alias.commandPath,
|
|
200
|
-
endpoint,
|
|
201
|
-
pathParamsAfterCommand: alias.pathParamsAfterCommand,
|
|
202
|
-
usage: commandUsage(alias.commandPath, endpoint, alias.pathParamsAfterCommand),
|
|
203
|
-
}));
|
|
204
|
-
});
|
|
205
|
-
commands.push({
|
|
206
|
-
commandPath: ['openapi'],
|
|
207
|
-
endpoint: {
|
|
208
|
-
bodyParams: [],
|
|
209
|
-
bodySchema: null,
|
|
210
|
-
description: 'Return the public Agent API OpenAPI document.',
|
|
211
|
-
idempotencyRequired: false,
|
|
212
|
-
key: 'GET /v1/agent/openapi.json',
|
|
213
|
-
method: 'GET',
|
|
214
|
-
path: '/v1/agent/openapi.json',
|
|
215
|
-
pathParams: [],
|
|
216
|
-
queryParams: [],
|
|
217
|
-
requestSchema: null,
|
|
218
|
-
requestType: null,
|
|
219
|
-
responseSchema: null,
|
|
220
|
-
responseType: null,
|
|
221
|
-
routeClass: 'read',
|
|
222
|
-
},
|
|
223
|
-
pathParamsAfterCommand: [],
|
|
224
|
-
usage: 'hightop openapi',
|
|
225
|
-
});
|
|
226
|
-
const seen = new Set();
|
|
227
|
-
return commands.filter((command) => {
|
|
228
|
-
const key = command.commandPath.join(' ');
|
|
229
|
-
if (seen.has(key)) {
|
|
230
|
-
return false;
|
|
231
|
-
}
|
|
232
|
-
seen.add(key);
|
|
233
|
-
return true;
|
|
234
|
-
});
|
|
235
|
-
}
|
|
236
|
-
const CLI_ENDPOINT_COMMANDS = buildCliEndpointCommands();
|
|
237
|
-
function commandDisplayName(command) {
|
|
238
|
-
const suffix = command.pathParamsAfterCommand.map((param) => ` <${param}>`).join('');
|
|
239
|
-
return `${command.commandPath.join(' ')}${suffix}`;
|
|
97
|
+
return commandEndpointCanSimulate(endpoint, SIMULATABLE_ENDPOINT_KEYS);
|
|
240
98
|
}
|
|
241
99
|
function formatGlobalHelp() {
|
|
242
100
|
const commandLines = CLI_ENDPOINT_COMMANDS.map((command) => ({
|
|
@@ -292,7 +150,7 @@ function formatCommandHelp(commandPath) {
|
|
|
292
150
|
const exact = matches.find((command) => command.commandPath.length === commandPath.length);
|
|
293
151
|
if (exact && matches.length === 1) {
|
|
294
152
|
const endpoint = exact.endpoint;
|
|
295
|
-
const requestFlags =
|
|
153
|
+
const requestFlags = requestFieldNames(endpoint);
|
|
296
154
|
const flagLines = requestFlags.length > 0
|
|
297
155
|
? `\nRequest flags:\n${requestFlags.map((param) => ` --${param.replace(/_/g, '-')} <value>`).join('\n')}\n`
|
|
298
156
|
: '';
|
|
@@ -0,0 +1,37 @@
|
|
|
1
|
+
export type CliEndpointMetadata = {
|
|
2
|
+
readonly key: string;
|
|
3
|
+
readonly method: string;
|
|
4
|
+
readonly path: string;
|
|
5
|
+
readonly pathParams: readonly string[];
|
|
6
|
+
readonly queryParams: readonly string[];
|
|
7
|
+
readonly bodyParams: readonly string[];
|
|
8
|
+
readonly requestSchema: string | null;
|
|
9
|
+
readonly bodySchema: string | null;
|
|
10
|
+
readonly responseSchema: string | null;
|
|
11
|
+
readonly requestType: string | null;
|
|
12
|
+
readonly responseType: string | null;
|
|
13
|
+
readonly idempotencyRequired: boolean;
|
|
14
|
+
readonly routeClass: string;
|
|
15
|
+
readonly description: string;
|
|
16
|
+
};
|
|
17
|
+
export type CliEndpointCommand = {
|
|
18
|
+
commandPath: string[];
|
|
19
|
+
endpoint: CliEndpointMetadata;
|
|
20
|
+
pathParamsAfterCommand: string[];
|
|
21
|
+
requestFlags: string[];
|
|
22
|
+
usage: string;
|
|
23
|
+
canSimulate: boolean;
|
|
24
|
+
canWait: boolean;
|
|
25
|
+
};
|
|
26
|
+
type BuildCliEndpointCommandOptions = {
|
|
27
|
+
simulatableEndpointKeys: ReadonlySet<string>;
|
|
28
|
+
};
|
|
29
|
+
export declare const KNOWN_BOOLEAN_REQUEST_FIELDS: readonly ["allow_conversion", "allow_partial", "enabled", "move_all", "remove_all", "repay_all", "to_best_available", "use_available_cash_first", "use_best_available", "withdraw_all"];
|
|
30
|
+
export declare function flagNameForField(field: string): string;
|
|
31
|
+
export declare function requestFieldNames(endpoint: CliEndpointMetadata): string[];
|
|
32
|
+
export declare function requestFlags(endpoint: CliEndpointMetadata): string[];
|
|
33
|
+
export declare function endpointCanWait(endpoint: CliEndpointMetadata): boolean;
|
|
34
|
+
export declare function endpointCanSimulate(endpoint: CliEndpointMetadata, simulatableEndpointKeys: ReadonlySet<string>): boolean;
|
|
35
|
+
export declare function commandDisplayName(command: Pick<CliEndpointCommand, 'commandPath' | 'pathParamsAfterCommand'>): string;
|
|
36
|
+
export declare function buildCliEndpointCommands(metadata: readonly CliEndpointMetadata[], options: BuildCliEndpointCommandOptions): CliEndpointCommand[];
|
|
37
|
+
export {};
|
|
@@ -0,0 +1,151 @@
|
|
|
1
|
+
export const KNOWN_BOOLEAN_REQUEST_FIELDS = [
|
|
2
|
+
'allow_conversion',
|
|
3
|
+
'allow_partial',
|
|
4
|
+
'enabled',
|
|
5
|
+
'move_all',
|
|
6
|
+
'remove_all',
|
|
7
|
+
'repay_all',
|
|
8
|
+
'to_best_available',
|
|
9
|
+
'use_available_cash_first',
|
|
10
|
+
'use_best_available',
|
|
11
|
+
'withdraw_all',
|
|
12
|
+
];
|
|
13
|
+
export function flagNameForField(field) {
|
|
14
|
+
return field.replace(/_/g, '-');
|
|
15
|
+
}
|
|
16
|
+
export function requestFieldNames(endpoint) {
|
|
17
|
+
return [...endpoint.queryParams, ...endpoint.bodyParams].filter((param) => !endpoint.pathParams.includes(param));
|
|
18
|
+
}
|
|
19
|
+
export function requestFlags(endpoint) {
|
|
20
|
+
return requestFieldNames(endpoint).map((param) => `--${flagNameForField(param)}`);
|
|
21
|
+
}
|
|
22
|
+
export function endpointCanWait(endpoint) {
|
|
23
|
+
return ['AgentApiWriteResponse', 'AgentApiX402SignResponse', 'AgentApiX402PurchaseResponse'].includes(endpoint.responseType ?? '');
|
|
24
|
+
}
|
|
25
|
+
export function endpointCanSimulate(endpoint, simulatableEndpointKeys) {
|
|
26
|
+
return simulatableEndpointKeys.has(endpoint.key);
|
|
27
|
+
}
|
|
28
|
+
export function commandDisplayName(command) {
|
|
29
|
+
const suffix = command.pathParamsAfterCommand.map((param) => ` <${param}>`).join('');
|
|
30
|
+
return `${command.commandPath.join(' ')}${suffix}`;
|
|
31
|
+
}
|
|
32
|
+
function endpointSegments(endpoint) {
|
|
33
|
+
return endpoint.path
|
|
34
|
+
.replace(/^\/v1\/agent\/?/, '')
|
|
35
|
+
.split('/')
|
|
36
|
+
.filter(Boolean);
|
|
37
|
+
}
|
|
38
|
+
function endpointPathParamsAfterCommand(endpoint) {
|
|
39
|
+
return endpoint.pathParams.filter((param) => !endpoint.queryParams.includes(param) && !endpoint.bodyParams.includes(param));
|
|
40
|
+
}
|
|
41
|
+
function commandUsage(commandPath, endpoint, pathParamsAfterCommand, options) {
|
|
42
|
+
const pathSuffix = pathParamsAfterCommand.map((param) => ` <${param}>`).join('');
|
|
43
|
+
const flags = requestFlags(endpoint)
|
|
44
|
+
.map((flag) => ` [${flag} <value>]`)
|
|
45
|
+
.join('');
|
|
46
|
+
const waitFlag = endpointCanWait(endpoint) ? ' [--wait]' : '';
|
|
47
|
+
const simulateFlag = endpointCanSimulate(endpoint, options.simulatableEndpointKeys) ? ' [--simulate]' : '';
|
|
48
|
+
const submitFlags = endpoint.idempotencyRequired ? ` [--idempotency-key <key>]${waitFlag}${simulateFlag}` : '';
|
|
49
|
+
return `hightop ${commandPath.join(' ')}${pathSuffix}${flags}${submitFlags}`;
|
|
50
|
+
}
|
|
51
|
+
function commandFromEndpoint(endpoint) {
|
|
52
|
+
const segments = endpointSegments(endpoint);
|
|
53
|
+
const pathParamsAfterCommand = endpointPathParamsAfterCommand(endpoint);
|
|
54
|
+
const staticSegments = segments.filter((segment) => !segment.startsWith('{'));
|
|
55
|
+
if (endpoint.path === '/v1/agent/capabilities.json') {
|
|
56
|
+
return { commandPath: ['capabilities', 'json'], pathParamsAfterCommand };
|
|
57
|
+
}
|
|
58
|
+
if (endpoint.method === 'GET' && endpoint.pathParams.length === 0) {
|
|
59
|
+
return { commandPath: staticSegments, pathParamsAfterCommand };
|
|
60
|
+
}
|
|
61
|
+
if (endpoint.method === 'GET' && endpoint.pathParams.length > 0) {
|
|
62
|
+
const tail = staticSegments.slice(1);
|
|
63
|
+
if (tail.length > 0) {
|
|
64
|
+
return { commandPath: [staticSegments[0], ...tail], pathParamsAfterCommand };
|
|
65
|
+
}
|
|
66
|
+
return { commandPath: [staticSegments[0], 'get'], pathParamsAfterCommand };
|
|
67
|
+
}
|
|
68
|
+
if (endpoint.method === 'POST') {
|
|
69
|
+
if (endpoint.pathParams.length > 0) {
|
|
70
|
+
return { commandPath: staticSegments, pathParamsAfterCommand };
|
|
71
|
+
}
|
|
72
|
+
if (staticSegments.length === 1) {
|
|
73
|
+
if (staticSegments[0] === 'conversions') {
|
|
74
|
+
return { commandPath: ['conversions', 'execute'], pathParamsAfterCommand };
|
|
75
|
+
}
|
|
76
|
+
return { commandPath: [staticSegments[0], 'create'], pathParamsAfterCommand };
|
|
77
|
+
}
|
|
78
|
+
return { commandPath: staticSegments, pathParamsAfterCommand };
|
|
79
|
+
}
|
|
80
|
+
if (endpoint.method === 'PATCH') {
|
|
81
|
+
return { commandPath: [staticSegments[0], 'update'], pathParamsAfterCommand };
|
|
82
|
+
}
|
|
83
|
+
if (endpoint.method === 'DELETE') {
|
|
84
|
+
return { commandPath: [staticSegments[0], 'delete'], pathParamsAfterCommand };
|
|
85
|
+
}
|
|
86
|
+
return { commandPath: staticSegments, pathParamsAfterCommand };
|
|
87
|
+
}
|
|
88
|
+
function openApiEndpoint() {
|
|
89
|
+
return {
|
|
90
|
+
bodyParams: [],
|
|
91
|
+
bodySchema: null,
|
|
92
|
+
description: 'Return the public Agent API OpenAPI document.',
|
|
93
|
+
idempotencyRequired: false,
|
|
94
|
+
key: 'GET /v1/agent/openapi.json',
|
|
95
|
+
method: 'GET',
|
|
96
|
+
path: '/v1/agent/openapi.json',
|
|
97
|
+
pathParams: [],
|
|
98
|
+
queryParams: [],
|
|
99
|
+
requestSchema: null,
|
|
100
|
+
requestType: null,
|
|
101
|
+
responseSchema: null,
|
|
102
|
+
responseType: null,
|
|
103
|
+
routeClass: 'read',
|
|
104
|
+
};
|
|
105
|
+
}
|
|
106
|
+
export function buildCliEndpointCommands(metadata, options) {
|
|
107
|
+
const commands = metadata
|
|
108
|
+
.filter((endpoint) => endpoint.key !== 'POST /v1/agent/simulate')
|
|
109
|
+
.flatMap((endpoint) => {
|
|
110
|
+
const primary = commandFromEndpoint(endpoint);
|
|
111
|
+
const aliases = [primary];
|
|
112
|
+
if (endpoint.key === 'GET /v1/agent/self/usage') {
|
|
113
|
+
aliases.push({ commandPath: ['usage'], pathParamsAfterCommand: [] });
|
|
114
|
+
}
|
|
115
|
+
if (endpoint.method === 'GET' &&
|
|
116
|
+
endpoint.pathParams.length === 0 &&
|
|
117
|
+
endpoint.queryParams.some((param) => param === 'cursor' || param === 'limit')) {
|
|
118
|
+
aliases.push({ commandPath: [...primary.commandPath, 'list'], pathParamsAfterCommand: [] });
|
|
119
|
+
}
|
|
120
|
+
return aliases.map((alias) => ({
|
|
121
|
+
commandPath: alias.commandPath,
|
|
122
|
+
endpoint,
|
|
123
|
+
pathParamsAfterCommand: alias.pathParamsAfterCommand,
|
|
124
|
+
requestFlags: requestFlags(endpoint),
|
|
125
|
+
usage: commandUsage(alias.commandPath, endpoint, alias.pathParamsAfterCommand, options),
|
|
126
|
+
canSimulate: endpointCanSimulate(endpoint, options.simulatableEndpointKeys),
|
|
127
|
+
canWait: endpointCanWait(endpoint),
|
|
128
|
+
}));
|
|
129
|
+
});
|
|
130
|
+
const openapi = openApiEndpoint();
|
|
131
|
+
commands.push({
|
|
132
|
+
commandPath: ['openapi'],
|
|
133
|
+
endpoint: openapi,
|
|
134
|
+
pathParamsAfterCommand: [],
|
|
135
|
+
requestFlags: [],
|
|
136
|
+
usage: 'hightop openapi',
|
|
137
|
+
canSimulate: false,
|
|
138
|
+
canWait: false,
|
|
139
|
+
});
|
|
140
|
+
const seen = new Set();
|
|
141
|
+
return commands
|
|
142
|
+
.filter((command) => {
|
|
143
|
+
const key = command.commandPath.join(' ');
|
|
144
|
+
if (seen.has(key)) {
|
|
145
|
+
return false;
|
|
146
|
+
}
|
|
147
|
+
seen.add(key);
|
|
148
|
+
return true;
|
|
149
|
+
})
|
|
150
|
+
.sort((a, b) => commandDisplayName(a).localeCompare(commandDisplayName(b)));
|
|
151
|
+
}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
export declare const SIMULATABLE_ENDPOINT_KEYS: ReadonlySet<string>;
|
|
@@ -0,0 +1,23 @@
|
|
|
1
|
+
// CLI-supported write routes that may be routed through POST /v1/agent/simulate.
|
|
2
|
+
// Keep this in sync with compatible entries in src/backend/agentApi/simulate.ts.
|
|
3
|
+
const SIMULATABLE_ENDPOINT_KEY_VALUES = [
|
|
4
|
+
'POST /v1/agent/payments',
|
|
5
|
+
'POST /v1/agent/one-off-payments',
|
|
6
|
+
'POST /v1/agent/conversions/quote',
|
|
7
|
+
'POST /v1/agent/conversions',
|
|
8
|
+
'POST /v1/agent/earn/deposit',
|
|
9
|
+
'POST /v1/agent/earn/withdraw',
|
|
10
|
+
'POST /v1/agent/earn/move',
|
|
11
|
+
'POST /v1/agent/earn/rewards/claim',
|
|
12
|
+
'POST /v1/agent/borrow',
|
|
13
|
+
'POST /v1/agent/borrow/repay',
|
|
14
|
+
'POST /v1/agent/borrow/deleverage',
|
|
15
|
+
'POST /v1/agent/borrow/collateral/add',
|
|
16
|
+
'POST /v1/agent/borrow/collateral/remove',
|
|
17
|
+
'POST /v1/agent/withdrawals/to-bank',
|
|
18
|
+
'POST /v1/agent/withdrawals/to-crypto',
|
|
19
|
+
'POST /v1/agent/trusted-destinations/{id}/confirm',
|
|
20
|
+
'POST /v1/agent/trusted-destinations/{id}/cancel',
|
|
21
|
+
'DELETE /v1/agent/trusted-destinations/{id}',
|
|
22
|
+
];
|
|
23
|
+
export const SIMULATABLE_ENDPOINT_KEYS = new Set(SIMULATABLE_ENDPOINT_KEY_VALUES);
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@hightop/cli",
|
|
3
|
-
"version": "0.1.
|
|
3
|
+
"version": "0.1.5",
|
|
4
4
|
"license": "MIT",
|
|
5
5
|
"type": "module",
|
|
6
6
|
"bin": {
|
|
@@ -41,6 +41,6 @@
|
|
|
41
41
|
"test": "vitest run --config vitest.config.ts"
|
|
42
42
|
},
|
|
43
43
|
"dependencies": {
|
|
44
|
-
"@hightop/sdk": "0.1.
|
|
44
|
+
"@hightop/sdk": "0.1.5"
|
|
45
45
|
}
|
|
46
46
|
}
|