@ghl-ai/aw 0.1.35-beta.17 → 0.1.35-beta.18

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/ecc.mjs +40 -73
  2. package/package.json +1 -1
package/ecc.mjs CHANGED
@@ -1,7 +1,7 @@
1
1
  import { execSync } from "node:child_process";
2
2
  import {
3
- cpSync, existsSync, mkdirSync, readFileSync, readdirSync,
4
- renameSync, rmSync, writeFileSync,
3
+ existsSync, readFileSync, readdirSync, renameSync,
4
+ mkdirSync, rmSync, writeFileSync,
5
5
  } from "node:fs";
6
6
  import { dirname, join } from "node:path";
7
7
  import { homedir } from "node:os";
@@ -9,18 +9,16 @@ import * as fmt from "./fmt.mjs";
9
9
 
10
10
  const AW_ECC_REPO_SSH = "git@github.com:shreyansh-ghl/aw-ecc.git";
11
11
  const AW_ECC_REPO_HTTPS = "https://github.com/shreyansh-ghl/aw-ecc.git";
12
- const AW_ECC_TAG = "v1.1.0";
12
+ const AW_ECC_TAG = "v1.2.0";
13
13
  const TMP_DIR = "/tmp/aw-ecc";
14
14
 
15
- const PLUGIN_NAME = "aw";
16
- const PLUGIN_VERSION = "1.1.0";
17
- const PLUGIN_KEY = `${PLUGIN_NAME}@${PLUGIN_NAME}`;
15
+ const MARKETPLACE_NAME = "aw-marketplace";
16
+ const PLUGIN_KEY = `aw@${MARKETPLACE_NAME}`;
18
17
 
19
- const FILE_COPY_TARGETS = ["cursor", "claude", "codex"];
18
+ const FILE_COPY_TARGETS = ["cursor", "codex"];
20
19
 
21
20
  const TARGET_STATE = {
22
21
  cursor: { state: ".cursor/ecc-install-state.json" },
23
- claude: { state: ".claude/ecc/install-state.json" },
24
22
  codex: { state: ".codex/ecc-install-state.json" },
25
23
  };
26
24
 
@@ -36,64 +34,20 @@ function cloneRepo(tag, dest) {
36
34
  }
37
35
  }
38
36
 
