@dawnai/cli 1.1.0 → 1.1.1
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 +9 -0
- package/dist/index.js +225 -1
- package/package.json +1 -1
- package/postinstall.js +85 -0
package/README.md
CHANGED
|
@@ -25,6 +25,10 @@ dawn account overview
|
|
|
25
25
|
dawn account fund
|
|
26
26
|
dawn account wallet
|
|
27
27
|
|
|
28
|
+
dawn wallet list
|
|
29
|
+
dawn wallet use <address-or-name>
|
|
30
|
+
dawn wallet current
|
|
31
|
+
|
|
28
32
|
dawn strategy list
|
|
29
33
|
dawn strategy create "<text>"
|
|
30
34
|
dawn strategy status <id>
|
|
@@ -45,6 +49,8 @@ dawn run stop <id>
|
|
|
45
49
|
|
|
46
50
|
dawn skill list
|
|
47
51
|
dawn skill install [--force] [--dir <path>]
|
|
52
|
+
|
|
53
|
+
dawn sdk doctor
|
|
48
54
|
```
|
|
49
55
|
|
|
50
56
|
## Environment Variables
|
|
@@ -57,5 +63,8 @@ dawn skill install [--force] [--dir <path>]
|
|
|
57
63
|
## Notes
|
|
58
64
|
|
|
59
65
|
- Auth token is stored at `~/.dawn-cli/config.json`.
|
|
66
|
+
- Active Moonpay wallet selection is stored in `~/.dawn-cli/config.json` under `moonpay`.
|
|
67
|
+
- `dawn wallet list` shells out to `mp wallet list` and uses the Polygon address for selection.
|
|
60
68
|
- `dawn account fund` prints the wallet address and Polygon USDC deposit instructions.
|
|
61
69
|
- `dawn skill install` copies bundled Dawn skills into `~/.claude/skills` for Claude Code.
|
|
70
|
+
- `dawn sdk doctor` verifies the local Dawn SDK executable (`dawnsdk`) is available.
|
package/dist/index.js
CHANGED
|
@@ -6,7 +6,7 @@ import process from 'node:process';
|
|
|
6
6
|
import readline from 'node:readline/promises';
|
|
7
7
|
import { spawn } from 'node:child_process';
|
|
8
8
|
import { fileURLToPath } from 'node:url';
|
|
9
|
-
const CLI_VERSION = '1.1.
|
|
9
|
+
const CLI_VERSION = '1.1.1';
|
|
10
10
|
const DAWN_API_BASE_URL = 'https://api.dawn.ai';
|
|
11
11
|
const FUNDING_LINK_TEMPLATE = process.env.DAWN_HELIO_LINK_TEMPLATE || '';
|
|
12
12
|
const CLI_HOME = process.env.DAWN_CLI_HOME || path.join(os.homedir(), '.dawn-cli');
|
|
@@ -195,6 +195,10 @@ function printUsage() {
|
|
|
195
195
|
dawn account fund
|
|
196
196
|
dawn account wallet
|
|
197
197
|
|
|
198
|
+
dawn wallet list
|
|
199
|
+
dawn wallet use <address-or-name>
|
|
200
|
+
dawn wallet current
|
|
201
|
+
|
|
198
202
|
dawn strategy list
|
|
199
203
|
dawn strategy create <text>
|
|
200
204
|
dawn strategy status <id>
|
|
@@ -217,6 +221,8 @@ function printUsage() {
|
|
|
217
221
|
dawn skill list
|
|
218
222
|
dawn skill install [--force] [--dir <path>]
|
|
219
223
|
|
|
224
|
+
dawn sdk doctor
|
|
225
|
+
|
|
220
226
|
dawn update
|
|
221
227
|
|
|
222
228
|
dawn --version
|
|
@@ -226,6 +232,111 @@ Environment variables:
|
|
|
226
232
|
DAWN_CLI_HOME Override config directory (default: ~/.dawn-cli)
|
|
227
233
|
`);
|
|
228
234
|
}
|
|
235
|
+
function normalizeEvmAddress(value) {
|
|
236
|
+
if (typeof value !== 'string') {
|
|
237
|
+
return null;
|
|
238
|
+
}
|
|
239
|
+
const trimmed = value.trim();
|
|
240
|
+
if (!/^0x[a-fA-F0-9]{40}$/.test(trimmed)) {
|
|
241
|
+
return null;
|
|
242
|
+
}
|
|
243
|
+
return trimmed.toLowerCase();
|
|
244
|
+
}
|
|
245
|
+
function getMoonpayConfig(config) {
|
|
246
|
+
if (!config.moonpay || typeof config.moonpay !== 'object' || Array.isArray(config.moonpay)) {
|
|
247
|
+
return {};
|
|
248
|
+
}
|
|
249
|
+
const moonpay = config.moonpay;
|
|
250
|
+
return {
|
|
251
|
+
activeWalletAddress: typeof moonpay.activeWalletAddress === 'string' ? moonpay.activeWalletAddress : undefined,
|
|
252
|
+
activeWalletName: typeof moonpay.activeWalletName === 'string' ? moonpay.activeWalletName : undefined,
|
|
253
|
+
};
|
|
254
|
+
}
|
|
255
|
+
async function runMoonpayCommand(args) {
|
|
256
|
+
const result = await new Promise((resolve) => {
|
|
257
|
+
const child = spawn('mp', args, {
|
|
258
|
+
stdio: ['ignore', 'pipe', 'pipe'],
|
|
259
|
+
});
|
|
260
|
+
let stdout = '';
|
|
261
|
+
let stderr = '';
|
|
262
|
+
child.stdout.on('data', (data) => { stdout += data.toString(); });
|
|
263
|
+
child.stderr.on('data', (data) => { stderr += data.toString(); });
|
|
264
|
+
child.on('close', (code) => { resolve({ code: code ?? 1, stdout, stderr }); });
|
|
265
|
+
});
|
|
266
|
+
if (result.code !== 0) {
|
|
267
|
+
throw new Error(result.stderr.trim() || result.stdout.trim() || 'Moonpay CLI command failed.');
|
|
268
|
+
}
|
|
269
|
+
return result.stdout;
|
|
270
|
+
}
|
|
271
|
+
function parseMoonpayWalletList(output) {
|
|
272
|
+
const lines = output.split(/\r?\n/);
|
|
273
|
+
const wallets = [];
|
|
274
|
+
let currentName = null;
|
|
275
|
+
let currentPolygonAddress = null;
|
|
276
|
+
const flushCurrent = () => {
|
|
277
|
+
if (currentName && currentPolygonAddress) {
|
|
278
|
+
wallets.push({
|
|
279
|
+
name: currentName,
|
|
280
|
+
address: currentPolygonAddress,
|
|
281
|
+
});
|
|
282
|
+
}
|
|
283
|
+
};
|
|
284
|
+
for (const line of lines) {
|
|
285
|
+
const nameMatch = line.match(/^\s*-\s*name:\s*(.+)\s*$/);
|
|
286
|
+
if (nameMatch) {
|
|
287
|
+
flushCurrent();
|
|
288
|
+
currentName = nameMatch[1].trim();
|
|
289
|
+
currentPolygonAddress = null;
|
|
290
|
+
continue;
|
|
291
|
+
}
|
|
292
|
+
const polygonMatch = line.match(/^\s*polygon:\s*(0x[a-fA-F0-9]{40})\s*$/);
|
|
293
|
+
if (polygonMatch) {
|
|
294
|
+
currentPolygonAddress = polygonMatch[1].toLowerCase();
|
|
295
|
+
}
|
|
296
|
+
}
|
|
297
|
+
flushCurrent();
|
|
298
|
+
return wallets;
|
|
299
|
+
}
|
|
300
|
+
async function loadMoonpayWallets() {
|
|
301
|
+
const output = await runMoonpayCommand(['wallet', 'list']);
|
|
302
|
+
const wallets = parseMoonpayWalletList(output);
|
|
303
|
+
if (!wallets.length) {
|
|
304
|
+
throw new Error('Could not find Polygon wallets from `mp wallet list`. Ensure Moonpay CLI is installed and has wallets.');
|
|
305
|
+
}
|
|
306
|
+
return wallets;
|
|
307
|
+
}
|
|
308
|
+
function findMoonpayWalletBySelector(wallets, selector) {
|
|
309
|
+
const normalizedAddress = normalizeEvmAddress(selector);
|
|
310
|
+
if (normalizedAddress) {
|
|
311
|
+
const byAddress = wallets.find((wallet) => wallet.address === normalizedAddress);
|
|
312
|
+
if (byAddress) {
|
|
313
|
+
return byAddress;
|
|
314
|
+
}
|
|
315
|
+
}
|
|
316
|
+
const lowered = selector.toLowerCase();
|
|
317
|
+
const byName = wallets.filter((wallet) => wallet.name.toLowerCase() === lowered);
|
|
318
|
+
if (byName.length === 1) {
|
|
319
|
+
return byName[0];
|
|
320
|
+
}
|
|
321
|
+
if (byName.length > 1) {
|
|
322
|
+
throw new Error(`Multiple Moonpay wallets match "${selector}". Use full address or wallet ID instead.`);
|
|
323
|
+
}
|
|
324
|
+
throw new Error(`No Moonpay wallet matched "${selector}". Run: dawn wallet list`);
|
|
325
|
+
}
|
|
326
|
+
function printMoonpayWalletTable(wallets, activeAddress) {
|
|
327
|
+
const rows = wallets.map((wallet) => ({
|
|
328
|
+
active: activeAddress && wallet.address === activeAddress ? '*' : ' ',
|
|
329
|
+
name: wallet.name,
|
|
330
|
+
address: wallet.address,
|
|
331
|
+
}));
|
|
332
|
+
const nameWidth = Math.max(8, ...rows.map((row) => row.name.length));
|
|
333
|
+
const addressWidth = Math.max(42, ...rows.map((row) => row.address.length));
|
|
334
|
+
console.log(`${'A'.padEnd(2)}${'NAME'.padEnd(nameWidth)} ${'POLYGON_ADDRESS'.padEnd(addressWidth)}`);
|
|
335
|
+
console.log(`${'-'.repeat(2)}${'-'.repeat(nameWidth)} ${'-'.repeat(addressWidth)}`);
|
|
336
|
+
for (const row of rows) {
|
|
337
|
+
console.log(`${row.active.padEnd(2)}${row.name.padEnd(nameWidth)} ${row.address}`);
|
|
338
|
+
}
|
|
339
|
+
}
|
|
229
340
|
function parseFlags(args) {
|
|
230
341
|
const flags = {};
|
|
231
342
|
const positional = [];
|
|
@@ -732,6 +843,69 @@ async function handleAccount(args) {
|
|
|
732
843
|
}
|
|
733
844
|
throw new Error(`Unknown account command: ${subcommand}`);
|
|
734
845
|
}
|
|
846
|
+
async function handleWallet(args) {
|
|
847
|
+
if (args.includes('--help') || args.includes('-h')) {
|
|
848
|
+
console.log(`Usage:
|
|
849
|
+
dawn wallet list
|
|
850
|
+
dawn wallet use <address-or-name>
|
|
851
|
+
dawn wallet current`);
|
|
852
|
+
return;
|
|
853
|
+
}
|
|
854
|
+
const [subcommand, ...rest] = args;
|
|
855
|
+
if (!subcommand) {
|
|
856
|
+
throw new Error('Missing wallet command.');
|
|
857
|
+
}
|
|
858
|
+
const config = await loadConfig();
|
|
859
|
+
const moonpayConfig = getMoonpayConfig(config);
|
|
860
|
+
if (subcommand === 'list') {
|
|
861
|
+
const wallets = await loadMoonpayWallets();
|
|
862
|
+
printMoonpayWalletTable(wallets, moonpayConfig.activeWalletAddress);
|
|
863
|
+
console.log('\nUse a wallet: dawn wallet use <address-or-name>');
|
|
864
|
+
return;
|
|
865
|
+
}
|
|
866
|
+
if (subcommand === 'current') {
|
|
867
|
+
const activeAddress = moonpayConfig.activeWalletAddress;
|
|
868
|
+
if (!activeAddress) {
|
|
869
|
+
console.log('No active Moonpay wallet selected. Run: dawn wallet use <address-or-name>');
|
|
870
|
+
return;
|
|
871
|
+
}
|
|
872
|
+
const wallets = await loadMoonpayWallets();
|
|
873
|
+
const wallet = wallets.find((entry) => entry.address === activeAddress);
|
|
874
|
+
if (!wallet) {
|
|
875
|
+
throw new Error(`Active wallet ${activeAddress} is no longer present in Moonpay wallets. Run: dawn wallet list`);
|
|
876
|
+
}
|
|
877
|
+
console.log('Active Moonpay wallet');
|
|
878
|
+
console.log('=====================');
|
|
879
|
+
printKeyValue('Name', wallet.name);
|
|
880
|
+
printKeyValue('Address', wallet.address);
|
|
881
|
+
printKeyValue('Source', 'mp wallet list');
|
|
882
|
+
return;
|
|
883
|
+
}
|
|
884
|
+
if (subcommand === 'use') {
|
|
885
|
+
const selector = rest[0];
|
|
886
|
+
if (!selector) {
|
|
887
|
+
throw new Error('Usage: dawn wallet use <address-or-name>');
|
|
888
|
+
}
|
|
889
|
+
const wallets = await loadMoonpayWallets();
|
|
890
|
+
const selectedWallet = findMoonpayWalletBySelector(wallets, selector);
|
|
891
|
+
const nextConfig = {
|
|
892
|
+
...config,
|
|
893
|
+
moonpay: {
|
|
894
|
+
...moonpayConfig,
|
|
895
|
+
activeWalletAddress: selectedWallet.address,
|
|
896
|
+
activeWalletName: selectedWallet.name,
|
|
897
|
+
},
|
|
898
|
+
};
|
|
899
|
+
await saveConfig(nextConfig);
|
|
900
|
+
console.log('Selected Moonpay wallet');
|
|
901
|
+
console.log('=======================');
|
|
902
|
+
printKeyValue('Name', selectedWallet.name);
|
|
903
|
+
printKeyValue('Address', selectedWallet.address);
|
|
904
|
+
printKeyValue('Source', 'mp wallet list');
|
|
905
|
+
return;
|
|
906
|
+
}
|
|
907
|
+
throw new Error(`Unknown wallet command: ${subcommand}`);
|
|
908
|
+
}
|
|
735
909
|
function renderConversationList(conversations) {
|
|
736
910
|
if (!Array.isArray(conversations) || conversations.length === 0) {
|
|
737
911
|
console.log('No strategies found.');
|
|
@@ -1454,6 +1628,48 @@ async function handleSkill(args) {
|
|
|
1454
1628
|
}
|
|
1455
1629
|
throw new Error(`Unknown skill command: ${subcommand}`);
|
|
1456
1630
|
}
|
|
1631
|
+
async function handleSdk(args) {
|
|
1632
|
+
if (args.includes('--help') || args.includes('-h')) {
|
|
1633
|
+
console.log(`Usage:
|
|
1634
|
+
dawn sdk doctor`);
|
|
1635
|
+
return;
|
|
1636
|
+
}
|
|
1637
|
+
const [subcommand] = args;
|
|
1638
|
+
if (!subcommand) {
|
|
1639
|
+
throw new Error('Missing sdk command. Run: dawn sdk doctor');
|
|
1640
|
+
}
|
|
1641
|
+
if (subcommand === 'doctor') {
|
|
1642
|
+
const result = await new Promise((resolve) => {
|
|
1643
|
+
const child = spawn('dawnsdk', ['doctor'], {
|
|
1644
|
+
stdio: ['ignore', 'pipe', 'pipe'],
|
|
1645
|
+
});
|
|
1646
|
+
let stdout = '';
|
|
1647
|
+
let stderr = '';
|
|
1648
|
+
child.stdout.on('data', (data) => { stdout += data.toString(); });
|
|
1649
|
+
child.stderr.on('data', (data) => { stderr += data.toString(); });
|
|
1650
|
+
child.on('close', (code) => { resolve({ code: code ?? 1, stdout, stderr }); });
|
|
1651
|
+
child.on('error', (error) => {
|
|
1652
|
+
resolve({
|
|
1653
|
+
code: 1,
|
|
1654
|
+
stdout: '',
|
|
1655
|
+
stderr: error instanceof Error ? error.message : String(error),
|
|
1656
|
+
});
|
|
1657
|
+
});
|
|
1658
|
+
});
|
|
1659
|
+
if (result.code !== 0) {
|
|
1660
|
+
throw new Error(`Failed to run SDK doctor. ${result.stderr.trim() || result.stdout.trim()}\nInstall locally from repo: cd py/sdk && uv tool install --from . dawnai-sdk --force`);
|
|
1661
|
+
}
|
|
1662
|
+
const output = result.stdout.trim();
|
|
1663
|
+
if (output) {
|
|
1664
|
+
console.log(output);
|
|
1665
|
+
}
|
|
1666
|
+
else {
|
|
1667
|
+
console.log('SDK doctor completed successfully.');
|
|
1668
|
+
}
|
|
1669
|
+
return;
|
|
1670
|
+
}
|
|
1671
|
+
throw new Error(`Unknown sdk command: ${subcommand}`);
|
|
1672
|
+
}
|
|
1457
1673
|
async function handleUpdate() {
|
|
1458
1674
|
console.log('Checking for updates...');
|
|
1459
1675
|
const result = await new Promise((resolve) => {
|
|
@@ -1499,6 +1715,10 @@ async function main() {
|
|
|
1499
1715
|
await handleAccount(args);
|
|
1500
1716
|
return;
|
|
1501
1717
|
}
|
|
1718
|
+
if (cmd === 'wallet') {
|
|
1719
|
+
await handleWallet(args);
|
|
1720
|
+
return;
|
|
1721
|
+
}
|
|
1502
1722
|
if (cmd === 'strategy') {
|
|
1503
1723
|
await handleStrategy(args);
|
|
1504
1724
|
return;
|
|
@@ -1511,6 +1731,10 @@ async function main() {
|
|
|
1511
1731
|
await handleSkill(args);
|
|
1512
1732
|
return;
|
|
1513
1733
|
}
|
|
1734
|
+
if (cmd === 'sdk') {
|
|
1735
|
+
await handleSdk(args);
|
|
1736
|
+
return;
|
|
1737
|
+
}
|
|
1514
1738
|
if (cmd === 'update') {
|
|
1515
1739
|
await handleUpdate();
|
|
1516
1740
|
return;
|
package/package.json
CHANGED
package/postinstall.js
CHANGED
|
@@ -3,6 +3,7 @@
|
|
|
3
3
|
import fs from 'node:fs/promises';
|
|
4
4
|
import os from 'node:os';
|
|
5
5
|
import path from 'node:path';
|
|
6
|
+
import { spawn } from 'node:child_process';
|
|
6
7
|
import { fileURLToPath } from 'node:url';
|
|
7
8
|
|
|
8
9
|
// Only show the banner for global installs (skip when installing as a dependency).
|
|
@@ -40,6 +41,73 @@ async function installDefaultClaudeSkill() {
|
|
|
40
41
|
return { status: 'installed', path: destinationSkillPath };
|
|
41
42
|
}
|
|
42
43
|
|
|
44
|
+
function runCommand(command, args) {
|
|
45
|
+
return new Promise((resolve) => {
|
|
46
|
+
const child = spawn(command, args, {
|
|
47
|
+
stdio: ['ignore', 'pipe', 'pipe'],
|
|
48
|
+
});
|
|
49
|
+
let stdout = '';
|
|
50
|
+
let stderr = '';
|
|
51
|
+
child.stdout.on('data', (data) => { stdout += data.toString(); });
|
|
52
|
+
child.stderr.on('data', (data) => { stderr += data.toString(); });
|
|
53
|
+
child.on('close', (code) => {
|
|
54
|
+
resolve({
|
|
55
|
+
code: code ?? 1,
|
|
56
|
+
stdout: stdout.trim(),
|
|
57
|
+
stderr: stderr.trim(),
|
|
58
|
+
});
|
|
59
|
+
});
|
|
60
|
+
child.on('error', (error) => {
|
|
61
|
+
resolve({
|
|
62
|
+
code: 1,
|
|
63
|
+
stdout: '',
|
|
64
|
+
stderr: error instanceof Error ? error.message : String(error),
|
|
65
|
+
});
|
|
66
|
+
});
|
|
67
|
+
});
|
|
68
|
+
}
|
|
69
|
+
|
|
70
|
+
async function installLocalSdkExecutable() {
|
|
71
|
+
const currentFilePath = fileURLToPath(import.meta.url);
|
|
72
|
+
const currentDir = path.dirname(currentFilePath);
|
|
73
|
+
const sdkPath = path.resolve(currentDir, '..', 'py', 'sdk');
|
|
74
|
+
|
|
75
|
+
try {
|
|
76
|
+
await fs.access(path.join(sdkPath, 'pyproject.toml'));
|
|
77
|
+
} catch {
|
|
78
|
+
return {
|
|
79
|
+
status: 'missing',
|
|
80
|
+
message:
|
|
81
|
+
'Local SDK source not found (expected ../py/sdk). Skipping SDK executable bootstrap.',
|
|
82
|
+
};
|
|
83
|
+
}
|
|
84
|
+
|
|
85
|
+
// Preferred path: uv tool install from local sdk package.
|
|
86
|
+
const uvInstall = await runCommand('uv', [
|
|
87
|
+
'tool',
|
|
88
|
+
'install',
|
|
89
|
+
'--from',
|
|
90
|
+
sdkPath,
|
|
91
|
+
'dawnai-sdk',
|
|
92
|
+
'--force',
|
|
93
|
+
]);
|
|
94
|
+
if (uvInstall.code === 0) {
|
|
95
|
+
return {
|
|
96
|
+
status: 'installed',
|
|
97
|
+
message: `Installed Dawn SDK executable from local source: ${sdkPath}`,
|
|
98
|
+
};
|
|
99
|
+
}
|
|
100
|
+
|
|
101
|
+
return {
|
|
102
|
+
status: 'failed',
|
|
103
|
+
message: [
|
|
104
|
+
'Could not auto-install Dawn SDK executable from local source using uv.',
|
|
105
|
+
`uv error: ${uvInstall.stderr || uvInstall.stdout || 'unknown error'}`,
|
|
106
|
+
`Manual setup: cd "${sdkPath}" && uv tool install --from . dawnai-sdk --force`,
|
|
107
|
+
].join('\n '),
|
|
108
|
+
};
|
|
109
|
+
}
|
|
110
|
+
|
|
43
111
|
let skillInstallMessage = '';
|
|
44
112
|
try {
|
|
45
113
|
const result = await installDefaultClaudeSkill();
|
|
@@ -53,16 +121,33 @@ try {
|
|
|
53
121
|
skillInstallMessage = `\n Note: could not auto-install default Claude skill (${message}).\n`;
|
|
54
122
|
}
|
|
55
123
|
|
|
124
|
+
let sdkInstallMessage = '';
|
|
125
|
+
try {
|
|
126
|
+
const result = await installLocalSdkExecutable();
|
|
127
|
+
if (result.status === 'installed') {
|
|
128
|
+
sdkInstallMessage = `\n SDK bootstrap:\n ${result.message}\n`;
|
|
129
|
+
} else if (result.status === 'missing') {
|
|
130
|
+
sdkInstallMessage = `\n SDK bootstrap:\n ${result.message}\n`;
|
|
131
|
+
} else {
|
|
132
|
+
sdkInstallMessage = `\n SDK bootstrap warning:\n ${result.message}\n`;
|
|
133
|
+
}
|
|
134
|
+
} catch (error) {
|
|
135
|
+
const message = error instanceof Error ? error.message : String(error);
|
|
136
|
+
sdkInstallMessage = `\n SDK bootstrap warning:\n Unexpected error: ${message}\n`;
|
|
137
|
+
}
|
|
138
|
+
|
|
56
139
|
console.log(`
|
|
57
140
|
@dawnai/cli installed successfully.
|
|
58
141
|
|
|
59
142
|
Get started:
|
|
60
143
|
dawn --version Check installed version
|
|
61
144
|
dawn auth login Authenticate (opens browser)
|
|
145
|
+
dawn sdk doctor Verify local SDK executable
|
|
62
146
|
dawn skill install Install all bundled Claude Code skills
|
|
63
147
|
dawn --help Show all commands
|
|
64
148
|
|
|
65
149
|
${skillInstallMessage}
|
|
150
|
+
${sdkInstallMessage}
|
|
66
151
|
|
|
67
152
|
Headless / CI / agent environments:
|
|
68
153
|
export DAWN_JWT_TOKEN="<your-token>"
|