@ghl-ai/aw 0.1.35-beta.2 → 0.1.35-beta.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/commands/init.mjs +0 -4
- package/commands/nuke.mjs +2 -6
- package/commands/search.mjs +1 -1
- package/constants.mjs +1 -1
- package/link.mjs +1 -1
- package/package.json +2 -3
- package/paths.mjs +1 -1
- package/plan.mjs +4 -3
- package/registry.mjs +2 -2
- package/ide-hooks.mjs +0 -193
package/commands/init.mjs
CHANGED
|
@@ -19,7 +19,6 @@ import { generateCommands, copyInstructions, initAwDocs } from '../integrate.mjs
|
|
|
19
19
|
import { setupMcp } from '../mcp.mjs';
|
|
20
20
|
import { autoUpdate, promptUpdate } from '../update.mjs';
|
|
21
21
|
import { installGlobalHooks } from '../hooks.mjs';
|
|
22
|
-
import { installIdeHooks } from '../ide-hooks.mjs';
|
|
23
22
|
|
|
24
23
|
const __dirname = dirname(fileURLToPath(import.meta.url));
|
|
25
24
|
const VERSION = JSON.parse(readFileSync(join(__dirname, '..', 'package.json'), 'utf8')).version;
|
|
@@ -207,7 +206,6 @@ export async function initCommand(args) {
|
|
|
207
206
|
setupMcp(HOME, freshCfg?.namespace || team) || [];
|
|
208
207
|
if (cwd !== HOME) setupMcp(cwd, freshCfg?.namespace || team);
|
|
209
208
|
installGlobalHooks();
|
|
210
|
-
const ideHookFiles = installIdeHooks(HOME);
|
|
211
209
|
|
|
212
210
|
// Link current project if needed
|
|
213
211
|
if (cwd !== HOME && !existsSync(join(cwd, '.aw_registry'))) {
|
|
@@ -288,7 +286,6 @@ export async function initCommand(args) {
|
|
|
288
286
|
const mcpFiles = setupMcp(HOME, team) || [];
|
|
289
287
|
if (cwd !== HOME) setupMcp(cwd, team);
|
|
290
288
|
const hooksInstalled = installGlobalHooks();
|
|
291
|
-
const ideHookFilesInit = installIdeHooks(HOME);
|
|
292
289
|
installIdeTasks();
|
|
293
290
|
|
|
294
291
|
// Step 4: Symlink in current directory if it's a git repo
|
|
@@ -307,7 +304,6 @@ export async function initCommand(args) {
|
|
|
307
304
|
createdFiles: [
|
|
308
305
|
...instructionFiles.map(p => p.startsWith(HOME) ? p.slice(HOME.length + 1) : p),
|
|
309
306
|
...mcpFiles.map(p => p.startsWith(HOME) ? p.slice(HOME.length + 1) : p),
|
|
310
|
-
...(ideHookFilesInit || []).map(p => p.startsWith(HOME) ? p.slice(HOME.length + 1) : p),
|
|
311
307
|
],
|
|
312
308
|
globalHooksDir: hooksInstalled ? join(HOME, '.aw', 'hooks') : null,
|
|
313
309
|
};
|
package/commands/nuke.mjs
CHANGED
|
@@ -9,14 +9,13 @@ import { execSync } from 'node:child_process';
|
|
|
9
9
|
import * as fmt from '../fmt.mjs';
|
|
10
10
|
import { chalk } from '../fmt.mjs';
|
|
11
11
|
import { removeGlobalHooks } from '../hooks.mjs';
|
|
12
|
-
import { removeIdeHooks } from '../ide-hooks.mjs';
|
|
13
12
|
|
|
14
13
|
const HOME = homedir();
|
|
15
14
|
const GLOBAL_AW_DIR = join(HOME, '.aw_registry');
|
|
16
15
|
const MANIFEST_PATH = join(GLOBAL_AW_DIR, '.aw-manifest.json');
|
|
17
16
|
|
|
18
17
|
const IDE_DIRS = ['.claude', '.cursor', '.codex', '.agents'];
|
|
19
|
-
const CONTENT_TYPES = ['agents', 'skills', 'commands', 'evals'];
|
|
18
|
+
const CONTENT_TYPES = ['agents', 'skills', 'commands', 'evals', 'hooks'];
|
|
20
19
|
|
|
21
20
|
function loadManifest() {
|
|
22
21
|
if (!existsSync(MANIFEST_PATH)) return null;
|
|
@@ -250,10 +249,7 @@ export function nukeCommand(args) {
|
|
|
250
249
|
// 4. Remove git hooks (core.hooksPath + legacy template)
|
|
251
250
|
removeGitHooks(manifest);
|
|
252
251
|
|
|
253
|
-
// 5. Remove IDE
|
|
254
|
-
removeIdeHooks(HOME);
|
|
255
|
-
|
|
256
|
-
// 6. Remove IDE auto-init tasks
|
|
252
|
+
// 5. Remove IDE auto-init tasks
|
|
257
253
|
removeIdeTasks();
|
|
258
254
|
|
|
259
255
|
// 5b. Remove upgrade lock/log (inside .aw_registry, must happen before dir removal)
|
package/commands/search.mjs
CHANGED
|
@@ -94,7 +94,7 @@ function searchLocal(workspaceDir, query) {
|
|
|
94
94
|
if (!nsEntry.isDirectory() || nsEntry.name.startsWith('.')) continue;
|
|
95
95
|
const ns = nsEntry.name;
|
|
96
96
|
|
|
97
|
-
for (const type of ['agents', 'skills', 'commands', 'evals']) {
|
|
97
|
+
for (const type of ['agents', 'skills', 'commands', 'evals', 'hooks']) {
|
|
98
98
|
const typeDir = join(workspaceDir, ns, type);
|
|
99
99
|
if (!existsSync(typeDir)) continue;
|
|
100
100
|
|
package/constants.mjs
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
// constants.mjs — Single source of truth for registry settings.
|
|
2
2
|
|
|
3
3
|
/** Base branch for PRs and sync checkout */
|
|
4
|
-
export const REGISTRY_BASE_BRANCH = 'sync/platform-superpowers-
|
|
4
|
+
export const REGISTRY_BASE_BRANCH = 'sync/platform-superpowers-n1qrx';
|
|
5
5
|
|
|
6
6
|
/** Default registry repository */
|
|
7
7
|
export const REGISTRY_REPO = 'GoHighLevel/platform-docs';
|
package/link.mjs
CHANGED
|
@@ -13,7 +13,7 @@ function forceSymlink(target, linkPath) {
|
|
|
13
13
|
const IDE_DIRS = ['.claude', '.cursor', '.codex'];
|
|
14
14
|
// Per-file symlink types
|
|
15
15
|
const FILE_TYPES = ['agents'];
|
|
16
|
-
const ALL_KNOWN_TYPES = new Set([...FILE_TYPES, 'skills', 'commands', 'evals', 'docs']);
|
|
16
|
+
const ALL_KNOWN_TYPES = new Set([...FILE_TYPES, 'skills', 'commands', 'evals', 'hooks', 'docs']);
|
|
17
17
|
|
|
18
18
|
/**
|
|
19
19
|
* List namespace directories inside .aw_registry/ (skip dotfiles).
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@ghl-ai/aw",
|
|
3
|
-
"version": "0.1.35-beta.
|
|
3
|
+
"version": "0.1.35-beta.4",
|
|
4
4
|
"description": "Agentic Workspace CLI — pull, push & manage agents, skills and commands from the registry",
|
|
5
5
|
"type": "module",
|
|
6
6
|
"bin": {
|
|
@@ -24,8 +24,7 @@
|
|
|
24
24
|
"registry.mjs",
|
|
25
25
|
"apply.mjs",
|
|
26
26
|
"update.mjs",
|
|
27
|
-
"hooks.mjs"
|
|
28
|
-
"ide-hooks.mjs"
|
|
27
|
+
"hooks.mjs"
|
|
29
28
|
],
|
|
30
29
|
"engines": {
|
|
31
30
|
"node": ">=18.0.0"
|
package/paths.mjs
CHANGED
|
@@ -3,7 +3,7 @@
|
|
|
3
3
|
import { existsSync, statSync, lstatSync, readlinkSync } from 'node:fs';
|
|
4
4
|
import { join, resolve, relative, basename, dirname } from 'node:path';
|
|
5
5
|
|
|
6
|
-
const VALID_TYPES = new Set(['agents', 'skills', 'commands', 'evals']);
|
|
6
|
+
const VALID_TYPES = new Set(['agents', 'skills', 'commands', 'evals', 'hooks']);
|
|
7
7
|
|
|
8
8
|
// IDE dirs that may contain symlinks into .aw_registry/
|
|
9
9
|
const IDE_PREFIXES = ['.claude/', '.cursor/', '.codex/', '.agents/'];
|
package/plan.mjs
CHANGED
|
@@ -46,8 +46,9 @@ export function computePlan(registryDirs, workspaceDir, includePatterns = [], {
|
|
|
46
46
|
targetFilename = `${entry.namespacePath}/${entry.type}/${entry.slug}/${entry.skillRelPath}`;
|
|
47
47
|
targetPath = join(workspaceDir, entry.namespacePath, entry.type, entry.slug, entry.skillRelPath);
|
|
48
48
|
} else {
|
|
49
|
-
|
|
50
|
-
|
|
49
|
+
const fileName = entry.filename || `${entry.slug}.md`;
|
|
50
|
+
targetFilename = `${entry.namespacePath}/${entry.type}/${fileName}`;
|
|
51
|
+
targetPath = join(workspaceDir, entry.namespacePath, entry.type, fileName);
|
|
51
52
|
}
|
|
52
53
|
|
|
53
54
|
const manifestKey = targetFilename;
|
|
@@ -113,7 +114,7 @@ export function computePlan(registryDirs, workspaceDir, includePatterns = [], {
|
|
|
113
114
|
const parts = manifestKey.split('/');
|
|
114
115
|
let typeIdx = -1;
|
|
115
116
|
for (let i = 0; i < parts.length; i++) {
|
|
116
|
-
if (['agents', 'skills', 'commands', 'evals'].includes(parts[i])) {
|
|
117
|
+
if (['agents', 'skills', 'commands', 'evals', 'hooks'].includes(parts[i])) {
|
|
117
118
|
typeIdx = i;
|
|
118
119
|
break;
|
|
119
120
|
}
|
package/registry.mjs
CHANGED
|
@@ -4,7 +4,7 @@ import { readFileSync, existsSync, readdirSync, statSync } from 'node:fs';
|
|
|
4
4
|
import { join, relative } from 'node:path';
|
|
5
5
|
import { createHash } from 'node:crypto';
|
|
6
6
|
|
|
7
|
-
const TYPE_DIRS = new Set(['agents', 'skills', 'commands', 'evals']);
|
|
7
|
+
const TYPE_DIRS = new Set(['agents', 'skills', 'commands', 'evals', 'hooks']);
|
|
8
8
|
const SKIP_DIRS = new Set(['docs']);
|
|
9
9
|
|
|
10
10
|
export function sha256(content) {
|
|
@@ -84,7 +84,7 @@ export function walkRegistryTree(baseDir, baseName) {
|
|
|
84
84
|
});
|
|
85
85
|
}
|
|
86
86
|
} else {
|
|
87
|
-
// Agents, commands — flat files
|
|
87
|
+
// Agents, commands, hooks — flat files
|
|
88
88
|
for (const fileEntry of readdirSync(fullPath)) {
|
|
89
89
|
if (fileEntry === '.gitkeep' || fileEntry.startsWith('.')) continue;
|
|
90
90
|
const filePath = join(fullPath, fileEntry);
|
package/ide-hooks.mjs
DELETED
|
@@ -1,193 +0,0 @@
|
|
|
1
|
-
// ide-hooks.mjs — Generate IDE session-start hooks for superpowers bootstrap.
|
|
2
|
-
//
|
|
3
|
-
// installIdeHooks(cwd) → writes/merges hook configs into ~/.claude/ and ~/.cursor/
|
|
4
|
-
// removeIdeHooks(cwd) → removes aw-generated hook entries from IDE hook configs
|
|
5
|
-
|
|
6
|
-
import { existsSync, readFileSync, writeFileSync, mkdirSync } from 'node:fs';
|
|
7
|
-
import { join } from 'node:path';
|
|
8
|
-
import { homedir } from 'node:os';
|
|
9
|
-
import * as fmt from './fmt.mjs';
|
|
10
|
-
|
|
11
|
-
const HOME = homedir();
|
|
12
|
-
const AW_REGISTRY = join(HOME, '.aw_registry');
|
|
13
|
-
const HOOKS_DIR = join(AW_REGISTRY, 'platform', 'superpowers', 'hooks');
|
|
14
|
-
const SESSION_START = join(HOOKS_DIR, 'session-start');
|
|
15
|
-
const RUN_HOOK_CMD = join(HOOKS_DIR, 'run-hook.cmd');
|
|
16
|
-
|
|
17
|
-
const AW_MARKER = 'aw-superpowers-session';
|
|
18
|
-
|
|
19
|
-
/**
|
|
20
|
-
* Install IDE session-start hooks that bootstrap using-superpowers.
|
|
21
|
-
* Only installs if the superpowers hooks exist in the registry.
|
|
22
|
-
* Merges with existing hook configs — never clobbers user hooks.
|
|
23
|
-
* @returns {string[]} paths of created/modified hook config files
|
|
24
|
-
*/
|
|
25
|
-
export function installIdeHooks(cwd) {
|
|
26
|
-
if (!existsSync(SESSION_START)) return [];
|
|
27
|
-
|
|
28
|
-
const created = [];
|
|
29
|
-
|
|
30
|
-
const claudeResult = installClaudeCodeHooks(cwd);
|
|
31
|
-
if (claudeResult) created.push(claudeResult);
|
|
32
|
-
|
|
33
|
-
const cursorResult = installCursorHooks(cwd);
|
|
34
|
-
if (cursorResult) created.push(cursorResult);
|
|
35
|
-
|
|
36
|
-
if (created.length > 0) {
|
|
37
|
-
fmt.logStep('IDE session hooks installed (superpowers bootstrap)');
|
|
38
|
-
}
|
|
39
|
-
|
|
40
|
-
return created;
|
|
41
|
-
}
|
|
42
|
-
|
|
43
|
-
/**
|
|
44
|
-
* Remove aw-generated hook entries from IDE hook configs.
|
|
45
|
-
*/
|
|
46
|
-
export function removeIdeHooks(cwd) {
|
|
47
|
-
removeClaudeCodeHooks(cwd);
|
|
48
|
-
removeCursorHooks(cwd);
|
|
49
|
-
fmt.logStep('IDE session hooks removed');
|
|
50
|
-
}
|
|
51
|
-
|
|
52
|
-
// ── Claude Code ─────────────────────────────────────────────────────────
|
|
53
|
-
|
|
54
|
-
function installClaudeCodeHooks(cwd) {
|
|
55
|
-
const hooksPath = join(HOME, '.claude', 'hooks.json');
|
|
56
|
-
|
|
57
|
-
const hookEntry = {
|
|
58
|
-
matcher: AW_MARKER,
|
|
59
|
-
hooks: [{
|
|
60
|
-
type: 'command',
|
|
61
|
-
command: `"${RUN_HOOK_CMD}" session-start`,
|
|
62
|
-
async: false,
|
|
63
|
-
}],
|
|
64
|
-
};
|
|
65
|
-
|
|
66
|
-
let config;
|
|
67
|
-
if (existsSync(hooksPath)) {
|
|
68
|
-
try {
|
|
69
|
-
config = JSON.parse(readFileSync(hooksPath, 'utf8'));
|
|
70
|
-
} catch {
|
|
71
|
-
return null;
|
|
72
|
-
}
|
|
73
|
-
|
|
74
|
-
if (!config.hooks) config.hooks = {};
|
|
75
|
-
if (!Array.isArray(config.hooks.SessionStart)) config.hooks.SessionStart = [];
|
|
76
|
-
|
|
77
|
-
const existing = config.hooks.SessionStart.findIndex(
|
|
78
|
-
e => e.matcher === AW_MARKER
|
|
79
|
-
);
|
|
80
|
-
if (existing !== -1) {
|
|
81
|
-
config.hooks.SessionStart[existing] = hookEntry;
|
|
82
|
-
} else {
|
|
83
|
-
config.hooks.SessionStart.push(hookEntry);
|
|
84
|
-
}
|
|
85
|
-
} else {
|
|
86
|
-
mkdirSync(join(HOME, '.claude'), { recursive: true });
|
|
87
|
-
config = {
|
|
88
|
-
hooks: {
|
|
89
|
-
SessionStart: [hookEntry],
|
|
90
|
-
},
|
|
91
|
-
};
|
|
92
|
-
}
|
|
93
|
-
|
|
94
|
-
writeFileSync(hooksPath, JSON.stringify(config, null, 2) + '\n');
|
|
95
|
-
return hooksPath;
|
|
96
|
-
}
|
|
97
|
-
|
|
98
|
-
function removeClaudeCodeHooks(cwd) {
|
|
99
|
-
const hooksPath = join(HOME, '.claude', 'hooks.json');
|
|
100
|
-
if (!existsSync(hooksPath)) return;
|
|
101
|
-
|
|
102
|
-
try {
|
|
103
|
-
const config = JSON.parse(readFileSync(hooksPath, 'utf8'));
|
|
104
|
-
if (!config.hooks?.SessionStart) return;
|
|
105
|
-
|
|
106
|
-
config.hooks.SessionStart = config.hooks.SessionStart.filter(
|
|
107
|
-
e => e.matcher !== AW_MARKER
|
|
108
|
-
);
|
|
109
|
-
|
|
110
|
-
if (config.hooks.SessionStart.length === 0) {
|
|
111
|
-
delete config.hooks.SessionStart;
|
|
112
|
-
}
|
|
113
|
-
if (Object.keys(config.hooks).length === 0) {
|
|
114
|
-
delete config.hooks;
|
|
115
|
-
}
|
|
116
|
-
|
|
117
|
-
if (Object.keys(config).length === 0) {
|
|
118
|
-
writeFileSync(hooksPath, '{}\n');
|
|
119
|
-
} else {
|
|
120
|
-
writeFileSync(hooksPath, JSON.stringify(config, null, 2) + '\n');
|
|
121
|
-
}
|
|
122
|
-
} catch { /* best effort */ }
|
|
123
|
-
}
|
|
124
|
-
|
|
125
|
-
// ── Cursor ──────────────────────────────────────────────────────────────
|
|
126
|
-
|
|
127
|
-
function installCursorHooks(cwd) {
|
|
128
|
-
const hooksPath = join(HOME, '.cursor', 'hooks.json');
|
|
129
|
-
|
|
130
|
-
const hookEntry = {
|
|
131
|
-
command: SESSION_START,
|
|
132
|
-
_aw: AW_MARKER,
|
|
133
|
-
};
|
|
134
|
-
|
|
135
|
-
let config;
|
|
136
|
-
if (existsSync(hooksPath)) {
|
|
137
|
-
try {
|
|
138
|
-
config = JSON.parse(readFileSync(hooksPath, 'utf8'));
|
|
139
|
-
} catch {
|
|
140
|
-
return null;
|
|
141
|
-
}
|
|
142
|
-
|
|
143
|
-
if (!config.hooks) config.hooks = {};
|
|
144
|
-
if (!Array.isArray(config.hooks.sessionStart)) config.hooks.sessionStart = [];
|
|
145
|
-
|
|
146
|
-
const existing = config.hooks.sessionStart.findIndex(
|
|
147
|
-
e => e._aw === AW_MARKER
|
|
148
|
-
);
|
|
149
|
-
if (existing !== -1) {
|
|
150
|
-
config.hooks.sessionStart[existing] = hookEntry;
|
|
151
|
-
} else {
|
|
152
|
-
config.hooks.sessionStart.push(hookEntry);
|
|
153
|
-
}
|
|
154
|
-
} else {
|
|
155
|
-
mkdirSync(join(HOME, '.cursor'), { recursive: true });
|
|
156
|
-
config = {
|
|
157
|
-
version: 1,
|
|
158
|
-
hooks: {
|
|
159
|
-
sessionStart: [hookEntry],
|
|
160
|
-
},
|
|
161
|
-
};
|
|
162
|
-
}
|
|
163
|
-
|
|
164
|
-
writeFileSync(hooksPath, JSON.stringify(config, null, 2) + '\n');
|
|
165
|
-
return hooksPath;
|
|
166
|
-
}
|
|
167
|
-
|
|
168
|
-
function removeCursorHooks(cwd) {
|
|
169
|
-
const hooksPath = join(HOME, '.cursor', 'hooks.json');
|
|
170
|
-
if (!existsSync(hooksPath)) return;
|
|
171
|
-
|
|
172
|
-
try {
|
|
173
|
-
const config = JSON.parse(readFileSync(hooksPath, 'utf8'));
|
|
174
|
-
if (!config.hooks?.sessionStart) return;
|
|
175
|
-
|
|
176
|
-
config.hooks.sessionStart = config.hooks.sessionStart.filter(
|
|
177
|
-
e => e._aw !== AW_MARKER
|
|
178
|
-
);
|
|
179
|
-
|
|
180
|
-
if (config.hooks.sessionStart.length === 0) {
|
|
181
|
-
delete config.hooks.sessionStart;
|
|
182
|
-
}
|
|
183
|
-
if (config.hooks && Object.keys(config.hooks).length === 0) {
|
|
184
|
-
delete config.hooks;
|
|
185
|
-
}
|
|
186
|
-
|
|
187
|
-
if (Object.keys(config).length <= 1 && config.version) {
|
|
188
|
-
writeFileSync(hooksPath, JSON.stringify({ version: config.version }, null, 2) + '\n');
|
|
189
|
-
} else {
|
|
190
|
-
writeFileSync(hooksPath, JSON.stringify(config, null, 2) + '\n');
|
|
191
|
-
}
|
|
192
|
-
} catch { /* best effort */ }
|
|
193
|
-
}
|