@kibibot/cli 1.0.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 +148 -0
- package/bin/kibi.js +2 -0
- package/dist/commands/balances.d.ts +5 -0
- package/dist/commands/balances.js +60 -0
- package/dist/commands/config.d.ts +5 -0
- package/dist/commands/config.js +53 -0
- package/dist/commands/llm.d.ts +5 -0
- package/dist/commands/llm.js +229 -0
- package/dist/commands/login.d.ts +5 -0
- package/dist/commands/login.js +68 -0
- package/dist/commands/quota.d.ts +5 -0
- package/dist/commands/quota.js +28 -0
- package/dist/commands/skills.d.ts +5 -0
- package/dist/commands/skills.js +32 -0
- package/dist/commands/status.d.ts +5 -0
- package/dist/commands/status.js +33 -0
- package/dist/commands/token.d.ts +5 -0
- package/dist/commands/token.js +140 -0
- package/dist/commands/tokens.d.ts +5 -0
- package/dist/commands/tokens.js +45 -0
- package/dist/commands/whoami.d.ts +5 -0
- package/dist/commands/whoami.js +25 -0
- package/dist/index.d.ts +2 -0
- package/dist/index.js +50 -0
- package/dist/lib/api.d.ts +28 -0
- package/dist/lib/api.js +152 -0
- package/dist/lib/config.d.ts +31 -0
- package/dist/lib/config.js +86 -0
- package/dist/lib/display.d.ts +36 -0
- package/dist/lib/display.js +113 -0
- package/dist/types.d.ts +141 -0
- package/dist/types.js +5 -0
- package/package.json +47 -0
package/README.md
ADDED
|
@@ -0,0 +1,148 @@
|
|
|
1
|
+
# @kibibot/cli
|
|
2
|
+
|
|
3
|
+
The official KibiBot command-line interface. Deploy tokens on-chain, check balances, manage Kibi Credits, and control your AI agent from the terminal.
|
|
4
|
+
|
|
5
|
+
## Installation
|
|
6
|
+
|
|
7
|
+
```bash
|
|
8
|
+
npm install -g @kibibot/cli
|
|
9
|
+
```
|
|
10
|
+
|
|
11
|
+
```bash
|
|
12
|
+
kibi --version
|
|
13
|
+
```
|
|
14
|
+
|
|
15
|
+
### Run without installing
|
|
16
|
+
|
|
17
|
+
```bash
|
|
18
|
+
npx @kibibot/cli whoami
|
|
19
|
+
npx @kibibot/cli token create --name MyToken --symbol MTK --chain base
|
|
20
|
+
```
|
|
21
|
+
|
|
22
|
+
## Setup
|
|
23
|
+
|
|
24
|
+
### 1. Get an API key
|
|
25
|
+
|
|
26
|
+
Go to [kibi.bot/settings/api-keys](https://kibi.bot/settings/api-keys) → Create API Key → copy the `kb_...` key.
|
|
27
|
+
|
|
28
|
+
### 2. Login
|
|
29
|
+
|
|
30
|
+
```bash
|
|
31
|
+
# Interactive — prompts for API key
|
|
32
|
+
kibi login
|
|
33
|
+
|
|
34
|
+
# Headless — pass key directly
|
|
35
|
+
kibi login --api-key kb_YOUR_KEY
|
|
36
|
+
```
|
|
37
|
+
|
|
38
|
+
Credentials are stored in `~/.kibi/config.json`. You can also set `KIBI_API_KEY` as an environment variable.
|
|
39
|
+
|
|
40
|
+
### 3. Verify
|
|
41
|
+
|
|
42
|
+
```bash
|
|
43
|
+
kibi whoami
|
|
44
|
+
```
|
|
45
|
+
|
|
46
|
+
## Commands
|
|
47
|
+
|
|
48
|
+
### Identity
|
|
49
|
+
|
|
50
|
+
```bash
|
|
51
|
+
kibi whoami # your account info and wallet addresses
|
|
52
|
+
kibi logout # clear stored credentials
|
|
53
|
+
```
|
|
54
|
+
|
|
55
|
+
### Token Creation
|
|
56
|
+
|
|
57
|
+
```bash
|
|
58
|
+
# Interactive (prompts for name, symbol, chain)
|
|
59
|
+
kibi token create
|
|
60
|
+
|
|
61
|
+
# Headless
|
|
62
|
+
kibi token create --name "MyToken" --symbol MTK --chain base
|
|
63
|
+
kibi token create --name "Moon" --symbol MOON --chain solana --description "To the moon"
|
|
64
|
+
kibi token create --name "Test" --symbol TST --chain base --no-wait # return job ID immediately
|
|
65
|
+
|
|
66
|
+
# Check deployment status
|
|
67
|
+
kibi status 12345
|
|
68
|
+
|
|
69
|
+
# Get token info
|
|
70
|
+
kibi token info 0x1234...
|
|
71
|
+
kibi token info 5Yz8K... --chain solana
|
|
72
|
+
|
|
73
|
+
# List tokens you've created
|
|
74
|
+
kibi tokens created
|
|
75
|
+
kibi tokens created --page 2
|
|
76
|
+
```
|
|
77
|
+
|
|
78
|
+
Supported chains: `base` · `bsc` · `solana`
|
|
79
|
+
|
|
80
|
+
### Balances & Quota
|
|
81
|
+
|
|
82
|
+
```bash
|
|
83
|
+
kibi balances # on-chain wallet balances across all chains
|
|
84
|
+
kibi quota # daily token creation quota per chain
|
|
85
|
+
```
|
|
86
|
+
|
|
87
|
+
### Kibi Credits & Kibi LLM Gateway
|
|
88
|
+
|
|
89
|
+
```bash
|
|
90
|
+
# Check Kibi Credit balance + agent reload config
|
|
91
|
+
kibi llm credits
|
|
92
|
+
|
|
93
|
+
# List available AI models
|
|
94
|
+
kibi llm models
|
|
95
|
+
|
|
96
|
+
# Reload Kibi Credits from trading wallet (requires Agent Reload enabled)
|
|
97
|
+
kibi llm reload
|
|
98
|
+
|
|
99
|
+
# Emergency disable agent reload
|
|
100
|
+
kibi llm reload --disable
|
|
101
|
+
|
|
102
|
+
# Generate provider config for your tool
|
|
103
|
+
kibi llm setup openclaw # OpenClaw config JSON (use with --install to write directly)
|
|
104
|
+
kibi llm setup cursor # Cursor IDE settings
|
|
105
|
+
kibi llm setup claude # Claude Code env vars
|
|
106
|
+
```
|
|
107
|
+
|
|
108
|
+
### Skills & Config
|
|
109
|
+
|
|
110
|
+
```bash
|
|
111
|
+
kibi skills # list all agent capabilities
|
|
112
|
+
|
|
113
|
+
kibi config get # show all config
|
|
114
|
+
kibi config get apiKey # show specific key
|
|
115
|
+
kibi config set apiUrl https://custom.api.url
|
|
116
|
+
```
|
|
117
|
+
|
|
118
|
+
## Global Flags
|
|
119
|
+
|
|
120
|
+
| Flag | Description |
|
|
121
|
+
|---|---|
|
|
122
|
+
| `--json` | Machine-readable JSON output |
|
|
123
|
+
| `--debug` | Verbose HTTP request/response logging |
|
|
124
|
+
| `--version` | Print version |
|
|
125
|
+
| `--help` | Print help |
|
|
126
|
+
|
|
127
|
+
## Configuration
|
|
128
|
+
|
|
129
|
+
Config precedence (highest to lowest):
|
|
130
|
+
|
|
131
|
+
1. **Environment variable** — `KIBI_API_KEY`
|
|
132
|
+
2. **Config file** — `~/.kibi/config.json`
|
|
133
|
+
3. **Defaults** — API URL: `https://api.kibi.bot`, LLM URL: `https://llm.kibi.bot`
|
|
134
|
+
|
|
135
|
+
## Requirements
|
|
136
|
+
|
|
137
|
+
- Node.js >= 18.0.0
|
|
138
|
+
|
|
139
|
+
## Links
|
|
140
|
+
|
|
141
|
+
- [Agent & Developer Docs](https://kibi.bot/docs/agent)
|
|
142
|
+
- [API Keys](https://kibi.bot/settings/api-keys)
|
|
143
|
+
- [Kibi Credits](https://kibi.bot/credits)
|
|
144
|
+
- [GitHub Skills](https://github.com/OfficialKibiBot/skills)
|
|
145
|
+
|
|
146
|
+
## License
|
|
147
|
+
|
|
148
|
+
MIT
|
package/bin/kibi.js
ADDED
|
@@ -0,0 +1,60 @@
|
|
|
1
|
+
import chalk from 'chalk';
|
|
2
|
+
import { agent, handleApiError } from '../lib/api.js';
|
|
3
|
+
import { fmtBalance, shortAddr } from '../lib/display.js';
|
|
4
|
+
function printWallet(label, slot, kind) {
|
|
5
|
+
if (!slot.address) {
|
|
6
|
+
console.log(` ${chalk.dim(label + ':')} ${chalk.dim('Not configured')}`);
|
|
7
|
+
return;
|
|
8
|
+
}
|
|
9
|
+
console.log(` ${chalk.bold(label)} ${chalk.dim(shortAddr(slot.address))}`);
|
|
10
|
+
// Show only relevant balances per wallet type
|
|
11
|
+
const balances = kind === 'evm'
|
|
12
|
+
? [
|
|
13
|
+
['ETH (Base)', slot.balance_eth, slot.eth_error],
|
|
14
|
+
['BNB (BSC)', slot.balance_bnb, slot.bnb_error],
|
|
15
|
+
['USDC (Base)', slot.balance_usdc_base, slot.usdc_base_error],
|
|
16
|
+
['USDT (BSC)', slot.balance_usdt_bsc, slot.usdt_bsc_error],
|
|
17
|
+
]
|
|
18
|
+
: [
|
|
19
|
+
['SOL', slot.balance_sol, slot.sol_error],
|
|
20
|
+
['USDC (Sol)', slot.balance_usdc_solana, slot.usdc_solana_error],
|
|
21
|
+
];
|
|
22
|
+
// Always show native balances (even if zero); show stablecoins only if > 0
|
|
23
|
+
const nativeTokens = kind === 'evm' ? ['ETH (Base)', 'BNB (BSC)'] : ['SOL'];
|
|
24
|
+
for (const [name, value, error] of balances) {
|
|
25
|
+
if (error) {
|
|
26
|
+
console.log(` ${name.padEnd(14)} ${chalk.red('error')}`);
|
|
27
|
+
}
|
|
28
|
+
else if (nativeTokens.includes(name) || (value && parseFloat(value) > 0)) {
|
|
29
|
+
const symbol = name.split(' ')[0];
|
|
30
|
+
console.log(` ${name.padEnd(14)} ${fmtBalance(value, symbol)}`);
|
|
31
|
+
}
|
|
32
|
+
}
|
|
33
|
+
console.log();
|
|
34
|
+
}
|
|
35
|
+
export function registerBalances(program) {
|
|
36
|
+
program
|
|
37
|
+
.command('balances')
|
|
38
|
+
.description('Show wallet balances across all chains')
|
|
39
|
+
.action(async (_, cmd) => {
|
|
40
|
+
try {
|
|
41
|
+
const res = await agent.walletBalance();
|
|
42
|
+
const isJson = cmd.optsWithGlobals().json;
|
|
43
|
+
if (isJson) {
|
|
44
|
+
console.log(JSON.stringify(res, null, 2));
|
|
45
|
+
return;
|
|
46
|
+
}
|
|
47
|
+
console.log();
|
|
48
|
+
console.log(chalk.bold.cyan('Wallet Balances'));
|
|
49
|
+
console.log(chalk.dim('─'.repeat(40)));
|
|
50
|
+
console.log();
|
|
51
|
+
printWallet('EVM Main', res.evm_main, 'evm');
|
|
52
|
+
printWallet('EVM Trading', res.evm_trading, 'evm');
|
|
53
|
+
printWallet('Solana Main', res.solana_main, 'solana');
|
|
54
|
+
printWallet('Solana Trading', res.solana_trading, 'solana');
|
|
55
|
+
}
|
|
56
|
+
catch (err) {
|
|
57
|
+
handleApiError(err);
|
|
58
|
+
}
|
|
59
|
+
});
|
|
60
|
+
}
|
|
@@ -0,0 +1,53 @@
|
|
|
1
|
+
import chalk from 'chalk';
|
|
2
|
+
import { readConfig, setConfigValue, CONFIG_PATH } from '../lib/config.js';
|
|
3
|
+
const VALID_KEYS = ['apiKey', 'apiUrl', 'llmUrl'];
|
|
4
|
+
function maskKey(key) {
|
|
5
|
+
if (key.length <= 8)
|
|
6
|
+
return '***';
|
|
7
|
+
return key.slice(0, 6) + '...' + key.slice(-4);
|
|
8
|
+
}
|
|
9
|
+
export function registerConfig(program) {
|
|
10
|
+
const configCmd = program
|
|
11
|
+
.command('config')
|
|
12
|
+
.description('Read or write CLI configuration');
|
|
13
|
+
configCmd
|
|
14
|
+
.command('get [key]')
|
|
15
|
+
.description('Show config values')
|
|
16
|
+
.action((key) => {
|
|
17
|
+
const config = readConfig();
|
|
18
|
+
if (key) {
|
|
19
|
+
if (!VALID_KEYS.includes(key)) {
|
|
20
|
+
console.error(`Error: Unknown key '${key}'. Valid keys: ${VALID_KEYS.join(', ')}`);
|
|
21
|
+
process.exit(1);
|
|
22
|
+
}
|
|
23
|
+
const value = config[key];
|
|
24
|
+
if (value) {
|
|
25
|
+
console.log(key === 'apiKey' ? maskKey(value) : value);
|
|
26
|
+
}
|
|
27
|
+
else {
|
|
28
|
+
console.log(chalk.dim('(not set)'));
|
|
29
|
+
}
|
|
30
|
+
return;
|
|
31
|
+
}
|
|
32
|
+
// Show all
|
|
33
|
+
console.log();
|
|
34
|
+
console.log(chalk.bold.cyan('Configuration'));
|
|
35
|
+
console.log(chalk.dim('─'.repeat(40)));
|
|
36
|
+
console.log(` ${chalk.dim('File:')} ${CONFIG_PATH}`);
|
|
37
|
+
console.log(` ${chalk.dim('apiKey:')} ${config.apiKey ? maskKey(config.apiKey) : chalk.dim('(not set)')}`);
|
|
38
|
+
console.log(` ${chalk.dim('apiUrl:')} ${config.apiUrl || chalk.dim('(not set)')}`);
|
|
39
|
+
console.log(` ${chalk.dim('llmUrl:')} ${config.llmUrl || chalk.dim('(not set)')}`);
|
|
40
|
+
console.log();
|
|
41
|
+
});
|
|
42
|
+
configCmd
|
|
43
|
+
.command('set <key> <value>')
|
|
44
|
+
.description('Set a config value (apiKey, apiUrl, llmUrl)')
|
|
45
|
+
.action((key, value) => {
|
|
46
|
+
if (!VALID_KEYS.includes(key)) {
|
|
47
|
+
console.error(`Error: Unknown key '${key}'. Valid keys: ${VALID_KEYS.join(', ')}`);
|
|
48
|
+
process.exit(1);
|
|
49
|
+
}
|
|
50
|
+
setConfigValue(key, value);
|
|
51
|
+
console.log(chalk.green('✓') + ` ${key} updated`);
|
|
52
|
+
});
|
|
53
|
+
}
|
|
@@ -0,0 +1,229 @@
|
|
|
1
|
+
import chalk from 'chalk';
|
|
2
|
+
import ora from 'ora';
|
|
3
|
+
import { agent, llm, handleApiError } from '../lib/api.js';
|
|
4
|
+
import { readConfig } from '../lib/config.js';
|
|
5
|
+
import { printCard, success } from '../lib/display.js';
|
|
6
|
+
export function registerLlm(program) {
|
|
7
|
+
const llmCmd = program
|
|
8
|
+
.command('llm')
|
|
9
|
+
.description('LLM Gateway commands');
|
|
10
|
+
// ── llm models ────────────────────────────────────────
|
|
11
|
+
llmCmd
|
|
12
|
+
.command('models')
|
|
13
|
+
.description('List available LLM models')
|
|
14
|
+
.action(async (_, cmd) => {
|
|
15
|
+
try {
|
|
16
|
+
const res = await llm.models();
|
|
17
|
+
const isJson = cmd.optsWithGlobals().json;
|
|
18
|
+
if (isJson) {
|
|
19
|
+
console.log(JSON.stringify(res, null, 2));
|
|
20
|
+
return;
|
|
21
|
+
}
|
|
22
|
+
const models = res.models || [];
|
|
23
|
+
if (models.length === 0) {
|
|
24
|
+
console.log('\nNo models available.\n');
|
|
25
|
+
return;
|
|
26
|
+
}
|
|
27
|
+
console.log();
|
|
28
|
+
console.log(chalk.bold.cyan(`Available Models (${models.length})`));
|
|
29
|
+
console.log(chalk.dim('─'.repeat(40)));
|
|
30
|
+
for (const modelId of models) {
|
|
31
|
+
console.log(` ${chalk.bold(modelId)}`);
|
|
32
|
+
}
|
|
33
|
+
console.log();
|
|
34
|
+
}
|
|
35
|
+
catch (err) {
|
|
36
|
+
handleApiError(err);
|
|
37
|
+
}
|
|
38
|
+
});
|
|
39
|
+
// ── llm credits ───────────────────────────────────────
|
|
40
|
+
llmCmd
|
|
41
|
+
.command('credits')
|
|
42
|
+
.description('Check your Kibi Credit balance')
|
|
43
|
+
.action(async (_, cmd) => {
|
|
44
|
+
try {
|
|
45
|
+
const res = await agent.kibiCreditBalance();
|
|
46
|
+
const isJson = cmd.optsWithGlobals().json;
|
|
47
|
+
if (isJson) {
|
|
48
|
+
console.log(JSON.stringify(res, null, 2));
|
|
49
|
+
return;
|
|
50
|
+
}
|
|
51
|
+
printCard('Kibi Credits', [
|
|
52
|
+
['Balance', `$${res.balance_usd}`],
|
|
53
|
+
]);
|
|
54
|
+
// Show agent reload config
|
|
55
|
+
if (res.agent_reload) {
|
|
56
|
+
const r = res.agent_reload;
|
|
57
|
+
console.log();
|
|
58
|
+
if (r.enabled) {
|
|
59
|
+
console.log(` ${chalk.dim('Agent Reload:')} ${chalk.green('ON')}`);
|
|
60
|
+
console.log(` ${chalk.dim('Amount:')} $${r.amount_usd.toFixed(2)}`);
|
|
61
|
+
console.log(` ${chalk.dim('Daily Limit:')} $${r.daily_limit_usd.toFixed(2)}`);
|
|
62
|
+
console.log(` ${chalk.dim('Chains:')} ${r.chains.join(', ')}`);
|
|
63
|
+
}
|
|
64
|
+
else {
|
|
65
|
+
console.log(` ${chalk.dim('Agent Reload:')} ${chalk.dim('OFF')}`);
|
|
66
|
+
}
|
|
67
|
+
}
|
|
68
|
+
}
|
|
69
|
+
catch (err) {
|
|
70
|
+
handleApiError(err);
|
|
71
|
+
}
|
|
72
|
+
});
|
|
73
|
+
// ── llm reload ────────────────────────────────────────
|
|
74
|
+
llmCmd
|
|
75
|
+
.command('reload')
|
|
76
|
+
.description('Reload Kibi Credits from trading wallet')
|
|
77
|
+
.option('--disable', 'Emergency disable agent reload')
|
|
78
|
+
.action(async (opts, cmd) => {
|
|
79
|
+
try {
|
|
80
|
+
if (opts.disable) {
|
|
81
|
+
await agent.disableReload();
|
|
82
|
+
const isJson = cmd.optsWithGlobals().json;
|
|
83
|
+
if (isJson) {
|
|
84
|
+
console.log(JSON.stringify({ disabled: true }));
|
|
85
|
+
}
|
|
86
|
+
else {
|
|
87
|
+
success('Agent reload disabled. Re-enable from your KibiBot dashboard.');
|
|
88
|
+
}
|
|
89
|
+
return;
|
|
90
|
+
}
|
|
91
|
+
const isJson = cmd.optsWithGlobals().json;
|
|
92
|
+
const spinner = ora('Reloading Kibi Credits from trading wallet...').start();
|
|
93
|
+
const res = await agent.reloadKibiCredits();
|
|
94
|
+
if (isJson) {
|
|
95
|
+
spinner.stop();
|
|
96
|
+
console.log(JSON.stringify(res, null, 2));
|
|
97
|
+
return;
|
|
98
|
+
}
|
|
99
|
+
spinner.succeed('Reload complete!');
|
|
100
|
+
printCard('Kibi Credit Reload', [
|
|
101
|
+
['Amount', `$${res.amount_usd}`],
|
|
102
|
+
['Tx Hash', res.tx_hash],
|
|
103
|
+
['New Balance', res.new_balance_usd ? `$${res.new_balance_usd}` : undefined],
|
|
104
|
+
['Daily Used', `$${res.daily_used_usd} / $${res.daily_remaining_usd} remaining`],
|
|
105
|
+
]);
|
|
106
|
+
}
|
|
107
|
+
catch (err) {
|
|
108
|
+
handleApiError(err);
|
|
109
|
+
}
|
|
110
|
+
});
|
|
111
|
+
// ── llm setup ─────────────────────────────────────────
|
|
112
|
+
llmCmd
|
|
113
|
+
.command('setup <target>')
|
|
114
|
+
.description('Generate config for coding tools (cursor, claude, openclaw)')
|
|
115
|
+
.option('--install', 'Write config directly (openclaw only)')
|
|
116
|
+
.action(async (target, opts, cmd) => {
|
|
117
|
+
const config = readConfig();
|
|
118
|
+
const apiKey = config.apiKey || process.env['KIBI_API_KEY'];
|
|
119
|
+
const llmUrl = config.llmUrl || 'https://llm.kibi.bot/v1';
|
|
120
|
+
if (!apiKey) {
|
|
121
|
+
console.error("Error: Not logged in. Run 'kibi login' first.");
|
|
122
|
+
process.exit(1);
|
|
123
|
+
}
|
|
124
|
+
switch (target.toLowerCase()) {
|
|
125
|
+
case 'cursor': {
|
|
126
|
+
console.log();
|
|
127
|
+
console.log(chalk.bold.cyan('Cursor IDE Configuration'));
|
|
128
|
+
console.log(chalk.dim('─'.repeat(40)));
|
|
129
|
+
console.log();
|
|
130
|
+
console.log('Add this to your Cursor settings (Settings → Models → OpenAI API Key):');
|
|
131
|
+
console.log();
|
|
132
|
+
console.log(` ${chalk.bold('API Base URL:')} ${llmUrl}`);
|
|
133
|
+
console.log(` ${chalk.bold('API Key:')} ${apiKey}`);
|
|
134
|
+
console.log();
|
|
135
|
+
console.log(chalk.yellow('⚠ Your API key is shown above. Do not share this output.'));
|
|
136
|
+
console.log(chalk.dim('Then select a Kibi model from the model dropdown.'));
|
|
137
|
+
console.log();
|
|
138
|
+
break;
|
|
139
|
+
}
|
|
140
|
+
case 'claude': {
|
|
141
|
+
console.log();
|
|
142
|
+
console.log(chalk.bold.cyan('Claude Code Configuration'));
|
|
143
|
+
console.log(chalk.dim('─'.repeat(40)));
|
|
144
|
+
console.log();
|
|
145
|
+
console.log('Set these environment variables:');
|
|
146
|
+
console.log();
|
|
147
|
+
console.log(` export ANTHROPIC_BASE_URL="${llmUrl}"`);
|
|
148
|
+
console.log(` export ANTHROPIC_API_KEY="${apiKey}"`);
|
|
149
|
+
console.log();
|
|
150
|
+
console.log(chalk.yellow('⚠ Your API key is shown above. Do not share this output.'));
|
|
151
|
+
console.log(chalk.dim('Then run `claude` as usual.'));
|
|
152
|
+
console.log();
|
|
153
|
+
break;
|
|
154
|
+
}
|
|
155
|
+
case 'openclaw': {
|
|
156
|
+
const openclawConfig = {
|
|
157
|
+
models: {
|
|
158
|
+
mode: 'merge',
|
|
159
|
+
providers: {
|
|
160
|
+
kibi: {
|
|
161
|
+
baseUrl: llmUrl.replace('/v1', ''),
|
|
162
|
+
apiKey: apiKey,
|
|
163
|
+
api: 'openai-completions',
|
|
164
|
+
models: [
|
|
165
|
+
{ id: 'claude-haiku-4-5', name: 'Claude Haiku (KibiBot)', api: 'anthropic-messages', contextWindow: 200000, maxTokens: 4096 },
|
|
166
|
+
{ id: 'claude-sonnet-4-6', name: 'Claude Sonnet (KibiBot)', api: 'anthropic-messages', contextWindow: 200000, maxTokens: 8192 },
|
|
167
|
+
{ id: 'claude-opus-4-6', name: 'Claude Opus (KibiBot)', api: 'anthropic-messages', contextWindow: 200000, maxTokens: 8192 },
|
|
168
|
+
{ id: 'gpt-4o', name: 'GPT-4o (KibiBot)', contextWindow: 128000, maxTokens: 16384 },
|
|
169
|
+
{ id: 'gpt-4o-mini', name: 'GPT-4o Mini (KibiBot)', contextWindow: 128000, maxTokens: 16384 },
|
|
170
|
+
{ id: 'gemini-2.5-flash', name: 'Gemini 2.5 Flash (KibiBot)', contextWindow: 1048576, maxTokens: 8192 },
|
|
171
|
+
{ id: 'gemini-2.5-pro', name: 'Gemini 2.5 Pro (KibiBot)', contextWindow: 1048576, maxTokens: 8192 },
|
|
172
|
+
],
|
|
173
|
+
},
|
|
174
|
+
},
|
|
175
|
+
},
|
|
176
|
+
};
|
|
177
|
+
if (opts.install) {
|
|
178
|
+
try {
|
|
179
|
+
const { readFileSync, writeFileSync, existsSync, mkdirSync } = await import('node:fs');
|
|
180
|
+
const { join } = await import('node:path');
|
|
181
|
+
const { homedir } = await import('node:os');
|
|
182
|
+
const configDir = join(homedir(), '.openclaw');
|
|
183
|
+
const configPath = join(configDir, 'openclaw.json');
|
|
184
|
+
let existing = {};
|
|
185
|
+
if (existsSync(configPath)) {
|
|
186
|
+
try {
|
|
187
|
+
existing = JSON.parse(readFileSync(configPath, 'utf-8'));
|
|
188
|
+
}
|
|
189
|
+
catch {
|
|
190
|
+
existing = {};
|
|
191
|
+
}
|
|
192
|
+
}
|
|
193
|
+
else {
|
|
194
|
+
mkdirSync(configDir, { recursive: true });
|
|
195
|
+
}
|
|
196
|
+
// Deep merge into models.providers
|
|
197
|
+
existing.models = existing.models || {};
|
|
198
|
+
existing.models.mode = 'merge';
|
|
199
|
+
existing.models.providers = existing.models.providers || {};
|
|
200
|
+
existing.models.providers.kibi = openclawConfig.models.providers.kibi;
|
|
201
|
+
writeFileSync(configPath, JSON.stringify(existing, null, 2) + '\n', 'utf-8');
|
|
202
|
+
success(`Kibi provider added to ${configPath}`);
|
|
203
|
+
console.log(chalk.dim(' Restart OpenClaw: openclaw gateway restart'));
|
|
204
|
+
}
|
|
205
|
+
catch (err) {
|
|
206
|
+
console.error(`Error: Failed to write config — ${err instanceof Error ? err.message : err}`);
|
|
207
|
+
process.exit(1);
|
|
208
|
+
}
|
|
209
|
+
}
|
|
210
|
+
else {
|
|
211
|
+
console.log();
|
|
212
|
+
console.log(chalk.bold.cyan('OpenClaw Configuration'));
|
|
213
|
+
console.log(chalk.dim('─'.repeat(40)));
|
|
214
|
+
console.log();
|
|
215
|
+
console.log('Add this to your ~/.openclaw/openclaw.json:');
|
|
216
|
+
console.log();
|
|
217
|
+
console.log(JSON.stringify(openclawConfig, null, 2));
|
|
218
|
+
console.log();
|
|
219
|
+
console.log(chalk.dim('Or run: kibi llm setup openclaw --install'));
|
|
220
|
+
console.log();
|
|
221
|
+
}
|
|
222
|
+
break;
|
|
223
|
+
}
|
|
224
|
+
default:
|
|
225
|
+
console.error(`Error: Unknown target '${target}'. Supported: cursor, claude, openclaw`);
|
|
226
|
+
process.exit(1);
|
|
227
|
+
}
|
|
228
|
+
});
|
|
229
|
+
}
|
|
@@ -0,0 +1,68 @@
|
|
|
1
|
+
import chalk from 'chalk';
|
|
2
|
+
import { writeConfig, clearConfig, CONFIG_PATH } from '../lib/config.js';
|
|
3
|
+
import { agent, handleApiError } from '../lib/api.js';
|
|
4
|
+
import { success } from '../lib/display.js';
|
|
5
|
+
export function registerLogin(program) {
|
|
6
|
+
program
|
|
7
|
+
.command('login')
|
|
8
|
+
.description('Authenticate with your KibiBot API key')
|
|
9
|
+
.option('--api-key <key>', 'API key (kb_...)')
|
|
10
|
+
.option('--url', 'Open the KibiBot API keys page in your browser')
|
|
11
|
+
.action(async (opts) => {
|
|
12
|
+
if (opts.url) {
|
|
13
|
+
const url = 'https://kibi.bot/settings/api-keys';
|
|
14
|
+
console.log(`Open this URL to get your API key:\n\n ${chalk.cyan(url)}\n`);
|
|
15
|
+
// Try to open browser
|
|
16
|
+
try {
|
|
17
|
+
const { exec } = await import('node:child_process');
|
|
18
|
+
const cmd = process.platform === 'darwin' ? 'open'
|
|
19
|
+
: process.platform === 'win32' ? 'start'
|
|
20
|
+
: 'xdg-open';
|
|
21
|
+
exec(`${cmd} ${url}`);
|
|
22
|
+
}
|
|
23
|
+
catch {
|
|
24
|
+
// browser open is best-effort
|
|
25
|
+
}
|
|
26
|
+
return;
|
|
27
|
+
}
|
|
28
|
+
let apiKey = opts.apiKey;
|
|
29
|
+
if (!apiKey) {
|
|
30
|
+
// Interactive prompt
|
|
31
|
+
const readline = await import('node:readline');
|
|
32
|
+
const rl = readline.createInterface({
|
|
33
|
+
input: process.stdin,
|
|
34
|
+
output: process.stdout,
|
|
35
|
+
});
|
|
36
|
+
apiKey = await new Promise((resolve) => {
|
|
37
|
+
rl.question('Enter your API key: ', (answer) => {
|
|
38
|
+
rl.close();
|
|
39
|
+
resolve(answer.trim());
|
|
40
|
+
});
|
|
41
|
+
});
|
|
42
|
+
}
|
|
43
|
+
if (!apiKey || !apiKey.startsWith('kb_')) {
|
|
44
|
+
console.error('Error: Invalid API key. Keys start with kb_');
|
|
45
|
+
process.exit(1);
|
|
46
|
+
}
|
|
47
|
+
// Save key first so the API call can use it
|
|
48
|
+
writeConfig({ apiKey });
|
|
49
|
+
// Verify the key works
|
|
50
|
+
try {
|
|
51
|
+
const me = await agent.me();
|
|
52
|
+
success(`Logged in as ${chalk.bold('@' + (me.twitter_username || me.twitter_user_id))}`);
|
|
53
|
+
console.log(` Config saved to ${chalk.dim(CONFIG_PATH)}`);
|
|
54
|
+
}
|
|
55
|
+
catch (err) {
|
|
56
|
+
// Key is bad — clear it
|
|
57
|
+
clearConfig();
|
|
58
|
+
handleApiError(err);
|
|
59
|
+
}
|
|
60
|
+
});
|
|
61
|
+
program
|
|
62
|
+
.command('logout')
|
|
63
|
+
.description('Clear stored credentials')
|
|
64
|
+
.action(() => {
|
|
65
|
+
clearConfig();
|
|
66
|
+
success('Logged out. Credentials cleared.');
|
|
67
|
+
});
|
|
68
|
+
}
|
|
@@ -0,0 +1,28 @@
|
|
|
1
|
+
import chalk from 'chalk';
|
|
2
|
+
import { agent, handleApiError } from '../lib/api.js';
|
|
3
|
+
import { printTable } from '../lib/display.js';
|
|
4
|
+
export function registerQuota(program) {
|
|
5
|
+
program
|
|
6
|
+
.command('quota')
|
|
7
|
+
.description('Show daily token creation quota per chain')
|
|
8
|
+
.action(async (_, cmd) => {
|
|
9
|
+
try {
|
|
10
|
+
const res = await agent.quota();
|
|
11
|
+
const isJson = cmd.optsWithGlobals().json;
|
|
12
|
+
if (isJson) {
|
|
13
|
+
console.log(JSON.stringify(res, null, 2));
|
|
14
|
+
return;
|
|
15
|
+
}
|
|
16
|
+
printTable(['Chain', 'Free Used', 'Free Limit', 'Sponsored', 'Can Create'], res.chains.map((c) => [
|
|
17
|
+
chalk.bold(c.chain.charAt(0).toUpperCase() + c.chain.slice(1)),
|
|
18
|
+
`${c.free_used_today}`,
|
|
19
|
+
`${c.free_limit}`,
|
|
20
|
+
`${c.sponsored_remaining}`,
|
|
21
|
+
c.can_create_paid ? chalk.green('Yes') : chalk.dim('No'),
|
|
22
|
+
]));
|
|
23
|
+
}
|
|
24
|
+
catch (err) {
|
|
25
|
+
handleApiError(err);
|
|
26
|
+
}
|
|
27
|
+
});
|
|
28
|
+
}
|
|
@@ -0,0 +1,32 @@
|
|
|
1
|
+
import chalk from 'chalk';
|
|
2
|
+
import { agent, handleApiError } from '../lib/api.js';
|
|
3
|
+
export function registerSkills(program) {
|
|
4
|
+
program
|
|
5
|
+
.command('skills')
|
|
6
|
+
.description('List available KibiBot agent capabilities')
|
|
7
|
+
.action(async (_, cmd) => {
|
|
8
|
+
try {
|
|
9
|
+
const res = await agent.skills();
|
|
10
|
+
const isJson = cmd.optsWithGlobals().json;
|
|
11
|
+
if (isJson) {
|
|
12
|
+
console.log(JSON.stringify(res, null, 2));
|
|
13
|
+
return;
|
|
14
|
+
}
|
|
15
|
+
console.log();
|
|
16
|
+
console.log(chalk.bold.cyan(`Available Skills (${res.total})`));
|
|
17
|
+
console.log(chalk.dim('─'.repeat(50)));
|
|
18
|
+
for (const skill of res.skills) {
|
|
19
|
+
console.log();
|
|
20
|
+
console.log(` ${chalk.bold(skill.name)}`);
|
|
21
|
+
console.log(` ${skill.description}`);
|
|
22
|
+
if (skill.example) {
|
|
23
|
+
console.log(` ${chalk.dim(skill.example)}`);
|
|
24
|
+
}
|
|
25
|
+
}
|
|
26
|
+
console.log();
|
|
27
|
+
}
|
|
28
|
+
catch (err) {
|
|
29
|
+
handleApiError(err);
|
|
30
|
+
}
|
|
31
|
+
});
|
|
32
|
+
}
|