@a-company/paradigm 3.1.2 → 3.1.5

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.
@@ -0,0 +1,168 @@
1
+ #!/usr/bin/env node
2
+ import "./chunk-MO4EEYFW.js";
3
+
4
+ // src/commands/plugin/check.ts
5
+ import * as fs from "fs";
6
+ import * as path from "path";
7
+ import * as os from "os";
8
+ import { exec } from "child_process";
9
+ import chalk from "chalk";
10
+ function execAsync(cmd, options = {}) {
11
+ return new Promise((resolve, reject) => {
12
+ exec(cmd, { timeout: options.timeout || 5e3, cwd: options.cwd }, (err, stdout) => {
13
+ if (err) return reject(err);
14
+ resolve(stdout.trim());
15
+ });
16
+ });
17
+ }
18
+ function readJsonSafe(filePath) {
19
+ try {
20
+ if (!fs.existsSync(filePath)) return null;
21
+ return JSON.parse(fs.readFileSync(filePath, "utf8"));
22
+ } catch {
23
+ return null;
24
+ }
25
+ }
26
+ function discoverPlugins() {
27
+ const plugins = [];
28
+ const claudePluginsDir = path.join(os.homedir(), ".claude", "plugins");
29
+ const marketplacesDir = path.join(claudePluginsDir, "marketplaces");
30
+ const cacheDir = path.join(claudePluginsDir, "cache");
31
+ if (!fs.existsSync(marketplacesDir)) return plugins;
32
+ let marketplaceRepos;
33
+ try {
34
+ marketplaceRepos = fs.readdirSync(marketplacesDir).filter((d) => {
35
+ const fullPath = path.join(marketplacesDir, d);
36
+ return fs.statSync(fullPath).isDirectory() && fs.existsSync(path.join(fullPath, ".git"));
37
+ });
38
+ } catch {
39
+ return plugins;
40
+ }
41
+ for (const repoDir of marketplaceRepos) {
42
+ const marketplacePath = path.join(marketplacesDir, repoDir);
43
+ const pluginsSubdir = path.join(marketplacePath, "plugins");
44
+ if (!fs.existsSync(pluginsSubdir)) continue;
45
+ let pluginDirs;
46
+ try {
47
+ pluginDirs = fs.readdirSync(pluginsSubdir).filter(
48
+ (d) => fs.statSync(path.join(pluginsSubdir, d)).isDirectory()
49
+ );
50
+ } catch {
51
+ continue;
52
+ }
53
+ for (const pluginName of pluginDirs) {
54
+ const pluginJsonPath = path.join(pluginsSubdir, pluginName, ".claude-plugin", "plugin.json");
55
+ const pluginJson = readJsonSafe(pluginJsonPath);
56
+ if (!pluginJson) continue;
57
+ const localVersion = pluginJson.version || "unknown";
58
+ const pluginCacheDir = path.join(cacheDir, repoDir, pluginName);
59
+ let installedVersion = "unknown";
60
+ if (fs.existsSync(pluginCacheDir)) {
61
+ try {
62
+ const versions = fs.readdirSync(pluginCacheDir).filter((d) => fs.statSync(path.join(pluginCacheDir, d)).isDirectory()).sort().reverse();
63
+ if (versions.length > 0) installedVersion = versions[0];
64
+ } catch {
65
+ }
66
+ }
67
+ let repo = repoDir;
68
+ try {
69
+ const gitConfig = fs.readFileSync(path.join(marketplacePath, ".git", "config"), "utf8");
70
+ const match = gitConfig.match(/github\.com[:/]([^/]+\/[^/\s.]+)/);
71
+ if (match) repo = match[1].replace(/\.git$/, "");
72
+ } catch {
73
+ }
74
+ plugins.push({ repo, plugin: pluginName, installedVersion, marketplacePath, localVersion });
75
+ }
76
+ }
77
+ return plugins;
78
+ }
79
+ async function checkPlugin(plugin) {
80
+ let remoteSha = null;
81
+ let localSha = "unknown";
82
+ try {
83
+ localSha = await execAsync("git rev-parse HEAD", { cwd: plugin.marketplacePath });
84
+ } catch {
85
+ }
86
+ try {
87
+ const output = await execAsync("git ls-remote origin HEAD", {
88
+ cwd: plugin.marketplacePath,
89
+ timeout: 5e3
90
+ });
91
+ const match = output.match(/^([a-f0-9]+)/);
92
+ if (match) remoteSha = match[1];
93
+ } catch {
94
+ }
95
+ const hasRemoteUpdate = remoteSha !== null && remoteSha !== localSha;
96
+ const hasCacheStale = plugin.localVersion !== plugin.installedVersion && plugin.installedVersion !== "unknown";
97
+ return {
98
+ repo: plugin.repo,
99
+ plugin: plugin.plugin,
100
+ installedVersion: plugin.installedVersion,
101
+ localVersion: plugin.localVersion,
102
+ remoteSha,
103
+ localSha,
104
+ marketplacePath: plugin.marketplacePath,
105
+ hasRemoteUpdate,
106
+ hasCacheStale
107
+ };
108
+ }
109
+ async function pluginCheckCommand(options = {}) {
110
+ console.log(chalk.blue("\nPlugin Update Check\n"));
111
+ const plugins = discoverPlugins();
112
+ if (plugins.length === 0) {
113
+ console.log(chalk.gray("No Claude Code plugins found in ~/.claude/plugins/marketplaces/"));
114
+ console.log(chalk.gray("Install plugins with: /plugin marketplace add <owner>/<repo>\n"));
115
+ return;
116
+ }
117
+ console.log(chalk.gray(`Checking ${plugins.length} plugin(s)...
118
+ `));
119
+ const results = await Promise.all(plugins.map((p) => checkPlugin(p)));
120
+ const updatable = results.filter((r) => r.hasRemoteUpdate || r.hasCacheStale);
121
+ for (const r of results) {
122
+ const status = r.hasRemoteUpdate ? chalk.yellow("update available") : r.hasCacheStale ? chalk.cyan("restart needed") : chalk.green("up to date");
123
+ const version = r.installedVersion !== "unknown" ? `${r.installedVersion} \u2192 ${r.localVersion}` : r.localVersion;
124
+ console.log(` ${chalk.bold(r.plugin)} ${chalk.gray(`(${r.repo})`)}`);
125
+ console.log(` Version: ${version} Status: ${status}`);
126
+ if (r.hasRemoteUpdate) {
127
+ console.log(chalk.gray(` Local: ${r.localSha?.slice(0, 8) || "?"}`));
128
+ console.log(chalk.gray(` Remote: ${r.remoteSha?.slice(0, 8) || "?"}`));
129
+ }
130
+ if (r.remoteSha === null) {
131
+ console.log(chalk.gray(" (remote check skipped \u2014 network unavailable)"));
132
+ }
133
+ console.log();
134
+ }
135
+ if (updatable.length === 0) {
136
+ console.log(chalk.green("All plugins are up to date.\n"));
137
+ return;
138
+ }
139
+ const remoteUpdates = updatable.filter((r) => r.hasRemoteUpdate);
140
+ if (options.update && remoteUpdates.length > 0) {
141
+ console.log(chalk.blue("Pulling updates...\n"));
142
+ for (const r of remoteUpdates) {
143
+ process.stdout.write(` ${r.plugin}: `);
144
+ try {
145
+ await execAsync("git pull origin main", {
146
+ cwd: r.marketplacePath,
147
+ timeout: 15e3
148
+ });
149
+ console.log(chalk.green("updated"));
150
+ } catch (err) {
151
+ console.log(chalk.red(`failed \u2014 ${err instanceof Error ? err.message : "unknown error"}`));
152
+ }
153
+ }
154
+ console.log(chalk.yellow("\nRestart your Claude Code session to apply updates.\n"));
155
+ } else if (remoteUpdates.length > 0) {
156
+ console.log(chalk.yellow("To pull updates, run:"));
157
+ for (const r of remoteUpdates) {
158
+ console.log(chalk.gray(` git -C ${r.marketplacePath} pull origin main`));
159
+ }
160
+ console.log(chalk.gray("\nOr run: paradigm plugin check --update"));
161
+ console.log(chalk.yellow("\nAfter updating, restart your Claude Code session.\n"));
162
+ } else {
163
+ console.log(chalk.yellow("Restart your Claude Code session to apply cached updates.\n"));
164
+ }
165
+ }
166
+ export {
167
+ pluginCheckCommand
168
+ };
@@ -0,0 +1,241 @@
1
+ #!/usr/bin/env node
2
+ var __create = Object.create;
3
+ var __defProp = Object.defineProperty;
4
+ var __getOwnPropDesc = Object.getOwnPropertyDescriptor;
5
+ var __getOwnPropNames = Object.getOwnPropertyNames;
6
+ var __getProtoOf = Object.getPrototypeOf;
7
+ var __hasOwnProp = Object.prototype.hasOwnProperty;
8
+ var __require = /* @__PURE__ */ ((x) => typeof require !== "undefined" ? require : typeof Proxy !== "undefined" ? new Proxy(x, {
9
+ get: (a, b) => (typeof require !== "undefined" ? require : a)[b]
10
+ }) : x)(function(x) {
11
+ if (typeof require !== "undefined") return require.apply(this, arguments);
12
+ throw Error('Dynamic require of "' + x + '" is not supported');
13
+ });
14
+ var __commonJS = (cb, mod) => function __require2() {
15
+ return mod || (0, cb[__getOwnPropNames(cb)[0]])((mod = { exports: {} }).exports, mod), mod.exports;
16
+ };
17
+ var __copyProps = (to, from, except, desc) => {
18
+ if (from && typeof from === "object" || typeof from === "function") {
19
+ for (let key of __getOwnPropNames(from))
20
+ if (!__hasOwnProp.call(to, key) && key !== except)
21
+ __defProp(to, key, { get: () => from[key], enumerable: !(desc = __getOwnPropDesc(from, key)) || desc.enumerable });
22
+ }
23
+ return to;
24
+ };
25
+ var __toESM = (mod, isNodeMode, target) => (target = mod != null ? __create(__getProtoOf(mod)) : {}, __copyProps(
26
+ // If the importer is in node compatibility mode or this is not an ESM
27
+ // file that has been converted to a CommonJS file using a Babel-
28
+ // compatible transform (i.e. "__esModule" has not been set), then set
29
+ // "default" to the CommonJS "module.exports" for node compatibility.
30
+ isNodeMode || !mod || !mod.__esModule ? __defProp(target, "default", { value: mod, enumerable: true }) : target,
31
+ mod
32
+ ));
33
+
34
+ // ../paradigm-mcp/src/utils/plugin-update-checker.ts
35
+ import * as fs from "fs";
36
+ import * as path from "path";
37
+ import * as os from "os";
38
+ import { exec } from "child_process";
39
+ var CLAUDE_PLUGINS_DIR = path.join(os.homedir(), ".claude", "plugins");
40
+ var CHECK_STATE_PATH = path.join(os.homedir(), ".paradigm", "plugin-update-check.json");
41
+ var THROTTLE_HOURS = 6;
42
+ function execAsync(cmd, options = {}) {
43
+ return new Promise((resolve, reject) => {
44
+ exec(cmd, { timeout: options.timeout || 3e3, cwd: options.cwd }, (err, stdout) => {
45
+ if (err) return reject(err);
46
+ resolve(stdout.trim());
47
+ });
48
+ });
49
+ }
50
+ function readJsonSafe(filePath) {
51
+ try {
52
+ if (!fs.existsSync(filePath)) return null;
53
+ return JSON.parse(fs.readFileSync(filePath, "utf8"));
54
+ } catch {
55
+ return null;
56
+ }
57
+ }
58
+ function loadCheckState() {
59
+ return readJsonSafe(CHECK_STATE_PATH);
60
+ }
61
+ function saveCheckState(state) {
62
+ const dir = path.dirname(CHECK_STATE_PATH);
63
+ if (!fs.existsSync(dir)) {
64
+ fs.mkdirSync(dir, { recursive: true });
65
+ }
66
+ fs.writeFileSync(CHECK_STATE_PATH, JSON.stringify(state, null, 2));
67
+ }
68
+ function isThrottled() {
69
+ const state = loadCheckState();
70
+ if (!state) return false;
71
+ const elapsed = Date.now() - new Date(state.lastCheck).getTime();
72
+ return elapsed < THROTTLE_HOURS * 3600 * 1e3;
73
+ }
74
+ function discoverPlugins() {
75
+ const plugins = [];
76
+ const marketplacesDir = path.join(CLAUDE_PLUGINS_DIR, "marketplaces");
77
+ const cacheDir = path.join(CLAUDE_PLUGINS_DIR, "cache");
78
+ if (!fs.existsSync(marketplacesDir)) return plugins;
79
+ let marketplaceRepos;
80
+ try {
81
+ marketplaceRepos = fs.readdirSync(marketplacesDir).filter((d) => {
82
+ const fullPath = path.join(marketplacesDir, d);
83
+ return fs.statSync(fullPath).isDirectory() && fs.existsSync(path.join(fullPath, ".git"));
84
+ });
85
+ } catch {
86
+ return plugins;
87
+ }
88
+ for (const repoDir of marketplaceRepos) {
89
+ const marketplacePath = path.join(marketplacesDir, repoDir);
90
+ const pluginsSubdir = path.join(marketplacePath, "plugins");
91
+ if (!fs.existsSync(pluginsSubdir)) continue;
92
+ let pluginDirs;
93
+ try {
94
+ pluginDirs = fs.readdirSync(pluginsSubdir).filter(
95
+ (d) => fs.statSync(path.join(pluginsSubdir, d)).isDirectory()
96
+ );
97
+ } catch {
98
+ continue;
99
+ }
100
+ for (const pluginName of pluginDirs) {
101
+ const pluginJsonPath = path.join(pluginsSubdir, pluginName, ".claude-plugin", "plugin.json");
102
+ const pluginJson = readJsonSafe(pluginJsonPath);
103
+ if (!pluginJson) continue;
104
+ const localVersion = pluginJson.version || "unknown";
105
+ const pluginCacheDir = path.join(cacheDir, repoDir, pluginName);
106
+ let installedVersion = "unknown";
107
+ let installedSha = "unknown";
108
+ if (fs.existsSync(pluginCacheDir)) {
109
+ try {
110
+ const versions = fs.readdirSync(pluginCacheDir).filter((d) => fs.statSync(path.join(pluginCacheDir, d)).isDirectory()).sort().reverse();
111
+ if (versions.length > 0) {
112
+ installedVersion = versions[0];
113
+ const cachedPluginJson = readJsonSafe(
114
+ path.join(pluginCacheDir, versions[0], ".claude-plugin", "plugin.json")
115
+ );
116
+ if (cachedPluginJson?.sha) {
117
+ installedSha = cachedPluginJson.sha;
118
+ }
119
+ }
120
+ } catch {
121
+ }
122
+ }
123
+ let repo = repoDir;
124
+ try {
125
+ const remoteUrl = fs.readFileSync(
126
+ path.join(marketplacePath, ".git", "config"),
127
+ "utf8"
128
+ );
129
+ const match = remoteUrl.match(/github\.com[:/]([^/]+\/[^/\s.]+)/);
130
+ if (match) {
131
+ repo = match[1].replace(/\.git$/, "");
132
+ }
133
+ } catch {
134
+ }
135
+ plugins.push({
136
+ repo,
137
+ plugin: pluginName,
138
+ installedVersion,
139
+ installedSha,
140
+ marketplacePath,
141
+ localVersion
142
+ });
143
+ }
144
+ }
145
+ return plugins;
146
+ }
147
+ async function checkPlugin(plugin) {
148
+ let remoteSha = null;
149
+ let localSha = plugin.installedSha;
150
+ try {
151
+ localSha = await execAsync("git rev-parse HEAD", { cwd: plugin.marketplacePath });
152
+ } catch {
153
+ }
154
+ try {
155
+ const output = await execAsync("git ls-remote origin HEAD", {
156
+ cwd: plugin.marketplacePath,
157
+ timeout: 3e3
158
+ });
159
+ const match = output.match(/^([a-f0-9]+)/);
160
+ if (match) {
161
+ remoteSha = match[1];
162
+ }
163
+ } catch {
164
+ }
165
+ const hasRemoteUpdate = remoteSha !== null && remoteSha !== localSha;
166
+ const hasCacheStale = plugin.localVersion !== plugin.installedVersion && plugin.installedVersion !== "unknown";
167
+ return {
168
+ repo: plugin.repo,
169
+ plugin: plugin.plugin,
170
+ installedVersion: plugin.installedVersion,
171
+ installedSha: localSha,
172
+ localVersion: plugin.localVersion,
173
+ remoteSha,
174
+ marketplacePath: plugin.marketplacePath,
175
+ hasRemoteUpdate,
176
+ hasCacheStale
177
+ };
178
+ }
179
+ function getPluginUpdateNotice() {
180
+ const state = loadCheckState();
181
+ if (!state?.results) return null;
182
+ const updatable = state.results.filter((r) => r.hasRemoteUpdate || r.hasCacheStale);
183
+ if (updatable.length === 0) return null;
184
+ const lines = [];
185
+ lines.push("--- PLUGIN UPDATES AVAILABLE ---");
186
+ lines.push("Updates available for installed Claude Code plugins:");
187
+ const pullCmds = [];
188
+ for (const r of updatable) {
189
+ if (r.hasRemoteUpdate) {
190
+ const versionInfo = r.installedVersion !== "unknown" ? `${r.installedVersion} \u2192 ${r.localVersion}` : "newer commits available";
191
+ lines.push(` - ${r.plugin} (${r.repo}): ${versionInfo}`);
192
+ pullCmds.push(`git -C ${r.marketplacePath} pull origin main`);
193
+ } else if (r.hasCacheStale) {
194
+ lines.push(` - ${r.plugin} (${r.repo}): ${r.installedVersion} \u2192 ${r.localVersion} (restart needed)`);
195
+ }
196
+ }
197
+ if (pullCmds.length > 0) {
198
+ lines.push("");
199
+ lines.push("Tell the user about these updates and suggest running:");
200
+ lines.push(` ${pullCmds.join(" && \\\n ")}`);
201
+ lines.push("");
202
+ lines.push("After updating, the user should restart their Claude Code session.");
203
+ } else {
204
+ lines.push("");
205
+ lines.push("Restart the session to apply cached updates.");
206
+ }
207
+ lines.push("---");
208
+ return lines.join("\n");
209
+ }
210
+ function schedulePluginUpdateCheck() {
211
+ if (isThrottled()) return;
212
+ (async () => {
213
+ try {
214
+ const results = await runPluginUpdateCheck();
215
+ saveCheckState({
216
+ lastCheck: (/* @__PURE__ */ new Date()).toISOString(),
217
+ results
218
+ });
219
+ } catch {
220
+ }
221
+ })();
222
+ }
223
+ async function runPluginUpdateCheck() {
224
+ const plugins = discoverPlugins();
225
+ if (plugins.length === 0) return [];
226
+ const results = await Promise.all(plugins.map((p) => checkPlugin(p)));
227
+ saveCheckState({
228
+ lastCheck: (/* @__PURE__ */ new Date()).toISOString(),
229
+ results
230
+ });
231
+ return results;
232
+ }
233
+
234
+ export {
235
+ __require,
236
+ __commonJS,
237
+ __toESM,
238
+ getPluginUpdateNotice,
239
+ schedulePluginUpdateCheck,
240
+ runPluginUpdateCheck
241
+ };