@vike-io/cli 0.7.0 → 0.7.2
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/CHANGELOG.md +7 -0
- package/package.json +4 -4
- package/src/commands/wallet.js +2 -2
- package/src/index.js +20 -0
- package/src/telemetry.js +17 -11
- package/src/update-check.js +1 -10
package/CHANGELOG.md
CHANGED
|
@@ -2,6 +2,13 @@
|
|
|
2
2
|
|
|
3
3
|
All notable changes are documented here. Entries follow [Keep a Changelog](https://keepachangelog.com/en/1.1.0/).
|
|
4
4
|
|
|
5
|
+
## 0.7.1 — eval harness v2 + help tweaks + SQL fix
|
|
6
|
+
|
|
7
|
+
- **Eval schema upgraded** (`evals/questions.yaml`): multi-command list, per-skill tag, multi-step flag, word-boundary forbidden matching. Per-skill scoring breakdown + single-vs-multi-step split in the runner output.
|
|
8
|
+
- **10 new multi-step questions** exercising composite playbook skills (smart-money-discovery, wallet-portfolio, polymarket-screener, perp-screener, hl-trader-profile, alerts-setup, etc.) — 32 questions total.
|
|
9
|
+
- **Help discoverability tweaks**: `wallet counterparties --limit` and `wallet balances --min-usd` descriptions improved (eval surfaced both as commonly-missed flags).
|
|
10
|
+
- **Backend bug fix shipped (server-side)**: `wallet_transactions` returned 0 rows due to ClickHouse SELECT-alias shadowing — fixed in monorepo, deployed to prod.
|
|
11
|
+
|
|
5
12
|
## 0.7.0 — 5 new commands (transactions, compare, trace, batch, screener)
|
|
6
13
|
|
|
7
14
|
- **`vike wallet transactions <address>`** (alias `txs`) — raw per-wallet transfer list with `--direction in|out|all`, `--days`, `--min-usd`, `--token` filters.
|
package/package.json
CHANGED
|
@@ -3,7 +3,7 @@
|
|
|
3
3
|
"publishConfig": {
|
|
4
4
|
"access": "public"
|
|
5
5
|
},
|
|
6
|
-
"version": "0.7.
|
|
6
|
+
"version": "0.7.2",
|
|
7
7
|
"description": "AI-agent CLI for vike.io on-chain analytics, perps, options, and prediction markets across 11 chains",
|
|
8
8
|
"type": "module",
|
|
9
9
|
"main": "src/index.js",
|
|
@@ -65,11 +65,11 @@
|
|
|
65
65
|
"node": ">=20.0.0"
|
|
66
66
|
},
|
|
67
67
|
"dependencies": {
|
|
68
|
-
"commander": "^
|
|
68
|
+
"commander": "^14.0.3"
|
|
69
69
|
},
|
|
70
70
|
"devDependencies": {
|
|
71
71
|
"@changesets/cli": "^2.27.9",
|
|
72
|
-
"eslint": "^
|
|
73
|
-
"vitest": "^
|
|
72
|
+
"eslint": "^10.4.0",
|
|
73
|
+
"vitest": "^4.1.7"
|
|
74
74
|
}
|
|
75
75
|
}
|
package/src/commands/wallet.js
CHANGED
|
@@ -104,7 +104,7 @@ export function registerWallet(program) {
|
|
|
104
104
|
.description('Top trading partners of a wallet by combined transfer volume')
|
|
105
105
|
.option('--chain <c>', 'ethereum | bsc | base', 'ethereum')
|
|
106
106
|
.option('--window <w>', '24h | 7d | 30d | 90d | 180d | all', '30d')
|
|
107
|
-
.option('--limit <n>', 'Max counterparties (max 50)', '10')
|
|
107
|
+
.option('--limit <n>', 'Max counterparties returned (default 10, max 50)', '10')
|
|
108
108
|
.option('--json', 'Emit JSON')
|
|
109
109
|
.action(async (address, opts) => {
|
|
110
110
|
try {
|
|
@@ -139,7 +139,7 @@ export function registerWallet(program) {
|
|
|
139
139
|
.command('balances <address>')
|
|
140
140
|
.description('Current ERC-20 holdings across major EVM chains')
|
|
141
141
|
.option('--chains <list>', 'Comma-separated chains (eth,bsc,base,arbitrum,polygon,optimism)')
|
|
142
|
-
.option('--min-usd <n>', 'Filter dust below this USD value', '1')
|
|
142
|
+
.option('--min-usd <n>', 'Filter dust below this USD value (default $1; recommend $100+ for noisy wallets)', '1')
|
|
143
143
|
.option('--json', 'Emit JSON')
|
|
144
144
|
.action(async (address, opts) => {
|
|
145
145
|
try {
|
package/src/index.js
CHANGED
|
@@ -21,6 +21,7 @@ import {
|
|
|
21
21
|
getUpgradeNotice,
|
|
22
22
|
scheduleUpdateCheck,
|
|
23
23
|
} from './update-check.js';
|
|
24
|
+
import { trackCommandSucceeded, trackCommandFailed } from './telemetry.js';
|
|
24
25
|
|
|
25
26
|
const version = readPackageVersion();
|
|
26
27
|
|
|
@@ -38,6 +39,19 @@ program
|
|
|
38
39
|
.description('AI-agent CLI for vike.io on-chain analytics')
|
|
39
40
|
.version(version, '-v, --version', 'Show CLI version');
|
|
40
41
|
|
|
42
|
+
// Telemetry: time each command from preAction to postAction; failure path is
|
|
43
|
+
// caught below via parseAsync().catch().
|
|
44
|
+
const _cmdStart = new WeakMap();
|
|
45
|
+
program.hook('preAction', (_thisCmd, actionCmd) => {
|
|
46
|
+
_cmdStart.set(actionCmd, Date.now());
|
|
47
|
+
});
|
|
48
|
+
program.hook('postAction', (_thisCmd, actionCmd) => {
|
|
49
|
+
const t0 = _cmdStart.get(actionCmd);
|
|
50
|
+
trackCommandSucceeded(actionCmd.name(), actionCmd.opts(), {
|
|
51
|
+
durationMs: t0 ? Date.now() - t0 : null,
|
|
52
|
+
});
|
|
53
|
+
});
|
|
54
|
+
|
|
41
55
|
registerLogin(program);
|
|
42
56
|
registerLogout(program);
|
|
43
57
|
registerInit(program);
|
|
@@ -52,10 +66,16 @@ registerPolymarket(program);
|
|
|
52
66
|
registerLabels(program);
|
|
53
67
|
registerWeb(program);
|
|
54
68
|
|
|
69
|
+
const _parseT0 = Date.now();
|
|
55
70
|
program.parseAsync(process.argv)
|
|
56
71
|
.catch((err) => {
|
|
57
72
|
console.error(`vike: ${err.message ?? err}`);
|
|
58
73
|
process.exitCode = 1;
|
|
74
|
+
const cmd = program.args[0] || 'unknown';
|
|
75
|
+
trackCommandFailed(cmd, {}, {
|
|
76
|
+
errorCode: err?.code || err?.name || 'error',
|
|
77
|
+
durationMs: Date.now() - _parseT0,
|
|
78
|
+
});
|
|
59
79
|
})
|
|
60
80
|
.finally(() => {
|
|
61
81
|
// Fire-and-forget background check, detached subprocess. Survives our exit.
|
package/src/telemetry.js
CHANGED
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
// Anonymous, opt-out telemetry
|
|
1
|
+
// Anonymous, opt-out telemetry.
|
|
2
2
|
//
|
|
3
3
|
// Design decisions:
|
|
4
4
|
// - Honors DO_NOT_TRACK=1 (industry standard) AND VIKE_NO_TELEMETRY=1
|
|
@@ -7,25 +7,24 @@
|
|
|
7
7
|
// - Rolling 30-min session ID — same session_id within a 30-min window
|
|
8
8
|
// - AbortController + 1000ms timeout, timer.unref() so we can't keep
|
|
9
9
|
// the process alive
|
|
10
|
-
// - Payload includes: flag NAMES (no values), latency, success/error_code
|
|
11
|
-
//
|
|
10
|
+
// - Payload includes: flag NAMES (no values), latency, success/error_code.
|
|
11
|
+
// NEVER the actual data the user queried (no addresses, no symbols).
|
|
12
12
|
// - Fire-and-forget: errors are swallowed
|
|
13
|
-
//
|
|
14
|
-
// THE SINK IS NOT YET WIRED. `_send()` is a no-op until we have an
|
|
15
|
-
// endpoint. Keeping the API shape stable now so we can flip the switch
|
|
16
|
-
// later without a refactor.
|
|
17
13
|
|
|
18
|
-
import { existsSync, mkdirSync, readFileSync, writeFileSync
|
|
14
|
+
import { existsSync, mkdirSync, readFileSync, writeFileSync } from 'node:fs';
|
|
19
15
|
import { homedir } from 'node:os';
|
|
20
16
|
import { join } from 'node:path';
|
|
21
17
|
import { randomUUID } from 'node:crypto';
|
|
18
|
+
import { readPackageVersion } from './util.js';
|
|
22
19
|
|
|
23
20
|
const CONFIG_DIR = join(homedir(), '.vike');
|
|
24
21
|
const ID_FILE = join(CONFIG_DIR, 'telemetry-id');
|
|
25
22
|
const SESSION_FILE = join(CONFIG_DIR, 'session');
|
|
26
23
|
const SESSION_TTL_MS = 30 * 60 * 1000;
|
|
27
|
-
const ENDPOINT = process.env.VIKE_TELEMETRY_ENDPOINT
|
|
24
|
+
const ENDPOINT = process.env.VIKE_TELEMETRY_ENDPOINT
|
|
25
|
+
|| 'https://vike.io/api/cli-telemetry';
|
|
28
26
|
const REQUEST_TIMEOUT_MS = 1000;
|
|
27
|
+
const CLI_VERSION = (() => { try { return readPackageVersion(); } catch { return ''; } })();
|
|
29
28
|
|
|
30
29
|
function disabled() {
|
|
31
30
|
return process.env.DO_NOT_TRACK === '1' ||
|
|
@@ -82,9 +81,13 @@ function _send(event, payload) {
|
|
|
82
81
|
if (typeof timer.unref === 'function') timer.unref();
|
|
83
82
|
fetch(ENDPOINT, {
|
|
84
83
|
method: 'POST',
|
|
85
|
-
headers: {
|
|
84
|
+
headers: {
|
|
85
|
+
'Content-Type': 'application/json',
|
|
86
|
+
'User-Agent': `vike-cli/${CLI_VERSION}`,
|
|
87
|
+
},
|
|
86
88
|
body: JSON.stringify({
|
|
87
89
|
event,
|
|
90
|
+
cli_version: CLI_VERSION,
|
|
88
91
|
device_id: getDeviceId(),
|
|
89
92
|
session_id: getSessionId(),
|
|
90
93
|
ts: Date.now(),
|
|
@@ -98,8 +101,11 @@ function _send(event, payload) {
|
|
|
98
101
|
|
|
99
102
|
function flagNames(opts) {
|
|
100
103
|
// Extract flag names from a commander options object. Values stripped.
|
|
104
|
+
// Convert camelCase to kebab-case for readability in analytics.
|
|
101
105
|
if (!opts || typeof opts !== 'object') return [];
|
|
102
|
-
return Object.keys(opts)
|
|
106
|
+
return Object.keys(opts)
|
|
107
|
+
.filter((k) => !k.startsWith('_') && k !== 'parent')
|
|
108
|
+
.map((k) => '--' + k.replace(/[A-Z]/g, (m) => '-' + m.toLowerCase()));
|
|
103
109
|
}
|
|
104
110
|
|
|
105
111
|
export function trackCommandSucceeded(command, opts, { durationMs } = {}) {
|
package/src/update-check.js
CHANGED
|
@@ -11,8 +11,7 @@
|
|
|
11
11
|
import { spawn } from 'node:child_process';
|
|
12
12
|
import { existsSync, mkdirSync, readFileSync, writeFileSync } from 'node:fs';
|
|
13
13
|
import { homedir } from 'node:os';
|
|
14
|
-
import {
|
|
15
|
-
import { fileURLToPath } from 'node:url';
|
|
14
|
+
import { join } from 'node:path';
|
|
16
15
|
|
|
17
16
|
const CONFIG_DIR = join(homedir(), '.vike');
|
|
18
17
|
const CHECK_FILE = join(CONFIG_DIR, 'update-check.json');
|
|
@@ -33,13 +32,6 @@ function readCache() {
|
|
|
33
32
|
try { return JSON.parse(readFileSync(CHECK_FILE, 'utf8')); } catch { return null; }
|
|
34
33
|
}
|
|
35
34
|
|
|
36
|
-
function writeCache(latest) {
|
|
37
|
-
try {
|
|
38
|
-
if (!existsSync(CONFIG_DIR)) mkdirSync(CONFIG_DIR, { recursive: true, mode: 0o700 });
|
|
39
|
-
writeFileSync(CHECK_FILE, JSON.stringify({ latest, checkedAt: Date.now() }, null, 2));
|
|
40
|
-
} catch { /* ignore */ }
|
|
41
|
-
}
|
|
42
|
-
|
|
43
35
|
function cmpSemver(a, b) {
|
|
44
36
|
const pa = a.split('.').map(Number);
|
|
45
37
|
const pb = b.split('.').map(Number);
|
|
@@ -73,7 +65,6 @@ export function scheduleUpdateCheck() {
|
|
|
73
65
|
const cache = readCache();
|
|
74
66
|
if (cache && Date.now() - (cache.checkedAt || 0) < CHECK_INTERVAL_MS) return;
|
|
75
67
|
|
|
76
|
-
const __filename = fileURLToPath(import.meta.url);
|
|
77
68
|
// Inline child script — no separate file needed, no dependency on
|
|
78
69
|
// package layout, survives `npm install -g` symlinking.
|
|
79
70
|
const code = `
|