39
- function getPluginPaths() {
40
- const HOME = homedir();
41
- const pluginsDir = join(HOME, ".claude", "plugins");
42
- const cachePath = join(pluginsDir, "cache", PLUGIN_NAME, PLUGIN_NAME, PLUGIN_VERSION);
43
- const registryPath = join(pluginsDir, "installed_plugins.json");
44
- return { pluginsDir, cachePath, registryPath };
45
- }
46
-
47
- function registerClaudePlugin(repoDir) {
48
- const { cachePath, registryPath } = getPluginPaths();
49
-
50
- if (existsSync(cachePath)) rmSync(cachePath, { recursive: true, force: true });
51
- mkdirSync(cachePath, { recursive: true });
52
- cpSync(repoDir, cachePath, { recursive: true });
53
-
54
- // Remove .git from the cached copy
55
- const dotGit = join(cachePath, ".git");
56
- if (existsSync(dotGit)) rmSync(dotGit, { recursive: true, force: true });
57
-
58
- let registry = { version: 2, plugins: {} };
59
- if (existsSync(registryPath)) {
60
- try { registry = JSON.parse(readFileSync(registryPath, "utf8")); } catch { /* fresh */ }
37
+ // Claude Code: register marketplace + install plugin via CLI
38
+ function installClaudePlugin(repoDir) {
39
+ try {
40
+ run(`claude plugin marketplace add ${repoDir} --scope user`);
41
+ } catch {
42
+ // marketplace may already exist — update it instead
43
+ try { run(`claude plugin marketplace update ${MARKETPLACE_NAME}`); } catch { /* ok */ }
61
44
  }
62
-
63
- let commitSha = "";
64
- try { commitSha = run("git rev-parse HEAD", { cwd: repoDir }).toString().trim(); } catch { /* ok */ }
65
-
66
- registry.plugins[PLUGIN_KEY] = [
67
- {
68
- scope: "user",
69
- installPath: cachePath,
70
- version: PLUGIN_VERSION,
71
- installedAt: new Date().toISOString(),
72
- lastUpdated: new Date().toISOString(),
73
- ...(commitSha && { gitCommitSha: commitSha }),
74
- },
75
- ];
76
-
77
- writeFileSync(registryPath, JSON.stringify(registry, null, 2));
45
+ run(`claude plugin install ${PLUGIN_KEY} --scope user`);
78
46
  }
79
47
 
80
- function unregisterClaudePlugin() {
81
- const { cachePath, registryPath } = getPluginPaths();
82
-
83
- if (existsSync(cachePath)) {
84
- rmSync(cachePath, { recursive: true, force: true });
85
- pruneEmptyParents(cachePath, join(homedir(), ".claude"));
86
- }
87
-
88
- if (existsSync(registryPath)) {
89
- try {
90
- const registry = JSON.parse(readFileSync(registryPath, "utf8"));
91
- if (registry.plugins?.[PLUGIN_KEY]) {
92
- delete registry.plugins[PLUGIN_KEY];
93
- writeFileSync(registryPath, JSON.stringify(registry, null, 2));
94
- }
95
- } catch { /* best effort */ }
96
- }
48
+ function uninstallClaudePlugin() {
49
+ try { run(`claude plugin uninstall ${PLUGIN_KEY} --scope user`); } catch { /* not installed */ }
50
+ try { run(`claude plugin marketplace remove ${MARKETPLACE_NAME}`); } catch { /* not registered */ }
97
51
  }
98
52
 
99
53
  function namespaceCommands(target) {
@@ -142,12 +96,16 @@ export async function installAwEcc(
142
96
  try {
143
97
  cloneRepo(AW_ECC_TAG, TMP_DIR);
144
98
 
145
- // Claude Code: register as plugin (proper agent dispatch)
99
+ // Claude Code: proper plugin install via marketplace CLI
146
100
  if (targets.includes("claude")) {
147
- registerClaudePlugin(TMP_DIR);
101
+ try {
102
+ installClaudePlugin(TMP_DIR);
103
+ } catch (err) {
104
+ if (!silent) fmt.logWarn(`Claude plugin install skipped: ${err.message}`);
105
+ }
148
106
  }
149
107
 
150
- // Cursor + Codex: file-copy approach + namespace commands into /aw:
108
+ // Cursor + Codex: file-copy via install-apply.js + namespace commands
151
109
  const fileCopyTargets = targets.filter((t) => FILE_COPY_TARGETS.includes(t));
152
110
  if (fileCopyTargets.length > 0) {
153
111
  run("npm install --no-audit --no-fund --ignore-scripts --loglevel=error", {
@@ -176,14 +134,16 @@ export function uninstallAwEcc({ silent = false } = {}) {
176
134
  const HOME = homedir();
177
135
  let removed = 0;
178
136
 
179
- // Claude Code: unregister plugin + remove cache
180
- unregisterClaudePlugin();
181
- removed++;
137
+ // Claude Code: uninstall plugin + remove marketplace via CLI
138
+ try {
139
+ uninstallClaudePlugin();
140
+ removed++;
141
+ } catch { /* best effort */ }
182
142
 
183
143
  // Cursor + Codex: remove file-copied content via install-state
184
144
  for (const cfg of Object.values(TARGET_STATE)) {
185
145
  const statePath = join(HOME, cfg.state);
186
- const ideDir = join(HOME, cfg.state.split("/")[0]);
146
+ const ideDir = join(HOME, "." + cfg.state.split("/")[0].replace(".", ""));
187
147
  if (!existsSync(statePath)) continue;
188
148
 
189
149
  try {
@@ -192,15 +152,15 @@ export function uninstallAwEcc({ silent = false } = {}) {
192
152
  if (op.destinationPath && existsSync(op.destinationPath)) {
193
153
  rmSync(op.destinationPath, { recursive: true, force: true });
194
154
  removed++;
195
- pruneEmptyParents(op.destinationPath, ideDir);
155
+ pruneEmptyParents(op.destinationPath, join(HOME, cfg.state.split("/")[0]));
196
156
  }
197
157
  }
198
158
  rmSync(statePath, { force: true });
199
- pruneEmptyParents(statePath, ideDir);
159
+ pruneEmptyParents(statePath, join(HOME, cfg.state.split("/")[0]));
200
160
  } catch { /* corrupted state — skip */ }
201
161
  }
202
162
 
203
- // Clean leftover claude install-state from older versions
163
+ // Clean leftover claude install-state from older file-copy versions
204
164
  const claudeState = join(HOME, ".claude", "ecc", "install-state.json");
205
165
  if (existsSync(claudeState)) {
206
166
  try {
@@ -216,6 +176,13 @@ export function uninstallAwEcc({ silent = false } = {}) {
216
176
  } catch { /* best effort */ }
217
177
  }
218
178
 
179
+ // Clean leftover manual plugin cache from older versions
180
+ const oldCache = join(HOME, ".claude", "plugins", "cache", "aw");
181
+ if (existsSync(oldCache)) {
182
+ rmSync(oldCache, { recursive: true, force: true });
183
+ removed++;
184
+ }
185
+
219
186
  if (!silent && removed > 0)
220
187
  fmt.logStep(`Removed ${removed} aw-ecc file${removed > 1 ? "s" : ""}`);
221
188
  return removed;
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@ghl-ai/aw",
3
- "version": "0.1.35-beta.17",
3
+ "version": "0.1.35-beta.18",
4
4
  "description": "Agentic Workspace CLI — pull, push & manage agents, skills and commands from the registry",
5
5
  "type": "module",
6
6
  "bin": {