aawp-ai 1.6.3 → 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.
Files changed (2) hide show
  1. package/bin/install.js +69 -135
  2. 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 colors ───────────────────────────────────────────────────────────────
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
- async function fetchBuffer(url) {
42
- if (typeof fetch !== 'undefined') {
43
- const res = await fetch(url);
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
- // ── Git clone (full install) ──────────────────────────────────────────────────
63
- function gitClone(dest) {
64
- if (dirExists(dest) && dirExists(path.join(dest, '.git'))) {
65
- info('Existing install found pulling latest...');
66
- const r = spawnSync('git', ['-C', dest, 'pull', '--ff-only'], { stdio: 'inherit' });
67
- return r.status === 0;
68
- }
69
- if (dirExists(dest)) {
70
- // Directory exists but not a git repo — remove and re-clone
71
- warn(`${dest} exists but is not a git repo replacing...`);
72
- fs.rmSync(dest, { recursive: true, force: true });
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
- // ── Manifest-only fallback (no git) ──────────────────────────────────────────
80
- async function manifestFallback(dest) {
81
- info('git not available — installing SKILL.md manifest only');
82
- warn('Full functionality requires git. Install git and re-run: npx aawp-ai');
83
- fs.mkdirSync(dest, { recursive: true });
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
- // ── Client detection ──────────────────────────────────────────────────────────
95
- const CLIENTS = [
96
- { name: 'OpenClaw', detect: () => hasCmd('clawhub') || hasCmd('openclaw') || dirExists('skills'), skillDir: 'skills' },
97
- { name: 'Cursor', detect: () => hasCmd('cursor') || dirExists(path.join(HOME, '.cursor')), skillDir: path.join(HOME, '.cursor', 'skills') },
98
- { name: 'Claude Code',detect: () => hasCmd('claude') || dirExists(path.join(HOME, '.claude')), skillDir: path.join(HOME, '.claude', 'skills') },
99
- { name: 'Gemini CLI', detect: () => hasCmd('gemini') || dirExists(path.join(HOME, '.gemini')), skillDir: path.join(HOME, '.gemini', 'skills') },
100
- { name: 'OpenCode', detect: () => hasCmd('opencode') || dirExists(path.join(HOME, '.config', 'opencode')), skillDir: path.join(HOME, '.config', 'opencode', 'skills') },
101
- { name: 'Goose', detect: () => hasCmd('goose') || dirExists(path.join(HOME, '.config', 'goose')), skillDir: path.join(HOME, '.config', 'goose', 'skills') },
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
- const UNIVERSAL_DIR = path.join(HOME, '.agents', 'skills');
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
- async function main() {
95
+ function main() {
108
96
  console.log('');
109
- console.log(` ${bold('AAWP Skill Installer')} ${dim('v' + VERSION)}`);
110
- console.log(` ${dim('AI Agent Wallet Protocol — aawp.ai')}`);
97
+ console.log(` ${bold('AAWP')} ${dim('v' + VERSION)}`);
98
+ console.log(` ${dim('AI Agent Wallet Protocol')}`);
111
99
  console.log('');
112
100
 
113
- const detected = CLIENTS.filter(c => c.detect());
114
- const git = hasGit();
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
- for (const client of detected) {
129
- if (client.skillDir && !seenDirs.has(client.skillDir)) {
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
- let count = 0;
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 (count > 0) {
179
- console.log(` ${bold(green('AAWP skill installed!'))}`);
115
+ if (install(dir)) {
180
116
  console.log('');
181
- console.log(` ${dim('Restart your AI client to load the skill.')}`);
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('Docs: https://aawp.ai · GitHub: https://github.com/aawp-ai/aawp')}`);
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
- fail('Nothing was installed.');
187
- console.log(` ${dim('Try: git clone https://github.com/aawp-ai/aawp.git ~/.agents/skills/aawp')}`);
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().catch(e => {
193
- fail(`Unexpected error: ${e.message}`);
194
- process.exit(1);
195
- });
129
+ main();
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "aawp-ai",
3
- "version": "1.6.3",
3
+ "version": "1.6.4",
4
4
  "description": "Install the AAWP skill for any Agent Skills compatible AI client",
5
5
  "keywords": [
6
6
  "aawp",