enton-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/README.md +188 -0
- package/bin/enton.js +34 -0
- package/dist/api/client.d.ts +61 -0
- package/dist/api/client.js +160 -0
- package/dist/commands/auth.d.ts +5 -0
- package/dist/commands/auth.js +156 -0
- package/dist/commands/config.d.ts +5 -0
- package/dist/commands/config.js +96 -0
- package/dist/commands/interactive.d.ts +7 -0
- package/dist/commands/interactive.js +143 -0
- package/dist/commands/query.d.ts +8 -0
- package/dist/commands/query.js +73 -0
- package/dist/commands/watch.d.ts +5 -0
- package/dist/commands/watch.js +98 -0
- package/dist/config/manager.d.ts +54 -0
- package/dist/config/manager.js +168 -0
- package/dist/index.d.ts +11 -0
- package/dist/index.js +104 -0
- package/package.json +65 -0
|
@@ -0,0 +1,96 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
/**
|
|
3
|
+
* Config Command - Manage CLI configuration
|
|
4
|
+
*/
|
|
5
|
+
var __importDefault = (this && this.__importDefault) || function (mod) {
|
|
6
|
+
return (mod && mod.__esModule) ? mod : { "default": mod };
|
|
7
|
+
};
|
|
8
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
9
|
+
exports.configCommand = configCommand;
|
|
10
|
+
const chalk_1 = __importDefault(require("chalk"));
|
|
11
|
+
const cli_table3_1 = __importDefault(require("cli-table3"));
|
|
12
|
+
const manager_1 = require("../config/manager");
|
|
13
|
+
async function configCommand(action, key, value) {
|
|
14
|
+
switch (action) {
|
|
15
|
+
case 'set':
|
|
16
|
+
if (!key || !value) {
|
|
17
|
+
console.log(chalk_1.default.red('Error: Both key and value are required\n'));
|
|
18
|
+
showConfigHelp();
|
|
19
|
+
return;
|
|
20
|
+
}
|
|
21
|
+
await setConfigValue(key, value);
|
|
22
|
+
break;
|
|
23
|
+
case 'get':
|
|
24
|
+
if (!key) {
|
|
25
|
+
console.log(chalk_1.default.red('Error: Key is required\n'));
|
|
26
|
+
showConfigHelp();
|
|
27
|
+
return;
|
|
28
|
+
}
|
|
29
|
+
await getConfigSingle(key);
|
|
30
|
+
break;
|
|
31
|
+
case 'list':
|
|
32
|
+
await listAllConfig();
|
|
33
|
+
break;
|
|
34
|
+
}
|
|
35
|
+
}
|
|
36
|
+
async function setConfigValue(key, value) {
|
|
37
|
+
const validKeys = ['apiUrl', 'defaultAccount', 'outputFormat', 'theme'];
|
|
38
|
+
if (!validKeys.includes(key)) {
|
|
39
|
+
console.log(chalk_1.default.red(`\nError: Unknown config key "${key}"\n`));
|
|
40
|
+
console.log(chalk_1.default.dim('Valid keys: ' + validKeys.join(', ')));
|
|
41
|
+
return;
|
|
42
|
+
}
|
|
43
|
+
// Validate specific values
|
|
44
|
+
if (key === 'outputFormat' && !['text', 'json'].includes(value)) {
|
|
45
|
+
console.log(chalk_1.default.red('\nError: outputFormat must be "text" or "json"\n'));
|
|
46
|
+
return;
|
|
47
|
+
}
|
|
48
|
+
if (key === 'theme' && !['light', 'dark'].includes(value)) {
|
|
49
|
+
console.log(chalk_1.default.red('\nError: theme must be "light" or "dark"\n'));
|
|
50
|
+
return;
|
|
51
|
+
}
|
|
52
|
+
(0, manager_1.setConfig)(key, value);
|
|
53
|
+
console.log(chalk_1.default.green(`\n✅ Set ${key} = ${value}\n`));
|
|
54
|
+
}
|
|
55
|
+
async function getConfigSingle(key) {
|
|
56
|
+
const value = (0, manager_1.getConfigValue)(key);
|
|
57
|
+
if (value === undefined) {
|
|
58
|
+
console.log(chalk_1.default.yellow(`\n⚠️ Config key "${key}" is not set\n`));
|
|
59
|
+
}
|
|
60
|
+
else {
|
|
61
|
+
console.log(`\n${chalk_1.default.bold(key)}: ${chalk_1.default.cyan(String(value))}\n`);
|
|
62
|
+
}
|
|
63
|
+
}
|
|
64
|
+
async function listAllConfig() {
|
|
65
|
+
const config = (0, manager_1.listConfig)();
|
|
66
|
+
console.log(chalk_1.default.bold('\n⚙️ ENTON CLI Configuration\n'));
|
|
67
|
+
const table = new cli_table3_1.default({
|
|
68
|
+
head: [chalk_1.default.bold('Key'), chalk_1.default.bold('Value')],
|
|
69
|
+
style: {
|
|
70
|
+
head: [],
|
|
71
|
+
border: ['dim']
|
|
72
|
+
}
|
|
73
|
+
});
|
|
74
|
+
for (const [key, value] of Object.entries(config)) {
|
|
75
|
+
table.push([
|
|
76
|
+
key,
|
|
77
|
+
value !== undefined ? chalk_1.default.cyan(String(value)) : chalk_1.default.dim('(not set)')
|
|
78
|
+
]);
|
|
79
|
+
}
|
|
80
|
+
console.log(table.toString());
|
|
81
|
+
console.log(chalk_1.default.dim('\nUse `enton config set <key> <value>` to change values\n'));
|
|
82
|
+
}
|
|
83
|
+
function showConfigHelp() {
|
|
84
|
+
console.log(chalk_1.default.bold('Usage:'));
|
|
85
|
+
console.log(' enton config set <key> <value>');
|
|
86
|
+
console.log(' enton config get <key>');
|
|
87
|
+
console.log(' enton config list');
|
|
88
|
+
console.log('');
|
|
89
|
+
console.log(chalk_1.default.bold('Available Keys:'));
|
|
90
|
+
console.log(' apiUrl - ENTON API URL (default: https://enton.ai)');
|
|
91
|
+
console.log(' defaultAccount - Default trading account to use');
|
|
92
|
+
console.log(' outputFormat - Output format: text | json');
|
|
93
|
+
console.log(' theme - Color theme: light | dark');
|
|
94
|
+
console.log('');
|
|
95
|
+
}
|
|
96
|
+
exports.default = configCommand;
|
|
@@ -0,0 +1,143 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
/**
|
|
3
|
+
* Interactive Mode - REPL-style chat with ENTON
|
|
4
|
+
*/
|
|
5
|
+
var __importDefault = (this && this.__importDefault) || function (mod) {
|
|
6
|
+
return (mod && mod.__esModule) ? mod : { "default": mod };
|
|
7
|
+
};
|
|
8
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
9
|
+
exports.interactiveMode = interactiveMode;
|
|
10
|
+
const chalk_1 = __importDefault(require("chalk"));
|
|
11
|
+
const ora_1 = __importDefault(require("ora"));
|
|
12
|
+
const inquirer_1 = __importDefault(require("inquirer"));
|
|
13
|
+
const client_1 = require("../api/client");
|
|
14
|
+
const manager_1 = require("../config/manager");
|
|
15
|
+
async function interactiveMode(options) {
|
|
16
|
+
const config = (0, manager_1.getConfig)();
|
|
17
|
+
const client = new client_1.EntonAPIClient(config.apiUrl, config.apiKey);
|
|
18
|
+
console.log(chalk_1.default.dim('Type your questions or commands. Type "exit" to quit.\n'));
|
|
19
|
+
while (true) {
|
|
20
|
+
const { input } = await inquirer_1.default.prompt([
|
|
21
|
+
{
|
|
22
|
+
type: 'input',
|
|
23
|
+
name: 'input',
|
|
24
|
+
message: chalk_1.default.cyan('>'),
|
|
25
|
+
prefix: ''
|
|
26
|
+
}
|
|
27
|
+
]);
|
|
28
|
+
const trimmed = input.trim();
|
|
29
|
+
// Handle exit commands
|
|
30
|
+
if (['exit', 'quit', 'q', ':q'].includes(trimmed.toLowerCase())) {
|
|
31
|
+
console.log(chalk_1.default.dim('\nGoodbye! 👋\n'));
|
|
32
|
+
break;
|
|
33
|
+
}
|
|
34
|
+
// Handle empty input
|
|
35
|
+
if (!trimmed) {
|
|
36
|
+
continue;
|
|
37
|
+
}
|
|
38
|
+
// Handle special commands
|
|
39
|
+
if (trimmed.startsWith('/')) {
|
|
40
|
+
await handleCommand(trimmed.slice(1), client);
|
|
41
|
+
continue;
|
|
42
|
+
}
|
|
43
|
+
// Send query to ENTON
|
|
44
|
+
await executeQuery(trimmed, client, options);
|
|
45
|
+
}
|
|
46
|
+
}
|
|
47
|
+
async function executeQuery(query, client, options) {
|
|
48
|
+
const spinner = (0, ora_1.default)({
|
|
49
|
+
text: chalk_1.default.dim('Thinking...'),
|
|
50
|
+
color: 'cyan'
|
|
51
|
+
}).start();
|
|
52
|
+
try {
|
|
53
|
+
const response = await client.query(query, {
|
|
54
|
+
onThinking: (message) => {
|
|
55
|
+
spinner.text = chalk_1.default.dim(message);
|
|
56
|
+
},
|
|
57
|
+
onToolStart: (tool, args) => {
|
|
58
|
+
spinner.text = chalk_1.default.yellow(`🔧 ${tool}`);
|
|
59
|
+
},
|
|
60
|
+
onToolResult: (tool, success) => {
|
|
61
|
+
if (success) {
|
|
62
|
+
spinner.text = chalk_1.default.green(`✅ ${tool}`);
|
|
63
|
+
}
|
|
64
|
+
else {
|
|
65
|
+
spinner.text = chalk_1.default.red(`❌ ${tool} failed`);
|
|
66
|
+
}
|
|
67
|
+
}
|
|
68
|
+
});
|
|
69
|
+
spinner.stop();
|
|
70
|
+
if (options.json) {
|
|
71
|
+
console.log(JSON.stringify(response, null, 2));
|
|
72
|
+
}
|
|
73
|
+
else {
|
|
74
|
+
console.log('\n' + formatResponse(response) + '\n');
|
|
75
|
+
}
|
|
76
|
+
}
|
|
77
|
+
catch (error) {
|
|
78
|
+
spinner.fail(chalk_1.default.red('Error'));
|
|
79
|
+
console.log(chalk_1.default.red(` ${error.message}\n`));
|
|
80
|
+
}
|
|
81
|
+
}
|
|
82
|
+
function formatResponse(response) {
|
|
83
|
+
let output = '';
|
|
84
|
+
// Main answer
|
|
85
|
+
if (response.answer) {
|
|
86
|
+
output += chalk_1.default.white(response.answer);
|
|
87
|
+
}
|
|
88
|
+
// Show tools used
|
|
89
|
+
if (response.toolsUsed && response.toolsUsed.length > 0) {
|
|
90
|
+
output += chalk_1.default.dim(`\n\n📊 Tools: ${response.toolsUsed.join(', ')}`);
|
|
91
|
+
}
|
|
92
|
+
// Show timing
|
|
93
|
+
if (response.totalTime) {
|
|
94
|
+
output += chalk_1.default.dim(` | ${response.totalTime}ms`);
|
|
95
|
+
}
|
|
96
|
+
return output;
|
|
97
|
+
}
|
|
98
|
+
async function handleCommand(command, client) {
|
|
99
|
+
const [cmd, ...args] = command.split(' ');
|
|
100
|
+
switch (cmd.toLowerCase()) {
|
|
101
|
+
case 'help':
|
|
102
|
+
showHelp();
|
|
103
|
+
break;
|
|
104
|
+
case 'clear':
|
|
105
|
+
console.clear();
|
|
106
|
+
break;
|
|
107
|
+
case 'history':
|
|
108
|
+
console.log(chalk_1.default.dim('Command history not yet implemented'));
|
|
109
|
+
break;
|
|
110
|
+
case 'status':
|
|
111
|
+
await showStatus(client);
|
|
112
|
+
break;
|
|
113
|
+
default:
|
|
114
|
+
console.log(chalk_1.default.yellow(`Unknown command: /${cmd}`));
|
|
115
|
+
console.log(chalk_1.default.dim('Type /help for available commands'));
|
|
116
|
+
}
|
|
117
|
+
}
|
|
118
|
+
function showHelp() {
|
|
119
|
+
console.log(`
|
|
120
|
+
${chalk_1.default.bold('Available Commands:')}
|
|
121
|
+
${chalk_1.default.cyan('/help')} - Show this help message
|
|
122
|
+
${chalk_1.default.cyan('/clear')} - Clear the screen
|
|
123
|
+
${chalk_1.default.cyan('/status')} - Show connection status
|
|
124
|
+
${chalk_1.default.cyan('/history')} - Show command history
|
|
125
|
+
|
|
126
|
+
${chalk_1.default.bold('Query Examples:')}
|
|
127
|
+
${chalk_1.default.dim('What is the price of AAPL?')}
|
|
128
|
+
${chalk_1.default.dim('Get me news about Tesla')}
|
|
129
|
+
${chalk_1.default.dim('Analyze NVDA stock')}
|
|
130
|
+
${chalk_1.default.dim('Show my portfolio')}
|
|
131
|
+
${chalk_1.default.dim('Buy 10 shares of MSFT')}
|
|
132
|
+
|
|
133
|
+
${chalk_1.default.bold('Exit:')}
|
|
134
|
+
Type ${chalk_1.default.cyan('exit')}, ${chalk_1.default.cyan('quit')}, or ${chalk_1.default.cyan('q')}
|
|
135
|
+
`);
|
|
136
|
+
}
|
|
137
|
+
async function showStatus(client) {
|
|
138
|
+
console.log(`
|
|
139
|
+
${chalk_1.default.bold('Connection Status:')}
|
|
140
|
+
API URL: ${chalk_1.default.cyan(client.baseUrl)}
|
|
141
|
+
Auth: ${client.isAuthenticated() ? chalk_1.default.green('✅ Connected') : chalk_1.default.yellow('⚠️ Not authenticated')}
|
|
142
|
+
`);
|
|
143
|
+
}
|
|
@@ -0,0 +1,73 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
/**
|
|
3
|
+
* Query Command - Direct single query mode
|
|
4
|
+
*/
|
|
5
|
+
var __importDefault = (this && this.__importDefault) || function (mod) {
|
|
6
|
+
return (mod && mod.__esModule) ? mod : { "default": mod };
|
|
7
|
+
};
|
|
8
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
9
|
+
exports.queryCommand = queryCommand;
|
|
10
|
+
const chalk_1 = __importDefault(require("chalk"));
|
|
11
|
+
const ora_1 = __importDefault(require("ora"));
|
|
12
|
+
const client_1 = require("../api/client");
|
|
13
|
+
const manager_1 = require("../config/manager");
|
|
14
|
+
async function queryCommand(query, options) {
|
|
15
|
+
const config = (0, manager_1.getConfig)();
|
|
16
|
+
const client = new client_1.EntonAPIClient(config.apiUrl, config.apiKey);
|
|
17
|
+
const spinner = (0, ora_1.default)({
|
|
18
|
+
text: chalk_1.default.dim('Thinking...'),
|
|
19
|
+
color: 'cyan'
|
|
20
|
+
}).start();
|
|
21
|
+
try {
|
|
22
|
+
const response = await client.query(query, {
|
|
23
|
+
onThinking: (message) => {
|
|
24
|
+
spinner.text = chalk_1.default.dim(message);
|
|
25
|
+
},
|
|
26
|
+
onToolStart: (tool, args) => {
|
|
27
|
+
spinner.text = chalk_1.default.yellow(`🔧 ${tool}`);
|
|
28
|
+
},
|
|
29
|
+
onToolResult: (tool, success) => {
|
|
30
|
+
if (success) {
|
|
31
|
+
spinner.text = chalk_1.default.green(`✅ ${tool}`);
|
|
32
|
+
}
|
|
33
|
+
else {
|
|
34
|
+
spinner.text = chalk_1.default.red(`❌ ${tool} failed`);
|
|
35
|
+
}
|
|
36
|
+
}
|
|
37
|
+
});
|
|
38
|
+
spinner.stop();
|
|
39
|
+
if (options.json) {
|
|
40
|
+
console.log(JSON.stringify(response, null, 2));
|
|
41
|
+
}
|
|
42
|
+
else {
|
|
43
|
+
console.log('\n' + formatResponse(response) + '\n');
|
|
44
|
+
}
|
|
45
|
+
}
|
|
46
|
+
catch (error) {
|
|
47
|
+
spinner.fail(chalk_1.default.red('Error'));
|
|
48
|
+
if (options.json) {
|
|
49
|
+
console.log(JSON.stringify({ error: error.message }, null, 2));
|
|
50
|
+
}
|
|
51
|
+
else {
|
|
52
|
+
console.log(chalk_1.default.red(` ${error.message}\n`));
|
|
53
|
+
}
|
|
54
|
+
process.exit(1);
|
|
55
|
+
}
|
|
56
|
+
}
|
|
57
|
+
function formatResponse(response) {
|
|
58
|
+
let output = '';
|
|
59
|
+
// Main answer
|
|
60
|
+
if (response.answer) {
|
|
61
|
+
output += chalk_1.default.white(response.answer);
|
|
62
|
+
}
|
|
63
|
+
// Show tools used
|
|
64
|
+
if (response.toolsUsed && response.toolsUsed.length > 0) {
|
|
65
|
+
output += chalk_1.default.dim(`\n\n📊 Tools: ${response.toolsUsed.join(', ')}`);
|
|
66
|
+
}
|
|
67
|
+
// Show timing
|
|
68
|
+
if (response.totalTime) {
|
|
69
|
+
output += chalk_1.default.dim(` | ${response.totalTime}ms`);
|
|
70
|
+
}
|
|
71
|
+
return output;
|
|
72
|
+
}
|
|
73
|
+
exports.default = queryCommand;
|
|
@@ -0,0 +1,98 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
/**
|
|
3
|
+
* Watch Command - Real-time price monitoring
|
|
4
|
+
*/
|
|
5
|
+
var __importDefault = (this && this.__importDefault) || function (mod) {
|
|
6
|
+
return (mod && mod.__esModule) ? mod : { "default": mod };
|
|
7
|
+
};
|
|
8
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
9
|
+
exports.watchCommand = watchCommand;
|
|
10
|
+
const chalk_1 = __importDefault(require("chalk"));
|
|
11
|
+
const cli_table3_1 = __importDefault(require("cli-table3"));
|
|
12
|
+
const client_1 = require("../api/client");
|
|
13
|
+
const manager_1 = require("../config/manager");
|
|
14
|
+
async function watchCommand(symbols, interval = 5) {
|
|
15
|
+
const symbolList = symbols.toUpperCase().split(',').map(s => s.trim());
|
|
16
|
+
console.log(chalk_1.default.bold.cyan('\n📈 ENTON Watch Mode\n'));
|
|
17
|
+
console.log(chalk_1.default.dim(`Watching: ${symbolList.join(', ')}`));
|
|
18
|
+
console.log(chalk_1.default.dim(`Refresh: Every ${interval} seconds\n`));
|
|
19
|
+
console.log(chalk_1.default.dim('Press Ctrl+C to exit\n'));
|
|
20
|
+
const config = (0, manager_1.getConfig)();
|
|
21
|
+
const client = new client_1.EntonAPIClient(config.apiUrl, config.apiKey);
|
|
22
|
+
const priceData = new Map();
|
|
23
|
+
// Initial fetch
|
|
24
|
+
await fetchPrices(symbolList, client, priceData);
|
|
25
|
+
displayPrices(priceData);
|
|
26
|
+
// Set up refresh interval
|
|
27
|
+
const intervalId = setInterval(async () => {
|
|
28
|
+
await fetchPrices(symbolList, client, priceData);
|
|
29
|
+
displayPrices(priceData);
|
|
30
|
+
}, interval * 1000);
|
|
31
|
+
// Handle exit
|
|
32
|
+
process.on('SIGINT', () => {
|
|
33
|
+
clearInterval(intervalId);
|
|
34
|
+
console.log(chalk_1.default.dim('\n\nExiting watch mode...\n'));
|
|
35
|
+
process.exit(0);
|
|
36
|
+
});
|
|
37
|
+
}
|
|
38
|
+
async function fetchPrices(symbols, client, priceData) {
|
|
39
|
+
for (const symbol of symbols) {
|
|
40
|
+
try {
|
|
41
|
+
const response = await client.query(`price of ${symbol}`, { stream: false });
|
|
42
|
+
// Parse the response (this is a simplified parser)
|
|
43
|
+
const priceMatch = response.answer.match(/\$?([\d,]+\.?\d*)/);
|
|
44
|
+
const changeMatch = response.answer.match(/(up|down)\s+([\d.]+)%/i);
|
|
45
|
+
if (priceMatch) {
|
|
46
|
+
const price = parseFloat(priceMatch[1].replace(',', ''));
|
|
47
|
+
const isDown = changeMatch?.[1]?.toLowerCase() === 'down';
|
|
48
|
+
const changePercent = changeMatch ? parseFloat(changeMatch[2]) * (isDown ? -1 : 1) : 0;
|
|
49
|
+
const existing = priceData.get(symbol);
|
|
50
|
+
const previousClose = existing?.previousClose || price / (1 + changePercent / 100);
|
|
51
|
+
const change = price - previousClose;
|
|
52
|
+
priceData.set(symbol, {
|
|
53
|
+
symbol,
|
|
54
|
+
price,
|
|
55
|
+
change,
|
|
56
|
+
changePercent,
|
|
57
|
+
previousClose,
|
|
58
|
+
lastUpdated: new Date()
|
|
59
|
+
});
|
|
60
|
+
}
|
|
61
|
+
}
|
|
62
|
+
catch (error) {
|
|
63
|
+
// Keep previous data on error
|
|
64
|
+
console.error(chalk_1.default.dim(`Error fetching ${symbol}`));
|
|
65
|
+
}
|
|
66
|
+
}
|
|
67
|
+
}
|
|
68
|
+
function displayPrices(priceData) {
|
|
69
|
+
// Clear screen and move cursor to top
|
|
70
|
+
console.clear();
|
|
71
|
+
console.log(chalk_1.default.bold.cyan('📈 ENTON Watch Mode'));
|
|
72
|
+
console.log(chalk_1.default.dim(`Last update: ${new Date().toLocaleTimeString()}\n`));
|
|
73
|
+
const table = new cli_table3_1.default({
|
|
74
|
+
head: [
|
|
75
|
+
chalk_1.default.bold('Symbol'),
|
|
76
|
+
chalk_1.default.bold('Price'),
|
|
77
|
+
chalk_1.default.bold('Change'),
|
|
78
|
+
chalk_1.default.bold('% Change')
|
|
79
|
+
],
|
|
80
|
+
style: {
|
|
81
|
+
head: [],
|
|
82
|
+
border: ['dim']
|
|
83
|
+
}
|
|
84
|
+
});
|
|
85
|
+
for (const [symbol, data] of priceData) {
|
|
86
|
+
const changeColor = data.change >= 0 ? chalk_1.default.green : chalk_1.default.red;
|
|
87
|
+
const arrow = data.change >= 0 ? '▲' : '▼';
|
|
88
|
+
table.push([
|
|
89
|
+
chalk_1.default.bold(symbol),
|
|
90
|
+
`$${data.price.toFixed(2)}`,
|
|
91
|
+
changeColor(`${arrow} $${Math.abs(data.change).toFixed(2)}`),
|
|
92
|
+
changeColor(`${data.changePercent >= 0 ? '+' : ''}${data.changePercent.toFixed(2)}%`)
|
|
93
|
+
]);
|
|
94
|
+
}
|
|
95
|
+
console.log(table.toString());
|
|
96
|
+
console.log(chalk_1.default.dim('\nPress Ctrl+C to exit'));
|
|
97
|
+
}
|
|
98
|
+
exports.default = watchCommand;
|
|
@@ -0,0 +1,54 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Configuration Manager
|
|
3
|
+
* Simple JSON file-based config storage
|
|
4
|
+
*/
|
|
5
|
+
interface EntonConfig {
|
|
6
|
+
apiUrl: string;
|
|
7
|
+
apiKey: string | null;
|
|
8
|
+
defaultAccount?: string;
|
|
9
|
+
outputFormat?: 'text' | 'json';
|
|
10
|
+
theme?: 'light' | 'dark';
|
|
11
|
+
}
|
|
12
|
+
/**
|
|
13
|
+
* Get full config including API key from env
|
|
14
|
+
*/
|
|
15
|
+
export declare function getConfig(): EntonConfig;
|
|
16
|
+
/**
|
|
17
|
+
* Get API key
|
|
18
|
+
*/
|
|
19
|
+
export declare function getApiKey(): Promise<string | null>;
|
|
20
|
+
/**
|
|
21
|
+
* Save API key
|
|
22
|
+
*/
|
|
23
|
+
export declare function saveApiKey(apiKey: string): Promise<void>;
|
|
24
|
+
/**
|
|
25
|
+
* Delete API key
|
|
26
|
+
*/
|
|
27
|
+
export declare function deleteApiKey(): Promise<void>;
|
|
28
|
+
/**
|
|
29
|
+
* Set a config value
|
|
30
|
+
*/
|
|
31
|
+
export declare function setConfig<K extends keyof EntonConfig>(key: K, value: EntonConfig[K]): void;
|
|
32
|
+
/**
|
|
33
|
+
* Get a config value
|
|
34
|
+
*/
|
|
35
|
+
export declare function getConfigValue<K extends keyof EntonConfig>(key: K): EntonConfig[K];
|
|
36
|
+
/**
|
|
37
|
+
* List all config values (without sensitive data)
|
|
38
|
+
*/
|
|
39
|
+
export declare function listConfig(): Omit<EntonConfig, 'apiKey'>;
|
|
40
|
+
/**
|
|
41
|
+
* Reset config to defaults
|
|
42
|
+
*/
|
|
43
|
+
export declare function resetConfig(): void;
|
|
44
|
+
declare const _default: {
|
|
45
|
+
getConfig: typeof getConfig;
|
|
46
|
+
getApiKey: typeof getApiKey;
|
|
47
|
+
saveApiKey: typeof saveApiKey;
|
|
48
|
+
deleteApiKey: typeof deleteApiKey;
|
|
49
|
+
setConfig: typeof setConfig;
|
|
50
|
+
getConfigValue: typeof getConfigValue;
|
|
51
|
+
listConfig: typeof listConfig;
|
|
52
|
+
resetConfig: typeof resetConfig;
|
|
53
|
+
};
|
|
54
|
+
export default _default;
|
|
@@ -0,0 +1,168 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
/**
|
|
3
|
+
* Configuration Manager
|
|
4
|
+
* Simple JSON file-based config storage
|
|
5
|
+
*/
|
|
6
|
+
var __createBinding = (this && this.__createBinding) || (Object.create ? (function(o, m, k, k2) {
|
|
7
|
+
if (k2 === undefined) k2 = k;
|
|
8
|
+
var desc = Object.getOwnPropertyDescriptor(m, k);
|
|
9
|
+
if (!desc || ("get" in desc ? !m.__esModule : desc.writable || desc.configurable)) {
|
|
10
|
+
desc = { enumerable: true, get: function() { return m[k]; } };
|
|
11
|
+
}
|
|
12
|
+
Object.defineProperty(o, k2, desc);
|
|
13
|
+
}) : (function(o, m, k, k2) {
|
|
14
|
+
if (k2 === undefined) k2 = k;
|
|
15
|
+
o[k2] = m[k];
|
|
16
|
+
}));
|
|
17
|
+
var __setModuleDefault = (this && this.__setModuleDefault) || (Object.create ? (function(o, v) {
|
|
18
|
+
Object.defineProperty(o, "default", { enumerable: true, value: v });
|
|
19
|
+
}) : function(o, v) {
|
|
20
|
+
o["default"] = v;
|
|
21
|
+
});
|
|
22
|
+
var __importStar = (this && this.__importStar) || (function () {
|
|
23
|
+
var ownKeys = function(o) {
|
|
24
|
+
ownKeys = Object.getOwnPropertyNames || function (o) {
|
|
25
|
+
var ar = [];
|
|
26
|
+
for (var k in o) if (Object.prototype.hasOwnProperty.call(o, k)) ar[ar.length] = k;
|
|
27
|
+
return ar;
|
|
28
|
+
};
|
|
29
|
+
return ownKeys(o);
|
|
30
|
+
};
|
|
31
|
+
return function (mod) {
|
|
32
|
+
if (mod && mod.__esModule) return mod;
|
|
33
|
+
var result = {};
|
|
34
|
+
if (mod != null) for (var k = ownKeys(mod), i = 0; i < k.length; i++) if (k[i] !== "default") __createBinding(result, mod, k[i]);
|
|
35
|
+
__setModuleDefault(result, mod);
|
|
36
|
+
return result;
|
|
37
|
+
};
|
|
38
|
+
})();
|
|
39
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
40
|
+
exports.getConfig = getConfig;
|
|
41
|
+
exports.getApiKey = getApiKey;
|
|
42
|
+
exports.saveApiKey = saveApiKey;
|
|
43
|
+
exports.deleteApiKey = deleteApiKey;
|
|
44
|
+
exports.setConfig = setConfig;
|
|
45
|
+
exports.getConfigValue = getConfigValue;
|
|
46
|
+
exports.listConfig = listConfig;
|
|
47
|
+
exports.resetConfig = resetConfig;
|
|
48
|
+
const fs = __importStar(require("fs"));
|
|
49
|
+
const path = __importStar(require("path"));
|
|
50
|
+
const os = __importStar(require("os"));
|
|
51
|
+
const CONFIG_DIR = path.join(os.homedir(), '.enton');
|
|
52
|
+
const CONFIG_FILE = path.join(CONFIG_DIR, 'config.json');
|
|
53
|
+
const DEFAULT_CONFIG = {
|
|
54
|
+
apiUrl: 'https://enton.ai',
|
|
55
|
+
apiKey: null,
|
|
56
|
+
defaultAccount: undefined,
|
|
57
|
+
outputFormat: 'text',
|
|
58
|
+
theme: 'dark'
|
|
59
|
+
};
|
|
60
|
+
/**
|
|
61
|
+
* Ensure config directory exists
|
|
62
|
+
*/
|
|
63
|
+
function ensureConfigDir() {
|
|
64
|
+
if (!fs.existsSync(CONFIG_DIR)) {
|
|
65
|
+
fs.mkdirSync(CONFIG_DIR, { recursive: true });
|
|
66
|
+
}
|
|
67
|
+
}
|
|
68
|
+
/**
|
|
69
|
+
* Load config from file
|
|
70
|
+
*/
|
|
71
|
+
function loadConfig() {
|
|
72
|
+
ensureConfigDir();
|
|
73
|
+
if (!fs.existsSync(CONFIG_FILE)) {
|
|
74
|
+
return { ...DEFAULT_CONFIG };
|
|
75
|
+
}
|
|
76
|
+
try {
|
|
77
|
+
const data = fs.readFileSync(CONFIG_FILE, 'utf-8');
|
|
78
|
+
return { ...DEFAULT_CONFIG, ...JSON.parse(data) };
|
|
79
|
+
}
|
|
80
|
+
catch {
|
|
81
|
+
return { ...DEFAULT_CONFIG };
|
|
82
|
+
}
|
|
83
|
+
}
|
|
84
|
+
/**
|
|
85
|
+
* Save config to file
|
|
86
|
+
*/
|
|
87
|
+
function saveConfig(config) {
|
|
88
|
+
ensureConfigDir();
|
|
89
|
+
fs.writeFileSync(CONFIG_FILE, JSON.stringify(config, null, 2));
|
|
90
|
+
}
|
|
91
|
+
/**
|
|
92
|
+
* Get full config including API key from env
|
|
93
|
+
*/
|
|
94
|
+
function getConfig() {
|
|
95
|
+
const config = loadConfig();
|
|
96
|
+
// Environment variable takes precedence
|
|
97
|
+
if (process.env.ENTON_API_KEY) {
|
|
98
|
+
config.apiKey = process.env.ENTON_API_KEY;
|
|
99
|
+
}
|
|
100
|
+
return config;
|
|
101
|
+
}
|
|
102
|
+
/**
|
|
103
|
+
* Get API key
|
|
104
|
+
*/
|
|
105
|
+
async function getApiKey() {
|
|
106
|
+
// Try environment variable first
|
|
107
|
+
if (process.env.ENTON_API_KEY) {
|
|
108
|
+
return process.env.ENTON_API_KEY;
|
|
109
|
+
}
|
|
110
|
+
// Then try config file
|
|
111
|
+
const config = loadConfig();
|
|
112
|
+
return config.apiKey;
|
|
113
|
+
}
|
|
114
|
+
/**
|
|
115
|
+
* Save API key
|
|
116
|
+
*/
|
|
117
|
+
async function saveApiKey(apiKey) {
|
|
118
|
+
const config = loadConfig();
|
|
119
|
+
config.apiKey = apiKey;
|
|
120
|
+
saveConfig(config);
|
|
121
|
+
}
|
|
122
|
+
/**
|
|
123
|
+
* Delete API key
|
|
124
|
+
*/
|
|
125
|
+
async function deleteApiKey() {
|
|
126
|
+
const config = loadConfig();
|
|
127
|
+
config.apiKey = null;
|
|
128
|
+
saveConfig(config);
|
|
129
|
+
}
|
|
130
|
+
/**
|
|
131
|
+
* Set a config value
|
|
132
|
+
*/
|
|
133
|
+
function setConfig(key, value) {
|
|
134
|
+
const config = loadConfig();
|
|
135
|
+
config[key] = value;
|
|
136
|
+
saveConfig(config);
|
|
137
|
+
}
|
|
138
|
+
/**
|
|
139
|
+
* Get a config value
|
|
140
|
+
*/
|
|
141
|
+
function getConfigValue(key) {
|
|
142
|
+
const config = loadConfig();
|
|
143
|
+
return config[key];
|
|
144
|
+
}
|
|
145
|
+
/**
|
|
146
|
+
* List all config values (without sensitive data)
|
|
147
|
+
*/
|
|
148
|
+
function listConfig() {
|
|
149
|
+
const config = loadConfig();
|
|
150
|
+
const { apiKey, ...rest } = config;
|
|
151
|
+
return rest;
|
|
152
|
+
}
|
|
153
|
+
/**
|
|
154
|
+
* Reset config to defaults
|
|
155
|
+
*/
|
|
156
|
+
function resetConfig() {
|
|
157
|
+
saveConfig({ ...DEFAULT_CONFIG });
|
|
158
|
+
}
|
|
159
|
+
exports.default = {
|
|
160
|
+
getConfig,
|
|
161
|
+
getApiKey,
|
|
162
|
+
saveApiKey,
|
|
163
|
+
deleteApiKey,
|
|
164
|
+
setConfig,
|
|
165
|
+
getConfigValue,
|
|
166
|
+
listConfig,
|
|
167
|
+
resetConfig
|
|
168
|
+
};
|
package/dist/index.d.ts
ADDED
|
@@ -0,0 +1,11 @@
|
|
|
1
|
+
#!/usr/bin/env node
|
|
2
|
+
/**
|
|
3
|
+
* ENTON CLI - AI-powered financial assistant
|
|
4
|
+
*
|
|
5
|
+
* Usage:
|
|
6
|
+
* enton # Interactive mode
|
|
7
|
+
* enton "query" # Direct query mode
|
|
8
|
+
* enton auth login # Authenticate with ENTON
|
|
9
|
+
* enton watch AAPL,TSLA # Watch mode for real-time prices
|
|
10
|
+
*/
|
|
11
|
+
export {};
|