@a-company/paradigm 3.1.4 → 3.1.6
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/dist/check-UZY647TB.js +168 -0
- package/dist/chunk-4G54C4VM.js +241 -0
- package/dist/{chunk-6HZ7PZGG.js → chunk-HXY6AY52.js} +164 -23
- package/dist/{hooks-QGUF77MB.js → hooks-RLJFGKPF.js} +1 -1
- package/dist/index.js +14 -5
- package/dist/mcp.js +58 -34
- package/dist/plugin-update-checker-EWT7YMDF.js +11 -0
- package/dist/{shift-OCNF4575.js → shift-YELZUPYG.js} +1 -1
- package/package.json +1 -1
|
@@ -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
|
+
};
|
|
@@ -3,6 +3,7 @@
|
|
|
3
3
|
// src/commands/hooks/index.ts
|
|
4
4
|
import * as fs from "fs";
|
|
5
5
|
import * as path from "path";
|
|
6
|
+
import * as os from "os";
|
|
6
7
|
import chalk from "chalk";
|
|
7
8
|
|
|
8
9
|
// src/commands/hooks/generated-hooks.ts
|
|
@@ -247,6 +248,8 @@ fi
|
|
|
247
248
|
# --- Check 7: Lore entry expected for significant sessions ---
|
|
248
249
|
if [ "$SOURCE_COUNT" -ge 3 ] && [ -d ".paradigm/lore" ]; then
|
|
249
250
|
LORE_RECORDED=false
|
|
251
|
+
|
|
252
|
+
# Check git diff first (covers staged/committed lore)
|
|
250
253
|
for file in $MODIFIED; do
|
|
251
254
|
case "$file" in
|
|
252
255
|
.paradigm/lore/entries/*.yaml|.paradigm/lore/entries/*/*.yaml)
|
|
@@ -256,6 +259,17 @@ if [ "$SOURCE_COUNT" -ge 3 ] && [ -d ".paradigm/lore" ]; then
|
|
|
256
259
|
esac
|
|
257
260
|
done
|
|
258
261
|
|
|
262
|
+
# Also check for recent lore on disk (covers MCP-written entries not yet staged)
|
|
263
|
+
if [ "$LORE_RECORDED" = false ]; then
|
|
264
|
+
TODAY=$(date -u +"%Y-%m-%d")
|
|
265
|
+
if [ -d ".paradigm/lore/entries/$TODAY" ]; then
|
|
266
|
+
ENTRY_COUNT=$(find ".paradigm/lore/entries/$TODAY" -name "*.yaml" 2>/dev/null | head -1)
|
|
267
|
+
if [ -n "$ENTRY_COUNT" ]; then
|
|
268
|
+
LORE_RECORDED=true
|
|
269
|
+
fi
|
|
270
|
+
fi
|
|
271
|
+
fi
|
|
272
|
+
|
|
259
273
|
if [ "$LORE_RECORDED" = false ]; then
|
|
260
274
|
VIOLATIONS="$VIOLATIONS
|
|
261
275
|
- You modified $SOURCE_COUNT source files but recorded no lore entry.
|
|
@@ -702,6 +716,8 @@ fi
|
|
|
702
716
|
# --- Check 7: Lore entry expected for significant sessions ---
|
|
703
717
|
if [ "$SOURCE_COUNT" -ge 3 ] && [ -d ".paradigm/lore" ]; then
|
|
704
718
|
LORE_RECORDED=false
|
|
719
|
+
|
|
720
|
+
# Check git diff first (covers staged/committed lore)
|
|
705
721
|
for file in $MODIFIED; do
|
|
706
722
|
case "$file" in
|
|
707
723
|
.paradigm/lore/entries/*.yaml|.paradigm/lore/entries/*/*.yaml)
|
|
@@ -711,6 +727,17 @@ if [ "$SOURCE_COUNT" -ge 3 ] && [ -d ".paradigm/lore" ]; then
|
|
|
711
727
|
esac
|
|
712
728
|
done
|
|
713
729
|
|
|
730
|
+
# Also check for recent lore on disk (covers MCP-written entries not yet staged)
|
|
731
|
+
if [ "$LORE_RECORDED" = false ]; then
|
|
732
|
+
TODAY=$(date -u +"%Y-%m-%d")
|
|
733
|
+
if [ -d ".paradigm/lore/entries/$TODAY" ]; then
|
|
734
|
+
ENTRY_COUNT=$(find ".paradigm/lore/entries/$TODAY" -name "*.yaml" 2>/dev/null | head -1)
|
|
735
|
+
if [ -n "$ENTRY_COUNT" ]; then
|
|
736
|
+
LORE_RECORDED=true
|
|
737
|
+
fi
|
|
738
|
+
fi
|
|
739
|
+
fi
|
|
740
|
+
|
|
714
741
|
if [ "$LORE_RECORDED" = false ]; then
|
|
715
742
|
VIOLATIONS="$VIOLATIONS
|
|
716
743
|
- You modified $SOURCE_COUNT source files but recorded no lore entry.
|
|
@@ -918,6 +945,80 @@ exit 0
|
|
|
918
945
|
`;
|
|
919
946
|
|
|
920
947
|
// src/commands/hooks/index.ts
|
|
948
|
+
function isParadigmPluginActive() {
|
|
949
|
+
try {
|
|
950
|
+
const globalSettingsPath = path.join(os.homedir(), ".claude", "settings.json");
|
|
951
|
+
if (!fs.existsSync(globalSettingsPath)) return { active: false };
|
|
952
|
+
const settings = JSON.parse(fs.readFileSync(globalSettingsPath, "utf8"));
|
|
953
|
+
const enabled = settings.enabledPlugins?.["paradigm@a-paradigm"];
|
|
954
|
+
if (!enabled) return { active: false };
|
|
955
|
+
const cacheBase = path.join(os.homedir(), ".claude", "plugins", "cache", "a-paradigm", "paradigm");
|
|
956
|
+
if (!fs.existsSync(cacheBase)) return { active: false };
|
|
957
|
+
const versions = fs.readdirSync(cacheBase).filter((d) => fs.statSync(path.join(cacheBase, d)).isDirectory()).sort().reverse();
|
|
958
|
+
if (versions.length === 0) return { active: false };
|
|
959
|
+
const latestCache = path.join(cacheBase, versions[0]);
|
|
960
|
+
const hooksJson = path.join(latestCache, "hooks", "hooks.json");
|
|
961
|
+
if (!fs.existsSync(hooksJson)) return { active: false };
|
|
962
|
+
return { active: true, cacheVersion: versions[0] };
|
|
963
|
+
} catch {
|
|
964
|
+
return { active: false };
|
|
965
|
+
}
|
|
966
|
+
}
|
|
967
|
+
function cleanupProjectClaudeCodeHooks(rootDir) {
|
|
968
|
+
const removed = [];
|
|
969
|
+
const claudeHooksDir = path.join(rootDir, ".claude", "hooks");
|
|
970
|
+
if (fs.existsSync(claudeHooksDir)) {
|
|
971
|
+
for (const hookName of ["paradigm-stop.sh", "paradigm-precommit.sh", "paradigm-postwrite.sh"]) {
|
|
972
|
+
const hookPath = path.join(claudeHooksDir, hookName);
|
|
973
|
+
if (fs.existsSync(hookPath)) {
|
|
974
|
+
fs.unlinkSync(hookPath);
|
|
975
|
+
removed.push(hookName);
|
|
976
|
+
}
|
|
977
|
+
}
|
|
978
|
+
try {
|
|
979
|
+
const remaining = fs.readdirSync(claudeHooksDir);
|
|
980
|
+
if (remaining.length === 0) {
|
|
981
|
+
fs.rmdirSync(claudeHooksDir);
|
|
982
|
+
}
|
|
983
|
+
} catch {
|
|
984
|
+
}
|
|
985
|
+
}
|
|
986
|
+
const settingsPath = path.join(rootDir, ".claude", "settings.json");
|
|
987
|
+
if (fs.existsSync(settingsPath)) {
|
|
988
|
+
try {
|
|
989
|
+
const settings = JSON.parse(fs.readFileSync(settingsPath, "utf8"));
|
|
990
|
+
const hooks = settings.hooks;
|
|
991
|
+
if (hooks) {
|
|
992
|
+
let modified = false;
|
|
993
|
+
for (const [key, arr] of Object.entries(hooks)) {
|
|
994
|
+
if (!Array.isArray(arr)) continue;
|
|
995
|
+
const filtered = arr.filter(
|
|
996
|
+
(h) => !JSON.stringify(h).includes("paradigm-")
|
|
997
|
+
);
|
|
998
|
+
if (filtered.length !== arr.length) {
|
|
999
|
+
modified = true;
|
|
1000
|
+
if (filtered.length === 0) {
|
|
1001
|
+
delete hooks[key];
|
|
1002
|
+
} else {
|
|
1003
|
+
hooks[key] = filtered;
|
|
1004
|
+
}
|
|
1005
|
+
}
|
|
1006
|
+
}
|
|
1007
|
+
if (modified) {
|
|
1008
|
+
if (Object.keys(hooks).length === 0) {
|
|
1009
|
+
delete settings.hooks;
|
|
1010
|
+
} else {
|
|
1011
|
+
settings.hooks = hooks;
|
|
1012
|
+
}
|
|
1013
|
+
fs.writeFileSync(settingsPath, JSON.stringify(settings, null, 2) + "\n", "utf8");
|
|
1014
|
+
removed.push("settings.json hooks");
|
|
1015
|
+
}
|
|
1016
|
+
}
|
|
1017
|
+
} catch {
|
|
1018
|
+
}
|
|
1019
|
+
}
|
|
1020
|
+
return { cleaned: removed.length > 0, removed };
|
|
1021
|
+
}
|
|
921
1022
|
var POST_COMMIT_HOOK = `#!/bin/sh
|
|
922
1023
|
# Paradigm post-commit hook - captures history from commits
|
|
923
1024
|
# Installed by: paradigm hooks install
|
|
@@ -1073,6 +1174,18 @@ async function hooksInstallCommand(options = {}) {
|
|
|
1073
1174
|
}
|
|
1074
1175
|
}
|
|
1075
1176
|
async function installClaudeCodeHooks(rootDir, force) {
|
|
1177
|
+
const plugin = isParadigmPluginActive();
|
|
1178
|
+
if (plugin.active) {
|
|
1179
|
+
console.log(chalk.cyan(` Paradigm plugin v${plugin.cacheVersion} is active \u2014 hooks are managed by the plugin.`));
|
|
1180
|
+
const { cleaned, removed } = cleanupProjectClaudeCodeHooks(rootDir);
|
|
1181
|
+
if (cleaned) {
|
|
1182
|
+
console.log(chalk.green(` Cleaned up stale project hooks: ${removed.join(", ")}`));
|
|
1183
|
+
} else {
|
|
1184
|
+
console.log(chalk.gray(" No stale project hooks to clean up."));
|
|
1185
|
+
}
|
|
1186
|
+
console.log(chalk.gray(" Plugin hooks auto-update with each session \u2014 no manual install needed."));
|
|
1187
|
+
return;
|
|
1188
|
+
}
|
|
1076
1189
|
const claudeHooksDir = path.join(rootDir, ".claude", "hooks");
|
|
1077
1190
|
fs.mkdirSync(claudeHooksDir, { recursive: true });
|
|
1078
1191
|
const installed = [];
|
|
@@ -1327,32 +1440,60 @@ async function hooksStatusCommand() {
|
|
|
1327
1440
|
console.log(chalk.gray("\n Not a git repository (git hooks N/A)\n"));
|
|
1328
1441
|
}
|
|
1329
1442
|
console.log(chalk.magenta(" Claude Code Hooks Status\n"));
|
|
1330
|
-
const
|
|
1331
|
-
|
|
1332
|
-
|
|
1333
|
-
|
|
1334
|
-
|
|
1335
|
-
|
|
1336
|
-
|
|
1337
|
-
|
|
1443
|
+
const plugin = isParadigmPluginActive();
|
|
1444
|
+
if (plugin.active) {
|
|
1445
|
+
console.log(chalk.cyan(` Plugin: paradigm v${plugin.cacheVersion} (active)`));
|
|
1446
|
+
console.log(chalk.green(" Hooks are managed by the plugin \u2014 auto-updates with each session."));
|
|
1447
|
+
const claudeHooksDir = path.join(rootDir, ".claude", "hooks");
|
|
1448
|
+
const staleHooks = [];
|
|
1449
|
+
for (const hookName of ["paradigm-stop.sh", "paradigm-precommit.sh", "paradigm-postwrite.sh"]) {
|
|
1450
|
+
if (fs.existsSync(path.join(claudeHooksDir, hookName))) {
|
|
1451
|
+
staleHooks.push(hookName);
|
|
1452
|
+
}
|
|
1338
1453
|
}
|
|
1339
|
-
|
|
1340
|
-
|
|
1341
|
-
|
|
1342
|
-
|
|
1343
|
-
|
|
1344
|
-
|
|
1345
|
-
|
|
1346
|
-
|
|
1347
|
-
|
|
1348
|
-
|
|
1349
|
-
console.log(chalk.
|
|
1350
|
-
console.log(chalk.
|
|
1351
|
-
|
|
1352
|
-
console.log(chalk.yellow(" settings.json: parse error"));
|
|
1454
|
+
const settingsPath = path.join(rootDir, ".claude", "settings.json");
|
|
1455
|
+
let hasProjectHookEntries = false;
|
|
1456
|
+
if (fs.existsSync(settingsPath)) {
|
|
1457
|
+
try {
|
|
1458
|
+
const settings = JSON.parse(fs.readFileSync(settingsPath, "utf8"));
|
|
1459
|
+
hasProjectHookEntries = JSON.stringify(settings.hooks || {}).includes("paradigm-");
|
|
1460
|
+
} catch {
|
|
1461
|
+
}
|
|
1462
|
+
}
|
|
1463
|
+
if (staleHooks.length > 0 || hasProjectHookEntries) {
|
|
1464
|
+
console.log(chalk.yellow(` WARNING: Stale project hooks detected (${staleHooks.join(", ")}${hasProjectHookEntries ? ", settings.json entries" : ""})`));
|
|
1465
|
+
console.log(chalk.yellow(" These shadow the plugin hooks and may run outdated logic."));
|
|
1466
|
+
console.log(chalk.gray(" Run `paradigm hooks install --claude-code` to clean them up."));
|
|
1353
1467
|
}
|
|
1354
1468
|
} else {
|
|
1355
|
-
console.log(chalk.gray("
|
|
1469
|
+
console.log(chalk.gray(" Plugin: not active (using project-level hooks)"));
|
|
1470
|
+
const claudeHooksDir = path.join(rootDir, ".claude", "hooks");
|
|
1471
|
+
const claudeHooks = ["paradigm-stop.sh", "paradigm-precommit.sh", "paradigm-postwrite.sh"];
|
|
1472
|
+
for (const hookName of claudeHooks) {
|
|
1473
|
+
const hookPath = path.join(claudeHooksDir, hookName);
|
|
1474
|
+
if (fs.existsSync(hookPath)) {
|
|
1475
|
+
console.log(chalk.green(` ${hookName}: installed`));
|
|
1476
|
+
} else {
|
|
1477
|
+
console.log(chalk.gray(` ${hookName}: not installed`));
|
|
1478
|
+
}
|
|
1479
|
+
}
|
|
1480
|
+
const settingsPath = path.join(rootDir, ".claude", "settings.json");
|
|
1481
|
+
if (fs.existsSync(settingsPath)) {
|
|
1482
|
+
try {
|
|
1483
|
+
const settings = JSON.parse(fs.readFileSync(settingsPath, "utf8"));
|
|
1484
|
+
const hooks = settings.hooks || {};
|
|
1485
|
+
const hasStop = JSON.stringify(hooks.Stop || []).includes("paradigm-stop.sh");
|
|
1486
|
+
const hasPrecommit = JSON.stringify(hooks.PreToolUse || []).includes("paradigm-precommit.sh");
|
|
1487
|
+
const hasPostwrite = JSON.stringify(hooks.PostToolUse || []).includes("paradigm-postwrite.sh");
|
|
1488
|
+
console.log(chalk.gray(` settings.json Stop hook: ${hasStop ? "configured" : "missing"}`));
|
|
1489
|
+
console.log(chalk.gray(` settings.json PreToolUse hook: ${hasPrecommit ? "configured" : "missing"}`));
|
|
1490
|
+
console.log(chalk.gray(` settings.json PostToolUse hook: ${hasPostwrite ? "configured" : "missing"}`));
|
|
1491
|
+
} catch {
|
|
1492
|
+
console.log(chalk.yellow(" settings.json: parse error"));
|
|
1493
|
+
}
|
|
1494
|
+
} else {
|
|
1495
|
+
console.log(chalk.gray(" settings.json: not found"));
|
|
1496
|
+
}
|
|
1356
1497
|
}
|
|
1357
1498
|
console.log(chalk.magenta("\n Cursor Hooks Status\n"));
|
|
1358
1499
|
const cursorHooksDir = path.join(rootDir, ".cursor", "hooks");
|
package/dist/index.js
CHANGED
|
@@ -109,7 +109,7 @@ ${chalk2.magenta("\u2569 ")}${chalk2.cyan("\u2534 \u2534\u2534\u2514\u2500\u253
|
|
|
109
109
|
program.name("paradigm").description("Unified developer tools ecosystem").version(VERSION).addHelpText("before", banner);
|
|
110
110
|
program.command("init").description("Initialize Paradigm in the current project").option("-f, --force", "Overwrite existing files").option("--name <name>", "Project name").option("--ide <ide>", "Target IDE: cursor, copilot, windsurf, claude").option("--migrate", "Output migration prompt for existing IDE files").option("--quick", "Non-interactive mode with smart defaults").option("--dry-run", "Show what would be created without creating").action(initCommand);
|
|
111
111
|
program.command("shift").description("Full project setup in one command (init + team init + scan + sync all IDEs + doctor)").option("-f, --force", "Reinitialize even if already setup").option("-q, --quick", "Skip slow operations (scan)").option("--verify", "Run health checks after setup").option("--ide <ide>", "Target specific IDE instead of all").option("--configure-models", "Force model configuration prompts for team agents").action(async (options) => {
|
|
112
|
-
const { shiftCommand } = await import("./shift-
|
|
112
|
+
const { shiftCommand } = await import("./shift-YELZUPYG.js");
|
|
113
113
|
await shiftCommand(options);
|
|
114
114
|
});
|
|
115
115
|
program.command("setup [path]").description("Interactive setup wizard for Paradigm").option("-y, --yes", "Accept all defaults (non-interactive)").option("-f, --force", "Overwrite existing .paradigm config").action(async (path2, options) => {
|
|
@@ -277,6 +277,15 @@ teamCmd.action(async () => {
|
|
|
277
277
|
const { teamStatusCommand } = await import("./team-NWP2KJAB.js");
|
|
278
278
|
await teamStatusCommand(void 0, {});
|
|
279
279
|
});
|
|
280
|
+
var pluginCmd = program.command("plugin").description("Plugin management commands");
|
|
281
|
+
pluginCmd.command("check").description("Check for updates to installed Claude Code plugins").option("-u, --update", "Pull latest changes for all stale marketplace clones").action(async (options) => {
|
|
282
|
+
const { pluginCheckCommand } = await import("./check-UZY647TB.js");
|
|
283
|
+
await pluginCheckCommand(options);
|
|
284
|
+
});
|
|
285
|
+
pluginCmd.action(async () => {
|
|
286
|
+
const { pluginCheckCommand } = await import("./check-UZY647TB.js");
|
|
287
|
+
await pluginCheckCommand({});
|
|
288
|
+
});
|
|
280
289
|
program.command("doctor").description("Health check - validate Paradigm setup").action(async () => {
|
|
281
290
|
const { doctorCommand } = await import("./doctor-JBIV5PMN.js");
|
|
282
291
|
await doctorCommand();
|
|
@@ -470,19 +479,19 @@ historyCmd.option("--json", "Output as JSON").action(async (options) => {
|
|
|
470
479
|
});
|
|
471
480
|
var hooksCmd = program.command("hooks").description("Git hooks for automatic history capture");
|
|
472
481
|
hooksCmd.command("install").description("Install git hooks, Claude Code hooks, and Cursor hooks").option("-f, --force", "Overwrite existing hooks").option("--post-commit", "Only install post-commit hook").option("--pre-push", "Only install pre-push hook").option("--claude-code", "Only install Claude Code hooks (stop + pre-commit)").option("--cursor", "Only install Cursor hooks (.cursor/hooks.json)").action(async (options) => {
|
|
473
|
-
const { hooksInstallCommand } = await import("./hooks-
|
|
482
|
+
const { hooksInstallCommand } = await import("./hooks-RLJFGKPF.js");
|
|
474
483
|
await hooksInstallCommand(options);
|
|
475
484
|
});
|
|
476
485
|
hooksCmd.command("uninstall").description("Remove paradigm hooks (git hooks, or --cursor for Cursor hooks)").option("--cursor", "Remove Cursor hooks instead of git hooks").action(async (options) => {
|
|
477
|
-
const { hooksUninstallCommand } = await import("./hooks-
|
|
486
|
+
const { hooksUninstallCommand } = await import("./hooks-RLJFGKPF.js");
|
|
478
487
|
await hooksUninstallCommand(options);
|
|
479
488
|
});
|
|
480
489
|
hooksCmd.command("status").description("Check git hooks status").action(async () => {
|
|
481
|
-
const { hooksStatusCommand } = await import("./hooks-
|
|
490
|
+
const { hooksStatusCommand } = await import("./hooks-RLJFGKPF.js");
|
|
482
491
|
await hooksStatusCommand();
|
|
483
492
|
});
|
|
484
493
|
hooksCmd.action(async () => {
|
|
485
|
-
const { hooksStatusCommand } = await import("./hooks-
|
|
494
|
+
const { hooksStatusCommand } = await import("./hooks-RLJFGKPF.js");
|
|
486
495
|
await hooksStatusCommand();
|
|
487
496
|
});
|
|
488
497
|
var triageCmd = program.command("triage").description("Semantic error triage - incident management and pattern matching");
|
package/dist/mcp.js
CHANGED
|
@@ -1,35 +1,11 @@
|
|
|
1
1
|
#!/usr/bin/env node
|
|
2
|
-
|
|
3
|
-
|
|
4
|
-
|
|
5
|
-
|
|
6
|
-
|
|
7
|
-
|
|
8
|
-
|
|
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
|
-
));
|
|
2
|
+
import {
|
|
3
|
+
__commonJS,
|
|
4
|
+
__require,
|
|
5
|
+
__toESM,
|
|
6
|
+
getPluginUpdateNotice,
|
|
7
|
+
schedulePluginUpdateCheck
|
|
8
|
+
} from "./chunk-4G54C4VM.js";
|
|
33
9
|
|
|
34
10
|
// ../../node_modules/sql.js/dist/sql-wasm.js
|
|
35
11
|
var require_sql_wasm = __commonJS({
|
|
@@ -16354,7 +16330,20 @@ function registerTools(server, getContext2, reloadContext2) {
|
|
|
16354
16330
|
// Lore tools
|
|
16355
16331
|
...getLoreToolsList(),
|
|
16356
16332
|
// Habits tools
|
|
16357
|
-
...getHabitsToolsList()
|
|
16333
|
+
...getHabitsToolsList(),
|
|
16334
|
+
// Plugin update check
|
|
16335
|
+
{
|
|
16336
|
+
name: "paradigm_plugin_check",
|
|
16337
|
+
description: "Check for updates to installed Claude Code plugins. Reports which marketplace clones have newer remote commits and which cached versions are stale.",
|
|
16338
|
+
inputSchema: {
|
|
16339
|
+
type: "object",
|
|
16340
|
+
properties: {}
|
|
16341
|
+
},
|
|
16342
|
+
annotations: {
|
|
16343
|
+
readOnlyHint: true,
|
|
16344
|
+
destructiveHint: false
|
|
16345
|
+
}
|
|
16346
|
+
}
|
|
16358
16347
|
]
|
|
16359
16348
|
};
|
|
16360
16349
|
}
|
|
@@ -16368,8 +16357,11 @@ function registerTools(server, getContext2, reloadContext2) {
|
|
|
16368
16357
|
const tracker2 = getSessionTracker();
|
|
16369
16358
|
tracker2.setRootDir(ctx.rootDir);
|
|
16370
16359
|
let recoveryPreamble = null;
|
|
16360
|
+
let updateNotice = null;
|
|
16371
16361
|
if (!tracker2.hasRecoveredThisSession()) {
|
|
16372
16362
|
recoveryPreamble = buildRecoveryPreamble(ctx.rootDir);
|
|
16363
|
+
updateNotice = getPluginUpdateNotice();
|
|
16364
|
+
schedulePluginUpdateCheck();
|
|
16373
16365
|
tracker2.markRecovered();
|
|
16374
16366
|
}
|
|
16375
16367
|
const toolResult = await (async () => {
|
|
@@ -16802,6 +16794,37 @@ function registerTools(server, getContext2, reloadContext2) {
|
|
|
16802
16794
|
}]
|
|
16803
16795
|
};
|
|
16804
16796
|
}
|
|
16797
|
+
case "paradigm_plugin_check": {
|
|
16798
|
+
const { runPluginUpdateCheck } = await import("./plugin-update-checker-EWT7YMDF.js");
|
|
16799
|
+
const results = await runPluginUpdateCheck();
|
|
16800
|
+
const updatable = results.filter((r) => r.hasRemoteUpdate || r.hasCacheStale);
|
|
16801
|
+
if (updatable.length === 0) {
|
|
16802
|
+
const msg = results.length === 0 ? "No Claude Code plugins found in ~/.claude/plugins/marketplaces/." : "All installed plugins are up to date.";
|
|
16803
|
+
trackToolCall(msg.length, name);
|
|
16804
|
+
return { content: [{ type: "text", text: msg }] };
|
|
16805
|
+
}
|
|
16806
|
+
const lines = ["Plugin updates available:\n"];
|
|
16807
|
+
const pullCmds = [];
|
|
16808
|
+
for (const r of updatable) {
|
|
16809
|
+
if (r.hasRemoteUpdate) {
|
|
16810
|
+
lines.push(` ${r.plugin} (${r.repo}): remote has newer commits`);
|
|
16811
|
+
pullCmds.push(`git -C ${r.marketplacePath} pull origin main`);
|
|
16812
|
+
} else if (r.hasCacheStale) {
|
|
16813
|
+
lines.push(` ${r.plugin} (${r.repo}): ${r.installedVersion} \u2192 ${r.localVersion} (restart needed)`);
|
|
16814
|
+
}
|
|
16815
|
+
}
|
|
16816
|
+
if (pullCmds.length > 0) {
|
|
16817
|
+
lines.push(`
|
|
16818
|
+
Update command:
|
|
16819
|
+
${pullCmds.join(" && \\\n ")}`);
|
|
16820
|
+
lines.push("\nAfter running, restart the session to apply updates.");
|
|
16821
|
+
} else {
|
|
16822
|
+
lines.push("\nRestart the session to apply cached updates.");
|
|
16823
|
+
}
|
|
16824
|
+
const pluginText = lines.join("\n");
|
|
16825
|
+
trackToolCall(pluginText.length, name);
|
|
16826
|
+
return { content: [{ type: "text", text: pluginText }] };
|
|
16827
|
+
}
|
|
16805
16828
|
default: {
|
|
16806
16829
|
if (name === "paradigm_navigate") {
|
|
16807
16830
|
const result = await handleNavigateTool(name, args, ctx);
|
|
@@ -16934,10 +16957,11 @@ function registerTools(server, getContext2, reloadContext2) {
|
|
|
16934
16957
|
}
|
|
16935
16958
|
}
|
|
16936
16959
|
})();
|
|
16937
|
-
if (recoveryPreamble) {
|
|
16960
|
+
if (recoveryPreamble || updateNotice) {
|
|
16938
16961
|
const first = toolResult.content?.[0];
|
|
16939
16962
|
if (first && typeof first === "object" && "text" in first && typeof first.text === "string") {
|
|
16940
|
-
|
|
16963
|
+
const preamble = [updateNotice, recoveryPreamble].filter(Boolean).join("\n\n");
|
|
16964
|
+
first.text = preamble + "\n\n" + first.text;
|
|
16941
16965
|
}
|
|
16942
16966
|
}
|
|
16943
16967
|
return toolResult;
|