aawp-ai 1.6.2 → 1.6.4
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/bin/install.js +69 -135
- package/package.json +1 -1
package/bin/install.js
CHANGED
|
@@ -9,10 +9,8 @@ const { execSync, spawnSync } = require('child_process');
|
|
|
9
9
|
const VERSION = require('../package.json').version;
|
|
10
10
|
const SKILL_NAME = 'aawp';
|
|
11
11
|
const REPO_URL = 'https://github.com/aawp-ai/aawp.git';
|
|
12
|
-
const RAW_BASE = 'https://raw.githubusercontent.com/aawp-ai/aawp/main';
|
|
13
|
-
const FALLBACK = 'https://aawp.ai/skill';
|
|
14
12
|
|
|
15
|
-
// ── ANSI
|
|
13
|
+
// ── ANSI ──────────────────────────────────────────────────────────────────────
|
|
16
14
|
const isTTY = process.stdout.isTTY;
|
|
17
15
|
const c = (code, s) => isTTY ? `\x1b[${code}m${s}\x1b[0m` : s;
|
|
18
16
|
const bold = s => c('1', s);
|
|
@@ -29,167 +27,103 @@ const fail = s => console.log(` ${red('✗')} ${s}`);
|
|
|
29
27
|
|
|
30
28
|
// ── Helpers ───────────────────────────────────────────────────────────────────
|
|
31
29
|
const HOME = os.homedir();
|
|
32
|
-
|
|
33
30
|
function hasCmd(cmd) {
|
|
34
31
|
try { execSync(`command -v ${cmd}`, { stdio: 'ignore' }); return true; } catch { return false; }
|
|
35
32
|
}
|
|
36
33
|
function dirExists(p) {
|
|
37
34
|
try { return fs.statSync(p).isDirectory(); } catch { return false; }
|
|
38
35
|
}
|
|
39
|
-
function hasGit() { return hasCmd('git'); }
|
|
40
36
|
|
|
41
|
-
|
|
42
|
-
|
|
43
|
-
|
|
44
|
-
if (!res.ok) throw new Error(`HTTP ${res.status}`);
|
|
45
|
-
return Buffer.from(await res.arrayBuffer());
|
|
46
|
-
}
|
|
47
|
-
return new Promise((resolve, reject) => {
|
|
48
|
-
const proto = url.startsWith('https') ? require('https') : require('http');
|
|
49
|
-
proto.get(url, res => {
|
|
50
|
-
if (res.statusCode >= 300 && res.statusCode < 400 && res.headers.location) {
|
|
51
|
-
return fetchBuffer(res.headers.location).then(resolve).catch(reject);
|
|
52
|
-
}
|
|
53
|
-
if (res.statusCode !== 200) return reject(new Error(`HTTP ${res.status}`));
|
|
54
|
-
const chunks = [];
|
|
55
|
-
res.on('data', c => chunks.push(c));
|
|
56
|
-
res.on('end', () => resolve(Buffer.concat(chunks)));
|
|
57
|
-
res.on('error', reject);
|
|
58
|
-
}).on('error', reject);
|
|
59
|
-
});
|
|
60
|
-
}
|
|
37
|
+
// ── Install to a directory ────────────────────────────────────────────────────
|
|
38
|
+
function install(dest) {
|
|
39
|
+
const absDest = path.resolve(dest);
|
|
61
40
|
|
|
62
|
-
//
|
|
63
|
-
|
|
64
|
-
|
|
65
|
-
|
|
66
|
-
|
|
67
|
-
|
|
68
|
-
|
|
69
|
-
|
|
70
|
-
|
|
71
|
-
|
|
72
|
-
|
|
41
|
+
// Already installed — pull latest
|
|
42
|
+
if (dirExists(path.join(absDest, '.git'))) {
|
|
43
|
+
info('Updating existing install...');
|
|
44
|
+
const r = spawnSync('git', ['-C', absDest, 'pull', '--ff-only'], { stdio: 'inherit' });
|
|
45
|
+
if (r.status !== 0) { warn('git pull failed'); return false; }
|
|
46
|
+
} else {
|
|
47
|
+
// Fresh clone
|
|
48
|
+
if (dirExists(absDest)) fs.rmSync(absDest, { recursive: true, force: true });
|
|
49
|
+
fs.mkdirSync(path.dirname(absDest), { recursive: true });
|
|
50
|
+
const r = spawnSync('git', ['clone', '--depth', '1', REPO_URL, absDest], { stdio: 'inherit' });
|
|
51
|
+
if (r.status !== 0) { fail('git clone failed'); return false; }
|
|
73
52
|
}
|
|
74
|
-
fs.mkdirSync(path.dirname(dest), { recursive: true });
|
|
75
|
-
const r = spawnSync('git', ['clone', '--depth', '1', REPO_URL, dest], { stdio: 'inherit' });
|
|
76
|
-
return r.status === 0;
|
|
77
|
-
}
|
|
78
53
|
|
|
79
|
-
//
|
|
80
|
-
|
|
81
|
-
|
|
82
|
-
|
|
83
|
-
|
|
84
|
-
try {
|
|
85
|
-
const md = await fetchBuffer(`${RAW_BASE}/SKILL.md`);
|
|
86
|
-
fs.writeFileSync(path.join(dest, 'SKILL.md'), md);
|
|
87
|
-
} catch {
|
|
88
|
-
const md = await fetchBuffer(`${FALLBACK}/SKILL.md`);
|
|
89
|
-
fs.writeFileSync(path.join(dest, 'SKILL.md'), md);
|
|
54
|
+
// Run bootstrap (downloads binary if missing)
|
|
55
|
+
const bootstrap = path.join(absDest, 'scripts', 'bootstrap.sh');
|
|
56
|
+
if (fs.existsSync(bootstrap)) {
|
|
57
|
+
const r = spawnSync('bash', [bootstrap], { stdio: 'inherit', cwd: absDest });
|
|
58
|
+
if (r.status !== 0) warn('Bootstrap issue — binary may need manual download');
|
|
90
59
|
}
|
|
60
|
+
|
|
91
61
|
return true;
|
|
92
62
|
}
|
|
93
63
|
|
|
94
|
-
// ──
|
|
95
|
-
|
|
96
|
-
|
|
97
|
-
|
|
98
|
-
|
|
99
|
-
|
|
100
|
-
|
|
101
|
-
|
|
102
|
-
|
|
64
|
+
// ── Detect best install location ──────────────────────────────────────────────
|
|
65
|
+
function detectInstallDir() {
|
|
66
|
+
// OpenClaw workspace — look for clawd/skills or skills/ in common locations
|
|
67
|
+
const clawdSkills = [
|
|
68
|
+
path.join(HOME, 'clawd', 'skills'),
|
|
69
|
+
path.join(HOME, '.openclaw', 'workspace', 'skills'),
|
|
70
|
+
];
|
|
71
|
+
for (const d of clawdSkills) {
|
|
72
|
+
if (dirExists(d)) return { dir: path.join(d, SKILL_NAME), client: 'OpenClaw' };
|
|
73
|
+
}
|
|
74
|
+
if (hasCmd('openclaw') || hasCmd('clawhub')) {
|
|
75
|
+
return { dir: path.join(HOME, 'clawd', 'skills', SKILL_NAME), client: 'OpenClaw' };
|
|
76
|
+
}
|
|
103
77
|
|
|
104
|
-
|
|
78
|
+
// Other AI clients
|
|
79
|
+
const clients = [
|
|
80
|
+
{ name: 'Cursor', dir: path.join(HOME, '.cursor', 'skills'), detect: () => hasCmd('cursor') || dirExists(path.join(HOME, '.cursor')) },
|
|
81
|
+
{ name: 'Claude Code', dir: path.join(HOME, '.claude', 'skills'), detect: () => hasCmd('claude') || dirExists(path.join(HOME, '.claude')) },
|
|
82
|
+
{ name: 'Gemini CLI', dir: path.join(HOME, '.gemini', 'skills'), detect: () => hasCmd('gemini') || dirExists(path.join(HOME, '.gemini')) },
|
|
83
|
+
{ name: 'OpenCode', dir: path.join(HOME, '.config', 'opencode', 'skills'), detect: () => hasCmd('opencode') || dirExists(path.join(HOME, '.config', 'opencode')) },
|
|
84
|
+
{ name: 'Goose', dir: path.join(HOME, '.config', 'goose', 'skills'), detect: () => hasCmd('goose') || dirExists(path.join(HOME, '.config', 'goose')) },
|
|
85
|
+
];
|
|
86
|
+
for (const c of clients) {
|
|
87
|
+
if (c.detect()) return { dir: path.join(c.dir, SKILL_NAME), client: c.name };
|
|
88
|
+
}
|
|
89
|
+
|
|
90
|
+
// Fallback: universal
|
|
91
|
+
return { dir: path.join(HOME, '.agents', 'skills', SKILL_NAME), client: null };
|
|
92
|
+
}
|
|
105
93
|
|
|
106
94
|
// ── Main ──────────────────────────────────────────────────────────────────────
|
|
107
|
-
|
|
95
|
+
function main() {
|
|
108
96
|
console.log('');
|
|
109
|
-
console.log(` ${bold('AAWP
|
|
110
|
-
console.log(` ${dim('AI Agent Wallet Protocol
|
|
97
|
+
console.log(` ${bold('AAWP')} ${dim('v' + VERSION)}`);
|
|
98
|
+
console.log(` ${dim('AI Agent Wallet Protocol')}`);
|
|
111
99
|
console.log('');
|
|
112
100
|
|
|
113
|
-
|
|
114
|
-
|
|
115
|
-
|
|
116
|
-
if (detected.length === 0) {
|
|
117
|
-
info('No AI clients detected — installing to universal ~/.agents/skills/');
|
|
118
|
-
} else {
|
|
119
|
-
info(`Detected: ${detected.map(c => c.name).join(', ')}`);
|
|
101
|
+
if (!hasCmd('git')) {
|
|
102
|
+
fail('git is required. Install git and re-run: npx aawp-ai');
|
|
103
|
+
process.exit(1);
|
|
120
104
|
}
|
|
121
|
-
if (!git) warn('git not found — will install manifest only (limited functionality)');
|
|
122
|
-
console.log('');
|
|
123
|
-
|
|
124
|
-
// Collect unique install dirs
|
|
125
|
-
const seenDirs = new Set();
|
|
126
|
-
const targets = [];
|
|
127
105
|
|
|
128
|
-
|
|
129
|
-
|
|
130
|
-
seenDirs.add(client.skillDir);
|
|
131
|
-
targets.push({ dir: client.skillDir, label: client.name });
|
|
132
|
-
}
|
|
133
|
-
}
|
|
134
|
-
if (!seenDirs.has(UNIVERSAL_DIR)) {
|
|
135
|
-
targets.push({ dir: UNIVERSAL_DIR, label: 'universal' });
|
|
136
|
-
}
|
|
106
|
+
const { dir, client } = detectInstallDir();
|
|
107
|
+
const shortDir = dir.replace(HOME, '~');
|
|
137
108
|
|
|
138
|
-
|
|
139
|
-
|
|
140
|
-
for (const { dir, label } of targets) {
|
|
141
|
-
const dest = path.join(dir, SKILL_NAME);
|
|
142
|
-
const shortDest = dest.replace(HOME, '~');
|
|
143
|
-
info(`Installing to ${shortDest} ${dim('(' + label + ')')}`);
|
|
144
|
-
|
|
145
|
-
try {
|
|
146
|
-
let ok = false;
|
|
147
|
-
if (git) {
|
|
148
|
-
ok = gitClone(dest);
|
|
149
|
-
if (!ok) {
|
|
150
|
-
warn('git clone failed — falling back to manifest-only');
|
|
151
|
-
ok = await manifestFallback(dest);
|
|
152
|
-
}
|
|
153
|
-
} else {
|
|
154
|
-
ok = await manifestFallback(dest);
|
|
155
|
-
}
|
|
156
|
-
|
|
157
|
-
if (ok) {
|
|
158
|
-
// Run bootstrap if full install (downloads binary if missing)
|
|
159
|
-
const bootstrap = path.join(dest, 'scripts', 'bootstrap.sh');
|
|
160
|
-
if (fs.existsSync(bootstrap)) {
|
|
161
|
-
info('Running bootstrap (downloading binary artifacts)...');
|
|
162
|
-
const r = spawnSync('bash', [bootstrap], { stdio: 'inherit', cwd: dest });
|
|
163
|
-
if (r.status === 0) {
|
|
164
|
-
success('Bootstrap complete — binary verified');
|
|
165
|
-
} else {
|
|
166
|
-
warn('Bootstrap had issues — binary may need manual download');
|
|
167
|
-
}
|
|
168
|
-
}
|
|
169
|
-
success(`Installed → ${shortDest}`);
|
|
170
|
-
count++;
|
|
171
|
-
}
|
|
172
|
-
} catch (e) {
|
|
173
|
-
fail(`Failed: ${e.message}`);
|
|
174
|
-
}
|
|
175
|
-
console.log('');
|
|
109
|
+
if (client) {
|
|
110
|
+
info(`Detected ${client}`);
|
|
176
111
|
}
|
|
112
|
+
info(`Installing to ${shortDir}`);
|
|
113
|
+
console.log('');
|
|
177
114
|
|
|
178
|
-
if (
|
|
179
|
-
console.log(` ${bold(green('AAWP skill installed!'))}`);
|
|
115
|
+
if (install(dir)) {
|
|
180
116
|
console.log('');
|
|
181
|
-
console.log(` ${
|
|
182
|
-
console.log(` ${dim('Then ask your AI: "set up my AAWP wallet"')}`);
|
|
117
|
+
console.log(` ${bold(green('Done!'))} Installed to ${shortDir}`);
|
|
183
118
|
console.log('');
|
|
184
|
-
console.log(` ${dim('
|
|
119
|
+
console.log(` ${dim('Ask your AI:')} ${bold('"set up my AAWP wallet"')}`);
|
|
120
|
+
console.log(` ${dim('Docs: https://aawp.ai')}`);
|
|
185
121
|
} else {
|
|
186
|
-
|
|
187
|
-
|
|
122
|
+
console.log('');
|
|
123
|
+
fail('Installation failed.');
|
|
124
|
+
console.log(` ${dim('Try manually: git clone https://github.com/aawp-ai/aawp.git ' + shortDir)}`);
|
|
188
125
|
}
|
|
189
126
|
console.log('');
|
|
190
127
|
}
|
|
191
128
|
|
|
192
|
-
main()
|
|
193
|
-
fail(`Unexpected error: ${e.message}`);
|
|
194
|
-
process.exit(1);
|
|
195
|
-
});
|
|
129
|
+
main();
|